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,267 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Momentum Indicator Module - Momentum and Rate of Change.
|
|
3
|
+
|
|
4
|
+
This module provides momentum-based indicators for measuring the rate
|
|
5
|
+
of price change over a given period.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
Momentum: Measures price change (difference).
|
|
9
|
+
MomentumOscillator: Momentum as ratio (alias: MomentumOsc).
|
|
10
|
+
RateOfChange: Rate of change indicator (alias: ROC).
|
|
11
|
+
RateOfChange100: ROC with base 100 (alias: ROC100).
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
class MyStrategy(bt.Strategy):
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.mom = bt.indicators.Momentum(self.data.close, period=12)
|
|
17
|
+
self.roc = bt.indicators.ROC(self.data.close, period=10)
|
|
18
|
+
self.roc100 = bt.indicators.ROC100(self.data.close, period=12)
|
|
19
|
+
|
|
20
|
+
def next(self):
|
|
21
|
+
# Momentum-based strategy
|
|
22
|
+
if self.mom.momentum[0] > 0:
|
|
23
|
+
self.buy()
|
|
24
|
+
elif self.mom.momentum[0] < 0:
|
|
25
|
+
self.sell()
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from . import Indicator
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Momentum(Indicator):
|
|
32
|
+
"""
|
|
33
|
+
Measures the change in price by calculating the difference between the
|
|
34
|
+
current price and the price from a given period ago
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
Formula:
|
|
38
|
+
- momentum = data - data_period
|
|
39
|
+
|
|
40
|
+
See:
|
|
41
|
+
- http://en.wikipedia.org/wiki/Momentum_(technical_analysis)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
lines = ("momentum",)
|
|
45
|
+
params = (("period", 12),)
|
|
46
|
+
plotinfo = {"plothlines": [0.0]}
|
|
47
|
+
|
|
48
|
+
def __init__(self):
|
|
49
|
+
"""Initialize the Momentum indicator.
|
|
50
|
+
|
|
51
|
+
Sets minimum period to period + 1 for difference calculation.
|
|
52
|
+
"""
|
|
53
|
+
super().__init__()
|
|
54
|
+
self.addminperiod(self.p.period + 1)
|
|
55
|
+
|
|
56
|
+
def next(self):
|
|
57
|
+
"""Calculate momentum for the current bar.
|
|
58
|
+
|
|
59
|
+
Momentum = current_price - price_period_ago
|
|
60
|
+
"""
|
|
61
|
+
self.lines.momentum[0] = self.data[0] - self.data[-self.p.period]
|
|
62
|
+
|
|
63
|
+
def once(self, start, end):
|
|
64
|
+
"""Calculate momentum in runonce mode.
|
|
65
|
+
|
|
66
|
+
Computes price difference across all bars.
|
|
67
|
+
"""
|
|
68
|
+
darray = self.data.array
|
|
69
|
+
larray = self.lines.momentum.array
|
|
70
|
+
period = self.p.period
|
|
71
|
+
|
|
72
|
+
while len(larray) < end:
|
|
73
|
+
larray.append(float("nan"))
|
|
74
|
+
|
|
75
|
+
for i in range(period, min(end, len(darray))):
|
|
76
|
+
larray[i] = darray[i] - darray[i - period]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class MomentumOscillator(Indicator):
|
|
80
|
+
"""
|
|
81
|
+
Measures the ratio of change in prices over a period
|
|
82
|
+
|
|
83
|
+
Formula:
|
|
84
|
+
- mosc = 100 * (data / data_period)
|
|
85
|
+
|
|
86
|
+
See:
|
|
87
|
+
- http://ta.mql4.com/indicators/oscillators/momentum
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
alias = ("MomentumOsc",)
|
|
91
|
+
|
|
92
|
+
# Named output lines
|
|
93
|
+
lines = ("momosc",)
|
|
94
|
+
|
|
95
|
+
# Accepted parameters (and defaults)
|
|
96
|
+
params = (("period", 12), ("band", 100.0))
|
|
97
|
+
|
|
98
|
+
def _plotlabel(self):
|
|
99
|
+
plabels = [self.p.period]
|
|
100
|
+
return plabels
|
|
101
|
+
|
|
102
|
+
def _plotinit(self):
|
|
103
|
+
self.plotinfo.plothlines = [self.p.band]
|
|
104
|
+
|
|
105
|
+
def __init__(self):
|
|
106
|
+
"""Initialize the Momentum Oscillator indicator.
|
|
107
|
+
|
|
108
|
+
Sets minimum period to period + 1 for ratio calculation.
|
|
109
|
+
"""
|
|
110
|
+
super().__init__()
|
|
111
|
+
self.addminperiod(self.p.period + 1)
|
|
112
|
+
|
|
113
|
+
def next(self):
|
|
114
|
+
"""Calculate momentum oscillator for the current bar.
|
|
115
|
+
|
|
116
|
+
Oscillator = 100 * (current_price / price_period_ago)
|
|
117
|
+
Returns 0.0 if previous value is 0 to avoid division by zero.
|
|
118
|
+
"""
|
|
119
|
+
prev_val = self.data[-self.p.period]
|
|
120
|
+
if prev_val != 0:
|
|
121
|
+
self.lines.momosc[0] = 100.0 * (self.data[0] / prev_val)
|
|
122
|
+
else:
|
|
123
|
+
self.lines.momosc[0] = 0.0
|
|
124
|
+
|
|
125
|
+
def once(self, start, end):
|
|
126
|
+
"""Calculate momentum oscillator in runonce mode.
|
|
127
|
+
|
|
128
|
+
Computes 100 * ratio across all bars.
|
|
129
|
+
"""
|
|
130
|
+
darray = self.data.array
|
|
131
|
+
larray = self.lines.momosc.array
|
|
132
|
+
period = self.p.period
|
|
133
|
+
|
|
134
|
+
while len(larray) < end:
|
|
135
|
+
larray.append(float("nan"))
|
|
136
|
+
|
|
137
|
+
for i in range(period, min(end, len(darray))):
|
|
138
|
+
prev_val = darray[i - period]
|
|
139
|
+
if prev_val != 0:
|
|
140
|
+
larray[i] = 100.0 * (darray[i] / prev_val)
|
|
141
|
+
else:
|
|
142
|
+
larray[i] = 0.0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class RateOfChange(Indicator):
|
|
146
|
+
"""
|
|
147
|
+
Measures the ratio of change in prices over a period
|
|
148
|
+
|
|
149
|
+
Formula:
|
|
150
|
+
- roc = (data - data_period) / data_period
|
|
151
|
+
|
|
152
|
+
See:
|
|
153
|
+
- http://en.wikipedia.org/wiki/Momentum_(technical_analysis)
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
alias = ("ROC",)
|
|
157
|
+
|
|
158
|
+
# Named output lines
|
|
159
|
+
lines = ("roc",)
|
|
160
|
+
|
|
161
|
+
# Accepted parameters (and defaults)
|
|
162
|
+
params = (("period", 12),)
|
|
163
|
+
|
|
164
|
+
def __init__(self):
|
|
165
|
+
"""Initialize the Rate of Change indicator.
|
|
166
|
+
|
|
167
|
+
Sets minimum period to period + 1 for ratio calculation.
|
|
168
|
+
"""
|
|
169
|
+
super().__init__()
|
|
170
|
+
self.addminperiod(self.p.period + 1)
|
|
171
|
+
|
|
172
|
+
def next(self):
|
|
173
|
+
"""Calculate ROC for the current bar.
|
|
174
|
+
|
|
175
|
+
ROC = (current_price - price_period_ago) / price_period_ago
|
|
176
|
+
Returns 0.0 if previous value is 0 to avoid division by zero.
|
|
177
|
+
"""
|
|
178
|
+
prev_val = self.data[-self.p.period]
|
|
179
|
+
if prev_val != 0:
|
|
180
|
+
self.lines.roc[0] = (self.data[0] - prev_val) / prev_val
|
|
181
|
+
else:
|
|
182
|
+
self.lines.roc[0] = 0.0
|
|
183
|
+
|
|
184
|
+
def once(self, start, end):
|
|
185
|
+
"""Calculate ROC in runonce mode.
|
|
186
|
+
|
|
187
|
+
Computes rate of change ratio across all bars.
|
|
188
|
+
"""
|
|
189
|
+
darray = self.data.array
|
|
190
|
+
larray = self.lines.roc.array
|
|
191
|
+
period = self.p.period
|
|
192
|
+
|
|
193
|
+
while len(larray) < end:
|
|
194
|
+
larray.append(float("nan"))
|
|
195
|
+
|
|
196
|
+
for i in range(period, min(end, len(darray))):
|
|
197
|
+
prev_val = darray[i - period]
|
|
198
|
+
if prev_val != 0:
|
|
199
|
+
larray[i] = (darray[i] - prev_val) / prev_val
|
|
200
|
+
else:
|
|
201
|
+
larray[i] = 0.0
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class RateOfChange100(Indicator):
|
|
205
|
+
"""
|
|
206
|
+
Measures the ratio of change in prices over a period with base 100
|
|
207
|
+
|
|
208
|
+
This is, for example, how ROC is defined in stockcharts
|
|
209
|
+
|
|
210
|
+
Formula:
|
|
211
|
+
- roc = 100 * (data - data_period) / data_period
|
|
212
|
+
|
|
213
|
+
See:
|
|
214
|
+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:rate_of_change_roc_and_momentum
|
|
215
|
+
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
alias = ("ROC100",)
|
|
219
|
+
|
|
220
|
+
# Named output lines
|
|
221
|
+
lines = ("roc100",)
|
|
222
|
+
|
|
223
|
+
# Accepted parameters (and defaults)
|
|
224
|
+
params = (("period", 12),)
|
|
225
|
+
|
|
226
|
+
def __init__(self):
|
|
227
|
+
"""Initialize the ROC100 indicator.
|
|
228
|
+
|
|
229
|
+
Sets minimum period to period + 1 for ratio calculation.
|
|
230
|
+
"""
|
|
231
|
+
super().__init__()
|
|
232
|
+
self.addminperiod(self.p.period + 1)
|
|
233
|
+
|
|
234
|
+
def next(self):
|
|
235
|
+
"""Calculate ROC100 for the current bar.
|
|
236
|
+
|
|
237
|
+
ROC100 = 100 * (current_price - price_period_ago) / price_period_ago
|
|
238
|
+
Returns 0.0 if previous value is 0 to avoid division by zero.
|
|
239
|
+
"""
|
|
240
|
+
prev_val = self.data[-self.p.period]
|
|
241
|
+
if prev_val != 0:
|
|
242
|
+
self.lines.roc100[0] = 100.0 * (self.data[0] - prev_val) / prev_val
|
|
243
|
+
else:
|
|
244
|
+
self.lines.roc100[0] = 0.0
|
|
245
|
+
|
|
246
|
+
def once(self, start, end):
|
|
247
|
+
"""Calculate ROC100 in runonce mode.
|
|
248
|
+
|
|
249
|
+
Computes rate of change with base 100 across all bars.
|
|
250
|
+
"""
|
|
251
|
+
darray = self.data.array
|
|
252
|
+
larray = self.lines.roc100.array
|
|
253
|
+
period = self.p.period
|
|
254
|
+
|
|
255
|
+
while len(larray) < end:
|
|
256
|
+
larray.append(float("nan"))
|
|
257
|
+
|
|
258
|
+
for i in range(period, min(end, len(darray))):
|
|
259
|
+
prev_val = darray[i - period]
|
|
260
|
+
if prev_val != 0:
|
|
261
|
+
larray[i] = 100.0 * (darray[i] - prev_val) / prev_val
|
|
262
|
+
else:
|
|
263
|
+
larray[i] = 0.0
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
ROC = RateOfChange
|
|
267
|
+
ROC100 = RateOfChange100
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Money flow indicators migrated from functional strategy tests."""
|
|
3
|
+
|
|
4
|
+
from . import Indicator
|
|
5
|
+
from .atr import ATR
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"DeltaMFI",
|
|
9
|
+
"MFI",
|
|
10
|
+
"MFIHistogramIndicator",
|
|
11
|
+
"MFISlowdown",
|
|
12
|
+
"MoneyFlowIndex",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MoneyFlowIndex(Indicator):
|
|
17
|
+
"""Money Flow Index using a current-inclusive lookback window."""
|
|
18
|
+
|
|
19
|
+
lines = ("mfi",)
|
|
20
|
+
params = (("period", 14),)
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
"""Register the rolling window size needed for the MFI calculation."""
|
|
24
|
+
self.addminperiod(self.p.period + 1)
|
|
25
|
+
|
|
26
|
+
def next(self):
|
|
27
|
+
"""Compute the Money Flow Index for the current bar.
|
|
28
|
+
|
|
29
|
+
Walks the most recent ``period`` bars (current inclusive), sums
|
|
30
|
+
the positive raw money flow (typical price rising) and the
|
|
31
|
+
negative raw money flow (typical price falling) where the raw
|
|
32
|
+
flow is ``typical_price * volume``. The MFI is then written as
|
|
33
|
+
``100 - 100 / (1 + positive/negative)``; when no negative flow
|
|
34
|
+
is observed, the indicator is saturated at ``100.0``.
|
|
35
|
+
"""
|
|
36
|
+
positive_flow = 0.0
|
|
37
|
+
negative_flow = 0.0
|
|
38
|
+
for i in range(self.p.period):
|
|
39
|
+
curr_tp = (
|
|
40
|
+
float(self.data.high[-i]) + float(self.data.low[-i]) + float(self.data.close[-i])
|
|
41
|
+
) / 3.0
|
|
42
|
+
prev_tp = (
|
|
43
|
+
float(self.data.high[-i - 1])
|
|
44
|
+
+ float(self.data.low[-i - 1])
|
|
45
|
+
+ float(self.data.close[-i - 1])
|
|
46
|
+
) / 3.0
|
|
47
|
+
raw_flow = curr_tp * float(self.data.volume[-i])
|
|
48
|
+
if curr_tp > prev_tp:
|
|
49
|
+
positive_flow += raw_flow
|
|
50
|
+
elif curr_tp < prev_tp:
|
|
51
|
+
negative_flow += raw_flow
|
|
52
|
+
|
|
53
|
+
if negative_flow == 0.0:
|
|
54
|
+
self.lines.mfi[0] = 100.0
|
|
55
|
+
else:
|
|
56
|
+
money_ratio = positive_flow / negative_flow
|
|
57
|
+
self.lines.mfi[0] = 100.0 - (100.0 / (1.0 + money_ratio))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MFI(Indicator):
|
|
61
|
+
"""Money Flow Index variant using the previous completed window.
|
|
62
|
+
|
|
63
|
+
Some functional strategies historically calculated MFI over
|
|
64
|
+
``range(-period, 0)`` instead of including bar 0. This class preserves
|
|
65
|
+
that behavior and is intentionally not an alias of ``MoneyFlowIndex``.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
lines = ("mfi",)
|
|
69
|
+
params = (("period", 14),)
|
|
70
|
+
|
|
71
|
+
def __init__(self):
|
|
72
|
+
"""Register the rolling window size needed for the MFI calculation."""
|
|
73
|
+
self.addminperiod(self.p.period + 1)
|
|
74
|
+
|
|
75
|
+
def next(self):
|
|
76
|
+
"""Compute MFI over the previous ``period`` bars (not the current bar).
|
|
77
|
+
|
|
78
|
+
Unlike :class:`MoneyFlowIndex`, the loop indexes
|
|
79
|
+
``range(-period, 0)`` so the current bar is excluded from the
|
|
80
|
+
window. The positive/negative flow split and saturation rule
|
|
81
|
+
are otherwise identical. This preserves the historical
|
|
82
|
+
functional-strategy behavior.
|
|
83
|
+
"""
|
|
84
|
+
period = self.p.period
|
|
85
|
+
pos_flow = 0.0
|
|
86
|
+
neg_flow = 0.0
|
|
87
|
+
for i in range(-period, 0):
|
|
88
|
+
tp_cur = (
|
|
89
|
+
float(self.data.high[i]) + float(self.data.low[i]) + float(self.data.close[i])
|
|
90
|
+
) / 3.0
|
|
91
|
+
tp_prev = (
|
|
92
|
+
float(self.data.high[i - 1])
|
|
93
|
+
+ float(self.data.low[i - 1])
|
|
94
|
+
+ float(self.data.close[i - 1])
|
|
95
|
+
) / 3.0
|
|
96
|
+
mf = tp_cur * float(self.data.volume[i])
|
|
97
|
+
if tp_cur > tp_prev:
|
|
98
|
+
pos_flow += mf
|
|
99
|
+
elif tp_cur < tp_prev:
|
|
100
|
+
neg_flow += mf
|
|
101
|
+
|
|
102
|
+
if neg_flow == 0:
|
|
103
|
+
self.lines.mfi[0] = 100.0
|
|
104
|
+
else:
|
|
105
|
+
ratio = pos_flow / neg_flow
|
|
106
|
+
self.lines.mfi[0] = 100.0 - 100.0 / (1.0 + ratio)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class DeltaMFI(Indicator):
|
|
110
|
+
"""Difference between two current-inclusive MFI periods plus color state."""
|
|
111
|
+
|
|
112
|
+
lines = ("color", "delta")
|
|
113
|
+
params = {"mfi_period1": 14, "mfi_period2": 50, "level": 50}
|
|
114
|
+
|
|
115
|
+
def __init__(self):
|
|
116
|
+
"""Set up the two MFI sub-indicators and the regime thresholds."""
|
|
117
|
+
self.addminperiod(max(int(self.p.mfi_period1), int(self.p.mfi_period2)) + 3)
|
|
118
|
+
self.mfi1 = MoneyFlowIndex(self.data, period=int(self.p.mfi_period1))
|
|
119
|
+
self.mfi2 = MoneyFlowIndex(self.data, period=int(self.p.mfi_period2))
|
|
120
|
+
lvl = int(self.p.level)
|
|
121
|
+
self.max_level = 100 - (100 - lvl)
|
|
122
|
+
self.min_level = 100 - lvl
|
|
123
|
+
|
|
124
|
+
def next(self):
|
|
125
|
+
"""Compute the MFI delta and assign a regime color.
|
|
126
|
+
|
|
127
|
+
Writes ``mfi_fast - mfi_slow`` to ``self.lines.delta`` and
|
|
128
|
+
colors ``0.0`` when the slow MFI is above the upper threshold
|
|
129
|
+
and the fast MFI is climbing, ``2.0`` when the slow MFI is
|
|
130
|
+
below the lower threshold and the fast MFI is falling, and
|
|
131
|
+
``1.0`` (neutral) otherwise.
|
|
132
|
+
"""
|
|
133
|
+
m1 = float(self.mfi1[0])
|
|
134
|
+
m2 = float(self.mfi2[0])
|
|
135
|
+
self.lines.delta[0] = m1 - m2
|
|
136
|
+
color = 1.0
|
|
137
|
+
if m2 > self.max_level and m1 > m2:
|
|
138
|
+
color = 0.0
|
|
139
|
+
if m2 < self.min_level and m1 < m2:
|
|
140
|
+
color = 2.0
|
|
141
|
+
self.lines.color[0] = color
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class MFISlowdown(Indicator):
|
|
145
|
+
"""MFI extreme signal generator with optional slowdown detection."""
|
|
146
|
+
|
|
147
|
+
lines = ("sell", "buy")
|
|
148
|
+
params = {"mfi_period": 2, "level_max": 90.0, "level_min": 10.0, "seek_slowdown": True}
|
|
149
|
+
|
|
150
|
+
def __init__(self):
|
|
151
|
+
"""Set up the MFI and ATR sub-indicators and the minimum period."""
|
|
152
|
+
self.addminperiod(max(int(self.p.mfi_period) + 2, 18))
|
|
153
|
+
self.mfi = MoneyFlowIndex(self.data, period=int(self.p.mfi_period))
|
|
154
|
+
self.atr = ATR(self.data, period=15)
|
|
155
|
+
|
|
156
|
+
def next(self):
|
|
157
|
+
"""Emit ATR-buffered stop levels when MFI touches an extreme.
|
|
158
|
+
|
|
159
|
+
When ``seek_slowdown`` is enabled, a signal is only produced if
|
|
160
|
+
the MFI's previous bar value differs from the current value by
|
|
161
|
+
less than ``1.0`` (i.e. the MFI is stalling at the extreme).
|
|
162
|
+
The buy line is placed ``atr * 3/8`` below the low, and the
|
|
163
|
+
sell line ``atr * 3/8`` above the high. Lines are ``NaN`` when
|
|
164
|
+
no signal is produced.
|
|
165
|
+
"""
|
|
166
|
+
self.lines.buy[0] = float("nan")
|
|
167
|
+
self.lines.sell[0] = float("nan")
|
|
168
|
+
m0 = float(self.mfi[0])
|
|
169
|
+
m1 = float(self.mfi[-1])
|
|
170
|
+
atr = float(self.atr[0])
|
|
171
|
+
if m0 >= float(self.p.level_max):
|
|
172
|
+
if (not self.p.seek_slowdown) or abs(m1 - m0) < 1.0:
|
|
173
|
+
self.lines.buy[0] = float(self.data.low[0]) - atr * 3.0 / 8.0
|
|
174
|
+
if m0 <= float(self.p.level_min):
|
|
175
|
+
if (not self.p.seek_slowdown) or abs(m1 - m0) < 1.0:
|
|
176
|
+
self.lines.sell[0] = float(self.data.high[0]) + atr * 3.0 / 8.0
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class MFIHistogramIndicator(Indicator):
|
|
180
|
+
"""MFI value, midpoint and color-state histogram."""
|
|
181
|
+
|
|
182
|
+
lines = ("value", "midline", "color_state")
|
|
183
|
+
params = {"mfi_period": 14, "high_level": 60, "low_level": 40}
|
|
184
|
+
|
|
185
|
+
def __init__(self):
|
|
186
|
+
"""Register the minimum period needed for the MFI lookback."""
|
|
187
|
+
self.addminperiod(self.p.mfi_period + 1)
|
|
188
|
+
|
|
189
|
+
def next(self):
|
|
190
|
+
"""Write the MFI value, the 50 midline and the regime color.
|
|
191
|
+
|
|
192
|
+
For the first ``mfi_period`` bars the output is the neutral
|
|
193
|
+
``(50.0, 50.0, 1.0)`` triple. After the buffer is warm, the
|
|
194
|
+
MFI is computed from typical prices and volume, falling back to
|
|
195
|
+
``50.0`` when there is no flow information. The color is
|
|
196
|
+
``0.0`` above ``high_level``, ``2.0`` below ``low_level``, and
|
|
197
|
+
``1.0`` (neutral) in between.
|
|
198
|
+
"""
|
|
199
|
+
if len(self.data) <= self.p.mfi_period:
|
|
200
|
+
self.lines.value[0] = 50.0
|
|
201
|
+
self.lines.midline[0] = 50.0
|
|
202
|
+
self.lines.color_state[0] = 1.0
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
positive_flow = 0.0
|
|
206
|
+
negative_flow = 0.0
|
|
207
|
+
for ago in range(self.p.mfi_period):
|
|
208
|
+
high = float(self.data.high[-ago])
|
|
209
|
+
low = float(self.data.low[-ago])
|
|
210
|
+
close = float(self.data.close[-ago])
|
|
211
|
+
prev_high = float(self.data.high[-ago - 1])
|
|
212
|
+
prev_low = float(self.data.low[-ago - 1])
|
|
213
|
+
prev_close = float(self.data.close[-ago - 1])
|
|
214
|
+
volume = float(self.data.volume[-ago])
|
|
215
|
+
typical = (high + low + close) / 3.0
|
|
216
|
+
prev_typical = (prev_high + prev_low + prev_close) / 3.0
|
|
217
|
+
raw_money_flow = typical * volume
|
|
218
|
+
if typical > prev_typical:
|
|
219
|
+
positive_flow += raw_money_flow
|
|
220
|
+
elif typical < prev_typical:
|
|
221
|
+
negative_flow += raw_money_flow
|
|
222
|
+
|
|
223
|
+
if negative_flow <= 1e-12:
|
|
224
|
+
mfi_value = 100.0 if positive_flow > 0 else 50.0
|
|
225
|
+
else:
|
|
226
|
+
money_ratio = positive_flow / negative_flow
|
|
227
|
+
mfi_value = 100.0 - (100.0 / (1.0 + money_ratio))
|
|
228
|
+
|
|
229
|
+
color = 1.0
|
|
230
|
+
if mfi_value > float(self.p.high_level):
|
|
231
|
+
color = 0.0
|
|
232
|
+
elif mfi_value < float(self.p.low_level):
|
|
233
|
+
color = 2.0
|
|
234
|
+
|
|
235
|
+
self.lines.value[0] = mfi_value
|
|
236
|
+
self.lines.midline[0] = 50.0
|
|
237
|
+
self.lines.color_state[0] = color
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""MT5-compatible ATR Indicator Module.
|
|
3
|
+
|
|
4
|
+
This module provides an ATR indicator that exactly matches MetaTrader 5's
|
|
5
|
+
iATR() function, using Wilder's smoothing with MT5's seeding convention.
|
|
6
|
+
|
|
7
|
+
Differences from standard backtrader ATR:
|
|
8
|
+
- Seed at bar index (period - 1) using TR[0..period-1]
|
|
9
|
+
- TR[0] = High[0] - Low[0] (no previous close available)
|
|
10
|
+
- Subsequent: ATR[i] = (ATR[i-1] * (period-1) + TR[i]) / period
|
|
11
|
+
|
|
12
|
+
Classes:
|
|
13
|
+
MT5AverageTrueRange: ATR matching MT5's iATR() (alias: MT5ATR).
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
class MyStrategy(bt.Strategy):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self.atr = bt.indicators.MT5ATR(self.data, period=14)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from . import Indicator
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MT5AverageTrueRange(Indicator):
|
|
25
|
+
"""Average True Range matching MetaTrader 5's iATR() implementation.
|
|
26
|
+
|
|
27
|
+
MT5 ATR algorithm:
|
|
28
|
+
- TR[0] = High[0] - Low[0]
|
|
29
|
+
- TR[i] = max(High[i], Close[i-1]) - min(Low[i], Close[i-1]) for i >= 1
|
|
30
|
+
- ATR[period-1] = SMA(TR[0..period-1]) (seed)
|
|
31
|
+
- ATR[i] = (ATR[i-1] * (period-1) + TR[i]) / period for i >= period
|
|
32
|
+
|
|
33
|
+
See:
|
|
34
|
+
- https://www.mql5.com/en/docs/indicators/iatr
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
alias = ("MT5ATR",)
|
|
38
|
+
|
|
39
|
+
lines = ("atr",)
|
|
40
|
+
params = (("period", 14),)
|
|
41
|
+
|
|
42
|
+
def _plotlabel(self):
|
|
43
|
+
"""Return the label segments used by the plot helper (just the period)."""
|
|
44
|
+
return [self.p.period]
|
|
45
|
+
|
|
46
|
+
def __init__(self):
|
|
47
|
+
"""Wire the minimum period and cache the configured period on the instance.
|
|
48
|
+
|
|
49
|
+
The MT5 convention places the first ATR at bar index
|
|
50
|
+
``period - 1``; the very first true range uses the high-low
|
|
51
|
+
range (no previous close), so the minimum period is just
|
|
52
|
+
``period`` bars.
|
|
53
|
+
"""
|
|
54
|
+
super().__init__()
|
|
55
|
+
# MT5 first ATR at bar index period-1, but TR needs prev close from bar 1,
|
|
56
|
+
# and bar 0's TR uses High-Low only. Min period = period bars total.
|
|
57
|
+
self.addminperiod(self.p.period)
|
|
58
|
+
self._period = self.p.period
|
|
59
|
+
|
|
60
|
+
@staticmethod
|
|
61
|
+
def _calc_tr(high, low, prev_close):
|
|
62
|
+
"""Calculate True Range: max(high, prev_close) - min(low, prev_close)."""
|
|
63
|
+
return max(high, prev_close) - min(low, prev_close)
|
|
64
|
+
|
|
65
|
+
def nextstart(self):
|
|
66
|
+
"""Seed ATR with SMA of first period TR values (MT5 convention)."""
|
|
67
|
+
period = self._period
|
|
68
|
+
tr_sum = 0.0
|
|
69
|
+
for i in range(period):
|
|
70
|
+
idx = -(period - 1 - i) # oldest to newest: -(period-1), ..., -1, 0
|
|
71
|
+
if i == 0:
|
|
72
|
+
# First bar: no prev close, use High - Low
|
|
73
|
+
tr = self.data.high[idx] - self.data.low[idx]
|
|
74
|
+
else:
|
|
75
|
+
prev_idx = idx - 1
|
|
76
|
+
tr = self._calc_tr(
|
|
77
|
+
self.data.high[idx], self.data.low[idx], self.data.close[prev_idx]
|
|
78
|
+
)
|
|
79
|
+
tr_sum += tr
|
|
80
|
+
self.lines.atr[0] = tr_sum / period
|
|
81
|
+
|
|
82
|
+
def next(self):
|
|
83
|
+
"""ATR[i] = (ATR[i-1] * (period-1) + TR[i]) / period."""
|
|
84
|
+
tr = self._calc_tr(self.data.high[0], self.data.low[0], self.data.close[-1])
|
|
85
|
+
self.lines.atr[0] = (self.lines.atr[-1] * (self._period - 1) + tr) / self._period
|
|
86
|
+
|
|
87
|
+
def once(self, start, end):
|
|
88
|
+
"""Calculate ATR in runonce mode (matches MT5 iATR exactly)."""
|
|
89
|
+
high = self.data.high.array
|
|
90
|
+
low = self.data.low.array
|
|
91
|
+
close = self.data.close.array
|
|
92
|
+
out = self.lines.atr.array
|
|
93
|
+
period = self._period
|
|
94
|
+
|
|
95
|
+
# Ensure output array is sized
|
|
96
|
+
while len(out) < end:
|
|
97
|
+
out.append(float("nan"))
|
|
98
|
+
|
|
99
|
+
n = min(end, len(high), len(low), len(close))
|
|
100
|
+
|
|
101
|
+
# Pre-fill with NaN before seed
|
|
102
|
+
for i in range(min(period - 1, n)):
|
|
103
|
+
out[i] = float("nan")
|
|
104
|
+
|
|
105
|
+
if n < period:
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# Seed: SMA of TR[0..period-1]
|
|
109
|
+
seed_idx = period - 1
|
|
110
|
+
tr_sum = high[0] - low[0] # TR[0] = High - Low (no prev close)
|
|
111
|
+
for i in range(1, period):
|
|
112
|
+
tr_sum += max(high[i], close[i - 1]) - min(low[i], close[i - 1])
|
|
113
|
+
prev_atr = tr_sum / period
|
|
114
|
+
out[seed_idx] = prev_atr
|
|
115
|
+
|
|
116
|
+
# Wilder smoothing for remaining bars
|
|
117
|
+
pm1 = period - 1 # period - 1
|
|
118
|
+
for i in range(period, n):
|
|
119
|
+
tr = max(high[i], close[i - 1]) - min(low[i], close[i - 1])
|
|
120
|
+
prev_atr = (prev_atr * pm1 + tr) / period
|
|
121
|
+
out[i] = prev_atr
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
MT5ATR = MT5AverageTrueRange
|