sentisense 0.52.0 → 0.54.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 +40 -4
- package/dist/cli.cjs +10 -2
- package/dist/index.cjs +9 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +114 -9
- package/dist/index.d.ts +114 -9
- package/dist/index.mjs +9 -2
- 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` `actions` `estimates` `marketActivity` `coverage` `profile` `calls` |
|
|
178
|
+
| `calendar` | `getEarnings` |
|
|
179
|
+
| `earnings` | `getSummaries` `getRecent` |
|
|
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();
|
|
@@ -241,6 +256,27 @@ client.documents.getStories({ limit: 10 })
|
|
|
241
256
|
client.documents.getStoryDetail("cluster_abc123")
|
|
242
257
|
```
|
|
243
258
|
|
|
259
|
+
A story's `cluster` says where it came from and whether it has settled. `storySource` is
|
|
260
|
+
`"ORIGINAL"` for an editorially authored SentiSense Original and `"AI"` for a
|
|
261
|
+
pipeline-generated story, and `isLive` is true while the story is still being revised as
|
|
262
|
+
the event develops. Both are optional: against an API build that predates them they are
|
|
263
|
+
`undefined`, which means "not known" rather than `"AI"` or `false`.
|
|
264
|
+
|
|
265
|
+
`getStoryDetail` returns `unknown`, so narrow it yourself. It carries the same two fields
|
|
266
|
+
plus a `timeline` array of dated updates, newest first and empty when a story has none.
|
|
267
|
+
The `StoryTimelineEntry` type is exported for that array:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import type { StoryTimelineEntry } from "sentisense";
|
|
271
|
+
|
|
272
|
+
const detail = (await client.documents.getStoryDetail("cluster_abc123")) as {
|
|
273
|
+
timeline: StoryTimelineEntry[];
|
|
274
|
+
};
|
|
275
|
+
for (const update of detail.timeline) {
|
|
276
|
+
console.log(new Date(update.publishedAt), update.updateType, update.content);
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
244
280
|
### Institutional flows (13F)
|
|
245
281
|
|
|
246
282
|
```typescript
|
|
@@ -454,11 +490,11 @@ client.stocks.getOptionsHistory("NVDA", { window: "2y" }) // That name's daily
|
|
|
454
490
|
|
|
455
491
|
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.
|
|
456
492
|
|
|
457
|
-
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`
|
|
493
|
+
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.
|
|
458
494
|
|
|
459
495
|
### SentiSense Rating
|
|
460
496
|
|
|
461
|
-
Where a stock ranks against the other stocks rated that day, as a score, a letter and a percentile, plus the
|
|
497
|
+
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).
|
|
462
498
|
|
|
463
499
|
```typescript
|
|
464
500
|
const rating = await client.stocks.getRating("AAPL");
|
|
@@ -477,7 +513,7 @@ if (rating.rated) {
|
|
|
477
513
|
|
|
478
514
|
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`.
|
|
479
515
|
|
|
480
|
-
`dimensions` always holds all
|
|
516
|
+
`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`.
|
|
481
517
|
|
|
482
518
|
**`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`.
|
|
483
519
|
|
package/dist/cli.cjs
CHANGED
|
@@ -1324,7 +1324,7 @@ var flowsCommand = {
|
|
|
1324
1324
|
};
|
|
1325
1325
|
|
|
1326
1326
|
// src/version.ts
|
|
1327
|
-
var VERSION = "0.
|
|
1327
|
+
var VERSION = "0.54.0";
|
|
1328
1328
|
|
|
1329
1329
|
// src/resources/analyst.ts
|
|
1330
1330
|
var Analyst = class {
|
|
@@ -1507,7 +1507,14 @@ var Documents = class {
|
|
|
1507
1507
|
async getStories(options) {
|
|
1508
1508
|
return this.client.get("/api/v1/documents/stories", options);
|
|
1509
1509
|
}
|
|
1510
|
-
/**
|
|
1510
|
+
/**
|
|
1511
|
+
* Get full story detail by cluster ID.
|
|
1512
|
+
*
|
|
1513
|
+
* Deliberately untyped: narrow it yourself. The response carries `storySource` and
|
|
1514
|
+
* `isLive` alongside the story body, plus a `timeline` array of dated updates,
|
|
1515
|
+
* newest first and empty when the story has none. {@link StoryTimelineEntry} is
|
|
1516
|
+
* exported for that array.
|
|
1517
|
+
*/
|
|
1511
1518
|
async getStoryDetail(clusterId) {
|
|
1512
1519
|
return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);
|
|
1513
1520
|
}
|
|
@@ -3445,6 +3452,7 @@ var optionsCommand = {
|
|
|
3445
3452
|
kind: "facts",
|
|
3446
3453
|
items: fields(
|
|
3447
3454
|
field("ATM IV", fixed(latest.atmIv, 4)),
|
|
3455
|
+
field("Exp move 1d", fixed(latest.expectedMove1d, 4)),
|
|
3448
3456
|
field("Skew 25d", signed(latest.skew25d, 4)),
|
|
3449
3457
|
field("Call vol", humanize(latest.callVol, 1)),
|
|
3450
3458
|
field("Put vol", humanize(latest.putVol, 1)),
|
package/dist/index.cjs
CHANGED
|
@@ -255,7 +255,14 @@ var Documents = class {
|
|
|
255
255
|
async getStories(options) {
|
|
256
256
|
return this.client.get("/api/v1/documents/stories", options);
|
|
257
257
|
}
|
|
258
|
-
/**
|
|
258
|
+
/**
|
|
259
|
+
* Get full story detail by cluster ID.
|
|
260
|
+
*
|
|
261
|
+
* Deliberately untyped: narrow it yourself. The response carries `storySource` and
|
|
262
|
+
* `isLive` alongside the story body, plus a `timeline` array of dated updates,
|
|
263
|
+
* newest first and empty when the story has none. {@link StoryTimelineEntry} is
|
|
264
|
+
* exported for that array.
|
|
265
|
+
*/
|
|
259
266
|
async getStoryDetail(clusterId) {
|
|
260
267
|
return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);
|
|
261
268
|
}
|
|
@@ -1242,7 +1249,7 @@ var Trackers = class {
|
|
|
1242
1249
|
};
|
|
1243
1250
|
|
|
1244
1251
|
// src/version.ts
|
|
1245
|
-
var VERSION = "0.
|
|
1252
|
+
var VERSION = "0.54.0";
|
|
1246
1253
|
|
|
1247
1254
|
// src/client.ts
|
|
1248
1255
|
var DEFAULT_BASE_URL = "https://app.sentisense.ai";
|