back-trader-python 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- back_trader_python-1.4.0.dist-info/METADATA +1491 -0
- back_trader_python-1.4.0.dist-info/RECORD +465 -0
- back_trader_python-1.4.0.dist-info/WHEEL +5 -0
- back_trader_python-1.4.0.dist-info/licenses/LICENSE +674 -0
- back_trader_python-1.4.0.dist-info/top_level.txt +1 -0
- backtrader/__init__.py +148 -0
- backtrader/_cerebro/__init__.py +5 -0
- backtrader/_cerebro/channel.py +382 -0
- backtrader/_cerebro/execution.py +377 -0
- backtrader/_cerebro/lifecycle.py +143 -0
- backtrader/_cerebro/notifications.py +150 -0
- backtrader/_cerebro/presentation.py +230 -0
- backtrader/_cerebro/registry.py +593 -0
- backtrader/_cerebro/runnext.py +551 -0
- backtrader/_cerebro/runonce.py +142 -0
- backtrader/analyzer.py +594 -0
- backtrader/analyzers/__init__.py +50 -0
- backtrader/analyzers/annualreturn.py +226 -0
- backtrader/analyzers/calmar.py +165 -0
- backtrader/analyzers/drawdown.py +287 -0
- backtrader/analyzers/leverage.py +112 -0
- backtrader/analyzers/logreturnsrolling.py +190 -0
- backtrader/analyzers/periodstats.py +153 -0
- backtrader/analyzers/positions.py +119 -0
- backtrader/analyzers/pyfolio.py +470 -0
- backtrader/analyzers/returns.py +192 -0
- backtrader/analyzers/sharpe.py +307 -0
- backtrader/analyzers/sharpe_ratio_stats.py +534 -0
- backtrader/analyzers/sqn.py +112 -0
- backtrader/analyzers/timereturn.py +192 -0
- backtrader/analyzers/total_value.py +75 -0
- backtrader/analyzers/tradeanalyzer.py +278 -0
- backtrader/analyzers/transactions.py +141 -0
- backtrader/analyzers/vwr.py +245 -0
- backtrader/bokeh/__init__.py +155 -0
- backtrader/bokeh/analyzers/__init__.py +13 -0
- backtrader/bokeh/analyzers/plot.py +192 -0
- backtrader/bokeh/analyzers/recorder.py +181 -0
- backtrader/bokeh/app.py +1094 -0
- backtrader/bokeh/live/__init__.py +11 -0
- backtrader/bokeh/live/client.py +352 -0
- backtrader/bokeh/live/datahandler.py +346 -0
- backtrader/bokeh/plot_adapter.py +200 -0
- backtrader/bokeh/schemes/__init__.py +14 -0
- backtrader/bokeh/schemes/blackly.py +76 -0
- backtrader/bokeh/schemes/scheme.py +150 -0
- backtrader/bokeh/schemes/tradimo.py +82 -0
- backtrader/bokeh/tab.py +125 -0
- backtrader/bokeh/tabs/__init__.py +30 -0
- backtrader/bokeh/tabs/analyzer.py +120 -0
- backtrader/bokeh/tabs/config.py +154 -0
- backtrader/bokeh/tabs/live.py +109 -0
- backtrader/bokeh/tabs/log.py +185 -0
- backtrader/bokeh/tabs/metadata.py +182 -0
- backtrader/bokeh/tabs/performance.py +359 -0
- backtrader/bokeh/tabs/source.py +70 -0
- backtrader/bokeh/utils/__init__.py +8 -0
- backtrader/bokeh/utils/helpers.py +167 -0
- backtrader/bokeh/webapp.py +164 -0
- backtrader/broker.py +478 -0
- backtrader/brokers/__init__.py +36 -0
- backtrader/brokers/bbroker.py +2576 -0
- backtrader/brokers/btapibroker.py +8227 -0
- backtrader/brokers/hft/__init__.py +89 -0
- backtrader/brokers/hft/binance_bbo.py +625 -0
- backtrader/brokers/hft/binance_bbo_compare.py +1398 -0
- backtrader/brokers/hft/examples.py +1228 -0
- backtrader/brokers/hft/exchange.py +380 -0
- backtrader/brokers/hft/latency.py +309 -0
- backtrader/brokers/hft/matching_core.py +572 -0
- backtrader/brokers/hft/queue.py +238 -0
- backtrader/brokers/hft/recorder.py +88 -0
- backtrader/brokers/hft/state.py +138 -0
- backtrader/brokers/impact_models.py +118 -0
- backtrader/brokers/mixbroker.py +895 -0
- backtrader/brokers/tickbroker.py +1991 -0
- backtrader/btrun/__init__.py +12 -0
- backtrader/btrun/btrun.py +1218 -0
- backtrader/cerebro.py +828 -0
- backtrader/channel.py +682 -0
- backtrader/channels/__init__.py +23 -0
- backtrader/channels/bridge.py +186 -0
- backtrader/channels/funding.py +248 -0
- backtrader/channels/live_queue.py +216 -0
- backtrader/channels/live_validator.py +294 -0
- backtrader/channels/orderbook.py +257 -0
- backtrader/channels/tick.py +202 -0
- backtrader/comminfo.py +665 -0
- backtrader/commissions/__init__.py +106 -0
- backtrader/commissions/ctpoption.py +993 -0
- backtrader/configs/account_config_example.yaml +8 -0
- backtrader/dataseries.py +379 -0
- backtrader/errors.py +106 -0
- backtrader/events.py +980 -0
- backtrader/feed.py +1523 -0
- backtrader/feeds/__init__.py +75 -0
- backtrader/feeds/barrier.py +2006 -0
- backtrader/feeds/blaze.py +118 -0
- backtrader/feeds/btapifeed.py +1538 -0
- backtrader/feeds/btcsv.py +203 -0
- backtrader/feeds/chainer.py +114 -0
- backtrader/feeds/cryptohftdata.py +164 -0
- backtrader/feeds/csvgeneric.py +1205 -0
- backtrader/feeds/ctpcohort.py +1051 -0
- backtrader/feeds/influxfeed.py +158 -0
- backtrader/feeds/livefeed.py +71 -0
- backtrader/feeds/mixed_channel.py +108 -0
- backtrader/feeds/mt4csv.py +42 -0
- backtrader/feeds/pandafeed.py +381 -0
- backtrader/feeds/quandl.py +256 -0
- backtrader/feeds/rollover.py +229 -0
- backtrader/feeds/sierrachart.py +30 -0
- backtrader/feeds/vchart.py +162 -0
- backtrader/feeds/vchartcsv.py +84 -0
- backtrader/feeds/vchartfile.py +153 -0
- backtrader/feeds/yahoo.py +399 -0
- backtrader/fillers.py +148 -0
- backtrader/filters/__init__.py +34 -0
- backtrader/filters/bsplitter.py +127 -0
- backtrader/filters/calendardays.py +121 -0
- backtrader/filters/datafiller.py +192 -0
- backtrader/filters/datafilter.py +74 -0
- backtrader/filters/daysteps.py +96 -0
- backtrader/filters/heikinashi.py +63 -0
- backtrader/filters/renko.py +164 -0
- backtrader/filters/session.py +289 -0
- backtrader/flt.py +80 -0
- backtrader/functions.py +960 -0
- backtrader/indicator.py +449 -0
- backtrader/indicators/__init__.py +148 -0
- backtrader/indicators/accdecoscillator.py +110 -0
- backtrader/indicators/aroon.py +300 -0
- backtrader/indicators/atr.py +315 -0
- backtrader/indicators/awesomeoscillator.py +122 -0
- backtrader/indicators/basicops.py +834 -0
- backtrader/indicators/bollinger.py +223 -0
- backtrader/indicators/cci.py +89 -0
- backtrader/indicators/channels_ext.py +83 -0
- backtrader/indicators/contrib/__init__.py +228 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma.py +28 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma_color.py +44 -0
- backtrader/indicators/contrib/accumulation_distribution_line.py +92 -0
- backtrader/indicators/contrib/adx_cross_hull_style_indicator.py +249 -0
- backtrader/indicators/contrib/adxdmi.py +34 -0
- backtrader/indicators/contrib/ai_acceleration_deceleration_oscillator.py +34 -0
- backtrader/indicators/contrib/altr_trend_signal_v22.py +85 -0
- backtrader/indicators/contrib/anchored_momentum_line.py +115 -0
- backtrader/indicators/contrib/any_range_cld_tail_indicator.py +82 -0
- backtrader/indicators/contrib/aroon_horn_sign_indicator.py +96 -0
- backtrader/indicators/contrib/aroon_oscillator_sign_alert.py +50 -0
- backtrader/indicators/contrib/arrows_curves_indicator.py +112 -0
- backtrader/indicators/contrib/as_ctrend_indicator.py +143 -0
- backtrader/indicators/contrib/asimmetric_stoch_nr_indicator.py +187 -0
- backtrader/indicators/contrib/atr_normalize_histogram.py +118 -0
- backtrader/indicators/contrib/average_change_candle.py +165 -0
- backtrader/indicators/contrib/bb_squeeze_indicator.py +60 -0
- backtrader/indicators/contrib/bezier_st_dev_indicator.py +135 -0
- backtrader/indicators/contrib/binary_wave_indicator.py +233 -0
- backtrader/indicators/contrib/blau_c_momentum_indicator.py +123 -0
- backtrader/indicators/contrib/blau_cmi_indicator.py +141 -0
- backtrader/indicators/contrib/blau_csi.py +76 -0
- backtrader/indicators/contrib/blau_ergodic.py +53 -0
- backtrader/indicators/contrib/blau_t_stoch_i.py +72 -0
- backtrader/indicators/contrib/blau_ts_stochastic.py +85 -0
- backtrader/indicators/contrib/blau_tvi.py +55 -0
- backtrader/indicators/contrib/brain_trend2_indicator.py +128 -0
- backtrader/indicators/contrib/brain_trend_signal_proxy.py +47 -0
- backtrader/indicators/contrib/brake_parb_indicator.py +85 -0
- backtrader/indicators/contrib/breakout_bars_trend_v2.py +121 -0
- backtrader/indicators/contrib/bsi_indicator.py +87 -0
- backtrader/indicators/contrib/bulls_bears_eyes.py +67 -0
- backtrader/indicators/contrib/bulls_power.py +56 -0
- backtrader/indicators/contrib/bw_wise_man1_signal.py +102 -0
- backtrader/indicators/contrib/bykov_trend_indicator.py +85 -0
- backtrader/indicators/contrib/candle_stop_color.py +46 -0
- backtrader/indicators/contrib/candles_x_smoothed_indicator.py +69 -0
- backtrader/indicators/contrib/candlesticks_bw.py +45 -0
- backtrader/indicators/contrib/caudate_x_period_candle_color.py +56 -0
- backtrader/indicators/contrib/cci_histogram_indicator.py +53 -0
- backtrader/indicators/contrib/cci_woodies_indicator.py +80 -0
- backtrader/indicators/contrib/center_of_gravity_candle_indicator.py +83 -0
- backtrader/indicators/contrib/center_of_gravity_indicator.py +70 -0
- backtrader/indicators/contrib/cg_oscillator.py +40 -0
- backtrader/indicators/contrib/close_line_cci.py +38 -0
- backtrader/indicators/contrib/close_price_fractals.py +47 -0
- backtrader/indicators/contrib/color3rd_gen_xma_indicator.py +122 -0
- backtrader/indicators/contrib/color_bb_candles_indicator.py +108 -0
- backtrader/indicators/contrib/color_coppock_indicator.py +157 -0
- backtrader/indicators/contrib/color_hma.py +71 -0
- backtrader/indicators/contrib/color_j_variation_indicator.py +53 -0
- backtrader/indicators/contrib/color_metro_de_marker_indicator.py +78 -0
- backtrader/indicators/contrib/color_metro_stochastic_indicator.py +93 -0
- backtrader/indicators/contrib/color_metro_wpr_indicator.py +85 -0
- backtrader/indicators/contrib/color_schaff_de_marker_trend_cycle.py +92 -0
- backtrader/indicators/contrib/color_schaff_trend_cycle_indicator.py +203 -0
- backtrader/indicators/contrib/color_step_xccx_indicator.py +193 -0
- backtrader/indicators/contrib/color_x2_ma.py +49 -0
- backtrader/indicators/contrib/color_x_derivative.py +63 -0
- backtrader/indicators/contrib/color_zerolag_de_marker.py +84 -0
- backtrader/indicators/contrib/corrected_average_indicator.py +127 -0
- backtrader/indicators/contrib/darvas_boxes_system.py +73 -0
- backtrader/indicators/contrib/dema_range_channel_color.py +42 -0
- backtrader/indicators/contrib/derivative_indicator.py +95 -0
- backtrader/indicators/contrib/digital_ft01_indicator.py +112 -0
- backtrader/indicators/contrib/digital_macd.py +200 -0
- backtrader/indicators/contrib/donchian_channels_system.py +45 -0
- backtrader/indicators/contrib/dots_indicator.py +93 -0
- backtrader/indicators/contrib/ef_distance_indicator.py +82 -0
- backtrader/indicators/contrib/ema_rsi_va.py +80 -0
- backtrader/indicators/contrib/envelopes_jp_alonso.py +32 -0
- backtrader/indicators/contrib/f2a_ao_indicator.py +120 -0
- backtrader/indicators/contrib/fatl_filter.py +179 -0
- backtrader/indicators/contrib/fibo_candles_indicator.py +78 -0
- backtrader/indicators/contrib/fine_tuning_ma.py +100 -0
- backtrader/indicators/contrib/fisher_org_v1.py +102 -0
- backtrader/indicators/contrib/fisher_org_v1_sign.py +118 -0
- backtrader/indicators/contrib/force_index_ema.py +96 -0
- backtrader/indicators/contrib/force_index_ema_2.py +27 -0
- backtrader/indicators/contrib/forecast_oscilator.py +145 -0
- backtrader/indicators/contrib/fractal_amambk.py +81 -0
- backtrader/indicators/contrib/frama_series.py +84 -0
- backtrader/indicators/contrib/frasm_av2_indicator.py +104 -0
- backtrader/indicators/contrib/go_indicator.py +93 -0
- backtrader/indicators/contrib/hlr_indicator.py +95 -0
- backtrader/indicators/contrib/hma.py +50 -0
- backtrader/indicators/contrib/i4_drfv2.py +34 -0
- backtrader/indicators/contrib/i4_drfv3.py +38 -0
- backtrader/indicators/contrib/i_anch_mom_indicator.py +72 -0
- backtrader/indicators/contrib/i_de_marker_sign_indicator.py +64 -0
- backtrader/indicators/contrib/i_gap_indicator.py +45 -0
- backtrader/indicators/contrib/i_stoch_komposter_indicator.py +77 -0
- backtrader/indicators/contrib/i_trend_indicator.py +125 -0
- backtrader/indicators/contrib/iamma_indicator.py +39 -0
- backtrader/indicators/contrib/indexed_moving_average.py +33 -0
- backtrader/indicators/contrib/instantaneous_trend_filter_indicator.py +51 -0
- backtrader/indicators/contrib/inverse_reaction_indicator.py +41 -0
- backtrader/indicators/contrib/irsi_sign_indicator.py +95 -0
- backtrader/indicators/contrib/iwpr_sign_indicator.py +59 -0
- backtrader/indicators/contrib/j_brain_trend1_sig_indicator.py +233 -0
- backtrader/indicators/contrib/j_tpo_proxy.py +32 -0
- backtrader/indicators/contrib/jma_slope_indicator.py +73 -0
- backtrader/indicators/contrib/kalman_filter_indicator.py +119 -0
- backtrader/indicators/contrib/kalman_filter_line.py +127 -0
- backtrader/indicators/contrib/kama_indicator.py +150 -0
- backtrader/indicators/contrib/karacatica_indicator.py +99 -0
- backtrader/indicators/contrib/kdj_indicator.py +59 -0
- backtrader/indicators/contrib/kwan_ccc_indicator.py +195 -0
- backtrader/indicators/contrib/kwan_nrp_indicator.py +113 -0
- backtrader/indicators/contrib/kwan_rdp_indicator.py +192 -0
- backtrader/indicators/contrib/laguerre_adx_indicator.py +85 -0
- backtrader/indicators/contrib/laguerre_filter_indicator.py +66 -0
- backtrader/indicators/contrib/laguerre_plus_di_proxy.py +57 -0
- backtrader/indicators/contrib/laguerre_roc_indicator.py +81 -0
- backtrader/indicators/contrib/le_man_signal_indicator.py +63 -0
- backtrader/indicators/contrib/linear_reg_slope_v2_indicator.py +136 -0
- backtrader/indicators/contrib/loco_indicator.py +88 -0
- backtrader/indicators/contrib/lrma_indicator.py +185 -0
- backtrader/indicators/contrib/lsma_angle_indicator.py +106 -0
- backtrader/indicators/contrib/ma_rounding_channel_indicator.py +149 -0
- backtrader/indicators/contrib/macd2_indicator.py +61 -0
- backtrader/indicators/contrib/macd_candle_indicator.py +80 -0
- backtrader/indicators/contrib/malr_indicator.py +77 -0
- backtrader/indicators/contrib/momentum_candle_sign_indicator.py +51 -0
- backtrader/indicators/contrib/moving_average_fn_indicator.py +139 -0
- backtrader/indicators/contrib/mt5_stochastic_close_close.py +57 -0
- backtrader/indicators/contrib/muv_nor_diff_cloud_indicator.py +107 -0
- backtrader/indicators/contrib/non_lag_dot_indicator.py +124 -0
- backtrader/indicators/contrib/nrtr_extr_indicator.py +95 -0
- backtrader/indicators/contrib/nrtr_indicator.py +95 -0
- backtrader/indicators/contrib/p_channel_system.py +40 -0
- backtrader/indicators/contrib/percent_envelope.py +37 -0
- backtrader/indicators/contrib/percentage_crossover_channel.py +47 -0
- backtrader/indicators/contrib/pivot_zig_zag_proxy.py +47 -0
- backtrader/indicators/contrib/price_channel_stop_indicator.py +104 -0
- backtrader/indicators/contrib/price_extreme_channel.py +35 -0
- backtrader/indicators/contrib/qqe_cloud_indicator.py +129 -0
- backtrader/indicators/contrib/ravi_indicator.py +40 -0
- backtrader/indicators/contrib/raw_close_close_stochastic.py +74 -0
- backtrader/indicators/contrib/rd_trend_trigger_indicator.py +51 -0
- backtrader/indicators/contrib/renko_level.py +85 -0
- backtrader/indicators/contrib/renko_line_break.py +91 -0
- backtrader/indicators/contrib/rftl_indicator.py +41 -0
- backtrader/indicators/contrib/rkd_indicator.py +53 -0
- backtrader/indicators/contrib/roc2_vg_indicator.py +68 -0
- backtrader/indicators/contrib/rsi_histogram_indicator.py +43 -0
- backtrader/indicators/contrib/rsi_slowdown.py +57 -0
- backtrader/indicators/contrib/rsioma_v2.py +41 -0
- backtrader/indicators/contrib/rvi_histogram_indicator.py +107 -0
- backtrader/indicators/contrib/safe_adx.py +89 -0
- backtrader/indicators/contrib/shared_strategy_indicators.py +1651 -0
- backtrader/indicators/contrib/sidus_indicator.py +105 -0
- backtrader/indicators/contrib/silver_trend_indicator.py +79 -0
- backtrader/indicators/contrib/sliding_range_color.py +56 -0
- backtrader/indicators/contrib/slow_stoch.py +42 -0
- backtrader/indicators/contrib/smoothed_adx_indicator.py +86 -0
- backtrader/indicators/contrib/smoothed_rsi.py +31 -0
- backtrader/indicators/contrib/spearman_rank_correlation_histogram.py +60 -0
- backtrader/indicators/contrib/stalin_indicator.py +152 -0
- backtrader/indicators/contrib/starter_laguerre_filter.py +62 -0
- backtrader/indicators/contrib/step_manrtr_indicator.py +137 -0
- backtrader/indicators/contrib/stochastic_histogram_indicator.py +143 -0
- backtrader/indicators/contrib/t3_alarm_indicator.py +125 -0
- backtrader/indicators/contrib/t3_average.py +76 -0
- backtrader/indicators/contrib/t3_indicator.py +40 -0
- backtrader/indicators/contrib/the20s_v020_signal.py +93 -0
- backtrader/indicators/contrib/three_candles_indicator.py +70 -0
- backtrader/indicators/contrib/three_line_break_indicator.py +64 -0
- backtrader/indicators/contrib/time_line.py +57 -0
- backtrader/indicators/contrib/trading_channel_index_proxy.py +48 -0
- backtrader/indicators/contrib/trend_arrows_indicator.py +109 -0
- backtrader/indicators/contrib/trend_continuation_indicator.py +127 -0
- backtrader/indicators/contrib/trend_intensity_index_proxy.py +51 -0
- backtrader/indicators/contrib/trend_manager_indicator.py +39 -0
- backtrader/indicators/contrib/tri_x_candle_indicator.py +51 -0
- backtrader/indicators/contrib/trigger_line.py +66 -0
- backtrader/indicators/contrib/triple_ema_rate.py +34 -0
- backtrader/indicators/contrib/trvi_indicator.py +194 -0
- backtrader/indicators/contrib/two_pb_ideal_xosma_indicator.py +127 -0
- backtrader/indicators/contrib/ultra_absolutely_no_lag_lwma_color.py +92 -0
- backtrader/indicators/contrib/ultra_wpr_indicator.py +173 -0
- backtrader/indicators/contrib/up_down_candle_strength.py +68 -0
- backtrader/indicators/contrib/vinin_i_trend_indicator.py +139 -0
- backtrader/indicators/contrib/volume_weighted_ma_indicator.py +78 -0
- backtrader/indicators/contrib/volume_weighted_ma_st_dev_indicator.py +111 -0
- backtrader/indicators/contrib/vwap_close_indicator.py +65 -0
- backtrader/indicators/contrib/vwma_candle.py +57 -0
- backtrader/indicators/contrib/vwma_digit_system.py +70 -0
- backtrader/indicators/contrib/wami.py +43 -0
- backtrader/indicators/contrib/wprsi_signal_indicator.py +105 -0
- backtrader/indicators/contrib/x_de_marker_histogram_vol_direct_indicator.py +145 -0
- backtrader/indicators/contrib/x_fisher_indicator.py +64 -0
- backtrader/indicators/contrib/xcci_histogram_vol_direct_indicator.py +56 -0
- backtrader/indicators/contrib/xcci_histogram_vol_indicator.py +85 -0
- backtrader/indicators/contrib/xma_ichimoku.py +163 -0
- backtrader/indicators/contrib/xma_ishimoku_channel_indicator.py +65 -0
- backtrader/indicators/contrib/xma_ishimoku_line.py +68 -0
- backtrader/indicators/contrib/xma_range_bands_indicator.py +107 -0
- backtrader/indicators/contrib/xmacd_indicator.py +70 -0
- backtrader/indicators/contrib/xrsi_de_marker_histogram.py +67 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_direct_indicator.py +52 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_indicator.py +81 -0
- backtrader/indicators/contrib/xrvi_indicator.py +130 -0
- backtrader/indicators/contrib/zero_lag_macd.py +36 -0
- backtrader/indicators/contrib/zig_zag_recent_pivot_signal.py +90 -0
- backtrader/indicators/contrib/zpf_indicator.py +115 -0
- backtrader/indicators/crossover.py +337 -0
- backtrader/indicators/dema.py +175 -0
- backtrader/indicators/demarker.py +270 -0
- backtrader/indicators/deviation.py +284 -0
- backtrader/indicators/directionalmove.py +1071 -0
- backtrader/indicators/dma.py +112 -0
- backtrader/indicators/dpo.py +96 -0
- backtrader/indicators/dv2.py +56 -0
- backtrader/indicators/ema.py +145 -0
- backtrader/indicators/envelope.py +475 -0
- backtrader/indicators/hadelta.py +198 -0
- backtrader/indicators/heikinashi.py +153 -0
- backtrader/indicators/hma.py +153 -0
- backtrader/indicators/hurst.py +151 -0
- backtrader/indicators/ichimoku.py +267 -0
- backtrader/indicators/kama.py +181 -0
- backtrader/indicators/kst.py +159 -0
- backtrader/indicators/lrsi.py +125 -0
- backtrader/indicators/mabase.py +147 -0
- backtrader/indicators/macd.py +322 -0
- backtrader/indicators/momentum.py +267 -0
- backtrader/indicators/moneyflow.py +237 -0
- backtrader/indicators/mt5atr.py +124 -0
- backtrader/indicators/myind.py +179 -0
- backtrader/indicators/obv.py +94 -0
- backtrader/indicators/ols.py +265 -0
- backtrader/indicators/oscillator.py +161 -0
- backtrader/indicators/percentchange.py +83 -0
- backtrader/indicators/percentrank.py +46 -0
- backtrader/indicators/pivotpoint.py +469 -0
- backtrader/indicators/prettygoodoscillator.py +113 -0
- backtrader/indicators/priceops_ext.py +123 -0
- backtrader/indicators/priceoscillator.py +262 -0
- backtrader/indicators/psar.py +212 -0
- backtrader/indicators/rmi.py +69 -0
- backtrader/indicators/rsi.py +440 -0
- backtrader/indicators/sma.py +141 -0
- backtrader/indicators/smma.py +116 -0
- backtrader/indicators/spread.py +54 -0
- backtrader/indicators/stochastic.py +263 -0
- backtrader/indicators/supertrend.py +436 -0
- backtrader/indicators/trend_ext.py +105 -0
- backtrader/indicators/trix.py +202 -0
- backtrader/indicators/tsi.py +155 -0
- backtrader/indicators/ultimateoscillator.py +158 -0
- backtrader/indicators/vortex.py +62 -0
- backtrader/indicators/williams.py +194 -0
- backtrader/indicators/wma.py +103 -0
- backtrader/indicators/zlema.py +135 -0
- backtrader/indicators/zlind.py +104 -0
- backtrader/linebuffer.py +3155 -0
- backtrader/lineiterator.py +2911 -0
- backtrader/lineroot.py +1106 -0
- backtrader/lineseries.py +2559 -0
- backtrader/live_trading/__init__.py +31 -0
- backtrader/live_trading/interface.py +404 -0
- backtrader/mathsupport.py +94 -0
- backtrader/metabase.py +1804 -0
- backtrader/mixins/__init__.py +21 -0
- backtrader/mixins/singleton.py +118 -0
- backtrader/observer.py +106 -0
- backtrader/observers/__init__.py +45 -0
- backtrader/observers/benchmark.py +126 -0
- backtrader/observers/broker.py +184 -0
- backtrader/observers/buysell.py +144 -0
- backtrader/observers/drawdown.py +161 -0
- backtrader/observers/logreturns.py +113 -0
- backtrader/observers/timereturn.py +86 -0
- backtrader/observers/trade_logger.py +2972 -0
- backtrader/observers/tradelogger.py +6 -0
- backtrader/observers/trades.py +258 -0
- backtrader/order.py +1114 -0
- backtrader/parameters.py +2345 -0
- backtrader/plot/__init__.py +54 -0
- backtrader/plot/finance.py +1022 -0
- backtrader/plot/formatters.py +200 -0
- backtrader/plot/locator.py +353 -0
- backtrader/plot/multicursor.py +495 -0
- backtrader/plot/plot.py +2500 -0
- backtrader/plot/plot_plotly.py +1351 -0
- backtrader/plot/scheme.py +253 -0
- backtrader/plot/utils.py +104 -0
- backtrader/position.py +290 -0
- backtrader/position_modes.py +132 -0
- backtrader/profiles.py +254 -0
- backtrader/reports/__init__.py +39 -0
- backtrader/reports/charts.py +371 -0
- backtrader/reports/performance.py +620 -0
- backtrader/reports/reporter.py +660 -0
- backtrader/resamplerfilter.py +1001 -0
- backtrader/signal.py +118 -0
- backtrader/signals/__init__.py +17 -0
- backtrader/sizer.py +114 -0
- backtrader/sizers/__init__.py +26 -0
- backtrader/sizers/fixedsize.py +161 -0
- backtrader/sizers/percents_sizer.py +119 -0
- backtrader/store.py +221 -0
- backtrader/stores/__init__.py +33 -0
- backtrader/stores/btapistore.py +15506 -0
- backtrader/stores/livestore.py +137 -0
- backtrader/stores/vchartfile.py +96 -0
- backtrader/strategy.py +3655 -0
- backtrader/talib.py +280 -0
- backtrader/test_helpers.py +96 -0
- backtrader/timer.py +358 -0
- backtrader/trade.py +442 -0
- backtrader/tradingcal.py +361 -0
- backtrader/utils/__init__.py +68 -0
- backtrader/utils/autodict.py +251 -0
- backtrader/utils/date.py +71 -0
- backtrader/utils/dateintern.py +509 -0
- backtrader/utils/flushfile.py +94 -0
- backtrader/utils/fractal.py +101 -0
- backtrader/utils/get_metrics.py +101 -0
- backtrader/utils/load_data.py +209 -0
- backtrader/utils/log_message.py +998 -0
- backtrader/utils/ordereddefaultdict.py +75 -0
- backtrader/utils/py3.py +296 -0
- backtrader/version.py +21 -0
- backtrader/writer.py +372 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""Queue-position models for maker order fills in HFT simulation.
|
|
2
|
+
|
|
3
|
+
Defines :class:`NoQueueModel` (and probabilistic variants like
|
|
4
|
+
``ProbQueueModel``) that estimate how much volume sits ahead of a resting limit
|
|
5
|
+
order and how it gets consumed by trades/depth updates, driving realistic maker
|
|
6
|
+
fill timing in the tick matching engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NoQueueModel:
|
|
11
|
+
"""No-op queue model: resting orders fill instantly on a matching trade."""
|
|
12
|
+
|
|
13
|
+
def estimate_queue_position(self, order, ob_snapshot):
|
|
14
|
+
"""Return a fixed zero queue-ahead for the resting order."""
|
|
15
|
+
_ = (order, ob_snapshot)
|
|
16
|
+
return 0.0
|
|
17
|
+
|
|
18
|
+
def on_new_order(self, order, ob_snapshot):
|
|
19
|
+
"""Initialize the order's queue state to a no-queue configuration."""
|
|
20
|
+
order._queue_ahead = self.estimate_queue_position(order, ob_snapshot)
|
|
21
|
+
order._queue_initial_ahead = float(getattr(order, "_queue_ahead", 0.0))
|
|
22
|
+
order._queue_trade_qty = 0.0
|
|
23
|
+
order._queue_fillable = 0.0
|
|
24
|
+
|
|
25
|
+
def update_on_trade(self, order, trade_event):
|
|
26
|
+
"""Mark the order fully fillable up to the available trade volume."""
|
|
27
|
+
remaining = getattr(getattr(order, "executed", None), "remsize", None)
|
|
28
|
+
if remaining is None:
|
|
29
|
+
remaining = getattr(order, "size", 0.0)
|
|
30
|
+
if remaining is None:
|
|
31
|
+
remaining = 0.0
|
|
32
|
+
trade_volume = abs(getattr(trade_event, "volume", 0.0))
|
|
33
|
+
fillable = min(abs(float(remaining)), trade_volume)
|
|
34
|
+
order._queue_fillable = fillable
|
|
35
|
+
return fillable
|
|
36
|
+
|
|
37
|
+
def update_on_depth(self, order, prev_qty, new_qty):
|
|
38
|
+
"""Clamp the queue-ahead to the latest depth at the order's price."""
|
|
39
|
+
_ = prev_qty
|
|
40
|
+
order._queue_ahead = min(
|
|
41
|
+
max(0.0, float(getattr(order, "_queue_ahead", 0.0))), float(new_qty)
|
|
42
|
+
)
|
|
43
|
+
order._queue_trade_qty = 0.0
|
|
44
|
+
|
|
45
|
+
def is_filled(self, order):
|
|
46
|
+
"""Return True when the no-queue model has any fillable volume."""
|
|
47
|
+
return float(getattr(order, "_queue_fillable", 0.0)) > 0.0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ProbQueueModel:
|
|
51
|
+
"""Probabilistic queue-position model for maker order fills.
|
|
52
|
+
|
|
53
|
+
Estimates the volume that sits ahead of a resting limit order based on the
|
|
54
|
+
displayed size at the order's price, then probabilistically consumes that
|
|
55
|
+
volume as trades and depth updates arrive. The ``power`` argument
|
|
56
|
+
parameterizes the front-vs-back-of-queue probability ratio (a value of 2
|
|
57
|
+
approximates the classical Cont/Stoikov-style weighting), and ``lot_size``
|
|
58
|
+
sets the discrete fill granularity.
|
|
59
|
+
|
|
60
|
+
Attributes:
|
|
61
|
+
power (float): Exponent used in the front/back probability ratio. A
|
|
62
|
+
higher value biases fills toward the back of the queue, making
|
|
63
|
+
position-dependent fill probability more pronounced.
|
|
64
|
+
lot_size (float): Default lot size used when the order does not expose
|
|
65
|
+
its own ``_queue_lot_size`` attribute, controlling the granularity
|
|
66
|
+
of partial fills.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, power: float = 2.0, lot_size: float = 1.0):
|
|
70
|
+
"""Initialize the probabilistic queue model.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
power: Exponent applied to the front/back-of-queue volumes when
|
|
74
|
+
computing the probability that an incoming aggressor
|
|
75
|
+
consumes a unit behind the resting order. Must be non-negative.
|
|
76
|
+
lot_size: Fallback lot size used by :meth:`is_filled` to round
|
|
77
|
+
fills to a discrete quantity. Must be strictly positive.
|
|
78
|
+
"""
|
|
79
|
+
self.power = float(power)
|
|
80
|
+
self.lot_size = float(lot_size)
|
|
81
|
+
|
|
82
|
+
def estimate_queue_position(self, order, ob_snapshot):
|
|
83
|
+
"""Estimate the volume sitting ahead of ``order`` in its price level.
|
|
84
|
+
|
|
85
|
+
Walks the appropriate side of the order book (``bids`` for buys,
|
|
86
|
+
``asks`` for sells) and returns the displayed quantity at the order's
|
|
87
|
+
price level. If the order has no price or the price is not present in
|
|
88
|
+
the snapshot, returns ``0.0``.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
order: The resting order being modeled. Must expose ``price`` and
|
|
92
|
+
an ``isbuy()`` method that returns ``True`` for buy orders.
|
|
93
|
+
ob_snapshot: Order book snapshot providing ``bids`` and ``asks``
|
|
94
|
+
as iterables of ``(price, quantity)`` tuples sorted with the
|
|
95
|
+
best price first.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
float: Quantity (in base asset units) ahead of the order at its
|
|
99
|
+
price level, or ``0.0`` when no price match is found.
|
|
100
|
+
"""
|
|
101
|
+
price = getattr(order, "price", None)
|
|
102
|
+
if price is None:
|
|
103
|
+
return 0.0
|
|
104
|
+
levels = ob_snapshot.bids if order.isbuy() else ob_snapshot.asks
|
|
105
|
+
for level_price, level_qty in levels:
|
|
106
|
+
if level_price == price:
|
|
107
|
+
return float(level_qty)
|
|
108
|
+
return 0.0
|
|
109
|
+
|
|
110
|
+
def on_new_order(self, order, ob_snapshot):
|
|
111
|
+
"""Initialize the queue-tracking state on a freshly placed order.
|
|
112
|
+
|
|
113
|
+
Records the initial queue-ahead (from
|
|
114
|
+
:meth:`estimate_queue_position`), captures it as the baseline
|
|
115
|
+
``_queue_initial_ahead`` for later comparison, and resets the
|
|
116
|
+
running trade-volume accumulator.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
order: The newly accepted resting order that will participate in
|
|
120
|
+
queue dynamics.
|
|
121
|
+
ob_snapshot: Order book snapshot taken at the moment the order
|
|
122
|
+
was accepted by the matching engine.
|
|
123
|
+
"""
|
|
124
|
+
order._queue_ahead = self.estimate_queue_position(order, ob_snapshot)
|
|
125
|
+
order._queue_initial_ahead = float(getattr(order, "_queue_ahead", 0.0))
|
|
126
|
+
order._queue_trade_qty = 0.0
|
|
127
|
+
|
|
128
|
+
def _probability(self, front: float, back: float) -> float:
|
|
129
|
+
"""Compute the probability that a consumed unit is behind this order.
|
|
130
|
+
|
|
131
|
+
Uses the front/back ratio raised to ``self.power`` so that a small
|
|
132
|
+
``back`` (i.e. the order sits near the back of the queue) yields a
|
|
133
|
+
low probability and a small ``front`` yields a high probability.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
front: Quantity sitting ahead of this order at its price level.
|
|
137
|
+
back: Quantity sitting behind this order at its price level.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
float: Probability in ``[0.0, 1.0]`` that the next consumed unit
|
|
141
|
+
passes behind the resting order. Returns ``1.0`` if both
|
|
142
|
+
quantities are zero.
|
|
143
|
+
"""
|
|
144
|
+
front = max(0.0, float(front))
|
|
145
|
+
back = max(0.0, float(back))
|
|
146
|
+
denominator = back**self.power + front**self.power
|
|
147
|
+
if denominator <= 0.0:
|
|
148
|
+
return 1.0
|
|
149
|
+
return back**self.power / denominator
|
|
150
|
+
|
|
151
|
+
def update_on_trade(self, order, trade_event):
|
|
152
|
+
"""Consume a trade event and update the order's queue-ahead.
|
|
153
|
+
|
|
154
|
+
Subtracts the absolute trade volume from the queue-ahead and
|
|
155
|
+
accumulates it into ``_queue_trade_qty`` so the subsequent depth
|
|
156
|
+
update can reconcile the displayed quantity against the volume
|
|
157
|
+
that was already attributed to trades.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
order: The resting order being tracked. The method mutates
|
|
161
|
+
``_queue_ahead``, ``_queue_trade_qty`` and ``_queue_fillable``
|
|
162
|
+
on the order in place.
|
|
163
|
+
trade_event: The trade event to consume. Must expose a
|
|
164
|
+
``volume`` attribute (absolute trade size).
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
float: The fillable volume computed via :meth:`is_filled` after
|
|
168
|
+
the trade has been applied (``0.0`` when nothing filled).
|
|
169
|
+
"""
|
|
170
|
+
queue_ahead = float(getattr(order, "_queue_ahead", 0.0))
|
|
171
|
+
trade_qty = abs(float(getattr(trade_event, "volume", 0.0)))
|
|
172
|
+
if trade_qty <= 0.0:
|
|
173
|
+
order._queue_fillable = 0.0
|
|
174
|
+
return 0.0
|
|
175
|
+
queue_ahead -= trade_qty
|
|
176
|
+
order._queue_ahead = queue_ahead
|
|
177
|
+
order._queue_trade_qty = float(getattr(order, "_queue_trade_qty", 0.0)) + trade_qty
|
|
178
|
+
fillable = self.is_filled(order)
|
|
179
|
+
order._queue_fillable = fillable
|
|
180
|
+
return fillable
|
|
181
|
+
|
|
182
|
+
def update_on_depth(self, order, prev_qty, new_qty):
|
|
183
|
+
"""Reconcile the order's queue-ahead against an updated depth value.
|
|
184
|
+
|
|
185
|
+
The order book manager reports the new total size at the order's
|
|
186
|
+
price level. The model first removes the volume already attributed
|
|
187
|
+
to trades (kept in ``_queue_trade_qty``) and then estimates the new
|
|
188
|
+
queue-ahead as a probabilistic blend of the previous front/back
|
|
189
|
+
split.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
order: The resting order being tracked. The method mutates
|
|
193
|
+
``_queue_ahead`` and ``_queue_trade_qty`` in place.
|
|
194
|
+
prev_qty: Displayed quantity at the order's price level before
|
|
195
|
+
the depth update.
|
|
196
|
+
new_qty: Displayed quantity at the order's price level after
|
|
197
|
+
the depth update.
|
|
198
|
+
"""
|
|
199
|
+
change = float(prev_qty) - float(new_qty)
|
|
200
|
+
queue_ahead = float(getattr(order, "_queue_ahead", 0.0))
|
|
201
|
+
trade_qty = float(getattr(order, "_queue_trade_qty", 0.0))
|
|
202
|
+
change -= trade_qty
|
|
203
|
+
order._queue_trade_qty = 0.0
|
|
204
|
+
if change < 0.0:
|
|
205
|
+
order._queue_ahead = min(queue_ahead, float(new_qty))
|
|
206
|
+
return
|
|
207
|
+
front = queue_ahead
|
|
208
|
+
back = float(prev_qty) - front
|
|
209
|
+
probability = self._probability(front, back)
|
|
210
|
+
estimate = front - (1.0 - probability) * change + min(back - probability * change, 0.0)
|
|
211
|
+
order._queue_ahead = min(estimate, float(new_qty))
|
|
212
|
+
|
|
213
|
+
def is_filled(self, order):
|
|
214
|
+
"""Compute the lot-rounded fillable volume for the order.
|
|
215
|
+
|
|
216
|
+
When the queue-ahead has gone non-positive, the order has been
|
|
217
|
+
fully consumed and the method returns the number of whole lots that
|
|
218
|
+
would have filled, rescaled to absolute volume. Otherwise returns
|
|
219
|
+
``0.0``. The order's ``_queue_ahead`` is reset to zero when a
|
|
220
|
+
positive fill is produced.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
order: The resting order being tracked. The method mutates
|
|
224
|
+
``_queue_ahead`` when a positive fill is detected.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
float: Fillable volume rounded to whole lots (or ``0.0`` if the
|
|
228
|
+
order has not been fully consumed).
|
|
229
|
+
"""
|
|
230
|
+
queue_ahead = float(getattr(order, "_queue_ahead", 0.0))
|
|
231
|
+
lot_size = abs(float(getattr(order, "_queue_lot_size", self.lot_size)))
|
|
232
|
+
if lot_size <= 0.0:
|
|
233
|
+
lot_size = 1.0
|
|
234
|
+
exec_lots = int(round((-queue_ahead) / lot_size))
|
|
235
|
+
if exec_lots > 0:
|
|
236
|
+
order._queue_ahead = 0.0
|
|
237
|
+
return exec_lots * lot_size
|
|
238
|
+
return 0.0
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Event recorder for HFT simulation diagnostics.
|
|
2
|
+
|
|
3
|
+
Defines :class:`Recorder`, a small bounded-history collector of timestamped
|
|
4
|
+
per-symbol events used to capture and replay the matching engine's activity.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Recorder:
|
|
9
|
+
"""Bounded-history collector of timestamped per-symbol events.
|
|
10
|
+
|
|
11
|
+
The recorder is used by the HFT simulation stack to capture activity
|
|
12
|
+
produced by the matching engine (orders, trades, cancels, etc.) so that
|
|
13
|
+
it can be inspected or replayed later. Events are stored as plain
|
|
14
|
+
dictionaries and trimmed to a configurable maximum length to keep memory
|
|
15
|
+
usage predictable during long runs.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
_maxlen: Optional maximum number of events to retain. ``None`` means
|
|
19
|
+
unbounded (events accumulate for the lifetime of the recorder).
|
|
20
|
+
_events: Internal list of recorded event dictionaries, in insertion
|
|
21
|
+
order. Each entry has the shape
|
|
22
|
+
``{"timestamp": ..., "symbol": ..., "payload": {...}}``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, maxlen=None):
|
|
26
|
+
"""Initialize the recorder with an optional retention cap.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
maxlen: Maximum number of events to keep in memory. When the
|
|
30
|
+
cap is exceeded, the oldest events are dropped. ``None``
|
|
31
|
+
disables trimming and lets events accumulate indefinitely.
|
|
32
|
+
"""
|
|
33
|
+
self._maxlen = maxlen
|
|
34
|
+
self._events = []
|
|
35
|
+
|
|
36
|
+
def record(self, timestamp, symbol, payload):
|
|
37
|
+
"""Append a new event to the recorder.
|
|
38
|
+
|
|
39
|
+
The ``payload`` mapping is shallow-copied to insulate the recorder
|
|
40
|
+
from later mutations made by the caller. When ``_maxlen`` is set and
|
|
41
|
+
the new length would exceed it, the oldest entries are trimmed so
|
|
42
|
+
that the internal list never grows past the cap.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
timestamp: Event timestamp. Any value that the caller considers
|
|
46
|
+
a valid time identifier (typically a ``float`` epoch second,
|
|
47
|
+
but the recorder does not enforce a type).
|
|
48
|
+
symbol: Trading symbol (e.g. ``"BTCUSDT"``) associated with the
|
|
49
|
+
event. Used purely for indexing/inspection downstream.
|
|
50
|
+
payload: Mapping describing the event body. The mapping is
|
|
51
|
+
shallow-copied before being stored so that subsequent
|
|
52
|
+
modifications to the caller's object do not affect the
|
|
53
|
+
recorded history.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
dict: The recorded event dictionary as it was inserted (with
|
|
57
|
+
``timestamp``, ``symbol`` and the copied ``payload``).
|
|
58
|
+
"""
|
|
59
|
+
item = {
|
|
60
|
+
"timestamp": timestamp,
|
|
61
|
+
"symbol": symbol,
|
|
62
|
+
"payload": dict(payload),
|
|
63
|
+
}
|
|
64
|
+
self._events.append(item)
|
|
65
|
+
if self._maxlen is not None and len(self._events) > self._maxlen:
|
|
66
|
+
self._events = self._events[-self._maxlen :]
|
|
67
|
+
return item
|
|
68
|
+
|
|
69
|
+
def snapshot(self):
|
|
70
|
+
"""Return a shallow copy of the recorded events.
|
|
71
|
+
|
|
72
|
+
The returned list is a fresh list, but the event dictionaries inside
|
|
73
|
+
it are the same objects stored in the recorder. Callers that need to
|
|
74
|
+
mutate individual events should copy them explicitly.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
list[dict]: Recorded events in insertion order (oldest first).
|
|
78
|
+
"""
|
|
79
|
+
return list(self._events)
|
|
80
|
+
|
|
81
|
+
def clear(self):
|
|
82
|
+
"""Drop every recorded event from the recorder.
|
|
83
|
+
|
|
84
|
+
After this call :meth:`snapshot` returns an empty list and the
|
|
85
|
+
recorder behaves as if it had just been constructed. The configured
|
|
86
|
+
``_maxlen`` is preserved.
|
|
87
|
+
"""
|
|
88
|
+
self._events = []
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Per-symbol trading state tracking for HFT simulation.
|
|
2
|
+
|
|
3
|
+
Defines :class:`StateTracker`, which accumulates per-symbol statistics (fees,
|
|
4
|
+
trade count, traded volume/value) updated on each fill, used for reporting and
|
|
5
|
+
fee accounting in the tick broker.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class StateTracker:
|
|
10
|
+
"""Per-symbol trading-state accumulator for the HFT tick broker.
|
|
11
|
+
|
|
12
|
+
Maintains, for every symbol seen in a fill, a running count of
|
|
13
|
+
trades, traded volume and traded notional value, and the
|
|
14
|
+
cumulative fees paid. Snapshots are produced for either a single
|
|
15
|
+
symbol or every known symbol and are intended for reporting and
|
|
16
|
+
fee accounting.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
"""Initialize the empty per-symbol state dict."""
|
|
21
|
+
self._states = {}
|
|
22
|
+
|
|
23
|
+
def reset(self):
|
|
24
|
+
"""Clear all per-symbol state. Useful between backtest runs."""
|
|
25
|
+
self._states = {}
|
|
26
|
+
|
|
27
|
+
def get_state(self, symbol):
|
|
28
|
+
"""Return (and lazily create) the state dict for ``symbol``.
|
|
29
|
+
|
|
30
|
+
The state dict holds four counters: ``fee`` (cumulative
|
|
31
|
+
commission), ``num_trades`` (number of fills), ``trading_volume``
|
|
32
|
+
(absolute shares/contracts traded) and ``trading_value``
|
|
33
|
+
(absolute notional traded, ``volume * price``).
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
symbol: Symbol whose state to fetch or create.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
dict: The mutable per-symbol state dict.
|
|
40
|
+
"""
|
|
41
|
+
if symbol not in self._states:
|
|
42
|
+
self._states[symbol] = {
|
|
43
|
+
"fee": 0.0,
|
|
44
|
+
"num_trades": 0,
|
|
45
|
+
"trading_volume": 0.0,
|
|
46
|
+
"trading_value": 0.0,
|
|
47
|
+
}
|
|
48
|
+
return self._states[symbol]
|
|
49
|
+
|
|
50
|
+
def on_fill(self, symbol, price, size, commission, role=None):
|
|
51
|
+
"""Record a fill and return the updated per-symbol state.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
symbol: Symbol the fill belongs to.
|
|
55
|
+
price: Fill price (per unit). Used to update
|
|
56
|
+
``trading_value``.
|
|
57
|
+
size: Signed fill size. Only its absolute value is added
|
|
58
|
+
to ``trading_volume``.
|
|
59
|
+
commission: Commission charged for the fill, added to
|
|
60
|
+
``fee``.
|
|
61
|
+
role: Optional :class:`backtrader.brokers.hft.exchange.FillRole`
|
|
62
|
+
tag. The tracker ignores it; it is accepted so the
|
|
63
|
+
call site can pass the role verbatim.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
dict: The updated per-symbol state dict.
|
|
67
|
+
"""
|
|
68
|
+
_ = role
|
|
69
|
+
state = self.get_state(symbol)
|
|
70
|
+
state["num_trades"] += 1
|
|
71
|
+
state["trading_volume"] += abs(size)
|
|
72
|
+
state["trading_value"] += abs(size) * price
|
|
73
|
+
state["fee"] += commission
|
|
74
|
+
return state
|
|
75
|
+
|
|
76
|
+
def snapshot(self, symbol, position, balance, mid_price=None):
|
|
77
|
+
"""Build a per-symbol snapshot dict combining state and P&L.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
symbol: Symbol to snapshot.
|
|
81
|
+
position: Current net position (signed shares/contracts).
|
|
82
|
+
balance: Cash balance attributable to ``symbol`` (or
|
|
83
|
+
the full account, depending on accounting).
|
|
84
|
+
mid_price: Optional mid price used to mark the position
|
|
85
|
+
to market when computing ``equity``. When ``None``,
|
|
86
|
+
``equity`` equals ``balance``.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
dict: ``{"position", "balance", "fee", "num_trades",
|
|
90
|
+
"trading_volume", "trading_value", "equity"}``.
|
|
91
|
+
"""
|
|
92
|
+
state = self.get_state(symbol)
|
|
93
|
+
equity = balance
|
|
94
|
+
if mid_price is not None:
|
|
95
|
+
equity += position * mid_price
|
|
96
|
+
return {
|
|
97
|
+
"position": position,
|
|
98
|
+
"balance": balance,
|
|
99
|
+
"fee": state["fee"],
|
|
100
|
+
"num_trades": state["num_trades"],
|
|
101
|
+
"trading_volume": state["trading_volume"],
|
|
102
|
+
"trading_value": state["trading_value"],
|
|
103
|
+
"equity": equity,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
def snapshot_all(self, positions, balance_by_symbol=None, mid_prices=None):
|
|
107
|
+
"""Build per-symbol snapshots for every known symbol.
|
|
108
|
+
|
|
109
|
+
The symbol set is the union of the keys already in the
|
|
110
|
+
tracker and the keys in the ``positions`` mapping, so symbols
|
|
111
|
+
that have only ever carried a position (but no fills) are
|
|
112
|
+
still included. Missing positions/balances default to
|
|
113
|
+
``0.0``; missing mid prices leave ``equity`` equal to the
|
|
114
|
+
balance.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
positions: Mapping of symbol -> signed position.
|
|
118
|
+
balance_by_symbol: Optional mapping of symbol -> cash
|
|
119
|
+
balance. ``None`` or missing keys default to ``0.0``.
|
|
120
|
+
mid_prices: Optional mapping of symbol -> mid price for
|
|
121
|
+
mark-to-market. ``None`` or missing keys leave
|
|
122
|
+
``equity`` equal to the balance.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
dict: ``{symbol: snapshot_dict}`` for every known symbol.
|
|
126
|
+
"""
|
|
127
|
+
balance_by_symbol = balance_by_symbol or {}
|
|
128
|
+
mid_prices = mid_prices or {}
|
|
129
|
+
symbols = set(self._states) | set(positions)
|
|
130
|
+
result = {}
|
|
131
|
+
for symbol in symbols:
|
|
132
|
+
result[symbol] = self.snapshot(
|
|
133
|
+
symbol,
|
|
134
|
+
positions.get(symbol, 0.0),
|
|
135
|
+
balance_by_symbol.get(symbol, 0.0),
|
|
136
|
+
mid_prices.get(symbol),
|
|
137
|
+
)
|
|
138
|
+
return result
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Market impact models for order book depth matching.
|
|
2
|
+
|
|
3
|
+
Provides pluggable market impact models used by TickBroker to
|
|
4
|
+
estimate price impact of large orders consuming depth levels.
|
|
5
|
+
|
|
6
|
+
Models:
|
|
7
|
+
- MarketImpactModel: Abstract base class
|
|
8
|
+
- LinearImpactModel: Linear price impact proportional to order size
|
|
9
|
+
- SquareRootImpactModel: Square-root impact model (more realistic)
|
|
10
|
+
|
|
11
|
+
Example::
|
|
12
|
+
|
|
13
|
+
from backtrader.brokers.impact_models import SquareRootImpactModel
|
|
14
|
+
model = SquareRootImpactModel(coefficient=0.1)
|
|
15
|
+
impact = model.calculate_impact(price=50000, size=10.0)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import math
|
|
19
|
+
from abc import ABC, abstractmethod
|
|
20
|
+
|
|
21
|
+
__all__ = ["MarketImpactModel", "LinearImpactModel", "SquareRootImpactModel"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MarketImpactModel(ABC):
|
|
25
|
+
"""Abstract base class for market impact models.
|
|
26
|
+
|
|
27
|
+
Market impact models estimate how a trade of a given size at a given
|
|
28
|
+
price level will move the market price, accounting for liquidity
|
|
29
|
+
consumption effects.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def calculate_impact(self, price, size) -> float:
|
|
34
|
+
"""Calculate the absolute price impact.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
price: Current price level.
|
|
38
|
+
size: Order size being filled.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Absolute price impact (always >= 0).
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class LinearImpactModel(MarketImpactModel):
|
|
46
|
+
"""Linear market impact: impact = coefficient * size * price.
|
|
47
|
+
|
|
48
|
+
Simple model where price impact scales linearly with order size.
|
|
49
|
+
Suitable for small orders relative to market depth.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
coefficient: Impact coefficient (default: 0.001).
|
|
53
|
+
Higher values mean more price impact per unit size.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def __init__(self, coefficient=0.001):
|
|
57
|
+
"""Initialize the linear impact model.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
coefficient: Impact coefficient (default: 0.001).
|
|
61
|
+
Higher values mean more price impact per unit size.
|
|
62
|
+
"""
|
|
63
|
+
self.coefficient = coefficient
|
|
64
|
+
|
|
65
|
+
def calculate_impact(self, price, size) -> float:
|
|
66
|
+
"""Calculate linear price impact.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
coefficient * size * price
|
|
70
|
+
"""
|
|
71
|
+
return self.coefficient * abs(size) * price
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class SquareRootImpactModel(MarketImpactModel):
|
|
75
|
+
"""Square-root market impact: impact = coefficient * sqrt(size) * price.
|
|
76
|
+
|
|
77
|
+
More realistic model based on empirical research showing that price
|
|
78
|
+
impact scales with the square root of order size. Better suited for
|
|
79
|
+
large orders.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
coefficient: Impact coefficient (default: 0.01).
|
|
83
|
+
daily_volume: Average daily volume for normalization (default: 0.0).
|
|
84
|
+
If > 0, size is normalized by daily volume before sqrt.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
def __init__(self, coefficient=0.01, daily_volume=0.0):
|
|
88
|
+
"""Initialize the square-root impact model.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
coefficient: Impact coefficient (default: 0.01).
|
|
92
|
+
daily_volume: Average daily volume for normalization (default: 0.0).
|
|
93
|
+
If > 0, size is normalized by daily volume before sqrt.
|
|
94
|
+
"""
|
|
95
|
+
self.coefficient = coefficient
|
|
96
|
+
self.daily_volume = daily_volume
|
|
97
|
+
|
|
98
|
+
def calculate_impact(self, price, size) -> float:
|
|
99
|
+
"""Calculate square-root price impact.
|
|
100
|
+
|
|
101
|
+
If daily_volume > 0:
|
|
102
|
+
impact = coefficient * sqrt(size / daily_volume) * price
|
|
103
|
+
Else:
|
|
104
|
+
impact = coefficient * sqrt(size) * price
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Absolute price impact.
|
|
108
|
+
"""
|
|
109
|
+
abs_size = abs(size)
|
|
110
|
+
if abs_size <= 0:
|
|
111
|
+
return 0.0
|
|
112
|
+
|
|
113
|
+
if self.daily_volume > 0:
|
|
114
|
+
normalized = abs_size / self.daily_volume
|
|
115
|
+
else:
|
|
116
|
+
normalized = abs_size
|
|
117
|
+
|
|
118
|
+
return self.coefficient * math.sqrt(normalized) * price
|