alphacouncil-agent 0.5.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.
Files changed (139) hide show
  1. package/.claude/agents/alphacouncil-bear_researcher.md +39 -0
  2. package/.claude/agents/alphacouncil-bull_researcher.md +40 -0
  3. package/.claude/agents/alphacouncil-earnings_deep_dive.md +49 -0
  4. package/.claude/agents/alphacouncil-forward_expectations.md +48 -0
  5. package/.claude/agents/alphacouncil-ib_event_analysis.md +40 -0
  6. package/.claude/agents/alphacouncil-insider_sec.md +39 -0
  7. package/.claude/agents/alphacouncil-macro_regime.md +31 -0
  8. package/.claude/agents/alphacouncil-market_data.md +37 -0
  9. package/.claude/agents/alphacouncil-market_narrative.md +45 -0
  10. package/.claude/agents/alphacouncil-news_industry_management.md +49 -0
  11. package/.claude/agents/alphacouncil-portfolio_manager.md +22 -0
  12. package/.claude/agents/alphacouncil-quant_factor.md +38 -0
  13. package/.claude/agents/alphacouncil-social_pulse.md +49 -0
  14. package/.claude/agents/alphacouncil-valuation_long_short.md +45 -0
  15. package/.claude-plugin/marketplace.json +30 -0
  16. package/.claude-plugin/plugin.json +28 -0
  17. package/.codex-plugin/plugin.json +32 -0
  18. package/.grok/agents/alphacouncil-bear_researcher.md +41 -0
  19. package/.grok/agents/alphacouncil-bull_researcher.md +42 -0
  20. package/.grok/agents/alphacouncil-earnings_deep_dive.md +50 -0
  21. package/.grok/agents/alphacouncil-forward_expectations.md +49 -0
  22. package/.grok/agents/alphacouncil-ib_event_analysis.md +41 -0
  23. package/.grok/agents/alphacouncil-insider_sec.md +40 -0
  24. package/.grok/agents/alphacouncil-macro_regime.md +32 -0
  25. package/.grok/agents/alphacouncil-market_data.md +38 -0
  26. package/.grok/agents/alphacouncil-market_narrative.md +46 -0
  27. package/.grok/agents/alphacouncil-news_industry_management.md +50 -0
  28. package/.grok/agents/alphacouncil-portfolio_manager.md +24 -0
  29. package/.grok/agents/alphacouncil-quant_factor.md +39 -0
  30. package/.grok/agents/alphacouncil-social_pulse.md +50 -0
  31. package/.grok/agents/alphacouncil-valuation_long_short.md +46 -0
  32. package/.grok/config.toml +4 -0
  33. package/.mcp.json +11 -0
  34. package/.opencode/agent/alphacouncil-bear_researcher.md +45 -0
  35. package/.opencode/agent/alphacouncil-bull_researcher.md +46 -0
  36. package/.opencode/agent/alphacouncil-earnings_deep_dive.md +54 -0
  37. package/.opencode/agent/alphacouncil-forward_expectations.md +53 -0
  38. package/.opencode/agent/alphacouncil-ib_event_analysis.md +45 -0
  39. package/.opencode/agent/alphacouncil-insider_sec.md +44 -0
  40. package/.opencode/agent/alphacouncil-macro_regime.md +36 -0
  41. package/.opencode/agent/alphacouncil-market_data.md +42 -0
  42. package/.opencode/agent/alphacouncil-market_narrative.md +50 -0
  43. package/.opencode/agent/alphacouncil-news_industry_management.md +54 -0
  44. package/.opencode/agent/alphacouncil-portfolio_manager.md +28 -0
  45. package/.opencode/agent/alphacouncil-quant_factor.md +43 -0
  46. package/.opencode/agent/alphacouncil-social_pulse.md +54 -0
  47. package/.opencode/agent/alphacouncil-valuation_long_short.md +50 -0
  48. package/AGENTS.md +96 -0
  49. package/CHANGELOG.md +112 -0
  50. package/CLAUDE.md +144 -0
  51. package/LICENSE +21 -0
  52. package/README.ja.md +282 -0
  53. package/README.md +361 -0
  54. package/README.zh-CN.md +282 -0
  55. package/data/industry-map.json +74 -0
  56. package/docs/attribution.md +99 -0
  57. package/docs/personas.md +59 -0
  58. package/docs/report-contract.md +110 -0
  59. package/mcp/lib/codex.mjs +152 -0
  60. package/mcp/lib/constants.mjs +139 -0
  61. package/mcp/lib/council-options.mjs +111 -0
  62. package/mcp/lib/errors.mjs +46 -0
  63. package/mcp/lib/feeds.mjs +140 -0
  64. package/mcp/lib/fsutil.mjs +69 -0
  65. package/mcp/lib/gates.mjs +208 -0
  66. package/mcp/lib/grounding.mjs +252 -0
  67. package/mcp/lib/headings.mjs +65 -0
  68. package/mcp/lib/industry.mjs +208 -0
  69. package/mcp/lib/lang.mjs +24 -0
  70. package/mcp/lib/macro.mjs +167 -0
  71. package/mcp/lib/markdown.mjs +337 -0
  72. package/mcp/lib/markets-kr-jp.mjs +180 -0
  73. package/mcp/lib/markets.mjs +261 -0
  74. package/mcp/lib/narrative.mjs +235 -0
  75. package/mcp/lib/options.mjs +216 -0
  76. package/mcp/lib/orchestrator.mjs +541 -0
  77. package/mcp/lib/output-modes.mjs +144 -0
  78. package/mcp/lib/packets.mjs +256 -0
  79. package/mcp/lib/personas/frontmatter.mjs +80 -0
  80. package/mcp/lib/personas/registry.mjs +215 -0
  81. package/mcp/lib/preflight.mjs +174 -0
  82. package/mcp/lib/prompts.mjs +151 -0
  83. package/mcp/lib/quotes.mjs +108 -0
  84. package/mcp/lib/rpc.mjs +737 -0
  85. package/mcp/lib/run-store.mjs +140 -0
  86. package/mcp/lib/screen.mjs +283 -0
  87. package/mcp/lib/sec.mjs +131 -0
  88. package/mcp/lib/social.mjs +261 -0
  89. package/mcp/lib/tables.mjs +150 -0
  90. package/mcp/lib/text.mjs +27 -0
  91. package/mcp/lib/weights.mjs +150 -0
  92. package/mcp/server.mjs +92 -0
  93. package/opencode.json +20 -0
  94. package/package.json +61 -0
  95. package/personas/_shared/_debate_base.md +46 -0
  96. package/personas/_shared/_evidence_base.md +56 -0
  97. package/personas/_shared/_master_base.md +77 -0
  98. package/personas/analysts/earnings_deep_dive.md +118 -0
  99. package/personas/analysts/forward_expectations.md +115 -0
  100. package/personas/analysts/ib_event_analysis.md +100 -0
  101. package/personas/analysts/insider_sec.md +98 -0
  102. package/personas/analysts/macro_regime.md +66 -0
  103. package/personas/analysts/market_data.md +94 -0
  104. package/personas/analysts/market_narrative.md +94 -0
  105. package/personas/analysts/news_industry_management.md +117 -0
  106. package/personas/analysts/quant_factor.md +97 -0
  107. package/personas/analysts/social_pulse.md +102 -0
  108. package/personas/analysts/valuation_long_short.md +109 -0
  109. package/personas/debate/bear_researcher.md +96 -0
  110. package/personas/debate/bull_researcher.md +98 -0
  111. package/personas/debate/portfolio_manager.md +64 -0
  112. package/personas/masters/masters-adversarial/burry.md +137 -0
  113. package/personas/masters/masters-adversarial/dalio.md +139 -0
  114. package/personas/masters/masters-adversarial/druckenmiller.md +144 -0
  115. package/personas/masters/masters-adversarial/short_seller.md +145 -0
  116. package/personas/masters/masters-adversarial/soros.md +137 -0
  117. package/personas/masters/masters-modern/aschenbrenner.md +147 -0
  118. package/personas/masters/masters-options/natenberg.md +168 -0
  119. package/personas/masters/masters-options/sinclair.md +166 -0
  120. package/personas/masters/masters-options/taleb.md +163 -0
  121. package/personas/masters/masters-quant/asness.md +142 -0
  122. package/personas/masters/masters-quant/simons.md +143 -0
  123. package/personas/masters/masters-quant/thorp.md +143 -0
  124. package/personas/masters/masters-value/buffett.md +123 -0
  125. package/personas/masters/masters-value/duan_yongping.md +142 -0
  126. package/personas/masters/masters-value/li_lu.md +146 -0
  127. package/personas/masters/masters-value/munger.md +117 -0
  128. package/personas/masters/masters-value-classic/fisher.md +140 -0
  129. package/personas/masters/masters-value-classic/graham.md +137 -0
  130. package/personas/masters/masters-value-classic/klarman.md +138 -0
  131. package/personas/masters/masters-value-classic/lynch.md +133 -0
  132. package/personas/masters/masters-value-classic/marks.md +145 -0
  133. package/personas/verifiers/rederivation.md +97 -0
  134. package/personas/verifiers/refuter.md +99 -0
  135. package/personas/verifiers/source_fidelity.md +91 -0
  136. package/skills/agent-skills-governance/SKILL.md +42 -0
  137. package/skills/alphacouncil-agent/SKILL.md +259 -0
  138. package/skills/investment-banking/SKILL.md +70 -0
  139. package/skills/public-equity-investing/SKILL.md +74 -0
