agentbnb 5.1.0 → 5.1.2

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.
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Orchestrator: ties together all 5 analysis modules + thesis.
3
+ * All heavy computation happens here (no LLM until thesis step).
4
+ */
5
+
6
+ import { fetchAllData } from './api/alpha-vantage.js';
7
+ import { calculateValuation } from './analysis/valuation.js';
8
+ import { analyzeTechnicals } from './analysis/technicals.js';
9
+ import { analyzeFinancialHealth } from './analysis/financial-health.js';
10
+ import { analyzeSentiment } from './analysis/sentiment.js';
11
+ import { generateCompositeSignal } from './analysis/signal.js';
12
+ import { generateThesis } from './llm/thesis.js';
13
+ import type { InvestmentStyle } from './analysis/signal.js';
14
+
15
+ export interface AnalysisOptions {
16
+ ticker: string;
17
+ depth?: 'quick' | 'standard' | 'deep';
18
+ style?: InvestmentStyle;
19
+ apiKey: string;
20
+ }
21
+
22
+ export interface AnalysisResult {
23
+ ticker: string;
24
+ analyzed_at: string;
25
+ depth: string;
26
+ style: string;
27
+
28
+ // Top-level verdict
29
+ signal: string;
30
+ confidence: number;
31
+ composite_score: number;
32
+
33
+ // Module results
34
+ valuation: {
35
+ verdict: string;
36
+ composite: number;
37
+ pe_score: number;
38
+ peg_score: number;
39
+ fcf_yield_score: number;
40
+ ev_ebitda_score: number;
41
+ ps_score: number;
42
+ raw: Record<string, number>;
43
+ };
44
+ technicals: {
45
+ regime: string;
46
+ composite: number;
47
+ trend_score: number;
48
+ momentum_score: number;
49
+ volatility_score: number;
50
+ strength_score: number;
51
+ signals: Array<{ type: string; name: string; strength: number; description: string }>;
52
+ raw: Record<string, number>;
53
+ };
54
+ financials: {
55
+ composite: number;
56
+ profitability_score: number;
57
+ growth_score: number;
58
+ leverage_score: number;
59
+ efficiency_score: number;
60
+ red_flags: string[];
61
+ green_flags: string[];
62
+ raw: Record<string, number>;
63
+ };
64
+ sentiment: {
65
+ composite: number;
66
+ news_sentiment: number;
67
+ news_volume: number;
68
+ bullish_ratio: number;
69
+ key_headlines: string[];
70
+ topic_breakdown: Record<string, number>;
71
+ };
72
+
73
+ // LLM thesis
74
+ thesis: {
75
+ bull_case: string;
76
+ bear_case: string;
77
+ catalysts: string[];
78
+ risks: string[];
79
+ time_horizon: string;
80
+ entry_strategy: string;
81
+ };
82
+
83
+ // Price levels
84
+ support_levels: number[];
85
+ resistance_levels: number[];
86
+ key_factors: string[];
87
+ risk_factors: string[];
88
+ data_completeness: number;
89
+
90
+ // Company metadata
91
+ company: {
92
+ name: string;
93
+ sector: string;
94
+ industry: string;
95
+ market_cap: string;
96
+ price: number;
97
+ analyst_target: number;
98
+ };
99
+ }
100
+
101
+ export async function runAnalysis(options: AnalysisOptions): Promise<AnalysisResult> {
102
+ const { ticker, depth = 'standard', style = 'hybrid', apiKey } = options;
103
+
104
+ // Step 1: Fetch all API data (12 calls, serialized)
105
+ const data = await fetchAllData(ticker, apiKey);
106
+
107
+ // Step 2: Compute all modules (pure math, no LLM)
108
+ const valuation = calculateValuation(data.overview);
109
+ const technicals = analyzeTechnicals(
110
+ data.daily, data.rsi, data.macd, data.bbands, data.stoch, data.adx,
111
+ );
112
+ const financials = analyzeFinancialHealth(
113
+ data.overview, data.income, data.balance, data.cashflow, data.earnings,
114
+ );
115
+ const sentiment = analyzeSentiment(data.news, ticker);
116
+ const composite = generateCompositeSignal(
117
+ valuation, technicals, financials, sentiment, data.daily, style,
118
+ );
119
+
120
+ // Step 3: LLM thesis (~200ms, Gemini Flash)
121
+ const thesis = await generateThesis(
122
+ ticker, data.overview, composite, valuation, technicals, financials, sentiment,
123
+ );
124
+
125
+ // Step 4: Assemble result
126
+ const price = parseFloat(data.daily[0]?.adjustedClose ?? data.daily[0]?.close ?? '0');
127
+ const analystTarget = parseFloat(data.overview.AnalystTargetPrice ?? '0');
128
+ const marketCap = parseFloat(data.overview.MarketCapitalization ?? '0');
129
+ const mcStr =
130
+ marketCap >= 1e12 ? `$${(marketCap / 1e12).toFixed(2)}T`
131
+ : marketCap >= 1e9 ? `$${(marketCap / 1e9).toFixed(2)}B`
132
+ : marketCap >= 1e6 ? `$${(marketCap / 1e6).toFixed(2)}M`
133
+ : `$${marketCap.toFixed(0)}`;
134
+
135
+ return {
136
+ ticker: ticker.toUpperCase(),
137
+ analyzed_at: new Date().toISOString(),
138
+ depth,
139
+ style,
140
+
141
+ signal: composite.signal,
142
+ confidence: composite.confidence,
143
+ composite_score: composite.composite_score,
144
+
145
+ valuation: {
146
+ verdict: valuation.verdict,
147
+ composite: parseFloat(valuation.composite.toFixed(1)),
148
+ pe_score: parseFloat(valuation.pe_score.toFixed(1)),
149
+ peg_score: parseFloat(valuation.peg_score.toFixed(1)),
150
+ fcf_yield_score: parseFloat(valuation.fcf_yield_score.toFixed(1)),
151
+ ev_ebitda_score: parseFloat(valuation.ev_ebitda_score.toFixed(1)),
152
+ ps_score: parseFloat(valuation.ps_score.toFixed(1)),
153
+ raw: {
154
+ pe: valuation.raw.pe,
155
+ peg: valuation.raw.peg,
156
+ ps: valuation.raw.ps,
157
+ fcf_yield_pct: parseFloat(valuation.raw.fcfYieldPct.toFixed(2)),
158
+ },
159
+ },
160
+
161
+ technicals: {
162
+ regime: technicals.regime,
163
+ composite: parseFloat(technicals.composite.toFixed(1)),
164
+ trend_score: parseFloat(technicals.trend_score.toFixed(1)),
165
+ momentum_score: parseFloat(technicals.momentum_score.toFixed(1)),
166
+ volatility_score: parseFloat(technicals.volatility_score.toFixed(1)),
167
+ strength_score: parseFloat(technicals.strength_score.toFixed(1)),
168
+ signals: technicals.signals,
169
+ raw: {
170
+ rsi: parseFloat(technicals.raw.rsi.toFixed(1)),
171
+ macd_hist: parseFloat(technicals.raw.macdHist.toFixed(4)),
172
+ adx: parseFloat(technicals.raw.adx.toFixed(1)),
173
+ bb_position: parseFloat(technicals.raw.bbPosition.toFixed(2)),
174
+ price,
175
+ sma20: parseFloat(technicals.raw.sma20.toFixed(2)),
176
+ sma50: parseFloat(technicals.raw.sma50.toFixed(2)),
177
+ sma200: parseFloat(technicals.raw.sma200.toFixed(2)),
178
+ },
179
+ },
180
+
181
+ financials: {
182
+ composite: parseFloat(financials.composite.toFixed(1)),
183
+ profitability_score: parseFloat(financials.profitability_score.toFixed(1)),
184
+ growth_score: parseFloat(financials.growth_score.toFixed(1)),
185
+ leverage_score: parseFloat(financials.leverage_score.toFixed(1)),
186
+ efficiency_score: parseFloat(financials.efficiency_score.toFixed(1)),
187
+ red_flags: financials.red_flags,
188
+ green_flags: financials.green_flags,
189
+ raw: {
190
+ gross_margin_pct: parseFloat(financials.raw.grossMarginPct.toFixed(1)),
191
+ operating_margin_pct: parseFloat(financials.raw.operatingMarginPct.toFixed(1)),
192
+ net_margin_pct: parseFloat(financials.raw.netMarginPct.toFixed(1)),
193
+ roe: parseFloat(financials.raw.roe.toFixed(1)),
194
+ debt_to_equity: parseFloat(financials.raw.debtToEquity.toFixed(2)),
195
+ current_ratio: parseFloat(financials.raw.currentRatio.toFixed(2)),
196
+ revenue_growth_pct: parseFloat(financials.raw.revenueGrowthPct.toFixed(1)),
197
+ earnings_growth_pct: parseFloat(financials.raw.earningsGrowthPct.toFixed(1)),
198
+ consecutive_beats: financials.raw.consecutiveBeats,
199
+ },
200
+ },
201
+
202
+ sentiment: {
203
+ composite: parseFloat(sentiment.composite.toFixed(1)),
204
+ news_sentiment: parseFloat(sentiment.news_sentiment.toFixed(3)),
205
+ news_volume: sentiment.news_volume,
206
+ bullish_ratio: parseFloat(sentiment.bullish_ratio.toFixed(2)),
207
+ key_headlines: sentiment.key_headlines,
208
+ topic_breakdown: sentiment.topic_breakdown,
209
+ },
210
+
211
+ thesis,
212
+
213
+ support_levels: composite.support_levels,
214
+ resistance_levels: composite.resistance_levels,
215
+ key_factors: composite.key_factors,
216
+ risk_factors: composite.risk_factors,
217
+ data_completeness: composite.data_completeness,
218
+
219
+ company: {
220
+ name: data.overview.Name ?? ticker,
221
+ sector: data.overview.Sector ?? 'N/A',
222
+ industry: data.overview.Industry ?? 'N/A',
223
+ market_cap: mcStr,
224
+ price,
225
+ analyst_target: analystTarget,
226
+ },
227
+ };
228
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "sourceMap": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "noUncheckedIndexedAccess": true,
16
+ "noUnusedLocals": true,
17
+ "noUnusedParameters": true
18
+ },
19
+ "include": ["src/**/*.ts"],
20
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
21
+ }