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,475 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Envelope Indicator Module - Envelope bands around indicators.
|
|
3
|
+
|
|
4
|
+
This module provides envelope indicators that create upper and lower bands
|
|
5
|
+
around an indicator at a specified percentage.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
EnvelopeMixIn: MixIn class for creating envelope bands.
|
|
9
|
+
_EnvelopeBase: Base class for envelope indicators.
|
|
10
|
+
Envelope: Envelope bands around data source.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
class MyStrategy(bt.Strategy):
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.sma_env = bt.indicators.SMAEnvelope(self.data.close, period=20, perc=2.5)
|
|
16
|
+
|
|
17
|
+
def next(self):
|
|
18
|
+
if self.data.close[0] < self.sma_env.bot[0]:
|
|
19
|
+
self.buy()
|
|
20
|
+
elif self.data.close[0] > self.sma_env.top[0]:
|
|
21
|
+
self.sell()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import sys
|
|
25
|
+
|
|
26
|
+
from . import Indicator, MovingAverage
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PlotLineAttr:
|
|
30
|
+
"""Plot line attribute container for envelope visualization."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, **kwargs):
|
|
33
|
+
"""Initialize plot line attributes.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
**kwargs: Arbitrary plot line attributes.
|
|
37
|
+
"""
|
|
38
|
+
for k, v in kwargs.items():
|
|
39
|
+
setattr(self, k, v)
|
|
40
|
+
|
|
41
|
+
def _get(self, key, default=None):
|
|
42
|
+
"""Get attribute value for plotting system compatibility.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
key: Attribute name to retrieve.
|
|
46
|
+
default: Default value if key not found.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Attribute value or default.
|
|
50
|
+
"""
|
|
51
|
+
return getattr(self, key, default)
|
|
52
|
+
|
|
53
|
+
def get(self, key, default=None):
|
|
54
|
+
"""Standard get method for compatibility.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
key: Attribute name to retrieve.
|
|
58
|
+
default: Default value if key not found.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Attribute value or default.
|
|
62
|
+
"""
|
|
63
|
+
return getattr(self, key, default)
|
|
64
|
+
|
|
65
|
+
def __contains__(self, key):
|
|
66
|
+
"""Check if attribute exists.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
key: Attribute name to check.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
True if attribute exists, False otherwise.
|
|
73
|
+
"""
|
|
74
|
+
return hasattr(self, key)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Decorate other indicators, set upper and lower percentage limits for indicator values
|
|
78
|
+
class EnvelopeMixIn:
|
|
79
|
+
"""
|
|
80
|
+
MixIn class to create a subclass with another indicator. The main line of
|
|
81
|
+
that indicator will be surrounded by an upper and lower band separated a
|
|
82
|
+
given "percentage" from the input main line
|
|
83
|
+
|
|
84
|
+
The usage is:
|
|
85
|
+
|
|
86
|
+
- Class XXXEnvelope(XXX, EnvelopeMixIn)
|
|
87
|
+
|
|
88
|
+
Formula:
|
|
89
|
+
- 'line' (inherited from XXX)
|
|
90
|
+
- top = 'line' * (1 + perc)
|
|
91
|
+
- bot = 'line' * (1 - perc)
|
|
92
|
+
|
|
93
|
+
See also:
|
|
94
|
+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_average_envelopes
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
lines = (
|
|
98
|
+
"top",
|
|
99
|
+
"bot",
|
|
100
|
+
)
|
|
101
|
+
params = (("perc", 2.5),)
|
|
102
|
+
|
|
103
|
+
# CRITICAL FIX: Convert plotlines from dict to object with _get method for plotting compatibility
|
|
104
|
+
class PlotLinesObj:
|
|
105
|
+
"""Plot lines configuration object for envelope visualization."""
|
|
106
|
+
|
|
107
|
+
def __init__(self):
|
|
108
|
+
"""Initialize plot lines with top and bot attributes."""
|
|
109
|
+
self.top = PlotLineAttr(_samecolor=True)
|
|
110
|
+
self.bot = PlotLineAttr(_samecolor=True)
|
|
111
|
+
|
|
112
|
+
def _get(self, key, default=None):
|
|
113
|
+
"""Get plot line attribute for plotting system.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
key: Attribute name.
|
|
117
|
+
default: Default value if not found.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Attribute value or default.
|
|
121
|
+
"""
|
|
122
|
+
return getattr(self, key, default)
|
|
123
|
+
|
|
124
|
+
def get(self, key, default=None):
|
|
125
|
+
"""Standard get method for compatibility.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
key: Attribute name.
|
|
129
|
+
default: Default value if not found.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Attribute value or default.
|
|
133
|
+
"""
|
|
134
|
+
return getattr(self, key, default)
|
|
135
|
+
|
|
136
|
+
def __contains__(self, key):
|
|
137
|
+
"""Check if attribute exists.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
key: Attribute name to check.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
True if attribute exists, False otherwise.
|
|
144
|
+
"""
|
|
145
|
+
return hasattr(self, key)
|
|
146
|
+
|
|
147
|
+
plotlines = PlotLinesObj()
|
|
148
|
+
|
|
149
|
+
# CRITICAL FIX: Add complete plotinfo object with all required attributes
|
|
150
|
+
class PlotInfoObj:
|
|
151
|
+
"""Plot information configuration object for envelope visualization."""
|
|
152
|
+
|
|
153
|
+
def __init__(self):
|
|
154
|
+
"""Initialize plot info with default envelope settings."""
|
|
155
|
+
self.subplot = False
|
|
156
|
+
self.plot = True
|
|
157
|
+
self.plotname = ""
|
|
158
|
+
self.plotskip = False
|
|
159
|
+
self.plotabove = False
|
|
160
|
+
self.plotlinelabels = False
|
|
161
|
+
self.plotlinevalues = True
|
|
162
|
+
self.plotvaluetags = True
|
|
163
|
+
self.plotymargin = 0.0
|
|
164
|
+
self.plotyhlines = []
|
|
165
|
+
self.plotyticks = []
|
|
166
|
+
self.plothlines = []
|
|
167
|
+
self.plotforce = False
|
|
168
|
+
self.plotmaster = None
|
|
169
|
+
self.legendloc = None # CRITICAL: Add the missing legendloc attribute
|
|
170
|
+
|
|
171
|
+
def _get(self, key, default=None):
|
|
172
|
+
"""Get plot info attribute for plotting system.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
key: Attribute name.
|
|
176
|
+
default: Default value if not found.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
Attribute value or default.
|
|
180
|
+
"""
|
|
181
|
+
return getattr(self, key, default)
|
|
182
|
+
|
|
183
|
+
def get(self, key, default=None):
|
|
184
|
+
"""Standard get method for compatibility.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
key: Attribute name.
|
|
188
|
+
default: Default value if not found.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Attribute value or default.
|
|
192
|
+
"""
|
|
193
|
+
return getattr(self, key, default)
|
|
194
|
+
|
|
195
|
+
def __contains__(self, key):
|
|
196
|
+
"""Check if attribute exists.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
key: Attribute name to check.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
True if attribute exists, False otherwise.
|
|
203
|
+
"""
|
|
204
|
+
return hasattr(self, key)
|
|
205
|
+
|
|
206
|
+
plotinfo = PlotInfoObj()
|
|
207
|
+
|
|
208
|
+
def __init__(self):
|
|
209
|
+
"""Initialize the envelope mix-in.
|
|
210
|
+
|
|
211
|
+
Calculates percentage value for band width.
|
|
212
|
+
"""
|
|
213
|
+
# CRITICAL FIX: Call super().__init__() first to ensure params and lines are initialized
|
|
214
|
+
super().__init__()
|
|
215
|
+
|
|
216
|
+
# Now we can safely use self.p.perc and self.lines[0]
|
|
217
|
+
# Check if perc parameter exists, use default if not
|
|
218
|
+
perc_value = getattr(self.p, "perc", 2.5)
|
|
219
|
+
if perc_value is None:
|
|
220
|
+
perc_value = 2.5
|
|
221
|
+
self._perc = perc_value / 100.0
|
|
222
|
+
|
|
223
|
+
def next(self):
|
|
224
|
+
"""Calculate envelope bands for the current bar.
|
|
225
|
+
|
|
226
|
+
top = base * (1 + perc)
|
|
227
|
+
bot = base * (1 - perc)
|
|
228
|
+
"""
|
|
229
|
+
base_val = self.lines[0][0]
|
|
230
|
+
self.lines.top[0] = base_val * (1.0 + self._perc)
|
|
231
|
+
self.lines.bot[0] = base_val * (1.0 - self._perc)
|
|
232
|
+
|
|
233
|
+
def once(self, start, end):
|
|
234
|
+
"""Calculate envelope bands in runonce mode.
|
|
235
|
+
|
|
236
|
+
Computes top and bot bands as percentage of base value.
|
|
237
|
+
"""
|
|
238
|
+
import math
|
|
239
|
+
|
|
240
|
+
base_array = self.lines[0].array
|
|
241
|
+
top_array = self.lines.top.array
|
|
242
|
+
bot_array = self.lines.bot.array
|
|
243
|
+
perc = self._perc
|
|
244
|
+
|
|
245
|
+
for arr in [top_array, bot_array]:
|
|
246
|
+
while len(arr) < end:
|
|
247
|
+
arr.append(float("nan"))
|
|
248
|
+
|
|
249
|
+
for i in range(start, min(end, len(base_array))):
|
|
250
|
+
base_val = base_array[i] if i < len(base_array) else 0.0
|
|
251
|
+
if isinstance(base_val, float) and math.isnan(base_val):
|
|
252
|
+
top_array[i] = float("nan")
|
|
253
|
+
bot_array[i] = float("nan")
|
|
254
|
+
else:
|
|
255
|
+
top_array[i] = base_val * (1.0 + perc)
|
|
256
|
+
bot_array[i] = base_val * (1.0 - perc)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# Base class
|
|
260
|
+
class _EnvelopeBase(Indicator):
|
|
261
|
+
lines = ("src",)
|
|
262
|
+
|
|
263
|
+
# CRITICAL FIX: Add complete plotinfo object with all required attributes
|
|
264
|
+
class PlotInfoObjBase:
|
|
265
|
+
"""Plot information configuration for envelope base class."""
|
|
266
|
+
|
|
267
|
+
def __init__(self):
|
|
268
|
+
"""Initialize plot info with default settings."""
|
|
269
|
+
self.subplot = False
|
|
270
|
+
self.plot = True
|
|
271
|
+
self.plotname = ""
|
|
272
|
+
self.plotskip = False
|
|
273
|
+
self.plotabove = False
|
|
274
|
+
self.plotlinelabels = False
|
|
275
|
+
self.plotlinevalues = True
|
|
276
|
+
self.plotvaluetags = True
|
|
277
|
+
self.plotymargin = 0.0
|
|
278
|
+
self.plotyhlines = []
|
|
279
|
+
self.plotyticks = []
|
|
280
|
+
self.plothlines = []
|
|
281
|
+
self.plotforce = False
|
|
282
|
+
self.plotmaster = None
|
|
283
|
+
self.legendloc = None # CRITICAL: Add the missing legendloc attribute
|
|
284
|
+
|
|
285
|
+
def _get(self, key, default=None):
|
|
286
|
+
"""Get plot info attribute for plotting system.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
key: Attribute name.
|
|
290
|
+
default: Default value if not found.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Attribute value or default.
|
|
294
|
+
"""
|
|
295
|
+
return getattr(self, key, default)
|
|
296
|
+
|
|
297
|
+
def get(self, key, default=None):
|
|
298
|
+
"""Standard get method for compatibility.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
key: Attribute name.
|
|
302
|
+
default: Default value if not found.
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Attribute value or default.
|
|
306
|
+
"""
|
|
307
|
+
return getattr(self, key, default)
|
|
308
|
+
|
|
309
|
+
def __contains__(self, key):
|
|
310
|
+
"""Check if attribute exists.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
key: Attribute name to check.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
True if attribute exists, False otherwise.
|
|
317
|
+
"""
|
|
318
|
+
return hasattr(self, key)
|
|
319
|
+
|
|
320
|
+
plotinfo = PlotInfoObjBase()
|
|
321
|
+
|
|
322
|
+
# Do not replot the data line
|
|
323
|
+
# CRITICAL FIX: Convert plotlines from dict to object with _get method for plotting compatibility
|
|
324
|
+
class PlotLinesObjBase:
|
|
325
|
+
"""Plot lines configuration for envelope base class."""
|
|
326
|
+
|
|
327
|
+
def __init__(self):
|
|
328
|
+
"""Initialize plot lines with src skipped from plotting."""
|
|
329
|
+
self.src = PlotLineAttr(_plotskip=True)
|
|
330
|
+
|
|
331
|
+
def _get(self, key, default=None):
|
|
332
|
+
"""Get plot line attribute for plotting system.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
key: Attribute name.
|
|
336
|
+
default: Default value if not found.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
Attribute value or default.
|
|
340
|
+
"""
|
|
341
|
+
return getattr(self, key, default)
|
|
342
|
+
|
|
343
|
+
def get(self, key, default=None):
|
|
344
|
+
"""Standard get method for compatibility.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
key: Attribute name.
|
|
348
|
+
default: Default value if not found.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
Attribute value or default.
|
|
352
|
+
"""
|
|
353
|
+
return getattr(self, key, default)
|
|
354
|
+
|
|
355
|
+
def __contains__(self, key):
|
|
356
|
+
"""Check if attribute exists.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
key: Attribute name to check.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
True if attribute exists, False otherwise.
|
|
363
|
+
"""
|
|
364
|
+
return hasattr(self, key)
|
|
365
|
+
|
|
366
|
+
plotlines = PlotLinesObjBase()
|
|
367
|
+
|
|
368
|
+
def __init__(self):
|
|
369
|
+
"""Initialize the envelope base indicator."""
|
|
370
|
+
super().__init__()
|
|
371
|
+
|
|
372
|
+
def next(self):
|
|
373
|
+
"""Pass data through to src line.
|
|
374
|
+
|
|
375
|
+
Copies data value to src line.
|
|
376
|
+
"""
|
|
377
|
+
self.lines.src[0] = self.data[0]
|
|
378
|
+
|
|
379
|
+
def once(self, start, end):
|
|
380
|
+
"""Pass data through in runonce mode.
|
|
381
|
+
|
|
382
|
+
Copies data values to src line across all bars.
|
|
383
|
+
"""
|
|
384
|
+
darray = self.data.array
|
|
385
|
+
larray = self.lines.src.array
|
|
386
|
+
|
|
387
|
+
while len(larray) < end:
|
|
388
|
+
larray.append(float("nan"))
|
|
389
|
+
|
|
390
|
+
for i in range(start, min(end, len(darray))):
|
|
391
|
+
larray[i] = darray[i] if i < len(darray) else 0.0
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
class Envelope(_EnvelopeBase, EnvelopeMixIn):
|
|
395
|
+
"""
|
|
396
|
+
It creates envelope bands separated from the source data by a given
|
|
397
|
+
percentage
|
|
398
|
+
|
|
399
|
+
Formula:
|
|
400
|
+
- src = datasource
|
|
401
|
+
- top = src * (1 + perc)
|
|
402
|
+
- bot = src * (1 - perc)
|
|
403
|
+
|
|
404
|
+
See also:
|
|
405
|
+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_average_envelopes
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
# Automatic creation of Moving Average Envelope classes
|
|
410
|
+
|
|
411
|
+
for movav in MovingAverage._movavs[0:]:
|
|
412
|
+
_newclsdoc = """
|
|
413
|
+
%s and envelope bands separated "perc" from it
|
|
414
|
+
|
|
415
|
+
Formula:
|
|
416
|
+
- %s (from %s)
|
|
417
|
+
- top = %s * (1 + perc)
|
|
418
|
+
- bot = %s * (1 - perc)
|
|
419
|
+
|
|
420
|
+
See also:
|
|
421
|
+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_average_envelopes
|
|
422
|
+
"""
|
|
423
|
+
# Skip aliases - they will be created automatically
|
|
424
|
+
if getattr(movav, "aliased", ""):
|
|
425
|
+
continue
|
|
426
|
+
|
|
427
|
+
movname = movav.__name__
|
|
428
|
+
# Handle both tuple lines and Lines objects after refactoring
|
|
429
|
+
try:
|
|
430
|
+
if hasattr(movav.lines, "_getlinealias"):
|
|
431
|
+
# It's a Lines object
|
|
432
|
+
linename = movav.lines._getlinealias(0)
|
|
433
|
+
elif isinstance(movav.lines, (tuple, list)) and movav.lines:
|
|
434
|
+
# It's a tuple/list of line names
|
|
435
|
+
linename = movav.lines[0]
|
|
436
|
+
elif isinstance(movav.lines, dict):
|
|
437
|
+
# It's a dictionary - extract first key as line name
|
|
438
|
+
if movav.lines:
|
|
439
|
+
try:
|
|
440
|
+
# Handle the case when trying to access _get on dict object
|
|
441
|
+
if hasattr(movav.lines, "_get"):
|
|
442
|
+
linename = movav.lines._get(0)
|
|
443
|
+
else:
|
|
444
|
+
# Use first key in the dictionary
|
|
445
|
+
linename = next(iter(movav.lines))
|
|
446
|
+
except (AttributeError, StopIteration, TypeError, KeyError):
|
|
447
|
+
# Fallback to the lower case name of the class
|
|
448
|
+
linename = movav.__name__.lower()
|
|
449
|
+
else:
|
|
450
|
+
linename = movav.__name__.lower()
|
|
451
|
+
else:
|
|
452
|
+
# Fallback to first line name or class name
|
|
453
|
+
linename = movav.__name__.lower()
|
|
454
|
+
except (AttributeError, IndexError, KeyError, TypeError):
|
|
455
|
+
# Ultimate fallback - use class name if all else fails
|
|
456
|
+
linename = movav.__name__.lower()
|
|
457
|
+
|
|
458
|
+
newclsname = movname + "Envelope"
|
|
459
|
+
|
|
460
|
+
newaliases = []
|
|
461
|
+
for alias in getattr(movav, "alias", []):
|
|
462
|
+
for suffix in ["Envelope"]:
|
|
463
|
+
newaliases.append(alias + suffix)
|
|
464
|
+
|
|
465
|
+
newclsdoc = _newclsdoc % (movname, linename, movname, linename, linename)
|
|
466
|
+
|
|
467
|
+
newclsdct = {
|
|
468
|
+
"__doc__": newclsdoc,
|
|
469
|
+
"__module__": EnvelopeMixIn.__module__,
|
|
470
|
+
"_notregister": True,
|
|
471
|
+
"alias": newaliases,
|
|
472
|
+
}
|
|
473
|
+
newcls = type(str(newclsname), (movav, EnvelopeMixIn), newclsdct)
|
|
474
|
+
module = sys.modules[EnvelopeMixIn.__module__]
|
|
475
|
+
setattr(module, newclsname, newcls)
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""HaDelta Indicator Module - Heikin Ashi Delta indicator.
|
|
3
|
+
|
|
4
|
+
This module provides the HaDelta indicator defined by Dan Valcu
|
|
5
|
+
for measuring Heikin Ashi candle body differences.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
HaDelta: Heikin Ashi Delta indicator (aliases: haD, haDelta).
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
class MyStrategy(bt.Strategy):
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.hadelta = bt.indicators.HaDelta(self.data)
|
|
14
|
+
|
|
15
|
+
def next(self):
|
|
16
|
+
if self.hadelta.smoothed[0] > 0:
|
|
17
|
+
self.buy()
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from . import Indicator
|
|
21
|
+
from .sma import SMA
|
|
22
|
+
|
|
23
|
+
__all__ = ["HaDelta", "haD", "haDelta"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class HaDelta(Indicator):
|
|
27
|
+
"""Heikin Ashi Delta. Defined by Dan Valcu in his book "Heikin-Ashi: How to
|
|
28
|
+
Trade Without Candlestick Patterns ".
|
|
29
|
+
|
|
30
|
+
This indicator measures the difference between Heikin Ashi close and open of
|
|
31
|
+
Heikin Ashi candles, the body of the candle.
|
|
32
|
+
|
|
33
|
+
To get signals add haDelta smoothed by 3 period moving average.
|
|
34
|
+
|
|
35
|
+
For correct use, the data for the indicator must have been previously
|
|
36
|
+
passed by the Heikin Ahsi filter.
|
|
37
|
+
|
|
38
|
+
Formula:
|
|
39
|
+
- HaDelta = Heikin Ashi close - Heikin Ashi open
|
|
40
|
+
- smoothed = movav(haDelta, period)
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
alias = ("haD",)
|
|
45
|
+
|
|
46
|
+
lines = ("haDelta", "smoothed")
|
|
47
|
+
|
|
48
|
+
params = (
|
|
49
|
+
("period", 3),
|
|
50
|
+
("movav", SMA),
|
|
51
|
+
("autoheikin", True),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
plotinfo = {"subplot": True}
|
|
55
|
+
|
|
56
|
+
plotlines = {
|
|
57
|
+
"haDelta": {"color": "red"},
|
|
58
|
+
"smoothed": {"color": "grey", "_fill_gt": (0, "green"), "_fill_lt": (0, "red")},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
def __init__(self):
|
|
62
|
+
"""Initialize the HaDelta indicator.
|
|
63
|
+
|
|
64
|
+
Sets up Heikin Ashi calculation state if autoheikin is enabled.
|
|
65
|
+
"""
|
|
66
|
+
super().__init__()
|
|
67
|
+
|
|
68
|
+
self._autoheikin = self.p.autoheikin
|
|
69
|
+
# Store previous HA values for recursive calculation
|
|
70
|
+
self._prev_ha_close = 0.0
|
|
71
|
+
self._prev_ha_open = 0.0
|
|
72
|
+
self._first_bar = True
|
|
73
|
+
|
|
74
|
+
# Set minperiod = period + 1 to match expected behavior
|
|
75
|
+
self.addminperiod(self.p.period + 1)
|
|
76
|
+
|
|
77
|
+
def _calc_heikin_ashi(self):
|
|
78
|
+
"""Calculate Heikin Ashi values for current bar inline."""
|
|
79
|
+
if self._autoheikin:
|
|
80
|
+
# ha_close = (open + high + low + close) / 4
|
|
81
|
+
ha_close = (
|
|
82
|
+
self.data.open[0] + self.data.high[0] + self.data.low[0] + self.data.close[0]
|
|
83
|
+
) / 4.0
|
|
84
|
+
|
|
85
|
+
# ha_open = (prev_ha_open + prev_ha_close) / 2
|
|
86
|
+
if self._first_bar:
|
|
87
|
+
ha_open = (self.data.open[0] + self.data.close[0]) / 2.0
|
|
88
|
+
self._first_bar = False
|
|
89
|
+
else:
|
|
90
|
+
ha_open = (self._prev_ha_open + self._prev_ha_close) / 2.0
|
|
91
|
+
|
|
92
|
+
# Store for next bar
|
|
93
|
+
self._prev_ha_close = ha_close
|
|
94
|
+
self._prev_ha_open = ha_open
|
|
95
|
+
|
|
96
|
+
return ha_close - ha_open
|
|
97
|
+
return self.data.close[0] - self.data.open[0]
|
|
98
|
+
|
|
99
|
+
def prenext(self):
|
|
100
|
+
"""Calculate HaDelta during warmup period.
|
|
101
|
+
|
|
102
|
+
Computes haDelta but not smoothed values during warmup.
|
|
103
|
+
"""
|
|
104
|
+
# Calculate haDelta during warmup period
|
|
105
|
+
hd = self._calc_heikin_ashi()
|
|
106
|
+
self.lines.haDelta[0] = hd
|
|
107
|
+
|
|
108
|
+
def nextstart(self):
|
|
109
|
+
"""Calculate HaDelta and seed smoothed on first valid bar.
|
|
110
|
+
|
|
111
|
+
Computes haDelta and seeds smoothed with SMA of haDelta values.
|
|
112
|
+
"""
|
|
113
|
+
# First valid bar - calculate haDelta and seed smoothed with SMA
|
|
114
|
+
hd = self._calc_heikin_ashi()
|
|
115
|
+
self.lines.haDelta[0] = hd
|
|
116
|
+
|
|
117
|
+
# Seed smoothed with SMA of first period haDelta values
|
|
118
|
+
period = self.p.period
|
|
119
|
+
hd_sum = hd
|
|
120
|
+
for i in range(1, period):
|
|
121
|
+
hd_sum += self.lines.haDelta[-i]
|
|
122
|
+
self.lines.smoothed[0] = hd_sum / period
|
|
123
|
+
|
|
124
|
+
def next(self):
|
|
125
|
+
"""Calculate HaDelta and smoothed values for current bar.
|
|
126
|
+
|
|
127
|
+
haDelta = ha_close - ha_open
|
|
128
|
+
smoothed = SMA(haDelta, period)
|
|
129
|
+
"""
|
|
130
|
+
# Calculate haDelta = ha_close - ha_open
|
|
131
|
+
hd = self._calc_heikin_ashi()
|
|
132
|
+
self.lines.haDelta[0] = hd
|
|
133
|
+
|
|
134
|
+
# Calculate SMA of haDelta
|
|
135
|
+
period = self.p.period
|
|
136
|
+
hd_sum = hd
|
|
137
|
+
for i in range(1, period):
|
|
138
|
+
hd_sum += self.lines.haDelta[-i]
|
|
139
|
+
self.lines.smoothed[0] = hd_sum / period
|
|
140
|
+
|
|
141
|
+
def once(self, start, end):
|
|
142
|
+
"""Calculate HaDelta and smoothed in runonce mode.
|
|
143
|
+
|
|
144
|
+
Computes haDelta values and smoothed SMA across all bars.
|
|
145
|
+
"""
|
|
146
|
+
# Get data arrays
|
|
147
|
+
o_array = self.data.open.array
|
|
148
|
+
h_array = self.data.high.array
|
|
149
|
+
l_array = self.data.low.array
|
|
150
|
+
c_array = self.data.close.array
|
|
151
|
+
|
|
152
|
+
hd_array = self.lines.haDelta.array
|
|
153
|
+
sm_array = self.lines.smoothed.array
|
|
154
|
+
period = self.p.period
|
|
155
|
+
|
|
156
|
+
# Ensure arrays are properly sized
|
|
157
|
+
for arr in [hd_array, sm_array]:
|
|
158
|
+
while len(arr) < end:
|
|
159
|
+
arr.append(float("nan"))
|
|
160
|
+
|
|
161
|
+
data_end = min(end, len(o_array), len(h_array), len(l_array), len(c_array))
|
|
162
|
+
|
|
163
|
+
if self._autoheikin:
|
|
164
|
+
# Calculate HeikinAshi values inline
|
|
165
|
+
prev_ha_close = 0.0
|
|
166
|
+
prev_ha_open = 0.0
|
|
167
|
+
|
|
168
|
+
for i in range(data_end):
|
|
169
|
+
# ha_close = (open + high + low + close) / 4
|
|
170
|
+
ha_close = (o_array[i] + h_array[i] + l_array[i] + c_array[i]) / 4.0
|
|
171
|
+
|
|
172
|
+
# ha_open = (prev_ha_open + prev_ha_close) / 2
|
|
173
|
+
if i == 0:
|
|
174
|
+
ha_open = (o_array[i] + c_array[i]) / 2.0
|
|
175
|
+
else:
|
|
176
|
+
ha_open = (prev_ha_open + prev_ha_close) / 2.0
|
|
177
|
+
|
|
178
|
+
hd_array[i] = ha_close - ha_open
|
|
179
|
+
|
|
180
|
+
prev_ha_close = ha_close
|
|
181
|
+
prev_ha_open = ha_open
|
|
182
|
+
else:
|
|
183
|
+
for i in range(data_end):
|
|
184
|
+
hd_array[i] = c_array[i] - o_array[i]
|
|
185
|
+
|
|
186
|
+
# Calculate smoothed (SMA of haDelta)
|
|
187
|
+
for i in range(min(end, len(hd_array))):
|
|
188
|
+
if i < period - 1:
|
|
189
|
+
sm_array[i] = float("nan")
|
|
190
|
+
else:
|
|
191
|
+
hd_sum = 0.0
|
|
192
|
+
for j in range(period):
|
|
193
|
+
hd_sum += hd_array[i - j]
|
|
194
|
+
sm_array[i] = hd_sum / period
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
haD = HaDelta
|
|
198
|
+
haDelta = HaDelta # Alias for tests
|