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,125 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Laguerre RSI Module - Laguerre filter-based RSI.
|
|
3
|
+
|
|
4
|
+
This module provides the LaguerreRSI indicator defined by John F. Ehlers
|
|
5
|
+
for faster reaction to price changes using Laguerre filters.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
LaguerreRSI: Laguerre RSI indicator (alias: LRSI).
|
|
9
|
+
LaguerreFilter: Laguerre filter (alias: LAGF).
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
class MyStrategy(bt.Strategy):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.lrsi = bt.indicators.LRSI(self.data, gamma=0.5)
|
|
15
|
+
self.lfilter = bt.indicators.LAGF(self.data, gamma=0.5)
|
|
16
|
+
|
|
17
|
+
def next(self):
|
|
18
|
+
if self.lrsi.lrsi[0] > 0.8:
|
|
19
|
+
self.sell()
|
|
20
|
+
elif self.lrsi.lrsi[0] < 0.2:
|
|
21
|
+
self.buy()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from . import PeriodN
|
|
25
|
+
|
|
26
|
+
__all__ = ["LaguerreRSI", "LRSI", "LaguerreFilter", "LAGF"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class LaguerreRSI(PeriodN):
|
|
30
|
+
"""
|
|
31
|
+
Defined by John F. Ehlers in `Cybernetic Analysis for Stock and Futures`,
|
|
32
|
+
2004, published by Wiley. `ISBN: 978-0-471-46307-8`
|
|
33
|
+
|
|
34
|
+
The Laguerre RSI tries to implement a better RSI by providing a sort of
|
|
35
|
+
*Time Warp without Time Travel* using a Laguerre filter. This provides for
|
|
36
|
+
faster reactions to price changes
|
|
37
|
+
|
|
38
|
+
``gamma`` is meant to have values between ``0.2`` and ``0.8``, with the
|
|
39
|
+
best balance found theoretically at the default of ``0.5``
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
alias = ("LRSI",)
|
|
43
|
+
lines = ("lrsi",)
|
|
44
|
+
params = (
|
|
45
|
+
("gamma", 0.5),
|
|
46
|
+
("period", 6),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
plotinfo = {"plotymargin": 0.15, "plotyticks": [0.0, 0.2, 0.5, 0.8, 1.0]}
|
|
50
|
+
|
|
51
|
+
l0, l1, l2, l3 = 0.0, 0.0, 0.0, 0.0
|
|
52
|
+
|
|
53
|
+
def next(self):
|
|
54
|
+
"""Calculate Laguerre RSI for the current bar.
|
|
55
|
+
|
|
56
|
+
Calculates L0-L3 Laguerre filter values and computes the
|
|
57
|
+
RSI-style ratio of upward changes to total changes.
|
|
58
|
+
"""
|
|
59
|
+
l0_1 = self.l0 # cache previous intermediate values
|
|
60
|
+
l1_1 = self.l1
|
|
61
|
+
l2_1 = self.l2
|
|
62
|
+
|
|
63
|
+
g = self.p.gamma # avoid more lookups
|
|
64
|
+
self.l0 = l0 = (1.0 - g) * self.data + g * l0_1
|
|
65
|
+
self.l1 = l1 = -g * l0 + l0_1 + g * l1_1
|
|
66
|
+
self.l2 = l2 = -g * l1 + l1_1 + g * l2_1
|
|
67
|
+
self.l3 = l3 = -g * l2 + l2_1 + g * self.l3
|
|
68
|
+
|
|
69
|
+
cu = 0.0
|
|
70
|
+
cd = 0.0
|
|
71
|
+
if l0 >= l1:
|
|
72
|
+
cu = l0 - l1
|
|
73
|
+
else:
|
|
74
|
+
cd = l1 - l0
|
|
75
|
+
|
|
76
|
+
if l1 >= l2:
|
|
77
|
+
cu += l1 - l2
|
|
78
|
+
else:
|
|
79
|
+
cd += l2 - l1
|
|
80
|
+
|
|
81
|
+
if l2 >= l3:
|
|
82
|
+
cu += l2 - l3
|
|
83
|
+
else:
|
|
84
|
+
cd += l3 - l2
|
|
85
|
+
|
|
86
|
+
den = cu + cd
|
|
87
|
+
self.lines.lrsi[0] = 1.0 if not den else cu / den
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class LaguerreFilter(PeriodN):
|
|
91
|
+
"""
|
|
92
|
+
Defined by John F. Ehlers in `Cybernetic Analysis for Stock and Futures`,
|
|
93
|
+
2004, published by Wiley. `ISBN: 978-0-471-46307-8`
|
|
94
|
+
|
|
95
|
+
``gamma`` is meant to have values between ``0.2`` and ``0.8``, with the
|
|
96
|
+
best balance found theoretically at the default of ``0.5``
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
alias = ("LAGF",)
|
|
100
|
+
lines = ("lfilter",)
|
|
101
|
+
params = (("gamma", 0.5),)
|
|
102
|
+
plotinfo = {"subplot": False}
|
|
103
|
+
|
|
104
|
+
l0, l1, l2, l3 = 0.0, 0.0, 0.0, 0.0
|
|
105
|
+
|
|
106
|
+
def next(self):
|
|
107
|
+
"""Calculate Laguerre filter for the current bar.
|
|
108
|
+
|
|
109
|
+
Computes L0-L3 Laguerre filter values and outputs the
|
|
110
|
+
weighted average (l0 + 2*l1 + 2*l2 + l3) / 6.
|
|
111
|
+
"""
|
|
112
|
+
l0_1 = self.l0 # cache previous intermediate values
|
|
113
|
+
l1_1 = self.l1
|
|
114
|
+
l2_1 = self.l2
|
|
115
|
+
|
|
116
|
+
g = self.p.gamma # avoid more lookups
|
|
117
|
+
self.l0 = l0 = (1.0 - g) * self.data + g * l0_1
|
|
118
|
+
self.l1 = l1 = -g * l0 + l0_1 + g * l1_1
|
|
119
|
+
self.l2 = l2 = -g * l1 + l1_1 + g * l2_1
|
|
120
|
+
self.l3 = l3 = -g * l2 + l2_1 + g * self.l3
|
|
121
|
+
self.lines.lfilter[0] = (l0 + (2 * l1) + (2 * l2) + l3) / 6
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
LRSI = LaguerreRSI
|
|
125
|
+
LAGF = LaguerreFilter
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Moving Average Base Module - Core moving average infrastructure.
|
|
3
|
+
|
|
4
|
+
This module provides the base classes and registration system for all
|
|
5
|
+
moving average indicators in backtrader.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
MovingAverage: Placeholder for all moving average types.
|
|
9
|
+
MovAv: Alias for MovingAverage.
|
|
10
|
+
MovingAverageBase: Base class for moving average indicators.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
class MyStrategy(bt.Strategy):
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.sma = bt.indicators.SMA(self.data.close, period=20)
|
|
16
|
+
self.ema = bt.indicators.EMA(self.data.close, period=12)
|
|
17
|
+
# Or using MovAv wrapper
|
|
18
|
+
self.wma = bt.indicators.MovAv.WMA(self.data.close, period=15)
|
|
19
|
+
|
|
20
|
+
def next(self):
|
|
21
|
+
if self.data.close[0] > self.sma[0]:
|
|
22
|
+
self.buy()
|
|
23
|
+
elif self.data.close[0] < self.sma[0]:
|
|
24
|
+
self.sell()
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from . import Indicator
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Moving average class, used to set indicator names
|
|
31
|
+
class MovingAverage:
|
|
32
|
+
"""MovingAverage (alias MovAv)
|
|
33
|
+
|
|
34
|
+
A placeholder to gather all Moving Average Types in a single place.
|
|
35
|
+
|
|
36
|
+
Instantiating a SimpleMovingAverage can be achieved as follows::
|
|
37
|
+
|
|
38
|
+
sma = MovingAverage.Simple(self.data, period)
|
|
39
|
+
|
|
40
|
+
Or using the shorter aliases::
|
|
41
|
+
|
|
42
|
+
sma = MovAv.SMA(self.data, period)
|
|
43
|
+
|
|
44
|
+
or with the full (forwards and backwards) names:
|
|
45
|
+
|
|
46
|
+
sma = MovAv.SimpleMovingAverage(self.data, period)
|
|
47
|
+
|
|
48
|
+
sma = MovAv.MovingAverageSimple(self.data, period)
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Storage for moving average classes
|
|
53
|
+
_movavs: list = []
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def register(cls, regcls):
|
|
57
|
+
"""Register a moving average class with the placeholder.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
regcls: The moving average class to register.
|
|
61
|
+
|
|
62
|
+
Sets the class name and aliases as attributes on the placeholder
|
|
63
|
+
for easy access (e.g., MovAv.SMA, MovAv.EMA).
|
|
64
|
+
"""
|
|
65
|
+
# If indicator doesn't have _notregister or _notregister value is False, continue to register, otherwise return directly
|
|
66
|
+
if getattr(regcls, "_notregister", False):
|
|
67
|
+
return
|
|
68
|
+
# Add indicator class to be calculated
|
|
69
|
+
cls._movavs.append(regcls)
|
|
70
|
+
# Class name, and set class name as cls attribute, attribute value is the specific class
|
|
71
|
+
clsname = regcls.__name__
|
|
72
|
+
setattr(cls, clsname, regcls)
|
|
73
|
+
|
|
74
|
+
# Specific indicator alias, if indicator starts with MovingAverage, use latter value as alias, if ends with MovingAverage, use former value as alias
|
|
75
|
+
# If obtained alias is not empty string, then also set alias as attribute, attribute value is this class
|
|
76
|
+
clsalias = ""
|
|
77
|
+
if clsname.endswith("MovingAverage"):
|
|
78
|
+
clsalias = clsname.split("MovingAverage")[0]
|
|
79
|
+
elif clsname.startswith("MovingAverage"):
|
|
80
|
+
clsalias = clsname.split("MovingAverage")[1]
|
|
81
|
+
|
|
82
|
+
if clsalias:
|
|
83
|
+
setattr(cls, clsalias, regcls)
|
|
84
|
+
|
|
85
|
+
# CRITICAL FIX: Process the alias attribute if it exists
|
|
86
|
+
# Many indicators define their own aliases like alias = ("SMA", "SimpleMovingAverage")
|
|
87
|
+
if hasattr(regcls, "alias"):
|
|
88
|
+
aliases = regcls.alias
|
|
89
|
+
# Support both tuple and single string
|
|
90
|
+
if isinstance(aliases, str):
|
|
91
|
+
aliases = (aliases,)
|
|
92
|
+
# Register each alias
|
|
93
|
+
for alias_name in aliases:
|
|
94
|
+
if alias_name and isinstance(alias_name, str):
|
|
95
|
+
setattr(cls, alias_name, regcls)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# Alias for moving average
|
|
99
|
+
class MovAv(MovingAverage):
|
|
100
|
+
"""Alias for MovingAverage.
|
|
101
|
+
|
|
102
|
+
Provides a shorter name for accessing moving average types.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
# alias
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# Base class for moving average, add parameters and plot settings - refactored to remove metaclass
|
|
109
|
+
class MovingAverageBase(Indicator):
|
|
110
|
+
"""Base class for all moving average indicators.
|
|
111
|
+
|
|
112
|
+
Provides common initialization with minimum period management and
|
|
113
|
+
automatic registration with the MovingAverage placeholder.
|
|
114
|
+
|
|
115
|
+
Attributes:
|
|
116
|
+
params: Default period parameter (30).
|
|
117
|
+
plotinfo: Default to plot on main chart (subplot=False).
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
# Parameters
|
|
121
|
+
params = (("period", 30),)
|
|
122
|
+
# Plot on main chart by default
|
|
123
|
+
plotinfo = {"subplot": False}
|
|
124
|
+
|
|
125
|
+
def __init__(self):
|
|
126
|
+
"""Initialize moving average and set minimum period"""
|
|
127
|
+
super().__init__()
|
|
128
|
+
|
|
129
|
+
# CRITICAL FIX: Inherit minperiod from data source BEFORE adding own period
|
|
130
|
+
# This ensures nested indicators (like EMA applied to MACD line) properly accumulate minperiods
|
|
131
|
+
if hasattr(self, "datas") and self.datas:
|
|
132
|
+
data_minperiods = [getattr(d, "_minperiod", 1) for d in self.datas if d is not None]
|
|
133
|
+
if data_minperiods:
|
|
134
|
+
data_max = max(data_minperiods)
|
|
135
|
+
if data_max > self._minperiod:
|
|
136
|
+
self._minperiod = data_max
|
|
137
|
+
|
|
138
|
+
# CRITICAL FIX: Set the minimum period based on the period parameter
|
|
139
|
+
# This ensures the indicator doesn't start calculating until enough data is available
|
|
140
|
+
self.addminperiod(self.p.period)
|
|
141
|
+
|
|
142
|
+
def __init_subclass__(cls, **kwargs):
|
|
143
|
+
"""Register moving average classes automatically"""
|
|
144
|
+
super().__init_subclass__(**kwargs)
|
|
145
|
+
# Register any MovingAverage with the placeholder to allow the automatic
|
|
146
|
+
# creation of envelopes and oscillators
|
|
147
|
+
MovingAverage.register(cls)
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""MACD Indicator Module - Moving Average Convergence Divergence.
|
|
3
|
+
|
|
4
|
+
This module provides the MACD (Moving Average Convergence Divergence)
|
|
5
|
+
indicator developed by Gerald Appel in the 1970s for trend following.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
MACD: MACD indicator with signal line.
|
|
9
|
+
MACDHisto: MACD with histogram (alias: MACDHistogram).
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
class MyStrategy(bt.Strategy):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.macd = bt.indicators.MACD(self.data)
|
|
15
|
+
self.macd_hist = bt.indicators.MACDHisto(self.data)
|
|
16
|
+
|
|
17
|
+
def next(self):
|
|
18
|
+
# MACD crossover strategy
|
|
19
|
+
if self.macd.macd[0] > self.macd.signal[0]:
|
|
20
|
+
self.buy()
|
|
21
|
+
elif self.macd.macd[0] < self.macd.signal[0]:
|
|
22
|
+
self.sell()
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import math
|
|
26
|
+
|
|
27
|
+
from . import Indicator, MovAv
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _finite(value):
|
|
31
|
+
return value is not None and not (isinstance(value, float) and not math.isfinite(value))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class MACD(Indicator):
|
|
35
|
+
"""
|
|
36
|
+
Moving Average Convergence Divergence. Defined by Gerald Appel in the 70s.
|
|
37
|
+
|
|
38
|
+
It measures the distance of a short and a long term moving average to
|
|
39
|
+
try to identify the trend.
|
|
40
|
+
|
|
41
|
+
A second lagging moving average over the convergence-divergence should
|
|
42
|
+
provide a "signal" upon being crossed by the macd
|
|
43
|
+
|
|
44
|
+
Formula:
|
|
45
|
+
- macd = ema(data, me1_period) - ema(data, me2_period)
|
|
46
|
+
- signal = ema(macd, signal_period)
|
|
47
|
+
|
|
48
|
+
See:
|
|
49
|
+
- http://en.wikipedia.org/wiki/MACD
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
lines = (
|
|
53
|
+
"macd",
|
|
54
|
+
"signal",
|
|
55
|
+
)
|
|
56
|
+
params = (
|
|
57
|
+
("period_me1", 12),
|
|
58
|
+
("period_me2", 26),
|
|
59
|
+
("period_signal", 9),
|
|
60
|
+
("movav", MovAv.Exponential),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
plotinfo = {"plothlines": [0.0]}
|
|
64
|
+
plotlines = {"signal": {"ls": "--"}}
|
|
65
|
+
|
|
66
|
+
def _plotlabel(self):
|
|
67
|
+
plabels = super()._plotlabel()
|
|
68
|
+
if self.p.isdefault("movav"):
|
|
69
|
+
plabels.remove(self.p.movav)
|
|
70
|
+
return plabels
|
|
71
|
+
|
|
72
|
+
def __init__(self):
|
|
73
|
+
"""Initialize the MACD indicator.
|
|
74
|
+
|
|
75
|
+
Creates moving averages and sets up signal line calculation.
|
|
76
|
+
"""
|
|
77
|
+
super().__init__()
|
|
78
|
+
# Store the EMAs as sub-indicators
|
|
79
|
+
self.me1 = self.p.movav(self.data, period=self.p.period_me1)
|
|
80
|
+
self.me2 = self.p.movav(self.data, period=self.p.period_me2)
|
|
81
|
+
# Preserve master's aliases without adding extra indicator output lines.
|
|
82
|
+
self.lines.me1 = self.me1
|
|
83
|
+
self.lines.me2 = self.me2
|
|
84
|
+
|
|
85
|
+
# Calculate minperiod
|
|
86
|
+
self.macd_minperiod = max(self.p.period_me1, self.p.period_me2)
|
|
87
|
+
signal_minperiod = self.macd_minperiod + self.p.period_signal - 1
|
|
88
|
+
self._minperiod = max(self._minperiod, signal_minperiod)
|
|
89
|
+
|
|
90
|
+
# CRITICAL FIX: Propagate minperiod to lines so that other indicators
|
|
91
|
+
# using these lines as data sources will inherit the correct minperiod
|
|
92
|
+
for line in self.lines:
|
|
93
|
+
line.updateminperiod(self._minperiod)
|
|
94
|
+
|
|
95
|
+
# Signal line alpha for EMA calculation
|
|
96
|
+
self.signal_alpha = 2.0 / (1.0 + self.p.period_signal)
|
|
97
|
+
self.signal_alpha1 = 1.0 - self.signal_alpha
|
|
98
|
+
|
|
99
|
+
def prenext(self):
|
|
100
|
+
"""Calculate MACD during warmup period.
|
|
101
|
+
|
|
102
|
+
Ensures MACD values are available for signal line seeding.
|
|
103
|
+
"""
|
|
104
|
+
try:
|
|
105
|
+
me1_val = self.me1[0]
|
|
106
|
+
me2_val = self.me2[0]
|
|
107
|
+
except (IndexError, TypeError):
|
|
108
|
+
self.lines.macd[0] = float("nan")
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
if not (_finite(me1_val) and _finite(me2_val)):
|
|
112
|
+
self.lines.macd[0] = float("nan")
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
self.lines.macd[0] = me1_val - me2_val
|
|
116
|
+
|
|
117
|
+
def nextstart(self):
|
|
118
|
+
"""Calculate MACD and seed signal line on first valid bar.
|
|
119
|
+
|
|
120
|
+
Computes MACD and seeds signal with SMA of MACD values.
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
me1_val = self.me1[0]
|
|
124
|
+
me2_val = self.me2[0]
|
|
125
|
+
except (IndexError, TypeError):
|
|
126
|
+
self.lines.macd[0] = float("nan")
|
|
127
|
+
self.lines.signal[0] = float("nan")
|
|
128
|
+
return
|
|
129
|
+
|
|
130
|
+
if not (_finite(me1_val) and _finite(me2_val)):
|
|
131
|
+
self.lines.macd[0] = float("nan")
|
|
132
|
+
self.lines.signal[0] = float("nan")
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
macd_val = me1_val - me2_val
|
|
136
|
+
self.lines.macd[0] = macd_val
|
|
137
|
+
# # Seed signal with MACD value
|
|
138
|
+
# self.lines.signal[0] = macd_val
|
|
139
|
+
signal_period = self.p.period_signal
|
|
140
|
+
macd_sum = 0.0
|
|
141
|
+
macd_count = 0
|
|
142
|
+
for i in range(signal_period):
|
|
143
|
+
try:
|
|
144
|
+
value = self.lines.macd[-i]
|
|
145
|
+
except (IndexError, TypeError):
|
|
146
|
+
value = float("nan")
|
|
147
|
+
if _finite(value):
|
|
148
|
+
macd_sum += value
|
|
149
|
+
macd_count += 1
|
|
150
|
+
self.lines.signal[0] = macd_sum / macd_count if macd_count else macd_val
|
|
151
|
+
|
|
152
|
+
def next(self):
|
|
153
|
+
"""Calculate MACD and signal line for the current bar.
|
|
154
|
+
|
|
155
|
+
MACD = me1 - me2
|
|
156
|
+
Signal = EMA(MACD)
|
|
157
|
+
"""
|
|
158
|
+
try:
|
|
159
|
+
me1_val = self.me1[0]
|
|
160
|
+
me2_val = self.me2[0]
|
|
161
|
+
except (IndexError, TypeError):
|
|
162
|
+
self.lines.macd[0] = float("nan")
|
|
163
|
+
self.lines.signal[0] = float("nan")
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
if not (_finite(me1_val) and _finite(me2_val)):
|
|
167
|
+
self.lines.macd[0] = float("nan")
|
|
168
|
+
self.lines.signal[0] = float("nan")
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
macd_val = me1_val - me2_val
|
|
172
|
+
self.lines.macd[0] = macd_val
|
|
173
|
+
# Calculate signal = EMA of MACD
|
|
174
|
+
try:
|
|
175
|
+
previous_signal = self.lines.signal[-1]
|
|
176
|
+
except (IndexError, TypeError):
|
|
177
|
+
previous_signal = macd_val
|
|
178
|
+
|
|
179
|
+
if not _finite(previous_signal):
|
|
180
|
+
previous_signal = macd_val
|
|
181
|
+
|
|
182
|
+
self.lines.signal[0] = previous_signal * self.signal_alpha1 + macd_val * self.signal_alpha
|
|
183
|
+
|
|
184
|
+
def once(self, start, end):
|
|
185
|
+
"""Calculate MACD in runonce mode"""
|
|
186
|
+
me1_array = self.me1.lines[0].array
|
|
187
|
+
me2_array = self.me2.lines[0].array
|
|
188
|
+
macd_array = self.lines.macd.array
|
|
189
|
+
signal_array = self.lines.signal.array
|
|
190
|
+
|
|
191
|
+
signal_alpha = self.signal_alpha
|
|
192
|
+
signal_alpha1 = self.signal_alpha1
|
|
193
|
+
macd_minperiod = self.macd_minperiod
|
|
194
|
+
signal_period = self.p.period_signal
|
|
195
|
+
|
|
196
|
+
# Ensure arrays are properly sized
|
|
197
|
+
while len(macd_array) < end:
|
|
198
|
+
macd_array.append(float("nan"))
|
|
199
|
+
while len(signal_array) < end:
|
|
200
|
+
signal_array.append(float("nan"))
|
|
201
|
+
|
|
202
|
+
# Pre-fill warmup period with NaN
|
|
203
|
+
for i in range(min(macd_minperiod - 1, len(me1_array))):
|
|
204
|
+
macd_array[i] = float("nan")
|
|
205
|
+
signal_array[i] = float("nan")
|
|
206
|
+
|
|
207
|
+
# Calculate MACD values for all data points from macd_minperiod onwards
|
|
208
|
+
for i in range(macd_minperiod - 1, min(end, len(me1_array), len(me2_array))):
|
|
209
|
+
me1_val = me1_array[i]
|
|
210
|
+
me2_val = me2_array[i]
|
|
211
|
+
|
|
212
|
+
# Handle NaN values
|
|
213
|
+
if isinstance(me1_val, float) and math.isnan(me1_val):
|
|
214
|
+
macd_array[i] = float("nan")
|
|
215
|
+
continue
|
|
216
|
+
if isinstance(me2_val, float) and math.isnan(me2_val):
|
|
217
|
+
macd_array[i] = float("nan")
|
|
218
|
+
continue
|
|
219
|
+
|
|
220
|
+
macd_array[i] = me1_val - me2_val
|
|
221
|
+
|
|
222
|
+
# Calculate signal line (EMA of MACD)
|
|
223
|
+
signal_start = macd_minperiod + signal_period - 2
|
|
224
|
+
|
|
225
|
+
# Pre-fill signal warmup with NaN
|
|
226
|
+
for i in range(macd_minperiod - 1, min(signal_start, len(signal_array))):
|
|
227
|
+
signal_array[i] = float("nan")
|
|
228
|
+
|
|
229
|
+
# Seed signal with SMA of first signal_period MACD values
|
|
230
|
+
if signal_start < len(macd_array) and signal_start >= 0:
|
|
231
|
+
seed_sum = 0.0
|
|
232
|
+
seed_count = 0
|
|
233
|
+
for j in range(macd_minperiod - 1, signal_start + 1):
|
|
234
|
+
if j < len(macd_array):
|
|
235
|
+
val = macd_array[j]
|
|
236
|
+
if not (isinstance(val, float) and math.isnan(val)):
|
|
237
|
+
seed_sum += val
|
|
238
|
+
seed_count += 1
|
|
239
|
+
prev_signal = seed_sum / seed_count if seed_count > 0 else 0.0
|
|
240
|
+
signal_array[signal_start] = prev_signal
|
|
241
|
+
else:
|
|
242
|
+
prev_signal = 0.0
|
|
243
|
+
|
|
244
|
+
# Calculate signal EMA for all subsequent data points
|
|
245
|
+
for i in range(signal_start + 1, min(end, len(macd_array))):
|
|
246
|
+
macd_val = macd_array[i]
|
|
247
|
+
if isinstance(macd_val, float) and math.isnan(macd_val):
|
|
248
|
+
signal_array[i] = float("nan")
|
|
249
|
+
continue
|
|
250
|
+
|
|
251
|
+
prev_signal = prev_signal * signal_alpha1 + macd_val * signal_alpha
|
|
252
|
+
signal_array[i] = prev_signal
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class MACDHisto(MACD):
|
|
256
|
+
"""
|
|
257
|
+
Subclass of MACD which adds a "histogram" of the difference between the
|
|
258
|
+
macd and signal lines
|
|
259
|
+
|
|
260
|
+
Formula:
|
|
261
|
+
- histo = macd - signal
|
|
262
|
+
|
|
263
|
+
See:
|
|
264
|
+
- http://en.wikipedia.org/wiki/MACD
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
alias = ("MACDHistogram",)
|
|
268
|
+
|
|
269
|
+
lines = ("histo",)
|
|
270
|
+
plotlines = {"histo": {"_method": "bar", "alpha": 0.50, "width": 1.0}}
|
|
271
|
+
|
|
272
|
+
def __init__(self):
|
|
273
|
+
"""Initialize the MACD Histogram indicator.
|
|
274
|
+
|
|
275
|
+
Extends MACD with histogram line.
|
|
276
|
+
"""
|
|
277
|
+
super().__init__()
|
|
278
|
+
|
|
279
|
+
def nextstart(self):
|
|
280
|
+
"""Calculate MACD Histogram on first valid bar.
|
|
281
|
+
|
|
282
|
+
Histogram = MACD - Signal.
|
|
283
|
+
"""
|
|
284
|
+
super().nextstart()
|
|
285
|
+
self.lines.histo[0] = self.lines.macd[0] - self.lines.signal[0]
|
|
286
|
+
|
|
287
|
+
def next(self):
|
|
288
|
+
"""Calculate MACD Histogram for the current bar.
|
|
289
|
+
|
|
290
|
+
Histogram = MACD - Signal.
|
|
291
|
+
"""
|
|
292
|
+
super().next()
|
|
293
|
+
self.lines.histo[0] = self.lines.macd[0] - self.lines.signal[0]
|
|
294
|
+
|
|
295
|
+
def once(self, start, end):
|
|
296
|
+
"""Calculate MACD Histogram in runonce mode.
|
|
297
|
+
|
|
298
|
+
Computes histogram as MACD minus signal across all bars.
|
|
299
|
+
"""
|
|
300
|
+
super().once(start, end)
|
|
301
|
+
macd_array = self.lines.macd.array
|
|
302
|
+
signal_array = self.lines.signal.array
|
|
303
|
+
histo_array = self.lines.histo.array
|
|
304
|
+
|
|
305
|
+
# Ensure histo array is sized
|
|
306
|
+
while len(histo_array) < end:
|
|
307
|
+
histo_array.append(float("nan"))
|
|
308
|
+
|
|
309
|
+
# Calculate histogram
|
|
310
|
+
for i in range(start, min(end, len(macd_array), len(signal_array))):
|
|
311
|
+
macd_val = macd_array[i] if i < len(macd_array) else 0.0
|
|
312
|
+
signal_val = signal_array[i] if i < len(signal_array) else 0.0
|
|
313
|
+
|
|
314
|
+
if (
|
|
315
|
+
isinstance(macd_val, float)
|
|
316
|
+
and math.isnan(macd_val)
|
|
317
|
+
or isinstance(signal_val, float)
|
|
318
|
+
and math.isnan(signal_val)
|
|
319
|
+
):
|
|
320
|
+
histo_array[i] = float("nan")
|
|
321
|
+
else:
|
|
322
|
+
histo_array[i] = macd_val - signal_val
|