back-trader-python 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- back_trader_python-1.4.0.dist-info/METADATA +1491 -0
- back_trader_python-1.4.0.dist-info/RECORD +465 -0
- back_trader_python-1.4.0.dist-info/WHEEL +5 -0
- back_trader_python-1.4.0.dist-info/licenses/LICENSE +674 -0
- back_trader_python-1.4.0.dist-info/top_level.txt +1 -0
- backtrader/__init__.py +148 -0
- backtrader/_cerebro/__init__.py +5 -0
- backtrader/_cerebro/channel.py +382 -0
- backtrader/_cerebro/execution.py +377 -0
- backtrader/_cerebro/lifecycle.py +143 -0
- backtrader/_cerebro/notifications.py +150 -0
- backtrader/_cerebro/presentation.py +230 -0
- backtrader/_cerebro/registry.py +593 -0
- backtrader/_cerebro/runnext.py +551 -0
- backtrader/_cerebro/runonce.py +142 -0
- backtrader/analyzer.py +594 -0
- backtrader/analyzers/__init__.py +50 -0
- backtrader/analyzers/annualreturn.py +226 -0
- backtrader/analyzers/calmar.py +165 -0
- backtrader/analyzers/drawdown.py +287 -0
- backtrader/analyzers/leverage.py +112 -0
- backtrader/analyzers/logreturnsrolling.py +190 -0
- backtrader/analyzers/periodstats.py +153 -0
- backtrader/analyzers/positions.py +119 -0
- backtrader/analyzers/pyfolio.py +470 -0
- backtrader/analyzers/returns.py +192 -0
- backtrader/analyzers/sharpe.py +307 -0
- backtrader/analyzers/sharpe_ratio_stats.py +534 -0
- backtrader/analyzers/sqn.py +112 -0
- backtrader/analyzers/timereturn.py +192 -0
- backtrader/analyzers/total_value.py +75 -0
- backtrader/analyzers/tradeanalyzer.py +278 -0
- backtrader/analyzers/transactions.py +141 -0
- backtrader/analyzers/vwr.py +245 -0
- backtrader/bokeh/__init__.py +155 -0
- backtrader/bokeh/analyzers/__init__.py +13 -0
- backtrader/bokeh/analyzers/plot.py +192 -0
- backtrader/bokeh/analyzers/recorder.py +181 -0
- backtrader/bokeh/app.py +1094 -0
- backtrader/bokeh/live/__init__.py +11 -0
- backtrader/bokeh/live/client.py +352 -0
- backtrader/bokeh/live/datahandler.py +346 -0
- backtrader/bokeh/plot_adapter.py +200 -0
- backtrader/bokeh/schemes/__init__.py +14 -0
- backtrader/bokeh/schemes/blackly.py +76 -0
- backtrader/bokeh/schemes/scheme.py +150 -0
- backtrader/bokeh/schemes/tradimo.py +82 -0
- backtrader/bokeh/tab.py +125 -0
- backtrader/bokeh/tabs/__init__.py +30 -0
- backtrader/bokeh/tabs/analyzer.py +120 -0
- backtrader/bokeh/tabs/config.py +154 -0
- backtrader/bokeh/tabs/live.py +109 -0
- backtrader/bokeh/tabs/log.py +185 -0
- backtrader/bokeh/tabs/metadata.py +182 -0
- backtrader/bokeh/tabs/performance.py +359 -0
- backtrader/bokeh/tabs/source.py +70 -0
- backtrader/bokeh/utils/__init__.py +8 -0
- backtrader/bokeh/utils/helpers.py +167 -0
- backtrader/bokeh/webapp.py +164 -0
- backtrader/broker.py +478 -0
- backtrader/brokers/__init__.py +36 -0
- backtrader/brokers/bbroker.py +2576 -0
- backtrader/brokers/btapibroker.py +8227 -0
- backtrader/brokers/hft/__init__.py +89 -0
- backtrader/brokers/hft/binance_bbo.py +625 -0
- backtrader/brokers/hft/binance_bbo_compare.py +1398 -0
- backtrader/brokers/hft/examples.py +1228 -0
- backtrader/brokers/hft/exchange.py +380 -0
- backtrader/brokers/hft/latency.py +309 -0
- backtrader/brokers/hft/matching_core.py +572 -0
- backtrader/brokers/hft/queue.py +238 -0
- backtrader/brokers/hft/recorder.py +88 -0
- backtrader/brokers/hft/state.py +138 -0
- backtrader/brokers/impact_models.py +118 -0
- backtrader/brokers/mixbroker.py +895 -0
- backtrader/brokers/tickbroker.py +1991 -0
- backtrader/btrun/__init__.py +12 -0
- backtrader/btrun/btrun.py +1218 -0
- backtrader/cerebro.py +828 -0
- backtrader/channel.py +682 -0
- backtrader/channels/__init__.py +23 -0
- backtrader/channels/bridge.py +186 -0
- backtrader/channels/funding.py +248 -0
- backtrader/channels/live_queue.py +216 -0
- backtrader/channels/live_validator.py +294 -0
- backtrader/channels/orderbook.py +257 -0
- backtrader/channels/tick.py +202 -0
- backtrader/comminfo.py +665 -0
- backtrader/commissions/__init__.py +106 -0
- backtrader/commissions/ctpoption.py +993 -0
- backtrader/configs/account_config_example.yaml +8 -0
- backtrader/dataseries.py +379 -0
- backtrader/errors.py +106 -0
- backtrader/events.py +980 -0
- backtrader/feed.py +1523 -0
- backtrader/feeds/__init__.py +75 -0
- backtrader/feeds/barrier.py +2006 -0
- backtrader/feeds/blaze.py +118 -0
- backtrader/feeds/btapifeed.py +1538 -0
- backtrader/feeds/btcsv.py +203 -0
- backtrader/feeds/chainer.py +114 -0
- backtrader/feeds/cryptohftdata.py +164 -0
- backtrader/feeds/csvgeneric.py +1205 -0
- backtrader/feeds/ctpcohort.py +1051 -0
- backtrader/feeds/influxfeed.py +158 -0
- backtrader/feeds/livefeed.py +71 -0
- backtrader/feeds/mixed_channel.py +108 -0
- backtrader/feeds/mt4csv.py +42 -0
- backtrader/feeds/pandafeed.py +381 -0
- backtrader/feeds/quandl.py +256 -0
- backtrader/feeds/rollover.py +229 -0
- backtrader/feeds/sierrachart.py +30 -0
- backtrader/feeds/vchart.py +162 -0
- backtrader/feeds/vchartcsv.py +84 -0
- backtrader/feeds/vchartfile.py +153 -0
- backtrader/feeds/yahoo.py +399 -0
- backtrader/fillers.py +148 -0
- backtrader/filters/__init__.py +34 -0
- backtrader/filters/bsplitter.py +127 -0
- backtrader/filters/calendardays.py +121 -0
- backtrader/filters/datafiller.py +192 -0
- backtrader/filters/datafilter.py +74 -0
- backtrader/filters/daysteps.py +96 -0
- backtrader/filters/heikinashi.py +63 -0
- backtrader/filters/renko.py +164 -0
- backtrader/filters/session.py +289 -0
- backtrader/flt.py +80 -0
- backtrader/functions.py +960 -0
- backtrader/indicator.py +449 -0
- backtrader/indicators/__init__.py +148 -0
- backtrader/indicators/accdecoscillator.py +110 -0
- backtrader/indicators/aroon.py +300 -0
- backtrader/indicators/atr.py +315 -0
- backtrader/indicators/awesomeoscillator.py +122 -0
- backtrader/indicators/basicops.py +834 -0
- backtrader/indicators/bollinger.py +223 -0
- backtrader/indicators/cci.py +89 -0
- backtrader/indicators/channels_ext.py +83 -0
- backtrader/indicators/contrib/__init__.py +228 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma.py +28 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma_color.py +44 -0
- backtrader/indicators/contrib/accumulation_distribution_line.py +92 -0
- backtrader/indicators/contrib/adx_cross_hull_style_indicator.py +249 -0
- backtrader/indicators/contrib/adxdmi.py +34 -0
- backtrader/indicators/contrib/ai_acceleration_deceleration_oscillator.py +34 -0
- backtrader/indicators/contrib/altr_trend_signal_v22.py +85 -0
- backtrader/indicators/contrib/anchored_momentum_line.py +115 -0
- backtrader/indicators/contrib/any_range_cld_tail_indicator.py +82 -0
- backtrader/indicators/contrib/aroon_horn_sign_indicator.py +96 -0
- backtrader/indicators/contrib/aroon_oscillator_sign_alert.py +50 -0
- backtrader/indicators/contrib/arrows_curves_indicator.py +112 -0
- backtrader/indicators/contrib/as_ctrend_indicator.py +143 -0
- backtrader/indicators/contrib/asimmetric_stoch_nr_indicator.py +187 -0
- backtrader/indicators/contrib/atr_normalize_histogram.py +118 -0
- backtrader/indicators/contrib/average_change_candle.py +165 -0
- backtrader/indicators/contrib/bb_squeeze_indicator.py +60 -0
- backtrader/indicators/contrib/bezier_st_dev_indicator.py +135 -0
- backtrader/indicators/contrib/binary_wave_indicator.py +233 -0
- backtrader/indicators/contrib/blau_c_momentum_indicator.py +123 -0
- backtrader/indicators/contrib/blau_cmi_indicator.py +141 -0
- backtrader/indicators/contrib/blau_csi.py +76 -0
- backtrader/indicators/contrib/blau_ergodic.py +53 -0
- backtrader/indicators/contrib/blau_t_stoch_i.py +72 -0
- backtrader/indicators/contrib/blau_ts_stochastic.py +85 -0
- backtrader/indicators/contrib/blau_tvi.py +55 -0
- backtrader/indicators/contrib/brain_trend2_indicator.py +128 -0
- backtrader/indicators/contrib/brain_trend_signal_proxy.py +47 -0
- backtrader/indicators/contrib/brake_parb_indicator.py +85 -0
- backtrader/indicators/contrib/breakout_bars_trend_v2.py +121 -0
- backtrader/indicators/contrib/bsi_indicator.py +87 -0
- backtrader/indicators/contrib/bulls_bears_eyes.py +67 -0
- backtrader/indicators/contrib/bulls_power.py +56 -0
- backtrader/indicators/contrib/bw_wise_man1_signal.py +102 -0
- backtrader/indicators/contrib/bykov_trend_indicator.py +85 -0
- backtrader/indicators/contrib/candle_stop_color.py +46 -0
- backtrader/indicators/contrib/candles_x_smoothed_indicator.py +69 -0
- backtrader/indicators/contrib/candlesticks_bw.py +45 -0
- backtrader/indicators/contrib/caudate_x_period_candle_color.py +56 -0
- backtrader/indicators/contrib/cci_histogram_indicator.py +53 -0
- backtrader/indicators/contrib/cci_woodies_indicator.py +80 -0
- backtrader/indicators/contrib/center_of_gravity_candle_indicator.py +83 -0
- backtrader/indicators/contrib/center_of_gravity_indicator.py +70 -0
- backtrader/indicators/contrib/cg_oscillator.py +40 -0
- backtrader/indicators/contrib/close_line_cci.py +38 -0
- backtrader/indicators/contrib/close_price_fractals.py +47 -0
- backtrader/indicators/contrib/color3rd_gen_xma_indicator.py +122 -0
- backtrader/indicators/contrib/color_bb_candles_indicator.py +108 -0
- backtrader/indicators/contrib/color_coppock_indicator.py +157 -0
- backtrader/indicators/contrib/color_hma.py +71 -0
- backtrader/indicators/contrib/color_j_variation_indicator.py +53 -0
- backtrader/indicators/contrib/color_metro_de_marker_indicator.py +78 -0
- backtrader/indicators/contrib/color_metro_stochastic_indicator.py +93 -0
- backtrader/indicators/contrib/color_metro_wpr_indicator.py +85 -0
- backtrader/indicators/contrib/color_schaff_de_marker_trend_cycle.py +92 -0
- backtrader/indicators/contrib/color_schaff_trend_cycle_indicator.py +203 -0
- backtrader/indicators/contrib/color_step_xccx_indicator.py +193 -0
- backtrader/indicators/contrib/color_x2_ma.py +49 -0
- backtrader/indicators/contrib/color_x_derivative.py +63 -0
- backtrader/indicators/contrib/color_zerolag_de_marker.py +84 -0
- backtrader/indicators/contrib/corrected_average_indicator.py +127 -0
- backtrader/indicators/contrib/darvas_boxes_system.py +73 -0
- backtrader/indicators/contrib/dema_range_channel_color.py +42 -0
- backtrader/indicators/contrib/derivative_indicator.py +95 -0
- backtrader/indicators/contrib/digital_ft01_indicator.py +112 -0
- backtrader/indicators/contrib/digital_macd.py +200 -0
- backtrader/indicators/contrib/donchian_channels_system.py +45 -0
- backtrader/indicators/contrib/dots_indicator.py +93 -0
- backtrader/indicators/contrib/ef_distance_indicator.py +82 -0
- backtrader/indicators/contrib/ema_rsi_va.py +80 -0
- backtrader/indicators/contrib/envelopes_jp_alonso.py +32 -0
- backtrader/indicators/contrib/f2a_ao_indicator.py +120 -0
- backtrader/indicators/contrib/fatl_filter.py +179 -0
- backtrader/indicators/contrib/fibo_candles_indicator.py +78 -0
- backtrader/indicators/contrib/fine_tuning_ma.py +100 -0
- backtrader/indicators/contrib/fisher_org_v1.py +102 -0
- backtrader/indicators/contrib/fisher_org_v1_sign.py +118 -0
- backtrader/indicators/contrib/force_index_ema.py +96 -0
- backtrader/indicators/contrib/force_index_ema_2.py +27 -0
- backtrader/indicators/contrib/forecast_oscilator.py +145 -0
- backtrader/indicators/contrib/fractal_amambk.py +81 -0
- backtrader/indicators/contrib/frama_series.py +84 -0
- backtrader/indicators/contrib/frasm_av2_indicator.py +104 -0
- backtrader/indicators/contrib/go_indicator.py +93 -0
- backtrader/indicators/contrib/hlr_indicator.py +95 -0
- backtrader/indicators/contrib/hma.py +50 -0
- backtrader/indicators/contrib/i4_drfv2.py +34 -0
- backtrader/indicators/contrib/i4_drfv3.py +38 -0
- backtrader/indicators/contrib/i_anch_mom_indicator.py +72 -0
- backtrader/indicators/contrib/i_de_marker_sign_indicator.py +64 -0
- backtrader/indicators/contrib/i_gap_indicator.py +45 -0
- backtrader/indicators/contrib/i_stoch_komposter_indicator.py +77 -0
- backtrader/indicators/contrib/i_trend_indicator.py +125 -0
- backtrader/indicators/contrib/iamma_indicator.py +39 -0
- backtrader/indicators/contrib/indexed_moving_average.py +33 -0
- backtrader/indicators/contrib/instantaneous_trend_filter_indicator.py +51 -0
- backtrader/indicators/contrib/inverse_reaction_indicator.py +41 -0
- backtrader/indicators/contrib/irsi_sign_indicator.py +95 -0
- backtrader/indicators/contrib/iwpr_sign_indicator.py +59 -0
- backtrader/indicators/contrib/j_brain_trend1_sig_indicator.py +233 -0
- backtrader/indicators/contrib/j_tpo_proxy.py +32 -0
- backtrader/indicators/contrib/jma_slope_indicator.py +73 -0
- backtrader/indicators/contrib/kalman_filter_indicator.py +119 -0
- backtrader/indicators/contrib/kalman_filter_line.py +127 -0
- backtrader/indicators/contrib/kama_indicator.py +150 -0
- backtrader/indicators/contrib/karacatica_indicator.py +99 -0
- backtrader/indicators/contrib/kdj_indicator.py +59 -0
- backtrader/indicators/contrib/kwan_ccc_indicator.py +195 -0
- backtrader/indicators/contrib/kwan_nrp_indicator.py +113 -0
- backtrader/indicators/contrib/kwan_rdp_indicator.py +192 -0
- backtrader/indicators/contrib/laguerre_adx_indicator.py +85 -0
- backtrader/indicators/contrib/laguerre_filter_indicator.py +66 -0
- backtrader/indicators/contrib/laguerre_plus_di_proxy.py +57 -0
- backtrader/indicators/contrib/laguerre_roc_indicator.py +81 -0
- backtrader/indicators/contrib/le_man_signal_indicator.py +63 -0
- backtrader/indicators/contrib/linear_reg_slope_v2_indicator.py +136 -0
- backtrader/indicators/contrib/loco_indicator.py +88 -0
- backtrader/indicators/contrib/lrma_indicator.py +185 -0
- backtrader/indicators/contrib/lsma_angle_indicator.py +106 -0
- backtrader/indicators/contrib/ma_rounding_channel_indicator.py +149 -0
- backtrader/indicators/contrib/macd2_indicator.py +61 -0
- backtrader/indicators/contrib/macd_candle_indicator.py +80 -0
- backtrader/indicators/contrib/malr_indicator.py +77 -0
- backtrader/indicators/contrib/momentum_candle_sign_indicator.py +51 -0
- backtrader/indicators/contrib/moving_average_fn_indicator.py +139 -0
- backtrader/indicators/contrib/mt5_stochastic_close_close.py +57 -0
- backtrader/indicators/contrib/muv_nor_diff_cloud_indicator.py +107 -0
- backtrader/indicators/contrib/non_lag_dot_indicator.py +124 -0
- backtrader/indicators/contrib/nrtr_extr_indicator.py +95 -0
- backtrader/indicators/contrib/nrtr_indicator.py +95 -0
- backtrader/indicators/contrib/p_channel_system.py +40 -0
- backtrader/indicators/contrib/percent_envelope.py +37 -0
- backtrader/indicators/contrib/percentage_crossover_channel.py +47 -0
- backtrader/indicators/contrib/pivot_zig_zag_proxy.py +47 -0
- backtrader/indicators/contrib/price_channel_stop_indicator.py +104 -0
- backtrader/indicators/contrib/price_extreme_channel.py +35 -0
- backtrader/indicators/contrib/qqe_cloud_indicator.py +129 -0
- backtrader/indicators/contrib/ravi_indicator.py +40 -0
- backtrader/indicators/contrib/raw_close_close_stochastic.py +74 -0
- backtrader/indicators/contrib/rd_trend_trigger_indicator.py +51 -0
- backtrader/indicators/contrib/renko_level.py +85 -0
- backtrader/indicators/contrib/renko_line_break.py +91 -0
- backtrader/indicators/contrib/rftl_indicator.py +41 -0
- backtrader/indicators/contrib/rkd_indicator.py +53 -0
- backtrader/indicators/contrib/roc2_vg_indicator.py +68 -0
- backtrader/indicators/contrib/rsi_histogram_indicator.py +43 -0
- backtrader/indicators/contrib/rsi_slowdown.py +57 -0
- backtrader/indicators/contrib/rsioma_v2.py +41 -0
- backtrader/indicators/contrib/rvi_histogram_indicator.py +107 -0
- backtrader/indicators/contrib/safe_adx.py +89 -0
- backtrader/indicators/contrib/shared_strategy_indicators.py +1651 -0
- backtrader/indicators/contrib/sidus_indicator.py +105 -0
- backtrader/indicators/contrib/silver_trend_indicator.py +79 -0
- backtrader/indicators/contrib/sliding_range_color.py +56 -0
- backtrader/indicators/contrib/slow_stoch.py +42 -0
- backtrader/indicators/contrib/smoothed_adx_indicator.py +86 -0
- backtrader/indicators/contrib/smoothed_rsi.py +31 -0
- backtrader/indicators/contrib/spearman_rank_correlation_histogram.py +60 -0
- backtrader/indicators/contrib/stalin_indicator.py +152 -0
- backtrader/indicators/contrib/starter_laguerre_filter.py +62 -0
- backtrader/indicators/contrib/step_manrtr_indicator.py +137 -0
- backtrader/indicators/contrib/stochastic_histogram_indicator.py +143 -0
- backtrader/indicators/contrib/t3_alarm_indicator.py +125 -0
- backtrader/indicators/contrib/t3_average.py +76 -0
- backtrader/indicators/contrib/t3_indicator.py +40 -0
- backtrader/indicators/contrib/the20s_v020_signal.py +93 -0
- backtrader/indicators/contrib/three_candles_indicator.py +70 -0
- backtrader/indicators/contrib/three_line_break_indicator.py +64 -0
- backtrader/indicators/contrib/time_line.py +57 -0
- backtrader/indicators/contrib/trading_channel_index_proxy.py +48 -0
- backtrader/indicators/contrib/trend_arrows_indicator.py +109 -0
- backtrader/indicators/contrib/trend_continuation_indicator.py +127 -0
- backtrader/indicators/contrib/trend_intensity_index_proxy.py +51 -0
- backtrader/indicators/contrib/trend_manager_indicator.py +39 -0
- backtrader/indicators/contrib/tri_x_candle_indicator.py +51 -0
- backtrader/indicators/contrib/trigger_line.py +66 -0
- backtrader/indicators/contrib/triple_ema_rate.py +34 -0
- backtrader/indicators/contrib/trvi_indicator.py +194 -0
- backtrader/indicators/contrib/two_pb_ideal_xosma_indicator.py +127 -0
- backtrader/indicators/contrib/ultra_absolutely_no_lag_lwma_color.py +92 -0
- backtrader/indicators/contrib/ultra_wpr_indicator.py +173 -0
- backtrader/indicators/contrib/up_down_candle_strength.py +68 -0
- backtrader/indicators/contrib/vinin_i_trend_indicator.py +139 -0
- backtrader/indicators/contrib/volume_weighted_ma_indicator.py +78 -0
- backtrader/indicators/contrib/volume_weighted_ma_st_dev_indicator.py +111 -0
- backtrader/indicators/contrib/vwap_close_indicator.py +65 -0
- backtrader/indicators/contrib/vwma_candle.py +57 -0
- backtrader/indicators/contrib/vwma_digit_system.py +70 -0
- backtrader/indicators/contrib/wami.py +43 -0
- backtrader/indicators/contrib/wprsi_signal_indicator.py +105 -0
- backtrader/indicators/contrib/x_de_marker_histogram_vol_direct_indicator.py +145 -0
- backtrader/indicators/contrib/x_fisher_indicator.py +64 -0
- backtrader/indicators/contrib/xcci_histogram_vol_direct_indicator.py +56 -0
- backtrader/indicators/contrib/xcci_histogram_vol_indicator.py +85 -0
- backtrader/indicators/contrib/xma_ichimoku.py +163 -0
- backtrader/indicators/contrib/xma_ishimoku_channel_indicator.py +65 -0
- backtrader/indicators/contrib/xma_ishimoku_line.py +68 -0
- backtrader/indicators/contrib/xma_range_bands_indicator.py +107 -0
- backtrader/indicators/contrib/xmacd_indicator.py +70 -0
- backtrader/indicators/contrib/xrsi_de_marker_histogram.py +67 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_direct_indicator.py +52 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_indicator.py +81 -0
- backtrader/indicators/contrib/xrvi_indicator.py +130 -0
- backtrader/indicators/contrib/zero_lag_macd.py +36 -0
- backtrader/indicators/contrib/zig_zag_recent_pivot_signal.py +90 -0
- backtrader/indicators/contrib/zpf_indicator.py +115 -0
- backtrader/indicators/crossover.py +337 -0
- backtrader/indicators/dema.py +175 -0
- backtrader/indicators/demarker.py +270 -0
- backtrader/indicators/deviation.py +284 -0
- backtrader/indicators/directionalmove.py +1071 -0
- backtrader/indicators/dma.py +112 -0
- backtrader/indicators/dpo.py +96 -0
- backtrader/indicators/dv2.py +56 -0
- backtrader/indicators/ema.py +145 -0
- backtrader/indicators/envelope.py +475 -0
- backtrader/indicators/hadelta.py +198 -0
- backtrader/indicators/heikinashi.py +153 -0
- backtrader/indicators/hma.py +153 -0
- backtrader/indicators/hurst.py +151 -0
- backtrader/indicators/ichimoku.py +267 -0
- backtrader/indicators/kama.py +181 -0
- backtrader/indicators/kst.py +159 -0
- backtrader/indicators/lrsi.py +125 -0
- backtrader/indicators/mabase.py +147 -0
- backtrader/indicators/macd.py +322 -0
- backtrader/indicators/momentum.py +267 -0
- backtrader/indicators/moneyflow.py +237 -0
- backtrader/indicators/mt5atr.py +124 -0
- backtrader/indicators/myind.py +179 -0
- backtrader/indicators/obv.py +94 -0
- backtrader/indicators/ols.py +265 -0
- backtrader/indicators/oscillator.py +161 -0
- backtrader/indicators/percentchange.py +83 -0
- backtrader/indicators/percentrank.py +46 -0
- backtrader/indicators/pivotpoint.py +469 -0
- backtrader/indicators/prettygoodoscillator.py +113 -0
- backtrader/indicators/priceops_ext.py +123 -0
- backtrader/indicators/priceoscillator.py +262 -0
- backtrader/indicators/psar.py +212 -0
- backtrader/indicators/rmi.py +69 -0
- backtrader/indicators/rsi.py +440 -0
- backtrader/indicators/sma.py +141 -0
- backtrader/indicators/smma.py +116 -0
- backtrader/indicators/spread.py +54 -0
- backtrader/indicators/stochastic.py +263 -0
- backtrader/indicators/supertrend.py +436 -0
- backtrader/indicators/trend_ext.py +105 -0
- backtrader/indicators/trix.py +202 -0
- backtrader/indicators/tsi.py +155 -0
- backtrader/indicators/ultimateoscillator.py +158 -0
- backtrader/indicators/vortex.py +62 -0
- backtrader/indicators/williams.py +194 -0
- backtrader/indicators/wma.py +103 -0
- backtrader/indicators/zlema.py +135 -0
- backtrader/indicators/zlind.py +104 -0
- backtrader/linebuffer.py +3155 -0
- backtrader/lineiterator.py +2911 -0
- backtrader/lineroot.py +1106 -0
- backtrader/lineseries.py +2559 -0
- backtrader/live_trading/__init__.py +31 -0
- backtrader/live_trading/interface.py +404 -0
- backtrader/mathsupport.py +94 -0
- backtrader/metabase.py +1804 -0
- backtrader/mixins/__init__.py +21 -0
- backtrader/mixins/singleton.py +118 -0
- backtrader/observer.py +106 -0
- backtrader/observers/__init__.py +45 -0
- backtrader/observers/benchmark.py +126 -0
- backtrader/observers/broker.py +184 -0
- backtrader/observers/buysell.py +144 -0
- backtrader/observers/drawdown.py +161 -0
- backtrader/observers/logreturns.py +113 -0
- backtrader/observers/timereturn.py +86 -0
- backtrader/observers/trade_logger.py +2972 -0
- backtrader/observers/tradelogger.py +6 -0
- backtrader/observers/trades.py +258 -0
- backtrader/order.py +1114 -0
- backtrader/parameters.py +2345 -0
- backtrader/plot/__init__.py +54 -0
- backtrader/plot/finance.py +1022 -0
- backtrader/plot/formatters.py +200 -0
- backtrader/plot/locator.py +353 -0
- backtrader/plot/multicursor.py +495 -0
- backtrader/plot/plot.py +2500 -0
- backtrader/plot/plot_plotly.py +1351 -0
- backtrader/plot/scheme.py +253 -0
- backtrader/plot/utils.py +104 -0
- backtrader/position.py +290 -0
- backtrader/position_modes.py +132 -0
- backtrader/profiles.py +254 -0
- backtrader/reports/__init__.py +39 -0
- backtrader/reports/charts.py +371 -0
- backtrader/reports/performance.py +620 -0
- backtrader/reports/reporter.py +660 -0
- backtrader/resamplerfilter.py +1001 -0
- backtrader/signal.py +118 -0
- backtrader/signals/__init__.py +17 -0
- backtrader/sizer.py +114 -0
- backtrader/sizers/__init__.py +26 -0
- backtrader/sizers/fixedsize.py +161 -0
- backtrader/sizers/percents_sizer.py +119 -0
- backtrader/store.py +221 -0
- backtrader/stores/__init__.py +33 -0
- backtrader/stores/btapistore.py +15506 -0
- backtrader/stores/livestore.py +137 -0
- backtrader/stores/vchartfile.py +96 -0
- backtrader/strategy.py +3655 -0
- backtrader/talib.py +280 -0
- backtrader/test_helpers.py +96 -0
- backtrader/timer.py +358 -0
- backtrader/trade.py +442 -0
- backtrader/tradingcal.py +361 -0
- backtrader/utils/__init__.py +68 -0
- backtrader/utils/autodict.py +251 -0
- backtrader/utils/date.py +71 -0
- backtrader/utils/dateintern.py +509 -0
- backtrader/utils/flushfile.py +94 -0
- backtrader/utils/fractal.py +101 -0
- backtrader/utils/get_metrics.py +101 -0
- backtrader/utils/load_data.py +209 -0
- backtrader/utils/log_message.py +998 -0
- backtrader/utils/ordereddefaultdict.py +75 -0
- backtrader/utils/py3.py +296 -0
- backtrader/version.py +21 -0
- backtrader/writer.py +372 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
"""Cerebro configuration/registration mixin (iteration 28 split).
|
|
2
|
+
|
|
3
|
+
Moved verbatim from ``backtrader/cerebro.py``: data feed registration,
|
|
4
|
+
timers, timezone/calendar, signals, stores, writers, sizers, indicators,
|
|
5
|
+
analyzers, observers, strategy registration and timer dispatch.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import collections
|
|
9
|
+
import datetime
|
|
10
|
+
import itertools
|
|
11
|
+
|
|
12
|
+
from .. import feeds
|
|
13
|
+
from ..timer import Timer
|
|
14
|
+
from ..tradingcal import PandasMarketCalendar, TradingCalendarBase
|
|
15
|
+
from ..utils.log_message import get_logger
|
|
16
|
+
from ..utils.py3 import map, string_types, zip # noqa: F401
|
|
17
|
+
|
|
18
|
+
logger = get_logger(__name__)
|
|
19
|
+
|
|
20
|
+
collectionsAbc = collections.abc
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RegistryMixin:
|
|
24
|
+
"""Configuration/registration half of Cerebro (see module docstring)."""
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def iterize(iterable):
|
|
28
|
+
"""Convert each element in iterable to be iterable itself.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
iterable: Input iterable whose elements may not be iterable.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
list: New list where each element is guaranteed to be iterable.
|
|
35
|
+
"""
|
|
36
|
+
niterable = []
|
|
37
|
+
for elem in iterable:
|
|
38
|
+
if isinstance(elem, string_types) or not isinstance(elem, collectionsAbc.Iterable):
|
|
39
|
+
elem = (elem,)
|
|
40
|
+
|
|
41
|
+
niterable.append(elem)
|
|
42
|
+
|
|
43
|
+
return niterable
|
|
44
|
+
|
|
45
|
+
def set_fund_history(self, fund):
|
|
46
|
+
"""
|
|
47
|
+
Add a history of orders to be directly executed in the broker for
|
|
48
|
+
performance evaluation
|
|
49
|
+
|
|
50
|
+
- ``fund``: is an iterable (ex: list, tuple, iterator, generator)
|
|
51
|
+
in which each element will be also iterable (with length) with
|
|
52
|
+
the following sub-elements (two formats are possible)
|
|
53
|
+
|
|
54
|
+
``[datetime, share_value, net asset value]``
|
|
55
|
+
|
|
56
|
+
**Note**: it must be sorted (or produce sorted elements) by
|
|
57
|
+
datetime ascending
|
|
58
|
+
|
|
59
|
+
where:
|
|
60
|
+
|
|
61
|
+
- ``datetime`` is a python ``date/datetime`` instance or a string
|
|
62
|
+
with format YYYY-MM-DD[THH:MM:SS[.us]] where the elements in
|
|
63
|
+
brackets are optional
|
|
64
|
+
- ``share_value`` is a float/integer
|
|
65
|
+
- ``net_asset_value`` is a float/integer
|
|
66
|
+
"""
|
|
67
|
+
self._fhistory = fund
|
|
68
|
+
|
|
69
|
+
def add_order_history(self, orders, notify=True):
|
|
70
|
+
"""
|
|
71
|
+
Add a history of orders to be directly executed in the broker for
|
|
72
|
+
performance evaluation
|
|
73
|
+
|
|
74
|
+
- ``orders``: is an iterable (ex: list, tuple, iterator, generator)
|
|
75
|
+
in which each element will be also iterable (with length) with
|
|
76
|
+
the following sub-elements (two formats are possible)
|
|
77
|
+
|
|
78
|
+
``[datetime, size, price]`` or ``[datetime, size, price, data]``
|
|
79
|
+
|
|
80
|
+
**Note**: it must be sorted (or produce sorted elements) by
|
|
81
|
+
datetime ascending
|
|
82
|
+
|
|
83
|
+
where:
|
|
84
|
+
|
|
85
|
+
- ``datetime`` is a python ``date/datetime`` instance or a string
|
|
86
|
+
with format YYYY-MM-DD[THH:MM:SS[.us]] where the elements in
|
|
87
|
+
brackets are optional
|
|
88
|
+
- ``size`` is an integer (positive to *buy*, negative to *sell*)
|
|
89
|
+
- ``price`` is a float/integer
|
|
90
|
+
- ``data`` if present can take any of the following values
|
|
91
|
+
|
|
92
|
+
- *None* - The 1st data feed will be used as target
|
|
93
|
+
- *integer* - The data with that index (insertion order in
|
|
94
|
+
**Cerebro**) will be used
|
|
95
|
+
- *string* - a data with that name, assigned for example with
|
|
96
|
+
``cerebro.addata(data, name=value)``, will be the target
|
|
97
|
+
|
|
98
|
+
- ``notify`` (default: *True*)
|
|
99
|
+
|
|
100
|
+
If ``True``, the first strategy inserted in the system will be
|
|
101
|
+
notified of the artificial orders created following the information
|
|
102
|
+
from each order in ``orders``
|
|
103
|
+
|
|
104
|
+
**Note**: Implicit in the description is the need to add a data feed
|
|
105
|
+
which is the target of the orders.This is, for example, needed by
|
|
106
|
+
analyzers which track, for example, the returns
|
|
107
|
+
"""
|
|
108
|
+
self._ohistory.append((orders, notify))
|
|
109
|
+
|
|
110
|
+
def notify_timer(self, timer, when, *args, **kwargs):
|
|
111
|
+
"""Receives a timer notification where ``timer`` is the timer that was
|
|
112
|
+
returned by ``add_timer``, and ``when`` is the calling time. ``args``
|
|
113
|
+
and ``kwargs`` are any additional arguments passed to ``add_timer``
|
|
114
|
+
|
|
115
|
+
The actual `when` time can be later, but the system may have not been
|
|
116
|
+
able to call the timer before. This value is the timer value and no the
|
|
117
|
+
system time.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def _add_timer(
|
|
121
|
+
self,
|
|
122
|
+
owner,
|
|
123
|
+
when,
|
|
124
|
+
offset=datetime.timedelta(),
|
|
125
|
+
repeat=datetime.timedelta(),
|
|
126
|
+
weekdays=None,
|
|
127
|
+
weekcarry=False,
|
|
128
|
+
monthdays=None,
|
|
129
|
+
monthcarry=True,
|
|
130
|
+
allow=None,
|
|
131
|
+
tzdata=None,
|
|
132
|
+
strats=False,
|
|
133
|
+
cheat=False,
|
|
134
|
+
*args,
|
|
135
|
+
**kwargs,
|
|
136
|
+
):
|
|
137
|
+
"""Internal method to really create the timer (not started yet) which
|
|
138
|
+
can be called by cerebro instances or other objects which can access
|
|
139
|
+
cerebro"""
|
|
140
|
+
|
|
141
|
+
# Normalize mutable-default placeholders (B006): Timer treats None as
|
|
142
|
+
# "all days", identical to the previous empty-list default.
|
|
143
|
+
weekdays = [] if weekdays is None else weekdays
|
|
144
|
+
monthdays = [] if monthdays is None else monthdays
|
|
145
|
+
timer = Timer(
|
|
146
|
+
tid=len(self._pretimers),
|
|
147
|
+
owner=owner,
|
|
148
|
+
strats=strats,
|
|
149
|
+
when=when,
|
|
150
|
+
offset=offset,
|
|
151
|
+
repeat=repeat,
|
|
152
|
+
weekdays=weekdays,
|
|
153
|
+
weekcarry=weekcarry,
|
|
154
|
+
monthdays=monthdays,
|
|
155
|
+
monthcarry=monthcarry,
|
|
156
|
+
allow=allow,
|
|
157
|
+
tzdata=tzdata,
|
|
158
|
+
cheat=cheat,
|
|
159
|
+
*args,
|
|
160
|
+
**kwargs,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
self._pretimers.append(timer)
|
|
164
|
+
return timer
|
|
165
|
+
|
|
166
|
+
def add_timer(
|
|
167
|
+
self,
|
|
168
|
+
when,
|
|
169
|
+
offset=datetime.timedelta(),
|
|
170
|
+
repeat=datetime.timedelta(),
|
|
171
|
+
weekdays=None,
|
|
172
|
+
weekcarry=False,
|
|
173
|
+
monthdays=None,
|
|
174
|
+
monthcarry=True,
|
|
175
|
+
allow=None,
|
|
176
|
+
tzdata=None,
|
|
177
|
+
strats=False,
|
|
178
|
+
cheat=False,
|
|
179
|
+
*args,
|
|
180
|
+
**kwargs,
|
|
181
|
+
):
|
|
182
|
+
"""
|
|
183
|
+
Schedules a timer to invoke ``notify_timer``
|
|
184
|
+
|
|
185
|
+
Arguments:
|
|
186
|
+
|
|
187
|
+
- ``when``: can be
|
|
188
|
+
|
|
189
|
+
- ``datetime.time`` instance (see below ``tzdata``)
|
|
190
|
+
- ``bt.timer.SESSION_START`` to reference a session start
|
|
191
|
+
- ``bt.timer.SESSION_END`` to reference a session end
|
|
192
|
+
|
|
193
|
+
- ``offset`` which must be a ``datetime.timedelta`` instance
|
|
194
|
+
|
|
195
|
+
Used to offset the value ``when``. It has a meaningful use in
|
|
196
|
+
combination with ``SESSION_START`` and ``SESSION_END``, to indicate
|
|
197
|
+
things like a timer being called ``15 minutes`` after the session
|
|
198
|
+
starts.
|
|
199
|
+
|
|
200
|
+
- ``repeat`` which must be a ``datetime.timedelta`` instance
|
|
201
|
+
|
|
202
|
+
Indicates if after a first call, further calls will be scheduled
|
|
203
|
+
within the same session at the scheduled `repeat` delta
|
|
204
|
+
|
|
205
|
+
Once the timer goes over the end of the session, it is reset to the
|
|
206
|
+
original value for ``when``
|
|
207
|
+
|
|
208
|
+
- ``weekdays``: a **sorted** iterable with integers indicating on
|
|
209
|
+
which days (iso codes, Monday is 1, Sunday is 7) the timers can
|
|
210
|
+
be actually invoked
|
|
211
|
+
|
|
212
|
+
If not specified, the timer will be active on all days
|
|
213
|
+
|
|
214
|
+
- ``weekcarry`` (default: ``False``). If ``True`` and the weekday was
|
|
215
|
+
not seen (ex: trading holiday), the timer will be executed on the
|
|
216
|
+
next day (even if in a new week)
|
|
217
|
+
|
|
218
|
+
- ``monthdays``: a **sorted** iterable with integers indicating on
|
|
219
|
+
which days of the month a timer has to be executed. For example,
|
|
220
|
+
always on day *15* of the month
|
|
221
|
+
|
|
222
|
+
If not specified, the timer will be active on all days
|
|
223
|
+
|
|
224
|
+
- ``monthcarry`` (default: ``True``). If the day was not seen
|
|
225
|
+
(weekend, trading holiday), the timer will be executed on the next
|
|
226
|
+
available day.
|
|
227
|
+
|
|
228
|
+
- ``allow`` (default: ``None``). A callback which receives a
|
|
229
|
+
`datetime.date`` instance and returns ``True`` if the date is
|
|
230
|
+
allowed for timers or else returns ``False``
|
|
231
|
+
|
|
232
|
+
- ``tzdata`` which can be either ``None`` (default), a ``pytz``
|
|
233
|
+
instance or a ``data feed`` instance.
|
|
234
|
+
|
|
235
|
+
``None``: ``when`` is interpreted at face value (which translates
|
|
236
|
+
to handling it as if it is UTC even if it's not)
|
|
237
|
+
|
|
238
|
+
``pytz`` instance: ``when`` will be interpreted as being specified
|
|
239
|
+
in the local time specified by the timezone instance.
|
|
240
|
+
|
|
241
|
+
``data feed`` instance: ``when`` will be interpreted as being
|
|
242
|
+
specified in the local time specified by the ``tz`` parameter of
|
|
243
|
+
the data feed instance.
|
|
244
|
+
|
|
245
|
+
**Note**: If ``when`` is either ``SESSION_START`` or
|
|
246
|
+
``SESSION_END`` and ``tzdata`` is ``None``, the first *data feed*
|
|
247
|
+
in the system (aka ``self.data0``) will be used as the reference
|
|
248
|
+
to find out the session times.
|
|
249
|
+
|
|
250
|
+
- ``strats`` (default: ``False``) call also the ``notify_timer`` of strategies
|
|
251
|
+
|
|
252
|
+
- ``cheat`` (default ``False``) if ``True`` the timer will be called
|
|
253
|
+
before the broker has a chance to evaluate the orders. This opens
|
|
254
|
+
the chance to issue orders based on opening price, for example, right
|
|
255
|
+
before the session starts
|
|
256
|
+
- ``*args``: any extra args will be passed to ``notify_timer``
|
|
257
|
+
|
|
258
|
+
- ``**kwargs``: any extra kwargs will be passed to ``notify_timer``
|
|
259
|
+
|
|
260
|
+
Return Value:
|
|
261
|
+
|
|
262
|
+
- The created timer
|
|
263
|
+
|
|
264
|
+
"""
|
|
265
|
+
# NOTE: *args (extra notify_timer args) are forwarded positionally after
|
|
266
|
+
# the named timer kwargs; _add_timer collects them into its own *args.
|
|
267
|
+
return self._add_timer(
|
|
268
|
+
owner=self,
|
|
269
|
+
when=when,
|
|
270
|
+
offset=offset,
|
|
271
|
+
repeat=repeat,
|
|
272
|
+
weekdays=weekdays,
|
|
273
|
+
weekcarry=weekcarry,
|
|
274
|
+
monthdays=monthdays,
|
|
275
|
+
monthcarry=monthcarry,
|
|
276
|
+
allow=allow,
|
|
277
|
+
tzdata=tzdata,
|
|
278
|
+
strats=strats,
|
|
279
|
+
cheat=cheat,
|
|
280
|
+
*args,
|
|
281
|
+
**kwargs,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def addtz(self, tz):
|
|
285
|
+
"""This can also be done with the parameter ``tz``
|
|
286
|
+
|
|
287
|
+
Adds a global timezone for strategies. The argument ``tz`` can be
|
|
288
|
+
|
|
289
|
+
- ``None``: in this case the datetime displayed by strategies will be
|
|
290
|
+
in UTC, which has always been the standard behavior
|
|
291
|
+
|
|
292
|
+
- ``pytz`` instance. It will be used as such to convert UTC times to
|
|
293
|
+
the chosen timezone
|
|
294
|
+
|
|
295
|
+
- ``string``. Instantiating a ``pytz`` instance will be attempted.
|
|
296
|
+
|
|
297
|
+
- ``integer``. Use, for the strategy, the same timezone as the
|
|
298
|
+
corresponding ``data`` in the ``self.datas`` iterable (``0`` would
|
|
299
|
+
use the timezone from ``data0``)
|
|
300
|
+
|
|
301
|
+
"""
|
|
302
|
+
self.p.tz = tz
|
|
303
|
+
|
|
304
|
+
def addcalendar(self, cal):
|
|
305
|
+
"""Adds a global trading calendar to the system. Individual data feeds
|
|
306
|
+
may have separate calendars which override the global one
|
|
307
|
+
|
|
308
|
+
``cal`` can be an instance of ``TradingCalendar`` a string or an
|
|
309
|
+
instance of ``pandas_market_calendars``. A string will be
|
|
310
|
+
instantiated as a ``PandasMarketCalendar`` (which needs the module
|
|
311
|
+
``pandas_market_calendar`` installed in the system).
|
|
312
|
+
|
|
313
|
+
If a subclass of `TradingCalendarBase` is passed (not an instance), it
|
|
314
|
+
will be instantiated
|
|
315
|
+
"""
|
|
316
|
+
# Handle string or pandas calendar with valid_days attribute
|
|
317
|
+
if isinstance(cal, string_types) or hasattr(cal, "valid_days"):
|
|
318
|
+
cal = PandasMarketCalendar(calendar=cal)
|
|
319
|
+
# Handle TradingCalendarBase subclass or instance
|
|
320
|
+
else:
|
|
321
|
+
try:
|
|
322
|
+
if issubclass(cal, TradingCalendarBase):
|
|
323
|
+
cal = cal()
|
|
324
|
+
except TypeError: # already an instance
|
|
325
|
+
logger.debug("registry:324 ignored TypeError")
|
|
326
|
+
self._tradingcal = cal
|
|
327
|
+
|
|
328
|
+
def add_signal(self, sigtype, sigcls, *sigargs, **sigkwargs):
|
|
329
|
+
"""Add a signal to be used with SignalStrategy."""
|
|
330
|
+
self.signals.append((sigtype, sigcls, sigargs, sigkwargs))
|
|
331
|
+
|
|
332
|
+
def signal_strategy(self, stratcls, *args, **kwargs):
|
|
333
|
+
"""Set a SignalStrategy subclass to receive signals."""
|
|
334
|
+
self._signal_strat = (stratcls, args, kwargs)
|
|
335
|
+
|
|
336
|
+
def signal_concurrent(self, onoff):
|
|
337
|
+
"""Allow concurrent orders when signals are pending."""
|
|
338
|
+
self._signal_concurrent = onoff
|
|
339
|
+
|
|
340
|
+
def signal_accumulate(self, onoff):
|
|
341
|
+
"""If signals are added to the system and the `accumulate` value is
|
|
342
|
+
set to True, entering the market when already in the market, will be
|
|
343
|
+
allowed to increase a position"""
|
|
344
|
+
self._signal_accumulate = onoff
|
|
345
|
+
|
|
346
|
+
def addstore(self, store):
|
|
347
|
+
"""Add a Store instance to the system."""
|
|
348
|
+
if store not in self.stores:
|
|
349
|
+
self.stores.append(store)
|
|
350
|
+
|
|
351
|
+
def _maybe_add_store(self, candidate):
|
|
352
|
+
"""Register a store exposed by a broker or data feed."""
|
|
353
|
+
store = getattr(candidate, "store", None) or getattr(candidate, "_store", None)
|
|
354
|
+
if store is not None:
|
|
355
|
+
self.addstore(store)
|
|
356
|
+
|
|
357
|
+
def addwriter(self, wrtcls, *args, **kwargs):
|
|
358
|
+
"""Adds an ``Writer`` class to the mix. Instantiation will be done at
|
|
359
|
+
``run`` time in cerebro"""
|
|
360
|
+
self.writers.append((wrtcls, args, kwargs))
|
|
361
|
+
|
|
362
|
+
def addsizer(self, sizercls, *args, **kwargs):
|
|
363
|
+
"""Adds a ``Sizer`` class (and args) which is the default sizer for any
|
|
364
|
+
strategy added to cerebro
|
|
365
|
+
"""
|
|
366
|
+
self.sizers[None] = (sizercls, args, kwargs)
|
|
367
|
+
|
|
368
|
+
def addsizer_byidx(self, idx, sizercls, *args, **kwargs):
|
|
369
|
+
"""Adds a ``Sizer`` class by idx. This idx is a reference compatible to
|
|
370
|
+
the one returned by ``addstrategy``. Only the strategy referenced by
|
|
371
|
+
``idx`` will receive this size
|
|
372
|
+
"""
|
|
373
|
+
self.sizers[idx] = (sizercls, args, kwargs)
|
|
374
|
+
|
|
375
|
+
def addindicator(self, indcls, *args, **kwargs):
|
|
376
|
+
"""Add an Indicator class to be instantiated at run time."""
|
|
377
|
+
self.indicators.append((indcls, args, kwargs))
|
|
378
|
+
|
|
379
|
+
def addanalyzer(self, ancls: type, *args, **kwargs) -> None:
|
|
380
|
+
"""Add an Analyzer class to be instantiated at run time."""
|
|
381
|
+
self.analyzers.append((ancls, args, kwargs))
|
|
382
|
+
|
|
383
|
+
def addobserver(self, obscls: type, *args, **kwargs) -> None:
|
|
384
|
+
"""
|
|
385
|
+
Adds an ``Observer`` class to the mix. Instantiation will be done at
|
|
386
|
+
``run`` time
|
|
387
|
+
"""
|
|
388
|
+
self.observers.append((False, obscls, args, kwargs))
|
|
389
|
+
|
|
390
|
+
def addobservermulti(self, obscls, *args, **kwargs):
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
It will be added once per "data" in the system. A use case is a
|
|
394
|
+
buy/sell observer that observes individual data.
|
|
395
|
+
|
|
396
|
+
A counter-example is the CashValue, which observes system-wide values
|
|
397
|
+
"""
|
|
398
|
+
self.observers.append((True, obscls, args, kwargs))
|
|
399
|
+
|
|
400
|
+
def adddata(self, data, name: str = None):
|
|
401
|
+
"""
|
|
402
|
+
Adds a ``Data Feed`` instance to the mix.
|
|
403
|
+
|
|
404
|
+
If ``name`` is not None, it will be put into ``data._name`` which is
|
|
405
|
+
meant for decoration/plotting purposes.
|
|
406
|
+
"""
|
|
407
|
+
# Set data name if provided
|
|
408
|
+
if name is not None:
|
|
409
|
+
data._name = name
|
|
410
|
+
data.name = name
|
|
411
|
+
# Assign unique ID to each data feed
|
|
412
|
+
data._id = next(self._dataid)
|
|
413
|
+
# Set data's environment to this cerebro
|
|
414
|
+
data.setenvironment(self)
|
|
415
|
+
# Add to data list
|
|
416
|
+
self.datas.append(data)
|
|
417
|
+
# Store in name lookup dictionary
|
|
418
|
+
self.datasbyname[data._name] = data
|
|
419
|
+
# Get feed from data
|
|
420
|
+
feed = data.getfeed()
|
|
421
|
+
# Add feed if not already present
|
|
422
|
+
if feed and feed not in self.feeds:
|
|
423
|
+
self.feeds.append(feed)
|
|
424
|
+
self._maybe_add_store(data)
|
|
425
|
+
# Set live mode if data is live
|
|
426
|
+
if data.islive():
|
|
427
|
+
self._dolive = True
|
|
428
|
+
|
|
429
|
+
return data
|
|
430
|
+
|
|
431
|
+
def chaindata(self, *args, **kwargs):
|
|
432
|
+
"""
|
|
433
|
+
Chains several data feeds into one
|
|
434
|
+
|
|
435
|
+
If ``name`` is passed as named argument and not `None`, it will be put
|
|
436
|
+
into ``data._name`` which is meant for decoration/plotting purposes.
|
|
437
|
+
|
|
438
|
+
If `None`, then the name of the first data will be used
|
|
439
|
+
"""
|
|
440
|
+
dname = kwargs.pop("name", None)
|
|
441
|
+
if dname is None:
|
|
442
|
+
dname = args[0]._dataname
|
|
443
|
+
d = feeds.Chainer(dataname=dname, *args)
|
|
444
|
+
self.adddata(d, name=dname)
|
|
445
|
+
|
|
446
|
+
return d
|
|
447
|
+
|
|
448
|
+
def rolloverdata(self, *args, **kwargs):
|
|
449
|
+
"""Chains several data feeds into one
|
|
450
|
+
|
|
451
|
+
If ``name`` is passed as named argument and is not None, it will be put
|
|
452
|
+
into ``data._name`` which is meant for decoration/plotting purposes.
|
|
453
|
+
|
|
454
|
+
If `None`, then the name of the first data will be used
|
|
455
|
+
|
|
456
|
+
Any other kwargs will be passed to the RollOver class
|
|
457
|
+
|
|
458
|
+
"""
|
|
459
|
+
dname = kwargs.pop("name", None)
|
|
460
|
+
if dname is None:
|
|
461
|
+
dname = args[0]._dataname
|
|
462
|
+
d = feeds.RollOver(dataname=dname, *args, **kwargs)
|
|
463
|
+
self.adddata(d, name=dname)
|
|
464
|
+
|
|
465
|
+
return d
|
|
466
|
+
|
|
467
|
+
def replaydata(self, dataname, name=None, **kwargs):
|
|
468
|
+
"""
|
|
469
|
+
Adds a ``Data Feed`` to be replayed by the system
|
|
470
|
+
|
|
471
|
+
If ``name`` is not None, it will be put into ``data._name`` which is
|
|
472
|
+
meant for decoration/plotting purposes.
|
|
473
|
+
|
|
474
|
+
Any other kwargs like ``timeframe``, ``compression``, ``todate`` which
|
|
475
|
+
are supported by the replay filter will be passed transparently
|
|
476
|
+
"""
|
|
477
|
+
if any(dataname is x for x in self.datas):
|
|
478
|
+
dataname = dataname.clone()
|
|
479
|
+
|
|
480
|
+
dataname.replay(**kwargs)
|
|
481
|
+
self.adddata(dataname, name=name)
|
|
482
|
+
self._doreplay = True
|
|
483
|
+
|
|
484
|
+
return dataname
|
|
485
|
+
|
|
486
|
+
def resampledata(self, dataname, name=None, **kwargs):
|
|
487
|
+
"""
|
|
488
|
+
Adds a ``Data Feed`` to be resample by the system
|
|
489
|
+
|
|
490
|
+
If ``name`` is not None, it will be put into ``data._name`` which is
|
|
491
|
+
meant for decoration/plotting purposes.
|
|
492
|
+
|
|
493
|
+
Any other kwargs like ``timeframe``, ``compression``, ``todate`` which
|
|
494
|
+
are supported by the resample filter will be passed transparently
|
|
495
|
+
"""
|
|
496
|
+
if any(dataname is x for x in self.datas):
|
|
497
|
+
dataname = dataname.clone()
|
|
498
|
+
|
|
499
|
+
dataname.resample(**kwargs)
|
|
500
|
+
self.adddata(dataname, name=name)
|
|
501
|
+
self._doreplay = True
|
|
502
|
+
|
|
503
|
+
return dataname
|
|
504
|
+
|
|
505
|
+
def optcallback(self, cb):
|
|
506
|
+
"""
|
|
507
|
+
Adds a *callback* to the list of callbacks that will be called with the
|
|
508
|
+
optimizations when each of the strategies has been run
|
|
509
|
+
|
|
510
|
+
The signature: cb(strategy)
|
|
511
|
+
"""
|
|
512
|
+
self.optcbs.append(cb)
|
|
513
|
+
|
|
514
|
+
def optstrategy(self, strategy, *args, **kwargs):
|
|
515
|
+
"""
|
|
516
|
+
Adds a ``Strategy`` class to the mix for optimization. Instantiation
|
|
517
|
+
will happen during ``run`` time.
|
|
518
|
+
|
|
519
|
+
args and kwargs MUST BE iterables that hold the values to check.
|
|
520
|
+
|
|
521
|
+
Example: if a Strategy accepts a parameter `period`, for optimization
|
|
522
|
+
purposes, the call to ``optstrategy`` looks like:
|
|
523
|
+
|
|
524
|
+
- cerebro.optstrategy(MyStrategy, period=(15, 25))
|
|
525
|
+
|
|
526
|
+
This will execute an optimization for values 15 and 25. Whereas
|
|
527
|
+
|
|
528
|
+
- cerebro.optstrategy(MyStrategy, period=range(15, 25))
|
|
529
|
+
|
|
530
|
+
will execute MyStrategy with ``period`` values 15 -> 25 (25 not
|
|
531
|
+
included, because ranges are semi-open in Python)
|
|
532
|
+
|
|
533
|
+
If a parameter is passed but shall not be optimized, the call looks
|
|
534
|
+
like:
|
|
535
|
+
|
|
536
|
+
- cerebro.optstrategy(MyStrategy, period=(15,))
|
|
537
|
+
|
|
538
|
+
Notice that `period` is still passed as an iterable ... of just one element
|
|
539
|
+
|
|
540
|
+
``backtrader`` will anyhow try to identify situations like:
|
|
541
|
+
|
|
542
|
+
- cerebro.optstrategy(MyStrategy, period=15)
|
|
543
|
+
|
|
544
|
+
and will create an internal pseudo-iterable if possible
|
|
545
|
+
"""
|
|
546
|
+
self._dooptimize = True
|
|
547
|
+
args = self.iterize(args)
|
|
548
|
+
optargs = itertools.product(*args)
|
|
549
|
+
|
|
550
|
+
optkeys = list(kwargs)
|
|
551
|
+
|
|
552
|
+
vals = self.iterize(kwargs.values())
|
|
553
|
+
optvals = itertools.product(*vals)
|
|
554
|
+
|
|
555
|
+
okwargs1 = map(zip, itertools.repeat(optkeys), optvals)
|
|
556
|
+
|
|
557
|
+
optkwargs = map(dict, okwargs1)
|
|
558
|
+
|
|
559
|
+
it = itertools.product([strategy], optargs, optkwargs)
|
|
560
|
+
self.strats.append(it)
|
|
561
|
+
|
|
562
|
+
def addstrategy(self, strategy: type, *args, **kwargs) -> int:
|
|
563
|
+
"""
|
|
564
|
+
Adds a ``Strategy`` class to the mix for a single pass run.
|
|
565
|
+
Instantiation will happen during ``run`` time.
|
|
566
|
+
|
|
567
|
+
Args and kwargs will be passed to the strategy as they are during
|
|
568
|
+
instantiation.
|
|
569
|
+
|
|
570
|
+
Returns the index with which addition of other objects (like sizers)
|
|
571
|
+
can be referenced
|
|
572
|
+
"""
|
|
573
|
+
self.strats.append([(strategy, args, kwargs)])
|
|
574
|
+
return len(self.strats) - 1
|
|
575
|
+
|
|
576
|
+
# Check timer
|
|
577
|
+
def _check_timers(self, runstrats, dt0, cheat=False):
|
|
578
|
+
# If cheat is False, timers equals self._timers, otherwise equals self._timerscheat
|
|
579
|
+
timers = self._timers if not cheat else self._timerscheat
|
|
580
|
+
# For timer in timers
|
|
581
|
+
for t in timers:
|
|
582
|
+
# Use timer.check(dt0), if returns True, enter below, otherwise check next timer
|
|
583
|
+
if not t.check(dt0):
|
|
584
|
+
continue
|
|
585
|
+
# CRITICAL FIX: Remove 'when' from kwargs to avoid conflict with position argument
|
|
586
|
+
# when is already passed as t.lastwhen (2nd argument)
|
|
587
|
+
timer_kwargs = {k: v for k, v in t.kwargs.items() if k != "when"}
|
|
588
|
+
# Notify timer
|
|
589
|
+
t.params.owner.notify_timer(t, t.lastwhen, *t.args, **timer_kwargs)
|
|
590
|
+
# If strategy needs to use timer (t.params.strats is True), iterate strategies and call notify_timer
|
|
591
|
+
if t.params.strats:
|
|
592
|
+
for strat in runstrats:
|
|
593
|
+
strat.notify_timer(t, t.lastwhen, *t.args, **timer_kwargs)
|