sentisense 0.63.1 → 0.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,8 +79,8 @@ npx -y sentisense@latest health
79
79
  | `congress [ticker]` | Congressional disclosures, market-wide or for one symbol |
80
80
  | `news [ticker]` | Clustered news stories with impact and tone |
81
81
  | `flows [ticker]` | Institutional 13F flows, or one ticker's holders and notable changes |
82
- | `options <ticker>` | End-of-day options positioning, IV rank, walls, unusual contracts |
83
- | `screen --filter ...` | Screen the universe on Score, analyst, technical, and price fields |
82
+ | `options <ticker>` | End-of-day options positioning, IV rank, walls, unusual contracts; `--intraday` for the session's 15-minute series (PRO) |
83
+ | `screen --filter ...` | Screen the universe on Score, analyst, technical, price, and end-of-day options fields |
84
84
  | `search <name>` | Resolve a name, alias, ticker or slug to a symbol and the entity handle |
85
85
 
86
86
  Run `sentisense help <command>` for its flags and examples.
@@ -183,9 +183,9 @@ Affected: every method whose declared return type is `PreviewResponse<T>`. A tes
183
183
  | `institutional` | `getFlows` `getHolders` `getActivists` |
184
184
  | `options` | `getOverview` |
185
185
  | `politicians` | `getActivity` `getFilings` `getMembers` `getMember` |
186
- | `stocks` | `getSentiment` `getKpis` `getOptionsSummary` `getOptionsHistory` |
186
+ | `stocks` | `getSentiment` `getKpis` `getOptionsSummary` `getOptionsHistory` `getOptionsIntradayHistory` |
187
187
 
188
- The envelope itself is always an object, so test the payload rather than the response. Two of these declare a `data` that can be null: `stocks.getOptionsSummary`, for a ticker outside the covered options universe, and `options.getOverview`, before its first nightly build. Everywhere else `data` is an array or an object.
188
+ The envelope itself is always an object, so test the payload rather than the response. Three of these declare a `data` that can be null: `stocks.getOptionsSummary`, for a ticker outside the covered options universe, `options.getOverview`, before its first nightly build, and `stocks.getOptionsIntradayHistory`, on a FREE key's `PRO_REQUIRED` preview. Everywhere else `data` is an array or an object.
189
189
 
190
190
  ```typescript
191
191
  const flows = await client.institutional.getFlows();
@@ -244,6 +244,7 @@ client.stocks.getFloat("GME") // Free float
244
244
  client.stocks.getGraph("AAPL", { depth: 1 }) // Company knowledge graph: people, products, peers
245
245
  client.stocks.getOptionsSummary("NVDA") // End-of-day options dossier
246
246
  client.stocks.getOptionsHistory("NVDA", { window: "2y" }) // Daily options aggregates over time
247
+ client.stocks.getOptionsIntradayHistory("NVDA") // One session's intraday options series (PRO)
247
248
  client.stocks.getRating("AAPL") // SentiSense Rating: score, letter, percentile, dimensions
248
249
  client.stocks.getAISummary("AAPL", { depth: "deep" }) // AI report (PRO)
249
250
  ```
@@ -521,11 +522,29 @@ End-of-day options positioning: where implied volatility, put/call flow and skew
521
522
  client.options.getOverview() // Market-wide radar, ranked
522
523
  client.stocks.getOptionsSummary("NVDA") // One name's full dossier
523
524
  client.stocks.getOptionsHistory("NVDA", { window: "2y" }) // That name's daily series
