Engines¶
BacktestEngine¶
BacktestEngine ¶
BacktestEngine(strategy: Strategy, sesh: SeshSimulatorBase, _feed_type: Literal['tick', 'kline'] = 'tick')
Bases: _StoreBuilderMixin
Unified backtesting engine.
# Ticks
bt = BacktestEngine.by_ticks(
strategy = MyStrategy(),
data = (TickData("BTCUSDT", ...),),
sesh = sesh,
)
bt.run()
# Multi-symbol klines
bt = BacktestEngine.by_klines(
strategy = MyStrategy(),
data = (
KlineData("BTCUSDT", ..., timeframe='5m'),
KlineData("ETHUSDT", ..., timeframe='1m'),
),
sesh = sesh,
)
bt.run()
Result
engine.stats - performance metrics engine.strategy - the strategy with its final state engine.broker - the internal broker engine.sesh - the SeshSimulatorBase provided
Source code in src/tradetropy/backtest/engine.py
stats
property
¶
Performance metrics calculated automatically at the end of run().
Returns None if there were no trades or no broker is configured.
Returns:
| Name | Type | Description |
|---|---|---|
Stats |
'Stats | None'
|
Performance metrics or None |
Example
bt = BacktestEngine.by_ticks(strategy, data=(ticks,), sesh=sesh).run() print(bt.stats) print(bt.stats['Sharpe Ratio']) trades = bt.stats.trades equity = bt.stats.equity_curve
out_of_money
property
¶
True if the backtest ended because the account was wiped (equity <= 0) or a margin stop-out fired, liquidating open positions and stopping the run cleanly (mirrors backtesting.py's out-of-money behavior).
stopped_early
property
¶
True if the backtest terminated early (out-of-money or stop-out).
tick_store
property
¶
First available TickDataStore (compatibility).
by_ticks
classmethod
¶
by_ticks(strategy: Strategy, data: Tuple[TickData, ...], sesh: 'SeshSimulatorBase | None' = None, align_by_ts: bool = False, book: 'BookData | tuple | list | None' = None, sync_book: bool = False) -> 'BacktestEngine'
Prepare engine for tick data.
Data must be a tuple of TickData, one per symbol. The engine does NOT run here - call .run() to start the loop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
Strategy
|
Trading strategy instance |
required |
data
|
tuple
|
Tuple of TickData objects |
required |
sesh
|
SeshSimulatorBase
|
Optional session for testing |
None
|
align_by_ts
|
bool
|
Align symbols by timestamp instead of position |
False
|
book
|
BookData | tuple | list | None
|
Optional recorded L2 order
book replayed alongside the ticks. Pass a single BookData or a
tuple/list of them; the symbol is read from each
|
None
|
sync_book
|
bool
|
When True and the preflight finds a recoverable clock offset between the book and the ticks, the book timestamps are shifted onto the trade clock. Default False (only warn on desync). An unrecoverable desync is never shifted. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
BacktestEngine |
'BacktestEngine'
|
Prepared engine instance |
Note
align_by_ts controls how multi-symbol tick data is synchronized:
-
False (default): Symbols aligned by matrix row index (fast path). All symbols must have identical number of rows. Each on_data() call processes the same row index across all symbols, regardless of their actual timestamps. Risk: introduces look-ahead bias if symbols have different tick frequencies or timestamps.
-
True: Symbols aligned by real timestamp (merge path). Builds a unified timeline from all unique timestamps across symbols, sorted chronologically. Each symbol forward-fills to its most recent tick with ts <= current_ts. on_data() fires only when at least one symbol produces a new tick. Eliminates look-ahead bias for realistic multi-feed scenarios (e.g., BTC + ADA from independent sources). Slower than fast path due to np.searchsorted() lookups.
With a single symbol, this parameter has no effect (dispatcher always uses fast path).
Example
ticks = TickData('BTCUSDT', tick_matrix, tick_step=0.01) bt = BacktestEngine.by_ticks(MyStrategy(), data=(ticks,), sesh=sesh) bt.run()
Source code in src/tradetropy/backtest/engine.py
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | |
by_klines
classmethod
¶
by_klines(strategy: Strategy, data: Tuple[KlineData, ...], sesh: 'SeshSimulatorBase | None' = None, book: 'BookData | tuple | list | None' = None) -> 'BacktestEngine'
Prepare engine for OHLC candle data (klines).
Data must be a tuple of KlineData, one per symbol. Each KlineData must have interval_ms configured. subscribe_ticks() is not supported in this mode. The engine does NOT run here - call .run() to start the loop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
Strategy
|
Trading strategy instance |
required |
data
|
tuple
|
Tuple of KlineData objects |
required |
sesh
|
SeshSimulatorBase
|
Optional session for testing |
None
|
book
|
BookData | tuple | list | None
|
Not supported in kline mode - the L2 order book needs per-trade timestamps for the causal book_as_of lookup. Passing a book raises ConfigError; use by_ticks(book=...). |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
BacktestEngine |
'BacktestEngine'
|
Prepared engine instance |
Note
If sesh is omitted, a SeshSimulatorBase() is built by default (balance 10,000, no commission). The internal broker's feed_type is inferred automatically from the engine mode.
Example
klines_btc = KlineData('BTCUSDT', btc_matrix, timeframe='5m') klines_eth = KlineData('ETHUSDT', eth_matrix, timeframe='1m') bt = BacktestEngine.by_klines( MyStrategy(), data=(klines_btc, klines_eth), sesh=sesh, ) bt.run()
Source code in src/tradetropy/backtest/engine.py
run ¶
run(params: dict = None, verbose: bool = False, save_log: 'bool | None' = None, stats_warn: bool = True) -> 'BacktestEngine'
Execute the complete backtest.
Call after by_ticks() or by_klines(). Returns self for optional chaining.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict
|
Optional dict to override parameters before running |
None
|
verbose
|
bool
|
Enable strategy logger output to console |
False
|
save_log
|
bool
|
Write log to file. None uses engine default |
None
|
stats_warn
|
bool
|
Emit the "Stats: insufficient sample" UserWarning when the sample (duration/closed trades) is too small to trust the annualized/trade-distribution metrics. The gating that zeroes those metrics to NaN and sets stats["_low_sample"] always applies; set stats_warn=False to silence just the warning for quick exploratory runs on small datasets. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
BacktestEngine |
'BacktestEngine'
|
Self for method chaining |
Note
save_log=None uses _DEFAULT_SAVE_LOG (False in backtest). Requires verbose=True and log_file defined in strategy.
Example
result = BacktestEngine.by_ticks( strategy, data=(ticks,), sesh=sesh, ).run()
Source code in src/tradetropy/backtest/engine.py
rerun ¶
Create new engine with same data, run with new parameters.
Creates a new engine with the same data and a cloned session, runs the backtest with the provided parameters and returns the new instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict
|
New parameters for the backtest |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
BacktestEngine |
'BacktestEngine'
|
New engine with results |
Example
bt_optimal = bt_original.rerun(params=result.best_params) bt_optimal.plot()
Source code in src/tradetropy/backtest/engine.py
plot ¶
plot(theme: str = 'light', width: int = 1200, plot_trades: bool = True, plot_volume: bool = True, ohlc_style: str = 'candle', plot_drawdown: bool = False, plot_footprint: bool = True, plot_stats: bool = False, plot_pl: bool = False, pl_height: int = 100, ohlc_height: int = 410, equity_height: int = 110, drawdown_height: int = 80, indicator_height: int = 100, footprint_zoom_range: int = 40, labels_zoom_range: int = 100, max_candles: int = 10000, equity_mode: str = 'return', equity_unit: str = 'percent', output: str = 'show', filename: str = 'backtest.html', title: str = 'Backtest', resample_timeframe: str | None = None, align_trades_to_candle: bool = True, max_trailing_dd: float | None = None, output_backend: str = 'webgl', show_price_tag: bool = False, header_text: str | None = None, footer_text: str | None = None, superimpose: bool | str = False, derender_on_pan: bool = True) -> None
Generate interactive backtest chart.
Requires: pip install bokeh
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
theme
|
str
|
'light' or 'dark' |
'light'
|
width
|
int
|
Total width in pixels |
1200
|
plot_trades
|
bool
|
Show trade entry/exit lines |
True
|
plot_volume
|
bool
|
Show volume bars |
True
|
ohlc_style
|
str
|
Price panel style - 'candle' (Japanese candlesticks, default) or 'bar' (OHLC bars: High-Low vertical with open/close ticks) |
'candle'
|
plot_drawdown
|
bool
|
Show drawdown panel |
False
|
plot_footprint
|
bool
|
Show footprint (requires FpProxy) |
True
|
plot_stats
|
bool
|
Show statistics bar |
False
|
plot_pl
|
bool
|
Show P&L panel per trade |
False
|
pl_height
|
int
|
P&L panel height in pixels |
100
|
ohlc_height
|
int
|
Main OHLC panel height |
410
|
equity_height
|
int
|
Equity/return panel height |
110
|
drawdown_height
|
int
|
Drawdown panel height |
80
|
indicator_height
|
int
|
Default height for indicator panels |
100
|
footprint_zoom_range
|
int
|
Max candles to display footprint |
40
|
labels_zoom_range
|
int
|
Max candles in view to display text labels |
100
|
max_candles
|
int
|
Candle render limit (performance) |
10000
|
equity_mode
|
str
|
'none' | 'balance' | 'return' |
'return'
|
equity_unit
|
str
|
'currency' | 'percent' |
'percent'
|
output
|
str
|
'notebook' | 'file' | 'show' |
'show'
|
filename
|
str
|
HTML filename (only if output='file') |
'backtest.html'
|
title
|
str
|
Browser tab / window title. Default 'Backtest'. |
'Backtest'
|
resample_timeframe
|
str
|
Resample candles to given timeframe (e.g. '1m', '5m', '1h', '1d'). |
None
|
align_trades_to_candle
|
bool
|
Align trade timestamps to candle open |
True
|
max_trailing_dd
|
float
|
Maximum trailing drawdown (e.g. 0.2 = 20%) |
None
|
output_backend
|
str
|
'canvas' | 'webgl' | 'svg'. Default 'webgl' for smooth pan/zoom/crosshair interaction; use 'canvas' for deterministic headless PNG export and 'svg' for vector export. |
'webgl'
|
show_price_tag
|
bool
|
DEPRECATED, removed. The floating price box has been removed from the chart entirely; this kwarg is still accepted for backwards compatibility and silently ignored, emitting a DeprecationWarning. Will be removed in a future version. |
False
|
header_text
|
str
|
Optional manual note rendered above the whole chart (e.g. a title). Raw HTML, not escaped -- do not pass untrusted/external text. None (default) renders nothing. |
None
|
footer_text
|
str
|
Optional manual note rendered below the whole chart (e.g. a disclaimer). Same HTML caveat as header_text. None (default) renders nothing. |
None
|
superimpose
|
bool | str
|
Overlay translucent, wick-less higher-timeframe candle bodies behind the main OHLC. True auto-selects a higher TF from the chart's own interval; a string (e.g. '4h') sets it explicitly. False (default) disables it. See PlotConfig.superimpose for the full auto-selection rules. |
False
|
derender_on_pan
|
bool
|
Temporarily hide heavy overlay glyphs (scatter markers, text labels) while dragging/wheel-zooming, restoring them once the interaction settles. Default True; set to False to disable the whole mechanism. |
True
|
Example
bt.plot() bt.plot(theme='dark', plot_trades=False) bt.plot(theme='dark', width=1400, equity_mode='balance')
Source code in src/tradetropy/backtest/engine.py
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | |
optimize ¶
optimize(maximize=None, minimize=None, constraints=None, method='grid', iterations=100, workers=None, progress=True, **param_lists)
Optimize strategy parameters.
Each parameter is passed as an explicit list of values to explore:
bt.optimize(
maximize = 'Sharpe Ratio',
fast_ma = [10, 20, 30, 50],
threshold = [0.1, 0.5, 1.0],
mode = ['trend', 'mean_revert'],
)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
maximize
|
str
|
Name of the metric to maximize |
None
|
minimize
|
str
|
Name of the metric to minimize |
None
|
constraints
|
Function (params: dict) -> bool for filtering |
None
|
|
method
|
str
|
'grid' or 'random' |
'grid'
|
iterations
|
int
|
Number of random samples (only with method='random') |
100
|
workers
|
int
|
Parallel processes (None -> cpu_count) |
None
|
progress
|
bool
|
Show a single aggregate progress bar counting completed backtests (default True). One bar for the whole optimization, not one per backtest. |
True
|
**param_lists
|
Parameter name -> list of values to explore |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
OptimizationResult |
With best_params, best_fitness, best_stats, top(n), and to_dataframe() method |
Source code in src/tradetropy/backtest/engine.py
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 | |
montecarlo ¶
montecarlo(n_sims=1000, methods=None, metrics=None, confidence=(0.95, 0.99), seed=None, workers=None)
Run a Monte Carlo robustness test on the finished backtest.
Generates many randomized variants of the result to estimate the distribution of performance metrics, confidence intervals, the probability of loss, the risk of ruin and a composite robustness score.
Methods operate at one of three levels (they cannot be mixed across levels in a single call):
- Trade level (fast, no re-run): 'shuffle_order', 'resample_trades',
'skip_trades', 'randomize_slippage', 'random_start_index'.
- Data level (re-runs the engine): 'randomize_prices',
'random_start_bar'.
- Parameter level (re-runs the engine): 'randomize_parameters'
(pass an instance with a search space).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_sims
|
int
|
Number of simulations to run. |
1000
|
methods
|
Sequence
|
Method identifiers (str) or MCMethod instances. Defaults to ['resample_trades']. |
None
|
metrics
|
Sequence[str]
|
Stats keys to track. Defaults to a standard set (Return, Max Drawdown, Sharpe, Profit Factor, Win Rate). |
None
|
confidence
|
Sequence[float]
|
Confidence levels in (0, 1). |
(0.95, 0.99)
|
seed
|
int
|
Base seed for reproducibility. |
None
|
workers
|
int
|
Parallel processes for the re-run path (None -> cpu_count). Ignored on the trade-level path. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
MonteCarloResult |
With summary(), to_dataframe(), percentile(), confidence_interval(), probability_of_loss, risk_of_ruin() and robustness_score. |
Example
bt.run() mc = bt.montecarlo(n_sims=1000, methods=['shuffle_order'], seed=42) print(mc.summary()) print(mc.robustness_score)
Source code in src/tradetropy/backtest/engine.py
PoolBacktestEngine¶
PoolBacktestEngine ¶
Runs multiple strategies in parallel with shared memory.
USAGE
With ticks [N x >=7]:¶
results = PoolBacktestEngine.by_ticks( strategies = [S1, S2, S3], data = (TickData("BTCUSDT", tick_matrix, tick_size=0.01),), workers = 8, )
With klines:¶
results = PoolBacktestEngine.by_klines( strategies = [S1, S2, S3], data = (KlineData("BTCUSDT", kline_matrix, timeframe=60_000),), workers = 8, )
The data type (TickData/KlineData) determines the mode -- it is never inferred from shape. Symbol config travels with the data.
Advantages
- SMA(20) on BTCUSDT shared across 400 strategies -> computed only once.
- Footprints pre-computed in bulk -> zero recalculation in workers.
- Works on Linux (fork), macOS and Windows (spawn).
by_ticks
classmethod
¶
by_ticks(strategies: list, data, workers: int | None = None, book: 'BookData | tuple | list | None' = None, sync_book: bool = False) -> list
Run strategies with tick data.
data : TickData or tuple/list of TickData (one per symbol). subscribe_ticks() and subscribe_footprint() are valid in this mode.
BookData or tuple/list of BookData with the recorded L2 book
to replay alongside ticks (enables DeepTrades / L2 metrics in the
pool, same as in backtest). The symbol is taken from each
BookData.symbol (no {symbol: BookData} map). A sync
preflight warns if the book is out of sync with the trades.
sync_book : if True and the preflight finds a recoverable clock offset, shifts the book to the trades' clock. Default False (warn only).
Source code in src/tradetropy/backtest/pool.py
by_klines
classmethod
¶
by_klines(strategies: list, data, workers: int | None = None, book: 'BookData | tuple | list | None' = None) -> list
Run strategies with OHLC bar data.
data : KlineData or tuple/list of KlineData (each with interval_ms). subscribe_ticks() and subscribe_footprint() are not supported.
Source code in src/tradetropy/backtest/pool.py
run
classmethod
¶
run(strategies: list, data: 'SymbolInput | tuple[SymbolInput, ...] | list[SymbolInput]', workers: int | None = None, save_log: 'bool | None' = None, book: 'BookData | tuple | list | None' = None, sync_book: bool = False) -> list
Unified entry point for PoolBacktestEngine.
.. note::
save_log is accepted for API consistency with other
engines, but is a no-op in pool/optimize: each worker uses
NullLogger (zero I/O), so nothing is ever written to a file.
Accepts two forms:
Typed API (v2.2+, preferred):
data is TickData, KlineData, or a list of them.
The mode is inferred from the type -- there is no mode parameter.
Symbol config travels with the data; no need to add it manually.
Example::
PoolBacktestEngine.run(
strategies = [S1, S2],
data = TickData("BTCUSDT", tick_matrix,
tick_step=0.25, tick_value=1.25),
workers = 4,
)
PoolBacktestEngine.run(
strategies = [S1, S2],
data = [
TickData("BTCUSDT", btc_ticks),
TickData("ETHUSDT", eth_ticks),
],
)
Legacy API (dict, compatible with v2.0/v2.1):
data is a dict {symbol: ndarray}. The mode is inferred from
shape[1] as in earlier versions. Kept for backwards
compatibility.
Example::
PoolBacktestEngine.run(
strategies = [S1, S2],
data = {"BTCUSDT": tick_matrix}, # [N x >=7]
workers = 4,
)
Source code in src/tradetropy/backtest/pool.py
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | |
LiveEngine¶
LiveEngine ¶
LiveEngine(strategy: Strategy, sesh=None, _feed_type: Literal['tick', 'kline'] = 'tick', _poll_interval: float = 1.0, chart_ohlc_interval_ms: int = 60000, require_warmup: bool = True)
Engine for live trading.
Handles automatic warmup (historical data loading), indicator initialization, and real-time feed loop for tick or candle-based strategies.
Preferred constructors: - LiveEngine.by_ticks(strategy, sesh=sesh) - warmup in ticks - LiveEngine.by_klines(strategy, sesh=sesh) - warmup in candles
Automatic Warmup: - by_ticks: Loads strategy.warmup ticks (with hybrid historical candle support) - by_klines: Loads strategy.warmup candles
Typical Usage
engine = LiveEngine.by_ticks(MyStrategy(), sesh=sesh) engine.run()
With chart (automatic wiring):¶
engine.run(live_chart=chart)
With chart (manual, fine control):¶
engine.prepare() engine.attach_chart(chart) chart.start() engine.run()
Source code in src/tradetropy/live/engine.py
sesh
property
¶
Get the session (broker) connected to the engine.
Returns:
| Name | Type | Description |
|---|---|---|
Session |
The broker instance. |
feed_type
property
¶
Get the engine feed type.
Returns:
| Name | Type | Description |
|---|---|---|
FeedType |
FeedType
|
Either 'tick' or 'kline'. |
by_ticks
classmethod
¶
by_ticks(strategy: Strategy, sesh=None, poll_interval: float = 1.0, chart_ohlc_interval_ms: int = 60000, require_warmup: bool = True) -> 'LiveEngine'
Create LiveEngine with tick-based warmup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
Strategy
|
Strategy instance (must have warmup attribute). |
required |
sesh
|
Optional session (broker) instance. |
None
|
|
poll_interval
|
float
|
Polling interval in seconds. |
1.0
|
chart_ohlc_interval_ms
|
int
|
Interval (ms) of the chart-only OHLC proxy auto-injected when the strategy subscribes ticks but no OHLC. Default 60_000 (1 minute). Used only for the chart; never fed to on_data(). |
60000
|
require_warmup
|
bool
|
If False, a broker returning zero historical ticks or klines is tolerated (warning instead of DataError) and the engine starts with empty rings. Default True (strict). |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
LiveEngine |
'LiveEngine'
|
Engine configured for tick-based operation. |
Source code in src/tradetropy/live/engine.py
by_klines
classmethod
¶
by_klines(strategy: Strategy, sesh=None, poll_interval: float = 1.0, require_warmup: bool = True) -> 'LiveEngine'
Create LiveEngine with candle-based warmup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
Strategy
|
Strategy instance (must have warmup attribute). |
required |
sesh
|
Optional session (broker) instance. |
None
|
|
poll_interval
|
float
|
Polling interval in seconds. |
1.0
|
require_warmup
|
bool
|
If False, a broker returning zero historical klines is tolerated (warning instead of DataError) and the engine starts with empty rings. Default True (strict). |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
LiveEngine |
'LiveEngine'
|
Engine configured for candle-based operation. |
Source code in src/tradetropy/live/engine.py
attach_chart ¶
Connect a LiveChart to the engine for real-time visualization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chart
|
LiveChart instance to attach. |
required |
Raises:
| Type | Description |
|---|---|
TradingError
|
If chart is not a LiveChart instance. |
Source code in src/tradetropy/live/engine.py
prepare ¶
Prepares the engine: fetches historical data, builds rings, warms indicators and calls strategy.init().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
historico
|
'dict | None'
|
optional dict with preloaded data (for tests). Format: {symbol: tick_array} and/or {(symbol, interval_ms): kline_array}. |
None
|
Source code in src/tradetropy/live/engine.py
run ¶
run(params: dict = None, verbose: bool = False, blocking: bool = True, live_chart=None, save_log: 'bool | None' = None)
Start the feed loop. Returns self for chaining.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict
|
Optional dict to override strategy parameters before starting (equivalent to BacktestEngine.run). |
None
|
verbose
|
bool
|
Enable diagnostic prints. |
False
|
blocking
|
bool
|
True -> blocks current thread. False -> launches daemon thread. |
True
|
live_chart
|
Optional LiveChart. If passed, engine connects and starts it automatically (equivalent to: prepare() -> attach_chart() -> start() -> run()). Done in correct order, so it's sufficient to call: engine.run(live_chart=chart) |
None
|
|
save_log
|
'bool | None'
|
Write strategy log to file (strategy.log_file). None -> uses engine default (_DEFAULT_SAVE_LOG = True in live, False in replay). Requires log_file to be defined. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
Engine instance for chaining. |
Raises:
| Type | Description |
|---|---|
TradingError
|
If both positional and live_chart= LiveChart passed. |
Source code in src/tradetropy/live/engine.py
stop ¶
Stop the run() loop cleanly.
In live mode, flushes any pending tick/OHLC records to disk before stopping the loop thread.
Source code in src/tradetropy/live/engine.py
on_tick ¶
Process a tick in tick mode (manual feed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol. |
required |
tick
|
ndarray
|
Tick array [ts_ms, bid, ask, volume, flags, volume_real, price]. |
required |
Source code in src/tradetropy/live/engine.py
on_kline ¶
Process a candle (kline) in kline mode (manual feed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol. |
required |
kline
|
ndarray
|
Kline array [ts_ms, open, high, low, close, volume, turnover]. |
required |
Source code in src/tradetropy/live/engine.py
ReplayEngine¶
ReplayEngine ¶
ReplayEngine(strategy: Strategy, data, sesh: '_ReplaySesh | None' = None, history: 'dict | None' = None, warmup_ticks: 'int | None' = None, warmup_pct: float = 0.2, _feed_type: str = 'tick', _poll_interval: float = 0.0, speed: float = 1.0, base_rate: float = 1.0, book: 'BookData | tuple | list | None' = None, sync_book: bool = False, chart_ohlc_interval_ms: int = 60000)
Bases: BaseEngine
Automated, forward-only replay engine over historical data.
Specialization of BaseEngine for auditing a programmatic strategy: it keeps
backward navigation disabled (_ALLOW_BACKWARD = False) so the Step
Backward (« ) control is hidden, matching PaperEngine. Use Restart to
rewind to the beginning and replay from scratch. Replay does not persist the
log by default (_DEFAULT_SAVE_LOG = False), same as backtest.
Quick mode (data + broker kwargs -> automatic ReplaySesh): engine = ReplayEngine.by_ticks(strategy, data=data, commission=1.5)
Full control mode (pre-configured ReplaySesh): sesh = ReplaySesh(feed_type='tick', commission=1.5) engine = ReplayEngine.by_ticks(strategy, data=data, sesh=sesh)
Source code in src/tradetropy/playback/base.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | |
PaperEngine¶
PaperEngine ¶
PaperEngine(strategy: Strategy, data, sesh: '_ReplaySesh | None' = None, history: 'dict | None' = None, warmup_ticks: 'int | None' = None, warmup_pct: float = 0.2, _feed_type: str = 'tick', _poll_interval: float = 0.0, speed: float = 1.0, base_rate: float = 1.0, book: 'BookData | tuple | list | None' = None, sync_book: bool = False, chart_ohlc_interval_ms: int = 60000)
Bases: BaseEngine
Manual, forward-only paper-trading engine driven by the UI Order Ticket.
Specialization of BaseEngine that forbids backward navigation
(_ALLOW_BACKWARD = False) so the user cannot peek ahead or rewind single
trades; the only reset is Restart (wipes the ledger, restores the baseline
balance and seeks to index 0). It synthesizes its strategy from a
PaperConfig, so no programmatic strategy is supplied.
Source code in src/tradetropy/playback/base.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | |
by_ticks
classmethod
¶
by_ticks(config: PaperConfig, data, sesh: 'ReplaySesh | None' = None, history: 'dict | None' = None, warmup_ticks: 'int | None' = None, warmup_pct: float = 0.2, speed: float = 1.0, base_rate: float = 1.0, poll_interval: float = 0.0, book: 'BookData | tuple | list | None' = None, chart_ohlc_interval_ms: int = 60000) -> 'PaperEngine'
Build a forward-only paper-trading engine over historical ticks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PaperConfig
|
Declarative session configuration. |
required |
data
|
Tuple of TickData (one per symbol). |
required | |
sesh
|
ReplaySesh | None
|
Optional pre-configured session; if omitted a ReplaySesh is built from config.initial_balance / commission. |
None
|
|
others
|
Same as ReplayEngine.by_ticks. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
PaperEngine |
'PaperEngine'
|
Configured forward-only paper-trading engine. |
Source code in src/tradetropy/paper/engine.py
by_klines
classmethod
¶
by_klines(config: PaperConfig, data, sesh: 'ReplaySesh | None' = None, history: 'dict | None' = None, warmup_ticks: 'int | None' = None, warmup_pct: float = 0.2, speed: float = 1.0, base_rate: float = 1.0, poll_interval: float = 0.0) -> 'PaperEngine'
Build a forward-only paper-trading engine over historical klines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PaperConfig
|
Declarative session configuration. |
required |
data
|
Tuple of KlineData (one per symbol-interval pair). |
required | |
sesh
|
ReplaySesh | None
|
Optional pre-configured session. |
None
|
|
others
|
Same as ReplayEngine.by_klines. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
PaperEngine |
'PaperEngine'
|
Configured forward-only paper-trading engine. |