This strategy achieved +16.99% PnL during February 2026 — a month when BTC fell −16.4% peak-to-trough. Rather than following technical indicators that lagged the macro-driven selloff, the strategy read live news and macro headlines every few hours, asked a local LLM to classify the environment asDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-docs/llms.txt
Use this file to discover all available pages before exploring further.
bullish, bearish, or wait, and held the position until either a trailing take-profit fired or the sentiment flipped to an opposing forecast. The LLM correctly held SHORT bias for nearly the entire month while BTC fell from ~60k, switched briefly to LONG on a recovery bounce, then reversed back to SHORT on geopolitical escalation news.
Backtest results (February 2026)
| Metric | Value |
|---|---|
| BTC price move (month) | −16.4% (65,879) |
| Strategy net PNL | +16.99% |
| Sharpe ratio | 0.25 |
| Win rate | 68.8% (11 / 16 trades) |
| Profit factor | 2.25 |
| Avg win | +2.78% |
| Avg loss | −2.72% |
| Best trade | +14.28% (SHORT Feb 4: 64,657) |
| Worst trade | −3.41% (stop-loss) |
| Direction split | 14 × SHORT / 2 × LONG |
| Closed by trailing take-profit | 9 |
| Closed by stop-loss | 4 |
| Closed by sentiment flip | 3 |
The full reference implementation is available at github.com/tripolskypetr/backtest-kit/tree/master/example/content/feb_2026.strategy. It includes the Tavily fetch logic, the Ollama prompt format, and the trailing exit implementation.
How it works
The strategy operates on two independent clocks: a periodic news refresh job and a per-candle signal check.Step 1 — Periodic news fetch (every 4–8 hours via Cron)
Step 1 — Periodic news fetch (every 4–8 hours via Cron)
A
Cron job registered with interval: '4h' fires once per virtual 4-hour boundary. It calls the Tavily search API with queries covering Bitcoin, macro economics, and geopolitical risk, collects the returned headlines and summaries, and passes the text to a local Ollama LLM instance.The LLM prompt asks for a single-word forecast: bullish, bearish, or wait. The response is written to a module-level variable currentForecast. In backtest mode, the cron job fires at the correct virtual timestamps — the same code runs live by simply calling Cron.enable() before starting the engine.Step 2 — Signal generation on every 15-minute candle
Step 2 — Signal generation on every 15-minute candle
addStrategySchema registers the strategy on a 15-minute interval. On every candle, getSignal reads currentForecast:'wait'→ returnnull(no new position opened)'bullish'→ open LONG with trailing take-profit (1% drawdown from peak) and stop-loss (1% from entry)'bearish'→ open SHORT with the same trailing/stop parameters
getSignal returns the same direction, the signal is silently rejected (no duplicate). If there is no open position and the forecast is wait, nothing happens until the next news refresh changes the forecast.Step 3 — Sentiment flip closes the current position mid-trade
Step 3 — Sentiment flip closes the current position mid-trade
While a position is open, each
listenActivePing tick checks whether the latest currentForecast conflicts with the open position direction. A bullish forecast while SHORT, or a bearish forecast while LONG, triggers commitClosePending to close the current position at market. The next call to getSignal will then open a fresh position in the new direction.Three of the 16 February trades were closed this way — including the Feb 9 SHORT that was exited for −0.01% when signals briefly became mixed before the LLM returned to a SHORT bias.Step 4 — Exit: trailing take-profit or stop-loss
Step 4 — Exit: trailing take-profit or stop-loss
Positions that are not flipped by a sentiment change close via two exit conditions registered on
listenActivePing:- Trailing take-profit: tracks the peak profit seen since entry. If the current profit falls more than 1% below the peak, the position closes. This lets winning trades run during fast trending moves (the +14.28% Feb 4 SHORT rode most of a $11k BTC decline) while cutting off retracements.
- Stop-loss: a fixed 1% from the entry price. Four trades in February hit this level.
Install dependencies
@backtest-kit/ollama provides a unified multi-provider LLM interface supporting Ollama, OpenAI, Claude, DeepSeek, Grok, Mistral, and others. agent-swarm-kit is required as a peer dependency for the agent coordination layer.
Strategy code pattern
Environment variables
Key techniques
Cron virtual-time scheduler:Cron fires handlers on virtual time boundaries, not wall-clock time. In backtest mode, a 4h interval fires once every four simulated hours as the engine replays historical candles. In live mode, it fires every four real hours. The same strategy code runs in both modes with no branching.
Position flip on sentiment change: Rather than letting the strategy accumulate both LONG and SHORT positions, the active-ping handler closes any position that conflicts with the current forecast. This keeps the strategy always aligned with the most recent LLM signal while avoiding the complexity of managing opposing positions.
Trailing exit for trending moves: The trailing take-profit (1% drawdown from peak) captures the bulk of sharp directional moves, like the Feb 4 SHORT that rode $11k of BTC decline before the trailing stop fired at +14.28%. A fixed take-profit would have closed the same trade much earlier.