@@ -0,0 +1,216 @@
1
+ import { LIMITS } from "./constants.mjs";
2
+ import { fetchText } from "./quotes.mjs";
3
+
4
+ /**
5
+ * Keyless delayed options chains from CBOE.
6
+ *
7
+ * The options bench (Taleb / Natenberg / Sinclair) was written to refuse to name an IV
8
+ * because the pipeline had no chain feed, and a model asked for one anyway will supply a
9
+ * number from training data that reads exactly like a live one. CBOE's delayed-quotes
10
+ * endpoint removes that gap: no key, full Greeks, open interest, ~3.5k contracts a name.
11
+ *
12
+ * What it still cannot give is IV *history*, so "IV is in the 80th percentile" remains
13
+ * uncomputable here and must stay an open question rather than becoming a guess.
14
+ */
15
+
16
+ const CBOE = (symbol) => `https://cdn.cboe.com/api/global/delayed_quotes/options/${encodeURIComponent(symbol)}.json`;
17
+
18
+ /** OSI-style contract symbol: root, YYMMDD, C|P, strike in thousandths. */
19
+ const CONTRACT = /^([A-Z]+)(\d{2})(\d{2})(\d{2})([CP])(\d{8})$/;
20
+
21
+ export function parseContract(option) {
22
+ const m = CONTRACT.exec(String(option || ""));
23
+ if (!m) return null;
24
+ const [, root, yy, mm, dd, right, strike] = m;
25
+ return {
26
+ root,
27
+ expiry: `20${yy}-${mm}-${dd}`,
28
+ right: right === "C" ? "call" : "put",
29
+ strike: Number(strike) / 1000,
30
+ };
31
+ }
32
+
33
+ const daysBetween = (fromIso, toIso) =>
34
+ Math.round((Date.parse(`${toIso}T00:00:00Z`) - Date.parse(`${fromIso}T00:00:00Z`)) / 86400000);
35
+
36
+ /**
37
+ * Is this row usable as a volatility observation?
38
+ *
39
+ * CBOE returns iv 0 for expired and deep-in-the-money contracts. Passing those through
40
+ * would put a hard zero into an IV term structure, which is not a low volatility reading
41
+ * -- it is a missing one, and it looks identical to a real number downstream.
42
+ */
43
+ const usable = (row) => row.iv > 0 && Number.isFinite(row.iv) && row.dte > 0;
44
+
45
+ const median = (xs) => {
46
+ if (!xs.length) return null;
47
+ const s = [...xs].sort((a, b) => a - b);
48
+ const mid = s.length >> 1;
49
+ return s.length % 2 ? s[mid] : (s[mid - 1] + s[mid]) / 2;
50
+ };
51
+
52
+ const round = (n, places = 4) =>
53
+ Number.isFinite(n) ? Number(n.toFixed(places)) : null;
54
+
55
+ /** The contract closest to a target delta on one side of one expiry. */
56
+ function nearestDelta(rows, expiry, right, targetAbsDelta) {
57
+ const side = rows.filter((r) => r.expiry === expiry && r.right === right && Number.isFinite(r.delta));
58
+ if (!side.length) return null;
59
+ return side.reduce((best, r) =>
60
+ Math.abs(Math.abs(r.delta) - targetAbsDelta) < Math.abs(Math.abs(best.delta) - targetAbsDelta) ? r : best);
61
+ }
62
+
63
+ /** Rows for one expiry ordered by distance from spot, nearest first. */
64
+ const byMoneyness = (rows, expiry, right, spot) =>
65
+ rows.filter((r) => r.expiry === expiry && r.right === right)
66
+ .sort((a, b) => Math.abs(a.strike - spot) - Math.abs(b.strike - spot));
67
+
68
+ export function summarizeChain(payload, { asOf, maxExpiries = 8 } = {}) {
69
+ const data = payload?.data;
70
+ if (!data || !Array.isArray(data.options)) return null;
71
+ const spot = Number(data.close) || Number(data.last_trade_price) || null;
72
+ const today = asOf || new Date().toISOString().slice(0, 10);
73
+
74
+ const all = data.options.map((o) => {
75
+ const c = parseContract(o.option);
76
+ if (!c) return null;
77
+ return {
78
+ ...c,
79
+ dte: daysBetween(today, c.expiry),
80
+ iv: Number(o.iv),
81
+ delta: Number(o.delta),
82
+ gamma: Number(o.gamma),
83
+ theta: Number(o.theta),
84
+ vega: Number(o.vega),
85
+ oi: Number(o.open_interest) || 0,
86
+ volume: Number(o.volume) || 0,
87
+ bid: Number(o.bid) || 0,
88
+ ask: Number(o.ask) || 0,
89
+ };
90
+ }).filter(Boolean);
91
+
92
+ const live = all.filter(usable);
93
+ const expiries = [...new Set(live.map((r) => r.expiry))].sort().slice(0, maxExpiries);
94
+
95
+ // ATM implied vol per expiry -- the term structure, which is the one thing the options
96
+ // bench needs before it can say whether a structure is cheap or expensive.
97
+ const term = expiries.map((expiry) => {
98
+ const call = byMoneyness(live, expiry, "call", spot)[0];
99
+ const put = byMoneyness(live, expiry, "put", spot)[0];
100
+ const ivs = [call?.iv, put?.iv].filter((v) => v > 0);
101
+ return {
102
+ expiry,
103
+ dte: daysBetween(today, expiry),
104
+ atm_strike: call?.strike ?? put?.strike ?? null,
105
+ atm_iv: ivs.length ? round(ivs.reduce((a, b) => a + b, 0) / ivs.length) : null,
106
+ };
107
+ }).filter((t) => t.atm_iv !== null);
108
+
109
+ // Skew and the headline IV are read from the first expiry at least a week out, not from
110
+ // the nearest one. A one-day contract prices pin risk and discreteness rather than
111
+ // volatility: on a live MU chain the 1-DTE ATM printed 69.6% between neighbours at 98.7%
112
+ // and 105.2%. Quoting that as "front ATM IV" hands the reader the least reliable number
113
+ // on the board as the summary of the whole surface.
114
+ const MIN_REFERENCE_DTE = 7;
115
+ const reference = term.find((t) => t.dte >= MIN_REFERENCE_DTE) || term[term.length - 1] || null;
116
+ const front = reference?.expiry;
117
+ const put25 = front ? nearestDelta(live, front, "put", 0.25) : null;
118
+ const call25 = front ? nearestDelta(live, front, "call", 0.25) : null;
119
+ const skew = put25 && call25 ? round(put25.iv - call25.iv) : null;
120
+
121
+ const callOi = all.filter((r) => r.right === "call").reduce((a, r) => a + r.oi, 0);
122
+ const putOi = all.filter((r) => r.right === "put").reduce((a, r) => a + r.oi, 0);
123
+ const callVol = all.filter((r) => r.right === "call").reduce((a, r) => a + r.volume, 0);
124
+ const putVol = all.filter((r) => r.right === "put").reduce((a, r) => a + r.volume, 0);
125
+
126
+ // Where the open interest actually sits. Large concentrations act as reference points and
127
+ // are far more informative than any single contract's price.
128
+ const byStrike = new Map();
129
+ for (const r of all) byStrike.set(r.strike, (byStrike.get(r.strike) || 0) + r.oi);
130
+ const oiStrikes = [...byStrike.entries()]
131
+ .sort((a, b) => b[1] - a[1]).slice(0, 6)
132
+ .map(([strike, oi]) => ({ strike, open_interest: oi, vs_spot_pct: spot ? round(((strike - spot) / spot) * 100, 1) : null }));
133
+
134
+ // Sinclair's point: a theoretical edge dies in the spread. Quote it before anyone proposes
135
+ // a structure, measured where it matters -- near the money on the front expiry.
136
+ const atmRows = front ? byMoneyness(live, front, "call", spot).slice(0, 6).concat(byMoneyness(live, front, "put", spot).slice(0, 6)) : [];
137
+ const spreads = atmRows
138
+ .filter((r) => r.ask > 0 && r.bid >= 0 && (r.bid + r.ask) > 0)
139
+ .map((r) => ((r.ask - r.bid) / ((r.ask + r.bid) / 2)) * 100);
140
+
141
+ return {
142
+ source: "CBOE delayed quotes (cdn.cboe.com), keyless",
143
+ as_of: today,
144
+ delayed: true,
145
+ spot,
146
+ contracts_total: all.length,
147
+ contracts_with_iv: live.length,
148
+ expiries_available: [...new Set(all.map((r) => r.expiry))].length,
149
+ term_structure: term,
150
+ // Which expiry the headline numbers below were read from, and why it may not be the
151
+ // nearest one. Without this the reader cannot tell that a short expiry was skipped.
152
+ reference_expiry: reference ? {
153
+ expiry: reference.expiry,
154
+ dte: reference.dte,
155
+ atm_iv: reference.atm_iv,
156
+ note: term[0] && term[0].dte < MIN_REFERENCE_DTE
157
+ ? `Nearest expiry is ${term[0].expiry} at ${term[0].dte}d and was skipped for the headline: `
158
+ + "under a week, an ATM implied vol reflects pin risk and discrete pricing more than volatility. "
159
+ + "It remains in term_structure."
160
+ : "Nearest expiry is at least a week out and is used directly.",
161
+ } : null,
162
+ skew_25delta: skew === null ? null : {
163
+ expiry: front,
164
+ put_iv: round(put25.iv),
165
+ call_iv: round(call25.iv),
166
+ put_minus_call: skew,
167
+ reading: skew > 0 ? "downside protection bid (normal for equity)" : "upside bid (unusual; check for a takeover or squeeze narrative)",
168
+ },
169
+ open_interest: {
170
+ calls: callOi,
171
+ puts: putOi,
172
+ put_call_ratio: callOi ? round(putOi / callOi, 3) : null,
173
+ },
174
+ volume: {
175
+ calls: callVol,
176
+ puts: putVol,
177
+ put_call_ratio: callVol ? round(putVol / callVol, 3) : null,
178
+ },
179
+ largest_open_interest_strikes: oiStrikes,
180
+ atm_spread_pct_of_mid: median(spreads) === null ? null : round(median(spreads), 1),
181
+ // Named explicitly so the bench treats it as a gap rather than filling it in.
182
+ unavailable: [
183
+ "IV percentile or rank: this endpoint returns a snapshot, not history, so no statement "
184
+ + "about IV being high or low versus its own past can be made from this data alone.",
185
+ "realised volatility: not in this feed; compute it from price history if the view needs it.",
186
+ ],
187
+ caveat: "Delayed quotes, not live. Contracts reporting iv = 0 (expired or deep in the money) "
188
+ + "are excluded from the term structure rather than read as zero volatility.",
189
+ };
190
+ }
191
+
192
+ export async function fetchOptionsChain(symbol, { asOf } = {}) {
193
+ const sym = String(symbol || "").trim().toUpperCase();
194
+ if (!/^[A-Z][A-Z0-9.\-]{0,9}$/.test(sym)) {
195
+ return { symbol, available: false, reason: `"${symbol}" is not a symbol this feed accepts` };
196
+ }
197
+ let text;
198
+ try {
199
+ text = await fetchText(CBOE(sym), LIMITS.QUOTE_FETCH_MS * 3);
200
+ } catch (error) {
201
+ return {
202
+ symbol: sym, available: false,
203
+ reason: `CBOE delayed quotes unreachable: ${String(error?.message || error)}`,
204
+ };
205
+ }
206
+ let payload;
207
+ try {
208
+ payload = JSON.parse(text);
209
+ } catch {
210
+ // A 404 from the CDN is HTML, which is the normal answer for a name with no listed options.
211
+ return { symbol: sym, available: false, reason: `no listed options found for ${sym} on CBOE (non-US listings are generally absent)` };
212
+ }
213
+ const summary = summarizeChain(payload, { asOf });
214
+ if (!summary) return { symbol: sym, available: false, reason: `CBOE returned no option rows for ${sym}` };
215
+ return { symbol: sym, available: true, ...summary };
216
+ }