sentisense 0.45.0 → 0.47.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/dist/cli.cjs CHANGED
@@ -1038,7 +1038,7 @@ var flowsCommand = {
1038
1038
  };
1039
1039
 
1040
1040
  // src/version.ts
1041
- var VERSION = "0.45.0";
1041
+ var VERSION = "0.47.0";
1042
1042
 
1043
1043
  // src/resources/analyst.ts
1044
1044
  var Analyst = class {
@@ -1623,6 +1623,39 @@ var MarketSummaryResource = class {
1623
1623
  }
1624
1624
  };
1625
1625
 
1626
+ // src/resources/options.ts
1627
+ var Options = class {
1628
+ constructor(client) {
1629
+ this.client = client;
1630
+ }
1631
+ /**
1632
+ * Get the market-wide options radar: where implied volatility, put/call flow and skew are
1633
+ * unusual today, ranked.
1634
+ *
1635
+ * End of day, not live. `asOf` is the latest completed session and the build refreshes the
1636
+ * following morning, so this is positioning, not a quote feed.
1637
+ *
1638
+ * **The response carries two separately-ranked boards.** `data.rows` is the covered stock
1639
+ * universe and `data.etfRows` is the covered ETF universe. Do not merge them: each row's
1640
+ * readings are percentiles of that ticker's own trailing history, so a rank built across
1641
+ * both boards compares numbers measured against different baselines. The aggregates are
1642
+ * split the same way, with the `etf`-prefixed fields describing the ETF board alone.
1643
+ *
1644
+ * `data` is `null` before the first nightly build populates it, which is a cold-start
1645
+ * state rather than an error.
1646
+ *
1647
+ * Tiering: a PRO key receives every row. A FREE key receives the top 25 stock rows plus
1648
+ * all the aggregates, with `isPreview` true and the envelope's `totalCount` reporting the
1649
+ * full stock board; `data.etfTotalCount` does the same for the ETF board.
1650
+ *
1651
+ * Drill into any row with `client.stocks.getOptionsSummary(ticker)` for its full dossier,
1652
+ * or `client.stocks.getOptionsHistory(ticker)` to chart how a reading has trended.
1653
+ */
1654
+ async getOverview() {
1655
+ return this.client.get("/api/v1/options/overview");
1656
+ }
1657
+ };
1658
+
1626
1659
  // src/resources/screener.ts
