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/cerebro.py
ADDED
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Cerebro - The main engine of the Backtrader framework.
|
|
3
|
+
|
|
4
|
+
This module contains the Cerebro class, which is the central orchestrator for
|
|
5
|
+
backtesting and live trading operations. Cerebro manages data feeds, strategies,
|
|
6
|
+
brokers, analyzers, observers, and all other components of the trading system.
|
|
7
|
+
|
|
8
|
+
Key Features:
|
|
9
|
+
- Data feed management and synchronization
|
|
10
|
+
- Strategy instantiation and execution
|
|
11
|
+
- Broker integration for order execution
|
|
12
|
+
- Multi-core optimization support
|
|
13
|
+
- Live trading and backtesting modes
|
|
14
|
+
- Plotting and analysis capabilities
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
Basic backtest setup::
|
|
18
|
+
|
|
19
|
+
import backtrader as bt
|
|
20
|
+
|
|
21
|
+
cerebro = bt.Cerebro()
|
|
22
|
+
data = bt.feeds.GenericCSVData(dataname='data.csv')
|
|
23
|
+
cerebro.adddata(data)
|
|
24
|
+
cerebro.addstrategy(MyStrategy)
|
|
25
|
+
cerebro.broker.setcash(100000)
|
|
26
|
+
results = cerebro.run()
|
|
27
|
+
cerebro.plot()
|
|
28
|
+
|
|
29
|
+
Classes:
|
|
30
|
+
OptReturn: Lightweight result object for optimization runs.
|
|
31
|
+
Cerebro: Main backtesting/trading engine.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# pylint: disable=unused-import
|
|
35
|
+
# ruff: noqa: F401
|
|
36
|
+
# NOTE (iteration 28): the module-level imports below are intentionally kept
|
|
37
|
+
# even where the facade no longer references every name: ``backtrader.cerebro``
|
|
38
|
+
# defines no ``__all__`` and ``from backtrader.cerebro import *`` has always
|
|
39
|
+
# exported these bindings. Narrowing them would be a breaking change
|
|
40
|
+
# (AC28-03 star-export parity).
|
|
41
|
+
|
|
42
|
+
import collections
|
|
43
|
+
import datetime
|
|
44
|
+
import functools
|
|
45
|
+
import itertools
|
|
46
|
+
import multiprocessing
|
|
47
|
+
import threading
|
|
48
|
+
from datetime import timezone
|
|
49
|
+
from typing import Dict
|
|
50
|
+
|
|
51
|
+
from . import errors, feeds, indicator, linebuffer, observers
|
|
52
|
+
|
|
53
|
+
# Iteration 28: implementation mixins (imported under private aliases so the
|
|
54
|
+
# star-export namespace of ``backtrader.cerebro`` stays unchanged).
|
|
55
|
+
from ._cerebro.channel import ChannelMixin as _ChannelMixin
|
|
56
|
+
from ._cerebro.execution import ExecutionMixin as _ExecutionMixin
|
|
57
|
+
from ._cerebro.lifecycle import RunLifecycleMixin as _RunLifecycleMixin
|
|
58
|
+
from ._cerebro.notifications import NotificationMixin as _NotificationMixin
|
|
59
|
+
from ._cerebro.presentation import PresentationMixin as _PresentationMixin
|
|
60
|
+
from ._cerebro.registry import RegistryMixin as _RegistryMixin
|
|
61
|
+
from ._cerebro.runnext import RunNextMixin as _RunNextMixin
|
|
62
|
+
from ._cerebro.runonce import RunOnceMixin as _RunOnceMixin
|
|
63
|
+
from .brokers import BackBroker
|
|
64
|
+
from .channel import ChannelDataRef
|
|
65
|
+
from .dataseries import TimeFrame
|
|
66
|
+
from .feed import AbstractDataBase
|
|
67
|
+
from .metabase import OwnerContext
|
|
68
|
+
from .parameters import ParameterDescriptor, ParameterizedBase
|
|
69
|
+
from .strategy import SignalStrategy, Strategy
|
|
70
|
+
from .timer import Timer
|
|
71
|
+
from .tradingcal import PandasMarketCalendar, TradingCalendarBase
|
|
72
|
+
from .utils import OrderedDict, date2num, tzparse
|
|
73
|
+
from .utils.dateintern import _num2date_cached
|
|
74
|
+
from .utils.log_message import (
|
|
75
|
+
_get_logging_config_snapshot,
|
|
76
|
+
_restore_logging_config,
|
|
77
|
+
get_logger,
|
|
78
|
+
)
|
|
79
|
+
from .utils.py3 import integer_types, map, range, string_types, zip
|
|
80
|
+
from .writer import WriterFile
|
|
81
|
+
|
|
82
|
+
logger = get_logger(__name__)
|
|
83
|
+
|
|
84
|
+
# Python 3 always provides collections.abc (the only supported baseline).
|
|
85
|
+
collectionsAbc = collections.abc # collections.Iterable -> collections.abc.Iterable
|
|
86
|
+
|
|
87
|
+
# Python 3.11+ has datetime.UTC, earlier versions use timezone.utc
|
|
88
|
+
UTC = timezone.utc
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class _RunStopEvent(threading.Event):
|
|
92
|
+
"""A thread-safe stop signal that preserves the legacy bool checks."""
|
|
93
|
+
|
|
94
|
+
def __bool__(self):
|
|
95
|
+
return self.is_set()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _runstop_scoped(run_method):
|
|
99
|
+
"""Publish an active run before its body and retire synchronous runs."""
|
|
100
|
+
|
|
101
|
+
@functools.wraps(run_method)
|
|
102
|
+
def _wrapped(self, *args, **kwargs):
|
|
103
|
+
token = self._open_run_scope()
|
|
104
|
+
retain_external_channel_scope = False
|
|
105
|
+
try:
|
|
106
|
+
result = run_method(self, *args, **kwargs)
|
|
107
|
+
if kwargs.get("channel") is True:
|
|
108
|
+
self._retain_external_channel_scope(token, result)
|
|
109
|
+
retain_external_channel_scope = True
|
|
110
|
+
return result
|
|
111
|
+
finally:
|
|
112
|
+
if not retain_external_channel_scope:
|
|
113
|
+
self._end_run(token)
|
|
114
|
+
|
|
115
|
+
return _wrapped
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class OptReturn:
|
|
119
|
+
"""Lightweight result container for optimization runs.
|
|
120
|
+
|
|
121
|
+
This class is defined at module level to make it picklable for
|
|
122
|
+
multiprocessing. It stores only essential information from strategy
|
|
123
|
+
runs during optimization to reduce memory usage.
|
|
124
|
+
|
|
125
|
+
Attributes:
|
|
126
|
+
p: Alias for params.
|
|
127
|
+
params: Strategy parameters used in this optimization run.
|
|
128
|
+
analyzers: Analyzer results (if returned during optimization).
|
|
129
|
+
|
|
130
|
+
Note:
|
|
131
|
+
Additional attributes may be set dynamically via kwargs.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
def __init__(self, params, **kwargs):
|
|
135
|
+
"""Initialize the OptReturn object.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
params: Strategy parameters used in this optimization run.
|
|
139
|
+
**kwargs: Additional keyword arguments to set as attributes.
|
|
140
|
+
"""
|
|
141
|
+
self.p = self.params = params
|
|
142
|
+
for k, v in kwargs.items():
|
|
143
|
+
setattr(self, k, v)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# pylint: disable=too-many-ancestors
|
|
147
|
+
# The eight implementation mixins keep the single public Cerebro class under
|
|
148
|
+
# the 900-line file budget (iteration 28); see backtrader/_cerebro/.
|
|
149
|
+
class Cerebro(
|
|
150
|
+
_RegistryMixin,
|
|
151
|
+
_NotificationMixin,
|
|
152
|
+
_RunLifecycleMixin,
|
|
153
|
+
_ChannelMixin,
|
|
154
|
+
_ExecutionMixin,
|
|
155
|
+
_RunNextMixin,
|
|
156
|
+
_RunOnceMixin,
|
|
157
|
+
_PresentationMixin,
|
|
158
|
+
ParameterizedBase,
|
|
159
|
+
):
|
|
160
|
+
"""Params:
|
|
161
|
+
|
|
162
|
+
- ``preload`` (default: ``True``)
|
|
163
|
+
|
|
164
|
+
Whether to preload the different ``data feeds`` passed to cerebro for
|
|
165
|
+
the Strategies
|
|
166
|
+
|
|
167
|
+
Note: When True (default), data is loaded into memory before backtesting,
|
|
168
|
+
which uses more memory but significantly improves execution speed.
|
|
169
|
+
|
|
170
|
+
- ``runonce`` (default: ``True``)
|
|
171
|
+
|
|
172
|
+
Run `Indicators` in vectorized mode to speed up the entire system.
|
|
173
|
+
Strategies and Observers will always be run on an event-based basis
|
|
174
|
+
|
|
175
|
+
Note: When True, indicators are calculated using vectorized operations
|
|
176
|
+
for better performance. Strategies and observers still run event-by-event.
|
|
177
|
+
|
|
178
|
+
- ``live`` (default: ``False``)
|
|
179
|
+
|
|
180
|
+
If no data has reported itself as *live* (via the data's ``islive``
|
|
181
|
+
method but the end user still wants to run in ``live`` mode, this
|
|
182
|
+
parameter can be set to true
|
|
183
|
+
|
|
184
|
+
This will simultaneously deactivate ``preload`` and ``runonce``. It
|
|
185
|
+
will have no effect on memory saving schemes.
|
|
186
|
+
|
|
187
|
+
Note: Setting to True forces live mode behavior, disabling preload and
|
|
188
|
+
runonce optimizations, which slows down backtesting.
|
|
189
|
+
|
|
190
|
+
- ``maxcpus`` (default: None -> all available cores)
|
|
191
|
+
|
|
192
|
+
How many cores to use simultaneously for optimization
|
|
193
|
+
|
|
194
|
+
Note: Set to number of CPU cores minus 1 to avoid system overload.
|
|
195
|
+
Use None (default) to use all available cores.
|
|
196
|
+
|
|
197
|
+
- ``stdstats`` (default: ``True``)
|
|
198
|
+
|
|
199
|
+
If True, default Observers will be added: Broker (Cash and Value),
|
|
200
|
+
Trades and BuySell
|
|
201
|
+
|
|
202
|
+
Note: These observers are used for plotting. Set to False if not needed.
|
|
203
|
+
|
|
204
|
+
- ``oldbuysell`` (default: ``False``)
|
|
205
|
+
|
|
206
|
+
If ``stdstats`` is ``True`` and observers are getting automatically
|
|
207
|
+
added, this switch controls the main behavior of the ``BuySell``
|
|
208
|
+
observer
|
|
209
|
+
|
|
210
|
+
- ``False``: use the modern behavior in which the buy / sell signals
|
|
211
|
+
are plotted below / above the low / high prices respectively to avoid
|
|
212
|
+
cluttering the plot
|
|
213
|
+
|
|
214
|
+
- ``True``: use the deprecated behavior in which the buy / sell signals
|
|
215
|
+
are plotted where the average price of the order executions for the
|
|
216
|
+
given moment in time is. This will, of course, be on top of an OHLC bar
|
|
217
|
+
or on a Line on Cloe bar, difficult the recognition of the plot.
|
|
218
|
+
|
|
219
|
+
Note: False (modern) plots signals outside the price bars for clarity.
|
|
220
|
+
True (old) plots signals at execution price, overlapping with bars.
|
|
221
|
+
|
|
222
|
+
- ``oldtrades`` (default: ``False``)
|
|
223
|
+
|
|
224
|
+
If ``stdstats`` is ``True`` and observers are getting automatically
|
|
225
|
+
added, this switch controls the main behavior of the ``Trades``
|
|
226
|
+
observer
|
|
227
|
+
|
|
228
|
+
- ``False``: use the modern behavior in which trades for all datas are
|
|
229
|
+
plotted with different markers
|
|
230
|
+
|
|
231
|
+
- ``True``: use the old Trades observer which plots the trades with the
|
|
232
|
+
same markers, differentiating only if they are positive or negative
|
|
233
|
+
|
|
234
|
+
Note: False uses different markers for different trades.
|
|
235
|
+
True uses same markers, only distinguishing positive/negative.
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
- ``exactbars`` (default: ``False``)
|
|
239
|
+
|
|
240
|
+
With the default value, each and every value stored in a line is kept in
|
|
241
|
+
memory
|
|
242
|
+
|
|
243
|
+
Possible values:
|
|
244
|
+
- ``True`` or ``1``: all "lines" objects reduce memory usage to the
|
|
245
|
+
automatically calculated minimum period.
|
|
246
|
+
|
|
247
|
+
If a Simple Moving Average has a period of 30, the underlying data
|
|
248
|
+
will have always a running buffer of 30 bars to allow the
|
|
249
|
+
calculation of the Simple Moving Average
|
|
250
|
+
|
|
251
|
+
- This setting will deactivate ``preload`` and ``runonce``
|
|
252
|
+
- Using this setting also deactivates **plotting**
|
|
253
|
+
|
|
254
|
+
- ``-1``: datafeeds and indicators/operations at strategy level will
|
|
255
|
+
keep all data in memory.
|
|
256
|
+
|
|
257
|
+
For example: a ``RSI`` internally uses the indicator ``UpDay`` to
|
|
258
|
+
make calculations. This subindicator will not keep all data in
|
|
259
|
+
memory
|
|
260
|
+
|
|
261
|
+
- This allows keeping ``plotting`` and ``preloading`` active.
|
|
262
|
+
|
|
263
|
+
- ``runonce`` will be deactivated
|
|
264
|
+
|
|
265
|
+
- ``-2``: data feeds and indicators kept as attributes of the
|
|
266
|
+
strategy will keep all points in memory.
|
|
267
|
+
|
|
268
|
+
For example: a ``RSI`` internally uses the indicator ``UpDay`` to
|
|
269
|
+
make calculations. This subindicator will not keep all data in
|
|
270
|
+
memory
|
|
271
|
+
|
|
272
|
+
If in the ``__init__`` something like
|
|
273
|
+
``a = self.data.close - self.data.high`` is defined, then ``a``
|
|
274
|
+
will not keep all data in memory
|
|
275
|
+
|
|
276
|
+
- This allows keeping ``plotting`` and ``preloading`` active.
|
|
277
|
+
|
|
278
|
+
- ``runonce`` will be deactivated
|
|
279
|
+
|
|
280
|
+
Note on exactbars values:
|
|
281
|
+
- True/1: Minimum memory, disables preload/runonce/plotting
|
|
282
|
+
- -1: Keeps data/indicators but not sub-indicator internals, disables runonce
|
|
283
|
+
- -2: Keeps strategy-level data/indicators, sub-indicators not using self are discarded
|
|
284
|
+
|
|
285
|
+
- ``objcache`` (default: ``False``)
|
|
286
|
+
|
|
287
|
+
Experimental option to implement a cache of lines objects and reduce
|
|
288
|
+
the amount of them. Example from UltimateOscillator:
|
|
289
|
+
|
|
290
|
+
bp = self.data.close - TrueLow(self.data)
|
|
291
|
+
tr = TrueRange(self.data) # -> creates another TrueLow(self.data)
|
|
292
|
+
|
|
293
|
+
If this is `True`, the second ``TrueLow(self.data)`` inside ``TrueRange``
|
|
294
|
+
matches the signature of the one in the ``bp`` calculation. It will be
|
|
295
|
+
reused.
|
|
296
|
+
|
|
297
|
+
Corner cases may happen in which this drives a line object off its
|
|
298
|
+
minimum period and breaks things, and it is therefore disabled.
|
|
299
|
+
|
|
300
|
+
Note: When True, identical indicator calculations are cached and reused
|
|
301
|
+
to reduce computation. Disabled by default due to edge cases.
|
|
302
|
+
|
|
303
|
+
- ``writer`` (default: ``False``)
|
|
304
|
+
|
|
305
|
+
If set to ``True`` a default WriterFile will be created which will
|
|
306
|
+
print to stdout. It will be added to the strategy (in addition to any
|
|
307
|
+
other writers added by the user code)
|
|
308
|
+
|
|
309
|
+
Note: Outputs trading information to stdout. Custom logging in strategy
|
|
310
|
+
is usually preferred for more control.
|
|
311
|
+
|
|
312
|
+
- ``tradehistory`` (default: ``False``)
|
|
313
|
+
|
|
314
|
+
If set to ``True``, it will activate update event logging in each trade
|
|
315
|
+
for all strategies. This can also be achieved on a per-strategy
|
|
316
|
+
basis with the strategy method ``set_tradehistory``
|
|
317
|
+
|
|
318
|
+
Note: Enables trade update logging for all strategies. Can also be
|
|
319
|
+
enabled per-strategy using set_tradehistory method.
|
|
320
|
+
|
|
321
|
+
- ``optdatas`` (default: ``True``)
|
|
322
|
+
|
|
323
|
+
If ``True`` and optimizing (and the system can ``preload`` and use
|
|
324
|
+
``runonce``, data preloading will be done only once in the main process
|
|
325
|
+
to save time and resources.
|
|
326
|
+
|
|
327
|
+
The tests show an approximate ``20%`` speed-up moving from a sample
|
|
328
|
+
execution in ``83`` seconds to ``66``
|
|
329
|
+
|
|
330
|
+
Note: When True with preload/runonce, data is preloaded once in the
|
|
331
|
+
main process and shared across optimization workers (~20% speedup).
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
- ``optreturn`` (default: ``True``)
|
|
335
|
+
|
|
336
|
+
If `True`, the optimization results will not be full ``Strategy``
|
|
337
|
+
objects (and all *datas*, *indicators*, *observers* ...) but object
|
|
338
|
+
with the following attributes (same as in ``Strategy``):
|
|
339
|
+
|
|
340
|
+
- ``params`` (or ``p``) the strategy had for the execution
|
|
341
|
+
- ``analyzers`` the strategy has executed
|
|
342
|
+
|
|
343
|
+
On most occasions, only the *analyzers* and with which *params* are
|
|
344
|
+
the things needed to evaluate the performance of a strategy. If
|
|
345
|
+
detailed analysis of the generated values for (for example)
|
|
346
|
+
*indicators* is needed, turn this off
|
|
347
|
+
|
|
348
|
+
The tests show a 13% - 15% improvement in execution time. Combined
|
|
349
|
+
with `optdatas` the total gain increases to a total speed-up of
|
|
350
|
+
`32%` in an optimization run.
|
|
351
|
+
|
|
352
|
+
Note: Returns only params and analyzers during optimization, discarding
|
|
353
|
+
data/indicators/observers for ~15% speedup (32% combined with optdatas).
|
|
354
|
+
|
|
355
|
+
- ``oldsync`` (default: ``False``)
|
|
356
|
+
|
|
357
|
+
Starting with release 1.9.0.99, the synchronization of multiple datas
|
|
358
|
+
(same or different timeframes) has been changed to allow datas of
|
|
359
|
+
different lengths.
|
|
360
|
+
|
|
361
|
+
If the old behavior with data0 as the master of the system is wished,
|
|
362
|
+
set this parameter to true
|
|
363
|
+
|
|
364
|
+
Note: False allows data feeds of different lengths.
|
|
365
|
+
True uses data0 as master (legacy behavior).
|
|
366
|
+
|
|
367
|
+
- ``tz`` (default: ``None``)
|
|
368
|
+
|
|
369
|
+
Adds a global timezone for strategies. The argument ``tz`` can be
|
|
370
|
+
|
|
371
|
+
- ``None``: in this case the datetime displayed by strategies will be
|
|
372
|
+
in UTC, which has always been the standard behavior
|
|
373
|
+
|
|
374
|
+
- ``pytz`` instance. It will be used as such to convert UTC times to
|
|
375
|
+
the chosen timezone
|
|
376
|
+
|
|
377
|
+
- ``string``. Instantiating a ``pytz`` instance will be attempted.
|
|
378
|
+
|
|
379
|
+
- ``integer``. Use, for the strategy, the same timezone as the
|
|
380
|
+
corresponding ``data`` in the ``self.datas`` iterable (``0`` would
|
|
381
|
+
use the timezone from ``data0``)
|
|
382
|
+
|
|
383
|
+
Note: None=UTC, pytz instance converts from UTC, string creates pytz,
|
|
384
|
+
integer uses timezone from corresponding data feed index.
|
|
385
|
+
|
|
386
|
+
- ``cheat_on_open`` (default: ``False``)
|
|
387
|
+
|
|
388
|
+
The ``next_open`` method of strategies will be called. This happens
|
|
389
|
+
before ``next`` and before the broker has had a chance to evaluate
|
|
390
|
+
orders. The indicators have not yet been recalculated. This allows
|
|
391
|
+
issuing an order which takes into account the indicators of the previous
|
|
392
|
+
day but uses the ``open`` price for stake calculations
|
|
393
|
+
|
|
394
|
+
For cheat_on_open order execution, it is also necessary to make the
|
|
395
|
+
call ``cerebro.broker.set_coo(True)`` or instantiate a broker with
|
|
396
|
+
``BackBroker(coo=True)`` (where *coo* stands for cheat-on-open) or set
|
|
397
|
+
the ``broker_coo`` parameter to ``True``. Cerebro will do it
|
|
398
|
+
automatically unless disabled below.
|
|
399
|
+
|
|
400
|
+
Note: Enables using next bar's open price for position sizing.
|
|
401
|
+
Useful for precise capital allocation. Requires broker_coo=True.
|
|
402
|
+
|
|
403
|
+
- ``broker_coo`` (default: ``True``)
|
|
404
|
+
|
|
405
|
+
This will automatically invoke the ``set_coo`` method of the broker
|
|
406
|
+
with ``True`` to activate ``cheat_on_open`` execution. Will only do it
|
|
407
|
+
if ``cheat_on_open`` is also ``True``
|
|
408
|
+
|
|
409
|
+
Note: Works together with cheat_on_open parameter.
|
|
410
|
+
|
|
411
|
+
- ``quicknotify`` (default: ``False``)
|
|
412
|
+
|
|
413
|
+
Broker notifications are delivered right before the delivery of the
|
|
414
|
+
*next* prices. For backtesting, this has no implications, but with live
|
|
415
|
+
brokers, a notification can take place long before the bar is
|
|
416
|
+
delivered. When set to ``True`` notifications will be delivered as soon
|
|
417
|
+
as possible (see ``qcheck`` in live feeds)
|
|
418
|
+
|
|
419
|
+
Set to ``False`` for compatibility. May be changed to ``True``
|
|
420
|
+
|
|
421
|
+
Note: False delays notifications until next bar. True sends immediately.
|
|
422
|
+
Mainly relevant for live trading.
|
|
423
|
+
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
# Parameter descriptors using new system
|
|
427
|
+
preload = ParameterDescriptor(
|
|
428
|
+
default=True, type_=bool, doc="Whether to preload the different data feeds"
|
|
429
|
+
)
|
|
430
|
+
runonce = ParameterDescriptor(default=True, type_=bool, doc="Run Indicators in vectorized mode")
|
|
431
|
+
maxcpus = ParameterDescriptor(default=None, doc="How many cores to use for optimization")
|
|
432
|
+
stdstats = ParameterDescriptor(default=True, type_=bool, doc="Add default Observers")
|
|
433
|
+
oldbuysell = ParameterDescriptor(
|
|
434
|
+
default=False, type_=bool, doc="Use old BuySell observer behavior"
|
|
435
|
+
)
|
|
436
|
+
oldtrades = ParameterDescriptor(
|
|
437
|
+
default=False, type_=bool, doc="Use old Trades observer behavior"
|
|
438
|
+
)
|
|
439
|
+
lookahead = ParameterDescriptor(default=0, type_=int, doc="Lookahead parameter")
|
|
440
|
+
exactbars = ParameterDescriptor(default=False, doc="Memory usage control for lines objects")
|
|
441
|
+
optdatas = ParameterDescriptor(
|
|
442
|
+
default=True, type_=bool, doc="Optimize data preloading during optimization"
|
|
443
|
+
)
|
|
444
|
+
optreturn = ParameterDescriptor(
|
|
445
|
+
default=True, type_=bool, doc="Return simplified objects during optimization"
|
|
446
|
+
)
|
|
447
|
+
objcache = ParameterDescriptor(
|
|
448
|
+
default=False, type_=bool, doc="Cache lines objects to reduce memory"
|
|
449
|
+
)
|
|
450
|
+
live = ParameterDescriptor(default=False, type_=bool, doc="Run in live mode")
|
|
451
|
+
writer = ParameterDescriptor(default=False, type_=bool, doc="Add a default WriterFile")
|
|
452
|
+
tradehistory = ParameterDescriptor(
|
|
453
|
+
default=False, type_=bool, doc="Activate trade history logging"
|
|
454
|
+
)
|
|
455
|
+
oldsync = ParameterDescriptor(default=False, type_=bool, doc="Use old synchronization behavior")
|
|
456
|
+
tz = ParameterDescriptor(default=None, doc="Global timezone for strategies")
|
|
457
|
+
cheat_on_open = ParameterDescriptor(
|
|
458
|
+
default=False, type_=bool, doc="Enable cheat-on-open execution"
|
|
459
|
+
)
|
|
460
|
+
broker_coo = ParameterDescriptor(
|
|
461
|
+
default=True, type_=bool, doc="Auto-activate broker cheat-on-open"
|
|
462
|
+
)
|
|
463
|
+
quicknotify = ParameterDescriptor(
|
|
464
|
+
default=False, type_=bool, doc="Deliver broker notifications quickly"
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
def __init__(self, **kwargs):
|
|
468
|
+
"""Initialize Cerebro with optional parameter overrides.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
**kwargs: Parameter overrides (preload, runonce, maxcpus, etc.)
|
|
472
|
+
"""
|
|
473
|
+
super().__init__(**kwargs)
|
|
474
|
+
|
|
475
|
+
# Internal state flags
|
|
476
|
+
self._timerscheat = None
|
|
477
|
+
self._timers = None
|
|
478
|
+
self.runningstrats: list = []
|
|
479
|
+
self.runstrats = None
|
|
480
|
+
self.writers_csv = None
|
|
481
|
+
self.runwriters = None
|
|
482
|
+
self._dopreload = None
|
|
483
|
+
self._dorunonce = None
|
|
484
|
+
self._exactbars = 0
|
|
485
|
+
# ``runstop`` may be called by a Timer or another thread while the
|
|
486
|
+
# engine is running. The event publishes that request safely; the
|
|
487
|
+
# lock defines the start/end boundary so stop requests made between
|
|
488
|
+
# runs cannot leak into a later run.
|
|
489
|
+
self._event_stop = _RunStopEvent()
|
|
490
|
+
self._runstop_lock = threading.RLock()
|
|
491
|
+
self._run_active = False
|
|
492
|
+
self._run_scope_token = 0
|
|
493
|
+
self._run_scope_owner = None
|
|
494
|
+
self._external_channel_token = None
|
|
495
|
+
self._external_channel_runstrats = None
|
|
496
|
+
self._external_channel_closing = False
|
|
497
|
+
self._dolive = False # Live trading mode flag
|
|
498
|
+
self._doreplay = False # Data replay mode flag
|
|
499
|
+
self._dooptimize = False # Optimization mode flag
|
|
500
|
+
|
|
501
|
+
# Component containers
|
|
502
|
+
self.stores = [] # Data stores
|
|
503
|
+
self.feeds = [] # Data feeds
|
|
504
|
+
self.datas = [] # Data objects
|
|
505
|
+
self.datasbyname = collections.OrderedDict() # Data lookup by name
|
|
506
|
+
self._channel_data_refs: Dict[str, ChannelDataRef] = {}
|
|
507
|
+
self.strats = [] # Strategy classes/instances
|
|
508
|
+
self.optcbs = [] # Optimization callbacks
|
|
509
|
+
self.observers = [] # Observer classes
|
|
510
|
+
self.analyzers = [] # Analyzer classes
|
|
511
|
+
self.indicators = [] # Indicator classes
|
|
512
|
+
self.sizers = {} # Position sizers
|
|
513
|
+
self.writers = [] # Output writers
|
|
514
|
+
self.storecbs = [] # Store callbacks
|
|
515
|
+
self.datacbs = [] # Data callbacks
|
|
516
|
+
self.signals = [] # Signal definitions
|
|
517
|
+
|
|
518
|
+
# Signal strategy configuration
|
|
519
|
+
self._signal_strat = (None, None, None)
|
|
520
|
+
self._signal_concurrent = False # Allow concurrent signals
|
|
521
|
+
self._signal_accumulate = False # Allow accumulating positions
|
|
522
|
+
|
|
523
|
+
# Internal counters and references
|
|
524
|
+
self._dataid = itertools.count(1) # Data ID counter
|
|
525
|
+
self._broker = BackBroker() # Default broker
|
|
526
|
+
self._broker.cerebro = self # Back-reference to cerebro
|
|
527
|
+
self._tradingcal = None # Trading calendar
|
|
528
|
+
self._pretimers = [] # Pre-run timers
|
|
529
|
+
self._ohistory = [] # Order history
|
|
530
|
+
self._fhistory = None # Fund history
|
|
531
|
+
|
|
532
|
+
# Override parameters from kwargs
|
|
533
|
+
pkeys = self.params._getkeys()
|
|
534
|
+
for key, val in kwargs.items():
|
|
535
|
+
if key in pkeys:
|
|
536
|
+
setattr(self.params, key, val)
|
|
537
|
+
|
|
538
|
+
def setbroker(self, broker):
|
|
539
|
+
"""
|
|
540
|
+
Sets a specific ``broker`` instance for this strategy, replacing the
|
|
541
|
+
one inherited from cerebro.
|
|
542
|
+
"""
|
|
543
|
+
self._broker = broker
|
|
544
|
+
broker.cerebro = self
|
|
545
|
+
self._maybe_add_store(broker)
|
|
546
|
+
return broker
|
|
547
|
+
|
|
548
|
+
def getbroker(self):
|
|
549
|
+
"""
|
|
550
|
+
Returns the broker instance.
|
|
551
|
+
|
|
552
|
+
This is also available as a ``property`` by the name ``broker``
|
|
553
|
+
"""
|
|
554
|
+
return self._broker
|
|
555
|
+
|
|
556
|
+
# Module passed to cerebro for multiprocessing during optimization
|
|
557
|
+
def __call__(self, iterstrat):
|
|
558
|
+
"""
|
|
559
|
+
Used during optimization to pass the cerebro over the multiprocessing
|
|
560
|
+
module without complaints
|
|
561
|
+
"""
|
|
562
|
+
token = self._open_run_scope()
|
|
563
|
+
try:
|
|
564
|
+
predata = self.p.optdatas and self._dopreload and self._dorunonce
|
|
565
|
+
return self.runstrategies(iterstrat, predata=predata)
|
|
566
|
+
finally:
|
|
567
|
+
self._end_run(token)
|
|
568
|
+
|
|
569
|
+
# Delete runstrats when pickling
|
|
570
|
+
def __getstate__(self):
|
|
571
|
+
"""
|
|
572
|
+
Used during optimization to prevent optimization result `runstrats`
|
|
573
|
+
from being pickled to subprocesses
|
|
574
|
+
"""
|
|
575
|
+
|
|
576
|
+
rv = vars(self).copy()
|
|
577
|
+
if "runstrats" in rv:
|
|
578
|
+
del rv["runstrats"]
|
|
579
|
+
# ``threading.Event`` and ``RLock`` are intentionally process-local.
|
|
580
|
+
# Optimization workers create a fresh inactive scope in ``__setstate__``.
|
|
581
|
+
rv.pop("_event_stop", None)
|
|
582
|
+
rv.pop("_runstop_lock", None)
|
|
583
|
+
rv["_run_active"] = False
|
|
584
|
+
rv["_run_scope_owner"] = None
|
|
585
|
+
rv.pop("_external_channel_token", None)
|
|
586
|
+
rv.pop("_external_channel_runstrats", None)
|
|
587
|
+
rv.pop("_external_channel_closing", None)
|
|
588
|
+
# Iteration 29: propagate only opt-in configuration, never handlers.
|
|
589
|
+
logging_config = _get_logging_config_snapshot()
|
|
590
|
+
if logging_config is not None:
|
|
591
|
+
rv["_logging_config"] = logging_config
|
|
592
|
+
else:
|
|
593
|
+
rv.pop("_logging_config", None)
|
|
594
|
+
return rv
|
|
595
|
+
|
|
596
|
+
def __setstate__(self, state):
|
|
597
|
+
"""Restore process-local run-stop state after multiprocessing pickle."""
|
|
598
|
+
state = state.copy()
|
|
599
|
+
logging_config = state.pop("_logging_config", None)
|
|
600
|
+
self.__dict__.update(state)
|
|
601
|
+
self._event_stop = _RunStopEvent()
|
|
602
|
+
self._runstop_lock = threading.RLock()
|
|
603
|
+
self._run_active = False
|
|
604
|
+
self._run_scope_token = 0
|
|
605
|
+
self._run_scope_owner = None
|
|
606
|
+
self._external_channel_token = None
|
|
607
|
+
self._external_channel_runstrats = None
|
|
608
|
+
self._external_channel_closing = False
|
|
609
|
+
_restore_logging_config(logging_config)
|
|
610
|
+
|
|
611
|
+
# Core method for backtesting. Any passed kwargs affect cerebro standard parameters.
|
|
612
|
+
# If no data added, will stop immediately. Return value differs based on optimization.
|
|
613
|
+
def _resolve_run_flags(self):
|
|
614
|
+
"""Resolve runonce/preload/exactbars/replay/live flags and build writers.
|
|
615
|
+
|
|
616
|
+
Extracted from run() to keep that method readable. Sets the private
|
|
617
|
+
execution-mode flags on self and populates self.runwriters /
|
|
618
|
+
self.writers_csv. No behavior change.
|
|
619
|
+
"""
|
|
620
|
+
# Check if _dorunonce, _dopreload, _exactbars
|
|
621
|
+
self._dorunonce = self.p.runonce
|
|
622
|
+
self._dopreload = self.p.preload
|
|
623
|
+
self._exactbars = int(self.p.exactbars)
|
|
624
|
+
# If _exactbars is not 0, _dorunonce must be False; if _dopreload is True and _exactbars < 1, set _dopreload to True
|
|
625
|
+
if self._exactbars:
|
|
626
|
+
self._dorunonce = False # something is saving memory, no runonce
|
|
627
|
+
self._dopreload = self._dopreload and self._exactbars < 1
|
|
628
|
+
# If _doreplay is True or any data has replaying attribute True, set _doreplay to True
|
|
629
|
+
self._doreplay = self._doreplay or any(x.replaying for x in self.datas)
|
|
630
|
+
# If _doreplay, need to set _dopreload to False
|
|
631
|
+
if self._doreplay:
|
|
632
|
+
# preloading is not supported with replay. full timeframe bars
|
|
633
|
+
# are constructed in realtime
|
|
634
|
+
self._dopreload = False
|
|
635
|
+
# If _dolive or live, need to set _dorunonce and _dopreload to False
|
|
636
|
+
if self._dolive or self.p.live:
|
|
637
|
+
# in this case, both preload and runonce must be off
|
|
638
|
+
self._dorunonce = False
|
|
639
|
+
self._dopreload = False
|
|
640
|
+
|
|
641
|
+
# Writer list
|
|
642
|
+
self.runwriters = []
|
|
643
|
+
|
|
644
|
+
# Add the system default writer if requested
|
|
645
|
+
if self.p.writer is True:
|
|
646
|
+
wr = WriterFile()
|
|
647
|
+
self.runwriters.append(wr)
|
|
648
|
+
|
|
649
|
+
# Instantiate any other writers
|
|
650
|
+
for wrcls, wrargs, wrkwargs in self.writers:
|
|
651
|
+
wr = wrcls(*wrargs, **wrkwargs)
|
|
652
|
+
self.runwriters.append(wr)
|
|
653
|
+
|
|
654
|
+
# Write down if any writer wants the full csv output
|
|
655
|
+
self.writers_csv = any(map(lambda x: x.p.csv, self.runwriters))
|
|
656
|
+
|
|
657
|
+
@_runstop_scoped
|
|
658
|
+
def run(self, **kwargs) -> list:
|
|
659
|
+
"""The core method to perform backtesting. Any ``kwargs`` passed to it
|
|
660
|
+
will affect the value of the standard parameters ``Cerebro`` was
|
|
661
|
+
instantiated with.
|
|
662
|
+
|
|
663
|
+
If `cerebro` has no data **and** no ``channel`` is given, the method
|
|
664
|
+
will immediately bail out.
|
|
665
|
+
|
|
666
|
+
Extra keyword arguments
|
|
667
|
+
-----------------------
|
|
668
|
+
channel : iterable or True, optional
|
|
669
|
+
When provided the engine runs in **channel mode** instead of the
|
|
670
|
+
traditional bar-based mode.
|
|
671
|
+
|
|
672
|
+
* *iterable* – an ``Event`` stream (``StreamingEventQueue``,
|
|
673
|
+
``LiveEventQueue``, or any iterable yielding ``Event``
|
|
674
|
+
objects). Events are dispatched to the broker and then to
|
|
675
|
+
every strategy via their ``notify_*`` callbacks.
|
|
676
|
+
* ``True`` – strategies are instantiated and returned
|
|
677
|
+
immediately **without** entering an event loop. This is
|
|
678
|
+
useful when an external async loop drives the data (e.g.
|
|
679
|
+
external market-data watchers calling ``strategy.notify_tick()``
|
|
680
|
+
directly). Call ``cerebro.close_channel()`` from the same
|
|
681
|
+
thread when that external loop is done to tear down brokers and
|
|
682
|
+
strategies.
|
|
683
|
+
|
|
684
|
+
It has different return values:
|
|
685
|
+
|
|
686
|
+
- For No Optimization: a list contanining instances of the Strategy
|
|
687
|
+
classes added with ``addstrategy``
|
|
688
|
+
|
|
689
|
+
- For Optimization: a list of lists which contain instances of the
|
|
690
|
+
Strategy classes added with ``addstrategy``
|
|
691
|
+
"""
|
|
692
|
+
# --- channel mode ---------------------------------------------------
|
|
693
|
+
channel = kwargs.pop("channel", None)
|
|
694
|
+
if channel is not None:
|
|
695
|
+
# _run_channel is dynamically typed; run() advertises -> list.
|
|
696
|
+
return self._run_channel(channel, **kwargs)
|
|
697
|
+
|
|
698
|
+
# If no data, return empty list immediately
|
|
699
|
+
if not self.datas:
|
|
700
|
+
return [] # nothing can be run
|
|
701
|
+
# Override standard parameters with passed kwargs
|
|
702
|
+
pkeys = self.params._getkeys()
|
|
703
|
+
for key, val in kwargs.items():
|
|
704
|
+
if key in pkeys:
|
|
705
|
+
setattr(self.params, key, val)
|
|
706
|
+
|
|
707
|
+
# Manage activate/deactivate object cache
|
|
708
|
+
# Manage object cache
|
|
709
|
+
linebuffer.LineActions.cleancache() # clean cache
|
|
710
|
+
indicator.Indicator.cleancache() # clean cache
|
|
711
|
+
|
|
712
|
+
linebuffer.LineActions.usecache(self.p.objcache)
|
|
713
|
+
indicator.Indicator.usecache(self.p.objcache)
|
|
714
|
+
|
|
715
|
+
# Resolve runonce/preload/exactbars/replay/live execution flags + writers
|
|
716
|
+
self._resolve_run_flags()
|
|
717
|
+
|
|
718
|
+
# Running strategy list
|
|
719
|
+
self.runstrats = []
|
|
720
|
+
# If signals is not None, handle signalstrategy related issues
|
|
721
|
+
if self.signals: # allow processing of signals
|
|
722
|
+
signalst, sargs, skwargs = self._signal_strat
|
|
723
|
+
if signalst is None:
|
|
724
|
+
# Try to see if the 1st regular strategy is a signal strategy
|
|
725
|
+
try:
|
|
726
|
+
signalst, sargs, skwargs = self.strats.pop(0)
|
|
727
|
+
except IndexError:
|
|
728
|
+
logger.debug("cerebro:715 ignored IndexError")
|
|
729
|
+
# Nothing there
|
|
730
|
+
else:
|
|
731
|
+
if not isinstance(signalst, SignalStrategy):
|
|
732
|
+
# no signal ... reinsert at the beginning
|
|
733
|
+
self.strats.insert(0, (signalst, sargs, skwargs))
|
|
734
|
+
signalst = None # flag as not present
|
|
735
|
+
|
|
736
|
+
if signalst is None: # recheck
|
|
737
|
+
# Still None, create a default one
|
|
738
|
+
signalst, sargs, skwargs = SignalStrategy, (), {}
|
|
739
|
+
|
|
740
|
+
# sargs/skwargs always come from a (args, kwargs) pair or the
|
|
741
|
+
# tuple()/dict() defaults above; normalize for safe unpacking.
|
|
742
|
+
sargs = sargs or ()
|
|
743
|
+
skwargs = skwargs or {}
|
|
744
|
+
|
|
745
|
+
# Add the signal strategy
|
|
746
|
+
self.addstrategy(
|
|
747
|
+
signalst,
|
|
748
|
+
*sargs,
|
|
749
|
+
_accumulate=self._signal_accumulate,
|
|
750
|
+
_concurrent=self._signal_concurrent,
|
|
751
|
+
signals=self.signals,
|
|
752
|
+
**skwargs,
|
|
753
|
+
)
|
|
754
|
+
# If strategy list is empty, add strategy
|
|
755
|
+
if not self.strats: # Datas are present, add a strategy
|
|
756
|
+
self.addstrategy(Strategy)
|
|
757
|
+
# Iterate strategies
|
|
758
|
+
iterstrats = itertools.product(*self.strats)
|
|
759
|
+
# If not optimization parameters, or using 1 cpu core
|
|
760
|
+
if not self._dooptimize or self.p.maxcpus == 1:
|
|
761
|
+
# If no optimmization is wished ... or 1 core is to be used
|
|
762
|
+
# let's skip process "spawning"
|
|
763
|
+
# Iterate through strategies
|
|
764
|
+
for iterstrat in iterstrats:
|
|
765
|
+
# Run strategy
|
|
766
|
+
runstrat = self.runstrategies(iterstrat)
|
|
767
|
+
# Add running strategy to running strategy list
|
|
768
|
+
self.runstrats.append(runstrat)
|
|
769
|
+
# If optimization parameters
|
|
770
|
+
if self._dooptimize:
|
|
771
|
+
# Iterate all optcbs to return stopped strategy results
|
|
772
|
+
for cb in self.optcbs:
|
|
773
|
+
cb(runstrat) # callback receives finished strategy
|
|
774
|
+
# If optimization parameters
|
|
775
|
+
else:
|
|
776
|
+
# If optdatas is True, and _dopreload, and _dorunonce
|
|
777
|
+
if self.p.optdatas and self._dopreload and self._dorunonce:
|
|
778
|
+
# Iterate each data, reset, if _exactbars < 1, extend data
|
|
779
|
+
# Start data
|
|
780
|
+
# If data _dopreload, call preload on data
|
|
781
|
+
for data in self.datas:
|
|
782
|
+
data.reset()
|
|
783
|
+
if self._exactbars < 1: # datas can be a full length
|
|
784
|
+
data.extend(size=self.params.lookahead)
|
|
785
|
+
data._start()
|
|
786
|
+
data.preload()
|
|
787
|
+
# Start process pool
|
|
788
|
+
pool = multiprocessing.Pool(self.p.maxcpus or None)
|
|
789
|
+
for r in pool.imap(self, iterstrats):
|
|
790
|
+
self.runstrats.append(r)
|
|
791
|
+
for cb in self.optcbs:
|
|
792
|
+
cb(r) # callback receives finished strategy
|
|
793
|
+
# Close process pool
|
|
794
|
+
pool.close()
|
|
795
|
+
# If optdatas is True, and _dopreload, and _dorunonce, iterate data and stop data
|
|
796
|
+
if self.p.optdatas and self._dopreload and self._dorunonce:
|
|
797
|
+
for data in self.datas:
|
|
798
|
+
data.stop()
|
|
799
|
+
# If not optimization parameters
|
|
800
|
+
if not self._dooptimize:
|
|
801
|
+
# avoid a list of list for regular cases
|
|
802
|
+
return self.runstrats[0]
|
|
803
|
+
|
|
804
|
+
return self.runstrats
|
|
805
|
+
|
|
806
|
+
def _build_optreturn_results(self, runstrats):
|
|
807
|
+
"""Build OptReturn results for an optimization run.
|
|
808
|
+
|
|
809
|
+
Detaches analyzers from their strategy/data references (so the result
|
|
810
|
+
is lightweight and picklable across process boundaries) and wraps each
|
|
811
|
+
strategy's params + analyzers in an OptReturn.
|
|
812
|
+
"""
|
|
813
|
+
results = []
|
|
814
|
+
for strat in runstrats:
|
|
815
|
+
for a in strat.analyzers:
|
|
816
|
+
a.strategy = None
|
|
817
|
+
a._parent = None
|
|
818
|
+
# OPTIMIZED: Use __dict__ instead of dir() for better performance
|
|
819
|
+
for attrname in list(a.__dict__.keys()):
|
|
820
|
+
if attrname.startswith("data"):
|
|
821
|
+
setattr(a, attrname, None)
|
|
822
|
+
|
|
823
|
+
oreturn = OptReturn(strat.params, analyzers=strat.analyzers, strategycls=type(strat))
|
|
824
|
+
results.append(oreturn)
|
|
825
|
+
|
|
826
|
+
return results
|
|
827
|
+
|
|
828
|
+
broker = property(getbroker, setbroker)
|