The strategy layer is the final consumer of the pipeline. Rather than evaluating raw Telegram messages directly,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-ollama-crontab/llms.txt
Use this file to discover all available pages before exploring further.
jan_2026.strategy.ts reads screen-items rows that have already been enriched with LLM risk assessments produced by the RiskOutline, and opens positions only when the LLM has voted follow and the live price is sitting within the signal’s prescribed entry zone. This separation of concerns keeps the decision logic simple: empirical rules about market conditions live in the Ollama prompt; the strategy code only acts on the verdict.
Strategy Decision Logic
The strategy is registered viaaddStrategySchema. The getSignal function runs on every 1-minute candle for every tracked symbol. It first fetches the most recent LLM-assessed signal from screen-items, enforces the riskAction verdict, validates the current price against the entry zone, and then returns the position parameters or null.
Position Parameters
WhengetSignal returns a non-null value, backtest-kit uses the following fields to open and manage the position:
| Field | Source | Description |
|---|---|---|
position | signal.direction | "long" or "short" — the trade direction as parsed from the Telegram signal |
priceStopLoss | signal.stoploss | The stop-loss level extracted from the signal text and stored in screen-items |
priceTakeProfit | signal.targets[2] | The third take-profit target (TP3) from the signal’s target array — deliberately the most ambitious exit |
minuteEstimatedTime | Infinity | No time-based exit; the position remains open until either TP3 or the stop-loss is hit |
note | JSON.stringify(info, null, 2) | Full JSON payload containing signal metadata and LLM risk fields — visible in the backtest-kit UI |
targets[2] (TP3) as the take-profit means the strategy holds for the full projected move. Combined with minuteEstimatedTime: Infinity, there is no forced time-exit — the trade either succeeds or fails on its own merits.
Signal Lookup
getLast4HourSignal(symbol, when) delegates to ScreenDbService.findLast4HourRow, which queries the screen-items MongoDB collection for the most recent document matching the given symbol whose publishedAt falls within the four-hour window [when − 4h, when], sorted by publishedAt descending.
getSignal returns null and no position is opened.
Entry Zone Check
[entryFrom, entryTo].
Entering outside the zone would invalidate the signal’s risk-to-reward assumptions. If the price has already broken through TP1 before entry, the remaining upside to TP3 is compressed while the stop-loss distance stays the same, worsening the R:R ratio. The zone check enforces that the trade is only taken when the original setup is still intact.
Active Position Monitoring
For every active position,listenActivePing fires on each candle tick and logs four key metrics:
peakProfitDistance— the highest favourable PnL cost reached since position open; shows how far in profit the trade went at its best.peakMaxDrawdown— the largest adverse PnL cost recorded since open; measures how deep the trade went against you before recovering (or hitting the stop).currentPnl— the unrealised PnL cost at the current candle close.currentPrice— the raw market price at tick time, logged alongside open price, TP, and SL for full context.
Note Payload
When a position is opened, the fullinfo object is JSON-stringified into the note field. This payload is stored in the position record and is visible in the backtest-kit UI’s trade detail view:
risk block captures all five LLM-generated fields from the RiskOutline:
| Field | Type | Description |
|---|---|---|
action | "skip" | "follow" | The LLM’s binary verdict — only "follow" reaches getSignal return |
sureLevel | "low" | "low_medium" | "medium" | "medium_high" | "high" | Confidence in the signal setup quality |
confidence | "reliable" | "not_reliable" | Whether the LLM considers its own assessment trustworthy |
description | string | Short human-readable summary of the LLM’s assessment |
reasoning | string | Full chain-of-thought reasoning from the LLM |
parsed field contains the original signal.note — typically the raw text extracted from the Telegram message by the parser — providing a complete audit trail from source message to open position.