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', 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) -> 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'
|
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
|
Show the floating price box that follows the crosshair snapped to the Y-axis (TradingView style). Default False; toggleable at runtime from the toolbar when enabled. |
False
|
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 | |
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
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 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 | |
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
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 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 | |
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 |