opencandle 0.1.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/LICENSE +21 -0
- package/README.md +150 -0
- package/dist/analysts/orchestrator.d.ts +9 -0
- package/dist/analysts/orchestrator.js +100 -0
- package/dist/analysts/orchestrator.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +122 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +76 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/browser.d.ts +27 -0
- package/dist/infra/browser.js +102 -0
- package/dist/infra/browser.js.map +1 -0
- package/dist/infra/cache.d.ts +18 -0
- package/dist/infra/cache.js +42 -0
- package/dist/infra/cache.js.map +1 -0
- package/dist/infra/http-client.d.ts +13 -0
- package/dist/infra/http-client.js +54 -0
- package/dist/infra/http-client.js.map +1 -0
- package/dist/infra/index.d.ts +5 -0
- package/dist/infra/index.js +6 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/open-url.d.ts +1 -0
- package/dist/infra/open-url.js +29 -0
- package/dist/infra/open-url.js.map +1 -0
- package/dist/infra/opencandle-paths.d.ts +11 -0
- package/dist/infra/opencandle-paths.js +48 -0
- package/dist/infra/opencandle-paths.js.map +1 -0
- package/dist/infra/rate-limiter.d.ts +7 -0
- package/dist/infra/rate-limiter.js +38 -0
- package/dist/infra/rate-limiter.js.map +1 -0
- package/dist/memory/index.d.ts +5 -0
- package/dist/memory/index.js +5 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/preference-extractor.d.ts +6 -0
- package/dist/memory/preference-extractor.js +88 -0
- package/dist/memory/preference-extractor.js.map +1 -0
- package/dist/memory/retrieval.d.ts +8 -0
- package/dist/memory/retrieval.js +61 -0
- package/dist/memory/retrieval.js.map +1 -0
- package/dist/memory/sqlite.d.ts +5 -0
- package/dist/memory/sqlite.js +95 -0
- package/dist/memory/sqlite.js.map +1 -0
- package/dist/memory/storage.d.ts +47 -0
- package/dist/memory/storage.js +124 -0
- package/dist/memory/storage.js.map +1 -0
- package/dist/onboarding/state.d.ts +8 -0
- package/dist/onboarding/state.js +31 -0
- package/dist/onboarding/state.js.map +1 -0
- package/dist/pi/opencandle-extension.d.ts +2 -0
- package/dist/pi/opencandle-extension.js +205 -0
- package/dist/pi/opencandle-extension.js.map +1 -0
- package/dist/pi/session.d.ts +10 -0
- package/dist/pi/session.js +28 -0
- package/dist/pi/session.js.map +1 -0
- package/dist/pi/setup.d.ts +10 -0
- package/dist/pi/setup.js +357 -0
- package/dist/pi/setup.js.map +1 -0
- package/dist/pi/tool-adapter.d.ts +5 -0
- package/dist/pi/tool-adapter.js +17 -0
- package/dist/pi/tool-adapter.js.map +1 -0
- package/dist/prompts/workflow-prompts.d.ts +9 -0
- package/dist/prompts/workflow-prompts.js +202 -0
- package/dist/prompts/workflow-prompts.js.map +1 -0
- package/dist/providers/alpha-vantage.d.ts +4 -0
- package/dist/providers/alpha-vantage.js +122 -0
- package/dist/providers/alpha-vantage.js.map +1 -0
- package/dist/providers/coingecko.d.ts +3 -0
- package/dist/providers/coingecko.js +53 -0
- package/dist/providers/coingecko.js.map +1 -0
- package/dist/providers/fear-greed.d.ts +2 -0
- package/dist/providers/fear-greed.js +26 -0
- package/dist/providers/fear-greed.js.map +1 -0
- package/dist/providers/fred.d.ts +2 -0
- package/dist/providers/fred.js +37 -0
- package/dist/providers/fred.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/reddit.d.ts +9 -0
- package/dist/providers/reddit.js +69 -0
- package/dist/providers/reddit.js.map +1 -0
- package/dist/providers/sec-edgar.d.ts +9 -0
- package/dist/providers/sec-edgar.js +59 -0
- package/dist/providers/sec-edgar.js.map +1 -0
- package/dist/providers/yahoo-finance.d.ts +17 -0
- package/dist/providers/yahoo-finance.js +231 -0
- package/dist/providers/yahoo-finance.js.map +1 -0
- package/dist/routing/classify-intent.d.ts +2 -0
- package/dist/routing/classify-intent.js +147 -0
- package/dist/routing/classify-intent.js.map +1 -0
- package/dist/routing/defaults.d.ts +7 -0
- package/dist/routing/defaults.js +26 -0
- package/dist/routing/defaults.js.map +1 -0
- package/dist/routing/entity-extractor.d.ts +3 -0
- package/dist/routing/entity-extractor.js +130 -0
- package/dist/routing/entity-extractor.js.map +1 -0
- package/dist/routing/index.d.ts +5 -0
- package/dist/routing/index.js +5 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/slot-resolver.d.ts +15 -0
- package/dist/routing/slot-resolver.js +120 -0
- package/dist/routing/slot-resolver.js.map +1 -0
- package/dist/routing/types.d.ts +51 -0
- package/dist/routing/types.js +2 -0
- package/dist/routing/types.js.map +1 -0
- package/dist/system-prompt.d.ts +1 -0
- package/dist/system-prompt.js +49 -0
- package/dist/system-prompt.js.map +1 -0
- package/dist/tool-kit.d.ts +19 -0
- package/dist/tool-kit.js +20 -0
- package/dist/tool-kit.js.map +1 -0
- package/dist/tools/fundamentals/company-overview.d.ts +7 -0
- package/dist/tools/fundamentals/company-overview.js +40 -0
- package/dist/tools/fundamentals/company-overview.js.map +1 -0
- package/dist/tools/fundamentals/comps.d.ts +22 -0
- package/dist/tools/fundamentals/comps.js +110 -0
- package/dist/tools/fundamentals/comps.js.map +1 -0
- package/dist/tools/fundamentals/dcf.d.ts +46 -0
- package/dist/tools/fundamentals/dcf.js +184 -0
- package/dist/tools/fundamentals/dcf.js.map +1 -0
- package/dist/tools/fundamentals/earnings.d.ts +7 -0
- package/dist/tools/fundamentals/earnings.js +33 -0
- package/dist/tools/fundamentals/earnings.js.map +1 -0
- package/dist/tools/fundamentals/financials.d.ts +7 -0
- package/dist/tools/fundamentals/financials.js +37 -0
- package/dist/tools/fundamentals/financials.js.map +1 -0
- package/dist/tools/fundamentals/sec-filings.d.ts +8 -0
- package/dist/tools/fundamentals/sec-filings.js +40 -0
- package/dist/tools/fundamentals/sec-filings.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +51 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/macro/fear-greed.d.ts +5 -0
- package/dist/tools/macro/fear-greed.js +26 -0
- package/dist/tools/macro/fear-greed.js.map +1 -0
- package/dist/tools/macro/fred-data.d.ts +8 -0
- package/dist/tools/macro/fred-data.js +34 -0
- package/dist/tools/macro/fred-data.js.map +1 -0
- package/dist/tools/market/crypto-history.d.ts +8 -0
- package/dist/tools/market/crypto-history.js +32 -0
- package/dist/tools/market/crypto-history.js.map +1 -0
- package/dist/tools/market/crypto-price.d.ts +7 -0
- package/dist/tools/market/crypto-price.js +42 -0
- package/dist/tools/market/crypto-price.js.map +1 -0
- package/dist/tools/market/search-ticker.d.ts +6 -0
- package/dist/tools/market/search-ticker.js +33 -0
- package/dist/tools/market/search-ticker.js.map +1 -0
- package/dist/tools/market/stock-history.d.ts +9 -0
- package/dist/tools/market/stock-history.js +35 -0
- package/dist/tools/market/stock-history.js.map +1 -0
- package/dist/tools/market/stock-quote.d.ts +7 -0
- package/dist/tools/market/stock-quote.js +32 -0
- package/dist/tools/market/stock-quote.js.map +1 -0
- package/dist/tools/options/greeks.d.ts +14 -0
- package/dist/tools/options/greeks.js +65 -0
- package/dist/tools/options/greeks.js.map +1 -0
- package/dist/tools/options/option-chain.d.ts +9 -0
- package/dist/tools/options/option-chain.js +61 -0
- package/dist/tools/options/option-chain.js.map +1 -0
- package/dist/tools/portfolio/correlation.d.ts +10 -0
- package/dist/tools/portfolio/correlation.js +122 -0
- package/dist/tools/portfolio/correlation.js.map +1 -0
- package/dist/tools/portfolio/predictions.d.ts +49 -0
- package/dist/tools/portfolio/predictions.js +171 -0
- package/dist/tools/portfolio/predictions.js.map +1 -0
- package/dist/tools/portfolio/risk-analysis.d.ts +12 -0
- package/dist/tools/portfolio/risk-analysis.js +113 -0
- package/dist/tools/portfolio/risk-analysis.js.map +1 -0
- package/dist/tools/portfolio/tracker.d.ts +10 -0
- package/dist/tools/portfolio/tracker.js +125 -0
- package/dist/tools/portfolio/tracker.js.map +1 -0
- package/dist/tools/portfolio/watchlist.d.ts +10 -0
- package/dist/tools/portfolio/watchlist.js +120 -0
- package/dist/tools/portfolio/watchlist.js.map +1 -0
- package/dist/tools/sentiment/news-sentiment.d.ts +7 -0
- package/dist/tools/sentiment/news-sentiment.js +57 -0
- package/dist/tools/sentiment/news-sentiment.js.map +1 -0
- package/dist/tools/sentiment/reddit-sentiment.d.ts +8 -0
- package/dist/tools/sentiment/reddit-sentiment.js +37 -0
- package/dist/tools/sentiment/reddit-sentiment.js.map +1 -0
- package/dist/tools/technical/backtest.d.ts +26 -0
- package/dist/tools/technical/backtest.js +190 -0
- package/dist/tools/technical/backtest.js.map +1 -0
- package/dist/tools/technical/indicators.d.ts +23 -0
- package/dist/tools/technical/indicators.js +212 -0
- package/dist/tools/technical/indicators.js.map +1 -0
- package/dist/types/fundamentals.d.ts +44 -0
- package/dist/types/fundamentals.js +2 -0
- package/dist/types/fundamentals.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/macro.d.ts +24 -0
- package/dist/types/macro.js +14 -0
- package/dist/types/macro.js.map +1 -0
- package/dist/types/market.d.ts +41 -0
- package/dist/types/market.js +2 -0
- package/dist/types/market.js.map +1 -0
- package/dist/types/options.d.ts +33 -0
- package/dist/types/options.js +2 -0
- package/dist/types/options.js.map +1 -0
- package/dist/types/portfolio.d.ts +44 -0
- package/dist/types/portfolio.js +2 -0
- package/dist/types/portfolio.js.map +1 -0
- package/dist/types/sentiment.d.ts +24 -0
- package/dist/types/sentiment.js +2 -0
- package/dist/types/sentiment.js.map +1 -0
- package/dist/workflows/compare-assets.d.ts +3 -0
- package/dist/workflows/compare-assets.js +14 -0
- package/dist/workflows/compare-assets.js.map +1 -0
- package/dist/workflows/index.d.ts +4 -0
- package/dist/workflows/index.js +4 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/options-screener.d.ts +3 -0
- package/dist/workflows/options-screener.js +22 -0
- package/dist/workflows/options-screener.js.map +1 -0
- package/dist/workflows/portfolio-builder.d.ts +3 -0
- package/dist/workflows/portfolio-builder.js +26 -0
- package/dist/workflows/portfolio-builder.js.map +1 -0
- package/dist/workflows/types.d.ts +4 -0
- package/dist/workflows/types.js +2 -0
- package/dist/workflows/types.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { getQuote } from "../../providers/yahoo-finance.js";
|
|
4
|
+
import { ensureParentDir, getPredictionsPath } from "../../infra/opencandle-paths.js";
|
|
5
|
+
function loadPredictions() {
|
|
6
|
+
const predictionsPath = getPredictionsPath();
|
|
7
|
+
if (!existsSync(predictionsPath))
|
|
8
|
+
return [];
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(predictionsPath, "utf-8"));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function savePredictions(predictions) {
|
|
17
|
+
const predictionsPath = getPredictionsPath();
|
|
18
|
+
ensureParentDir(predictionsPath);
|
|
19
|
+
writeFileSync(predictionsPath, JSON.stringify(predictions, null, 2));
|
|
20
|
+
}
|
|
21
|
+
export function recordPrediction(params) {
|
|
22
|
+
const predictions = loadPredictions();
|
|
23
|
+
const now = new Date();
|
|
24
|
+
const expires = new Date(now);
|
|
25
|
+
expires.setDate(expires.getDate() + params.timeframeDays);
|
|
26
|
+
const prediction = {
|
|
27
|
+
symbol: params.symbol.toUpperCase(),
|
|
28
|
+
direction: params.direction,
|
|
29
|
+
conviction: params.conviction,
|
|
30
|
+
entryPrice: params.entryPrice,
|
|
31
|
+
targetPrice: params.targetPrice,
|
|
32
|
+
date: now.toISOString().split("T")[0],
|
|
33
|
+
expiresAt: expires.toISOString().split("T")[0],
|
|
34
|
+
timeframeDays: params.timeframeDays,
|
|
35
|
+
};
|
|
36
|
+
predictions.push(prediction);
|
|
37
|
+
savePredictions(predictions);
|
|
38
|
+
return prediction;
|
|
39
|
+
}
|
|
40
|
+
export function checkPredictions(predictions, currentPrices, now = new Date()) {
|
|
41
|
+
if (predictions.length === 0) {
|
|
42
|
+
return { total: 0, open: 0, correct: 0, wrong: 0, hitRate: 0, weightedHitRate: 0, details: [] };
|
|
43
|
+
}
|
|
44
|
+
const details = [];
|
|
45
|
+
let totalConviction = 0;
|
|
46
|
+
let correctConviction = 0;
|
|
47
|
+
let openCount = 0;
|
|
48
|
+
const nowStr = now.toISOString().split("T")[0];
|
|
49
|
+
for (const p of predictions) {
|
|
50
|
+
const currentPrice = currentPrices.get(p.symbol);
|
|
51
|
+
if (currentPrice == null)
|
|
52
|
+
continue;
|
|
53
|
+
const isExpired = p.expiresAt <= nowStr;
|
|
54
|
+
const pnlPercent = (currentPrice - p.entryPrice) / p.entryPrice;
|
|
55
|
+
if (!isExpired) {
|
|
56
|
+
openCount++;
|
|
57
|
+
details.push({
|
|
58
|
+
symbol: p.symbol,
|
|
59
|
+
direction: p.direction,
|
|
60
|
+
conviction: p.conviction,
|
|
61
|
+
entryPrice: p.entryPrice,
|
|
62
|
+
currentPrice,
|
|
63
|
+
pnlPercent,
|
|
64
|
+
correct: false,
|
|
65
|
+
status: "open",
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const correct = (p.direction === "bullish" && currentPrice > p.entryPrice) ||
|
|
70
|
+
(p.direction === "bearish" && currentPrice < p.entryPrice) ||
|
|
71
|
+
(p.direction === "neutral" && Math.abs(pnlPercent) < 0.02);
|
|
72
|
+
details.push({
|
|
73
|
+
symbol: p.symbol,
|
|
74
|
+
direction: p.direction,
|
|
75
|
+
conviction: p.conviction,
|
|
76
|
+
entryPrice: p.entryPrice,
|
|
77
|
+
currentPrice,
|
|
78
|
+
pnlPercent,
|
|
79
|
+
correct,
|
|
80
|
+
status: "resolved",
|
|
81
|
+
});
|
|
82
|
+
totalConviction += p.conviction;
|
|
83
|
+
if (correct)
|
|
84
|
+
correctConviction += p.conviction;
|
|
85
|
+
}
|
|
86
|
+
const resolved = details.filter((d) => d.status === "resolved");
|
|
87
|
+
const correctCount = resolved.filter((d) => d.correct).length;
|
|
88
|
+
return {
|
|
89
|
+
total: details.length,
|
|
90
|
+
open: openCount,
|
|
91
|
+
correct: correctCount,
|
|
92
|
+
wrong: resolved.length - correctCount,
|
|
93
|
+
hitRate: resolved.length > 0 ? correctCount / resolved.length : 0,
|
|
94
|
+
weightedHitRate: totalConviction > 0 ? correctConviction / totalConviction : 0,
|
|
95
|
+
details,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const params = Type.Object({
|
|
99
|
+
action: Type.Union([Type.Literal("record"), Type.Literal("check")], { description: "record: save a new prediction. check: evaluate all predictions against current prices." }),
|
|
100
|
+
symbol: Type.Optional(Type.String({ description: "Ticker symbol (required for record)" })),
|
|
101
|
+
direction: Type.Optional(Type.Union([Type.Literal("bullish"), Type.Literal("bearish"), Type.Literal("neutral")], { description: "Predicted direction (required for record)" })),
|
|
102
|
+
conviction: Type.Optional(Type.Number({ description: "Conviction 1-10 (required for record)" })),
|
|
103
|
+
entry_price: Type.Optional(Type.Number({ description: "Entry price at time of prediction (required for record)" })),
|
|
104
|
+
target_price: Type.Optional(Type.Number({ description: "Optional target price" })),
|
|
105
|
+
timeframe_days: Type.Optional(Type.Number({ description: "Timeframe in days for the prediction (default: 30)" })),
|
|
106
|
+
});
|
|
107
|
+
export const predictionsTool = {
|
|
108
|
+
name: "track_prediction",
|
|
109
|
+
label: "Prediction Tracker",
|
|
110
|
+
description: "Track your analysis predictions and measure accuracy over time. Record: save a directional prediction with conviction. Check: evaluate all predictions against current prices, compute hit rate and conviction-weighted accuracy. Inspired by ATLAS's Darwinian scoring approach.",
|
|
111
|
+
parameters: params,
|
|
112
|
+
async execute(toolCallId, args) {
|
|
113
|
+
if (args.action === "record") {
|
|
114
|
+
if (!args.symbol || !args.direction || !args.conviction || !args.entry_price) {
|
|
115
|
+
throw new Error("symbol, direction, conviction, and entry_price are required for record action.");
|
|
116
|
+
}
|
|
117
|
+
const prediction = recordPrediction({
|
|
118
|
+
symbol: args.symbol,
|
|
119
|
+
direction: args.direction,
|
|
120
|
+
conviction: args.conviction,
|
|
121
|
+
entryPrice: args.entry_price,
|
|
122
|
+
targetPrice: args.target_price,
|
|
123
|
+
timeframeDays: args.timeframe_days ?? 30,
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
content: [{ type: "text", text: `Recorded: ${prediction.symbol} ${prediction.direction} (conviction ${prediction.conviction}/10) at $${prediction.entryPrice}. Expires ${prediction.expiresAt}.` }],
|
|
127
|
+
details: prediction,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// Check action
|
|
131
|
+
const predictions = loadPredictions();
|
|
132
|
+
if (predictions.length === 0) {
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: "text", text: "No predictions recorded yet. Use record action to track your calls." }],
|
|
135
|
+
details: null,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Fetch current prices for all symbols
|
|
139
|
+
const symbols = [...new Set(predictions.map((p) => p.symbol))];
|
|
140
|
+
const priceMap = new Map();
|
|
141
|
+
await Promise.all(symbols.map(async (sym) => {
|
|
142
|
+
try {
|
|
143
|
+
const quote = await getQuote(sym);
|
|
144
|
+
priceMap.set(sym, quote.price);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Skip symbols that fail
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
const result = checkPredictions(predictions, priceMap);
|
|
151
|
+
const resolved = result.correct + result.wrong;
|
|
152
|
+
const lines = [
|
|
153
|
+
`**Prediction Scorecard** — ${result.total} predictions (${resolved} resolved, ${result.open} open)`,
|
|
154
|
+
``,
|
|
155
|
+
`Hit Rate: ${(result.hitRate * 100).toFixed(0)}% (${result.correct}/${resolved})`,
|
|
156
|
+
`Weighted Hit Rate: ${(result.weightedHitRate * 100).toFixed(0)}% (by conviction)`,
|
|
157
|
+
``,
|
|
158
|
+
...result.details.map((d) => {
|
|
159
|
+
const icon = d.status === "open" ? "~" : d.correct ? "+" : "-";
|
|
160
|
+
const sign = d.pnlPercent >= 0 ? "+" : "";
|
|
161
|
+
const label = d.status === "open" ? " (open)" : "";
|
|
162
|
+
return ` [${icon}] ${d.symbol}: ${d.direction} (conv ${d.conviction}) → $${d.entryPrice.toFixed(2)} → $${d.currentPrice.toFixed(2)} (${sign}${(d.pnlPercent * 100).toFixed(1)}%)${label}`;
|
|
163
|
+
}),
|
|
164
|
+
];
|
|
165
|
+
return {
|
|
166
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
167
|
+
details: result,
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=predictions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predictions.js","sourceRoot":"","sources":["../../../src/tools/portfolio/predictions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
2
|
+
import type { RiskMetrics } from "../../types/portfolio.js";
|
|
3
|
+
declare const params: import("@sinclair/typebox").TObject<{
|
|
4
|
+
symbol: import("@sinclair/typebox").TString;
|
|
5
|
+
period: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const riskAnalysisTool: AgentTool<typeof params, RiskMetrics>;
|
|
8
|
+
export declare function computeRiskMetrics(symbol: string, closes: number[]): RiskMetrics;
|
|
9
|
+
export declare function computeDailyReturns(prices: number[]): number[];
|
|
10
|
+
export declare function computeMaxDrawdown(prices: number[]): number;
|
|
11
|
+
export declare function computeVaR(returns: number[], confidence: number): number;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { getHistory } from "../../providers/yahoo-finance.js";
|
|
3
|
+
const params = Type.Object({
|
|
4
|
+
symbol: Type.String({ description: "Stock ticker symbol (e.g. AAPL, MSFT, SPY)" }),
|
|
5
|
+
period: Type.Optional(Type.String({ description: "Historical period for analysis: 6mo, 1y, 2y. Default: 1y" })),
|
|
6
|
+
});
|
|
7
|
+
export const riskAnalysisTool = {
|
|
8
|
+
name: "analyze_risk",
|
|
9
|
+
label: "Risk Analysis",
|
|
10
|
+
description: "Compute risk metrics for a stock: annualized return, volatility, Sharpe ratio, max drawdown, and Value at Risk (95%). All computed locally from historical data.",
|
|
11
|
+
parameters: params,
|
|
12
|
+
async execute(toolCallId, args) {
|
|
13
|
+
const symbol = args.symbol.toUpperCase();
|
|
14
|
+
const period = args.period ?? "1y";
|
|
15
|
+
const bars = await getHistory(symbol, period, "1d");
|
|
16
|
+
const closes = bars.map((b) => b.close);
|
|
17
|
+
if (closes.length < 30) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: `Insufficient data for risk analysis (need 30+ days, got ${closes.length})` }],
|
|
20
|
+
details: null,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const metrics = computeRiskMetrics(symbol, closes);
|
|
24
|
+
const text = [
|
|
25
|
+
`**${symbol} Risk Analysis** (${bars[0].date} to ${bars[bars.length - 1].date}, ${closes.length} days)`,
|
|
26
|
+
``,
|
|
27
|
+
`Annualized Return: ${(metrics.annualizedReturn * 100).toFixed(2)}%`,
|
|
28
|
+
`Annualized Volatility: ${(metrics.annualizedVolatility * 100).toFixed(2)}%`,
|
|
29
|
+
`Sharpe Ratio: ${metrics.sharpeRatio.toFixed(2)} ${sharpeLabel(metrics.sharpeRatio)}`,
|
|
30
|
+
`Max Drawdown: ${(metrics.maxDrawdown * 100).toFixed(2)}%`,
|
|
31
|
+
`Value at Risk (95%, daily): ${(metrics.var95 * 100).toFixed(2)}%`,
|
|
32
|
+
``,
|
|
33
|
+
riskSummary(metrics),
|
|
34
|
+
].join("\n");
|
|
35
|
+
return { content: [{ type: "text", text }], details: metrics };
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export function computeRiskMetrics(symbol, closes) {
|
|
39
|
+
const dailyReturns = computeDailyReturns(closes);
|
|
40
|
+
const avgDailyReturn = mean(dailyReturns);
|
|
41
|
+
const dailyVol = stddev(dailyReturns);
|
|
42
|
+
const annualizedReturn = avgDailyReturn * 252;
|
|
43
|
+
const annualizedVolatility = dailyVol * Math.sqrt(252);
|
|
44
|
+
// Sharpe ratio (assuming 5% risk-free rate)
|
|
45
|
+
const riskFreeDaily = 0.05 / 252;
|
|
46
|
+
const sharpeRatio = dailyVol === 0 ? 0 : ((avgDailyReturn - riskFreeDaily) / dailyVol) * Math.sqrt(252);
|
|
47
|
+
const maxDrawdown = computeMaxDrawdown(closes);
|
|
48
|
+
const var95 = computeVaR(dailyReturns, 0.05);
|
|
49
|
+
return {
|
|
50
|
+
symbol,
|
|
51
|
+
annualizedReturn,
|
|
52
|
+
annualizedVolatility,
|
|
53
|
+
sharpeRatio,
|
|
54
|
+
maxDrawdown,
|
|
55
|
+
var95,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function computeDailyReturns(prices) {
|
|
59
|
+
const returns = [];
|
|
60
|
+
for (let i = 1; i < prices.length; i++) {
|
|
61
|
+
returns.push((prices[i] - prices[i - 1]) / prices[i - 1]);
|
|
62
|
+
}
|
|
63
|
+
return returns;
|
|
64
|
+
}
|
|
65
|
+
export function computeMaxDrawdown(prices) {
|
|
66
|
+
let peak = prices[0];
|
|
67
|
+
let maxDd = 0;
|
|
68
|
+
for (const price of prices) {
|
|
69
|
+
if (price > peak)
|
|
70
|
+
peak = price;
|
|
71
|
+
const dd = (peak - price) / peak;
|
|
72
|
+
if (dd > maxDd)
|
|
73
|
+
maxDd = dd;
|
|
74
|
+
}
|
|
75
|
+
return maxDd;
|
|
76
|
+
}
|
|
77
|
+
export function computeVaR(returns, confidence) {
|
|
78
|
+
const sorted = [...returns].sort((a, b) => a - b);
|
|
79
|
+
const idx = Math.floor(sorted.length * confidence);
|
|
80
|
+
return Math.abs(sorted[idx]);
|
|
81
|
+
}
|
|
82
|
+
function mean(arr) {
|
|
83
|
+
return arr.reduce((a, b) => a + b, 0) / arr.length;
|
|
84
|
+
}
|
|
85
|
+
function stddev(arr) {
|
|
86
|
+
const m = mean(arr);
|
|
87
|
+
const variance = arr.reduce((sum, val) => sum + (val - m) ** 2, 0) / arr.length;
|
|
88
|
+
return Math.sqrt(variance);
|
|
89
|
+
}
|
|
90
|
+
function sharpeLabel(s) {
|
|
91
|
+
if (s >= 2)
|
|
92
|
+
return "(Excellent)";
|
|
93
|
+
if (s >= 1)
|
|
94
|
+
return "(Good)";
|
|
95
|
+
if (s >= 0)
|
|
96
|
+
return "(Below average)";
|
|
97
|
+
return "(Negative — losing money)";
|
|
98
|
+
}
|
|
99
|
+
function riskSummary(m) {
|
|
100
|
+
const signals = [];
|
|
101
|
+
if (m.annualizedVolatility > 0.4)
|
|
102
|
+
signals.push("High volatility stock");
|
|
103
|
+
if (m.maxDrawdown > 0.3)
|
|
104
|
+
signals.push("Large historical drawdown (>30%)");
|
|
105
|
+
if (m.sharpeRatio < 0)
|
|
106
|
+
signals.push("Negative risk-adjusted returns");
|
|
107
|
+
if (m.sharpeRatio >= 1.5)
|
|
108
|
+
signals.push("Strong risk-adjusted performance");
|
|
109
|
+
if (m.var95 > 0.03)
|
|
110
|
+
signals.push("High daily VaR (>3%)");
|
|
111
|
+
return signals.length > 0 ? "Flags: " + signals.join(" | ") : "Risk profile appears moderate";
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=risk-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-analysis.js","sourceRoot":"","sources":["../../../src/tools/portfolio/risk-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAG9D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;IAClF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC,CACzF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAA0C;IACrE,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,eAAe;IACtB,WAAW,EACT,kKAAkK;IACpK,UAAU,EAAE,MAAM;IAClB,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAExC,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2DAA2D,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;gBAC9G,OAAO,EAAE,IAAW;aACrB,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEnD,MAAM,IAAI,GAAG;YACX,KAAK,MAAM,qBAAqB,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,QAAQ;YACvG,EAAE;YACF,sBAAsB,CAAC,OAAO,CAAC,gBAAgB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YACpE,0BAA0B,CAAC,OAAO,CAAC,oBAAoB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YAC5E,iBAAiB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;YACrF,iBAAiB,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YAC1D,+BAA+B,CAAC,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YAClE,EAAE;YACF,WAAW,CAAC,OAAO,CAAC;SACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACjE,CAAC;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAgB;IACjE,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAEtC,MAAM,gBAAgB,GAAG,cAAc,GAAG,GAAG,CAAC;IAC9C,MAAM,oBAAoB,GAAG,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEvD,4CAA4C;IAC5C,MAAM,aAAa,GAAG,IAAI,GAAG,GAAG,CAAC;IACjC,MAAM,WAAW,GACf,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,aAAa,CAAC,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtF,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM;QACN,gBAAgB;QAChB,oBAAoB;QACpB,WAAW;QACX,WAAW;QACX,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAgB;IAClD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAgB;IACjD,IAAI,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,GAAG,IAAI;YAAE,IAAI,GAAG,KAAK,CAAC;QAC/B,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;QACjC,IAAI,EAAE,GAAG,KAAK;YAAE,KAAK,GAAG,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAiB,EAAE,UAAkB;IAC9D,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,IAAI,CAAC,GAAa;IACzB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;AACrD,CAAC;AAED,SAAS,MAAM,CAAC,GAAa;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IAChF,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5B,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,iBAAiB,CAAC;IACrC,OAAO,2BAA2B,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,CAAc;IACjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,oBAAoB,GAAG,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxE,IAAI,CAAC,CAAC,WAAW,GAAG,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC1E,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACtE,IAAI,CAAC,CAAC,WAAW,IAAI,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC3E,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC;AAChG,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
2
|
+
import type { PortfolioSummary } from "../../types/portfolio.js";
|
|
3
|
+
declare const params: import("@sinclair/typebox").TObject<{
|
|
4
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"add">, import("@sinclair/typebox").TLiteral<"remove">, import("@sinclair/typebox").TLiteral<"view">]>;
|
|
5
|
+
symbol: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
|
+
shares: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
7
|
+
avg_cost: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const portfolioTrackerTool: AgentTool<typeof params, PortfolioSummary | null>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { getQuote } from "../../providers/yahoo-finance.js";
|
|
4
|
+
import { ensureParentDir, getPortfolioPath } from "../../infra/opencandle-paths.js";
|
|
5
|
+
function loadPortfolio() {
|
|
6
|
+
const portfolioPath = getPortfolioPath();
|
|
7
|
+
if (!existsSync(portfolioPath))
|
|
8
|
+
return [];
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(portfolioPath, "utf-8"));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function savePortfolio(positions) {
|
|
17
|
+
const portfolioPath = getPortfolioPath();
|
|
18
|
+
ensureParentDir(portfolioPath);
|
|
19
|
+
writeFileSync(portfolioPath, JSON.stringify(positions, null, 2));
|
|
20
|
+
}
|
|
21
|
+
async function getCurrentPrice(symbol) {
|
|
22
|
+
const quote = await getQuote(symbol);
|
|
23
|
+
return quote.price;
|
|
24
|
+
}
|
|
25
|
+
const params = Type.Object({
|
|
26
|
+
action: Type.Union([
|
|
27
|
+
Type.Literal("add"),
|
|
28
|
+
Type.Literal("remove"),
|
|
29
|
+
Type.Literal("view"),
|
|
30
|
+
], { description: "Action: add a position, remove a position, or view portfolio" }),
|
|
31
|
+
symbol: Type.Optional(Type.String({ description: "Ticker symbol — stocks (AAPL, MSFT) or crypto with -USD suffix (BTC-USD, ETH-USD, SOL-USD). Use search_ticker to find the right ticker." })),
|
|
32
|
+
shares: Type.Optional(Type.Number({ description: "Number of shares/units (required for add)" })),
|
|
33
|
+
avg_cost: Type.Optional(Type.Number({ description: "Average cost per share/unit in USD (required for add)" })),
|
|
34
|
+
});
|
|
35
|
+
export const portfolioTrackerTool = {
|
|
36
|
+
name: "track_portfolio",
|
|
37
|
+
label: "Portfolio Tracker",
|
|
38
|
+
description: "Track your portfolio of stocks and crypto. Add/remove positions with cost basis, or view current holdings with live P&L. For stocks use standard tickers (AAPL, MSFT). For crypto use the -USD suffix (BTC-USD, ETH-USD, SOL-USD). Use search_ticker first if you're unsure of the exact ticker. Data persisted to ~/.opencandle/portfolio.json.",
|
|
39
|
+
parameters: params,
|
|
40
|
+
async execute(toolCallId, args) {
|
|
41
|
+
const positions = loadPortfolio();
|
|
42
|
+
if (args.action === "add") {
|
|
43
|
+
if (!args.symbol || !args.shares || !args.avg_cost) {
|
|
44
|
+
throw new Error("symbol, shares, and avg_cost are required for add action.");
|
|
45
|
+
}
|
|
46
|
+
const symbol = args.symbol.toUpperCase();
|
|
47
|
+
const existing = positions.find((p) => p.symbol === symbol);
|
|
48
|
+
if (existing) {
|
|
49
|
+
const totalShares = existing.shares + args.shares;
|
|
50
|
+
existing.avgCost =
|
|
51
|
+
(existing.avgCost * existing.shares + args.avg_cost * args.shares) / totalShares;
|
|
52
|
+
existing.shares = totalShares;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
positions.push({
|
|
56
|
+
symbol,
|
|
57
|
+
shares: args.shares,
|
|
58
|
+
avgCost: args.avg_cost,
|
|
59
|
+
addedAt: new Date().toISOString(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
savePortfolio(positions);
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `Added ${args.shares} shares of ${symbol} at $${args.avg_cost.toFixed(2)}` }],
|
|
65
|
+
details: null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (args.action === "remove") {
|
|
69
|
+
if (!args.symbol) {
|
|
70
|
+
throw new Error("symbol is required for remove action.");
|
|
71
|
+
}
|
|
72
|
+
const symbol = args.symbol.toUpperCase();
|
|
73
|
+
const idx = positions.findIndex((p) => p.symbol === symbol);
|
|
74
|
+
if (idx === -1) {
|
|
75
|
+
return {
|
|
76
|
+
content: [{ type: "text", text: `${symbol} not found in portfolio` }],
|
|
77
|
+
details: null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
positions.splice(idx, 1);
|
|
81
|
+
savePortfolio(positions);
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: "text", text: `Removed ${symbol} from portfolio` }],
|
|
84
|
+
details: null,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// View portfolio
|
|
88
|
+
if (positions.length === 0) {
|
|
89
|
+
return {
|
|
90
|
+
content: [{ type: "text", text: "Portfolio is empty. Use add action to add positions." }],
|
|
91
|
+
details: null,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const enriched = await Promise.all(positions.map(async (p) => {
|
|
95
|
+
const currentPrice = await getCurrentPrice(p.symbol);
|
|
96
|
+
const marketValue = currentPrice * p.shares;
|
|
97
|
+
const totalCost = p.avgCost * p.shares;
|
|
98
|
+
return {
|
|
99
|
+
...p,
|
|
100
|
+
currentPrice,
|
|
101
|
+
marketValue,
|
|
102
|
+
totalCost,
|
|
103
|
+
pnl: marketValue - totalCost,
|
|
104
|
+
pnlPercent: ((marketValue - totalCost) / totalCost) * 100,
|
|
105
|
+
};
|
|
106
|
+
}));
|
|
107
|
+
const totalValue = enriched.reduce((s, p) => s + p.marketValue, 0);
|
|
108
|
+
const totalCost = enriched.reduce((s, p) => s + p.totalCost, 0);
|
|
109
|
+
const summary = {
|
|
110
|
+
positions: enriched,
|
|
111
|
+
totalValue,
|
|
112
|
+
totalCost,
|
|
113
|
+
totalPnl: totalValue - totalCost,
|
|
114
|
+
totalPnlPercent: totalCost > 0 ? ((totalValue - totalCost) / totalCost) * 100 : 0,
|
|
115
|
+
};
|
|
116
|
+
const header = `**Portfolio** — ${enriched.length} positions | Value: $${totalValue.toFixed(2)} | P&L: $${summary.totalPnl.toFixed(2)} (${summary.totalPnlPercent >= 0 ? "+" : ""}${summary.totalPnlPercent.toFixed(2)}%)`;
|
|
117
|
+
const rows = enriched.map((p) => {
|
|
118
|
+
const sign = p.pnlPercent >= 0 ? "+" : "";
|
|
119
|
+
return ` ${p.symbol}: ${p.shares} @ $${p.avgCost.toFixed(2)} → $${p.currentPrice.toFixed(2)} | P&L: $${p.pnl.toFixed(2)} (${sign}${p.pnlPercent.toFixed(2)}%)`;
|
|
120
|
+
});
|
|
121
|
+
const text = [header, ...rows].join("\n");
|
|
122
|
+
return { content: [{ type: "text", text }], details: summary };
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/tools/portfolio/tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
2
|
+
declare const params: import("@sinclair/typebox").TObject<{
|
|
3
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"add">, import("@sinclair/typebox").TLiteral<"remove">, import("@sinclair/typebox").TLiteral<"check">]>;
|
|
4
|
+
symbol: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
5
|
+
target_price: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
6
|
+
stop_price: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
7
|
+
notes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const watchlistTool: AgentTool<typeof params>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { getQuote } from "../../providers/yahoo-finance.js";
|
|
4
|
+
import { ensureParentDir, getWatchlistPath } from "../../infra/opencandle-paths.js";
|
|
5
|
+
function loadWatchlist() {
|
|
6
|
+
const watchlistPath = getWatchlistPath();
|
|
7
|
+
if (!existsSync(watchlistPath))
|
|
8
|
+
return [];
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(watchlistPath, "utf-8"));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function saveWatchlist(items) {
|
|
17
|
+
const watchlistPath = getWatchlistPath();
|
|
18
|
+
ensureParentDir(watchlistPath);
|
|
19
|
+
writeFileSync(watchlistPath, JSON.stringify(items, null, 2));
|
|
20
|
+
}
|
|
21
|
+
const params = Type.Object({
|
|
22
|
+
action: Type.Union([Type.Literal("add"), Type.Literal("remove"), Type.Literal("check")], { description: "One of: 'add', 'remove', or 'check'" }),
|
|
23
|
+
symbol: Type.Optional(Type.String({ description: "Ticker symbol (required for add/remove)" })),
|
|
24
|
+
target_price: Type.Optional(Type.Number({ description: "Alert when price rises above this level" })),
|
|
25
|
+
stop_price: Type.Optional(Type.Number({ description: "Alert when price falls below this level" })),
|
|
26
|
+
notes: Type.Optional(Type.String({ description: "Optional notes for why you're watching this" })),
|
|
27
|
+
});
|
|
28
|
+
export const watchlistTool = {
|
|
29
|
+
name: "manage_watchlist",
|
|
30
|
+
label: "Watchlist",
|
|
31
|
+
description: "Manage your watchlist of stocks and crypto. Add symbols with optional target and stop prices, remove symbols, or check current prices against your alert levels. Data persisted to ~/.opencandle/watchlist.json.",
|
|
32
|
+
parameters: params,
|
|
33
|
+
async execute(toolCallId, args) {
|
|
34
|
+
const items = loadWatchlist();
|
|
35
|
+
if (args.action === "add") {
|
|
36
|
+
if (!args.symbol) {
|
|
37
|
+
throw new Error("symbol is required for add action.");
|
|
38
|
+
}
|
|
39
|
+
const symbol = args.symbol.toUpperCase();
|
|
40
|
+
const existing = items.findIndex((i) => i.symbol === symbol);
|
|
41
|
+
const item = {
|
|
42
|
+
symbol,
|
|
43
|
+
addedAt: new Date().toISOString(),
|
|
44
|
+
...(args.target_price != null && { targetPrice: args.target_price }),
|
|
45
|
+
...(args.stop_price != null && { stopPrice: args.stop_price }),
|
|
46
|
+
...(args.notes != null && { notes: args.notes }),
|
|
47
|
+
};
|
|
48
|
+
if (existing >= 0) {
|
|
49
|
+
items[existing] = item;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
items.push(item);
|
|
53
|
+
}
|
|
54
|
+
saveWatchlist(items);
|
|
55
|
+
const alerts = [];
|
|
56
|
+
if (args.target_price)
|
|
57
|
+
alerts.push(`target: $${args.target_price}`);
|
|
58
|
+
if (args.stop_price)
|
|
59
|
+
alerts.push(`stop: $${args.stop_price}`);
|
|
60
|
+
const alertStr = alerts.length > 0 ? ` (${alerts.join(", ")})` : "";
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: `Added ${symbol} to watchlist${alertStr}` }],
|
|
63
|
+
details: null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (args.action === "remove") {
|
|
67
|
+
if (!args.symbol) {
|
|
68
|
+
throw new Error("symbol is required for remove action.");
|
|
69
|
+
}
|
|
70
|
+
const symbol = args.symbol.toUpperCase();
|
|
71
|
+
const idx = items.findIndex((i) => i.symbol === symbol);
|
|
72
|
+
if (idx === -1) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: `${symbol} not found in watchlist` }],
|
|
75
|
+
details: null,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
items.splice(idx, 1);
|
|
79
|
+
saveWatchlist(items);
|
|
80
|
+
return {
|
|
81
|
+
content: [{ type: "text", text: `Removed ${symbol} from watchlist` }],
|
|
82
|
+
details: null,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Check action
|
|
86
|
+
if (items.length === 0) {
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text", text: "Watchlist is empty. Use add action to add symbols." }],
|
|
89
|
+
details: null,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const checks = await Promise.all(items.map(async (item) => {
|
|
93
|
+
const quote = await getQuote(item.symbol);
|
|
94
|
+
const alerts = [];
|
|
95
|
+
if (item.targetPrice && quote.price >= item.targetPrice) {
|
|
96
|
+
alerts.push(`TARGET HIT: $${quote.price.toFixed(2)} >= $${item.targetPrice}`);
|
|
97
|
+
}
|
|
98
|
+
if (item.stopPrice && quote.price <= item.stopPrice) {
|
|
99
|
+
alerts.push(`STOP ALERT: $${quote.price.toFixed(2)} fell below $${item.stopPrice}`);
|
|
100
|
+
}
|
|
101
|
+
return { ...item, currentPrice: quote.price, alerts };
|
|
102
|
+
}));
|
|
103
|
+
const alertItems = checks.filter((c) => c.alerts.length > 0);
|
|
104
|
+
const lines = [
|
|
105
|
+
`**Watchlist** — ${items.length} symbols${alertItems.length > 0 ? ` | ${alertItems.length} ALERT(S)` : ""}`,
|
|
106
|
+
"",
|
|
107
|
+
];
|
|
108
|
+
for (const c of checks) {
|
|
109
|
+
const alertStr = c.alerts.length > 0 ? ` ** ${c.alerts.join(" | ")} **` : "";
|
|
110
|
+
const targetStr = c.targetPrice ? ` | Target: $${c.targetPrice}` : "";
|
|
111
|
+
const stopStr = c.stopPrice ? ` | Stop: $${c.stopPrice}` : "";
|
|
112
|
+
lines.push(` ${c.symbol}: $${c.currentPrice.toFixed(2)}${targetStr}${stopStr}${alertStr}`);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
116
|
+
details: { items: checks },
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=watchlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watchlist.js","sourceRoot":"","sources":["../../../src/tools/portfolio/watchlist.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
2
|
+
import type { RedditSentimentResult } from "../../types/sentiment.js";
|
|
3
|
+
declare const params: import("@sinclair/typebox").TObject<{
|
|
4
|
+
topic: import("@sinclair/typebox").TString;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const newsSentimentTool: AgentTool<typeof params, RedditSentimentResult>;
|
|
7
|
+
export {};
|