525
+ client.stocks.getOptionsIntradayHistory("NVDA", { session: "2026-10-14" }) // Every 15-minute cycle of one session (PRO)
524
526
  ```
525
527
 
526
528
  The radar carries two separately-ranked boards: `data.rows` for stocks and `data.etfRows` for ETFs. Keep them apart. Every reading behind a row's `interestScore` is a percentile of that ticker's own trailing history, so a ranking built across both boards compares numbers measured against different baselines. The aggregates split the same way, with the `etf`-prefixed fields describing the ETF board alone.
527
529
 
528
- During the trading session the dossier and the radar also carry a few intraday fields, the same on every tier: `intradayFlow` (a count of the ticker's unusual contracts so far, when the first one was flagged, and the board's own clock), `largePrintCount` and `largestPrintPctl` on the dossier, and `intradayActiveCount` with `intradayRanking` on the radar. They carry no contract, strike, price or premium, and are absent before the day's first board. `capabilities.intradayBoard` says where the contract-level board lives; its rows are served in the SentiSense app, not by the API.
530
+ During the trading session the dossier and the radar also carry a few intraday fields, the same on every tier: `intradayFlow` (a count of the ticker's unusual contracts so far, when the first one was flagged, and the board's own clock), `largePrintCount` and `largestPrintPctl` on the dossier, and `intradayActiveCount` with `intradayRanking` on the radar. They carry no contract, strike, price or premium, and are absent before the day's first board. On the radar, `intradayAsOf` (epoch seconds) and `intradayAsOfEt` date the board the ranking was read from. `capabilities.intradayBoard` says where the contract-level board lives; its rows are served in the SentiSense app, not by the API.
531
+
532
+ `getOptionsIntradayHistory` keeps every cycle of that board for one ticker, so you can test an intraday signal against what the board showed at each point in the day and then compare it with the session's end-of-day row from `getOptionsHistory`:
533
+
534
+ ```typescript
535
+ const day = await client.stocks.getOptionsIntradayHistory("NVDA", { session: "2026-10-14" });
536
+ if (day.data === null) {
537
+ console.log(day.upgrade?.message); // PRO only: a FREE key gets a preview with no series
538
+ } else {
539
+ for (const point of day.data.series) { // oldest cycle first
540
+ console.log(point.asOfEt, point.callVol, point.putVol, point.pcVol, point.unusualCount, point.atmIv);
541
+ }
542
+ }
543
+ ```
544
+
545
+ Each point carries call and put volume so far, the put/call ratio, the unusual-contract count, the percentile of the largest qualifying contract against the ticker's own year (`maxPremiumPctl1y`) and the ATM implied volatility; readings that are unavailable are absent, never zero. Omit `session` for the session the board ran most recently, and read `data.session` for the date served. A ticker appears only on cycles where it was on the board, so gaps show in each point's `cycle`, and `missingCycles` lists cycles whose stored point could not be read. A weekend, a holiday, a ticker outside the board and an unknown symbol all return an empty `series`, not a null payload. A malformed or future date rejects with an `APIError` whose `code` is `"invalid_session"`. From the CLI: `sentisense options NVDA --intraday`, or `--session YYYY-MM-DD` for another day.
546
+
547
+ A FREE key that has spent its ten monthly dossiers receives a headline preview from `getOptionsSummary`: `asOf`, `sentiment` and six flat readings, `ivRank1y`, `atmIv`, `expectedMove1d`, `pcVol`, `pcVolPctl1y` and `maxPain`, with no `latest`, `context` or `oiWalls`. On a full dossier those six are absent and the same readings live in the nested objects, so branch on `isPreview`.
529
548
 
530
549
  A row whose baseline is still building carries its raw readings with the percentiles and `interestScore` omitted, which means "not enough history yet" rather than "nothing interesting". `getOptionsSummary` reports an uncovered ticker as a null payload inside the usual envelope, so the check is `result.data === null`: the response object itself is always truthy, and a bare `if (summary === null)` never fires. `getOptionsHistory` reports it as an empty `series` instead, so check the array's length rather than null-checking there.
531
550
 
@@ -578,7 +597,7 @@ An empty array is the normal answer for a query that matches nothing, so branch
578
597
 
579
598
  ### Screener
580
599
 
581
- Filter the tracked universe on the SentiSense Score, attention, analyst consensus, technicals and price in one query. Screening on analyst ratings alone is something a dozen free tools do; screening on analyst ratings *where the Score disagrees* is not.
600
+ Filter the tracked universe on the SentiSense Score, attention, analyst consensus, technicals, price and end-of-day options readings in one query. Screening on analyst ratings alone is something a dozen free tools do; screening on analyst ratings *where the Score disagrees* is not.
582
601
 
583
602
  ```typescript
