Skip to main content

execution-context test suite

Added services/backend/tests/execution-context.test.ts — 23 tests verifying that input.execution is correctly populated in both the backtest runner and the live bot runner.

What is tested​

Backtest (13 tests)​

  • execution.market.pipSize = 0.0001 for EURUSD
  • execution.market.lotSize/minLotSize/lotStep correct for forex (100_000 / 0.01 / 0.01)
  • execution.market.previousClose matches the candle immediately before the current one (null at index 0)
  • execution.clock fields for a known London session candle (Tuesday 09:05 UTC): dayOfWeek=2, isLondonSession=true, isNewYorkSession=false
  • execution.clock.isNewYorkSession true during 14:00 UTC; London+NY overlap verified
  • execution.clock.isWeekend=true on Saturday; session flags all false
  • execution.bot.id/name/status are null in backtest context; symbol and isPaper=false correct
  • execution.schedule.upcomingEvents is empty array; allowed=true, reason=null
  • execution.costs.spreadPips/slippagePips reflect assumedSpreadPips/assumedSlippagePips parameters; commission type forwarded
  • session.dailyTradeCount increments from 0 → 1 after the first trade closes
  • session.consecutiveWins/consecutiveLosses are non-negative integers throughout
  • portfolio.cash equals initialBalance before any trades; equity equals cash with no open position
  • Real ClickHouse EURUSD 4h fixture: pipSize, lotSize, bot nulls, empty events, clock hour/dayOfWeek

Live bot runner (10 tests)​

  • execution.market.pipSize/lotSize/minLotSize/lotStep correct for EURUSD via bundled strategy metadata
  • execution.market.previousClose = second-to-last candle's close
  • execution.clock.evaluatedAt is a valid ISO string; all session flags are booleans; dayOfWeek in 1–7
  • execution.bot.id/name/symbol/status/isPaper match the BotRow values
  • execution.session.allTimeTrades/allTimePnl/allTimeWinRate read from bot.total_trades/total_profit/win_rate
  • execution.schedule.allowed is boolean
  • execution.costs.commission.type = 'per_lot' when commissionModel parameter is set
  • execution.costs.spreadPips/slippagePips from assumedSpreadPips/assumedSlippagePips parameters
  • portfolio.cash = bot.current_balance (not hardcoded 0)

Approach​

  • Backtest tests use a native StrategyDefinition that captures StrategyExecutionInput via a closure — no QuickJS overhead, direct field access.
  • Live bot tests use a bundled entry.js that returns input.execution.* fields in metadata for assertion via evaluateBotWithCandles().
  • Synthetic candles are pinned to known UTC timestamps so session flag assertions are deterministic.
  • One test uses real ClickHouse EURUSD data from tests/fixtures/strategy-real-data/eurusd-clickhouse-smoke.json.