market-data-analyzer 2.0.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.

Potentially problematic release.


This version of market-data-analyzer might be problematic. Click here for more details.

Files changed (58) hide show
  1. package/README.md +159 -0
  2. package/dist/index.d.ts +12 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +267 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/tools/analyze_portfolio.d.ts +14 -0
  7. package/dist/tools/analyze_portfolio.d.ts.map +1 -0
  8. package/dist/tools/analyze_portfolio.js +155 -0
  9. package/dist/tools/analyze_portfolio.js.map +1 -0
  10. package/dist/tools/analyze_stock.d.ts +8 -0
  11. package/dist/tools/analyze_stock.d.ts.map +1 -0
  12. package/dist/tools/analyze_stock.js +211 -0
  13. package/dist/tools/analyze_stock.js.map +1 -0
  14. package/dist/tools/compare_assets.d.ts +8 -0
  15. package/dist/tools/compare_assets.d.ts.map +1 -0
  16. package/dist/tools/compare_assets.js +138 -0
  17. package/dist/tools/compare_assets.js.map +1 -0
  18. package/dist/tools/crypto_analysis.d.ts +8 -0
  19. package/dist/tools/crypto_analysis.d.ts.map +1 -0
  20. package/dist/tools/crypto_analysis.js +192 -0
  21. package/dist/tools/crypto_analysis.js.map +1 -0
  22. package/dist/tools/market_overview.d.ts +8 -0
  23. package/dist/tools/market_overview.d.ts.map +1 -0
  24. package/dist/tools/market_overview.js +223 -0
  25. package/dist/tools/market_overview.js.map +1 -0
  26. package/dist/tools/screen_stocks.d.ts +19 -0
  27. package/dist/tools/screen_stocks.d.ts.map +1 -0
  28. package/dist/tools/screen_stocks.js +122 -0
  29. package/dist/tools/screen_stocks.js.map +1 -0
  30. package/dist/types.d.ts +158 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +5 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/utils/api.d.ts +37 -0
  35. package/dist/utils/api.d.ts.map +1 -0
  36. package/dist/utils/api.js +228 -0
  37. package/dist/utils/api.js.map +1 -0
  38. package/dist/utils/cache.d.ts +20 -0
  39. package/dist/utils/cache.d.ts.map +1 -0
  40. package/dist/utils/cache.js +52 -0
  41. package/dist/utils/cache.js.map +1 -0
  42. package/dist/utils/math.d.ts +30 -0
  43. package/dist/utils/math.d.ts.map +1 -0
  44. package/dist/utils/math.js +300 -0
  45. package/dist/utils/math.js.map +1 -0
  46. package/package.json +30 -0
  47. package/src/index.ts +329 -0
  48. package/src/tools/analyze_portfolio.ts +204 -0
  49. package/src/tools/analyze_stock.ts +204 -0
  50. package/src/tools/compare_assets.ts +181 -0
  51. package/src/tools/crypto_analysis.ts +221 -0
  52. package/src/tools/market_overview.ts +236 -0
  53. package/src/tools/screen_stocks.ts +154 -0
  54. package/src/types.ts +175 -0
  55. package/src/utils/api.ts +262 -0
  56. package/src/utils/cache.ts +65 -0
  57. package/src/utils/math.ts +332 -0
  58. package/tsconfig.json +19 -0
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # Market Data Analyzer MCP Server
2
+
3
+ Finance-focused MCP server providing live market data analysis. Analyze stocks with technical indicators, screen for opportunities, track portfolios, compare assets, monitor market conditions, and analyze crypto -- all powered by free APIs (Yahoo Finance + CoinGecko).
4
+
5
+ ## Pricing
6
+
7
+ | Plan | Price | Includes |
8
+ |------|-------|----------|
9
+ | **Basic** | $15/mo | `analyze_stock`, `screen_stocks`, `market_overview` |
10
+ | **Pro** | $25/mo | All 6 tools + priority data refresh |
11
+
12
+ ## Tools
13
+
14
+ ### `analyze_stock`
15
+ Deep analysis of a stock symbol with live Yahoo Finance data.
16
+
17
+ **Output:** Price overview, SMA (20/50/200), RSI (14), MACD (12,26,9), support/resistance levels, golden/death cross detection, signal summary.
18
+
19
+ ```json
20
+ { "symbol": "AAPL" }
21
+ ```
22
+
23
+ ### `screen_stocks`
24
+ Screen ~70 popular stocks by criteria with live data.
25
+
26
+ **Filters:** Market cap range, P/E ratio, sector, volume threshold, price range.
27
+
28
+ ```json
29
+ {
30
+ "sector": "tech",
31
+ "max_pe": 40,
32
+ "min_market_cap": 500000000000,
33
+ "limit": 10
34
+ }
35
+ ```
36
+
37
+ ### `analyze_portfolio`
38
+ Analyze a portfolio of holdings with live price lookup.
39
+
40
+ **Output:** Total value, P&L per position, allocation %, sector breakdown, diversification score (HHI-based), concentration warnings.
41
+
42
+ ```json
43
+ {
44
+ "holdings": [
45
+ { "symbol": "AAPL", "shares": 100, "avg_cost": 150.00 },
46
+ { "symbol": "MSFT", "shares": 50, "avg_cost": 380.00 },
47
+ { "symbol": "JPM", "shares": 75, "avg_cost": 195.00 }
48
+ ]
49
+ }
50
+ ```
51
+
52
+ ### `compare_assets`
53
+ Compare 2-5 assets side by side over a configurable period.
54
+
55
+ **Output:** Returns, volatility, Sharpe ratio, max drawdown, correlation matrix, rankings.
56
+
57
+ ```json
58
+ {
59
+ "symbols": ["AAPL", "MSFT", "GOOGL"],
60
+ "period": "1y"
61
+ }
62
+ ```
63
+
64
+ ### `market_overview`
65
+ Live market snapshot with no arguments needed.
66
+
67
+ **Output:** Major indices (S&P 500, NASDAQ, DOW, Russell 2000), VIX interpretation, sector ETF performance, crypto & commodities, market sentiment score.
68
+
69
+ ```json
70
+ {}
71
+ ```
72
+
73
+ ### `crypto_analysis`
74
+ Crypto-specific analysis via CoinGecko free API.
75
+
76
+ **Output:** Price, 24h/7d/30d changes, volume, market cap, dominance, supply metrics, ATH/ATL, fear & greed approximation, global crypto market context.
77
+
78
+ ```json
79
+ { "symbol": "BTC" }
80
+ ```
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ npm install
86
+ npm run build
87
+ ```
88
+
89
+ ## Usage
90
+
91
+ ### Stdio transport (default)
92
+ ```bash
93
+ node dist/index.js
94
+ ```
95
+
96
+ ### SSE transport
97
+ ```bash
98
+ node dist/index.js --sse
99
+ # or with custom port
100
+ PORT=8080 node dist/index.js --sse
101
+ ```
102
+
103
+ ### Claude Desktop configuration
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "market-data-analyzer": {
108
+ "command": "node",
109
+ "args": ["/path/to/market-data-analyzer/dist/index.js"]
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### SSE endpoints
116
+ - `GET /sse` -- SSE connection endpoint
117
+ - `POST /messages?sessionId=<id>` -- Message endpoint
118
+ - `GET /health` -- Health check
119
+
120
+ ## Data Sources
121
+
122
+ | Source | Used By | Rate Limits |
123
+ |--------|---------|-------------|
124
+ | Yahoo Finance (free) | `analyze_stock`, `screen_stocks`, `analyze_portfolio`, `compare_assets`, `market_overview` | Unofficial, best-effort |
125
+ | CoinGecko (free API) | `crypto_analysis` | 10-30 calls/min |
126
+
127
+ All price data is cached in-memory with a 5-minute TTL to minimize API calls and improve response times.
128
+
129
+ ## Technical Details
130
+
131
+ - **Runtime:** Node.js 18+
132
+ - **Language:** TypeScript (strict mode, ES modules)
133
+ - **Protocol:** Model Context Protocol (MCP) via `@modelcontextprotocol/sdk`
134
+ - **Dependencies:** `@modelcontextprotocol/sdk` + `zod` only
135
+ - **Caching:** In-memory with 5-minute TTL for all price data
136
+ - **Calculations:** SMA, EMA, RSI, MACD, Sharpe ratio, max drawdown, HHI diversification, support/resistance -- all implemented from scratch
137
+
138
+ ## Project Structure
139
+
140
+ ```
141
+ src/
142
+ index.ts # Server setup, tool registration, transports
143
+ types.ts # TypeScript interfaces
144
+ tools/
145
+ analyze_stock.ts # Stock analysis with technical indicators
146
+ screen_stocks.ts # Stock screener with live data
147
+ analyze_portfolio.ts # Portfolio analytics
148
+ compare_assets.ts # Multi-asset comparison
149
+ market_overview.ts # Market snapshot
150
+ crypto_analysis.ts # Crypto analysis via CoinGecko
151
+ utils/
152
+ api.ts # Yahoo Finance + CoinGecko API helpers
153
+ cache.ts # In-memory TTL cache
154
+ math.ts # Financial math (SMA, RSI, MACD, etc.)
155
+ ```
156
+
157
+ ## License
158
+
159
+ MIT
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Market Data Analyzer -- MCP Server
4
+ *
5
+ * Finance-focused MCP server with live data from Yahoo Finance and CoinGecko.
6
+ * Tools: analyze_stock, screen_stocks, analyze_portfolio, compare_assets,
7
+ * market_overview, crypto_analysis.
8
+ *
9
+ * Transports: stdio (default) or SSE (--sse flag).
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
package/dist/index.js ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Market Data Analyzer -- MCP Server
4
+ *
5
+ * Finance-focused MCP server with live data from Yahoo Finance and CoinGecko.
6
+ * Tools: analyze_stock, screen_stocks, analyze_portfolio, compare_assets,
7
+ * market_overview, crypto_analysis.
8
+ *
9
+ * Transports: stdio (default) or SSE (--sse flag).
10
+ */
11
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
14
+ import { z } from "zod";
15
+ import http from "node:http";
16
+ import { handleAnalyzeStock } from "./tools/analyze_stock.js";
17
+ import { handleScreenStocks } from "./tools/screen_stocks.js";
18
+ import { handleAnalyzePortfolio } from "./tools/analyze_portfolio.js";
19
+ import { handleCompareAssets } from "./tools/compare_assets.js";
20
+ import { handleMarketOverview } from "./tools/market_overview.js";
21
+ import { handleCryptoAnalysis } from "./tools/crypto_analysis.js";
22
+ // ---------------------------------------------------------------------------
23
+ // Server setup
24
+ // ---------------------------------------------------------------------------
25
+ const server = new McpServer({
26
+ name: "market-data-analyzer",
27
+ version: "2.0.0",
28
+ });
29
+ // ---------------------------------------------------------------------------
30
+ // Tool: analyze_stock
31
+ // ---------------------------------------------------------------------------
32
+ server.tool("analyze_stock", "Deep analysis of a stock symbol: price, moving averages (SMA 20/50/200), RSI, MACD, support/resistance levels. Uses live Yahoo Finance data.", {
33
+ symbol: z
34
+ .string()
35
+ .describe("Stock ticker symbol (e.g. 'AAPL', 'MSFT', 'TSLA')"),
36
+ }, async ({ symbol }) => {
37
+ try {
38
+ const result = await handleAnalyzeStock(symbol.toUpperCase());
39
+ return { content: [{ type: "text", text: result }] };
40
+ }
41
+ catch (err) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: "text",
46
+ text: `Error analyzing ${symbol}: ${err instanceof Error ? err.message : String(err)}`,
47
+ },
48
+ ],
49
+ isError: true,
50
+ };
51
+ }
52
+ });
53
+ // ---------------------------------------------------------------------------
54
+ // Tool: screen_stocks
55
+ // ---------------------------------------------------------------------------
56
+ server.tool("screen_stocks", "Screen stocks by criteria: market cap range, P/E ratio, sector, volume threshold. Returns top matches with key metrics. Fetches live data from Yahoo Finance for ~70 popular stocks.", {
57
+ min_market_cap: z
58
+ .number()
59
+ .optional()
60
+ .describe("Minimum market cap in USD (e.g. 1000000000 for $1B)"),
61
+ max_market_cap: z.number().optional().describe("Maximum market cap in USD"),
62
+ min_pe: z.number().optional().describe("Minimum trailing P/E ratio"),
63
+ max_pe: z.number().optional().describe("Maximum trailing P/E ratio"),
64
+ sector: z
65
+ .string()
66
+ .optional()
67
+ .describe("Sector filter (partial match, e.g. 'tech', 'health', 'energy')"),
68
+ min_volume: z.number().optional().describe("Minimum daily trading volume"),
69
+ min_price: z.number().optional().describe("Minimum stock price"),
70
+ max_price: z.number().optional().describe("Maximum stock price"),
71
+ limit: z
72
+ .number()
73
+ .int()
74
+ .min(1)
75
+ .max(50)
76
+ .optional()
77
+ .describe("Max results to return (default: 25)"),
78
+ }, async (criteria) => {
79
+ try {
80
+ const result = await handleScreenStocks(criteria);
81
+ return { content: [{ type: "text", text: result }] };
82
+ }
83
+ catch (err) {
84
+ return {
85
+ content: [
86
+ {
87
+ type: "text",
88
+ text: `Error screening stocks: ${err instanceof Error ? err.message : String(err)}`,
89
+ },
90
+ ],
91
+ isError: true,
92
+ };
93
+ }
94
+ });
95
+ // ---------------------------------------------------------------------------
96
+ // Tool: analyze_portfolio
97
+ // ---------------------------------------------------------------------------
98
+ server.tool("analyze_portfolio", "Analyze a portfolio of holdings. Provide positions with symbol, shares, and average cost. Returns total value, P&L per position, allocation %, diversification score, and risk metrics. Fetches live prices from Yahoo Finance.", {
99
+ holdings: z
100
+ .array(z.object({
101
+ symbol: z.string().describe("Ticker symbol (e.g. 'AAPL')"),
102
+ shares: z.number().describe("Number of shares held"),
103
+ avg_cost: z.number().describe("Average cost per share"),
104
+ }))
105
+ .min(1)
106
+ .describe("Array of portfolio holdings"),
107
+ }, async ({ holdings }) => {
108
+ try {
109
+ const result = await handleAnalyzePortfolio(holdings);
110
+ return { content: [{ type: "text", text: result }] };
111
+ }
112
+ catch (err) {
113
+ return {
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: `Error analyzing portfolio: ${err instanceof Error ? err.message : String(err)}`,
118
+ },
119
+ ],
120
+ isError: true,
121
+ };
122
+ }
123
+ });
124
+ // ---------------------------------------------------------------------------
125
+ // Tool: compare_assets
126
+ // ---------------------------------------------------------------------------
127
+ server.tool("compare_assets", "Compare 2-5 assets side by side: returns, volatility, correlation, Sharpe ratio approximation over a given period. Uses Yahoo Finance historical data.", {
128
+ symbols: z
129
+ .array(z.string())
130
+ .min(2)
131
+ .max(5)
132
+ .describe("Array of 2-5 ticker symbols to compare (e.g. ['AAPL', 'MSFT', 'GOOGL'])"),
133
+ period: z
134
+ .enum(["1mo", "3mo", "6mo", "1y", "2y", "5y"])
135
+ .optional()
136
+ .describe("Comparison period (default: '6mo')"),
137
+ }, async ({ symbols, period }) => {
138
+ try {
139
+ const result = await handleCompareAssets(symbols.map((s) => s.toUpperCase()), period ?? "6mo");
140
+ return { content: [{ type: "text", text: result }] };
141
+ }
142
+ catch (err) {
143
+ return {
144
+ content: [
145
+ {
146
+ type: "text",
147
+ text: `Error comparing assets: ${err instanceof Error ? err.message : String(err)}`,
148
+ },
149
+ ],
150
+ isError: true,
151
+ };
152
+ }
153
+ });
154
+ // ---------------------------------------------------------------------------
155
+ // Tool: market_overview
156
+ // ---------------------------------------------------------------------------
157
+ server.tool("market_overview", "Current market snapshot: major indices (S&P 500, NASDAQ, DOW), sector performance via ETFs, market breadth indicators, VIX, crypto, and commodities. Live data from Yahoo Finance.", {}, async () => {
158
+ try {
159
+ const result = await handleMarketOverview();
160
+ return { content: [{ type: "text", text: result }] };
161
+ }
162
+ catch (err) {
163
+ return {
164
+ content: [
165
+ {
166
+ type: "text",
167
+ text: `Error fetching market overview: ${err instanceof Error ? err.message : String(err)}`,
168
+ },
169
+ ],
170
+ isError: true,
171
+ };
172
+ }
173
+ });
174
+ // ---------------------------------------------------------------------------
175
+ // Tool: crypto_analysis
176
+ // ---------------------------------------------------------------------------
177
+ server.tool("crypto_analysis", "Crypto-specific analysis: price, 24h volume, market dominance, fear/greed index approximation, supply metrics, ATH/ATL data. Uses CoinGecko free API.", {
178
+ symbol: z
179
+ .string()
180
+ .describe("Cryptocurrency symbol or name (e.g. 'BTC', 'ETH', 'SOL', 'bitcoin')"),
181
+ }, async ({ symbol }) => {
182
+ try {
183
+ const result = await handleCryptoAnalysis(symbol);
184
+ return { content: [{ type: "text", text: result }] };
185
+ }
186
+ catch (err) {
187
+ return {
188
+ content: [
189
+ {
190
+ type: "text",
191
+ text: `Error analyzing crypto ${symbol}: ${err instanceof Error ? err.message : String(err)}`,
192
+ },
193
+ ],
194
+ isError: true,
195
+ };
196
+ }
197
+ });
198
+ // ---------------------------------------------------------------------------
199
+ // Transport: stdio or SSE
200
+ // ---------------------------------------------------------------------------
201
+ async function main() {
202
+ const useSSE = process.argv.includes("--sse");
203
+ if (useSSE) {
204
+ const port = parseInt(process.env.PORT ?? "3000", 10);
205
+ const transports = new Map();
206
+ const httpServer = http.createServer(async (req, res) => {
207
+ // CORS headers
208
+ res.setHeader("Access-Control-Allow-Origin", "*");
209
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
210
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
211
+ if (req.method === "OPTIONS") {
212
+ res.writeHead(204);
213
+ res.end();
214
+ return;
215
+ }
216
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
217
+ if (url.pathname === "/sse" && req.method === "GET") {
218
+ const transport = new SSEServerTransport("/messages", res);
219
+ const sessionId = transport.sessionId;
220
+ transports.set(sessionId, transport);
221
+ res.on("close", () => {
222
+ transports.delete(sessionId);
223
+ });
224
+ await server.connect(transport);
225
+ return;
226
+ }
227
+ if (url.pathname === "/messages" && req.method === "POST") {
228
+ const sessionId = url.searchParams.get("sessionId");
229
+ if (!sessionId || !transports.has(sessionId)) {
230
+ res.writeHead(400, { "Content-Type": "application/json" });
231
+ res.end(JSON.stringify({ error: "Invalid or missing sessionId" }));
232
+ return;
233
+ }
234
+ const transport = transports.get(sessionId);
235
+ await transport.handlePostMessage(req, res);
236
+ return;
237
+ }
238
+ if (url.pathname === "/health") {
239
+ res.writeHead(200, { "Content-Type": "application/json" });
240
+ res.end(JSON.stringify({
241
+ status: "ok",
242
+ server: "market-data-analyzer",
243
+ version: "2.0.0",
244
+ }));
245
+ return;
246
+ }
247
+ res.writeHead(404, { "Content-Type": "application/json" });
248
+ res.end(JSON.stringify({ error: "Not found" }));
249
+ });
250
+ httpServer.listen(port, () => {
251
+ console.error(`Market Data Analyzer MCP server (SSE) listening on port ${port}`);
252
+ console.error(` SSE endpoint: http://localhost:${port}/sse`);
253
+ console.error(` Messages endpoint: http://localhost:${port}/messages`);
254
+ console.error(` Health check: http://localhost:${port}/health`);
255
+ });
256
+ }
257
+ else {
258
+ const transport = new StdioServerTransport();
259
+ await server.connect(transport);
260
+ console.error("Market Data Analyzer MCP server running on stdio");
261
+ }
262
+ }
263
+ main().catch((err) => {
264
+ console.error("Fatal error:", err);
265
+ process.exit(1);
266
+ });
267
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * analyze_portfolio -- Portfolio analytics with live prices.
3
+ *
4
+ * Takes an array of { symbol, shares, avg_cost } holdings, fetches
5
+ * current prices from Yahoo Finance, and returns P&L, allocation,
6
+ * diversification score, and risk metrics.
7
+ */
8
+ export interface PortfolioHolding {
9
+ symbol: string;
10
+ shares: number;
11
+ avg_cost: number;
12
+ }
13
+ export declare function handleAnalyzePortfolio(holdings: PortfolioHolding[]): Promise<string>;
14
+ //# sourceMappingURL=analyze_portfolio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze_portfolio.d.ts","sourceRoot":"","sources":["../../src/tools/analyze_portfolio.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgBD,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,MAAM,CAAC,CA0KjB"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * analyze_portfolio -- Portfolio analytics with live prices.
3
+ *
4
+ * Takes an array of { symbol, shares, avg_cost } holdings, fetches
5
+ * current prices from Yahoo Finance, and returns P&L, allocation,
6
+ * diversification score, and risk metrics.
7
+ */
8
+ import { yahooQuote } from "../utils/api.js";
9
+ import { formatCurrency } from "../utils/math.js";
10
+ export async function handleAnalyzePortfolio(holdings) {
11
+ if (holdings.length === 0) {
12
+ throw new Error("At least one holding is required.");
13
+ }
14
+ // Fetch live quotes for all symbols
15
+ const symbols = holdings.map((h) => h.symbol);
16
+ const quotes = await yahooQuote(symbols);
17
+ const quoteMap = new Map(quotes.map((q) => [q.symbol, q]));
18
+ // Build position analysis
19
+ let totalValue = 0;
20
+ let totalCost = 0;
21
+ const positions = holdings.map((h) => {
22
+ const q = quoteMap.get(h.symbol);
23
+ const currentPrice = q?.regularMarketPrice ?? 0;
24
+ const marketValue = h.shares * currentPrice;
25
+ const costBasis = h.shares * h.avg_cost;
26
+ totalValue += marketValue;
27
+ totalCost += costBasis;
28
+ return {
29
+ symbol: h.symbol,
30
+ name: q?.shortName ?? q?.longName ?? h.symbol,
31
+ shares: h.shares,
32
+ avgCost: h.avg_cost,
33
+ currentPrice,
34
+ marketValue,
35
+ costBasis,
36
+ pnl: marketValue - costBasis,
37
+ pnlPercent: costBasis > 0 ? ((marketValue - costBasis) / costBasis) * 100 : 0,
38
+ allocationPercent: 0, // calculated below
39
+ sector: q?.sector ?? "Unknown",
40
+ };
41
+ });
42
+ // Calculate allocation percentages
43
+ for (const p of positions) {
44
+ p.allocationPercent = totalValue > 0 ? (p.marketValue / totalValue) * 100 : 0;
45
+ }
46
+ // Sort by market value descending
47
+ positions.sort((a, b) => b.marketValue - a.marketValue);
48
+ // Sector breakdown
49
+ const sectorAlloc = {};
50
+ for (const p of positions) {
51
+ sectorAlloc[p.sector] = (sectorAlloc[p.sector] ?? 0) + p.allocationPercent;
52
+ }
53
+ // Diversification score (HHI-based, 0-100 where 100 = perfectly diversified)
54
+ const weights = positions.map((p) => p.allocationPercent / 100);
55
+ const hhi = weights.reduce((s, w) => s + w * w, 0);
56
+ const n = weights.length;
57
+ const minHHI = n > 0 ? 1 / n : 1;
58
+ const divScore = n <= 1 ? 0 : Math.round((1 - (hhi - minHHI) / (1 - minHHI)) * 100);
59
+ // Risk warnings
60
+ const warnings = [];
61
+ for (const p of positions) {
62
+ if (p.allocationPercent > 30) {
63
+ warnings.push(`HIGH CONCENTRATION: ${p.symbol} is ${p.allocationPercent.toFixed(1)}% of portfolio.`);
64
+ }
65
+ }
66
+ for (const [sector, pct] of Object.entries(sectorAlloc)) {
67
+ if (pct > 50) {
68
+ warnings.push(`SECTOR RISK: ${sector} represents ${pct.toFixed(1)}% of portfolio.`);
69
+ }
70
+ }
71
+ for (const p of positions) {
72
+ if (p.pnlPercent < -20) {
73
+ warnings.push(`SIGNIFICANT LOSS: ${p.symbol} is down ${Math.abs(p.pnlPercent).toFixed(1)}%.`);
74
+ }
75
+ }
76
+ if (n < 5) {
77
+ warnings.push(`LOW DIVERSIFICATION: Only ${n} position(s). Consider adding more holdings.`);
78
+ }
79
+ if (Object.keys(sectorAlloc).length < 3 && n >= 3) {
80
+ warnings.push("LIMITED SECTOR EXPOSURE: Portfolio spans fewer than 3 sectors.");
81
+ }
82
+ // Any positions where we couldn't fetch a price?
83
+ const missingPrices = positions.filter((p) => p.currentPrice === 0);
84
+ for (const p of missingPrices) {
85
+ warnings.push(`MISSING DATA: Could not fetch price for ${p.symbol}. Values may be inaccurate.`);
86
+ }
87
+ // Format output
88
+ const lines = [];
89
+ lines.push("# Portfolio Analysis");
90
+ lines.push("");
91
+ // Summary
92
+ lines.push("## Summary");
93
+ lines.push("");
94
+ lines.push("| Metric | Value |");
95
+ lines.push("|--------|-------|");
96
+ lines.push(`| Total Value | ${formatCurrency(totalValue)} |`);
97
+ lines.push(`| Total Cost Basis | ${formatCurrency(totalCost)} |`);
98
+ const totalPnl = totalValue - totalCost;
99
+ const totalPnlPct = totalCost > 0 ? ((totalPnl) / totalCost) * 100 : 0;
100
+ lines.push(`| Total P&L | ${totalPnl >= 0 ? "+" : ""}${formatCurrency(totalPnl)} (${totalPnlPct >= 0 ? "+" : ""}${totalPnlPct.toFixed(2)}%) |`);
101
+ lines.push(`| Positions | ${n} |`);
102
+ lines.push(`| Sectors | ${Object.keys(sectorAlloc).length} |`);
103
+ lines.push(`| Diversification Score | ${divScore}/100 |`);
104
+ lines.push("");
105
+ // Positions
106
+ lines.push("## Positions");
107
+ lines.push("");
108
+ lines.push("| Symbol | Name | Shares | Avg Cost | Price | Value | P&L | P&L% | Alloc% |");
109
+ lines.push("|--------|------|--------|----------|-------|-------|-----|------|--------|");
110
+ for (const p of positions) {
111
+ const pnlSign = p.pnl >= 0 ? "+" : "";
112
+ lines.push(`| ${p.symbol} | ${p.name.slice(0, 20)} | ${p.shares} | $${p.avgCost.toFixed(2)} | $${p.currentPrice.toFixed(2)} | ${formatCurrency(p.marketValue)} | ${pnlSign}${formatCurrency(p.pnl)} | ${pnlSign}${p.pnlPercent.toFixed(2)}% | ${p.allocationPercent.toFixed(1)}% |`);
113
+ }
114
+ lines.push("");
115
+ // Sector allocation
116
+ lines.push("## Sector Allocation");
117
+ lines.push("");
118
+ lines.push("| Sector | Allocation |");
119
+ lines.push("|--------|------------|");
120
+ const sortedSectors = Object.entries(sectorAlloc).sort((a, b) => b[1] - a[1]);
121
+ for (const [sector, pct] of sortedSectors) {
122
+ const bar = "=".repeat(Math.round(pct / 2));
123
+ lines.push(`| ${sector} | ${pct.toFixed(1)}% ${bar} |`);
124
+ }
125
+ lines.push("");
126
+ // Winners and losers
127
+ const winners = [...positions].sort((a, b) => b.pnlPercent - a.pnlPercent);
128
+ if (winners.length > 0) {
129
+ lines.push("## Top Performers");
130
+ lines.push("");
131
+ const top3 = winners.slice(0, Math.min(3, winners.length));
132
+ for (const p of top3) {
133
+ lines.push(`- **${p.symbol}**: ${p.pnlPercent >= 0 ? "+" : ""}${p.pnlPercent.toFixed(2)}% (${p.pnl >= 0 ? "+" : ""}${formatCurrency(p.pnl)})`);
134
+ }
135
+ lines.push("");
136
+ const bottom3 = winners.slice(-Math.min(3, winners.length)).reverse();
137
+ lines.push("## Underperformers");
138
+ lines.push("");
139
+ for (const p of bottom3) {
140
+ lines.push(`- **${p.symbol}**: ${p.pnlPercent >= 0 ? "+" : ""}${p.pnlPercent.toFixed(2)}% (${p.pnl >= 0 ? "+" : ""}${formatCurrency(p.pnl)})`);
141
+ }
142
+ lines.push("");
143
+ }
144
+ // Risk warnings
145
+ if (warnings.length > 0) {
146
+ lines.push("## Risk Warnings");
147
+ lines.push("");
148
+ for (const w of warnings) {
149
+ lines.push(`- ${w}`);
150
+ }
151
+ lines.push("");
152
+ }
153
+ return lines.join("\n");
154
+ }
155
+ //# sourceMappingURL=analyze_portfolio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze_portfolio.js","sourceRoot":"","sources":["../../src/tools/analyze_portfolio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * analyze_stock -- Deep analysis of a stock symbol.
3
+ *
4
+ * Fetches live data from Yahoo Finance, computes SMA 20/50/200, RSI,
5
+ * MACD, and support/resistance levels.
6
+ */
7
+ export declare function handleAnalyzeStock(symbol: string): Promise<string>;
8
+ //# sourceMappingURL=analyze_stock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze_stock.d.ts","sourceRoot":"","sources":["../../src/tools/analyze_stock.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyLxE"}