{"id":"d609583d-4453-47a6-a10a-f20acaa06d29","entityType":"agent","slug":"clawhub-thesentitrader-unusual-options-activity","name":"unusual-options-activity","canonicalUrl":"https://www.xpersona.co/agent/clawhub-thesentitrader-unusual-options-activity","canonicalPath":"/agent/clawhub-thesentitrader-unusual-options-activity","generatedAt":"2026-10-11T07:41:42.080Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":null},"description":"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access. Skill: unusual-options-activity Owner: thesentitrader Summary: Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call rati","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s171aan38r2dn7ew5hddyscf1983x1h9:unusual-options-activity","sourceUrl":"https://clawhub.ai/thesentitrader/unusual-options-activity","homepage":"https://clawhub.ai/thesentitrader/skills/unusual-options-activity","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/thesentitrader/unusual-options-activity","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/thesentitrader/skills/unusual-options-activity","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-inter"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":null},"stars":null,"forks":null,"downloads":1142,"packageName":null,"latestVersion":"1.5.3","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:46:28.399Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T05:46:28.456Z","lastCrawledAt":"2026-10-11T05:46:28.399Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T05:46:28.399Z","lastVerifiedAt":null,"highlights":[{"version":"1.5.3","createdAt":"2026-10-01T18:49:18.271Z","changelog":"The interest score now needs $100,000 of premium traded in the session. Adds handling for the flat free headline preview and the building-baseline case.","fileCount":3,"zipByteSize":11865},{"version":"1.5.2","createdAt":"2026-10-01T03:12:44.785Z","changelog":"Clarifies refresh timing, the Radar score rule, the free allowance and its Eastern-time reset, the intraday ranking order, history depth (2+ years from July 2024) and error handling; adds preview and error shapes.","fileCount":3,"zipByteSize":11248},{"version":"1.5.1","createdAt":"2026-09-30T22:33:17.263Z","changelog":"Clarifies session dating, ETF coverage, null handling, missing scores, the free dossier allowance, the upgrade coupon, the intraday ranking shape, open-interest follow-ups and units, and adds a Codex install line.","fileCount":3,"zipByteSize":11204},{"version":"1.5.0","createdAt":"2026-09-30T17:50:00.196Z","changelog":"Adds the intraday session fields (a 15-minute delayed unusual-contract count and percentile per ticker, the latest session's large-print count, and the market-wide intraday ranking), corrects the free preview field list, and documents the same-day expiry rule and policy stamp on session highlights.","fileCount":3,"zipByteSize":10380},{"version":"1.4.0","createdAt":"2026-09-24T16:43:33.895Z","changelog":"Evening refresh: the board now lands the evening of the session. Adds the open-interest follow-up on each unusual contract (oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage), compared on the next session's chain, and the session highlights (highlights and etfHighlights on /options/overview). Numbers only: the follow-up never states who bought or sold.","fileCount":3,"zipByteSize":9519},{"version":"1.3.2","createdAt":"2026-09-08T07:42:39.432Z","changelog":"Removes the npx execution path, declares permissions, and locks the request helper to the API origin.","fileCount":3,"zipByteSize":9286},{"version":"1.3.1","createdAt":"2026-09-06T07:58:44.407Z","changelog":"Says plainly that the wall and unusual fields appear on a minority of rows.","fileCount":3,"zipByteSize":9342},{"version":"1.3.0","createdAt":"2026-09-01T21:58:45.010Z","changelog":"CLI quickstart pointer (options {T} prints the dossier, works for ETFs, --json is the exact /options/summary response; radar and history stay REST) and company/fund name resolution (SPY resolves only under type=etf; a wrong symbol returns data:null that reads like no coverage).","fileCount":3,"zipByteSize":9023}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171aan38r2dn7ew5hddyscf1983x1h9:unusual-options-activity","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T07:41:42.077Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-thesentitrader-unusual-options-activity/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":null},"readme":"Skill: unusual-options-activity\n\nOwner: thesentitrader\n\nSummary: Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\n\nTags: latest:1.5.3\n\nVersion history:\n\nv1.5.3 | 2026-10-01T18:49:18.271Z | user\n\nThe interest score now needs $100,000 of premium traded in the session. Adds handling for the flat free headline preview and the building-baseline case.\n\nv1.5.2 | 2026-10-01T03:12:44.785Z | user\n\nClarifies refresh timing, the Radar score rule, the free allowance and its Eastern-time reset, the intraday ranking order, history depth (2+ years from July 2024) and error handling; adds preview and error shapes.\n\nv1.5.1 | 2026-09-30T22:33:17.263Z | user\n\nClarifies session dating, ETF coverage, null handling, missing scores, the free dossier allowance, the upgrade coupon, the intraday ranking shape, open-interest follow-ups and units, and adds a Codex install line.\n\nv1.5.0 | 2026-09-30T17:50:00.196Z | user\n\nAdds the intraday session fields (a 15-minute delayed unusual-contract count and percentile per ticker, the latest session's large-print count, and the market-wide intraday ranking), corrects the free preview field list, and documents the same-day expiry rule and policy stamp on session highlights.\n\nv1.4.0 | 2026-09-24T16:43:33.895Z | user\n\nEvening refresh: the board now lands the evening of the session. Adds the open-interest follow-up on each unusual contract (oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage), compared on the next session's chain, and the session highlights (highlights and etfHighlights on /options/overview). Numbers only: the follow-up never states who bought or sold.\n\nv1.3.2 | 2026-09-08T07:42:39.432Z | user\n\nRemoves the npx execution path, declares permissions, and locks the request helper to the API origin.\n\nv1.3.1 | 2026-09-06T07:58:44.407Z | user\n\nSays plainly that the wall and unusual fields appear on a minority of rows.\n\nv1.3.0 | 2026-09-01T21:58:45.010Z | user\n\nCLI quickstart pointer (options {T} prints the dossier, works for ETFs, --json is the exact /options/summary response; radar and history stay REST) and company/fund name resolution (SPY resolves only under type=etf; a wrong symbol returns data:null that reads like no coverage).\n\nv1.2.0 | 2026-08-20T09:03:46.881Z | user\n\nAgent identity guidance\n\nv1.1.0 | 2026-07-24T05:26:29.449Z | user\n\nAdd the ETF options board alongside single stocks.\n\nv1.0.0 | 2026-07-18T22:14:07.524Z | user\n\nInitial release: end-of-day options analytics radar (IV rank, put/call percentile, 25-delta skew, OI walls, max pain, unusual contracts, options sentiment), ranked against each stock's own history.\n\nArchive index:\n\nArchive v1.5.3: 3 files, 11865 bytes\n\nFiles: skill-card.md (2127b), SKILL.md (25654b), _meta.json (143b)\n\nFile v1.5.3:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading describes the latest published snapshot, and `asOf` names its session: quote it. The snapshot refreshes each weekday evening after the close (the run starts about 21:15 ET), so after successful publication `asOf` is that day's session, and between the close and that refresh it is still the previous session. Follow-ups compare the next session's open interest and remain pending until that chain is observed. On weekends and holidays `asOf` is the latest completed session. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints; the one intraday reading is a 15-minute delayed count and percentile (see \"Intraday session fields\" below), which carries its own timestamp and can describe a later session than `asOf` in the same response. \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number. Units: IV and the expected moves are fractions (`atmIv` 0.3124 is 31.24%), `skew25d` is an IV difference in the same fraction units (0.0293 is 2.93 percentage points), and ranks and percentiles run 0 to 100.\n- **Coverage is two bounded universes.** Stocks: about 1,040 of the most actively optioned US names (the number moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: covered funds are served on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. The full overview's `etfRows` is the authoritative fund list: `GET /api/v1/etfs` lists every fund SentiSense tracks, a wider set, and a tracked fund without an options snapshot returns `data: null` from `/summary`. A free key receives only the top 25 ETF rows, so absence from that slice does not establish noncoverage. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (`observations1y` under 60 sessions) returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. A ticker with a full history can still be unscored when its latest session fell below the liquidity floor ($100,000 of estimated premium activity, `notionalVol`). Report a missing percentile or score as unavailable, never as a low reading, and call it a building baseline only when `observations1y` is low.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and history windows up to `5y` (2+ years available, from July 2024, growing daily). |\n\nThe free tier exercises every workflow below on real data, with one limit: the walls and the unusual-contract list (Workflow 3) come only with a full dossier, so on a free key they last as long as the month's ten full dossiers do. Every covered `/summary` call spends one of the ten full dossiers, repeat calls for the same ticker included, and calls made earlier in the month on the same account count too, so branch on `isPreview` rather than counting calls yourself. Uncovered tickers that return `data: null` never spend the monthly dossier meter. The dossier allowance and the monthly request quota reset at the start of the first day of each calendar month, Eastern time (America/New_York).\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nThe three options endpoints return the wrapped envelope `{ isPreview, previewReason, data }`; `GET /api/v1/etfs` and the name resolver below return bare arrays. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Inside `data`, unavailable nested metric fields are omitted rather than sent as `null`, but envelope fields can be an explicit `null` (`previewReason` on a full response, `data` for an uncovered ticker), and so can the resolver's `ticker`: handle absent and `null` alike. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names; unscored rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `notionalVol`, `observations1y` and `unusualCount`; nearly every row also carries `atmIv` and `skew25d` (a handful without a valid at-the-money reading omit both) and, when `atmIv` is valid, the expected-move set: `expectedMove1d`/`expectedMove5d`/`expectedMove20d`, a calibrated 90% range, and `expectedMove1s1d`/`expectedMove1s5d`/`expectedMove1s20d`, the one-sigma convention (`atmIv * sqrt(h / 252)`), all fractions of price over 1, 5 and 20 trading sessions. A row's own `asOf` can be a session behind the board's `asOf`; quote the row's `asOf` and say so when the two differ. **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since unavailable row fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls. The same response carries `highlights` (stocks) and `etfHighlights` (ETFs): each ticker's highest-premium qualifying contract of the latest completed session with an expiry at least one day out (same-day expiries are not eligible), one per ticker, up to 10, ranked by `premiumPctl1y` (that premium against the ticker's own previous 252 sessions; omitted while the baseline builds). Free keys receive the top 3 of each. Each list carries its own stamp, `highlightPolicy` for `highlights` and `etfHighlightPolicy` for `etfHighlights`: read a list under that rule only when its own stamp is `ex0dte-v1`, since an absent stamp means that list was built under the older rule, which allowed same-day expiries.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of `{ asOf, sentiment, ivRank1y, atmIv, expectedMove1d, pcVol, pcVolPctl1y, maxPain }`, plus the intraday session fields below when present, with `isPreview: true` until the monthly reset. `latest` is the aggregate for the returned `asOf` session (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium, oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage }`; the oi-prefixed fields are the open-interest follow-up described below.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns the available history within that window (2+ years, from July 2024, growing daily), not a guaranteed five years. Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n**Intraday session fields.** On a trading day the app runs an intraday options board, rebuilt every 15 minutes from 15-minute delayed chains, and publishes the session's large prints after the close. On the API the intraday session is a count and a percentile; the contract-level board is in the app. `/summary` adds `intradayFlow` (`unusualCount`, contracts on the ticker's row passing the unusual rule so far, up to 5; `firstSeenEt` and `firstSeenAt`, the earliest cycle that flagged one; `flowPctl1y`, the ticker's intraday highlight against its own history, omitted while that baseline holds fewer than 60 sessions; `asOfEt`, `asOf` in epoch seconds, `live`, `delayMinutes`), plus `largePrintCount` (the ticker's large prints in the latest published post-close session, up to 25) and `largestPrintPctl` (the highest percentile among them). `/overview` adds `intradayActiveCount` (stocks with at least one unusual contract so far) and `intradayRanking` (up to 25 of them as an array of ticker symbols, ordered by each ticker's own-year percentile where one exists and otherwise by the size of its largest flagged contract; it carries no per-ticker score, so take numbers from each ticker's `/summary`). Both carry `capabilities.intradayBoard`, which describes the board, not data: `apiData: false` means its rows are app-only, `access` is `signed_in_pro` or `power_user` (an early-access group), and `url` opens it. The fields are the same on every tier, previews included, carry no contract, strike, price or premium amount, and are omitted before the day's first board.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, and show each one's `notionalVol` beside it: a scored row traded at least $100,000 of premium that session, so a stretched reading near that floor is still thin activity and should be labeled as such. Then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (unscored: a building baseline or a session below the liquidity floor).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize in percentile terms: where `atmIv` sits in its 1y range (`ivRank1y`), whether `pcVol` is high or low for this name (`pcVolPctl1y`), and which way `skew25d` leans (positive means puts bid richer than calls, a downside-demand tilt). Note `maxPain` and the nearest walls as context for the dossier expiry, not as targets. If `context` percentiles are missing, report them as unavailable, and as a building baseline only when `observations1y` is low. If `isPreview` is `true` instead, the free monthly dossier meter is spent: only the headline fields are present, so summarize those and say the full dossier needs PRO or the next monthly reset, rather than reading the missing sections as a data gap.\n\n**3. Spot unusually active contracts**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/TSLA/options/summary\" | python3 -c \"\nimport sys, json\nj = json.load(sys.stdin)\nd = j.get('data')\nif j.get('isPreview'):\n    print('PREVIEW: the unusual list is withheld on the free headline preview (needs PRO or the monthly reset)')\nelif d is None:\n    print('NOT COVERED: data is null for this ticker')\nelse:\n    print(json.dumps(d.get('unusual', []), indent=2))\n\"\n```\nOn an `isPreview: true` response the `unusual` key is absent because the section is withheld, not because the session had no unusual contracts: never report \"no unusual activity\" from a preview. Say the list needs a full dossier, and use the preview's `largePrintCount` only for what it is, a count of large prints in the latest published post-close session, capped at 25. The `unusual` list is contracts whose session volume ran far above open interest (`volOiRatio`), ranked by dollar `premium`. A high ratio on a short-dated contract is often event-driven, so quote the `dte` and let the reader weigh it. This is end-of-day activity, so describe it as \"unusually active in the last session\", not as a live sweep. Each contract also carries an open-interest follow-up once the next session's open interest has been read: `oiConfirmation` is `opened` (open interest rose by at least half the session's volume), `closed` (it fell by at least a quarter of it), `mixed`, `pending`, or `unmatched` (not in the next chain). `pending` supports no conclusion about the next session's open interest yet. A contract that expired on the flagged session is never in the next chain, so it resolves `unmatched` and cannot show a position carried overnight. To follow up after the dossier rolls forward, keep the `contract` id and the session's `asOf`: the resolved follow-up lands on that date's `/options/history` row as `unusualOi`, one entry per contract. Report the numbers: \"open interest rose by 3,100 (62% of that session's volume)\", \"fell by 900\", or \"changed little (+40)\". These net changes do not establish trade composition; buyer or seller not identified. `oiObservedAt` is UTC epoch seconds and `oiVintage` is `prior_settle`, `settled`, or `next_session`.\n\n**4. Chart how a reading has trended**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/AAPL/options/history?window=1y\"\n```\nPull `atmIv`, `pcVol`, or `skew25d` out of `series` to show the trend behind today's percentile. A free key always gets `1y`; the `window` field confirms what was served.\n\n**5. Follow the convergence.** When rich call activity or a low put/call percentile lines up with climbing sentiment (`stock-sentiment`), a congressional buy (`politicians-stock-tracker`), or institutional accumulation (`institutional-13f-tracker`) on the same ticker in the same window, that agreement is the read worth surfacing. Say so explicitly, cite each source, and note when the dots disagree (for example, bullish flow against a put-heavy skew) rather than forcing a clean story.\n\n## Answering well\n\n- **Lead with the percentile.** \"IV rank 74 (elevated for this name)\" carries the signal; the bare 53% IV does not. Do the same for put/call and skew.\n- **Say end-of-day.** Frame every reading as the session its `asOf` names, except the intraday session fields: quote those with their clock and the delay (\"3 unusual contracts on NVDA as of 14:30 ET, 15-minute delayed\"). Never imply real-time flow, live sweeps, or intraday order tape, and never name the contracts behind a count the API does not list.\n- **Do not overstate structure.** Max pain and open-interest walls are descriptive magnets and context, not predictions of where the stock will close. `netDelta` is the chain's aggregate net delta exposure (open-interest-weighted), not an inference about dealer books and not a gamma or hedging figure.\n- **Respect the baseline.** If percentiles or `interestScore` are omitted, report them as unavailable rather than reading them as a zero or a bearish signal, and say history is still accruing only when `observations1y` is low.\n- **Report only what the API returns.** Do not infer greeks, dealer gamma, or intentions the data does not contain, and do not frame any of it as advice. Options carry a high level of risk; this is derived analytics for education.\n\n## Going further\n\nFree covers every workflow above: the top of the radar, ten full dossiers a month, and a year of history. **PRO ($15/mo)** lifts the monthly request cap (no monthly limit, just a 300/min rate), returns the full radar board and unlimited full dossiers, and deepens history, plus sentiment, smart-money flows, insider detail, and AI insights across the rest of the SentiSense API. Apply coupon `AGENTS` at checkout for a builder launch discount: https://app.sentisense.ai/pricing?coupon=AGENTS. A preview response's `upgrade` object may carry a different current code in its `url`; either code works, and when that object is present, relay its `price` and `url`.\n\n**ClawHub Skill:** [clawhub.ai/TheSentiTrader/unusual-options-activity](https://clawhub.ai/TheSentiTrader/unusual-options-activity)\n\n---\n\n*SentiSense is a read-only financial intelligence API. Options analytics here are derived, end-of-day, and for informational and educational purposes only, not investment advice. Options carry a high level of risk.*\n\nFile v1.5.3:_meta.json\n\n{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.5.3\",\n  \"publishedAt\": 1790880558271\n}\n\nFile v1.5.3:skill-card.md\n\n## Description:\n\nProvides read-only, historical-context options analytics for US stocks and ETFs, including unusual activity, implied volatility, put/call ratios, skew, and open-interest levels.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nInvestors, analysts, and developers use this skill to compare options activity and positioning against a ticker's own history. It provides informational market context, not trading advice or order execution.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill requires a SentiSense API key and sends requested ticker or company/fund searches to SentiSense.\n\nMitigation: Provide a key only if comfortable with this access and sharing those searches; keep the key private.\n\nRisk: Options analytics may be mistaken for real-time flow or investment advice.\n\nMitigation: Check the session timestamp and any intraday delay, and use the results as informational context rather than trading advice.\n\nRisk: Free-tier quotas and paid-tier behavior may affect access or cost.\n\nMitigation: Review the applicable quota and any upgrade terms before relying on additional requests or a paid tier.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Analysis, Guidance]\n\n**Output Format:** [Markdown]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [End-of-day readings include the session date; intraday counts, when available, are delayed and separately timestamped.]\n\n## Skill Version(s):\n\n1.5.3 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.5.2: 3 files, 11248 bytes\n\nFiles: skill-card.md (1898b), SKILL.md (24309b), _meta.json (143b)\n\nFile v1.5.2:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading describes the latest published snapshot, and `asOf` names its session: quote it. The snapshot refreshes each weekday evening after the close (the run starts about 21:15 ET), so after successful publication `asOf` is that day's session, and between the close and that refresh it is still the previous session. Follow-ups compare the next session's open interest and remain pending until that chain is observed. On weekends and holidays `asOf` is the latest completed session. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints; the one intraday reading is a 15-minute delayed count and percentile (see \"Intraday session fields\" below), which carries its own timestamp and can describe a later session than `asOf` in the same response. \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number. Units: IV and the expected moves are fractions (`atmIv` 0.3124 is 31.24%), `skew25d` is an IV difference in the same fraction units (0.0293 is 2.93 percentage points), and ranks and percentiles run 0 to 100.\n- **Coverage is two bounded universes.** Stocks: about 1,040 of the most actively optioned US names (the number moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: covered funds are served on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. The full overview's `etfRows` is the authoritative fund list: `GET /api/v1/etfs` lists every fund SentiSense tracks, a wider set, and a tracked fund without an options snapshot returns `data: null` from `/summary`. A free key receives only the top 25 ETF rows, so absence from that slice does not establish noncoverage. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (`observations1y` under 60 sessions) returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. A ticker with a full history can still be unscored when its latest session fell below the liquidity floor ($250,000 of estimated premium activity or 100 contracts listed in the chain). Report a missing percentile or score as unavailable, never as a low reading, and call it a building baseline only when `observations1y` is low.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and history windows up to `5y` (2+ years available, from July 2024, growing daily). |\n\nThe free tier exercises every workflow below on real data. Every covered `/summary` call spends one of the ten full dossiers, repeat calls for the same ticker included, and calls made earlier in the month on the same account count too, so branch on `isPreview` rather than counting calls yourself. Uncovered tickers that return `data: null` never spend the monthly dossier meter. The dossier allowance and the monthly request quota reset at the start of the first day of each calendar month, Eastern time (America/New_York).\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nThe three options endpoints return the wrapped envelope `{ isPreview, previewReason, data }`; `GET /api/v1/etfs` and the name resolver below return bare arrays. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Inside `data`, unavailable nested metric fields are omitted rather than sent as `null`, but envelope fields can be an explicit `null` (`previewReason` on a full response, `data` for an uncovered ticker), and so can the resolver's `ticker`: handle absent and `null` alike. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names; unscored rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `atmIv`, `skew25d`, `notionalVol`, `observations1y`, `unusualCount` and, when `atmIv` is valid, the expected-move set (`expectedMove1d`/`5d`/`20d` and their `1s` variants). **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since unavailable row fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls. The same response carries `highlights` (stocks) and `etfHighlights` (ETFs): each ticker's highest-premium qualifying contract of the latest completed session with an expiry at least one day out (same-day expiries are not eligible), one per ticker, up to 10, ranked by `premiumPctl1y` (that premium against the ticker's own previous 252 sessions; omitted while the baseline builds). Free keys receive the top 3 of each. Each list carries its own stamp, `highlightPolicy` for `highlights` and `etfHighlightPolicy` for `etfHighlights`: read a list under that rule only when its own stamp is `ex0dte-v1`, since an absent stamp means that list was built under the older rule, which allowed same-day expiries.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of `{ asOf, sentiment, ivRank1y, atmIv, expectedMove1d, pcVol, pcVolPctl1y, maxPain }`, plus the intraday session fields below when present, with `isPreview: true` until the monthly reset. `latest` is the aggregate for the returned `asOf` session (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium, oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage }`; the oi-prefixed fields are the open-interest follow-up described below.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns the available history within that window (2+ years, from July 2024, growing daily), not a guaranteed five years. Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n**Intraday session fields.** On a trading day the app runs an intraday options board, rebuilt every 15 minutes from 15-minute delayed chains, and publishes the session's large prints after the close. On the API the intraday session is a count and a percentile; the contract-level board is in the app. `/summary` adds `intradayFlow` (`unusualCount`, contracts on the ticker's row passing the unusual rule so far, up to 5; `firstSeenEt` and `firstSeenAt`, the earliest cycle that flagged one; `flowPctl1y`, the ticker's intraday highlight against its own history, omitted while that baseline holds fewer than 60 sessions; `asOfEt`, `asOf` in epoch seconds, `live`, `delayMinutes`), plus `largePrintCount` (the ticker's large prints in the latest published post-close session, up to 25) and `largestPrintPctl` (the highest percentile among them). `/overview` adds `intradayActiveCount` (stocks with at least one unusual contract so far) and `intradayRanking` (up to 25 of them as an array of ticker symbols, ordered by each ticker's own-year percentile where one exists and otherwise by the size of its largest flagged contract; it carries no per-ticker score, so take numbers from each ticker's `/summary`). Both carry `capabilities.intradayBoard`, which describes the board, not data: `apiData: false` means its rows are app-only, `access` is `signed_in_pro` or `power_user` (an early-access group), and `url` opens it. The fields are the same on every tier, previews included, carry no contract, strike, price or premium amount, and are omitted before the day's first board.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (unscored: a building baseline or a session below the liquidity floor).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize in percentile terms: where `atmIv` sits in its 1y range (`ivRank1y`), whether `pcVol` is high or low for this name (`pcVolPctl1y`), and which way `skew25d` leans (positive means puts bid richer than calls, a downside-demand tilt). Note `maxPain` and the nearest walls as context for the dossier expiry, not as targets. If `context` percentiles are missing, report them as unavailable, and as a building baseline only when `observations1y` is low. If `isPreview` is `true` instead, the free monthly dossier meter is spent: only the headline fields are present, so summarize those and say the full dossier needs PRO or the next monthly reset, rather than reading the missing sections as a data gap.\n\n**3. Spot unusually active contracts**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/TSLA/options/summary\" | \\\n  python3 -c \"import sys,json; d=json.load(sys.stdin).get('data') or {}; print(json.dumps(d.get('unusual', []), indent=2))\"\n```\nThe `unusual` list is contracts whose session volume ran far above open interest (`volOiRatio`), ranked by dollar `premium`. A high ratio on a short-dated contract is often event-driven, so quote the `dte` and let the reader weigh it. This is end-of-day activity, so describe it as \"unusually active in the last session\", not as a live sweep. Each contract also carries an open-interest follow-up once the next session's open interest has been read: `oiConfirmation` is `opened` (open interest rose by at least half the session's volume), `closed` (it fell by at least a quarter of it), `mixed`, `pending`, or `unmatched` (not in the next chain). `pending` supports no conclusion about the next session's open interest yet. A contract that expired on the flagged session is never in the next chain, so it resolves `unmatched` and cannot show a position carried overnight. To follow up after the dossier rolls forward, keep the `contract` id and the session's `asOf`: the resolved follow-up lands on that date's `/options/history` row as `unusualOi`, one entry per contract. Report the numbers: \"open interest rose by 3,100 (62% of that session's volume)\", \"fell by 900\", or \"changed little (+40)\". These net changes do not establish trade composition; buyer or seller not identified. `oiObservedAt` is UTC epoch seconds and `oiVintage` is `prior_settle`, `settled`, or `next_session`.\n\n**4. Chart how a reading has trended**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/AAPL/options/history?window=1y\"\n```\nPull `atmIv`, `pcVol`, or `skew25d` out of `series` to show the trend behind today's percentile. A free key always gets `1y`; the `window` field confirms what was served.\n\n**5. Follow the convergence.** When rich call activity or a low put/call percentile lines up with climbing sentiment (`stock-sentiment`), a congressional buy (`politicians-stock-tracker`), or institutional accumulation (`institutional-13f-tracker`) on the same ticker in the same window, that agreement is the read worth surfacing. Say so explicitly, cite each source, and note when the dots disagree (for example, bullish flow against a put-heavy skew) rather than forcing a clean story.\n\n## Answering well\n\n- **Lead with the percentile.** \"IV rank 74 (elevated for this name)\" carries the signal; the bare 53% IV does not. Do the same for put/call and skew.\n- **Say end-of-day.** Frame every reading as the session its `asOf` names, except the intraday session fields: quote those with their clock and the delay (\"3 unusual contracts on NVDA as of 14:30 ET, 15-minute delayed\"). Never imply real-time flow, live sweeps, or intraday order tape, and never name the contracts behind a count the API does not list.\n- **Do not overstate structure.** Max pain and open-interest walls are descriptive magnets and context, not predictions of where the stock will close. `netDelta` is the chain's aggregate net delta exposure (open-interest-weighted), not an inference about dealer books and not a gamma or hedging figure.\n- **Respect the baseline.** If percentiles or `interestScore` are omitted, report them as unavailable rather than reading them as a zero or a bearish signal, and say history is still accruing only when `observations1y` is low.\n- **Report only what the API returns.** Do not infer greeks, dealer gamma, or intentions the data does not contain, and do not frame any of it as advice. Options carry a high level of risk; this is derived analytics for education.\n\n## Going further\n\nFree covers every workflow above: the top of the radar, ten full dossiers a month, and a year of history. **PRO ($15/mo)** lifts the monthly request cap (no monthly limit, just a 300/min rate), returns the full radar board and unlimited full dossiers, and deepens history, plus sentiment, smart-money flows, insider detail, and AI insights across the rest of the SentiSense API. Apply coupon `AGENTS26` at checkout for a builder launch discount: https://app.sentisense.ai/pricing?coupon=AGENTS26. A preview response's `upgrade` object may carry a different current code in its `url`; either code works, and when that object is present, relay its `price` and `url`.\n\n**ClawHub Skill:** [clawhub.ai/TheSentiTrader/unusual-options-activity](https://clawhub.ai/TheSentiTrader/unusual-options-activity)\n\n---\n\n*SentiSense is a read-only financial intelligence API. Options analytics here are derived, end-of-day, and for informational and educational purposes only, not investment advice. Options carry a high level of risk.*\n\nFile v1.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.5.2\",\n  \"publishedAt\": 1790824364785\n}\n\nFile v1.5.2:skill-card.md\n\n## Description:\n\nProvides read-only SentiSense options analytics for US stocks and ETFs, including unusual activity, volatility rankings, put/call positioning, and open-interest levels.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nAnalysts and developers use this skill to review historical context and unusual options activity for US stocks and ETFs without placing trades. Its findings are educational market context, not investment advice.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Authenticated queries send the SentiSense API key to SentiSense.\n\nMitigation: Keep the key private and use it only for the disclosed read-only SentiSense requests.\n\nRisk: Options analytics may be mistaken for current trading signals or investment advice.\n\nMitigation: Label end-of-day readings and delayed intraday counts accurately; treat results as educational context, not standalone trading decisions.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Analysis, Guidance, Shell commands]\n\n**Output Format:** [Markdown with optional shell commands]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only, mostly end-of-day analytics; some intraday counts are delayed.]\n\n## Skill Version(s):\n\n1.5.2 (source: server-resolved release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.5.1: 3 files, 11204 bytes\n\nFiles: skill-card.md (2198b), SKILL.md (23722b), _meta.json (143b)\n\nFile v1.5.1:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading describes the latest published snapshot, and `asOf` names its session: quote it. The snapshot refreshes each weekday evening after the close (the run starts about 21:15 ET), so from then on `asOf` is that day's session, and between the close and that refresh it is still the previous session. Follow-ups compare the next session's open interest and remain pending until that chain is observed. On weekends and holidays `asOf` is the latest completed session. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints; the one intraday reading is a 15-minute delayed count and percentile (see \"Intraday session fields\" below), which carries its own timestamp and can describe a later session than `asOf` in the same response. \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number. Units: IV and the expected moves are fractions (`atmIv` 0.3124 is 31.24%), `skew25d` is an IV difference in the same fraction units (0.0293 is 2.93 percentage points), and ranks and percentiles run 0 to 100.\n- **Coverage is two bounded universes.** Stocks: about 1,040 of the most actively optioned US names (the number moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: covered funds are served on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. `etfRows` is the authoritative fund list: `GET /api/v1/etfs` lists every fund SentiSense tracks, a wider set, and a tracked fund outside `etfRows` returns `data: null` from `/summary`. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (`observations1y` roughly under 60 sessions) returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. A ticker with a full history can still lack `interestScore` when its latest session fell below a liquidity floor. Report a missing percentile or score as unavailable, never as a low reading, and call it a building baseline only when `observations1y` is low.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and up to `5y` history. |\n\nThe free tier exercises every workflow below on real data. Every covered `/summary` call spends one of the ten full dossiers, repeat calls for the same ticker included, and calls made earlier in the month on the same account count too, so branch on `isPreview` rather than counting calls yourself. Uncovered tickers that return `data: null` never spend the monthly dossier meter.\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nThe three options endpoints return the wrapped envelope `{ isPreview, previewReason, data }`; `GET /api/v1/etfs` and the name resolver below return bare arrays. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Inside `data`, a metric with no reading is omitted rather than sent as `null`, but envelope fields can be an explicit `null` (`previewReason` on a full response, `data` for an uncovered ticker), and so can the resolver's `ticker`: handle absent and `null` alike. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names today; building-baseline rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `atmIv`, `skew25d`, `notionalVol`, `observations1y`, `unusualCount` and the expected-move set (`expectedMove1d`/`5d`/`20d` and their `1s` variants). **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since null-valued fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls. The same response carries `highlights` (stocks) and `etfHighlights` (ETFs): each ticker's highest-premium qualifying contract of the latest completed session with an expiry at least one day out (same-day expiries are not eligible), one per ticker, up to 10, ranked by `premiumPctl1y` (that premium against the ticker's own previous 252 sessions; omitted while the baseline builds). Free keys receive the top 3 of each. Each list carries its own stamp, `highlightPolicy` for `highlights` and `etfHighlightPolicy` for `etfHighlights`: read a list under that rule only when its own stamp is `ex0dte-v1`, since an absent stamp means that list was built under the older rule, which allowed same-day expiries.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of `{ asOf, sentiment, ivRank1y, atmIv, expectedMove1d, pcVol, pcVolPctl1y, maxPain }`, plus the intraday session fields below when present, with `isPreview: true` until the monthly reset. `latest` is today's aggregate (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium, oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage }`; the oi-prefixed fields are the open-interest follow-up described below.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns all stored history (currently about two years, backfilled from mid-2024). Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n**Intraday session fields.** On a trading day the app runs an intraday options board, rebuilt every 15 minutes from 15-minute delayed chains, and publishes the session's large prints after the close. On the API the intraday session is a count and a percentile; the contract-level board is in the app. `/summary` adds `intradayFlow` (`unusualCount`, contracts on the ticker's row passing the unusual rule so far, up to 5; `firstSeenEt` and `firstSeenAt`, the earliest cycle that flagged one; `flowPctl1y`, the ticker's intraday highlight against its own history, omitted while that baseline holds fewer than 60 sessions; `asOfEt`, `asOf` in epoch seconds, `live`, `delayMinutes`), plus `largePrintCount` (the ticker's large prints in the latest published post-close session, up to 25) and `largestPrintPctl` (the highest percentile among them). `/overview` adds `intradayActiveCount` (stocks with at least one unusual contract so far) and `intradayRanking` (up to 25 of them as an array of ticker symbols, most unusual for their own history first; it carries no per-ticker score, so take numbers from each ticker's `/summary`). Both carry `capabilities.intradayBoard`, which describes the board, not data: `apiData: false` means its rows are app-only, `access` is `signed_in_pro` or `power_user` (an early-access group), and `url` opens it. The fields are the same on every tier, previews included, carry no contract, strike, price or premium amount, and are omitted before the day's first board.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (unscored: a building baseline or a session below the liquidity floor).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize in percentile terms: where `atmIv` sits in its 1y range (`ivRank1y`), whether `pcVol` is high or low for this name (`pcVolPctl1y`), and which way `skew25d` leans (positive means puts bid richer than calls, a downside-demand tilt). Note `maxPain` and the nearest walls as context for the dossier expiry, not as targets. If `context` percentiles are missing, report them as unavailable, and as a building baseline only when `observations1y` is low. If `isPreview` is `true` instead, the free monthly dossier meter is spent: only the headline fields are present, so summarize those and say the full dossier needs PRO or the next monthly reset, rather than reading the missing sections as a data gap.\n\n**3. Spot unusually active contracts**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/TSLA/options/summary\" | \\\n  python3 -c \"import sys,json; d=json.load(sys.stdin).get('data') or {}; print(json.dumps(d.get('unusual', []), indent=2))\"\n```\nThe `unusual` list is contracts whose session volume ran far above open interest (`volOiRatio`), ranked by dollar `premium`. A high ratio on a short-dated contract is often event-driven, so quote the `dte` and let the reader weigh it. This is end-of-day activity, so describe it as \"unusually active in the last session\", not as a live sweep. Each contract also carries an open-interest follow-up once the next session's open interest has been read: `oiConfirmation` is `opened` (open interest rose by at least half the session's volume), `closed` (it fell by at least a quarter of it), `mixed`, `pending`, or `unmatched` (not in the next chain). `pending` supports no conclusion about the next session's open interest yet. A contract that expired on the flagged session is never in the next chain, so it resolves `unmatched` and cannot show a position carried overnight. To follow up after the dossier rolls forward, keep the `contract` id and the session's `asOf`: the resolved follow-up lands on that date's `/options/history` row as `unusualOi`, one entry per contract. Report the numbers: \"open interest rose by 3,100 (62% of that session's volume)\", \"fell by 900\", or \"changed little (+40)\". These net changes do not establish trade composition; buyer or seller not identified. `oiObservedAt` is UTC epoch seconds and `oiVintage` is `prior_settle`, `settled`, or `next_session`.\n\n**4. Chart how a reading has trended**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/AAPL/options/history?window=1y\"\n```\nPull `atmIv`, `pcVol`, or `skew25d` out of `series` to show the trend behind today's percentile. A free key always gets `1y`; the `window` field confirms what was served.\n\n**5. Follow the convergence.** When rich call activity or a low put/call percentile lines up with climbing sentiment (`stock-sentiment`), a congressional buy (`politicians-stock-tracker`), or institutional accumulation (`institutional-13f-tracker`) on the same ticker in the same window, that agreement is the read worth surfacing. Say so explicitly, cite each source, and note when the dots disagree (for example, bullish flow against a put-heavy skew) rather than forcing a clean story.\n\n## Answering well\n\n- **Lead with the percentile.** \"IV rank 74 (elevated for this name)\" carries the signal; the bare 53% IV does not. Do the same for put/call and skew.\n- **Say end-of-day.** Frame every reading as the session its `asOf` names, except the intraday session fields: quote those with their clock and the delay (\"3 unusual contracts on NVDA as of 14:30 ET, 15-minute delayed\"). Never imply real-time flow, live sweeps, or intraday order tape, and never name the contracts behind a count the API does not list.\n- **Do not overstate structure.** Max pain and open-interest walls are descriptive magnets and context, not predictions of where the stock will close. `netDelta` is the chain's aggregate net delta exposure (open-interest-weighted), not an inference about dealer books and not a gamma or hedging figure.\n- **Respect the baseline.** If percentiles or `interestScore` are omitted, report them as unavailable rather than reading them as a zero or a bearish signal, and say history is still accruing only when `observations1y` is low.\n- **Report only what the API returns.** Do not infer greeks, dealer gamma, or intentions the data does not contain, and do not frame any of it as advice. Options carry a high level of risk; this is derived analytics for education.\n\n## Going further\n\nFree covers every workflow above: the top of the radar, ten full dossiers a month, and a year of history. **PRO ($15/mo)** lifts the monthly request cap (no monthly limit, just a 300/min rate), returns the full radar board and unlimited full dossiers, and deepens history, plus sentiment, smart-money flows, insider detail, and AI insights across the rest of the SentiSense API. Apply coupon `AGENTS26` at checkout for a builder launch discount: https://app.sentisense.ai/pricing?coupon=AGENTS26. A preview response's `upgrade` object may carry a different current code in its `url`; either code works, and when that object is present, relay its `price` and `url`.\n\n**ClawHub Skill:** [clawhub.ai/TheSentiTrader/unusual-options-activity](https://clawhub.ai/TheSentiTrader/unusual-options-activity)\n\n---\n\n*SentiSense is a read-only financial intelligence API. Options analytics here are derived, end-of-day, and for informational and educational purposes only, not investment advice. Options carry a high level of risk.*\n\nFile v1.5.1:_meta.json\n\n{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.5.1\",\n  \"publishedAt\": 1790807597263\n}\n\nFile v1.5.1:skill-card.md\n\n## Description:\n\nProvides read-only options activity and positioning analytics for US stocks and ETFs, comparing end-of-day readings with each ticker's own history.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nUsers and analysts can examine unusual options activity, implied volatility, sentiment, put/call positioning, skew, open-interest walls, and max pain for covered US stocks and ETFs. The results are informational, not trading instructions or personalized financial advice.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Exposing the SentiSense API key could allow unauthorized use of the account's data quota.\n\nMitigation: Keep SENTISENSE_API_KEY in the environment; never include it in prompts, URLs, or responses.\n\nRisk: Authenticated requests consume API quota, and free accounts have limited full dossiers.\n\nMitigation: Check coverage and preview status before additional requests, and respect rate and quota limits.\n\nRisk: Delayed or end-of-day options signals may be mistaken for live flow or investment advice.\n\nMitigation: State the session date and any intraday delay, and present the analytics as informational rather than predictive or personalized advice.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Analysis]\n\n**Output Format:** [Markdown with cited options analytics and session dates]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only; available readings reflect published sessions, while intraday counts are delayed.]\n\n## Skill Version(s):\n\n1.5.1 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.5.0: 3 files, 10380 bytes\n\nFiles: skill-card.md (2006b), SKILL.md (21665b), _meta.json (143b)\n\nFile v1.5.0:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading is the latest completed session. It refreshes each weekday evening after the close, so from the evening on `asOf` is that day's session and before it the prior trading day; follow-ups compare the next session's open interest and remain pending until that chain is observed. On weekends and holidays `asOf` is the latest completed session. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints; the one intraday reading is a 15-minute delayed count and percentile (see \"Intraday session fields\" below). \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number.\n- **Coverage is two bounded universes.** Stocks: about 1,040 of the most actively optioned US names (the number moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: the US ETFs SentiSense tracks (`GET /api/v1/etfs`) get the same coverage on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (roughly under 60 sessions) or below a liquidity floor returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. Treat a missing percentile as \"not enough history yet\", never as a low reading.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and up to `5y` history. |\n\nThe free tier exercises every workflow below on real data. Uncovered tickers that return `data: null` never spend the monthly dossier meter.\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nEvery endpoint returns the wrapped envelope `{ isPreview, previewReason, data }`. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Null-valued fields are omitted from the JSON entirely, so check for field presence rather than comparing against `null`. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names today; building-baseline rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `atmIv`, `skew25d`, `notionalVol`, `observations1y`, `unusualCount` and the expected-move set (`expectedMove1d`/`5d`/`20d` and their `1s` variants). **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since null-valued fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls. The same response carries `highlights` (stocks) and `etfHighlights` (ETFs): each ticker's highest-premium qualifying contract of the latest completed session with an expiry at least one day out (same-day expiries are not eligible), one per ticker, up to 10, ranked by `premiumPctl1y` (that premium against the ticker's own previous 252 sessions; omitted while the baseline builds). Free keys receive the top 3 of each. Each list carries its own stamp, `highlightPolicy` for `highlights` and `etfHighlightPolicy` for `etfHighlights`: read a list under that rule only when its own stamp is `ex0dte-v1`, since an absent stamp means that list was built under the older rule, which allowed same-day expiries.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of `{ asOf, sentiment, ivRank1y, atmIv, expectedMove1d, pcVol, pcVolPctl1y, maxPain }`, plus the intraday session fields below when present, with `isPreview: true` until the monthly reset. `latest` is today's aggregate (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium, oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage }`; the oi-prefixed fields are the open-interest follow-up described below.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns all stored history (currently about two years, backfilled from mid-2024). Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n**Intraday session fields.** On a trading day the app runs an intraday options board, rebuilt every 15 minutes from 15-minute delayed chains, and publishes the session's large prints after the close. On the API the intraday session is a count and a percentile; the contract-level board is in the app. `/summary` adds `intradayFlow` (`unusualCount`, contracts on the ticker's row passing the unusual rule so far, up to 5; `firstSeenEt` and `firstSeenAt`, the earliest cycle that flagged one; `flowPctl1y`, the ticker's intraday highlight against its own history, omitted while that baseline holds fewer than 60 sessions; `asOfEt`, `asOf` in epoch seconds, `live`, `delayMinutes`), plus `largePrintCount` (the ticker's large prints in the latest published post-close session, up to 25) and `largestPrintPctl` (the highest percentile among them). `/overview` adds `intradayActiveCount` (stocks with at least one unusual contract so far) and `intradayRanking` (up to 25 of them, most unusual for their own history first). Both carry `capabilities.intradayBoard`, which describes the board, not data: `apiData: false` means its rows are app-only, `access` is `signed_in_pro` or `power_user` (an early-access group), and `url` opens it. The fields are the same on every tier, previews included, carry no contract, strike, price or premium amount, and are omitted before the day's first board.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (baseline still building).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize in percentile terms: where `atmIv` sits in its 1y range (`ivRank1y`), whether `pcVol` is high or low for this name (`pcVolPctl1y`), and which way `skew25d` leans (positive means puts bid richer than calls, a downside-demand tilt). Note `maxPain` and the nearest walls as context for the dossier expiry, not as targets. If `context` percentiles are missing, say the baseline is still building. If `isPreview` is `true` instead, the free monthly dossier meter is spent: only the headline fields are present, so summarize those and say the full dossier needs PRO or the next monthly reset, rather than reading the missing sections as a data gap.\n\n**3. Spot unusually active contracts**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/TSLA/options/summary\" | \\\n  python3 -c \"import sys,json; d=json.load(sys.stdin).get('data') or {}; print(json.dumps(d.get('unusual', []), indent=2))\"\n```\nThe `unusual` list is contracts whose session volume ran far above open interest (`volOiRatio`), ranked by dollar `premium`. A high ratio on a short-dated contract is often event-driven, so quote the `dte` and let the reader weigh it. This is end-of-day activity, so describe it as \"unusually active in the last session\", not as a live sweep. Each contract also carries an open-interest follow-up once the next session's open interest has been read: `oiConfirmation` is `opened` (open interest rose by at least half the session's volume), `closed` (it fell by at least a quarter of it), `mixed`, `pending`, or `unmatched` (not in the next chain). Report the numbers: \"open interest rose by 3,100 (62% of that session's volume)\", \"fell by 900\", or \"changed little (+40)\". These net changes do not establish trade composition; buyer or seller not identified. `oiObservedAt` is UTC epoch seconds and `oiVintage` is `prior_settle`, `settled`, or `next_session`.\n\n**4. Chart how a reading has trended**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/AAPL/options/history?window=1y\"\n```\nPull `atmIv`, `pcVol`, or `skew25d` out of `series` to show the trend behind today's percentile. A free key always gets `1y`; the `window` field confirms what was served.\n\n**5. Follow the convergence.** When rich call activity or a low put/call percentile lines up with climbing sentiment (`stock-sentiment`), a congressional buy (`politicians-stock-tracker`), or institutional accumulation (`institutional-13f-tracker`) on the same ticker in the same window, that agreement is the read worth surfacing. Say so explicitly, cite each source, and note when the dots disagree (for example, bullish flow against a put-heavy skew) rather than forcing a clean story.\n\n## Answering well\n\n- **Lead with the percentile.** \"IV rank 74 (elevated for this name)\" carries the signal; the bare 53% IV does not. Do the same for put/call and skew.\n- **Say end-of-day.** Frame every reading as the latest completed session, except the intraday session fields: quote those with their clock and the delay (\"3 unusual contracts on NVDA as of 14:30 ET, 15-minute delayed\"). Never imply real-time flow, live sweeps, or intraday order tape, and never name the contracts behind a count the API does not list.\n- **Do not overstate structure.** Max pain and open-interest walls are descriptive magnets and context, not predictions of where the stock will close. `netDelta` is the chain's aggregate net delta exposure (open-interest-weighted), not an inference about dealer books and not a gamma or hedging figure.\n- **Respect the baseline.** If percentiles or `interestScore` are omitted, state that history is still accruing rather than reading it as a zero or a bearish signal.\n- **Report only what the API returns.** Do not infer greeks, dealer gamma, or intentions the data does not contain, and do not frame any of it as advice. Options carry a high level of risk; this is derived analytics for education.\n\n## Going further\n\nFree covers every workflow above: the top of the radar, ten full dossiers a month, and a year of history. **PRO ($15/mo)** lifts the monthly request cap (no monthly limit, just a 300/min rate), returns the full radar board and unlimited full dossiers, and deepens history, plus sentiment, smart-money flows, insider detail, and AI insights across the rest of the SentiSense API. Apply coupon `AGENTS26` at checkout for a builder launch discount: https://app.sentisense.ai/pricing?coupon=AGENTS26\n\n**ClawHub Skill:** [clawhub.ai/TheSentiTrader/unusual-options-activity](https://clawhub.ai/TheSentiTrader/unusual-options-activity)\n\n---\n\n*SentiSense is a read-only financial intelligence API. Options analytics here are derived, end-of-day, and for informational and educational purposes only, not investment advice. Options carry a high level of risk.*\n\nFile v1.5.0:_meta.json\n\n{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.5.0\",\n  \"publishedAt\": 1790790600196\n}\n\nFile v1.5.0:skill-card.md\n\n## Description:\n\nProvides read-only SentiSense options analytics for US stocks and ETFs, including unusual activity, implied-volatility rank, sentiment, skew, and open-interest context.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to review unusual options activity and historical percentile context for US stocks and ETFs. Its read-only findings support research, not personalized trading decisions.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Options queries and the SentiSense API key are sent to SentiSense.\n\nMitigation: Send only intended queries, keep the API key in the environment and authentication header, and never include it in URLs or user-facing output.\n\nRisk: Delayed or incomplete options analytics could be mistaken for live signals or investment advice.\n\nMitigation: Label end-of-day and 15-minute-delayed readings, disclose missing baselines or preview limits, and present findings as educational context rather than trading recommendations.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Guidance]\n\n**Output Format:** [Markdown]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only, sourced market analysis; end-of-day data with 15-minute-delayed intraday counts where available.]\n\n## Skill Version(s):\n\n1.5.0 (source: server-resolved release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.4.0: 3 files, 9519 bytes\n\nFiles: skill-card.md (1939b), SKILL.md (19547b), _meta.json (143b)\n\nFile v1.4.0:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading is the latest completed session. It refreshes each weekday evening after the close, so from the evening on `asOf` is that day's session and before it the prior trading day; follow-ups compare the next session's open interest and remain pending until that chain is observed. On weekends and holidays `asOf` is the latest completed session. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints. \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number.\n- **Coverage is two bounded universes.** Stocks: about a thousand of the most actively optioned US names (1,028 on 2026-09-05, and it moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: the US ETFs SentiSense tracks (`GET /api/v1/etfs`) get the same coverage on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (roughly under 60 sessions) or below a liquidity floor returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. Treat a missing percentile as \"not enough history yet\", never as a low reading.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and up to `5y` history. |\n\nThe free tier exercises every workflow below on real data. Uncovered tickers that return `data: null` never spend the monthly dossier meter.\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nEvery endpoint returns the wrapped envelope `{ isPreview, previewReason, data }`. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Null-valued fields are omitted from the JSON entirely, so check for field presence rather than comparing against `null`. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names today; building-baseline rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `atmIv`, `skew25d`, `notionalVol`, `observations1y`, `unusualCount` and the expected-move set (`expectedMove1d`/`5d`/`20d` and their `1s` variants). **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since null-valued fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls. The same response carries `highlights` (stocks) and `etfHighlights` (ETFs): each ticker's highest-premium unusual contract of the latest completed session, one per ticker, up to 10, ranked by `premiumPctl1y` (that premium against the ticker's own trailing year; omitted while the baseline builds). Free keys receive the top 3 of each.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of exactly `{ asOf, sentiment, ivRank1y, atmIv, pcVol, pcVolPctl1y, maxPain }` with `isPreview: true` until the monthly reset. `latest` is today's aggregate (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium, oiPrior, oiNext, oiChange, oiConfirmation, oiObservedAt, oiVintage }`; the oi-prefixed fields are the open-interest follow-up described below.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns all stored history (currently about two years, backfilled from mid-2024). Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (baseline still building).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize in percentile terms: where `atmIv` sits in its 1y range (`ivRank1y`), whether `pcVol` is high or low for this name (`pcVolPctl1y`), and which way `skew25d` leans (positive means puts bid richer than calls, a downside-demand tilt). Note `maxPain` and the nearest walls as context for the dossier expiry, not as targets. If `context` percentiles are missing, say the baseline is still building. If `isPreview` is `true` instead, the free monthly dossier meter is spent: only the headline fields are present, so summarize those and say the full dossier needs PRO or the next monthly reset, rather than reading the missing sections as a data gap.\n\n**3. Spot unusually active contracts**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/TSLA/options/summary\" | \\\n  python3 -c \"import sys,json; d=json.load(sys.stdin).get('data') or {}; print(json.dumps(d.get('unusual', []), indent=2))\"\n```\nThe `unusual` list is contracts whose session volume ran far above open interest (`volOiRatio`), ranked by dollar `premium`. A high ratio on a short-dated contract is often event-driven, so quote the `dte` and let the reader weigh it. This is end-of-day activity, so describe it as \"unusually active in the last session\", not as a live sweep. Each contract also carries an open-interest follow-up once the next session's open interest has been read: `oiConfirmation` is `opened` (open interest rose by at least half the session's volume), `closed` (it fell by at least a quarter of it), `mixed`, `pending`, or `unmatched` (not in the next chain). Report the numbers: \"open interest rose by 3,100 (62% of that session's volume)\", \"fell by 900\", or \"changed little (+40)\". These net changes do not establish trade composition; buyer or seller not identified. `oiObservedAt` is UTC epoch seconds and `oiVintage` is `prior_settle`, `settled`, or `next_session`.\n\n**4. Chart how a reading has trended**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/AAPL/options/history?window=1y\"\n```\nPull `atmIv`, `pcVol`, or `skew25d` out of `series` to show the trend behind today's percentile. A free key always gets `1y`; the `window` field confirms what was served.\n\n**5. Follow the convergence.** When rich call activity or a low put/call percentile lines up with climbing sentiment (`stock-sentiment`), a congressional buy (`politicians-stock-tracker`), or institutional accumulation (`institutional-13f-tracker`) on the same ticker in the same window, that agreement is the read worth surfacing. Say so explicitly, cite each source, and note when the dots disagree (for example, bullish flow against a put-heavy skew) rather than forcing a clean story.\n\n## Answering well\n\n- **Lead with the percentile.** \"IV rank 74 (elevated for this name)\" carries the signal; the bare 53% IV does not. Do the same for put/call and skew.\n- **Say end-of-day.** Frame every reading as the latest completed session. Never imply real-time flow, live sweeps, or intraday order tape.\n- **Do not overstate structure.** Max pain and open-interest walls are descriptive magnets and context, not predictions of where the stock will close. `netDelta` is the chain's aggregate net delta exposure (open-interest-weighted), not an inference about dealer books and not a gamma or hedging figure.\n- **Respect the baseline.** If percentiles or `interestScore` are omitted, state that history is still accruing rather than reading it as a zero or a bearish signal.\n- **Report only what the API returns.** Do not infer greeks, dealer gamma, or intentions the data does not contain, and do not frame any of it as advice. Options carry a high level of risk; this is derived analytics for education.\n\n## Going further\n\nFree covers every workflow above: the top of the radar, ten full dossiers a month, and a year of history. **PRO ($15/mo)** lifts the monthly request cap (no monthly limit, just a 300/min rate), returns the full radar board and unlimited full dossiers, and deepens history, plus sentiment, smart-money flows, insider detail, and AI insights across the rest of the SentiSense API. Apply coupon `AGENTS26` at checkout for a builder launch discount: https://app.sentisense.ai/pricing?coupon=AGENTS26\n\n**ClawHub Skill:** [clawhub.ai/TheSentiTrader/unusual-options-activity](https://clawhub.ai/TheSentiTrader/unusual-options-activity)\n\n---\n\n*SentiSense is a read-only financial intelligence API. Options analytics here are derived, end-of-day, and for informational and educational purposes only, not investment advice. Options carry a high level of risk.*\n\nFile v1.4.0:_meta.json\n\n{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.4.0\",\n  \"publishedAt\": 1790268213895\n}\n\nFile v1.4.0:skill-card.md\n\n## Description:\n\nProvides end-of-day options activity and positioning analytics for US stocks and ETFs, including IV rank, put/call percentiles, skew, open-interest walls, and unusually active contracts.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nInvestors, analysts, and developers use this skill to compare recent options activity and volatility with each ticker's own history. It provides educational market context, not personalized trading advice.\n\n### Deployment Geography for Use:\n\nGlobal (coverage focuses on US stocks and ETFs)\n\n## Known Risks and Mitigations:\n\nRisk: The SentiSense API key is sent with market-data requests.\n\nMitigation: Keep the key private and use it only for the disclosed read-only requests to app.sentisense.ai.\n\nRisk: Delayed options readings could be mistaken for live order flow or trading advice.\n\nMitigation: State the completed session date and present the readings as educational context, not a real-time signal or buy/sell recommendation.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Analysis, Guidance]\n\n**Output Format:** [Text or Markdown]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [End-of-day, read-only options analytics; includes as-of date and historical percentile context when available.]\n\n## Skill Version(s):\n\n1.4.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.3.2: 3 files, 9286 bytes\n\nFiles: skill-card.md (2479b), SKILL.md (18247b), _meta.json (143b)\n\nFile v1.3.2:SKILL.md\n\n---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before interpreting)\n\nOptions data is easy to over-read. Four things to hold onto:\n\n- **It is end-of-day, not real-time.** Each reading is the latest completed session, refreshed the next morning after the session settles. The `asOf` date is the prior trading day. This is not an intraday tape, so it does not classify sweeps or blocks and it does not stream live prints. \"Unusually active contracts\" means the session's volume ran far above standing open interest, which is a fresh-positioning signal, not a live order-flow feed.\n- **Percentiles are the point, not the raw levels.** A put/call ratio of 0.9 or an IV of 45% means little on its own. Every reading is served next to its rank within the ticker's own trailing window (a percentile for put/call and skew, a min-max range position for IV rank), so \"put/call volume at the 92nd percentile of its 1y range\" is the actual signal: unusual *for this specific name*. Lead with the ranked context, not the raw number.\n- **Coverage is two bounded universes.** Stocks: about a thousand of the most actively optioned US names (1,028 on 2026-09-05, and it moves as the universe is rebuilt), reported in the overview's `coverageCount`, which is the number to quote rather than any figure written here. The `rows` of `/options/overview` are the authoritative list. ETFs: the US ETFs SentiSense tracks (`GET /api/v1/etfs`) get the same coverage on the same `/stocks/{ticker}/options/...` paths, and on the radar they are a SEPARATE board, `etfRows`, never mixed into `rows`. `coverageCount` counts stocks only. Rank the two boards independently: every reading is a percentile of that ticker's own history, so an ETF's `interestScore` compares to other ETFs, not to a single stock. A ticker in neither universe returns `200` with `data: null` (summary) or an empty `series` (history). Treat a null as \"not covered\", not as an error.\n- **Building baseline is not zero.** A covered ticker with too little history (roughly under 60 sessions) or below a liquidity floor returns its raw readings with the percentiles and `interestScore` omitted while its baseline accrues. Treat a missing percentile as \"not enough history yet\", never as a low reading.\n\n## Prerequisites\n\n- A free `SENTISENSE_API_KEY`. Get one at https://app.sentisense.ai/get-api-key. The key is required on every call; anonymous requests return `401 api_key_required`.\n- Any HTTP client. Plain `curl` works, or Python 3.8+ using only the standard library (`urllib`, `json`); no third-party packages required. On macOS python.org installs can raise `CERTIFICATE_VERIFY_FAILED` (missing CA certs): run the bundled `Install Certificates.command`, use the system `/usr/bin/python3`, or use `curl`.\n- Network access to `https://app.sentisense.ai`.\n- Read-only scope. Every endpoint here is a GET. Nothing this skill does can place a trade, move money, or modify account state.\n\n## Permissions\n\n- Network: HTTPS to app.sentisense.ai only.\n- Credentials: SENTISENSE_API_KEY from the environment.\n- Shell: none required.\n- Files: none.\n\n| Tier | Request quota | Rate | Options data |\n|------|---------------|------|--------------|\n| Free | 1,000 requests/month | 30 requests/min | Radar: top 25 rows plus every market-pulse aggregate. Per-stock dossier: full detail for the first 10 calls each calendar month, then a headline-only preview. History: `1y` window. |\n| PRO ($15/mo) | Unlimited | 300 requests/min | Full radar board, unlimited full dossiers, and up to `5y` history. |\n\nThe free tier exercises every workflow below on real data. Uncovered tickers that return `data: null` never spend the monthly dossier meter.\n\n## How to Run\n\nIssue HTTP GET requests to `https://app.sentisense.ai` and synthesize the JSON into a concise, sourced answer. Authenticate every request with the `X-SentiSense-API-Key` header; keep the key in the shell environment and never place it in a query string or in user-facing output.\n\nEvery endpoint returns the wrapped envelope `{ isPreview, previewReason, data }`. When `isPreview` is `true` (`previewReason: \"PRO_REQUIRED\"`), say so (\"showing the free preview slice\"). Null-valued fields are omitted from the JSON entirely, so check for field presence rather than comparing against `null`. Two distinct `429` responses exist: a per-minute `rate_limit_exceeded` includes a `Retry-After: 60` header, so wait that long before retrying; a monthly `quota_exceeded` carries no `Retry-After` header and does not clear until the next calendar month, so stop calling rather than retrying.\n\n```python\nimport os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])\n```\n\nThe REST recipe in this file is the primary path. A maintained command-line client is available as the separate `sentisense-cli` skill for hosts that prefer one.\n\n**Company and fund names are not tickers.** When the user names the company or the fund (\"unusual activity in tesla\", \"skew on the S&P 500 ETF\") instead of typing a symbol, resolve it first: `GET /api/v1/kb/entities/search?q={name}&type=company&limit=5`, or `type=etf` for a fund (`SPY` resolves only under `etf`, never under `company`). The response is a bare array of `{name, urlSlug, type, ticker}`, best match first; take the first match with a non-null `ticker` (a tracked subsidiary can outrank its listed parent: \"google\" returns Google LLC with `ticker: null` before Alphabet `GOOGL`), ask a one-line clarification when several plausible matches carry tickers, and say so when the array is empty. Never uppercase the name into a symbol: `/stocks/TESLA/options/summary` answers `200` with `data: null`, which reads like an uncovered name when the real failure was the identifier. An exact ticker the user typed skips this step.\n\n## Endpoints\n\n- **`GET /api/v1/options/overview`** : the market-wide radar, one row per covered stock in `rows` plus the ETF board in `etfRows` (same row shape, omitted when a build has none), plus a few market-pulse aggregates (`asOf`, `medianIvRank`, `marketPcVol`, `extremeCount`, `coverageCount`). Rows arrive ranked by `interestScore` descending, so the top of the list is the most interesting names today; building-baseline rows sort last. Free keys receive the top 25 rows plus `totalCount`; PRO keys receive every row. Every row carries `ticker`, `name`, `sector`, `asOf`, `atmIv`, `skew25d`, `notionalVol`, `observations1y`, `unusualCount` and the expected-move set (`expectedMove1d`/`5d`/`20d` and their `1s` variants). **The rest are sparse, and the sparse ones are exactly the fields worth sorting on**, because a row only carries them when that reading exists for the ticker: on a full board of 1,028 rows measured 2026-09-05, `ivMove20` appeared on 1,020, `pcVol` on 950, `ivRank1y` and `skewPctl1y` on 943, `interestScore` on 870, `sentiment` and `pcVolPctl1y` on 865, `maxVolOiRatio` and `maxUnusualPremium` on **189**, and `wallSide` / `wallStrike` / `wallShare` on **31**. Since null-valued fields are omitted from the JSON entirely, a re-sort of the board by premium or by wall is ranking the 18% and the 3% of rows that have one, not the board. Treat an absent field as \"no reading for this ticker\", never as a zero or a low value: say how many rows carried it when you rank on one, and do not describe a wall board of 31 names as the market's heaviest walls.\n- **`GET /api/v1/stocks/{ticker}/options/summary`** : the latest dossier for one stock. `data` is `null` for uncovered or unknown tickers (which never spend the dossier meter), otherwise `{ asOf, sentiment, latest, context, oiWalls, unusual }`. Free keys receive this full dossier for the first 10 calls each calendar month; after that, `data` is a headline-only preview of exactly `{ asOf, sentiment, ivRank1y, atmIv, pcVol, pcVolPctl1y, maxPain }` with `isPreview: true` until the monthly reset. `latest` is today's aggregate (volumes, open interest, `pcVol`/`pcOi`, `vwIv`, `atmIv` plus the `atmIv60`/`atmIv90` term structure, `iv25c`/`iv25p`, `skew25d`, `netDelta`, `notionalVol`, `contracts`). `context` holds `ivRank1y` (a min-max range position, 0-100) plus the percentile readings (`pcVolPctl1y`, `pcVolPctl5y`, `pcOiPctl1y`, `skewPctl1y`) and `observations1y`. `oiWalls` holds `expiry`, `maxPain`, and up to three `callWalls` / `putWalls` `{ strike, oi }` levels. `unusual` is the top 5 contracts by premium, each `{ contract, type, strike, expiry, dte, volume, oi, volOiRatio, premium }`.\n- **`GET /api/v1/stocks/{ticker}/options/history`** : the daily aggregate time series, ascending by date, `{ ticker, window, series }`. Each `series` element has the same shape as `latest`. `window` is `1y` (default), `2y`, or `5y`; `5y` returns all stored history (currently about two years, backfilled from mid-2024). Free keys always receive `1y` regardless of the requested value; the response's `window` field reports what was actually served.\n\n## Workflows\n\n**1. Scan the radar for stretched names**\n\n**Identify your client.** Send a `User-Agent` naming your agent runtime and this skill, for\nexample `OpenClaw/1.4 (unusual-options-activity)` or `ClaudeCode/2.1 (unusual-options-activity)`. Substitute your own runtime and\nversion if neither matches. You can also volunteer what your agent is called by adding an\n`agent/<your-agent-name>` token inside the same parentheses, as in\n`OpenClaw/1.4 (unusual-options-activity; agent/research-desk)`. All of it is optional, and it is what tells\nus this skill has real integrations behind it, so it gets prioritized and you get notice before it\nchanges.\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\"\n```\nRows are pre-ranked by `interestScore`. Lead with the top few by that score, then re-sort client-side for a specific lens: `notionalVol` for \"most active by premium\", `abs(ivMove20)` for \"biggest IV moves\", or `pcVolPctl1y` for the most put-heavy names. Always report the percentile alongside the raw reading, and skip rows where `interestScore` is omitted (baseline still building).\n\n**2. Read one stock's options dossier**\n\n```bash\ncurl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\"\n```\nSummarize\n\nArchive v1.3.1: 3 files, 9342 bytes\n\nFiles: skill-card.md (2609b), SKILL.md (18327b), _meta.json (143b)\n\nArchive v1.3.0: 3 files, 9023 bytes\n\nFiles: skill-card.md (2675b), SKILL.md (17514b), _meta.json (143b)\n\nArchive v1.2.0: 3 files, 8131 bytes\n\nFiles: skill-card.md (2649b), SKILL.md (15471b), _meta.json (143b)\n\nArchive v1.1.0: 3 files, 7880 bytes\n\nFiles: skill-card.md (2690b), SKILL.md (14875b), _meta.json (143b)","readmeExcerpt":"Skill: unusual-options-activity Owner: thesentitrader Summary: Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call rati","codeSnippets":[],"executableExamples":[{"language":"python","snippet":"import os, json, urllib.parse, urllib.request\n\nAPI_ORIGIN = \"https://app.sentisense.ai\"\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\ndef sentisense_api_url(path):\n    url = urllib.parse.urljoin(API_ORIGIN + \"/\", path)\n    parsed = urllib.parse.urlparse(url)\n    if (parsed.scheme != \"https\" or parsed.hostname != \"app.sentisense.ai\"\n            or parsed.netloc != \"app.sentisense.ai\"\n            or parsed.username is not None or parsed.password is not None\n            or parsed.port is not None):\n        raise ValueError(\"API URL must use https://app.sentisense.ai with no credentials or port\")\n    return url\n\ndef get(path):\n    url = sentisense_api_url(path)\n    req = urllib.request.Request(\n        url,\n        headers={\"X-SentiSense-API-Key\": os.environ[\"SENTISENSE_API_KEY\"]},\n    )\n    with urllib.request.build_opener(NoRedirect).open(req) as r:\n        return json.load(r)\n\nboard = get(\"/api/v1/options/overview\")\ndata = board.get(\"data\")  # None before the first nightly build\nrows = (data or {}).get(\"rows\", [])"},{"language":"bash","snippet":"curl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\"},{"language":"bash","snippet":"curl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/options/overview\""},{"language":"bash","snippet":"curl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\"},{"language":"bash","snippet":"curl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\\n  \"https://app.sentisense.ai/api/v1/stocks/NVDA/options/summary\""},{"language":"bash","snippet":"curl -s -H \"X-SentiSense-API-Key: $SENTISENSE_API_KEY\" \\"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: unusual-options-activity\ndescription: \"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access.\"\nhomepage: https://sentisense.ai\nrequires:\n  env:\n    - SENTISENSE_API_KEY\nprimaryEnv: SENTISENSE_API_KEY\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - SENTISENSE_API_KEY\n    primaryEnv: SENTISENSE_API_KEY\n    envVars:\n      - name: SENTISENSE_API_KEY\n        required: true\n        description: \"SentiSense API key. Get one free at https://app.sentisense.ai/get-api-key. Used only to authenticate read-only data calls; no write or trading scope.\"\n---\n# Options Radar (SentiSense)\n\nRead the options market for US stocks without pulling and cleaning a full option chain yourself. This skill turns each session's chain into a small set of end-of-day analytics through the read-only SentiSense API, and it ranks every reading against that stock's own trailing history rather than against other stocks. You get a market-wide radar of the most interesting names, and a per-stock dossier covering IV rank, put/call percentile, 25-delta skew, open-interest walls, max pain, and the session's unusually active contracts.\n\nRead-only educational data interface. Output is informational context about how a chain looks today versus its own past, never a personalized buy or sell recommendation, and never a forecast.\n\n## When to Use\n\nReach for this skill when the question is about options positioning or activity on a stock:\n\n- \"Any unusual options activity in $NVDA today?\" (unusually active contracts, ranked by premium)\n- \"Where is implied volatility for this name relative to its own range?\" (IV rank)\n- \"Is the options market leaning puts or calls here?\" (put/call ratio and its percentile)\n- \"What is the downside skew on $TSLA?\" (25-delta put-minus-call skew and its percentile)\n- \"Where are the open-interest walls and max pain?\" (strike structure for the dossier expiry)\n- \"Which stocks have the most stretched options readings right now?\" (the market-wide radar board)\n\nThis skill pairs naturally with `stock-sentiment`, `politicians-stock-tracker`, and `institutional-13f-tracker`: the strongest reads come from convergence. Rich call activity that lines up with climbing sentiment, a congressional buy, and institutional accumulation on the same ticker is a story; any one signal alone is noise.\n\nDo not use it for order entry, portfolio management, greeks-based hedging, or personalized advice. It has no write, trading, or wallet surface; every endpoint is a GET.\n\n## What this data actually is (read before"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn71ca3nrt3w6w0v3nhv3c4tan82x1ym\",\n  \"slug\": \"unusual-options-activity\",\n  \"version\": \"1.5.3\",\n  \"publishedAt\": 1790880558271\n}"},{"path":"skill-card.md","content":"## Description:\n\nProvides read-only, historical-context options analytics for US stocks and ETFs, including unusual activity, implied volatility, put/call ratios, skew, and open-interest levels.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[thesentitrader](https://clawhub.ai/user/thesentitrader)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nInvestors, analysts, and developers use this skill to compare options activity and positioning against a ticker's own history. It provides informational market context, not trading advice or order execution.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill requires a SentiSense API key and sends requested ticker or company/fund searches to SentiSense.\n\nMitigation: Provide a key only if comfortable with this access and sharing those searches; keep the key private.\n\nRisk: Options analytics may be mistaken for real-time flow or investment advice.\n\nMitigation: Check the session timestamp and any intraday delay, and use the results as informational context rather than trading advice.\n\nRisk: Free-tier quotas and paid-tier behavior may affect access or cost.\n\nMitigation: Review the applicable quota and any upgrade terms before relying on additional requests or a paid tier.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/thesentitrader/skills/unusual-options-activity)\n- [SentiSense](https://sentisense.ai)\n- [SentiSense API key](https://app.sentisense.ai/get-api-key)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Analysis, Guidance]\n\n**Output Format:** [Markdown]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [End-of-day readings include the session date; intraday counts, when available, are delayed and separately timestamped.]\n\n## Skill Version(s):\n\n1.5.3 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call ratio, max pain, open-interest walls, spotting where options positioning is stretched for a ticker. Read-only. No trading, no purchases, no write operations, no wallet access. Skill: unusual-options-activity Owner: thesentitrader Summary: Unusual options activity radar for US stocks and ETFs: end-of-day IV rank, implied volatility, options sentiment, put/call percentile, 25-delta skew, open-interest walls, and max pain, each ranked against the ticker's own trailing history. Use for unusual options activity, options flow scanner, IV rank, implied volatility, options sentiment, put/call rati","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1442,"uniquenessScore":45,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T05:46:28.456Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:41:42.080Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}