584
603
  client.screener.fields() // Every filterable field, both universes, with units + operators
@@ -609,6 +628,18 @@ const res = await client.screener.run({
609
628
  for (const row of res.results) {
610
629
  console.log(row.ticker, row.sentiSenseScore7D, row.analystBuyRatioPct);
611
630
  }
631
+
632
+ // Options positioning: implied volatility in the top quarter of its own year
633
+ const highIv = await client.screener.run({
634
+ plan: {
635
+ filters: [{ fieldName: "IV_RANK_1Y", op: "GTE", value: 75 }],
636
+ sort: { fieldName: "IV_RANK_1Y", dir: "DESC" },
637
+ },
638
+ limit: 25,
639
+ });
640
+ for (const row of highIv.results) {
641
+ console.log(row.ticker, row.ivRank1y, row.expectedMove20d, row.optionsAsOf);
642
+ }
612
643
  ```
613
644
 
614
645
  `limit` rides next to the plan rather than inside it, because a plan is a stored object and paging is a transport concern. It defaults to 100 and caps at 500. `matched` is the count before `limit` was applied, so truncation is visible. `tickers` is optional: omit it to screen the whole tracked universe, pass a list to screen a watchlist.
@@ -623,7 +654,11 @@ The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are the
623
654
 
624
655
  On the ETF side, `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted Score across what the fund owns and is usually the one you want; `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself. `WEIGHT_COVERED_PCT` tells you how much of the fund's weight had constituent data behind the weighted number.
625
656
 
626
- Screens read a snapshot that refreshes every 20 minutes, so this is not a quote feed. Use `client.stocks.getQuote()` for current quotes.
657
+ Stock rows also carry seven end-of-day options readings, `ivRank1y`, `pcVol`, `pcVolPctl1y`, `skew25dPctl1y`, `optionsInterestScore`, `maxUnusualPremium` and `expectedMove20d`, plus `optionsAsOf`, the session date they are from. `expectedMove20d` is a fraction of price (`0.2` is 20%) and `optionsAsOf` is a `YYYY-MM-DD` date; filter on the options fields with names like `IV_RANK_1Y`.
658
+
659
+ Every stock row carries `priceAsOf`, when the market data behind `currentPrice`, `change` and `changePercent` is from, in epoch milliseconds (the same unit as the quote endpoints). It is `null` outside regular hours, on a previous-close fallback and when no quote was available, so read `null` as unknown rather than fresh, and judge a price's age from `priceAsOf`, not `lastUpdated`. Rated stocks also carry `ratingLetter`, `ratingScore` and `ratingPercentile`; all three are `null` for an unrated one.
660
+
661
+ Prices are 15-minute delayed quotes, refreshed at request time during the regular session from a cache at most 5 minutes old. Everything else on a row comes from a snapshot rebuilt about every 20 minutes during the session, so this is not a quote feed: use `client.stocks.getQuote()` for one ticker's current quote.
627
662
 
628
663
  ## Error handling
629
664
 
package/dist/cli.cjs CHANGED
@@ -1356,7 +1356,7 @@ var flowsCommand = {
1356
1356
  };
1357
1357
 
1358
1358
  // src/version.ts
1359
- var VERSION = "0.63.1";
1359
+ var VERSION = "0.65.0";
1360
1360
 
1361
1361
  // src/resources/analyst.ts
1362
1362
  var Analyst = class {
@@ -2518,7 +2518,9 @@ var Stocks = class {
2518
2518
  *
2519
2519
  * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first
2520
2520
  * ten calls each calendar month and a headline-only preview after that, with `isPreview`
2521
- * true; calls that return a null `data` never spend that allowance.
2521
+ * true; calls that return a null `data` never spend that allowance. The headline preview has
2522
+ * no nested objects: its readings arrive flat as `data.ivRank1y`, `data.atmIv`,
2523
+ * `data.expectedMove1d`, `data.pcVol`, `data.pcVolPctl1y` and `data.maxPain`.
2522
2524
  */
2523
2525
  async getOptionsSummary(ticker) {
2524
2526
  return this.client.get(
@@ -2548,6 +2550,33 @@ var Stocks = class {
2548
2550
  options
2549
2551
  );
2550
2552
  }
2553
+ /**
2554
+ * Get one stock's or ETF's intraday options series for one session: its numbers at every
2555
+ * 15-minute cycle of the intraday board, oldest cycle first.
2556
+ *
2557
+ * Use it to test an intraday signal against what the board actually showed at each point in
2558
+ * the day, then compare it with the session's end-of-day row from
2559
+ * {@link Stocks.getOptionsHistory}. Each point carries call and put volume so far, the
2560
+ * put/call ratio, the unusual-contract count, the percentile of the largest qualifying
2561
+ * contract against the ticker's own year, and the ATM implied volatility. It never carries a
2562
+ * contract symbol, strike, price, premium, open interest or print size.
2563
+ *
2564
+ * **PRO only.** A FREE key receives the standard preview: `isPreview` true, `previewReason`
2565
+ * `"PRO_REQUIRED"`, an `upgrade` hint, and `data: null`.
2566
+ *
2567
+ * **No data is an empty `series`, not a null payload.** A weekend, a holiday, a session from
2568
+ * before the history was kept, a ticker outside the board and an unknown symbol all answer
2569
+ * with `data.series` empty. `data.missingCycles` lists cycles whose stored point could not be
2570
+ * read, which are unknown rather than absent. A malformed or future `session` rejects with
2571
+ * an `APIError` (status 400, code `invalid_session`). A 503 means the stored series could
2572
+ * not be read; it is retried like any other 503 and never answered with a partial series.
2573
+ */
2574
+ async getOptionsIntradayHistory(ticker, options) {
2575
+ return this.client.get(
2576
+ `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/intraday-history`,
2577
+ options
2578
+ );
2579
+ }
2551
2580
  /**
2552
2581
  * Get the SentiSense Rating for one stock: where it ranks against the other stocks rated
2553
2582
  * that day, and the six dimensions the rank is blended from.
@@ -3584,6 +3613,7 @@ var newsCommand = {
3584
3613
  };
3585
3614
 
3586
3615
  // src/cli/commands/options.ts
3616
+ var SESSION_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
3587
3617
  function contractTone(type) {
3588
3618
  const side = type?.toUpperCase();
3589
3619
  if (side === "CALL") return "up";
@@ -3594,14 +3624,79 @@ function walls(rows) {
3594
3624
  if (!rows || rows.length === 0) return "n/a";
3595
3625
  return rows.map((wall) => `${fixed(wall.strike, 0)} (${humanize(wall.oi, 1)})`).join(" ");
3596
3626
  }
3627
+ async function intraday(api, ticker, session) {
3628
+ const envelope = await api.stocks.getOptionsIntradayHistory(ticker, { session });
3629
+ const data = envelope.data;
3630
+ if (envelope.isPreview && !data) {
3631
+ const lines = [
3632
+ { kind: "text", text: `Intraday options history for ${ticker} needs a PRO key.` }
3633
+ ];
3634
+ if (envelope.upgrade?.url) {
3635
+ lines.push({ kind: "text", text: envelope.upgrade.url, tone: "dim" });
3636
+ }
3637
+ return { json: envelope, doc: doc(...lines) };
3638
+ }
3639
+ const series = data?.series ?? [];
3640
+ const served = data?.session ?? session ?? "the latest session";
3641
+ if (series.length === 0) {
3642
+ const note = await verifyTickerOnEmpty(api, ticker);
3643
+ return {
3644
+ json: envelope,
3645
+ doc: doc({ kind: "text", text: `No intraday options history for ${ticker} on ${served}.` }),
3646
+ notes: note ? [note] : void 0
3647
+ };
3648
+ }
3649
+ const blocks = [
3650
+ {
3651
+ kind: "head",
3652
+ title: field("ticker", ticker),
3653
+ right: fields(
3654
+ field("session", served),
3655
+ field("board", data?.live ? "live" : "closed", data?.live ? "accent" : void 0),
3656
+ field("cycles", String(data?.cycles ?? series.length))
3657
+ )
3658
+ },
3659
+ {
3660
+ kind: "table",
3661
+ head: ["CYCLE", "TIME", "CALL VOL", "PUT VOL", "P/C", "UNUSUAL", "PCTL 1Y", "ATM IV"],
3662
+ align: ["right", "left", "right", "right", "right", "right", "right", "right"],
3663
+ rows: series.map((point) => [
3664
+ cell(String(point.cycle)),
3665
+ cell(point.asOfEt ?? ""),
3666
+ cell(humanize(point.callVol, 1)),
3667
+ cell(humanize(point.putVol, 1)),
3668
+ cell(fixed(point.pcVol, 2)),
3669
+ cell(String(point.unusualCount ?? 0)),
3670
+ cell(fixed(point.maxPremiumPctl1y, 1)),
3671
+ cell(fixed(point.atmIv, 4))
3672
+ ])
3673
+ }
3674
+ ];
3675
+ const missing = data?.missingCycles ?? [];
3676
+ if (missing.length > 0) {
3677
+ blocks.push({
3678
+ kind: "text",
3679
+ text: `${missing.length === 1 ? "Cycle" : "Cycles"} ${missing.join(", ")} ${missing.length === 1 ? "was" : "were"} published but could not be read, so ${ticker}'s numbers there are unknown.`,
3680
+ tone: "dim"
3681
+ });
3682
+ }
3683
+ blocks.push({
3684
+ kind: "text",
3685
+ text: `Volumes are cumulative for the session, from chains delayed ${data?.delayMinutes ?? 15} minutes.`,
3686
+ tone: "dim"
3687
+ });
3688
+ return { json: envelope, doc: doc(...blocks) };
3689
+ }
3597
3690
  var optionsCommand = {
3598
3691
  name: "options",
3599
3692
  summary: "End-of-day options positioning for one stock or ETF",
3600
- usage: "sentisense options <ticker>",
3693
+ usage: "sentisense options <ticker> [--intraday] [--session YYYY-MM-DD]",
3601
3694
  examples: [
3602
3695
  "sentisense options NVDA",
3603
3696
  "sentisense options SPY --full",
3604
- "sentisense options NVDA --json"
3697
+ "sentisense options NVDA --json",
3698
+ "sentisense options NVDA --intraday",
3699
+ "sentisense options SPY --session 2026-10-14"
3605
3700
  ],
3606
3701
  notes: [
3607
3702
  "End of day, not live: readings describe the latest completed session and refresh the",
@@ -3612,11 +3707,28 @@ var optionsCommand = {
3612
3707
  EMPTY_VERIFY_NOTE,
3613
3708
  EMPTY_VERIFY_NOTE_2,
3614
3709
  "A free key gets the full dossier for the first ten calls each month, then a headline",
3615
- "preview. Calls that return no dossier do not count against that."
3710
+ "preview. Calls that return no dossier do not count against that.",
3711
+ "--intraday shows one session's intraday series instead: the ticker's volumes, put/call",
3712
+ "ratio, unusual-contract count and ATM IV at every 15-minute cycle (PRO keys only).",
3713
+ "--session picks the session and implies --intraday; omitted, the latest one."
3616
3714
  ],
3617
- flags: {},
3715
+ flags: {
3716
+ intraday: { type: "boolean", describe: "Show the session's intraday series, every 15-minute cycle (PRO)" },
3717
+ session: {
3718
+ type: "string",
3719
+ placeholder: "YYYY-MM-DD",
3720
+ describe: "Session for the intraday series (default: the latest)"
3721
+ }
3722
+ },
3618
3723
  async run({ args, client, full }) {
3619
3724
  const ticker = oneTicker(args, "options");
3725
+ const session = typeof args.flags.session === "string" ? args.flags.session : void 0;
3726
+ if (session !== void 0 && !SESSION_PATTERN.test(session)) {
3727
+ throw new CliUsageError("--session must be a date, YYYY-MM-DD.", "for example: --session 2026-10-14");
3728
+ }
3729
+ if (args.flags.intraday === true || session !== void 0) {
3730
+ return intraday(client(), ticker, session);
3731
+ }
3620
3732
  const api = client();
3621
3733
  const envelope = await api.stocks.getOptionsSummary(ticker);
3622
3734
  const data = envelope.data;
@@ -3630,21 +3742,24 @@ var optionsCommand = {
3630
3742
  }
3631
3743
  const latest = data.latest ?? {};
3632
3744
  const context = data.context ?? {};
3745
+ const ivRank = context.ivRank1y ?? data.ivRank1y;
3746
+ const pcVol = latest.pcVol ?? data.pcVol;
3747
+ const maxPain = data.oiWalls?.maxPain ?? data.maxPain;
3633
3748
  const blocks = [
3634
3749
  {
3635
3750
  kind: "head",
3636
3751
  title: field("ticker", ticker),
3637
3752
  right: fields(
3638
3753
  field("positioning", signed(data.sentiment, 2), direction(data.sentiment)),
3639
- field("iv rank 1y", fixed(context.ivRank1y, 1)),
3640
- field("put/call vol", fixed(latest.pcVol, 2))
3754
+ field("iv rank 1y", fixed(ivRank, 1)),
3755
+ field("put/call vol", fixed(pcVol, 2))
3641
3756
  )
3642
3757
  },
3643
3758
  {
3644
3759
  kind: "facts",
3645
3760
  items: fields(
3646
- field("ATM IV", fixed(latest.atmIv, 4)),
3647
- field("Exp move 1d", fixed(latest.expectedMove1d, 4)),
3761
+ field("ATM IV", fixed(latest.atmIv ?? data.atmIv, 4)),
3762
+ field("Exp move 1d", fixed(latest.expectedMove1d ?? data.expectedMove1d, 4)),
3648
3763
  field("Skew 25d", signed(latest.skew25d, 4)),
3649
3764
  field("Call vol", humanize(latest.callVol, 1)),
3650
3765
  field("Put vol", humanize(latest.putVol, 1)),
@@ -3654,7 +3769,7 @@ var optionsCommand = {
3654
3769
  {
3655
3770
  kind: "facts",
3656
3771
  items: fields(
3657
- field("Max pain", fixed(data.oiWalls?.maxPain, 0)),
3772
+ field("Max pain", fixed(maxPain, 0)),
3658
3773
  field("Wall expiry", data.oiWalls?.expiry ?? "n/a"),
3659
3774
  field("Call OI", humanize(latest.callOi, 1)),
3660
3775
  field("Put OI", humanize(latest.putOi, 1)),
@@ -3676,7 +3791,7 @@ var optionsCommand = {
3676
3791
  field("term structure", `60d ${fixed(latest.atmIv60, 4)} 90d ${fixed(latest.atmIv90, 4)}`),
3677
3792
  field("net delta", humanize(latest.netDelta, 1)),
3678
3793
  field("put/call OI", fixed(latest.pcOi, 2)),
3679
- field("pc vol percentile 1y", fixed(context.pcVolPctl1y, 1)),
3794
+ field("pc vol percentile 1y", fixed(context.pcVolPctl1y ?? data.pcVolPctl1y, 1)),
3680
3795
  field("skew percentile 1y", fixed(context.skewPctl1y, 1)),
3681
3796
  field("observations 1y", fixed(context.observations1y, 0))
3682
3797
  )
@@ -3947,7 +4062,7 @@ function parseSort(raw) {
3947
4062
  }
3948
4063
  var screenCommand = {
3949
4064
  name: "screen",
3950
- summary: "Filter the tracked universe on Score, analyst, technical, and price fields",
4065
+ summary: "Filter the tracked universe on Score, analyst, technical, price, and end-of-day options fields",
3951
4066
  usage: "sentisense screen [--filter FIELD:OP:VALUE]... [--sort FIELD:DIR] [--limit N]",
3952
4067
  examples: [
3953
4068
  "sentisense screen --list",
package/dist/index.cjs CHANGED
@@ -1242,7 +1242,9 @@ var Stocks = class {
1242
1242
  *
1243
1243
  * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first
1244
1244
  * ten calls each calendar month and a headline-only preview after that, with `isPreview`
1245
- * true; calls that return a null `data` never spend that allowance.
1245
+ * true; calls that return a null `data` never spend that allowance. The headline preview has
1246
+ * no nested objects: its readings arrive flat as `data.ivRank1y`, `data.atmIv`,
1247
+ * `data.expectedMove1d`, `data.pcVol`, `data.pcVolPctl1y` and `data.maxPain`.
1246
1248
  */
1247
1249
  async getOptionsSummary(ticker) {
1248
1250
  return this.client.get(
@@ -1272,6 +1274,33 @@ var Stocks = class {
1272
1274
  options
1273
1275
  );
1274
1276
  }
1277
+ /**
1278
+ * Get one stock's or ETF's intraday options series for one session: its numbers at every
1279
+ * 15-minute cycle of the intraday board, oldest cycle first.
1280
+ *
1281
+ * Use it to test an intraday signal against what the board actually showed at each point in
1282
+ * the day, then compare it with the session's end-of-day row from
1283
+ * {@link Stocks.getOptionsHistory}. Each point carries call and put volume so far, the
1284
+ * put/call ratio, the unusual-contract count, the percentile of the largest qualifying
1285
+ * contract against the ticker's own year, and the ATM implied volatility. It never carries a
1286
+ * contract symbol, strike, price, premium, open interest or print size.
1287
+ *
1288
+ * **PRO only.** A FREE key receives the standard preview: `isPreview` true, `previewReason`
1289
+ * `"PRO_REQUIRED"`, an `upgrade` hint, and `data: null`.
1290
+ *
1291
+ * **No data is an empty `series`, not a null payload.** A weekend, a holiday, a session from
1292
+ * before the history was kept, a ticker outside the board and an unknown symbol all answer
1293
+ * with `data.series` empty. `data.missingCycles` lists cycles whose stored point could not be
1294
+ * read, which are unknown rather than absent. A malformed or future `session` rejects with
1295
+ * an `APIError` (status 400, code `invalid_session`). A 503 means the stored series could
1296
+ * not be read; it is retried like any other 503 and never answered with a partial series.
1297
+ */
1298
+ async getOptionsIntradayHistory(ticker, options) {
1299
+ return this.client.get(
1300
+ `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/intraday-history`,
1301
+ options
1302
+ );
1303
+ }
1275
1304
  /**
1276
1305
  * Get the SentiSense Rating for one stock: where it ranks against the other stocks rated
1277
1306
  * that day, and the six dimensions the rank is blended from.
@@ -1394,7 +1423,7 @@ var Trackers = class {
1394
1423
  };
1395
1424
 
1396
1425
  // src/version.ts
1397
- var VERSION = "0.63.1";
1426
+ var VERSION = "0.65.0";
1398
1427
 
1399
1428
  // src/client.ts
1400
1429
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";