opencandle 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/analysts/orchestrator.d.ts +1 -4
- package/dist/analysts/orchestrator.js +15 -44
- package/dist/analysts/orchestrator.js.map +1 -1
- package/dist/cli-main.js +242 -9
- package/dist/cli-main.js.map +1 -1
- package/dist/config.d.ts +4 -9
- package/dist/config.js +7 -10
- package/dist/config.js.map +1 -1
- package/dist/market-state/daily-report.d.ts +1 -1
- package/dist/market-state/daily-report.js +5 -16
- package/dist/market-state/daily-report.js.map +1 -1
- package/dist/market-state/service.d.ts +0 -35
- package/dist/market-state/service.js +0 -63
- package/dist/market-state/service.js.map +1 -1
- package/dist/memory/sqlite.js +20 -19
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/pi/opencandle-extension.js +13 -221
- package/dist/pi/opencandle-extension.js.map +1 -1
- package/dist/pi/session-action-dedupe.d.ts +6 -0
- package/dist/pi/session-action-dedupe.js +126 -0
- package/dist/pi/session-action-dedupe.js.map +1 -0
- package/dist/pi/session-writer-lock.d.ts +26 -2
- package/dist/pi/session-writer-lock.js +230 -18
- package/dist/pi/session-writer-lock.js.map +1 -1
- package/dist/pi/setup.js +5 -5
- package/dist/pi/setup.js.map +1 -1
- package/dist/pi/tui-session-coordinator.d.ts +15 -0
- package/dist/pi/tui-session-coordinator.js +283 -0
- package/dist/pi/tui-session-coordinator.js.map +1 -0
- package/dist/prompts/context-builder.js +1 -1
- package/dist/prompts/policy-cards.js +1 -1
- package/dist/prompts/policy-cards.js.map +1 -1
- package/dist/routing/classify-intent.js +4 -5
- package/dist/routing/classify-intent.js.map +1 -1
- package/dist/routing/route-manifest.js +0 -1
- package/dist/routing/route-manifest.js.map +1 -1
- package/dist/routing/router-prompt.js +1 -1
- package/dist/routing/router.js +35 -4
- package/dist/routing/router.js.map +1 -1
- package/dist/runtime/session-coordinator.js +2 -13
- package/dist/runtime/session-coordinator.js.map +1 -1
- package/dist/system-prompt.js +1 -1
- package/dist/tools/fundamentals/dcf.d.ts +1 -1
- package/dist/tools/fundamentals/dcf.js +49 -6
- package/dist/tools/fundamentals/dcf.js.map +1 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/portfolio/daily-report.js +10 -4
- package/dist/tools/portfolio/daily-report.js.map +1 -1
- package/dist/tools/technical/backtest.d.ts +23 -5
- package/dist/tools/technical/backtest.js +131 -94
- package/dist/tools/technical/backtest.js.map +1 -1
- package/gui/server/http-routes.ts +395 -19
- package/gui/server/invoke-tool.ts +164 -16
- package/gui/server/local-session-coordinator.ts +97 -0
- package/gui/server/market-state-api.ts +1 -43
- package/gui/server/server.ts +51 -6
- package/gui/server/session-actions.ts +117 -8
- package/gui/server/tool-metadata.ts +3 -1
- package/gui/server/ws-hub.ts +61 -6
- package/gui/web/dist/assets/CatalogOverlay-ChRTKNlf.js +1 -0
- package/gui/web/dist/assets/index-BzyqyVnd.css +2 -0
- package/gui/web/dist/assets/index-DvMjkOP9.js +65 -0
- package/gui/web/dist/index.html +2 -2
- package/package.json +8 -5
- package/src/analysts/orchestrator.ts +15 -56
- package/src/cli-main.ts +253 -13
- package/src/config.ts +12 -20
- package/src/market-state/daily-report.ts +6 -16
- package/src/market-state/service.ts +0 -136
- package/src/memory/sqlite.ts +23 -19
- package/src/pi/opencandle-extension.ts +12 -265
- package/src/pi/session-action-dedupe.ts +155 -0
- package/src/pi/session-writer-lock.ts +290 -20
- package/src/pi/setup.ts +6 -6
- package/src/pi/tui-session-coordinator.ts +351 -0
- package/src/prompts/context-builder.ts +1 -1
- package/src/prompts/policy-cards.ts +1 -1
- package/src/routing/classify-intent.ts +4 -5
- package/src/routing/route-manifest.ts +0 -1
- package/src/routing/router-prompt.ts +1 -1
- package/src/routing/router.ts +39 -3
- package/src/runtime/session-coordinator.ts +2 -17
- package/src/system-prompt.ts +1 -1
- package/src/tools/AGENTS.md +1 -1
- package/src/tools/fundamentals/dcf.ts +57 -7
- package/src/tools/index.ts +0 -3
- package/src/tools/portfolio/daily-report.ts +10 -4
- package/src/tools/technical/backtest.ts +167 -108
- package/dist/tools/portfolio/predictions.d.ts +0 -55
- package/dist/tools/portfolio/predictions.js +0 -422
- package/dist/tools/portfolio/predictions.js.map +0 -1
- package/gui/web/dist/assets/CatalogOverlay-DcTXLc7u.js +0 -1
- package/gui/web/dist/assets/index-DdMnIvZ7.css +0 -2
- package/gui/web/dist/assets/index-YlMaahAS.js +0 -65
- package/src/tools/portfolio/predictions.ts +0 -553
|
@@ -2,115 +2,125 @@ import { Type } from "@sinclair/typebox";
|
|
|
2
2
|
import { wrapProvider } from "../../providers/wrap-provider.js";
|
|
3
3
|
import { getHistory } from "../../providers/yahoo-finance.js";
|
|
4
4
|
import { computeRSI, computeSMA } from "./indicators.js";
|
|
5
|
-
|
|
5
|
+
/** Flat per-side transaction cost assumption, in basis points. */
|
|
6
|
+
export const DEFAULT_COST_BPS = 5;
|
|
7
|
+
/** What this simulator deliberately does not model. Rendered in tool output. */
|
|
8
|
+
export const BACKTEST_LIMITATIONS = [
|
|
9
|
+
"Fills are simulated at the next bar's open after a signal; intrabar moves and gaps beyond that open are not modeled",
|
|
10
|
+
"Only a flat per-side cost is applied — no slippage model, spreads, or market impact",
|
|
11
|
+
"Dividends, taxes, and financing costs are excluded",
|
|
12
|
+
"Liquidity is assumed unlimited at the fill price",
|
|
13
|
+
];
|
|
14
|
+
export function runBacktest(bars, strategy, options) {
|
|
6
15
|
const closes = bars.map((b) => b.close);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
function backtestSMACrossover(bars, closes, shortWindow, longWindow, strategyName) {
|
|
16
|
-
const shortSma = computeSMA(closes, shortWindow);
|
|
17
|
-
const longSma = computeSMA(closes, longWindow);
|
|
18
|
-
if (longSma.length === 0) {
|
|
19
|
-
return emptyResult(strategyName, closes);
|
|
20
|
-
}
|
|
21
|
-
const shortOffset = shortWindow - 1;
|
|
22
|
-
const longOffset = longWindow - 1;
|
|
23
|
-
let position = false;
|
|
24
|
-
let entryPrice = 0;
|
|
25
|
-
const tradeLog = [];
|
|
26
|
-
let equity = 1.0;
|
|
27
|
-
let peak = 1.0;
|
|
28
|
-
let maxDd = 0;
|
|
29
|
-
for (let i = 0; i < longSma.length; i++) {
|
|
30
|
-
const barIdx = i + longOffset;
|
|
31
|
-
const shortSmaIdx = i + (longOffset - shortOffset);
|
|
32
|
-
const sShort = shortSma[shortSmaIdx];
|
|
33
|
-
const sLong = longSma[i];
|
|
34
|
-
const price = closes[barIdx];
|
|
35
|
-
if (!position && sShort > sLong && price > 0) {
|
|
36
|
-
// Buy signal
|
|
37
|
-
position = true;
|
|
38
|
-
entryPrice = price;
|
|
39
|
-
tradeLog.push({ type: "buy", date: bars[barIdx].date, price });
|
|
40
|
-
}
|
|
41
|
-
else if (position && sShort < sLong) {
|
|
42
|
-
// Sell signal
|
|
43
|
-
const pnl = (price - entryPrice) / entryPrice;
|
|
44
|
-
equity *= 1 + pnl;
|
|
45
|
-
tradeLog.push({ type: "sell", date: bars[barIdx].date, price, pnl });
|
|
46
|
-
position = false;
|
|
16
|
+
const costBps = options?.costBps ?? DEFAULT_COST_BPS;
|
|
17
|
+
if (strategy === "sma_crossover" || strategy === "sma_50_200_crossover") {
|
|
18
|
+
const [shortWindow, longWindow] = strategy === "sma_crossover" ? [20, 50] : [50, 200];
|
|
19
|
+
const shortSma = computeSMA(closes, shortWindow);
|
|
20
|
+
const longSma = computeSMA(closes, longWindow);
|
|
21
|
+
if (longSma.length === 0) {
|
|
22
|
+
return emptyResult(strategy, closes, costBps);
|
|
47
23
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const lastPrice = closes[closes.length - 1];
|
|
59
|
-
const pnl = (lastPrice - entryPrice) / entryPrice;
|
|
60
|
-
equity *= 1 + pnl;
|
|
61
|
-
tradeLog.push({ type: "sell", date: bars[bars.length - 1].date, price: lastPrice, pnl });
|
|
24
|
+
const signalAt = (barIdx) => {
|
|
25
|
+
const sShort = shortSma[barIdx - (shortWindow - 1)];
|
|
26
|
+
const sLong = longSma[barIdx - (longWindow - 1)];
|
|
27
|
+
if (sShort > sLong)
|
|
28
|
+
return "enter";
|
|
29
|
+
if (sShort < sLong)
|
|
30
|
+
return "exit";
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
return simulate(bars, closes, signalAt, longWindow - 1, strategy, costBps);
|
|
62
34
|
}
|
|
63
|
-
return buildResult(strategyName, equity - 1, closes, tradeLog, maxDd);
|
|
64
|
-
}
|
|
65
|
-
function backtestRSIMeanReversion(bars, closes) {
|
|
66
35
|
const rsi = computeRSI(closes, 14);
|
|
67
36
|
if (rsi.length === 0) {
|
|
68
|
-
return emptyResult("rsi_mean_reversion", closes);
|
|
37
|
+
return emptyResult("rsi_mean_reversion", closes, costBps);
|
|
69
38
|
}
|
|
70
|
-
// RSI starts at index 14 (after 14 periods of data)
|
|
71
39
|
const rsiOffset = 14;
|
|
40
|
+
const signalAt = (barIdx) => {
|
|
41
|
+
const r = rsi[barIdx - rsiOffset];
|
|
42
|
+
if (r < 30)
|
|
43
|
+
return "enter";
|
|
44
|
+
if (r > 70)
|
|
45
|
+
return "exit";
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
return simulate(bars, closes, signalAt, rsiOffset, "rsi_mean_reversion", costBps);
|
|
49
|
+
}
|
|
50
|
+
// Shared fill engine: a signal computed from bar N's close fills at bar N+1's
|
|
51
|
+
// open (no same-bar lookahead), with a flat per-side cost on every fill. A
|
|
52
|
+
// signal on the final bar is reported as pending instead of a phantom trade.
|
|
53
|
+
function simulate(bars, closes, signalAt, startIdx, strategyName, costBps) {
|
|
54
|
+
const cost = costBps / 10_000;
|
|
72
55
|
let position = false;
|
|
73
|
-
let
|
|
56
|
+
let entryFill = 0;
|
|
57
|
+
let pendingAction = null;
|
|
58
|
+
let pendingSignal = null;
|
|
74
59
|
const tradeLog = [];
|
|
75
60
|
let equity = 1.0;
|
|
76
61
|
let peak = 1.0;
|
|
77
62
|
let maxDd = 0;
|
|
78
|
-
for (let i =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
63
|
+
for (let i = startIdx; i < bars.length; i++) {
|
|
64
|
+
// Execute the previous bar's signal at this bar's open.
|
|
65
|
+
if (pendingAction === "enter" && !position) {
|
|
66
|
+
const fillPrice = bars[i].open;
|
|
67
|
+
if (fillPrice > 0) {
|
|
68
|
+
position = true;
|
|
69
|
+
entryFill = fillPrice * (1 + cost);
|
|
70
|
+
tradeLog.push({ type: "buy", date: bars[i].date, price: fillPrice });
|
|
71
|
+
}
|
|
87
72
|
}
|
|
88
|
-
else if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
73
|
+
else if (pendingAction === "exit" && position) {
|
|
74
|
+
const fillPrice = bars[i].open;
|
|
75
|
+
if (fillPrice > 0 && entryFill > 0) {
|
|
76
|
+
const pnl = (fillPrice * (1 - cost) - entryFill) / entryFill;
|
|
77
|
+
equity *= 1 + pnl;
|
|
78
|
+
tradeLog.push({ type: "sell", date: bars[i].date, price: fillPrice, pnl });
|
|
79
|
+
position = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
pendingAction = null;
|
|
83
|
+
// Evaluate the signal at this bar's close.
|
|
84
|
+
const signal = signalAt(i);
|
|
85
|
+
if ((signal === "enter" && !position) || (signal === "exit" && position)) {
|
|
86
|
+
if (i + 1 >= bars.length) {
|
|
87
|
+
pendingSignal = { type: signal === "enter" ? "buy" : "sell", date: bars[i].date };
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
pendingAction = signal;
|
|
91
|
+
}
|
|
94
92
|
}
|
|
95
|
-
// Track mark-to-market equity for accurate drawdown
|
|
96
|
-
const
|
|
93
|
+
// Track mark-to-market equity for accurate drawdown.
|
|
94
|
+
const price = closes[i];
|
|
95
|
+
const currentEquity = position && entryFill > 0 && price > 0
|
|
96
|
+
? equity * (1 + (price - entryFill) / entryFill)
|
|
97
|
+
: equity;
|
|
97
98
|
if (currentEquity > peak)
|
|
98
99
|
peak = currentEquity;
|
|
99
100
|
const dd = (peak - currentEquity) / peak;
|
|
100
101
|
if (dd > maxDd)
|
|
101
102
|
maxDd = dd;
|
|
102
103
|
}
|
|
103
|
-
// Close open position at
|
|
104
|
-
if (position) {
|
|
104
|
+
// Close any open position at the final close for reporting.
|
|
105
|
+
if (position && entryFill > 0) {
|
|
105
106
|
const lastPrice = closes[closes.length - 1];
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (lastPrice > 0) {
|
|
108
|
+
const pnl = (lastPrice * (1 - cost) - entryFill) / entryFill;
|
|
109
|
+
equity *= 1 + pnl;
|
|
110
|
+
tradeLog.push({
|
|
111
|
+
type: "sell",
|
|
112
|
+
date: bars[bars.length - 1].date,
|
|
113
|
+
price: lastPrice,
|
|
114
|
+
pnl,
|
|
115
|
+
forced: true,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
109
118
|
}
|
|
110
|
-
return buildResult(
|
|
119
|
+
return buildResult(strategyName, equity - 1, closes, tradeLog, maxDd, costBps, pendingSignal);
|
|
111
120
|
}
|
|
112
|
-
function buildResult(strategy, totalReturn, closes, tradeLog, maxDrawdown) {
|
|
113
|
-
const sellTrades = tradeLog.filter((t) => t.type === "sell" && t.pnl != null);
|
|
121
|
+
function buildResult(strategy, totalReturn, closes, tradeLog, maxDrawdown, costBpsPerSide, pendingSignal) {
|
|
122
|
+
const sellTrades = tradeLog.filter((t) => t.type === "sell" && t.pnl != null && !t.forced);
|
|
123
|
+
const forcedClosures = tradeLog.filter((t) => t.type === "sell" && t.forced).length;
|
|
114
124
|
const wins = sellTrades.filter((t) => t.pnl > 0).length;
|
|
115
125
|
const buyAndHoldReturn = closes.length > 1 && closes[0] > 0 ? (closes[closes.length - 1] - closes[0]) / closes[0] : 0;
|
|
116
126
|
return {
|
|
@@ -118,21 +128,27 @@ function buildResult(strategy, totalReturn, closes, tradeLog, maxDrawdown) {
|
|
|
118
128
|
totalReturn,
|
|
119
129
|
buyAndHoldReturn,
|
|
120
130
|
trades: sellTrades.length,
|
|
131
|
+
forcedClosures,
|
|
121
132
|
wins,
|
|
122
133
|
winRate: sellTrades.length > 0 ? wins / sellTrades.length : 0,
|
|
123
134
|
maxDrawdown,
|
|
135
|
+
costBpsPerSide,
|
|
136
|
+
pendingSignal,
|
|
124
137
|
tradeLog,
|
|
125
138
|
};
|
|
126
139
|
}
|
|
127
|
-
function emptyResult(strategy, closes) {
|
|
140
|
+
function emptyResult(strategy, closes, costBpsPerSide) {
|
|
128
141
|
return {
|
|
129
142
|
strategy,
|
|
130
143
|
totalReturn: 0,
|
|
131
144
|
buyAndHoldReturn: closes.length > 1 && closes[0] > 0 ? (closes[closes.length - 1] - closes[0]) / closes[0] : 0,
|
|
132
145
|
trades: 0,
|
|
146
|
+
forcedClosures: 0,
|
|
133
147
|
wins: 0,
|
|
134
148
|
winRate: 0,
|
|
135
149
|
maxDrawdown: 0,
|
|
150
|
+
costBpsPerSide,
|
|
151
|
+
pendingSignal: null,
|
|
136
152
|
tradeLog: [],
|
|
137
153
|
};
|
|
138
154
|
}
|
|
@@ -148,11 +164,16 @@ const params = Type.Object({
|
|
|
148
164
|
period: Type.Optional(Type.Union([Type.Literal("1y"), Type.Literal("2y"), Type.Literal("5y")], {
|
|
149
165
|
description: "Historical period to backtest: 1y, 2y, 5y. Default: 2y",
|
|
150
166
|
})),
|
|
167
|
+
cost_bps: Type.Optional(Type.Number({
|
|
168
|
+
minimum: 0,
|
|
169
|
+
maximum: 100,
|
|
170
|
+
description: `Flat per-side transaction cost in basis points applied to every fill. Default: ${DEFAULT_COST_BPS}`,
|
|
171
|
+
})),
|
|
151
172
|
});
|
|
152
173
|
export const backtestTool = {
|
|
153
174
|
name: "backtest_strategy",
|
|
154
175
|
label: "Backtest Strategy",
|
|
155
|
-
description: "
|
|
176
|
+
description: "Replay a simple trading strategy against historical daily bars. Signals fill at the next bar's open with a flat per-side cost assumption; dividends, taxes, slippage beyond that cost, and liquidity are not modeled. Supported strategies: SMA crossover (SMA20/SMA50), standard long-term SMA crossover (SMA50/SMA200), and RSI mean-reversion (buy <30, sell >70). Returns total return, win rate, max drawdown, and comparison to buy-and-hold.",
|
|
156
177
|
parameters: params,
|
|
157
178
|
async execute(_toolCallId, args) {
|
|
158
179
|
const symbol = args.symbol.toUpperCase();
|
|
@@ -179,21 +200,37 @@ export const backtestTool = {
|
|
|
179
200
|
details: null,
|
|
180
201
|
};
|
|
181
202
|
}
|
|
182
|
-
const
|
|
203
|
+
const costBps = args.cost_bps ?? DEFAULT_COST_BPS;
|
|
204
|
+
const result = runBacktest(bars, args.strategy, { costBps });
|
|
183
205
|
const outperformance = result.totalReturn - result.buyAndHoldReturn;
|
|
184
206
|
const lines = [
|
|
185
207
|
`**${symbol} Backtest: ${strategyLabel(args.strategy)}** (${bars[0].date} to ${bars[bars.length - 1].date}, ${bars.length} days)`,
|
|
186
208
|
``,
|
|
187
|
-
`Strategy Return: ${(result.totalReturn * 100).toFixed(2)}%`,
|
|
188
|
-
`Buy & Hold Return: ${(result.buyAndHoldReturn * 100).toFixed(2)}%`,
|
|
209
|
+
`Strategy Return (net of costs): ${(result.totalReturn * 100).toFixed(2)}%`,
|
|
210
|
+
`Buy & Hold Return (gross): ${(result.buyAndHoldReturn * 100).toFixed(2)}%`,
|
|
189
211
|
`Outperformance: ${outperformance >= 0 ? "+" : ""}${(outperformance * 100).toFixed(2)}%`,
|
|
190
212
|
``,
|
|
191
|
-
`Trades: ${result.trades} | Wins: ${result.wins} | Win Rate: ${(result.winRate * 100).toFixed(0)}%`,
|
|
213
|
+
`Signal Trades: ${result.trades} | Forced Closures: ${result.forcedClosures} | Wins: ${result.wins} | Win Rate: ${(result.winRate * 100).toFixed(0)}%`,
|
|
192
214
|
`Max Drawdown: ${(result.maxDrawdown * 100).toFixed(2)}%`,
|
|
193
215
|
``,
|
|
216
|
+
`Execution assumptions: signals fill at the next bar's open with a flat cost of ${costBps} bps per side.`,
|
|
217
|
+
...(result.pendingSignal
|
|
218
|
+
? [
|
|
219
|
+
`Note: a ${result.pendingSignal.type} signal fired on the final bar (${result.pendingSignal.date}) and is pending — it has no next open to fill at and is not counted as a signal trade.`,
|
|
220
|
+
]
|
|
221
|
+
: []),
|
|
222
|
+
...(result.forcedClosures > 0
|
|
223
|
+
? [
|
|
224
|
+
`Note: ${result.forcedClosures} open position${result.forcedClosures === 1 ? " was" : "s were"} liquidated at the final close for return reporting; forced closures are not counted as signal trades.`,
|
|
225
|
+
]
|
|
226
|
+
: []),
|
|
227
|
+
``,
|
|
194
228
|
result.totalReturn > result.buyAndHoldReturn
|
|
195
|
-
? `
|
|
196
|
-
: `
|
|
229
|
+
? `In this simulation the strategy outperformed buy-and-hold by ${(outperformance * 100).toFixed(2)}%.`
|
|
230
|
+
: `In this simulation buy-and-hold outperformed the strategy by ${(-outperformance * 100).toFixed(2)}%.`,
|
|
231
|
+
``,
|
|
232
|
+
`Limitations — this is a strategy replay, not an execution simulation:`,
|
|
233
|
+
...BACKTEST_LIMITATIONS.map((limit) => `- ${limit}`),
|
|
197
234
|
];
|
|
198
235
|
return {
|
|
199
236
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backtest.js","sourceRoot":"","sources":["../../../src/tools/technical/backtest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"backtest.js","sourceRoot":"","sources":["../../../src/tools/technical/backtest.ts"],"names":[],"mappings":"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"}
|