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,436 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""SuperTrend indicator variants migrated from functional tests."""
|
|
3
|
+
|
|
4
|
+
from . import Indicator
|
|
5
|
+
from .atr import ATR
|
|
6
|
+
from .ema import EMA
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"AdaptiveSuperTrendIndicator",
|
|
10
|
+
"SuperTrendBandIndicator",
|
|
11
|
+
"SuperTrendBandsIndicator",
|
|
12
|
+
"SuperTrendCCIIndicator",
|
|
13
|
+
"SuperTrendIndicator",
|
|
14
|
+
"SupertrendIndicator",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SuperTrendIndicator(Indicator):
|
|
19
|
+
"""Classic SuperTrend with ``supertrend`` and ``direction`` lines."""
|
|
20
|
+
|
|
21
|
+
lines = ("supertrend", "direction")
|
|
22
|
+
params = {"period": 10, "multiplier": 3.0}
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
"""Build the ATR and ``(high + low) / 2`` series used by ``next``."""
|
|
26
|
+
self.atr = ATR(self.data, period=self.p.period)
|
|
27
|
+
self.hl2 = (self.data.high + self.data.low) / 2.0
|
|
28
|
+
|
|
29
|
+
def next(self):
|
|
30
|
+
"""Update the SuperTrend value and direction for the current bar.
|
|
31
|
+
|
|
32
|
+
Until the lookback window is full the SuperTrend equals
|
|
33
|
+
``hl2`` and the direction is ``1`` (up). Afterwards the
|
|
34
|
+
standard SuperTrend state machine is applied: when previously
|
|
35
|
+
bullish and the close dips below the prior SuperTrend, the
|
|
36
|
+
band flips to ``upper_band`` and direction becomes ``-1``;
|
|
37
|
+
otherwise the SuperTrend tracks the rising lower band. The
|
|
38
|
+
mirror logic applies when previously bearish.
|
|
39
|
+
"""
|
|
40
|
+
if len(self) < self.p.period + 1:
|
|
41
|
+
self.lines.supertrend[0] = self.hl2[0]
|
|
42
|
+
self.lines.direction[0] = 1
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
atr = self.atr[0]
|
|
46
|
+
hl2 = self.hl2[0]
|
|
47
|
+
upper_band = hl2 + self.p.multiplier * atr
|
|
48
|
+
lower_band = hl2 - self.p.multiplier * atr
|
|
49
|
+
prev_supertrend = self.lines.supertrend[-1]
|
|
50
|
+
prev_direction = self.lines.direction[-1]
|
|
51
|
+
|
|
52
|
+
if prev_direction == 1:
|
|
53
|
+
if self.data.close[0] < prev_supertrend:
|
|
54
|
+
self.lines.supertrend[0] = upper_band
|
|
55
|
+
self.lines.direction[0] = -1
|
|
56
|
+
else:
|
|
57
|
+
self.lines.supertrend[0] = max(lower_band, prev_supertrend)
|
|
58
|
+
self.lines.direction[0] = 1
|
|
59
|
+
else:
|
|
60
|
+
if self.data.close[0] > prev_supertrend:
|
|
61
|
+
self.lines.supertrend[0] = lower_band
|
|
62
|
+
self.lines.direction[0] = 1
|
|
63
|
+
else:
|
|
64
|
+
self.lines.supertrend[0] = min(upper_band, prev_supertrend)
|
|
65
|
+
self.lines.direction[0] = -1
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class SuperTrendBandIndicator(Indicator):
|
|
69
|
+
"""ATR SuperTrend variant with persistent upper/lower bands."""
|
|
70
|
+
|
|
71
|
+
lines = ("supertrend", "direction")
|
|
72
|
+
params = (("atr_period", 10), ("multiplier", 3.0))
|
|
73
|
+
|
|
74
|
+
def __init__(self):
|
|
75
|
+
"""Set up the ATR sub-indicator and the persistent band/direction state."""
|
|
76
|
+
self.atr = ATR(self.data, period=self.p.atr_period)
|
|
77
|
+
self._upper = None
|
|
78
|
+
self._lower = None
|
|
79
|
+
self._dir = 1
|
|
80
|
+
|
|
81
|
+
def next(self):
|
|
82
|
+
"""Update the persistent bands and direction for the current bar.
|
|
83
|
+
|
|
84
|
+
Upper and lower bands start as ``hl2 ± multiplier * ATR``,
|
|
85
|
+
then shrink when the previous close was on the opposite side
|
|
86
|
+
of the prior band (a classic SuperTrend non-widening rule).
|
|
87
|
+
The direction flips when the close crosses ``dn`` (was
|
|
88
|
+
bullish) or ``up`` (was bearish); the SuperTrend line itself
|
|
89
|
+
is the lower band in bullish mode and the upper band in
|
|
90
|
+
bearish mode.
|
|
91
|
+
"""
|
|
92
|
+
hl2 = (float(self.data.high[0]) + float(self.data.low[0])) / 2.0
|
|
93
|
+
atr_val = float(self.atr[0])
|
|
94
|
+
up = hl2 + self.p.multiplier * atr_val
|
|
95
|
+
dn = hl2 - self.p.multiplier * atr_val
|
|
96
|
+
|
|
97
|
+
if self._upper is not None:
|
|
98
|
+
up = min(up, self._upper) if float(self.data.close[-1]) > self._upper else up
|
|
99
|
+
dn = max(dn, self._lower) if float(self.data.close[-1]) < self._lower else dn
|
|
100
|
+
|
|
101
|
+
close = float(self.data.close[0])
|
|
102
|
+
if self._dir == 1:
|
|
103
|
+
if close < dn:
|
|
104
|
+
self._dir = -1
|
|
105
|
+
else:
|
|
106
|
+
if close > up:
|
|
107
|
+
self._dir = 1
|
|
108
|
+
|
|
109
|
+
self._upper = up
|
|
110
|
+
self._lower = dn
|
|
111
|
+
self.lines.supertrend[0] = dn if self._dir == 1 else up
|
|
112
|
+
self.lines.direction[0] = float(self._dir)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class SuperTrendBandsIndicator(Indicator):
|
|
116
|
+
"""SuperTrend variant exposing final bands and trend state."""
|
|
117
|
+
|
|
118
|
+
lines = ("st", "final_up", "final_dn", "trend")
|
|
119
|
+
params = {"period": 20, "multiplier": 3.0}
|
|
120
|
+
|
|
121
|
+
def __init__(self):
|
|
122
|
+
"""Build the basic ATR bands and reserve the min-period for warmup."""
|
|
123
|
+
self.atr = ATR(self.data, period=self.p.period)
|
|
124
|
+
hl2 = (self.data.high + self.data.low) / 2.0
|
|
125
|
+
self.basic_up = hl2 + self.p.multiplier * self.atr
|
|
126
|
+
self.basic_dn = hl2 - self.p.multiplier * self.atr
|
|
127
|
+
self.addminperiod(self.p.period + 1)
|
|
128
|
+
|
|
129
|
+
def next(self):
|
|
130
|
+
"""Refresh the final bands, the trend flag and the SuperTrend line.
|
|
131
|
+
|
|
132
|
+
On the first bar of the warmup window the final bands are
|
|
133
|
+
seeded from the basic bands and the trend defaults to ``1``.
|
|
134
|
+
Afterwards ``final_up`` only drops when the basic upper band
|
|
135
|
+
is lower than the prior final upper band, or when the
|
|
136
|
+
previous close poked above the prior final upper band; the
|
|
137
|
+
mirror rule applies to ``final_dn``. The trend flag is
|
|
138
|
+
derived from where the current close sits relative to the
|
|
139
|
+
previous final bands, and the SuperTrend line is the
|
|
140
|
+
lower-band value when bullish and the upper-band value when
|
|
141
|
+
bearish.
|
|
142
|
+
"""
|
|
143
|
+
if len(self) == self.p.period + 1:
|
|
144
|
+
self.final_up[0] = self.basic_up[0]
|
|
145
|
+
self.final_dn[0] = self.basic_dn[0]
|
|
146
|
+
self.trend[0] = 1
|
|
147
|
+
self.st[0] = self.basic_dn[0]
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
prev_fu = self.final_up[-1]
|
|
151
|
+
prev_fd = self.final_dn[-1]
|
|
152
|
+
|
|
153
|
+
if self.basic_up[0] < prev_fu or self.data.close[-1] > prev_fu:
|
|
154
|
+
self.final_up[0] = self.basic_up[0]
|
|
155
|
+
else:
|
|
156
|
+
self.final_up[0] = prev_fu
|
|
157
|
+
|
|
158
|
+
if self.basic_dn[0] > prev_fd or self.data.close[-1] < prev_fd:
|
|
159
|
+
self.final_dn[0] = self.basic_dn[0]
|
|
160
|
+
else:
|
|
161
|
+
self.final_dn[0] = prev_fd
|
|
162
|
+
|
|
163
|
+
if self.data.close[0] > self.final_up[-1]:
|
|
164
|
+
self.trend[0] = 1
|
|
165
|
+
elif self.data.close[0] < self.final_dn[-1]:
|
|
166
|
+
self.trend[0] = -1
|
|
167
|
+
else:
|
|
168
|
+
self.trend[0] = self.trend[-1]
|
|
169
|
+
|
|
170
|
+
self.st[0] = self.final_dn[0] if self.trend[0] > 0 else self.final_up[0]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class SupertrendIndicator(Indicator):
|
|
174
|
+
"""SuperTrend variant exposing ``final_up`` and ``final_down`` lines."""
|
|
175
|
+
|
|
176
|
+
lines = ("supertrend", "final_up", "final_down")
|
|
177
|
+
params = {"atr_period": 14, "atr_multiplier": 3}
|
|
178
|
+
plotinfo = {"subplot": False}
|
|
179
|
+
|
|
180
|
+
def __init__(self):
|
|
181
|
+
"""Build the basic upper/lower ATR bands for the SuperTrend state machine."""
|
|
182
|
+
self.atr = ATR(self.data, period=self.p.atr_period)
|
|
183
|
+
self.avg = (self.data.high + self.data.low) / 2
|
|
184
|
+
self.basic_up = self.avg - self.p.atr_multiplier * self.atr
|
|
185
|
+
self.basic_down = self.avg + self.p.atr_multiplier * self.atr
|
|
186
|
+
|
|
187
|
+
def prenext(self):
|
|
188
|
+
"""Zero-fill the output lines during the warmup window."""
|
|
189
|
+
self.l.final_up[0] = 0
|
|
190
|
+
self.l.final_down[0] = 0
|
|
191
|
+
self.l.supertrend[0] = 0
|
|
192
|
+
|
|
193
|
+
def next(self):
|
|
194
|
+
"""Update the final bands and pick a SuperTrend value for the current bar.
|
|
195
|
+
|
|
196
|
+
``final_up`` carries the larger of the basic upper band and
|
|
197
|
+
the prior final upper when the previous close was above the
|
|
198
|
+
prior final upper; otherwise it falls back to the basic
|
|
199
|
+
upper band. ``final_down`` follows the mirror rule. The
|
|
200
|
+
SuperTrend value is the final-up band when the close is
|
|
201
|
+
above the prior final-down band, the final-down band when
|
|
202
|
+
the close is below the prior final-up band, and the prior
|
|
203
|
+
SuperTrend otherwise.
|
|
204
|
+
"""
|
|
205
|
+
if self.data.close[-1] > self.l.final_up[-1]:
|
|
206
|
+
self.l.final_up[0] = max(self.basic_up[0], self.l.final_up[-1])
|
|
207
|
+
else:
|
|
208
|
+
self.l.final_up[0] = self.basic_up[0]
|
|
209
|
+
|
|
210
|
+
if self.data.close[-1] < self.l.final_down[-1]:
|
|
211
|
+
self.l.final_down[0] = min(self.basic_down[0], self.l.final_down[-1])
|
|
212
|
+
else:
|
|
213
|
+
self.l.final_down[0] = self.basic_down[0]
|
|
214
|
+
|
|
215
|
+
if self.data.close[0] > self.l.final_down[-1]:
|
|
216
|
+
self.l.supertrend[0] = self.l.final_up[0]
|
|
217
|
+
elif self.data.close[0] < self.l.final_up[-1]:
|
|
218
|
+
self.l.supertrend[0] = self.l.final_down[0]
|
|
219
|
+
else:
|
|
220
|
+
self.l.supertrend[0] = self.l.supertrend[-1]
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class SuperTrendCCIIndicator(Indicator):
|
|
224
|
+
"""CCI/ATR SuperTrend variant exposing trend and signal buffers."""
|
|
225
|
+
|
|
226
|
+
lines = ("trend_up", "trend_down", "sign_up", "sign_down")
|
|
227
|
+
params = {"cci_period": 50, "atr_period": 5, "level": 0}
|
|
228
|
+
|
|
229
|
+
def __init__(self):
|
|
230
|
+
"""Cache the parameter values, prime the previous-bar state and reserve min period."""
|
|
231
|
+
self._cci_period = int(self.p.cci_period)
|
|
232
|
+
self._atr_period = int(self.p.atr_period)
|
|
233
|
+
self._level = int(self.p.level)
|
|
234
|
+
self._prev_tu = 0.0
|
|
235
|
+
self._prev_td = 0.0
|
|
236
|
+
self._prev_cci = 0.0
|
|
237
|
+
self.addminperiod(max(self._cci_period, self._atr_period) + 2)
|
|
238
|
+
|
|
239
|
+
def _calc_cci(self):
|
|
240
|
+
"""Compute a manual CCI for the configured period.
|
|
241
|
+
|
|
242
|
+
Builds the typical-price array over the configured period,
|
|
243
|
+
takes its mean and mean absolute deviation, and returns
|
|
244
|
+
``(tp_current - mean) / (0.015 * mean_dev)``. Returns ``0.0``
|
|
245
|
+
when the deviation is zero (flat window).
|
|
246
|
+
"""
|
|
247
|
+
period = self._cci_period
|
|
248
|
+
tp_vals = []
|
|
249
|
+
for i in range(period):
|
|
250
|
+
h = float(self.data.high[-i])
|
|
251
|
+
low_price = float(self.data.low[-i])
|
|
252
|
+
c = float(self.data.close[-i])
|
|
253
|
+
tp_vals.append((h + low_price + c) / 3.0)
|
|
254
|
+
mean_tp = sum(tp_vals) / period
|
|
255
|
+
mean_dev = sum(abs(v - mean_tp) for v in tp_vals) / period
|
|
256
|
+
if mean_dev == 0:
|
|
257
|
+
return 0.0
|
|
258
|
+
return (tp_vals[0] - mean_tp) / (0.015 * mean_dev)
|
|
259
|
+
|
|
260
|
+
def _calc_atr(self):
|
|
261
|
+
"""Compute a manual average true range over the configured period.
|
|
262
|
+
|
|
263
|
+
The first iteration falls back to the bar's high-low range
|
|
264
|
+
(no previous close available); subsequent iterations use the
|
|
265
|
+
classic ``max(high - low, |high - prev_close|, |low - prev_close|)``
|
|
266
|
+
formula. The mean of the true ranges is returned.
|
|
267
|
+
"""
|
|
268
|
+
period = self._atr_period
|
|
269
|
+
total = 0.0
|
|
270
|
+
for i in range(period):
|
|
271
|
+
h = float(self.data.high[-i])
|
|
272
|
+
low_price = float(self.data.low[-i])
|
|
273
|
+
if i + 1 < len(self.data):
|
|
274
|
+
pc = float(self.data.close[-(i + 1)])
|
|
275
|
+
tr = max(h - low_price, abs(h - pc), abs(low_price - pc))
|
|
276
|
+
else:
|
|
277
|
+
tr = h - low_price
|
|
278
|
+
total += tr
|
|
279
|
+
return total / period
|
|
280
|
+
|
|
281
|
+
def next(self):
|
|
282
|
+
"""Run the CCI-driven SuperTrend state machine for the current bar.
|
|
283
|
+
|
|
284
|
+
On the bar where the CCI crosses above ``level`` the
|
|
285
|
+
trend-up value is initialised to the previous trend-down
|
|
286
|
+
value, and vice versa. While the CCI is above ``level`` the
|
|
287
|
+
trend-up band is ``current_low - ATR`` (capped at the prior
|
|
288
|
+
value when both bars agree on the regime). The trend-down
|
|
289
|
+
band is built mirror-symmetrically. ``sign_up`` /
|
|
290
|
+
``sign_down`` simply forward the current trend value when a
|
|
291
|
+
prior trend was already established, so they only change
|
|
292
|
+
after the first transition.
|
|
293
|
+
"""
|
|
294
|
+
cci = self._calc_cci()
|
|
295
|
+
atr = self._calc_atr()
|
|
296
|
+
level = self._level
|
|
297
|
+
tu = 0.0
|
|
298
|
+
td = 0.0
|
|
299
|
+
su = 0.0
|
|
300
|
+
sd = 0.0
|
|
301
|
+
cur_high = float(self.data.high[0])
|
|
302
|
+
cur_low = float(self.data.low[0])
|
|
303
|
+
|
|
304
|
+
if cci >= level and self._prev_cci < level:
|
|
305
|
+
tu = self._prev_td
|
|
306
|
+
if cci <= level and self._prev_cci > level:
|
|
307
|
+
td = self._prev_tu
|
|
308
|
+
if cci > level:
|
|
309
|
+
tu = cur_low - atr
|
|
310
|
+
if tu < self._prev_tu and self._prev_cci >= level:
|
|
311
|
+
tu = self._prev_tu
|
|
312
|
+
if cci < level:
|
|
313
|
+
td = cur_high + atr
|
|
314
|
+
if td > self._prev_td and self._prev_cci <= level:
|
|
315
|
+
td = self._prev_td
|
|
316
|
+
if self._prev_td != 0.0 and tu != 0.0:
|
|
317
|
+
su = tu
|
|
318
|
+
if self._prev_tu != 0.0 and td != 0.0:
|
|
319
|
+
sd = td
|
|
320
|
+
|
|
321
|
+
self._prev_cci = cci
|
|
322
|
+
self._prev_tu = tu
|
|
323
|
+
self._prev_td = td
|
|
324
|
+
self.lines.trend_up[0] = tu
|
|
325
|
+
self.lines.trend_down[0] = td
|
|
326
|
+
self.lines.sign_up[0] = su
|
|
327
|
+
self.lines.sign_down[0] = sd
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class AdaptiveSuperTrendIndicator(Indicator):
|
|
331
|
+
"""Adaptive SuperTrend that dynamically adjusts multiplier from ATR."""
|
|
332
|
+
|
|
333
|
+
lines = ("st",)
|
|
334
|
+
params = {
|
|
335
|
+
"period": 20,
|
|
336
|
+
"vol_lookback": 20,
|
|
337
|
+
"a_coef": 0.5,
|
|
338
|
+
"b_coef": 2.0,
|
|
339
|
+
"min_mult": 0.5,
|
|
340
|
+
"max_mult": 3.0,
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
def __init__(self):
|
|
344
|
+
"""Wire up the ATR, EMA-of-ATR and ``hl2`` sub-series and sync the min period."""
|
|
345
|
+
self.atr = ATR(self.data, period=self.p.period)
|
|
346
|
+
self.avg_atr = EMA(self.atr, period=self.p.vol_lookback)
|
|
347
|
+
self.hl2 = (self.data.high + self.data.low) / 2.0
|
|
348
|
+
self.updateminperiod(self.avg_atr._minperiod)
|
|
349
|
+
|
|
350
|
+
def _calc_bands(self):
|
|
351
|
+
"""Return the dynamically-scaled upper and lower bands for the current bar.
|
|
352
|
+
|
|
353
|
+
The base multiplier is ``a_coef + b_coef * avg_atr`` clamped
|
|
354
|
+
to ``[min_mult, max_mult]``. The dynamic multiplier further
|
|
355
|
+
scales it by ``avg_atr / atr`` (and re-clamps), so calm
|
|
356
|
+
regimes use a larger multiplier and volatile regimes use a
|
|
357
|
+
smaller one. Bands are then ``hl2 ± dyn_mult * atr``; the
|
|
358
|
+
``atr <= 0`` case falls back to a tiny epsilon to keep the
|
|
359
|
+
division defined.
|
|
360
|
+
"""
|
|
361
|
+
atr_val = float(self.atr[0])
|
|
362
|
+
avg_atr_val = float(self.avg_atr[0])
|
|
363
|
+
if atr_val <= 0:
|
|
364
|
+
atr_val = 0.0001
|
|
365
|
+
base_mult = self.p.a_coef + self.p.b_coef * avg_atr_val
|
|
366
|
+
base_mult = max(self.p.min_mult, min(self.p.max_mult, base_mult))
|
|
367
|
+
dyn_mult = base_mult * (avg_atr_val / atr_val) if atr_val > 0 else base_mult
|
|
368
|
+
dyn_mult = max(self.p.min_mult, min(self.p.max_mult, dyn_mult))
|
|
369
|
+
hl2 = float(self.hl2[0])
|
|
370
|
+
return hl2 + dyn_mult * atr_val, hl2 - dyn_mult * atr_val
|
|
371
|
+
|
|
372
|
+
def nextstart(self):
|
|
373
|
+
"""Seed the SuperTrend line with the upper band on the first ready bar."""
|
|
374
|
+
upper, _lower = self._calc_bands()
|
|
375
|
+
self.l.st[0] = upper
|
|
376
|
+
|
|
377
|
+
def next(self):
|
|
378
|
+
"""Update the SuperTrend value with the standard up/down state machine.
|
|
379
|
+
|
|
380
|
+
When the close is above the prior SuperTrend the new value
|
|
381
|
+
is the larger of the lower band and the prior value
|
|
382
|
+
(tracking the rising lower band). Otherwise the value falls
|
|
383
|
+
to the smaller of the upper band and the prior value.
|
|
384
|
+
"""
|
|
385
|
+
upper, lower = self._calc_bands()
|
|
386
|
+
prev_st = self.l.st[-1]
|
|
387
|
+
if self.data.close[0] > prev_st:
|
|
388
|
+
self.l.st[0] = max(lower, prev_st)
|
|
389
|
+
else:
|
|
390
|
+
self.l.st[0] = min(upper, prev_st)
|
|
391
|
+
|
|
392
|
+
def preonce(self, start, end):
|
|
393
|
+
"""No-op: vectorised path uses the same per-bar logic as ``once``."""
|
|
394
|
+
|
|
395
|
+
def oncestart(self, start, end):
|
|
396
|
+
"""No-op: vectorised path uses the same per-bar logic as ``once``."""
|
|
397
|
+
|
|
398
|
+
def once(self, start, end):
|
|
399
|
+
"""Vectorised implementation of the adaptive SuperTrend.
|
|
400
|
+
|
|
401
|
+
Walks the ATR, EMA-of-ATR, ``hl2`` and close arrays from the
|
|
402
|
+
warmup boundary to the end of the input. The first ready bar
|
|
403
|
+
seeds the SuperTrend with the upper band; every subsequent
|
|
404
|
+
bar applies the same state machine as :meth:`next` but
|
|
405
|
+
inlined for the ``once`` path.
|
|
406
|
+
"""
|
|
407
|
+
atr_array = self.atr.lines[0].array
|
|
408
|
+
avg_atr_array = self.avg_atr.lines[0].array
|
|
409
|
+
hl2_array = self.hl2.array
|
|
410
|
+
close_array = self.data.close.array
|
|
411
|
+
st_array = self.lines.st.array
|
|
412
|
+
minperiod = self.avg_atr._minperiod
|
|
413
|
+
actual_end = min(end, len(atr_array), len(avg_atr_array), len(hl2_array), len(close_array))
|
|
414
|
+
while len(st_array) < actual_end:
|
|
415
|
+
st_array.append(0.0)
|
|
416
|
+
for i in range(minperiod - 1, actual_end):
|
|
417
|
+
atr_val = float(atr_array[i])
|
|
418
|
+
avg_atr_val = float(avg_atr_array[i])
|
|
419
|
+
if atr_val <= 0:
|
|
420
|
+
atr_val = 0.0001
|
|
421
|
+
base_mult = self.p.a_coef + self.p.b_coef * avg_atr_val
|
|
422
|
+
base_mult = max(self.p.min_mult, min(self.p.max_mult, base_mult))
|
|
423
|
+
dyn_mult = base_mult * (avg_atr_val / atr_val) if atr_val > 0 else base_mult
|
|
424
|
+
dyn_mult = max(self.p.min_mult, min(self.p.max_mult, dyn_mult))
|
|
425
|
+
hl2 = float(hl2_array[i])
|
|
426
|
+
upper = hl2 + dyn_mult * atr_val
|
|
427
|
+
lower = hl2 - dyn_mult * atr_val
|
|
428
|
+
if i == minperiod - 1:
|
|
429
|
+
st_array[i] = upper
|
|
430
|
+
else:
|
|
431
|
+
prev_st = st_array[i - 1]
|
|
432
|
+
close_val = float(close_array[i])
|
|
433
|
+
if close_val > prev_st:
|
|
434
|
+
st_array[i] = max(lower, prev_st)
|
|
435
|
+
else:
|
|
436
|
+
st_array[i] = min(upper, prev_st)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Trend indicator extensions migrated from functional tests."""
|
|
3
|
+
|
|
4
|
+
from . import Indicator
|
|
5
|
+
from .smma import SmoothedMovingAverage
|
|
6
|
+
|
|
7
|
+
__all__ = ["AlligatorIndicator", "VortexIndicator", "VortexSystemIndicator"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AlligatorIndicator(Indicator):
|
|
11
|
+
"""Bill Williams Alligator lines used by functional strategies.
|
|
12
|
+
|
|
13
|
+
The historical functional-test variants accepted shift/ma_method
|
|
14
|
+
parameters but did not apply the shift or switch the MA method. Those
|
|
15
|
+
parameters are kept for API compatibility and the original SMMA behavior is
|
|
16
|
+
preserved.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
lines = ("jaw", "teeth", "lips")
|
|
20
|
+
params = (
|
|
21
|
+
("jaw_period", 13),
|
|
22
|
+
("teeth_period", 8),
|
|
23
|
+
("lips_period", 5),
|
|
24
|
+
("jaw_shift", 8),
|
|
25
|
+
("teeth_shift", 5),
|
|
26
|
+
("lips_shift", 3),
|
|
27
|
+
("ma_method", "smma"),
|
|
28
|
+
("applied_price", "close"),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def __init__(self):
|
|
32
|
+
"""Build the three smoothed moving-average Alligator lines.
|
|
33
|
+
|
|
34
|
+
Selects the source series based on ``applied_price`` (``median``
|
|
35
|
+
uses ``(high + low) / 2``, everything else uses the close)
|
|
36
|
+
and then binds a :class:`SmoothedMovingAverage` to the
|
|
37
|
+
``jaw``/``teeth``/``lips`` output lines. The shift/ma_method
|
|
38
|
+
parameters are accepted for API compatibility but not applied.
|
|
39
|
+
"""
|
|
40
|
+
if self.p.applied_price == "median":
|
|
41
|
+
src = (self.data.high + self.data.low) / 2.0
|
|
42
|
+
else:
|
|
43
|
+
src = self.data.close
|
|
44
|
+
|
|
45
|
+
self.lines.jaw = SmoothedMovingAverage(src, period=self.p.jaw_period)
|
|
46
|
+
self.lines.teeth = SmoothedMovingAverage(src, period=self.p.teeth_period)
|
|
47
|
+
self.lines.lips = SmoothedMovingAverage(src, period=self.p.lips_period)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class VortexIndicator(Indicator):
|
|
51
|
+
"""Vortex Indicator with both historical line naming conventions."""
|
|
52
|
+
|
|
53
|
+
lines = ("vi_plus", "vi_minus", "plus_vi", "minus_vi")
|
|
54
|
+
params = (("period", 14),)
|
|
55
|
+
|
|
56
|
+
def next(self):
|
|
57
|
+
"""Compute the Vortex Indicator plus/minus values for the current bar.
|
|
58
|
+
|
|
59
|
+
Sums ``|high - prev_low|`` (plus), ``|low - prev_high|``
|
|
60
|
+
(minus) and the true range ``max(high - low, |high - prev_close|,
|
|
61
|
+
|low - prev_close|)`` over the configured period. The two Vortex
|
|
62
|
+
values are ``sum_plus / tr_sum`` and ``sum_minus / tr_sum``
|
|
63
|
+
(both default to ``0.0`` when the true-range sum is zero).
|
|
64
|
+
During the warmup window every output line is set to ``0.0``.
|
|
65
|
+
"""
|
|
66
|
+
p = int(self.p.period)
|
|
67
|
+
if len(self.data) < p + 2:
|
|
68
|
+
for line in self.lines:
|
|
69
|
+
line[0] = 0.0
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
vm_plus_sum = 0.0
|
|
73
|
+
vm_minus_sum = 0.0
|
|
74
|
+
tr_sum = 0.0
|
|
75
|
+
for i in range(p):
|
|
76
|
+
idx = -i
|
|
77
|
+
idx_prev = idx - 1
|
|
78
|
+
h = float(self.data.high[idx])
|
|
79
|
+
low_price = float(self.data.low[idx])
|
|
80
|
+
h_prev = float(self.data.high[idx_prev])
|
|
81
|
+
l_prev = float(self.data.low[idx_prev])
|
|
82
|
+
c_prev = float(self.data.close[idx_prev])
|
|
83
|
+
vm_plus_sum += abs(h - l_prev)
|
|
84
|
+
vm_minus_sum += abs(low_price - h_prev)
|
|
85
|
+
tr_sum += max(h - low_price, abs(h - c_prev), abs(low_price - c_prev))
|
|
86
|
+
|
|
87
|
+
if tr_sum > 0:
|
|
88
|
+
plus = vm_plus_sum / tr_sum
|
|
89
|
+
minus = vm_minus_sum / tr_sum
|
|
90
|
+
else:
|
|
91
|
+
plus = 0.0
|
|
92
|
+
minus = 0.0
|
|
93
|
+
|
|
94
|
+
self.lines.vi_plus[0] = plus
|
|
95
|
+
self.lines.plus_vi[0] = plus
|
|
96
|
+
self.lines.vi_minus[0] = minus
|
|
97
|
+
self.lines.minus_vi[0] = minus
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class VortexSystemIndicator(VortexIndicator):
|
|
101
|
+
"""Vortex variant preserving the historical strategy-system warm-up."""
|
|
102
|
+
|
|
103
|
+
def __init__(self):
|
|
104
|
+
"""Reserve the extra warm-up bar required by the original system variant."""
|
|
105
|
+
self.addminperiod(int(self.p.period) + 1)
|