sentisense 0.42.0 → 0.43.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 +1 -1
- package/dist/cli.cjs +147 -60
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Get a key at [app.sentisense.ai/get-api-key](https://app.sentisense.ai/get-api-k
|
|
|
56
56
|
| `sentiment <ticker>` | SentiSense Score, tone, attention, per-source breakdown, `--days N` history |
|
|
57
57
|
| `mood` | Composite market sentiment, the signals behind it, and the sector map |
|
|
58
58
|
| `analysts <ticker>` | Consensus, price target band, recent upgrades and downgrades |
|
|
59
|
-
| `earnings [ticker]` | Forward calendar with no ticker, per-quarter analysis with one |
|
|
59
|
+
| `earnings [ticker]` | Forward calendar with no ticker, per-quarter analysis with one (`earnings AAPL`) |
|
|
60
60
|
| `insiders <ticker>` | Filed Form 4 transactions, including whether they were pre-planned |
|
|
61
61
|
| `insights <ticker>` | Generated signals, filterable by `--urgency` and `--type` |
|
|
62
62
|
| `congress [ticker]` | Congressional disclosures, market-wide or for one symbol |
|
package/dist/cli.cjs
CHANGED
|
@@ -70,6 +70,13 @@ var CliUsageError = class extends Error {
|
|
|
70
70
|
this.hint = hint;
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
|
+
var UnknownTickerError = class extends Error {
|
|
74
|
+
constructor(ticker) {
|
|
75
|
+
super(`unknown ticker "${ticker}".`);
|
|
76
|
+
this.name = "UnknownTickerError";
|
|
77
|
+
this.ticker = ticker;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
73
80
|
var MissingKeyError = class extends Error {
|
|
74
81
|
constructor() {
|
|
75
82
|
super("no API key configured.");
|
|
@@ -93,6 +100,15 @@ function classify(error) {
|
|
|
93
100
|
]
|
|
94
101
|
};
|
|
95
102
|
}
|
|
103
|
+
if (error instanceof UnknownTickerError) {
|
|
104
|
+
return {
|
|
105
|
+
exitCode: EXIT.NOT_FOUND,
|
|
106
|
+
lines: [
|
|
107
|
+
`error: ${error.message}`,
|
|
108
|
+
"next: check the symbol. Use canonical tickers, for example GOOGL rather than GOOG and BRK.B rather than BRK-B."
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
96
112
|
if (error instanceof CliUsageError) {
|
|
97
113
|
return {
|
|
98
114
|
exitCode: EXIT.USAGE,
|
|
@@ -158,6 +174,48 @@ function classify(error) {
|
|
|
158
174
|
};
|
|
159
175
|
}
|
|
160
176
|
|
|
177
|
+
// src/cli/ticker.ts
|
|
178
|
+
function rejectSurplus(args, name, allowed) {
|
|
179
|
+
if (args.positionals.length <= allowed) return;
|
|
180
|
+
throw new CliUsageError(
|
|
181
|
+
`${name} takes one ticker, and got ${args.positionals.length}.`,
|
|
182
|
+
"run it once per ticker. Only quote accepts more than one."
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
function oneTicker(args, name) {
|
|
186
|
+
rejectSurplus(args, name, 1);
|
|
187
|
+
const ticker = args.positionals[0];
|
|
188
|
+
if (!ticker) {
|
|
189
|
+
throw new CliUsageError(
|
|
190
|
+
`${name} needs a ticker.`,
|
|
191
|
+
`for example: sentisense ${name} NVDA`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
return ticker.toUpperCase();
|
|
195
|
+
}
|
|
196
|
+
function optionalTicker(args, name) {
|
|
197
|
+
rejectSurplus(args, name, 1);
|
|
198
|
+
return args.positionals[0]?.toUpperCase();
|
|
199
|
+
}
|
|
200
|
+
function rejectPositionals(args, name) {
|
|
201
|
+
if (args.positionals.length === 0) return;
|
|
202
|
+
throw new CliUsageError(
|
|
203
|
+
`${name} takes no ticker, and got ${args.positionals.length}.`,
|
|
204
|
+
`run "sentisense help ${name}" for what it accepts.`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
async function verifyTickerOnEmpty(api, ticker) {
|
|
208
|
+
try {
|
|
209
|
+
await api.stocks.getQuote(ticker);
|
|
210
|
+
return void 0;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
if (error instanceof NotFoundError) throw new UnknownTickerError(ticker);
|
|
213
|
+
return `could not verify ${ticker}, so the empty result is unconfirmed`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
var EMPTY_VERIFY_NOTE = "An empty result verifies the ticker before reporting no data, so a typo exits 4 rather";
|
|
217
|
+
var EMPTY_VERIFY_NOTE_2 = "than looking like a company with nothing to report.";
|
|
218
|
+
|
|
161
219
|
// src/cli/render/doc.ts
|
|
162
220
|
function cell(text, tone) {
|
|
163
221
|
return tone ? { text, tone } : { text };
|
|
@@ -269,13 +327,7 @@ var analystsCommand = {
|
|
|
269
327
|
days: { type: "number", placeholder: "N", describe: "Days of rating history (default 90)" }
|
|
270
328
|
},
|
|
271
329
|
async run({ args, client, full }) {
|
|
272
|
-
const ticker = args
|
|
273
|
-
if (!ticker) {
|
|
274
|
-
throw new CliUsageError(
|
|
275
|
-
"analysts needs a ticker.",
|
|
276
|
-
"for example: sentisense analysts NVDA"
|
|
277
|
-
);
|
|
278
|
-
}
|
|
330
|
+
const ticker = oneTicker(args, "analysts");
|
|
279
331
|
const lookbackDays = typeof args.flags.days === "number" ? args.flags.days : void 0;
|
|
280
332
|
const api = client();
|
|
281
333
|
const notes = [];
|
|
@@ -519,7 +571,9 @@ var congressCommand = {
|
|
|
519
571
|
"Disclosures are filed after the fact, so the gap between the trade date and the",
|
|
520
572
|
"disclosure date is part of the picture. The delay column carries it in days.",
|
|
521
573
|
"Amounts are the filed ranges, never exact figures: that is how the filings work.",
|
|
522
|
-
"A free key sees a short preview of either feed."
|
|
574
|
+
"A free key sees a short preview of either feed.",
|
|
575
|
+
EMPTY_VERIFY_NOTE,
|
|
576
|
+
EMPTY_VERIFY_NOTE_2
|
|
523
577
|
],
|
|
524
578
|
flags: {
|
|
525
579
|
days: { type: "number", placeholder: "N", describe: "Look-back window, 1 to 365 (default 90)" },
|
|
@@ -527,7 +581,8 @@ var congressCommand = {
|
|
|
527
581
|
},
|
|
528
582
|
async run({ args, client, full }) {
|
|
529
583
|
const api = client();
|
|
530
|
-
const ticker = args
|
|
584
|
+
const ticker = optionalTicker(args, "congress");
|
|
585
|
+
const notes = [];
|
|
531
586
|
const lookbackDays = typeof args.flags.days === "number" ? args.flags.days : void 0;
|
|
532
587
|
const limit = typeof args.flags.limit === "number" ? args.flags.limit : void 0;
|
|
533
588
|
let envelope;
|
|
@@ -546,6 +601,10 @@ var congressCommand = {
|
|
|
546
601
|
);
|
|
547
602
|
}
|
|
548
603
|
const trades = envelope.data ?? [];
|
|
604
|
+
if (ticker && trades.length === 0) {
|
|
605
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
606
|
+
if (note) notes.push(note);
|
|
607
|
+
}
|
|
549
608
|
const shown = full ? trades : trades.slice(0, 20);
|
|
550
609
|
const blocks = [
|
|
551
610
|
{
|
|
@@ -594,7 +653,7 @@ var congressCommand = {
|
|
|
594
653
|
tone: "dim"
|
|
595
654
|
});
|
|
596
655
|
}
|
|
597
|
-
return { json: envelope, doc: doc(...blocks) };
|
|
656
|
+
return { json: envelope, doc: doc(...blocks), notes };
|
|
598
657
|
}
|
|
599
658
|
};
|
|
600
659
|
|
|
@@ -612,14 +671,18 @@ var earningsCommand = {
|
|
|
612
671
|
examples: [
|
|
613
672
|
"sentisense earnings",
|
|
614
673
|
"sentisense earnings --week next",
|
|
615
|
-
"sentisense earnings
|
|
616
|
-
"sentisense earnings
|
|
674
|
+
"sentisense earnings AAPL",
|
|
675
|
+
"sentisense earnings AAPL --limit 4 --full"
|
|
617
676
|
],
|
|
618
677
|
notes: [
|
|
619
678
|
"With no ticker this is the forward calendar: who reports, when, and the consensus EPS.",
|
|
620
679
|
"With a ticker it is the backward-looking analysis: one entry per reported quarter with",
|
|
621
680
|
"the editorial headline, and on a PRO key the written summary and guidance language.",
|
|
622
|
-
"A free key sees the current week of the calendar and the latest quarter of the analysis."
|
|
681
|
+
"A free key sees the current week of the calendar and the latest quarter of the analysis.",
|
|
682
|
+
"Coverage of the per-ticker analysis is not the whole market, so a tracked company can",
|
|
683
|
+
"have no stored quarter yet.",
|
|
684
|
+
EMPTY_VERIFY_NOTE,
|
|
685
|
+
EMPTY_VERIFY_NOTE_2
|
|
623
686
|
],
|
|
624
687
|
flags: {
|
|
625
688
|
week: { type: "string", placeholder: "this|next", describe: "Calendar window shorthand" },
|
|
@@ -630,7 +693,8 @@ var earningsCommand = {
|
|
|
630
693
|
},
|
|
631
694
|
async run({ args, client, full }) {
|
|
632
695
|
const api = client();
|
|
633
|
-
const ticker = args
|
|
696
|
+
const ticker = optionalTicker(args, "earnings");
|
|
697
|
+
const notes = [];
|
|
634
698
|
if (ticker) {
|
|
635
699
|
const limit = typeof args.flags.limit === "number" ? args.flags.limit : void 0;
|
|
636
700
|
const envelope2 = await api.earnings.getSummaries(
|
|
@@ -638,6 +702,10 @@ var earningsCommand = {
|
|
|
638
702
|
limit === void 0 ? void 0 : { limit }
|
|
639
703
|
);
|
|
640
704
|
const quarters = envelope2.data ?? [];
|
|
705
|
+
if (quarters.length === 0) {
|
|
706
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
707
|
+
if (note) notes.push(note);
|
|
708
|
+
}
|
|
641
709
|
const blocks2 = [
|
|
642
710
|
{
|
|
643
711
|
kind: "head",
|
|
@@ -699,7 +767,7 @@ var earningsCommand = {
|
|
|
699
767
|
tone: "dim"
|
|
700
768
|
});
|
|
701
769
|
}
|
|
702
|
-
return { json: envelope2, doc: doc(...blocks2) };
|
|
770
|
+
return { json: envelope2, doc: doc(...blocks2), notes };
|
|
703
771
|
}
|
|
704
772
|
const week = typeof args.flags.week === "string" ? args.flags.week : void 0;
|
|
705
773
|
if (week && week !== "this" && week !== "next") {
|
|
@@ -791,7 +859,9 @@ var flowsCommand = {
|
|
|
791
859
|
"market. With a ticker it is that stock's institutional ownership and the quarter's",
|
|
792
860
|
"notable position changes, since flows are only published market-wide.",
|
|
793
861
|
"13F filings land up to 45 days after quarter end, so a still-open quarter shows only",
|
|
794
|
-
"early filers and says so."
|
|
862
|
+
"early filers and says so, and a ticker reads the newest quarter that has closed.",
|
|
863
|
+
EMPTY_VERIFY_NOTE,
|
|
864
|
+
EMPTY_VERIFY_NOTE_2
|
|
795
865
|
],
|
|
796
866
|
flags: {
|
|
797
867
|
limit: { type: "number", placeholder: "N", describe: `Rows per side (default ${DEFAULT_ROWS})` },
|
|
@@ -799,7 +869,8 @@ var flowsCommand = {
|
|
|
799
869
|
},
|
|
800
870
|
async run({ args, client, full }) {
|
|
801
871
|
const api = client();
|
|
802
|
-
const ticker = args
|
|
872
|
+
const ticker = optionalTicker(args, "flows");
|
|
873
|
+
const notes = [];
|
|
803
874
|
const limit = typeof args.flags.limit === "number" ? args.flags.limit : DEFAULT_ROWS;
|
|
804
875
|
const quarter = typeof args.flags.quarter === "string" ? args.flags.quarter : void 0;
|
|
805
876
|
if (ticker) {
|
|
@@ -820,6 +891,10 @@ var flowsCommand = {
|
|
|
820
891
|
});
|
|
821
892
|
const data2 = envelope2.data;
|
|
822
893
|
const holders = data2?.holders ?? [];
|
|
894
|
+
if (holders.length === 0) {
|
|
895
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
896
|
+
if (note) notes.push(note);
|
|
897
|
+
}
|
|
823
898
|
const blocks2 = [
|
|
824
899
|
{
|
|
825
900
|
kind: "head",
|
|
@@ -878,7 +953,7 @@ var flowsCommand = {
|
|
|
878
953
|
tone: "dim"
|
|
879
954
|
});
|
|
880
955
|
}
|
|
881
|
-
return { json: envelope2, doc: doc(...blocks2) };
|
|
956
|
+
return { json: envelope2, doc: doc(...blocks2), notes };
|
|
882
957
|
}
|
|
883
958
|
const envelope = await api.institutional.getFlows(quarter, { limit });
|
|
884
959
|
const data = envelope.data;
|
|
@@ -933,7 +1008,7 @@ var flowsCommand = {
|
|
|
933
1008
|
};
|
|
934
1009
|
|
|
935
1010
|
// src/version.ts
|
|
936
|
-
var VERSION = "0.
|
|
1011
|
+
var VERSION = "0.43.0";
|
|
937
1012
|
|
|
938
1013
|
// src/resources/analyst.ts
|
|
939
1014
|
var Analyst = class {
|
|
@@ -2312,7 +2387,8 @@ var healthCommand = {
|
|
|
2312
2387
|
"Exits 3 when the key is missing or rejected, 6 when the host cannot be reached."
|
|
2313
2388
|
],
|
|
2314
2389
|
flags: {},
|
|
2315
|
-
async run({ context }) {
|
|
2390
|
+
async run({ args, context }) {
|
|
2391
|
+
rejectPositionals(args, "health");
|
|
2316
2392
|
const baseUrl = effectiveBaseUrl(context);
|
|
2317
2393
|
const anonymous = createClient(context, { anonymous: true });
|
|
2318
2394
|
const reach = await probe(() => anonymous.stocks.getMarketStatus());
|
|
@@ -2382,25 +2458,27 @@ var insidersCommand = {
|
|
|
2382
2458
|
"Rows are individual filed transactions, newest first, not a net total.",
|
|
2383
2459
|
"The plan column says whether the trade was under a confirmed pre-arranged 10b5-1 plan,",
|
|
2384
2460
|
"which is the difference between a scheduled sale and a discretionary one.",
|
|
2385
|
-
"A free key sees the top few transactions; a PRO key sees the window you asked for."
|
|
2461
|
+
"A free key sees the top few transactions; a PRO key sees the window you asked for.",
|
|
2462
|
+
EMPTY_VERIFY_NOTE,
|
|
2463
|
+
EMPTY_VERIFY_NOTE_2
|
|
2386
2464
|
],
|
|
2387
2465
|
flags: {
|
|
2388
2466
|
days: { type: "number", placeholder: "N", describe: "Look-back window, 1 to 365 (default 90)" }
|
|
2389
2467
|
},
|
|
2390
2468
|
async run({ args, client, full }) {
|
|
2391
|
-
const ticker = args
|
|
2392
|
-
if (!ticker) {
|
|
2393
|
-
throw new CliUsageError(
|
|
2394
|
-
"insiders needs a ticker.",
|
|
2395
|
-
"for example: sentisense insiders NVDA"
|
|
2396
|
-
);
|
|
2397
|
-
}
|
|
2469
|
+
const ticker = oneTicker(args, "insiders");
|
|
2398
2470
|
const lookbackDays = typeof args.flags.days === "number" ? args.flags.days : void 0;
|
|
2399
|
-
const
|
|
2471
|
+
const api = client();
|
|
2472
|
+
const notes = [];
|
|
2473
|
+
const envelope = await api.insider.getTrades(
|
|
2400
2474
|
ticker,
|
|
2401
2475
|
lookbackDays === void 0 ? void 0 : { lookbackDays }
|
|
2402
2476
|
);
|
|
2403
2477
|
const trades = envelope.data ?? [];
|
|
2478
|
+
if (trades.length === 0) {
|
|
2479
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
2480
|
+
if (note) notes.push(note);
|
|
2481
|
+
}
|
|
2404
2482
|
const shown = full ? trades : trades.slice(0, 15);
|
|
2405
2483
|
const buys = trades.filter((trade) => trade.transactionType === "BUY");
|
|
2406
2484
|
const sells = trades.filter((trade) => trade.transactionType === "SELL");
|
|
@@ -2451,7 +2529,7 @@ var insidersCommand = {
|
|
|
2451
2529
|
tone: "dim"
|
|
2452
2530
|
});
|
|
2453
2531
|
}
|
|
2454
|
-
return { json: envelope, doc: doc(...blocks) };
|
|
2532
|
+
return { json: envelope, doc: doc(...blocks), notes };
|
|
2455
2533
|
}
|
|
2456
2534
|
};
|
|
2457
2535
|
|
|
@@ -2468,25 +2546,23 @@ var insightsCommand = {
|
|
|
2468
2546
|
examples: [
|
|
2469
2547
|
"sentisense insights NVDA",
|
|
2470
2548
|
"sentisense insights NVDA --urgency high",
|
|
2471
|
-
"sentisense insights NVDA --type
|
|
2549
|
+
"sentisense insights NVDA --type institutional_position_change --full"
|
|
2472
2550
|
],
|
|
2473
2551
|
notes: [
|
|
2474
2552
|
"Signals are generated observations about filings, flows, and attention, ordered by",
|
|
2475
2553
|
"urgency then confidence. They describe what the data shows, not what to do about it.",
|
|
2476
|
-
"A free key sees the top three; a PRO key sees the whole list."
|
|
2554
|
+
"A free key sees the top three; a PRO key sees the whole list.",
|
|
2555
|
+
"Signal types vary by ticker and over time, so take --type from what a plain run reports",
|
|
2556
|
+
"rather than guessing a name.",
|
|
2557
|
+
EMPTY_VERIFY_NOTE,
|
|
2558
|
+
EMPTY_VERIFY_NOTE_2
|
|
2477
2559
|
],
|
|
2478
2560
|
flags: {
|
|
2479
2561
|
urgency: { type: "string", placeholder: "level", describe: "Filter to low, medium, or high" },
|
|
2480
2562
|
type: { type: "string", placeholder: "name", describe: "Filter to one signal type" }
|
|
2481
2563
|
},
|
|
2482
2564
|
async run({ args, client, full }) {
|
|
2483
|
-
const ticker = args
|
|
2484
|
-
if (!ticker) {
|
|
2485
|
-
throw new CliUsageError(
|
|
2486
|
-
"insights needs a ticker.",
|
|
2487
|
-
"for example: sentisense insights NVDA"
|
|
2488
|
-
);
|
|
2489
|
-
}
|
|
2565
|
+
const ticker = oneTicker(args, "insights");
|
|
2490
2566
|
const urgency = typeof args.flags.urgency === "string" ? args.flags.urgency : void 0;
|
|
2491
2567
|
if (urgency && !["low", "medium", "high"].includes(urgency)) {
|
|
2492
2568
|
throw new CliUsageError(
|
|
@@ -2498,11 +2574,17 @@ var insightsCommand = {
|
|
|
2498
2574
|
...urgency ? { urgency } : {},
|
|
2499
2575
|
...typeof args.flags.type === "string" ? { insightType: args.flags.type } : {}
|
|
2500
2576
|
};
|
|
2501
|
-
const
|
|
2577
|
+
const api = client();
|
|
2578
|
+
const notes = [];
|
|
2579
|
+
const envelope = await api.insights.stock(
|
|
2502
2580
|
ticker,
|
|
2503
2581
|
Object.keys(options).length > 0 ? options : void 0
|
|
2504
2582
|
);
|
|
2505
2583
|
const insights = envelope.data ?? [];
|
|
2584
|
+
if (insights.length === 0) {
|
|
2585
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
2586
|
+
if (note) notes.push(note);
|
|
2587
|
+
}
|
|
2506
2588
|
const shown = full ? insights : insights.slice(0, 8);
|
|
2507
2589
|
const blocks = [
|
|
2508
2590
|
{
|
|
@@ -2555,7 +2637,7 @@ var insightsCommand = {
|
|
|
2555
2637
|
tone: "dim"
|
|
2556
2638
|
});
|
|
2557
2639
|
}
|
|
2558
|
-
return { json: envelope, doc: doc(...blocks) };
|
|
2640
|
+
return { json: envelope, doc: doc(...blocks), notes };
|
|
2559
2641
|
}
|
|
2560
2642
|
};
|
|
2561
2643
|
|
|
@@ -2584,7 +2666,8 @@ var moodCommand = {
|
|
|
2584
2666
|
"46-55 neutral, 56-70 optimism, 71-85 greed, 86-100 extreme greed."
|
|
2585
2667
|
],
|
|
2586
2668
|
flags: {},
|
|
2587
|
-
async run({ client, full }) {
|
|
2669
|
+
async run({ args, client, full }) {
|
|
2670
|
+
rejectPositionals(args, "mood");
|
|
2588
2671
|
const payload = await client().marketMood.get();
|
|
2589
2672
|
const market = readMarket(payload);
|
|
2590
2673
|
const sectors = readSectors(payload);
|
|
@@ -2669,7 +2752,9 @@ var newsCommand = {
|
|
|
2669
2752
|
"A story is a cluster of articles covering the same event, not a single headline, so",
|
|
2670
2753
|
"the size column is how many sources picked it up and impact ranks how much it moved.",
|
|
2671
2754
|
"Tone is the average sentiment across the cluster, between -1 and 1.",
|
|
2672
|
-
"--days only applies to the market-wide feed."
|
|
2755
|
+
"--days only applies to the market-wide feed.",
|
|
2756
|
+
EMPTY_VERIFY_NOTE,
|
|
2757
|
+
EMPTY_VERIFY_NOTE_2
|
|
2673
2758
|
],
|
|
2674
2759
|
flags: {
|
|
2675
2760
|
limit: { type: "number", placeholder: "N", describe: `Stories to return (default ${DEFAULT_LIMIT})` },
|
|
@@ -2677,10 +2762,15 @@ var newsCommand = {
|
|
|
2677
2762
|
},
|
|
2678
2763
|
async run({ args, client, full }) {
|
|
2679
2764
|
const api = client();
|
|
2680
|
-
const ticker = args
|
|
2765
|
+
const ticker = optionalTicker(args, "news");
|
|
2766
|
+
const notes = [];
|
|
2681
2767
|
const limit = typeof args.flags.limit === "number" ? args.flags.limit : DEFAULT_LIMIT;
|
|
2682
2768
|
const days = typeof args.flags.days === "number" ? args.flags.days : void 0;
|
|
2683
2769
|
const stories = ticker ? await api.documents.getStoriesByTicker(ticker, { limit }) : await api.documents.getStories({ limit, ...days === void 0 ? {} : { days } });
|
|
2770
|
+
if (ticker && stories.length === 0) {
|
|
2771
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
2772
|
+
if (note) notes.push(note);
|
|
2773
|
+
}
|
|
2684
2774
|
const blocks = [
|
|
2685
2775
|
{
|
|
2686
2776
|
kind: "head",
|
|
@@ -2738,7 +2828,7 @@ var newsCommand = {
|
|
|
2738
2828
|
tone: "dim"
|
|
2739
2829
|
});
|
|
2740
2830
|
}
|
|
2741
|
-
return { json: stories, doc: doc(...blocks) };
|
|
2831
|
+
return { json: stories, doc: doc(...blocks), notes };
|
|
2742
2832
|
}
|
|
2743
2833
|
};
|
|
2744
2834
|
|
|
@@ -2766,23 +2856,25 @@ var optionsCommand = {
|
|
|
2766
2856
|
"End of day, not live: readings describe the latest completed session and refresh the",
|
|
2767
2857
|
"following morning. Percentiles are against that ticker's own trailing history, so they",
|
|
2768
2858
|
"compare a stock to its past self, never to another stock.",
|
|
2769
|
-
"Coverage is the most actively optioned names plus the tracked ETFs. A ticker
|
|
2770
|
-
"that set reports no coverage and exits 0, the same as any other empty result.",
|
|
2859
|
+
"Coverage is the most actively optioned names plus the tracked ETFs. A real ticker",
|
|
2860
|
+
"outside that set reports no coverage and exits 0, the same as any other empty result.",
|
|
2861
|
+
EMPTY_VERIFY_NOTE,
|
|
2862
|
+
EMPTY_VERIFY_NOTE_2,
|
|
2771
2863
|
"A free key gets the full dossier for the first ten calls each month, then a headline",
|
|
2772
2864
|
"preview. Calls that return no dossier do not count against that."
|
|
2773
2865
|
],
|
|
2774
2866
|
flags: {},
|
|
2775
2867
|
async run({ args, client, full }) {
|
|
2776
|
-
const ticker = args
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
}
|
|
2780
|
-
const envelope = await client().stocks.getOptionsSummary(ticker);
|
|
2868
|
+
const ticker = oneTicker(args, "options");
|
|
2869
|
+
const api = client();
|
|
2870
|
+
const envelope = await api.stocks.getOptionsSummary(ticker);
|
|
2781
2871
|
const data = envelope.data;
|
|
2782
2872
|
if (!data) {
|
|
2873
|
+
const note = await verifyTickerOnEmpty(api, ticker);
|
|
2783
2874
|
return {
|
|
2784
2875
|
json: envelope,
|
|
2785
|
-
doc: doc({ kind: "text", text: `No options coverage for ${ticker}.` })
|
|
2876
|
+
doc: doc({ kind: "text", text: `No options coverage for ${ticker}.` }),
|
|
2877
|
+
notes: note ? [note] : void 0
|
|
2786
2878
|
};
|
|
2787
2879
|
}
|
|
2788
2880
|
const latest = data.latest ?? {};
|
|
@@ -3109,6 +3201,7 @@ var screenCommand = {
|
|
|
3109
3201
|
etf: { type: "boolean", describe: "Screen the ETF universe" }
|
|
3110
3202
|
},
|
|
3111
3203
|
async run({ args, client, full }) {
|
|
3204
|
+
rejectPositionals(args, "screen");
|
|
3112
3205
|
const api = client();
|
|
3113
3206
|
const etf = args.flags.etf === true;
|
|
3114
3207
|
if (args.flags.fields === true) {
|
|
@@ -3314,13 +3407,7 @@ var sentimentCommand = {
|
|
|
3314
3407
|
days: { type: "number", placeholder: "N", describe: `Days of Score history (default ${DEFAULT_DAYS})` }
|
|
3315
3408
|
},
|
|
3316
3409
|
async run({ args, client, full }) {
|
|
3317
|
-
const ticker = args
|
|
3318
|
-
if (!ticker) {
|
|
3319
|
-
throw new CliUsageError(
|
|
3320
|
-
"sentiment needs a ticker.",
|
|
3321
|
-
"for example: sentisense sentiment NVDA"
|
|
3322
|
-
);
|
|
3323
|
-
}
|
|
3410
|
+
const ticker = oneTicker(args, "sentiment");
|
|
3324
3411
|
const days = typeof args.flags.days === "number" ? args.flags.days : DEFAULT_DAYS;
|
|
3325
3412
|
if (days < 1) {
|
|
3326
3413
|
throw new CliUsageError("--days must be at least 1.", "for example: --days 30");
|