1627
1660
  var Screener = class {
1628
1661
  constructor(client) {
@@ -1704,6 +1737,12 @@ var Screener = class {
1704
1737
  };
1705
1738
 
1706
1739
  // src/resources/stocks.ts
1740
+ function withLegacyName(rows) {
1741
+ if (!Array.isArray(rows)) return rows;
1742
+ return rows.map(
1743
+ (row) => row && !row.name ? { ...row, name: row.simpleName || row.companyName || "" } : row
1744
+ );
1745
+ }
1707
1746
  var Stocks = class {
1708
1747
  constructor(client) {
1709
1748
  this.client = client;
@@ -1712,9 +1751,10 @@ var Stocks = class {
1712
1751
  async list() {
1713
1752
  return this.client.get("/api/v1/stocks");
1714
1753
  }
1715
- /** List all stocks with name, kbEntityId, urlSlug. */
1754
+ /** List all stocks with company names, kbEntityId, urlSlug. */
1716
1755
  async listDetailed() {
1717
- return this.client.get("/api/v1/stocks/detailed");
1756
+ const rows = await this.client.get("/api/v1/stocks/detailed");
1757
+ return withLegacyName(rows);
1718
1758
  }
1719
1759
  /** Get popular ticker symbols. */
1720
1760
  async listPopular() {
@@ -1722,7 +1762,8 @@ var Stocks = class {
1722
1762
  }
1723
1763
  /** Get popular stocks with details. */
1724
1764
  async listPopularDetailed() {
1725
- return this.client.get("/api/v1/stocks/popular/detailed");
1765
+ const rows = await this.client.get("/api/v1/stocks/popular/detailed");
1766
+ return withLegacyName(rows);
1726
1767
  }
1727
1768
  /** Get real-time price for a single ticker. */
1728
1769
  async getPrice(ticker) {
@@ -1923,6 +1964,29 @@ var Stocks = class {
1923
1964
  `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`
1924
1965
  );
1925
1966
  }
1967
+ /**
1968
+ * Get the daily options aggregates for one stock or ETF as a time series, oldest first.
1969
+ * Use it to chart how a reading has trended: implied volatility, put/call flow, skew.
1970
+ *
1971
+ * Each element has the same shape as the dossier's `latest` aggregate, so a chart built
1972
+ * off `getOptionsSummary` reads this series without a second mapping.
1973
+ *
1974
+ * **A null payload is not how this one reports no coverage.** Unlike
1975
+ * {@link Stocks.getOptionsSummary}, an uncovered ticker, an unknown symbol and a covered
1976
+ * ticker with nothing stored yet all answer with a populated object whose `series` is
1977
+ * empty. Check the array's length, not the payload.
1978
+ *
1979
+ * The window served is not always the window requested: an unrecognised value clamps to
1980
+ * `"1y"` rather than erroring, and a FREE key always receives `"1y"`. Read `data.window`
1981
+ * for what you actually got. `"5y"` means all stored history, currently a little over two
1982
+ * years, so it can answer with nearly the same series as `"2y"`.
1983
+ */
1984
+ async getOptionsHistory(ticker, options) {
1985
+ return this.client.get(
1986
+ `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/history`,
1987
+ options
1988
+ );
1989
+ }
1926
1990
  };
1927
1991
 
1928
1992
  // src/resources/indexes.ts
@@ -2048,6 +2112,7 @@ var SentiSense = class {
2048
2112
  this.calendar = new Calendar(this);
2049
2113
  this.earnings = new Earnings(this);
2050
2114
  this.screener = new Screener(this);
2115
+ this.options = new Options(this);
2051
2116
  }
2052
2117
  /** @internal */
2053
2118
  async get(path, params) {
@@ -2498,6 +2563,9 @@ var insidersCommand = {
2498
2563
  ],
2499
2564
  notes: [
2500
2565
  "Rows are individual filed transactions, newest first, not a net total.",
2566
+ "The bought/sold figures count open-market rows only. Form 4 code F rows (shares withheld",
2567
+ "to cover taxes on vesting) arrive typed SELL but are mechanical withholding, not a decision",
2568
+ "to sell, so they are excluded from sold and shown separately as withheld.",
2501
2569
  "The plan column says whether the trade was under a confirmed pre-arranged 10b5-1 plan,",
2502
2570
  "which is the difference between a scheduled sale and a discretionary one.",
2503
2571
  "A free key sees the top few transactions; a PRO key sees the window you asked for.",
@@ -2522,18 +2590,22 @@ var insidersCommand = {
2522
2590
  if (note) notes.push(note);
2523
2591
  }
2524
2592
  const shown = full ? trades : trades.slice(0, 15);
2593
+ const isWithholding = (row) => row.transactionCode === "F";
2525
2594
  const buys = trades.filter((trade) => trade.transactionType === "BUY");
2526
- const sells = trades.filter((trade) => trade.transactionType === "SELL");
2595
+ const sells = trades.filter((trade) => trade.transactionType === "SELL" && !isWithholding(trade));
2596
+ const withheld = trades.filter(isWithholding);
2527
2597
  const sum = (rows) => rows.reduce((total, row) => total + (row.totalValue || 0), 0);
2598
+ const headline = [
2599
+ field("trades", String(trades.length)),
2600
+ field("bought", humanize(sum(buys)), buys.length > 0 ? "up" : void 0),
2601
+ field("sold", humanize(sum(sells)), sells.length > 0 ? "down" : void 0)
2602
+ ];
2603
+ if (withheld.length > 0) headline.push(field("withheld", humanize(sum(withheld))));
2528
2604
  const blocks = [
2529
2605
  {
2530
2606
  kind: "head",
2531
2607
  title: field("ticker", ticker),
2532
- right: fields(
2533
- field("trades", String(trades.length)),
2534
- field("bought", humanize(sum(buys)), buys.length > 0 ? "up" : void 0),
2535
- field("sold", humanize(sum(sells)), sells.length > 0 ? "down" : void 0)
2536
- )
2608
+ right: fields(...headline)
2537
2609
  }
2538
2610
  ];
2539
2611
  if (shown.length === 0) {
@@ -2548,8 +2620,8 @@ var insidersCommand = {
2548
2620
  cell(truncate(trade.insiderName, full ? 40 : 22)),
2549
2621
  cell(truncate(trade.insiderTitle ?? "", full ? 40 : 18)),
2550
2622
  cell(
2551
- trade.transactionType,
2552
- trade.transactionType === "BUY" ? "up" : trade.transactionType === "SELL" ? "down" : void 0
2623
+ isWithholding(trade) ? "TAX-W" : trade.transactionType,
2624
+ !isWithholding(trade) && trade.transactionType === "BUY" ? "up" : !isWithholding(trade) && trade.transactionType === "SELL" ? "down" : void 0
2553
2625
  ),
2554
2626
  cell(humanize(trade.sharesTransacted, 1)),
2555
2627
  cell(humanize(trade.totalValue)),
package/dist/index.cjs CHANGED
@@ -657,6 +657,39 @@ var MarketSummaryResource = class {
657
657
  }
658
658
  };
659
659
 
660
+ // src/resources/options.ts
661
+ var Options = class {
662
+ constructor(client) {
663
+ this.client = client;
664
+ }
665
+ /**
666
+ * Get the market-wide options radar: where implied volatility, put/call flow and skew are
667
+ * unusual today, ranked.
668
+ *
669
+ * End of day, not live. `asOf` is the latest completed session and the build refreshes the
670
+ * following morning, so this is positioning, not a quote feed.
671
+ *
672
+ * **The response carries two separately-ranked boards.** `data.rows` is the covered stock
673
+ * universe and `data.etfRows` is the covered ETF universe. Do not merge them: each row's
674
+ * readings are percentiles of that ticker's own trailing history, so a rank built across
675
+ * both boards compares numbers measured against different baselines. The aggregates are
676
+ * split the same way, with the `etf`-prefixed fields describing the ETF board alone.
677
+ *
678
+ * `data` is `null` before the first nightly build populates it, which is a cold-start
679
+ * state rather than an error.
680
+ *
681
+ * Tiering: a PRO key receives every row. A FREE key receives the top 25 stock rows plus
682
+ * all the aggregates, with `isPreview` true and the envelope's `totalCount` reporting the
683
+ * full stock board; `data.etfTotalCount` does the same for the ETF board.
684
+ *
685
+ * Drill into any row with `client.stocks.getOptionsSummary(ticker)` for its full dossier,
686
+ * or `client.stocks.getOptionsHistory(ticker)` to chart how a reading has trended.
687
+ */
688
+ async getOverview() {
689
+ return this.client.get("/api/v1/options/overview");
690
+ }
691
+ };
692
+
660
693
  // src/resources/screener.ts
661
694
  var Screener = class {
662
695
  constructor(client) {
@@ -738,6 +771,12 @@ var Screener = class {
738
771
  };
739
772
 
740
773
  // src/resources/stocks.ts
774
+ function withLegacyName(rows) {
775
+ if (!Array.isArray(rows)) return rows;
776
+ return rows.map(
777
+ (row) => row && !row.name ? { ...row, name: row.simpleName || row.companyName || "" } : row
778
+ );
779
+ }
741
780
  var Stocks = class {
742
781
  constructor(client) {
743
782
  this.client = client;
@@ -746,9 +785,10 @@ var Stocks = class {
746
785
  async list() {
747
786
  return this.client.get("/api/v1/stocks");
748
787
  }
749
- /** List all stocks with name, kbEntityId, urlSlug. */
788
+ /** List all stocks with company names, kbEntityId, urlSlug. */
750
789
  async listDetailed() {
751
- return this.client.get("/api/v1/stocks/detailed");
790
+ const rows = await this.client.get("/api/v1/stocks/detailed");
791
+ return withLegacyName(rows);
752
792
  }
753
793
  /** Get popular ticker symbols. */
754
794
  async listPopular() {
@@ -756,7 +796,8 @@ var Stocks = class {
756
796
  }
757
797
  /** Get popular stocks with details. */
758
798
  async listPopularDetailed() {
759
- return this.client.get("/api/v1/stocks/popular/detailed");
799
+ const rows = await this.client.get("/api/v1/stocks/popular/detailed");
800
+ return withLegacyName(rows);
760
801
  }
761
802
  /** Get real-time price for a single ticker. */
762
803
  async getPrice(ticker) {
@@ -957,6 +998,29 @@ var Stocks = class {
957
998
  `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`
958
999
  );
959
1000
  }
1001
+ /**
1002
+ * Get the daily options aggregates for one stock or ETF as a time series, oldest first.
1003
+ * Use it to chart how a reading has trended: implied volatility, put/call flow, skew.
1004
+ *
1005
+ * Each element has the same shape as the dossier's `latest` aggregate, so a chart built
1006
+ * off `getOptionsSummary` reads this series without a second mapping.
1007
+ *
1008
+ * **A null payload is not how this one reports no coverage.** Unlike
1009
+ * {@link Stocks.getOptionsSummary}, an uncovered ticker, an unknown symbol and a covered
1010
+ * ticker with nothing stored yet all answer with a populated object whose `series` is
1011
+ * empty. Check the array's length, not the payload.
1012
+ *
1013
+ * The window served is not always the window requested: an unrecognised value clamps to
1014
+ * `"1y"` rather than erroring, and a FREE key always receives `"1y"`. Read `data.window`
1015
+ * for what you actually got. `"5y"` means all stored history, currently a little over two
1016
+ * years, so it can answer with nearly the same series as `"2y"`.
1017
+ */
1018
+ async getOptionsHistory(ticker, options) {
1019
+ return this.client.get(
1020
+ `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/history`,
1021
+ options
1022
+ );
1023
+ }
960
1024
  };
961
1025
 
962
1026
  // src/resources/indexes.ts
@@ -1036,7 +1100,7 @@ var Trackers = class {
1036
1100
  };
1037
1101
 
1038
1102
  // src/version.ts
1039
- var VERSION = "0.45.0";
1103
+ var VERSION = "0.47.0";
1040
1104
 
1041
1105
  // src/client.ts
1042
1106
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1085,6 +1149,7 @@ var SentiSense = class {
1085
1149
  this.calendar = new Calendar(this);
1086
1150
  this.earnings = new Earnings(this);
1087
1151
  this.screener = new Screener(this);
1152
+ this.options = new Options(this);
1088
1153
  }
1089
1154
  /** @internal */
1090
1155
  async get(path, params) {