Link to the source code
Generate runnable strategy code with an LLM. The optimizer analyzes a symbol across seven training days of multi-timeframe data, then emits a complete executable .mjs — exchange config, frames, seven strategies, and a Walker comparison — that you run to find the best variant on held-out test data.
@backtest-kit/ollama) — addOptimizerSchema wires data sources + train/test ranges + an LLM prompt function into one generator.Optimizer.dump() writes ./generated/btc-optimizer_BTCUSDT.mjs; running it executes a 7-strategy Walker ranked by Sharpe.cd demo/optimization
npm install
export OLLAMA_API_KEY=your_ollama_api_key
export CCXT_DUMPER_URL=your_node_ccxt_dumper_instance
npm start # → ./generated/btc-optimizer_BTCUSDT.mjs
node ./generated/btc-optimizer_BTCUSDT.mjs # run the generated comparison
addOptimizerSchema takes the training/test ranges, the source list, and a getPrompt that turns the assembled multi-timeframe messages into one strategy report; Optimizer.dump runs it and writes the executable:
import { addOptimizerSchema, Optimizer, listenOptimizerProgress } from "@backtest-kit/ollama";
addOptimizerSchema({
optimizerName: "btc-optimizer",
rangeTrain: TRAIN_RANGE, // 7 daily ranges, Nov 24–30 2025
rangeTest: TEST_RANGE, // Dec 1 2025
source: SOURCE_LIST, // 4 timeframe sources (below)
getPrompt: async (symbol, messages) => text(symbol, messages), // LLM → strategy report
});
listenOptimizerProgress(({ progress }) => console.log(`Progress: ${progress * 100}%`));
await Optimizer.dump("BTCUSDT", { optimizerName: "btc-optimizer" }, "./generated");
Optimizer.getData("BTCUSDT", { optimizerName }) is available too — it returns the per-range strategy metadata without generating code (commented out in the demo, handy for inspecting what the LLM produced).
Each source is { name, fetch, user, assistant }: fetch pulls rows from CCXT_DUMPER_URL/view/<range> for the given symbol/date window; user renders them as a markdown table followed by an exhaustive indicator legend (period, lookback, range for every column); assistant is the acknowledgement turn.
const SOURCE_LIST = [
{ name: "long-term-range", /* 1h, 48 candles, RSI/MACD/ADX/Bollinger/Fibonacci/DEMA/WMA/SMA50 … */ },
{ name: "swing-term-range", /* 30m, 96 candles, + volume/volatility/Bollinger width */ },
{ name: "short-term-range", /* 15m, fast indicators + ROC(5/10) */ },
{ name: "micro-term-range", /* 1m, 60 candles, squeeze momentum + pressure index */ },
];
// each: fetch({symbol,startDate,endDate,limit,offset}) → rows; user(symbol,data) → markdown + legend
The legends are deliberately verbose — they tell the model exactly what each column means (e.g. "RSI(14): over previous 14 candles before row timestamp, Min 0 Max 100"), so the generated strategy reasons over named indicators rather than raw numbers.
text() calls Ollama with think: true, a system instruction to return only a copy-paste-ready strategy report (no greeting, no meta-talk), the assembled source messages, and a final question asking for a fundamental (not just technical) recommendation with S/R entries and an RR target. The returned report is escaped for safe embedding into the generated .mjs:
const response = await ollama.chat({
model: "deepseek-v3.1:671b", think: true,
messages: [
{ role: "system", content: "только отчёт готовый для копипасты … Не здоровайся, не говори что делаешь" },
{ role: "system", content: "Reasoning: high" },
...messages,
{ role: "user", content: `На каких условиях мне купить ${symbol}? … RR? LONG или SHORT? … фундаментальный анализ` },
],
});
./generated/btc-optimizer_BTCUSDT.mjs is self-contained: exchange config (Binance/CCXT), frame definitions (the 7 training days + the test day), 7 strategy implementations (one per training day's generated report), a Walker setup, and progress listeners. Running it executes all seven strategies on the test data and ranks them by Sharpe — so a week of LLM analysis collapses into one comparable, reproducible artifact.
Node.js (ESM) · backtest-kit 13.6.0 · @backtest-kit/ollama 13.6.0 · Ollama (deepseek-v3.1:671b) · functools-kit · node-ccxt-dumper API.
MIT © tripolskypetr