Interactive Backtest Mode¶
BacktestRunner supports an interactive mode with step-by-step execution, pause, breakpoints, and state inspection. This is useful for debugging strategies and understanding market dynamics at specific points in time.
Quick Start¶
#include "flox/backtest/backtest_runner.h"
BacktestRunner runner;
runner.setStrategy(&myStrategy);
// Set callbacks for debugging
runner.setEventCallback([](const replay::ReplayEvent& ev, const BacktestState& state) {
std::cout << "Event " << state.eventCount << " at " << state.currentTimeNs << "\n";
});
runner.setPauseCallback([](const BacktestState& state) {
std::cout << "Paused at event " << state.eventCount << "\n";
});
// Start in background thread (starts paused)
std::thread t([&]() { runner.start(reader); });
// Step through events one by one
runner.step(); // Process 1 event
runner.step(); // Process another
// Run until breakpoint or end
runner.resume();
t.join();
Two Modes¶
BacktestRunner supports two execution modes:
Non-Interactive Mode¶
Synchronous execution from start to end:
BacktestRunner runner;
runner.setStrategy(&myStrategy);
// Blocks until complete
BacktestResult result = runner.run(reader);
Interactive Mode¶
Async execution with pause/step control:
BacktestRunner runner;
runner.setStrategy(&myStrategy);
// Start in background (begins paused)
std::thread t([&]() { runner.start(reader); });
// Control execution
runner.step(); // One event
runner.resume(); // Run until breakpoint/end
runner.pause(); // Pause execution
runner.stop(); // Stop completely
t.join();
Execution Commands¶
step()¶
Execute exactly one event:
stepUntil(mode)¶
Skip events until condition:
resume()¶
Run continuously until breakpoint or end:
pause()¶
Pause execution (can resume later):
stop()¶
Stop execution completely:
Breakpoints¶
Time-based¶
Pause at specific timestamp:
Event Count¶
Pause after N events:
Trade Count¶
Pause after N trades:
Signal Breakpoint¶
Pause when strategy emits a signal:
Custom Breakpoint¶
Pause on custom condition:
runner.addBreakpoint(Breakpoint::when([](const replay::ReplayEvent& ev) {
return ev.type == replay::EventType::Trade && ev.trade.price_raw > 50000'00000000;
}));
Clear Breakpoints¶
State Inspection¶
Check current backtest state at any time:
BacktestState state = runner.state();
std::cout << "Time: " << state.currentTimeNs << "\n"
<< "Events: " << state.eventCount << "\n"
<< "Trades: " << state.tradeCount << "\n"
<< "Book updates: " << state.bookUpdateCount << "\n"
<< "Signals: " << state.signalCount << "\n"
<< "Running: " << state.isRunning << "\n"
<< "Paused: " << state.isPaused << "\n"
<< "Finished: " << state.isFinished << "\n";
Convenience methods:
Control Flow¶
stateDiagram-v2
[*] --> Paused : start()
Paused --> Processing : step()
Processing --> Paused : event processed
Paused --> Running : resume()
Running --> Paused : breakpoint hit
Running --> Paused : pause()
Running --> Finished : end of data
Paused --> Finished : stop()
Finished --> [*]
Example: Debug Strategy¶
class DebugStrategy : public Strategy {
void onTrade(const TradeEvent& ev) override {
if (shouldBuy(ev)) {
emitMarketBuy(ev.trade.symbol, Quantity::fromDouble(1.0));
}
}
};
int main() {
auto reader = replay::createMultiSegmentReader("./data");
DebugStrategy strategy;
BacktestRunner runner;
runner.setStrategy(&strategy);
// Break when signal is emitted
runner.setBreakOnSignal(true);
std::thread t([&]() { runner.start(*reader); });
// Run until first signal
runner.resume();
// Inspect state when signal was emitted
auto state = runner.state();
std::cout << "Signal emitted at trade #" << state.tradeCount << "\n";
std::cout << "Time: " << state.currentTimeNs << "\n";
// Continue running
runner.resume();
t.join();
// Get results
auto result = runner.result();
auto stats = result.computeStats();
std::cout << "Total trades: " << stats.totalTrades << "\n";
}
Thread Safety¶
start()must be called from a separate thread (it blocks until completion)step(),resume(),pause(),stop()can be called from any threadstate()returns a snapshot, safe to call anytime- Callbacks are invoked from the runner thread
See Also¶
- BacktestRunner — API reference
- SimulatedExecutor — Order execution simulation