sentisense 0.53.0 → 0.55.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 +26 -6
- package/dist/cli.cjs +103 -6
- package/dist/index.cjs +104 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +424 -9
- package/dist/index.d.ts +424 -9
- package/dist/index.mjs +103 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -170,7 +170,22 @@ Most methods resolve to the payload directly, but two families wrap it. The retu
|
|
|
170
170
|
|
|
171
171
|
**1. Tier-gated endpoints return a preview envelope.** The payload is in `data`, and `isPreview` tells you whether it was truncated for your tier. `totalCount` carries the untruncated size whenever the server knows it: on a truncated response, so you can render "showing N of M", and on a paged endpoint such as `politicians.getActivity`, where it is the full match count on every tier including PRO. A missing `totalCount` means "count `data` yourself", never "zero results".
|
|
172
172
|
|
|
173
|
-
Affected:
|
|
173
|
+
Affected: every method whose declared return type is `PreviewResponse<T>`. A test keeps this table in step with the source, so it is the full list rather than a sample.
|
|
174
|
+
|
|
175
|
+
| Namespace | Methods |
|
|
176
|
+
|-----------|---------|
|
|
177
|
+
| `analyst` | `consensus` `consensusHistory` `calledIt` `actions` `estimates` `marketActivity` `coverage` `profile` `calls` |
|
|
178
|
+
| `calendar` | `getEarnings` |
|
|
179
|
+
| `earnings` | `getSummaries` `getRecent` `getStatistics` `getRanked` |
|
|
180
|
+
| `etfs` | `analystAggregate` `insiderAggregate` `sentimentAggregate` |
|
|
181
|
+
| `insider` | `getActivity` `getTrades` `getClusterBuys` |
|
|
182
|
+
| `insights` | `stock` `stockRange` `market` `latest` `user` |
|
|
183
|
+
| `institutional` | `getFlows` `getHolders` `getActivists` |
|
|
184
|
+
| `options` | `getOverview` |
|
|
185
|
+
| `politicians` | `getActivity` `getFilings` `getMembers` `getMember` |
|
|
186
|
+
| `stocks` | `getSentiment` `getKpis` `getOptionsSummary` `getOptionsHistory` |
|
|
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.
|
|
174
189
|
|
|
175
190
|
```typescript
|
|
176
191
|
const flows = await client.institutional.getFlows();
|
|
@@ -349,6 +364,8 @@ The price target cone (mean, high, low, upside %) and consensus are free for eve
|
|
|
349
364
|
|
|
350
365
|
```typescript
|
|
351
366
|
client.analyst.consensus("AAPL") // Price target cone + consensus. Free, full data.
|
|
367
|
+
client.analyst.consensusHistory("AAPL", { limit: 90 }) // Daily history. Free: last 30 days; distribution fields null.
|
|
368
|
+
client.analyst.calledIt("AAPL", { limit: 10 }) // Recorded calls for 20% moves over five sessions. Free: newest move, up to 5 calls, move counts intact.
|
|
352
369
|
client.analyst.actions("AAPL", { lookbackDays: 30 }) // Upgrade/downgrade feed. Free: 3 most recent.
|
|
353
370
|
client.analyst.estimates("AAPL") // Forward EPS + surprises. Free: 1 quarter.
|
|
354
371
|
client.analyst.marketActivity({ lookbackDays: 7 }) // Market-wide analyst actions (PRO).
|
|
@@ -396,11 +413,14 @@ Two shapes to read rather than assume. A firm can appear with `noteCount: 0`, a
|
|
|
396
413
|
|
|
397
414
|
### Earnings
|
|
398
415
|
|
|
399
|
-
The earnings analysis report is the assembled version of a quarter: one object per fiscal period carrying the editorial headline, the KPI cards with year-over-year deltas, the guidance language as management phrased it, and a summary of the earnings call. Pair it with the recent-reporters feed to drive a post-earnings sweep.
|
|
416
|
+
The earnings analysis report is the assembled version of a quarter: one object per fiscal period carrying the editorial headline, the KPI cards with year-over-year deltas, the guidance language as management phrased it, and a summary of the earnings call. Pair it with the recent-reporters feed to drive a post-earnings sweep. Summaries, recent reports, statistics, and rankings return the preview envelope; per-ticker reactions return a direct payload.
|
|
400
417
|
|
|
401
418
|
```typescript
|
|
402
419
|
client.earnings.getSummaries("AAPL", { limit: 4 }) // Per-quarter analysis, newest first. Free: latest quarter, shaped.
|
|
403
420
|
client.earnings.getRecent({ days: 7, limit: 25 }) // Who reported in the last N days. Full window on every key.
|
|
421
|
+
client.earnings.getReactions("AAPL") // Up to twelve measured post-report moves. Full series on every key.
|
|
422
|
+
client.earnings.getStatistics({ window: "week_to_date" }) // Market-wide outcomes, reaction rates, baseline, and coverage.
|
|
423
|
+
client.earnings.getRanked({ reportedDays: 14, upcomingDays: 7 }) // Free: first 3 rows per section. PRO: full ranking.
|
|
404
424
|
```
|
|
405
425
|
|
|
406
426
|
```typescript
|
|
@@ -461,7 +481,7 @@ client.entityMetrics.getDistribution("AAPL", "sentiment")
|
|
|
461
481
|
client.entityMetrics.getDistribution("AAPL", "mentions", { dimension: "source" })
|
|
462
482
|
```
|
|
463
483
|
|
|
464
|
-
Available metric types: `mentions`, `sentiment`, `sentisense_score`, `sentisense_rating`, `social_dominance`, `creators`. `sentisense_rating` is the SentiSense Rating score and is a time series only: it has no source breakdown, so `getDistribution` answers with an empty distribution for it.
|
|
484
|
+
Available metric types: `mentions`, `sentiment`, `sentisense_score`, `sentisense_rating`, `social_dominance`, `creators`. `sentisense` is an alias for `sentisense_score`; either spelling returns the same series, and keys are case-insensitive. Responses always name the canonical type, so a `sentisense` request answers with `SENTISENSE_SCORE`. `sentisense_rating` is the SentiSense Rating score and is a time series only: it has no source breakdown, so `getDistribution` answers with an empty distribution for it.
|
|
465
485
|
|
|
466
486
|
### Options
|
|
467
487
|
|
|
@@ -475,11 +495,11 @@ client.stocks.getOptionsHistory("NVDA", { window: "2y" }) // That name's daily
|
|
|
475
495
|
|
|
476
496
|
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.
|
|
477
497
|
|
|
478
|
-
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`
|
|
498
|
+
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.
|
|
479
499
|
|
|
480
500
|
### SentiSense Rating
|
|
481
501
|
|
|
482
|
-
Where a stock ranks against the other stocks rated that day, as a score, a letter and a percentile, plus the
|
|
502
|
+
Where a stock ranks against the other stocks rated that day, as a score, a letter and a percentile, plus the seven dimensions the rank is blended from. It is a relative research signal for informational and educational purposes, not financial, investment or trading advice, and not a recommendation about any security. Every response carries the wording to display alongside a grade in `disclaimer`. [Methodology](https://sentisense.ai/methodology/#sentisense-rating).
|
|
483
503
|
|
|
484
504
|
```typescript
|
|
485
505
|
const rating = await client.stocks.getRating("AAPL");
|
|
@@ -498,7 +518,7 @@ if (rating.rated) {
|
|
|
498
518
|
|
|
499
519
|
Having no grade is a normal 200, not a 404: ETFs and tickers outside the swept universe answer that way, and `reason` is one of `stale`, `not_rated_today`, `insufficient_dimensions` or `insufficient_coverage_weight`. Only a ticker that resolves to nothing we track rejects with `NotFoundError`.
|
|
500
520
|
|
|
501
|
-
`dimensions` always holds all
|
|
521
|
+
`dimensions` always holds all seven rows in a fixed order, including the ones with no data, which arrive with `present` false and a `null` percentile. Read `present` first and never substitute zero for a missing percentile: zero is the bottom of the cross-section, absence is not a position on it. Only the smart-money dimension carries `subLegs`.
|
|
502
522
|
|
|
503
523
|
**`score` is not `percentile`.** `percentile` is the rank of the blended signals against the day's rated set. `score = percentile - sum(riskAdjustments.map((a) => a.points))`, floored at 10 when fewer than five dimensions are available, and it is the number `letter` bands (A 90, B 70, C 30, D 10). `bucketLetter` is the band the percentile alone would give, so the two letters differ by exactly what the conditions cost. `riskAdjustments` itemises that cost, `penaltyPoints` totals it, and `riskConditions` names the active ones from the `RiskCondition` union: `thin_coverage`, `weak_dimension`, `unprofitable`, `no_fundamentals`, `high_leverage`, `unseasoned_listing`, `small_market_cap`, `thin_liquidity`, `extended_price`, `insider_selling` and `institutional_outflow`.
|
|
504
524
|
|
package/dist/cli.cjs
CHANGED
|
@@ -36,6 +36,13 @@ var RateLimitError = class extends SentiSenseError {
|
|
|
36
36
|
this.retryAfter = retryAfter;
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
|
+
var TemporarilyUnavailableError = class extends SentiSenseError {
|
|
40
|
+
constructor(message, retryAfter, code) {
|
|
41
|
+
super(message, 503, code);
|
|
42
|
+
this.name = "TemporarilyUnavailableError";
|
|
43
|
+
this.retryAfter = retryAfter;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
39
46
|
var APIError = class extends SentiSenseError {
|
|
40
47
|
constructor(message, status, code) {
|
|
41
48
|
super(message, status, code);
|
|
@@ -1324,7 +1331,7 @@ var flowsCommand = {
|
|
|
1324
1331
|
};
|
|
1325
1332
|
|
|
1326
1333
|
// src/version.ts
|
|
1327
|
-
var VERSION = "0.
|
|
1334
|
+
var VERSION = "0.55.0";
|
|
1328
1335
|
|
|
1329
1336
|
// src/resources/analyst.ts
|
|
1330
1337
|
var Analyst = class {
|
|
@@ -1340,6 +1347,38 @@ var Analyst = class {
|
|
|
1340
1347
|
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`
|
|
1341
1348
|
);
|
|
1342
1349
|
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Get daily consensus observations, ordered by `snapshotDate` ascending.
|
|
1352
|
+
* Each row describes the target fields as observed on that date. When
|
|
1353
|
+
* `countsObserved` is `false`, the vendor panel did not come back that day and the
|
|
1354
|
+
* distribution counts are carried forward.
|
|
1355
|
+
*
|
|
1356
|
+
* A PRO key receives the requested window. A FREE key receives the last 30 days;
|
|
1357
|
+
* `targetMedian`, `recommendationMean`, and the five distribution fields are `null`.
|
|
1358
|
+
* The envelope's `totalCount` still sizes the full requested window.
|
|
1359
|
+
*/
|
|
1360
|
+
async consensusHistory(ticker, options) {
|
|
1361
|
+
return this.client.get(
|
|
1362
|
+
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus/history`,
|
|
1363
|
+
options
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Get factual call history as recorded when a stock moved 20% or more over five
|
|
1368
|
+
* sessions, newest move first by `moveEndDate`.
|
|
1369
|
+
*
|
|
1370
|
+
* PRO receives full moves and calls. FREE receives the newest move with up to five
|
|
1371
|
+
* calls and all move-level counts intact. The envelope's `totalCount` counts all
|
|
1372
|
+
* available moves before the limit. A known stock with no qualifying move returns
|
|
1373
|
+
* an empty `moves` array. Each call includes `analystName`: it is `null`, never
|
|
1374
|
+
* absent, when the publisher named nobody.
|
|
1375
|
+
*/
|
|
1376
|
+
async calledIt(ticker, options) {
|
|
1377
|
+
return this.client.get(
|
|
1378
|
+
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/called-it`,
|
|
1379
|
+
options
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1343
1382
|
/**
|
|
1344
1383
|
* Get recent analyst upgrade/downgrade actions for a ticker, newest first.
|
|
1345
1384
|
* Free users receive the 3 most recent.
|
|
@@ -1572,6 +1611,52 @@ var Earnings = class {
|
|
|
1572
1611
|
async getRecent(options) {
|
|
1573
1612
|
return this.client.get("/api/v1/earnings/recent", options);
|
|
1574
1613
|
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Measured price reactions to a ticker's last earnings reports, newest first.
|
|
1616
|
+
*
|
|
1617
|
+
* Use this after {@link getRecent} when you need one company's realized
|
|
1618
|
+
* post-report history. `client.calendar.getEarnings()` is the forward-looking
|
|
1619
|
+
* schedule instead. This endpoint returns its payload directly, without a
|
|
1620
|
+
* preview envelope, and every API key receives the full series.
|
|
1621
|
+
*
|
|
1622
|
+
* `timing` is always present on each row and can be `null` when the reacting
|
|
1623
|
+
* session was inferred rather than observed.
|
|
1624
|
+
*/
|
|
1625
|
+
async getReactions(ticker) {
|
|
1626
|
+
return this.client.get(
|
|
1627
|
+
`/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings/reactions`
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* Market-wide earnings outcomes and realized reaction statistics.
|
|
1632
|
+
*
|
|
1633
|
+
* Use this for aggregate beat, miss, inline, and post-report move rates.
|
|
1634
|
+
* {@link getRecent} returns individual recent reports, while
|
|
1635
|
+
* `client.calendar.getEarnings()` covers upcoming dates. The response uses
|
|
1636
|
+
* the preview envelope, but every API key receives the full body and
|
|
1637
|
+
* `isPreview` is always `false`.
|
|
1638
|
+
*
|
|
1639
|
+
* `baseline` and `deviation` are omitted for long-span windows, and rates can
|
|
1640
|
+
* be `null` when their denominator is zero.
|
|
1641
|
+
*/
|
|
1642
|
+
async getStatistics(options) {
|
|
1643
|
+
return this.client.get("/api/v1/earnings/statistics", options);
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Important recently reported and upcoming earnings in one ranking.
|
|
1647
|
+
*
|
|
1648
|
+
* Use this to prioritize a cross-ticker sweep. Follow reported rows with
|
|
1649
|
+
* {@link getReactions} for realized history; use {@link getRecent} for an
|
|
1650
|
+
* unranked recent feed or `client.calendar.getEarnings()` for the broader
|
|
1651
|
+
* forward schedule.
|
|
1652
|
+
*
|
|
1653
|
+
* A PRO key receives the full ranking. A FREE key receives the first three
|
|
1654
|
+
* rows in each section with `totalInWindow` left intact. Optional row fields
|
|
1655
|
+
* are omitted when null, so check them before use.
|
|
1656
|
+
*/
|
|
1657
|
+
async getRanked(options) {
|
|
1658
|
+
return this.client.get("/api/v1/earnings/ranked", options);
|
|
1659
|
+
}
|
|
1575
1660
|
};
|
|
1576
1661
|
|
|
1577
1662
|
// src/resources/entityMetrics.ts
|
|
@@ -2300,7 +2385,7 @@ var Stocks = class {
|
|
|
2300
2385
|
* the full series. Returns 404 for tickers that do not yet have curated coverage.
|
|
2301
2386
|
*
|
|
2302
2387
|
* Coverage today: near-complete for the S&P 500 plus extended universe
|
|
2303
|
-
* (
|
|
2388
|
+
* (900+ tickers). Use `listKpiCoverage()` to enumerate.
|
|
2304
2389
|
*/
|
|
2305
2390
|
async getKpis(ticker) {
|
|
2306
2391
|
return this.client.get(
|
|
@@ -2597,12 +2682,23 @@ var SentiSense = class {
|
|
|
2597
2682
|
if (!response.ok) {
|
|
2598
2683
|
const isRetryable = response.status === 429 || response.status >= 500;
|
|
2599
2684
|
if (isRetryable && attempt < this.maxRetries) {
|
|
2600
|
-
if (response.status === 429) {
|
|
2601
|
-
|
|
2685
|
+
if (response.status === 429 || response.status === 503) {
|
|
2686
|
+
const requestedS = retryAfterSeconds(
|
|
2602
2687
|
response.headers.get("Retry-After"),
|
|
2603
2688
|
RATE_LIMIT_FALLBACK_WAIT_S,
|
|
2604
|
-
|
|
2605
|
-
)
|
|
2689
|
+
Number.POSITIVE_INFINITY
|
|
2690
|
+
);
|
|
2691
|
+
if (requestedS > MAX_RATE_LIMIT_WAIT_S) {
|
|
2692
|
+
try {
|
|
2693
|
+
await response.body?.cancel();
|
|
2694
|
+
} catch {
|
|
2695
|
+
}
|
|
2696
|
+
throw new TemporarilyUnavailableError(
|
|
2697
|
+
`Server asked for a ${Math.round(requestedS)}s wait, longer than this client's ${MAX_RATE_LIMIT_WAIT_S}s budget`,
|
|
2698
|
+
requestedS
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
delayMs = requestedS * 1e3;
|
|
2606
2702
|
} else {
|
|
2607
2703
|
delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1e3;
|
|
2608
2704
|
}
|
|
@@ -3452,6 +3548,7 @@ var optionsCommand = {
|
|
|
3452
3548
|
kind: "facts",
|
|
3453
3549
|
items: fields(
|
|
3454
3550
|
field("ATM IV", fixed(latest.atmIv, 4)),
|
|
3551
|
+
field("Exp move 1d", fixed(latest.expectedMove1d, 4)),
|
|
3455
3552
|
field("Skew 25d", signed(latest.skew25d, 4)),
|
|
3456
3553
|
field("Call vol", humanize(latest.callVol, 1)),
|
|
3457
3554
|
field("Put vol", humanize(latest.putVol, 1)),
|
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
RateLimitError: () => RateLimitError,
|
|
28
28
|
SentiSense: () => SentiSense,
|
|
29
29
|
SentiSenseError: () => SentiSenseError,
|
|
30
|
+
TemporarilyUnavailableError: () => TemporarilyUnavailableError,
|
|
30
31
|
VERSION: () => VERSION,
|
|
31
32
|
default: () => SentiSense
|
|
32
33
|
});
|
|
@@ -67,6 +68,13 @@ var RateLimitError = class extends SentiSenseError {
|
|
|
67
68
|
this.retryAfter = retryAfter;
|
|
68
69
|
}
|
|
69
70
|
};
|
|
71
|
+
var TemporarilyUnavailableError = class extends SentiSenseError {
|
|
72
|
+
constructor(message, retryAfter, code) {
|
|
73
|
+
super(message, 503, code);
|
|
74
|
+
this.name = "TemporarilyUnavailableError";
|
|
75
|
+
this.retryAfter = retryAfter;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
70
78
|
var APIError = class extends SentiSenseError {
|
|
71
79
|
constructor(message, status, code) {
|
|
72
80
|
super(message, status, code);
|
|
@@ -88,6 +96,38 @@ var Analyst = class {
|
|
|
88
96
|
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`
|
|
89
97
|
);
|
|
90
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Get daily consensus observations, ordered by `snapshotDate` ascending.
|
|
101
|
+
* Each row describes the target fields as observed on that date. When
|
|
102
|
+
* `countsObserved` is `false`, the vendor panel did not come back that day and the
|
|
103
|
+
* distribution counts are carried forward.
|
|
104
|
+
*
|
|
105
|
+
* A PRO key receives the requested window. A FREE key receives the last 30 days;
|
|
106
|
+
* `targetMedian`, `recommendationMean`, and the five distribution fields are `null`.
|
|
107
|
+
* The envelope's `totalCount` still sizes the full requested window.
|
|
108
|
+
*/
|
|
109
|
+
async consensusHistory(ticker, options) {
|
|
110
|
+
return this.client.get(
|
|
111
|
+
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus/history`,
|
|
112
|
+
options
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get factual call history as recorded when a stock moved 20% or more over five
|
|
117
|
+
* sessions, newest move first by `moveEndDate`.
|
|
118
|
+
*
|
|
119
|
+
* PRO receives full moves and calls. FREE receives the newest move with up to five
|
|
120
|
+
* calls and all move-level counts intact. The envelope's `totalCount` counts all
|
|
121
|
+
* available moves before the limit. A known stock with no qualifying move returns
|
|
122
|
+
* an empty `moves` array. Each call includes `analystName`: it is `null`, never
|
|
123
|
+
* absent, when the publisher named nobody.
|
|
124
|
+
*/
|
|
125
|
+
async calledIt(ticker, options) {
|
|
126
|
+
return this.client.get(
|
|
127
|
+
`/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/called-it`,
|
|
128
|
+
options
|
|
129
|
+
);
|
|
130
|
+
}
|
|
91
131
|
/**
|
|
92
132
|
* Get recent analyst upgrade/downgrade actions for a ticker, newest first.
|
|
93
133
|
* Free users receive the 3 most recent.
|
|
@@ -320,6 +360,52 @@ var Earnings = class {
|
|
|
320
360
|
async getRecent(options) {
|
|
321
361
|
return this.client.get("/api/v1/earnings/recent", options);
|
|
322
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Measured price reactions to a ticker's last earnings reports, newest first.
|
|
365
|
+
*
|
|
366
|
+
* Use this after {@link getRecent} when you need one company's realized
|
|
367
|
+
* post-report history. `client.calendar.getEarnings()` is the forward-looking
|
|
368
|
+
* schedule instead. This endpoint returns its payload directly, without a
|
|
369
|
+
* preview envelope, and every API key receives the full series.
|
|
370
|
+
*
|
|
371
|
+
* `timing` is always present on each row and can be `null` when the reacting
|
|
372
|
+
* session was inferred rather than observed.
|
|
373
|
+
*/
|
|
374
|
+
async getReactions(ticker) {
|
|
375
|
+
return this.client.get(
|
|
376
|
+
`/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings/reactions`
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Market-wide earnings outcomes and realized reaction statistics.
|
|
381
|
+
*
|
|
382
|
+
* Use this for aggregate beat, miss, inline, and post-report move rates.
|
|
383
|
+
* {@link getRecent} returns individual recent reports, while
|
|
384
|
+
* `client.calendar.getEarnings()` covers upcoming dates. The response uses
|
|
385
|
+
* the preview envelope, but every API key receives the full body and
|
|
386
|
+
* `isPreview` is always `false`.
|
|
387
|
+
*
|
|
388
|
+
* `baseline` and `deviation` are omitted for long-span windows, and rates can
|
|
389
|
+
* be `null` when their denominator is zero.
|
|
390
|
+
*/
|
|
391
|
+
async getStatistics(options) {
|
|
392
|
+
return this.client.get("/api/v1/earnings/statistics", options);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Important recently reported and upcoming earnings in one ranking.
|
|
396
|
+
*
|
|
397
|
+
* Use this to prioritize a cross-ticker sweep. Follow reported rows with
|
|
398
|
+
* {@link getReactions} for realized history; use {@link getRecent} for an
|
|
399
|
+
* unranked recent feed or `client.calendar.getEarnings()` for the broader
|
|
400
|
+
* forward schedule.
|
|
401
|
+
*
|
|
402
|
+
* A PRO key receives the full ranking. A FREE key receives the first three
|
|
403
|
+
* rows in each section with `totalInWindow` left intact. Optional row fields
|
|
404
|
+
* are omitted when null, so check them before use.
|
|
405
|
+
*/
|
|
406
|
+
async getRanked(options) {
|
|
407
|
+
return this.client.get("/api/v1/earnings/ranked", options);
|
|
408
|
+
}
|
|
323
409
|
};
|
|
324
410
|
|
|
325
411
|
// src/resources/entityMetrics.ts
|
|
@@ -1048,7 +1134,7 @@ var Stocks = class {
|
|
|
1048
1134
|
* the full series. Returns 404 for tickers that do not yet have curated coverage.
|
|
1049
1135
|
*
|
|
1050
1136
|
* Coverage today: near-complete for the S&P 500 plus extended universe
|
|
1051
|
-
* (
|
|
1137
|
+
* (900+ tickers). Use `listKpiCoverage()` to enumerate.
|
|
1052
1138
|
*/
|
|
1053
1139
|
async getKpis(ticker) {
|
|
1054
1140
|
return this.client.get(
|
|
@@ -1249,7 +1335,7 @@ var Trackers = class {
|
|
|
1249
1335
|
};
|
|
1250
1336
|
|
|
1251
1337
|
// src/version.ts
|
|
1252
|
-
var VERSION = "0.
|
|
1338
|
+
var VERSION = "0.55.0";
|
|
1253
1339
|
|
|
1254
1340
|
// src/client.ts
|
|
1255
1341
|
var DEFAULT_BASE_URL = "https://app.sentisense.ai";
|
|
@@ -1348,12 +1434,23 @@ var SentiSense = class {
|
|
|
1348
1434
|
if (!response.ok) {
|
|
1349
1435
|
const isRetryable = response.status === 429 || response.status >= 500;
|
|
1350
1436
|
if (isRetryable && attempt < this.maxRetries) {
|
|
1351
|
-
if (response.status === 429) {
|
|
1352
|
-
|
|
1437
|
+
if (response.status === 429 || response.status === 503) {
|
|
1438
|
+
const requestedS = retryAfterSeconds(
|
|
1353
1439
|
response.headers.get("Retry-After"),
|
|
1354
1440
|
RATE_LIMIT_FALLBACK_WAIT_S,
|
|
1355
|
-
|
|
1356
|
-
)
|
|
1441
|
+
Number.POSITIVE_INFINITY
|
|
1442
|
+
);
|
|
1443
|
+
if (requestedS > MAX_RATE_LIMIT_WAIT_S) {
|
|
1444
|
+
try {
|
|
1445
|
+
await response.body?.cancel();
|
|
1446
|
+
} catch {
|
|
1447
|
+
}
|
|
1448
|
+
throw new TemporarilyUnavailableError(
|
|
1449
|
+
`Server asked for a ${Math.round(requestedS)}s wait, longer than this client's ${MAX_RATE_LIMIT_WAIT_S}s budget`,
|
|
1450
|
+
requestedS
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
delayMs = requestedS * 1e3;
|
|
1357
1454
|
} else {
|
|
1358
1455
|
delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1e3;
|
|
1359
1456
|
}
|
|
@@ -1464,6 +1561,7 @@ var SentiSense = class {
|
|
|
1464
1561
|
RateLimitError,
|
|
1465
1562
|
SentiSense,
|
|
1466
1563
|
SentiSenseError,
|
|
1564
|
+
TemporarilyUnavailableError,
|
|
1467
1565
|
VERSION
|
|
1468
1566
|
});
|
|
1469
1567
|
//# sourceMappingURL=index.cjs.map
|