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
backtrader/__init__.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Backtrader - Python Trading Framework.
|
|
3
|
+
|
|
4
|
+
A feature-rich Python framework for backtesting and trading with support for
|
|
5
|
+
multiple data feeds, brokers, and analysis tools.
|
|
6
|
+
|
|
7
|
+
This module serves as the main entry point for the backtrader package,
|
|
8
|
+
exposing all public APIs through a unified namespace.
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
Basic usage::
|
|
12
|
+
|
|
13
|
+
import backtrader as bt
|
|
14
|
+
|
|
15
|
+
cerebro = bt.Cerebro()
|
|
16
|
+
data = bt.feeds.GenericCSVData(dataname='data.csv')
|
|
17
|
+
cerebro.adddata(data)
|
|
18
|
+
cerebro.addstrategy(MyStrategy)
|
|
19
|
+
results = cerebro.run()
|
|
20
|
+
cerebro.plot()
|
|
21
|
+
|
|
22
|
+
Core Components:
|
|
23
|
+
- **Cerebro**: Main engine that orchestrates backtesting
|
|
24
|
+
- **Strategy**: Base class for trading strategies
|
|
25
|
+
- **Indicator**: Base class for technical indicators
|
|
26
|
+
- **Analyzer**: Base class for performance analyzers
|
|
27
|
+
- **Broker**: Simulated broker for order execution
|
|
28
|
+
- **Feed**: Data feed classes for market data input
|
|
29
|
+
|
|
30
|
+
Subpackages:
|
|
31
|
+
- analyzers: Performance analysis tools (Sharpe, Drawdown, etc.)
|
|
32
|
+
- brokers: Broker implementations (backtesting + unified bt_api_py live broker)
|
|
33
|
+
- feeds: Data feed implementations (CSV, Pandas, Yahoo, bt_api_py live feed)
|
|
34
|
+
- indicators: Technical indicators (SMA, RSI, MACD, etc.)
|
|
35
|
+
- observers: Chart observers for visualization
|
|
36
|
+
- sizers: Position sizing algorithms
|
|
37
|
+
- stores: Data store implementations
|
|
38
|
+
- filters: Data filtering utilities
|
|
39
|
+
|
|
40
|
+
Attributes:
|
|
41
|
+
__version__ (str): Package version string
|
|
42
|
+
__btversion__ (tuple): Package version as tuple
|
|
43
|
+
|
|
44
|
+
See Also:
|
|
45
|
+
- Documentation: https://www.backtrader.com/docu/
|
|
46
|
+
- GitHub: https://github.com/mementum/backtrader
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
import os as _os
|
|
50
|
+
|
|
51
|
+
_LIGHT_IMPORT = _os.environ.get("BACKTRADER_LIGHT_IMPORT", "").strip().lower() in {
|
|
52
|
+
"1",
|
|
53
|
+
"true",
|
|
54
|
+
"yes",
|
|
55
|
+
"on",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if _LIGHT_IMPORT:
|
|
59
|
+
from . import broker as broker
|
|
60
|
+
from . import brokers as brokers
|
|
61
|
+
from . import errors as errors
|
|
62
|
+
from . import feeds as feeds
|
|
63
|
+
from . import indicators as ind
|
|
64
|
+
from . import indicators as indicators
|
|
65
|
+
from . import observers as obs
|
|
66
|
+
from . import observers as observers
|
|
67
|
+
from . import stores as stores
|
|
68
|
+
from .broker import *
|
|
69
|
+
from .cerebro import *
|
|
70
|
+
from .comminfo import *
|
|
71
|
+
from .dataseries import *
|
|
72
|
+
from .errors import *
|
|
73
|
+
from .feed import *
|
|
74
|
+
from .functions import *
|
|
75
|
+
from .indicator import *
|
|
76
|
+
from .linebuffer import *
|
|
77
|
+
from .lineiterator import *
|
|
78
|
+
from .lineseries import *
|
|
79
|
+
from .observer import *
|
|
80
|
+
from .order import *
|
|
81
|
+
from .position import *
|
|
82
|
+
from .signal import *
|
|
83
|
+
from .strategy import *
|
|
84
|
+
from .timer import *
|
|
85
|
+
from .trade import *
|
|
86
|
+
from .utils import date2num, num2date, num2dt, num2time, time2num
|
|
87
|
+
from .utils import configure_logging, get_logger, reset_logging, set_level
|
|
88
|
+
from .version import __btversion__, __version__
|
|
89
|
+
else:
|
|
90
|
+
# Load contributed indicators and studies (lazy import to avoid circular dependency)
|
|
91
|
+
# from .indicators import contrib as _indicators_contrib
|
|
92
|
+
|
|
93
|
+
from . import analyzers as analyzers
|
|
94
|
+
from . import broker as broker
|
|
95
|
+
from . import brokers as brokers
|
|
96
|
+
from . import channels as channels
|
|
97
|
+
from . import commissions as commissions
|
|
98
|
+
from . import commissions as comms
|
|
99
|
+
from . import errors as errors
|
|
100
|
+
from . import feeds as feeds
|
|
101
|
+
from . import filters as filters
|
|
102
|
+
from . import indicators as ind
|
|
103
|
+
from . import indicators as indicators
|
|
104
|
+
from . import observers as obs
|
|
105
|
+
from . import observers as observers
|
|
106
|
+
from . import signals as signals
|
|
107
|
+
from . import sizers as sizers
|
|
108
|
+
from . import stores as stores
|
|
109
|
+
from . import talib as talib
|
|
110
|
+
from . import timer as timer
|
|
111
|
+
from . import utils as utils
|
|
112
|
+
from .analyzer import *
|
|
113
|
+
from .broker import *
|
|
114
|
+
from .cerebro import *
|
|
115
|
+
from .comminfo import *
|
|
116
|
+
from .dataseries import *
|
|
117
|
+
from .errors import *
|
|
118
|
+
from .feed import *
|
|
119
|
+
from .flt import *
|
|
120
|
+
from .functions import *
|
|
121
|
+
from .indicator import *
|
|
122
|
+
from .linebuffer import *
|
|
123
|
+
from .lineiterator import *
|
|
124
|
+
from .lineseries import *
|
|
125
|
+
from .observer import *
|
|
126
|
+
from .order import *
|
|
127
|
+
from .position import *
|
|
128
|
+
from .resamplerfilter import *
|
|
129
|
+
from .signal import *
|
|
130
|
+
from .sizer import *
|
|
131
|
+
from .sizers import SizerFix # old sizer for compatibility
|
|
132
|
+
from .store import Store
|
|
133
|
+
from .strategy import *
|
|
134
|
+
from .timer import *
|
|
135
|
+
from .trade import *
|
|
136
|
+
from .utils import date2num, num2date, num2dt, num2time, time2num
|
|
137
|
+
from .utils import configure_logging, get_logger, reset_logging, set_level
|
|
138
|
+
from .version import __btversion__, __version__
|
|
139
|
+
from .writer import *
|
|
140
|
+
from .profiles import LiveProfile, build_cerebro
|
|
141
|
+
|
|
142
|
+
# Iteration 138: Tick-level backtesting and live trading
|
|
143
|
+
from .events import TickEvent, OrderBookSnapshot, FundingEvent, BarEvent
|
|
144
|
+
from .channel import Event, EventPriority, StreamingEventQueue
|
|
145
|
+
|
|
146
|
+
# import backtrader.studies.contrib
|
|
147
|
+
|
|
148
|
+
# from backtrader import vectors
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
"""Cerebro channel event mode mixin (iteration 28 split).
|
|
2
|
+
|
|
3
|
+
Moved verbatim from ``backtrader/cerebro.py``: channel event dispatch,
|
|
4
|
+
channel strategy wiring and the channel run loop.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
import itertools
|
|
9
|
+
import logging
|
|
10
|
+
from datetime import timezone
|
|
11
|
+
from typing import Dict
|
|
12
|
+
|
|
13
|
+
from .. import errors
|
|
14
|
+
from ..channel import ChannelDataRef
|
|
15
|
+
from ..lineseries import LineSeries
|
|
16
|
+
from ..metabase import OwnerContext
|
|
17
|
+
from ..utils import date2num
|
|
18
|
+
from ..utils.log_message import _is_output_enabled_for, get_logger, throttled_warning
|
|
19
|
+
|
|
20
|
+
UTC = timezone.utc
|
|
21
|
+
|
|
22
|
+
# Keep the historical logger name (D28-04.6): routing/filters must not change.
|
|
23
|
+
logger = get_logger("backtrader.cerebro")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ChannelMixin:
|
|
27
|
+
"""Channel event mode half of Cerebro (see module docstring)."""
|
|
28
|
+
|
|
29
|
+
def dispatch_channel_event(self, event):
|
|
30
|
+
"""Dispatch a channel event to all running strategies.
|
|
31
|
+
|
|
32
|
+
Routes tick, orderbook, funding, and bar events from the channel
|
|
33
|
+
system (StreamingEventQueue / LiveEventQueue) to the appropriate
|
|
34
|
+
``notify_*`` callbacks on each strategy.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
event: Event wrapper with ``.data`` and ``.channel_type`` attrs.
|
|
38
|
+
"""
|
|
39
|
+
data = event.data
|
|
40
|
+
channel_type = event.channel_type
|
|
41
|
+
data_ref = getattr(event, "_source_feed", None)
|
|
42
|
+
if data_ref is not None:
|
|
43
|
+
# Feed events use the actual data object for native broker routing.
|
|
44
|
+
# Channel-only events are matched separately by _run_channel().
|
|
45
|
+
processor = getattr(self._broker, "process_" + channel_type, None)
|
|
46
|
+
if processor is not None and channel_type in {"tick", "orderbook"}:
|
|
47
|
+
processor(data, data=data_ref)
|
|
48
|
+
else:
|
|
49
|
+
data_ref = self._get_channel_data_ref(event)
|
|
50
|
+
|
|
51
|
+
for strat in self.runningstrats:
|
|
52
|
+
strat._event_count += 1
|
|
53
|
+
if data_ref is not None and hasattr(strat, "_register_hft_data"):
|
|
54
|
+
strat._register_hft_data(data_ref)
|
|
55
|
+
|
|
56
|
+
if channel_type == "tick":
|
|
57
|
+
strat._tick_count += 1
|
|
58
|
+
strat._last_tick[getattr(data, "symbol", "")] = data
|
|
59
|
+
strat.notify_tick(data)
|
|
60
|
+
strat._notify_tick_to_observers(data)
|
|
61
|
+
elif channel_type == "orderbook":
|
|
62
|
+
strat._last_ob[getattr(data, "symbol", "")] = data
|
|
63
|
+
strat.notify_orderbook(data)
|
|
64
|
+
elif channel_type == "funding":
|
|
65
|
+
strat._last_funding[getattr(data, "symbol", "")] = data
|
|
66
|
+
strat.notify_funding(data)
|
|
67
|
+
elif channel_type == "bar":
|
|
68
|
+
strat.notify_bar(data)
|
|
69
|
+
strat._notify_bar_to_observers(data)
|
|
70
|
+
|
|
71
|
+
def _get_channel_data_ref(self, event):
|
|
72
|
+
"""Return a stable lightweight data reference for a channel event."""
|
|
73
|
+
event_data = getattr(event, "data", None)
|
|
74
|
+
symbol = getattr(event_data, "symbol", None) or getattr(event, "channel_name", None)
|
|
75
|
+
if symbol is None:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
symbol = str(symbol)
|
|
79
|
+
if not hasattr(self, "_channel_data_refs"):
|
|
80
|
+
# Same shape as Cerebro.__init__'s typed mapping (iteration 28
|
|
81
|
+
# note: minimal annotation so the mixin type-checks standalone).
|
|
82
|
+
self._channel_data_refs: Dict[str, ChannelDataRef] = {}
|
|
83
|
+
|
|
84
|
+
data_ref = self._channel_data_refs.get(symbol)
|
|
85
|
+
if data_ref is None:
|
|
86
|
+
data_ref = ChannelDataRef(
|
|
87
|
+
symbol=symbol, channel_name=getattr(event, "channel_name", None)
|
|
88
|
+
)
|
|
89
|
+
self._channel_data_refs[symbol] = data_ref
|
|
90
|
+
return data_ref
|
|
91
|
+
|
|
92
|
+
def _start_channel_strategy(self, strat):
|
|
93
|
+
"""Start a channel-mode strategy without assuming bar datas exist."""
|
|
94
|
+
if getattr(strat, "datas", None):
|
|
95
|
+
strat._start()
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
for analyzer in itertools.chain(strat.analyzers, strat._slave_analyzers):
|
|
99
|
+
analyzer._start()
|
|
100
|
+
|
|
101
|
+
for observer in strat._get_all_observers():
|
|
102
|
+
observer._start()
|
|
103
|
+
|
|
104
|
+
strat.start()
|
|
105
|
+
|
|
106
|
+
def _advance_channel_strategy_clock(self, strat, event):
|
|
107
|
+
"""Advance no-data channel strategies so observers can run per event."""
|
|
108
|
+
if getattr(strat, "datas", None):
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
strat.forward()
|
|
113
|
+
except Exception:
|
|
114
|
+
throttled_warning(
|
|
115
|
+
logger,
|
|
116
|
+
"channel_strategy_forward",
|
|
117
|
+
"Channel strategy forward() failed",
|
|
118
|
+
exc_info=False,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
timestamp = getattr(event, "timestamp", None)
|
|
122
|
+
if timestamp is None:
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
event_dt = datetime.datetime.fromtimestamp(float(timestamp), UTC)
|
|
127
|
+
event_num = date2num(event_dt)
|
|
128
|
+
strat.lines.datetime[0] = event_num
|
|
129
|
+
strat._last_valid_datetime = event_num
|
|
130
|
+
# `placeholder_data` is an optional strategy-owned mapping. A
|
|
131
|
+
# normal lookup for the standard Strategy path sends its missing
|
|
132
|
+
# case through LineSeries fallback resolution on every event.
|
|
133
|
+
# Bypass only that known fallback; a custom accessor may provide
|
|
134
|
+
# the mapping dynamically and must retain normal getattr() rules.
|
|
135
|
+
strategy_type = type(strat)
|
|
136
|
+
strategy_getattribute = getattr(strategy_type, "__getattribute__", None)
|
|
137
|
+
if (
|
|
138
|
+
strategy_getattribute is object.__getattribute__
|
|
139
|
+
and getattr(strategy_type, "__getattr__", None) is LineSeries.__getattr__
|
|
140
|
+
):
|
|
141
|
+
try:
|
|
142
|
+
placeholder_map = object.__getattribute__(strat, "placeholder_data")
|
|
143
|
+
except AttributeError:
|
|
144
|
+
placeholder_map = None
|
|
145
|
+
else:
|
|
146
|
+
placeholder_map = getattr(strat, "placeholder_data", None)
|
|
147
|
+
if isinstance(placeholder_map, dict):
|
|
148
|
+
symbol = getattr(getattr(event, "data", None), "symbol", None)
|
|
149
|
+
placeholder = placeholder_map.get(str(symbol)) if symbol is not None else None
|
|
150
|
+
if placeholder is not None:
|
|
151
|
+
try:
|
|
152
|
+
placeholder._len = max(int(getattr(placeholder, "_len", 0)), len(strat))
|
|
153
|
+
except Exception:
|
|
154
|
+
throttled_warning(
|
|
155
|
+
logger,
|
|
156
|
+
"channel_placeholder_length",
|
|
157
|
+
"Channel placeholder length update failed",
|
|
158
|
+
exc_info=False,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
placeholder.datetime[0] = event_num
|
|
163
|
+
except Exception:
|
|
164
|
+
throttled_warning(
|
|
165
|
+
logger,
|
|
166
|
+
"channel_placeholder_datetime",
|
|
167
|
+
"Channel placeholder datetime update failed",
|
|
168
|
+
exc_info=False,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
last_price = getattr(event.data, "price", None)
|
|
173
|
+
if last_price is None:
|
|
174
|
+
last_price = getattr(event.data, "close", None)
|
|
175
|
+
if last_price is not None:
|
|
176
|
+
placeholder.close[0] = float(last_price)
|
|
177
|
+
except Exception:
|
|
178
|
+
throttled_warning(
|
|
179
|
+
logger,
|
|
180
|
+
"channel_placeholder_price",
|
|
181
|
+
"Channel placeholder price update failed",
|
|
182
|
+
exc_info=False,
|
|
183
|
+
)
|
|
184
|
+
except Exception:
|
|
185
|
+
throttled_warning(
|
|
186
|
+
logger,
|
|
187
|
+
"channel_strategy_datetime",
|
|
188
|
+
"Channel strategy datetime update failed",
|
|
189
|
+
exc_info=False,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def _step_channel_strategy(self, strat):
|
|
193
|
+
"""Run channel-mode analyzers and observers once per event."""
|
|
194
|
+
if getattr(strat, "datas", None):
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
for analyzer in itertools.chain(strat.analyzers, strat._slave_analyzers):
|
|
198
|
+
analyzer._next()
|
|
199
|
+
|
|
200
|
+
for observer in strat._get_all_observers():
|
|
201
|
+
observer._next()
|
|
202
|
+
|
|
203
|
+
def _stop_channel_strategy(self, strat):
|
|
204
|
+
"""Stop a channel-mode strategy without requiring bar datas."""
|
|
205
|
+
if getattr(strat, "datas", None):
|
|
206
|
+
strat._stop()
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
strat.stop()
|
|
210
|
+
|
|
211
|
+
for analyzer in itertools.chain(strat.analyzers, strat._slave_analyzers):
|
|
212
|
+
analyzer._stop()
|
|
213
|
+
|
|
214
|
+
for observer in strat._get_all_observers():
|
|
215
|
+
try:
|
|
216
|
+
if hasattr(observer, "stop"):
|
|
217
|
+
observer.stop()
|
|
218
|
+
except Exception:
|
|
219
|
+
logger.warning(
|
|
220
|
+
"Observer %s.stop() raised an exception",
|
|
221
|
+
type(observer).__name__,
|
|
222
|
+
exc_info=True,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# ------------------------------------------------------------------
|
|
226
|
+
# Channel mode implementation (called from run(channel=...))
|
|
227
|
+
# ------------------------------------------------------------------
|
|
228
|
+
def _run_channel(self, channel, **kwargs):
|
|
229
|
+
"""Internal: run strategies in channel event mode.
|
|
230
|
+
|
|
231
|
+
``channel`` may be:
|
|
232
|
+
* An iterable of ``Event`` objects – events are processed in a
|
|
233
|
+
loop, dispatched to broker and strategies.
|
|
234
|
+
* ``True`` – strategies are instantiated and returned immediately
|
|
235
|
+
without entering an event loop (for external async drivers).
|
|
236
|
+
"""
|
|
237
|
+
# Override params
|
|
238
|
+
pkeys = self.params._getkeys()
|
|
239
|
+
for key, val in kwargs.items():
|
|
240
|
+
if key in pkeys:
|
|
241
|
+
setattr(self.params, key, val)
|
|
242
|
+
|
|
243
|
+
# Channel-mode brokers emit simulated order notifications; force the
|
|
244
|
+
# quick-notify path so strategy/observer callbacks receive them.
|
|
245
|
+
self.p.quicknotify = True
|
|
246
|
+
|
|
247
|
+
# --- strategy instantiation (simplified, no bar-data required) ---
|
|
248
|
+
self._init_stcount()
|
|
249
|
+
runstrats: list = []
|
|
250
|
+
self.runningstrats = runstrats
|
|
251
|
+
self._channel_data_refs = {}
|
|
252
|
+
|
|
253
|
+
# Start broker
|
|
254
|
+
self._broker.start()
|
|
255
|
+
|
|
256
|
+
# The optional lifecycle summary must only read a broker after it has
|
|
257
|
+
# entered its active state. Do not make a channel run depend on an
|
|
258
|
+
# informational accessor being available.
|
|
259
|
+
if _is_output_enabled_for(logging.INFO):
|
|
260
|
+
try:
|
|
261
|
+
cash = self._broker.getcash()
|
|
262
|
+
except Exception:
|
|
263
|
+
logger.warning("channel broker cash unavailable for lifecycle logging")
|
|
264
|
+
cash = "unavailable"
|
|
265
|
+
logger.info(
|
|
266
|
+
"channel run starting: strategies=%d datas=%d cash=%s",
|
|
267
|
+
len(self.strats),
|
|
268
|
+
len(self.datas),
|
|
269
|
+
cash,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
self._instantiate_channel_strategies(runstrats)
|
|
273
|
+
self._wire_channel_strategies(runstrats)
|
|
274
|
+
|
|
275
|
+
# If channel is just True, return strategies for external event loops
|
|
276
|
+
if channel is True:
|
|
277
|
+
self.runstrats = [runstrats]
|
|
278
|
+
return runstrats
|
|
279
|
+
|
|
280
|
+
# --- channel event loop ---
|
|
281
|
+
for event in channel:
|
|
282
|
+
if self._event_stop:
|
|
283
|
+
break
|
|
284
|
+
|
|
285
|
+
for strat in runstrats:
|
|
286
|
+
self._advance_channel_strategy_clock(strat, event)
|
|
287
|
+
|
|
288
|
+
# 1. Let the broker process the raw event data
|
|
289
|
+
ch = event.channel_type
|
|
290
|
+
evdata = event.data
|
|
291
|
+
if ch == "tick" and hasattr(self._broker, "process_tick"):
|
|
292
|
+
self._broker.process_tick(evdata)
|
|
293
|
+
elif ch == "orderbook" and hasattr(self._broker, "process_orderbook"):
|
|
294
|
+
self._broker.process_orderbook(evdata)
|
|
295
|
+
elif ch == "bar" and hasattr(self._broker, "process_bar"):
|
|
296
|
+
self._broker.process_bar(evdata)
|
|
297
|
+
|
|
298
|
+
# 2. Deliver broker order-fill notifications to strategies
|
|
299
|
+
while True:
|
|
300
|
+
order = self._broker.get_notification()
|
|
301
|
+
if order is None:
|
|
302
|
+
break
|
|
303
|
+
owner = getattr(order, "owner", None)
|
|
304
|
+
if owner is None:
|
|
305
|
+
owner = getattr(getattr(order, "p", None), "owner", None)
|
|
306
|
+
if owner is None and runstrats:
|
|
307
|
+
owner = runstrats[0]
|
|
308
|
+
if owner is not None:
|
|
309
|
+
owner._addnotification(order, quicknotify=True)
|
|
310
|
+
|
|
311
|
+
# 3. Dispatch channel event to strategies
|
|
312
|
+
self.dispatch_channel_event(event)
|
|
313
|
+
|
|
314
|
+
# 4. Advance analyzers/observers that rely on next()-style hooks
|
|
315
|
+
for strat in runstrats:
|
|
316
|
+
self._step_channel_strategy(strat)
|
|
317
|
+
|
|
318
|
+
# --- teardown ---
|
|
319
|
+
self._teardown_channel(runstrats)
|
|
320
|
+
return runstrats
|
|
321
|
+
|
|
322
|
+
def _teardown_channel(self, runstrats):
|
|
323
|
+
"""Stop a channel session after its event loop or owner has finished."""
|
|
324
|
+
for strat in runstrats:
|
|
325
|
+
self._stop_channel_strategy(strat)
|
|
326
|
+
|
|
327
|
+
self._broker.stop()
|
|
328
|
+
self.runstrats = [runstrats]
|
|
329
|
+
|
|
330
|
+
def _instantiate_channel_strategies(self, runstrats):
|
|
331
|
+
"""Instantiate strategy classes for channel mode and append to
|
|
332
|
+
``runstrats``.
|
|
333
|
+
|
|
334
|
+
Extracted from ``_run_channel`` (instantiation phase); behavior
|
|
335
|
+
unchanged. Honors ``StrategySkipError``, ``oldsync``,
|
|
336
|
+
``tradehistory`` and broker-provided context exactly as before.
|
|
337
|
+
"""
|
|
338
|
+
# Instantiate each strategy class added via addstrategy()
|
|
339
|
+
iterstrats = itertools.product(*self.strats)
|
|
340
|
+
for iterstrat in iterstrats:
|
|
341
|
+
for stratcls, sargs, skwargs in iterstrat:
|
|
342
|
+
try:
|
|
343
|
+
with OwnerContext.set_owner(self):
|
|
344
|
+
if hasattr(stratcls, "_create_strategy_safely"):
|
|
345
|
+
strat = stratcls._create_strategy_safely(*sargs, **skwargs)
|
|
346
|
+
else:
|
|
347
|
+
strat = stratcls(*sargs, **skwargs)
|
|
348
|
+
except errors.StrategySkipError:
|
|
349
|
+
logger.warning("channel:297 suppressed bare")
|
|
350
|
+
continue # user requested skip, same as standard run() path
|
|
351
|
+
if self.p.oldsync:
|
|
352
|
+
strat._oldsync = True
|
|
353
|
+
if self.p.tradehistory:
|
|
354
|
+
strat.set_tradehistory()
|
|
355
|
+
runstrats.append(strat)
|
|
356
|
+
|
|
357
|
+
context_getter = getattr(self._broker, "get_context", None)
|
|
358
|
+
if callable(context_getter):
|
|
359
|
+
context = context_getter()
|
|
360
|
+
for strat in runstrats:
|
|
361
|
+
strat.context = context
|
|
362
|
+
|
|
363
|
+
def _wire_channel_strategies(self, runstrats):
|
|
364
|
+
"""Attach observers, analyzers and sizers to channel strategies and
|
|
365
|
+
start them.
|
|
366
|
+
|
|
367
|
+
Extracted from ``_run_channel`` (setup phase); behavior unchanged.
|
|
368
|
+
"""
|
|
369
|
+
# Channel mode still needs explicit observers/analyzers initialization.
|
|
370
|
+
defaultsizer = self.sizers.get(None, (None, None, None))
|
|
371
|
+
for idx, strat in enumerate(runstrats):
|
|
372
|
+
for multi, obscls, obsargs, obskwargs in self.observers:
|
|
373
|
+
strat._addobserver(multi, obscls, *obsargs, **obskwargs)
|
|
374
|
+
|
|
375
|
+
for ancls, anargs, ankwargs in self.analyzers:
|
|
376
|
+
strat._addanalyzer(ancls, *anargs, **ankwargs)
|
|
377
|
+
|
|
378
|
+
sizer, sargs, skwargs = self.sizers.get(idx, defaultsizer)
|
|
379
|
+
if sizer is not None:
|
|
380
|
+
strat._addsizer(sizer, *sargs, **skwargs)
|
|
381
|
+
|
|
382
|
+
self._start_channel_strategy(strat)
|