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,106 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import math
|
|
9
|
+
|
|
10
|
+
from .. import Indicator
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"LsmaAngleIndicator",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LsmaAngleIndicator(Indicator):
|
|
18
|
+
"""Compute LSMA slope angle and map it to a color-state indicator.
|
|
19
|
+
|
|
20
|
+
The indicator evaluates two least-squares MAs at different shifts and uses
|
|
21
|
+
the angle and trend persistence to classify bullish/bearish momentum states.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
lsma_period: Look-back window used for each LSMA estimate.
|
|
25
|
+
angle_threshold: Threshold used to classify the angle magnitude.
|
|
26
|
+
start_shift: Shift index for the start LSMA sample.
|
|
27
|
+
end_shift: Shift index for the end LSMA sample.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
lines = ("angle", "color_index")
|
|
31
|
+
params = (
|
|
32
|
+
("lsma_period", 25),
|
|
33
|
+
("angle_threshold", 15),
|
|
34
|
+
("start_shift", 4),
|
|
35
|
+
("end_shift", 0),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def __init__(self):
|
|
39
|
+
"""Set minimum-history requirement and initialize derived scale factor."""
|
|
40
|
+
needed = (
|
|
41
|
+
int(max(self.p.lsma_period + self.p.start_shift, self.p.lsma_period + self.p.end_shift))
|
|
42
|
+
+ 2
|
|
43
|
+
)
|
|
44
|
+
self.addminperiod(needed)
|
|
45
|
+
self._m_factor = None
|
|
46
|
+
|
|
47
|
+
def _lsma(self, shift):
|
|
48
|
+
period = int(self.p.lsma_period)
|
|
49
|
+
values = [float(self.data.close[-(shift + i)]) for i in range(period)]
|
|
50
|
+
x = list(range(period))
|
|
51
|
+
x_mean = sum(x) / period
|
|
52
|
+
y_mean = sum(values) / period
|
|
53
|
+
numerator = sum((xi - x_mean) * (yi - y_mean) for xi, yi in zip(x, values))
|
|
54
|
+
denominator = sum((xi - x_mean) ** 2 for xi in x)
|
|
55
|
+
slope = numerator / denominator if denominator else 0.0
|
|
56
|
+
intercept = y_mean - slope * x_mean
|
|
57
|
+
return intercept + slope * (period - 1)
|
|
58
|
+
|
|
59
|
+
def _ensure_factor(self):
|
|
60
|
+
if self._m_factor is not None:
|
|
61
|
+
return
|
|
62
|
+
point = (
|
|
63
|
+
float(getattr(self.data, "_dataname", None).attrs["point"])
|
|
64
|
+
if hasattr(getattr(self.data, "_dataname", None), "attrs")
|
|
65
|
+
and "point" in self.data._dataname.attrs
|
|
66
|
+
else None
|
|
67
|
+
)
|
|
68
|
+
if point is None or point <= 0:
|
|
69
|
+
close0 = float(self.data.close[0]) if len(self.data) else 0.0
|
|
70
|
+
point = 0.01 if abs(close0) >= 10 and abs(close0) < 1000 else 0.0001
|
|
71
|
+
shift_diff = float(int(self.p.start_shift) - int(self.p.end_shift))
|
|
72
|
+
self._m_factor = (
|
|
73
|
+
1000.0
|
|
74
|
+
if abs(float(self.data.close[0])) >= 10 and abs(float(self.data.close[0])) < 1000
|
|
75
|
+
else 100000.0
|
|
76
|
+
) / shift_diff
|
|
77
|
+
|
|
78
|
+
def next(self):
|
|
79
|
+
"""Calculate the current angle and update color index for the next bar."""
|
|
80
|
+
if int(self.p.end_shift) >= int(self.p.start_shift):
|
|
81
|
+
self.lines.angle[0] = 0.0
|
|
82
|
+
self.lines.color_index[0] = 2
|
|
83
|
+
return
|
|
84
|
+
self._ensure_factor()
|
|
85
|
+
end_ma = self._lsma(int(self.p.end_shift))
|
|
86
|
+
start_ma = self._lsma(int(self.p.start_shift))
|
|
87
|
+
angle = self._m_factor * (end_ma - start_ma) / 2.0
|
|
88
|
+
self.lines.angle[0] = angle
|
|
89
|
+
clr = 2
|
|
90
|
+
threshold = float(self.p.angle_threshold)
|
|
91
|
+
prev_angle = (
|
|
92
|
+
float(self.lines.angle[-1])
|
|
93
|
+
if len(self) > 0 and math.isfinite(float(self.lines.angle[-1]))
|
|
94
|
+
else angle
|
|
95
|
+
)
|
|
96
|
+
if angle > threshold:
|
|
97
|
+
if angle > prev_angle:
|
|
98
|
+
clr = 4
|
|
99
|
+
elif angle < prev_angle:
|
|
100
|
+
clr = 3
|
|
101
|
+
if angle < -threshold:
|
|
102
|
+
if angle < prev_angle:
|
|
103
|
+
clr = 0
|
|
104
|
+
elif angle > prev_angle:
|
|
105
|
+
clr = 1
|
|
106
|
+
self.lines.color_index[0] = clr
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .. import (
|
|
9
|
+
ATR,
|
|
10
|
+
EMA,
|
|
11
|
+
SMA,
|
|
12
|
+
Indicator,
|
|
13
|
+
SmoothedMovingAverage,
|
|
14
|
+
WeightedMovingAverage,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"MARoundingChannelIndicator",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def resolve_ma_class(name):
|
|
23
|
+
"""Map MA method name to the corresponding Backtrader indicator class."""
|
|
24
|
+
mode = str(name).lower()
|
|
25
|
+
if mode in {"sma", "mode_sma"}:
|
|
26
|
+
return SMA
|
|
27
|
+
if mode in {"ema", "mode_ema"}:
|
|
28
|
+
return EMA
|
|
29
|
+
if mode in {"smma", "mode_smma"}:
|
|
30
|
+
return SmoothedMovingAverage
|
|
31
|
+
return WeightedMovingAverage
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def resolve_price_line(data, mode):
|
|
35
|
+
"""Map a configured price selector string to feed line values."""
|
|
36
|
+
price_mode = str(mode).lower()
|
|
37
|
+
if price_mode in {"price_open", "open"}:
|
|
38
|
+
return data.open
|
|
39
|
+
if price_mode in {"price_high", "high"}:
|
|
40
|
+
return data.high
|
|
41
|
+
if price_mode in {"price_low", "low"}:
|
|
42
|
+
return data.low
|
|
43
|
+
if price_mode in {"price_median", "median"}:
|
|
44
|
+
return (data.high + data.low) / 2.0
|
|
45
|
+
if price_mode in {"price_typical", "typical"}:
|
|
46
|
+
return (data.high + data.low + data.close) / 3.0
|
|
47
|
+
if price_mode in {"price_weighted", "weighted"}:
|
|
48
|
+
return (data.high + data.low + data.close + data.close) / 4.0
|
|
49
|
+
if price_mode in {"price_simpl", "simpl"}:
|
|
50
|
+
return (data.open + data.close) / 2.0
|
|
51
|
+
if price_mode in {"price_quarter", "quarter"}:
|
|
52
|
+
return (data.high + data.low + data.open + data.close) / 4.0
|
|
53
|
+
if price_mode in {"price_trendfollow0", "trendfollow0"}:
|
|
54
|
+
return (data.high + data.low + data.close + data.close) / 4.0
|
|
55
|
+
if price_mode in {"price_trendfollow1", "trendfollow1"}:
|
|
56
|
+
return (data.high + data.low + data.open + data.close + data.close) / 5.0
|
|
57
|
+
return data.close
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MARoundingChannelIndicator(Indicator):
|
|
61
|
+
"""Indicator that derives rounded moving-average centerline and channel bounds."""
|
|
62
|
+
|
|
63
|
+
lines = (
|
|
64
|
+
"base",
|
|
65
|
+
"upper",
|
|
66
|
+
"lower",
|
|
67
|
+
)
|
|
68
|
+
params = (
|
|
69
|
+
("xma_method", "sma"),
|
|
70
|
+
("xlength", 12),
|
|
71
|
+
("xphase", 15),
|
|
72
|
+
("ipc", "price_close"),
|
|
73
|
+
("ma_round", 500),
|
|
74
|
+
("atr_period", 12),
|
|
75
|
+
("atr_factor", 1.0),
|
|
76
|
+
("chan_continuity", False),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def __init__(self):
|
|
80
|
+
"""Resolve MA and ATR dependencies and initialize rolling channel state."""
|
|
81
|
+
ma_cls = resolve_ma_class(self.p.xma_method)
|
|
82
|
+
price_line = resolve_price_line(self.data, self.p.ipc)
|
|
83
|
+
self.ma = ma_cls(price_line, period=self.p.xlength)
|
|
84
|
+
self.atr = ATR(self.data, period=self.p.atr_period)
|
|
85
|
+
self._ma_ro = None
|
|
86
|
+
self._prev_ma = None
|
|
87
|
+
self._prev_dir = 0
|
|
88
|
+
self._prev_range = 0.0
|
|
89
|
+
self._prev_base = None
|
|
90
|
+
self._prev_prev_base = None
|
|
91
|
+
self._prev_upper = 0.0
|
|
92
|
+
self._prev_lower = 0.0
|
|
93
|
+
self.addminperiod(max(self.p.xlength, self.p.atr_period) + 3)
|
|
94
|
+
|
|
95
|
+
def next(self):
|
|
96
|
+
"""Update channel base/upper/lower values from latest MA and ATR context."""
|
|
97
|
+
if self._ma_ro is None:
|
|
98
|
+
self._ma_ro = (
|
|
99
|
+
float(self.data.close[0]) * 0.0 + self.data._dataname["close"].iloc[0] * 0.0
|
|
100
|
+
if False
|
|
101
|
+
else None
|
|
102
|
+
)
|
|
103
|
+
ma_ro = float(getattr(self.data, "_compression", 0) or 0)
|
|
104
|
+
if not ma_ro:
|
|
105
|
+
point = 0.01 if abs(float(self.data.close[0])) >= 1 else 0.0001
|
|
106
|
+
ma_ro = point * float(self.p.ma_round)
|
|
107
|
+
mov_ave0 = float(self.ma[0])
|
|
108
|
+
if self._prev_ma is None:
|
|
109
|
+
self._prev_ma = mov_ave0
|
|
110
|
+
res1 = self._prev_base if self._prev_base is not None else mov_ave0
|
|
111
|
+
if (
|
|
112
|
+
mov_ave0 > self._prev_ma + ma_ro
|
|
113
|
+
or mov_ave0 < self._prev_ma - ma_ro
|
|
114
|
+
or mov_ave0 > res1 + ma_ro
|
|
115
|
+
or mov_ave0 < res1 - ma_ro
|
|
116
|
+
or (mov_ave0 > res1 and self._prev_dir == 1)
|
|
117
|
+
or (mov_ave0 < res1 and self._prev_dir == -1)
|
|
118
|
+
):
|
|
119
|
+
base = mov_ave0
|
|
120
|
+
else:
|
|
121
|
+
base = res1
|
|
122
|
+
direction = 0
|
|
123
|
+
if base < res1:
|
|
124
|
+
direction = -1
|
|
125
|
+
elif base > res1:
|
|
126
|
+
direction = 1
|
|
127
|
+
else:
|
|
128
|
+
direction = self._prev_dir
|
|
129
|
+
upper = 0.0
|
|
130
|
+
lower = 0.0
|
|
131
|
+
range0 = self._prev_range
|
|
132
|
+
if base == res1:
|
|
133
|
+
if self._prev_prev_base is None or res1 != self._prev_prev_base:
|
|
134
|
+
range0 = float(self.atr[0]) * float(self.p.atr_factor)
|
|
135
|
+
upper = base + range0
|
|
136
|
+
lower = base - range0
|
|
137
|
+
elif self.p.chan_continuity:
|
|
138
|
+
upper = self._prev_upper
|
|
139
|
+
lower = self._prev_lower
|
|
140
|
+
self.lines.base[0] = base
|
|
141
|
+
self.lines.upper[0] = upper
|
|
142
|
+
self.lines.lower[0] = lower
|
|
143
|
+
self._prev_dir = direction
|
|
144
|
+
self._prev_ma = mov_ave0
|
|
145
|
+
self._prev_range = range0
|
|
146
|
+
self._prev_prev_base = self._prev_base
|
|
147
|
+
self._prev_base = base
|
|
148
|
+
self._prev_upper = upper
|
|
149
|
+
self._prev_lower = lower
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .. import (
|
|
9
|
+
MACD,
|
|
10
|
+
Indicator,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Macd2Indicator",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Macd2Indicator(Indicator):
|
|
19
|
+
"""MACD-derived indicator carrying cloud and histogram state for MACD-2."""
|
|
20
|
+
|
|
21
|
+
lines = ("cloud_a", "cloud_b", "hist", "color")
|
|
22
|
+
params = (
|
|
23
|
+
("fast_macd", 12),
|
|
24
|
+
("slow_macd", 26),
|
|
25
|
+
("signal_macd", 9),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
"""Create MACD-based cloud and initialize indicator warmup."""
|
|
30
|
+
self.macd = MACD(
|
|
31
|
+
self.data,
|
|
32
|
+
period_me1=int(self.p.fast_macd),
|
|
33
|
+
period_me2=int(self.p.slow_macd),
|
|
34
|
+
period_signal=int(self.p.signal_macd),
|
|
35
|
+
)
|
|
36
|
+
self.addminperiod(
|
|
37
|
+
int(self.p.signal_macd) + max(int(self.p.fast_macd), int(self.p.slow_macd)) + 2
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def next(self):
|
|
41
|
+
"""Populate cloud, histogram, and trend color lines each bar."""
|
|
42
|
+
main = float(self.macd.macd[0])
|
|
43
|
+
signal = float(self.macd.signal[0])
|
|
44
|
+
hist = 3.0 * (main - signal)
|
|
45
|
+
self.lines.cloud_a[0] = main
|
|
46
|
+
self.lines.cloud_b[0] = signal
|
|
47
|
+
self.lines.hist[0] = hist
|
|
48
|
+
color = 2
|
|
49
|
+
if len(self) > 1:
|
|
50
|
+
prev_hist = float(self.lines.hist[-1])
|
|
51
|
+
if hist > 0:
|
|
52
|
+
if hist > prev_hist:
|
|
53
|
+
color = 4
|
|
54
|
+
elif hist < prev_hist:
|
|
55
|
+
color = 3
|
|
56
|
+
elif hist < 0:
|
|
57
|
+
if hist < prev_hist:
|
|
58
|
+
color = 0
|
|
59
|
+
elif hist > prev_hist:
|
|
60
|
+
color = 1
|
|
61
|
+
self.lines.color[0] = color
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .. import (
|
|
9
|
+
MACD,
|
|
10
|
+
Indicator,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"MacdCandleIndicator",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MacdCandleIndicator(Indicator):
|
|
19
|
+
"""MACD-based candle indicator returning open/high/low/close values."""
|
|
20
|
+
|
|
21
|
+
lines = ("macd_open", "macd_high", "macd_low", "macd_close", "color")
|
|
22
|
+
params = (
|
|
23
|
+
("fast_ema_period", 12),
|
|
24
|
+
("slow_ema_period", 26),
|
|
25
|
+
("signal_period", 9),
|
|
26
|
+
("mode", "signal"),
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
"""Create MACD lines and register warmup period."""
|
|
31
|
+
self.addminperiod(
|
|
32
|
+
max(int(self.p.fast_ema_period), int(self.p.slow_ema_period))
|
|
33
|
+
+ int(self.p.signal_period)
|
|
34
|
+
+ 3
|
|
35
|
+
)
|
|
36
|
+
self.macd_open = MACD(
|
|
37
|
+
self.data.open,
|
|
38
|
+
period_me1=int(self.p.fast_ema_period),
|
|
39
|
+
period_me2=int(self.p.slow_ema_period),
|
|
40
|
+
period_signal=int(self.p.signal_period),
|
|
41
|
+
)
|
|
42
|
+
self.macd_high = MACD(
|
|
43
|
+
self.data.high,
|
|
44
|
+
period_me1=int(self.p.fast_ema_period),
|
|
45
|
+
period_me2=int(self.p.slow_ema_period),
|
|
46
|
+
period_signal=int(self.p.signal_period),
|
|
47
|
+
)
|
|
48
|
+
self.macd_low = MACD(
|
|
49
|
+
self.data.low,
|
|
50
|
+
period_me1=int(self.p.fast_ema_period),
|
|
51
|
+
period_me2=int(self.p.slow_ema_period),
|
|
52
|
+
period_signal=int(self.p.signal_period),
|
|
53
|
+
)
|
|
54
|
+
self.macd_close = MACD(
|
|
55
|
+
self.data.close,
|
|
56
|
+
period_me1=int(self.p.fast_ema_period),
|
|
57
|
+
period_me2=int(self.p.slow_ema_period),
|
|
58
|
+
period_signal=int(self.p.signal_period),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def _value(self, macd_obj):
|
|
62
|
+
return float(macd_obj.signal[0]) if self.p.mode == "signal" else float(macd_obj.macd[0])
|
|
63
|
+
|
|
64
|
+
def next(self):
|
|
65
|
+
"""Populate output candle components and derive color state per bar."""
|
|
66
|
+
open_value = self._value(self.macd_open)
|
|
67
|
+
high_value = self._value(self.macd_high)
|
|
68
|
+
low_value = self._value(self.macd_low)
|
|
69
|
+
close_value = self._value(self.macd_close)
|
|
70
|
+
self.lines.macd_open[0] = open_value
|
|
71
|
+
self.lines.macd_high[0] = high_value
|
|
72
|
+
self.lines.macd_low[0] = low_value
|
|
73
|
+
self.lines.macd_close[0] = close_value
|
|
74
|
+
if open_value < close_value:
|
|
75
|
+
color = 2
|
|
76
|
+
elif open_value > close_value:
|
|
77
|
+
color = 0
|
|
78
|
+
else:
|
|
79
|
+
color = 1
|
|
80
|
+
self.lines.color[0] = color
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .. import (
|
|
9
|
+
Indicator,
|
|
10
|
+
SimpleMovingAverage,
|
|
11
|
+
StandardDeviation,
|
|
12
|
+
WeightedMovingAverage,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"MalrIndicator",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MalrIndicator(Indicator):
|
|
21
|
+
"""Compute MALR trend channels used for breakout-trigger detection."""
|
|
22
|
+
|
|
23
|
+
lines = ("malr", "malrh", "malrl", "malrhh", "malrll")
|
|
24
|
+
params = (
|
|
25
|
+
("ma_period", 120),
|
|
26
|
+
("ma_shift", 0),
|
|
27
|
+
("channel_reversal", 1.1),
|
|
28
|
+
("channel_breakout", 1.1),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def __init__(self):
|
|
32
|
+
"""Initialize MA basis and channel deviation buffers."""
|
|
33
|
+
sma = SimpleMovingAverage(self.data.close, period=self.p.ma_period)
|
|
34
|
+
lwma = WeightedMovingAverage(self.data.close, period=self.p.ma_period)
|
|
35
|
+
self._ff = 3.0 * lwma - 2.0 * sma
|
|
36
|
+
diff = self.data.close - self._ff
|
|
37
|
+
self._std = StandardDeviation(diff, period=self.p.ma_period)
|
|
38
|
+
self.addminperiod(int(self.p.ma_period) * 2 + 3)
|
|
39
|
+
|
|
40
|
+
def next(self):
|
|
41
|
+
"""Calculate MALR center and channel boundaries for the current bar."""
|
|
42
|
+
ff = float(self._ff[0])
|
|
43
|
+
std = float(self._std[0])
|
|
44
|
+
t1 = std * float(self.p.channel_reversal)
|
|
45
|
+
t2 = std * (float(self.p.channel_reversal) + float(self.p.channel_breakout))
|
|
46
|
+
self.lines.malr[0] = ff
|
|
47
|
+
self.lines.malrh[0] = ff + t1
|
|
48
|
+
self.lines.malrl[0] = ff - t1
|
|
49
|
+
self.lines.malrhh[0] = ff + t2
|
|
50
|
+
self.lines.malrll[0] = ff - t2
|
|
51
|
+
|
|
52
|
+
def once(self, start, end):
|
|
53
|
+
"""Vectorized computation path for backtesting efficiency."""
|
|
54
|
+
ff_array = self._ff.array
|
|
55
|
+
std_array = self._std.array
|
|
56
|
+
lines = (
|
|
57
|
+
self.lines.malr.array,
|
|
58
|
+
self.lines.malrh.array,
|
|
59
|
+
self.lines.malrl.array,
|
|
60
|
+
self.lines.malrhh.array,
|
|
61
|
+
self.lines.malrll.array,
|
|
62
|
+
)
|
|
63
|
+
for line in lines:
|
|
64
|
+
while len(line) < end:
|
|
65
|
+
line.append(float("nan"))
|
|
66
|
+
|
|
67
|
+
actual_end = min(end, len(ff_array), len(std_array))
|
|
68
|
+
for i in range(start, actual_end):
|
|
69
|
+
ff = float(ff_array[i])
|
|
70
|
+
std = float(std_array[i])
|
|
71
|
+
t1 = std * float(self.p.channel_reversal)
|
|
72
|
+
t2 = std * (float(self.p.channel_reversal) + float(self.p.channel_breakout))
|
|
73
|
+
lines[0][i] = ff
|
|
74
|
+
lines[1][i] = ff + t1
|
|
75
|
+
lines[2][i] = ff - t1
|
|
76
|
+
lines[3][i] = ff + t2
|
|
77
|
+
lines[4][i] = ff - t2
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .. import (
|
|
9
|
+
ATR,
|
|
10
|
+
Indicator,
|
|
11
|
+
Momentum,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"MomentumCandleSignIndicator",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MomentumCandleSignIndicator(Indicator):
|
|
20
|
+
"""Emit ATR-offset buy/sell dots on open/close momentum crossovers."""
|
|
21
|
+
|
|
22
|
+
lines = ("sell_signal", "buy_signal", "momentum_open", "momentum_close")
|
|
23
|
+
params = (
|
|
24
|
+
("period", 12),
|
|
25
|
+
("atr_period", 15),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
"""Build open/close momentum and ATR sub-indicators and set min period."""
|
|
30
|
+
self.addminperiod(max(int(self.p.period), int(self.p.atr_period)) + 3)
|
|
31
|
+
self.momentum_open = Momentum(self.data.open, period=int(self.p.period))
|
|
32
|
+
self.momentum_close = Momentum(self.data.close, period=int(self.p.period))
|
|
33
|
+
self.atr = ATR(self.data, period=int(self.p.atr_period))
|
|
34
|
+
|
|
35
|
+
def next(self):
|
|
36
|
+
"""Detect momentum crossovers and place ATR-offset signal dots."""
|
|
37
|
+
self.lines.sell_signal[0] = 0.0
|
|
38
|
+
self.lines.buy_signal[0] = 0.0
|
|
39
|
+
self.lines.momentum_open[0] = float(self.momentum_open[0])
|
|
40
|
+
self.lines.momentum_close[0] = float(self.momentum_close[0])
|
|
41
|
+
if len(self.data) < 2:
|
|
42
|
+
return
|
|
43
|
+
prev_open = float(self.momentum_open[-1])
|
|
44
|
+
prev_close = float(self.momentum_close[-1])
|
|
45
|
+
curr_open = float(self.momentum_open[0])
|
|
46
|
+
curr_close = float(self.momentum_close[0])
|
|
47
|
+
atr = float(self.atr[0])
|
|
48
|
+
if prev_open >= prev_close and curr_open < curr_close:
|
|
49
|
+
self.lines.buy_signal[0] = float(self.data.low[0]) - atr * 3.0 / 8.0
|
|
50
|
+
if prev_open <= prev_close and curr_open > curr_close:
|
|
51
|
+
self.lines.sell_signal[0] = float(self.data.high[0]) + atr * 3.0 / 8.0
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Functional-test indicators migrated to contrib.
|
|
3
|
+
|
|
4
|
+
Generated from a single functional strategy module to preserve file-local
|
|
5
|
+
helper functions and constants without cross-test name collisions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import re
|
|
9
|
+
from collections import deque
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from .. import Indicator
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"MovingAverageFNIndicator",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
SOURCE_MQ5 = (
|
|
20
|
+
Path(__file__).resolve().parents[2]
|
|
21
|
+
/ "ea"
|
|
22
|
+
/ "1276_Exp_MovingAverage_FN"
|
|
23
|
+
/ "movingaverage_fn.mq5"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def resolve_price_line(data, mode):
|
|
28
|
+
"""Return the price line selected by an MT5 applied-price mode.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
data: The data feed providing OHLC lines.
|
|
32
|
+
mode: Applied-price mode name (e.g. ``price_close``, ``price_median``).
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The line or line expression for the requested applied price; defaults
|
|
36
|
+
to the close line for unrecognized modes.
|
|
37
|
+
"""
|
|
38
|
+
price_mode = str(mode).lower()
|
|
39
|
+
if price_mode in {"price_open", "open"}:
|
|
40
|
+
return data.open
|
|
41
|
+
if price_mode in {"price_high", "high"}:
|
|
42
|
+
return data.high
|
|
43
|
+
if price_mode in {"price_low", "low"}:
|
|
44
|
+
return data.low
|
|
45
|
+
if price_mode in {"price_median", "median"}:
|
|
46
|
+
return (data.high + data.low) / 2.0
|
|
47
|
+
if price_mode in {"price_typical", "typical"}:
|
|
48
|
+
return (data.high + data.low + data.close) / 3.0
|
|
49
|
+
if price_mode in {"price_weighted", "weighted"}:
|
|
50
|
+
return (data.high + data.low + data.close + data.close) / 4.0
|
|
51
|
+
return data.close
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def load_fn_coefficients(filter_name="N44"):
|
|
55
|
+
"""Parse FIR filter coefficients for a named filter from the MQ5 source.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
filter_name: Filter case name (e.g. ``N44``) to extract.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
List of float coefficients ordered by price-series offset; ``[1.0]`` if
|
|
62
|
+
the source file is missing.
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValueError: If the filter or the following case marker is not found.
|
|
66
|
+
"""
|
|
67
|
+
if not SOURCE_MQ5.exists():
|
|
68
|
+
return [1.0]
|
|
69
|
+
raw = SOURCE_MQ5.read_bytes()
|
|
70
|
+
candidates = []
|
|
71
|
+
for encoding in ("utf-16", "utf-16-le", "utf-8", "latin-1"):
|
|
72
|
+
candidates.append(raw.decode(encoding, errors="ignore"))
|
|
73
|
+
text = ""
|
|
74
|
+
for candidate in candidates:
|
|
75
|
+
normalized = candidate.replace("\x00", "")
|
|
76
|
+
if f"case {filter_name}:" in normalized:
|
|
77
|
+
text = normalized
|
|
78
|
+
break
|
|
79
|
+
if not text:
|
|
80
|
+
text = raw.decode("latin-1", errors="ignore").replace("\x00", "")
|
|
81
|
+
start = text.find(f"case {filter_name}:")
|
|
82
|
+
if start == -1:
|
|
83
|
+
raise ValueError(f"Filter {filter_name} not found in {SOURCE_MQ5}")
|
|
84
|
+
next_case = re.search(r"\n\s*case\s+N\d+:", text[start + 1 :])
|
|
85
|
+
if not next_case:
|
|
86
|
+
raise ValueError(f"Could not locate next filter after {filter_name}")
|
|
87
|
+
block = text[start : start + 1 + next_case.start()]
|
|
88
|
+
matches = re.findall(
|
|
89
|
+
r"([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\*PriceSeries\(Price,index(?:-(\d+))?", block
|
|
90
|
+
)
|
|
91
|
+
coeff_map = {int(offset or "0"): float(coef) for coef, offset in matches}
|
|
92
|
+
coeffs = [coeff_map[i] for i in range(max(coeff_map) + 1)]
|
|
93
|
+
return coeffs
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class MovingAverageFNIndicator(Indicator):
|
|
97
|
+
"""FIR moving average built from named filter coefficients plus smoothing."""
|
|
98
|
+
|
|
99
|
+
lines = ("mafn",)
|
|
100
|
+
params = (
|
|
101
|
+
("filter_number", "N44"),
|
|
102
|
+
("xma_method", "jjma"),
|
|
103
|
+
("xlength", 12),
|
|
104
|
+
("xphase", 15),
|
|
105
|
+
("ipc", "price_close"),
|
|
106
|
+
("price_shift", 0),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def __init__(self):
|
|
110
|
+
"""Load the filter coefficients and set up the smoothing buffer."""
|
|
111
|
+
self._coeffs = load_fn_coefficients(self.p.filter_number)
|
|
112
|
+
self._price_line = resolve_price_line(self.data, self.p.ipc)
|
|
113
|
+
self._smooth_values = deque(maxlen=max(1, int(self.p.xlength)))
|
|
114
|
+
self.addminperiod(len(self._coeffs) + self.p.xlength + 5)
|
|
115
|
+
|
|
116
|
+
def _smooth_filtered(self, value):
|
|
117
|
+
self._smooth_values.append(value)
|
|
118
|
+
values = list(self._smooth_values)
|
|
119
|
+
if not values:
|
|
120
|
+
return value
|
|
121
|
+
mode = str(self.p.xma_method).lower()
|
|
122
|
+
if mode in {"sma", "mode_sma"}:
|
|
123
|
+
return sum(values) / len(values)
|
|
124
|
+
if mode in {"ema", "mode_ema"}:
|
|
125
|
+
alpha = 2.0 / (len(values) + 1.0)
|
|
126
|
+
ema = values[0]
|
|
127
|
+
for item in values[1:]:
|
|
128
|
+
ema = alpha * item + (1.0 - alpha) * ema
|
|
129
|
+
return ema
|
|
130
|
+
weights = list(range(1, len(values) + 1))
|
|
131
|
+
weight_sum = float(sum(weights))
|
|
132
|
+
return sum(v * w for v, w in zip(values, weights)) / weight_sum
|
|
133
|
+
|
|
134
|
+
def next(self):
|
|
135
|
+
"""Convolve the filter coefficients with price and emit the smoothed value."""
|
|
136
|
+
filtered = 0.0
|
|
137
|
+
for offset, coef in enumerate(self._coeffs):
|
|
138
|
+
filtered += coef * float(self._price_line[-offset])
|
|
139
|
+
self.lines.mafn[0] = self._smooth_filtered(filtered) + float(self.p.price_shift)
|