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,123 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Price transform and simple signal indicators.
|
|
3
|
+
|
|
4
|
+
This module hosts small price-derived indicators migrated from functional
|
|
5
|
+
strategy tests. They are intentionally lightweight and depend only on the
|
|
6
|
+
standard Backtrader line API so they can be reused as ``bt.indicators.Xxx``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from . import Indicator
|
|
10
|
+
from .sma import SMA
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"HighLowAverage",
|
|
14
|
+
"MedianPrice",
|
|
15
|
+
"PercentReturnsPeriod",
|
|
16
|
+
"SMACloseSignal",
|
|
17
|
+
"TypicalPrice",
|
|
18
|
+
"WeightedPrice",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WeightedPrice(Indicator):
|
|
23
|
+
"""Weighted price ``(high + low + 2 * close) / 4``.
|
|
24
|
+
|
|
25
|
+
The indicator exposes both ``value`` and ``weighted`` lines because the
|
|
26
|
+
migrated functional tests used both names for the same formula.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
lines = ("value", "weighted")
|
|
30
|
+
|
|
31
|
+
def __init__(self):
|
|
32
|
+
"""Wire the weighted price series into both ``value`` and ``weighted`` lines."""
|
|
33
|
+
weighted = (self.data.high + self.data.low + self.data.close * 2.0) / 4.0
|
|
34
|
+
self.lines.value = weighted
|
|
35
|
+
self.lines.weighted = weighted
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MedianPrice(Indicator):
|
|
39
|
+
"""Median price ``(high + low) / 2``."""
|
|
40
|
+
|
|
41
|
+
lines = ("value", "median")
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
"""Wire the median-price series into both ``value`` and ``median`` lines."""
|
|
45
|
+
median = (self.data.high + self.data.low) / 2.0
|
|
46
|
+
self.lines.value = median
|
|
47
|
+
self.lines.median = median
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TypicalPrice(Indicator):
|
|
51
|
+
"""Typical price ``(high + low + close) / 3``."""
|
|
52
|
+
|
|
53
|
+
lines = ("typical", "value")
|
|
54
|
+
|
|
55
|
+
def __init__(self):
|
|
56
|
+
"""Wire the typical-price series into both ``typical`` and ``value`` lines."""
|
|
57
|
+
typical = (self.data.high + self.data.low + self.data.close) / 3.0
|
|
58
|
+
self.lines.typical = typical
|
|
59
|
+
self.lines.value = typical
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class HighLowAverage(Indicator):
|
|
63
|
+
"""Rolling average of the high-low range."""
|
|
64
|
+
|
|
65
|
+
lines = ("avg",)
|
|
66
|
+
params = (("period", 50),)
|
|
67
|
+
|
|
68
|
+
def __init__(self):
|
|
69
|
+
"""Reserve the rolling window used for the high-low range average."""
|
|
70
|
+
self.addminperiod(self.p.period)
|
|
71
|
+
|
|
72
|
+
def next(self):
|
|
73
|
+
"""Write the mean high-low range over the configured window to ``avg``.
|
|
74
|
+
|
|
75
|
+
Sums ``high - low`` for each of the last ``period`` bars
|
|
76
|
+
(current inclusive) and divides by ``period``. The output
|
|
77
|
+
line is updated in place; no value is returned.
|
|
78
|
+
"""
|
|
79
|
+
total = 0.0
|
|
80
|
+
for i in range(self.p.period):
|
|
81
|
+
total += float(self.data.high[-i] - self.data.low[-i])
|
|
82
|
+
self.lines.avg[0] = total / self.p.period
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class PercentReturnsPeriod(Indicator):
|
|
86
|
+
"""Percentage return over ``period`` bars using the close line."""
|
|
87
|
+
|
|
88
|
+
lines = ("returns",)
|
|
89
|
+
params = (("period", 40),)
|
|
90
|
+
|
|
91
|
+
def __init__(self):
|
|
92
|
+
"""Reserve the rolling window used for the percentage return."""
|
|
93
|
+
self.addminperiod(self.p.period)
|
|
94
|
+
|
|
95
|
+
def next(self):
|
|
96
|
+
"""Write ``(close - close[-period]) / close[-period]`` to ``returns``.
|
|
97
|
+
|
|
98
|
+
Uses the close at ``-period`` as the baseline so the value
|
|
99
|
+
is the simple percentage change over the configured window.
|
|
100
|
+
When the baseline is zero the value is forced to ``0`` to
|
|
101
|
+
avoid a division-by-zero error.
|
|
102
|
+
"""
|
|
103
|
+
previous = self.data.close[-self.p.period]
|
|
104
|
+
if previous != 0:
|
|
105
|
+
self.lines.returns[0] = (self.data.close[0] - previous) / previous
|
|
106
|
+
else:
|
|
107
|
+
self.lines.returns[0] = 0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class SMACloseSignal(Indicator):
|
|
111
|
+
"""Signal line equal to current price minus its SMA."""
|
|
112
|
+
|
|
113
|
+
lines = ("signal",)
|
|
114
|
+
params = (("period", 30),)
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
"""Compute ``data - SMA(data, period)`` and bind it to the ``signal`` line.
|
|
118
|
+
|
|
119
|
+
The line goes positive when the close is above its SMA and
|
|
120
|
+
negative when it is below, making it a simple momentum
|
|
121
|
+
proxy.
|
|
122
|
+
"""
|
|
123
|
+
self.lines.signal = self.data - SMA(self.data, period=self.p.period)
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Price Oscillator Module - Price oscillators.
|
|
3
|
+
|
|
4
|
+
This module provides Price Oscillator indicators that measure the
|
|
5
|
+
difference between two moving averages.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
_PriceOscBase: Base class for price oscillators.
|
|
9
|
+
PriceOscillator: Price difference (aliases: PriceOsc, APO, AbsPriceOsc).
|
|
10
|
+
PercentagePriceOscillator: Percentage price oscillator (aliases: PPO, PercPriceOsc).
|
|
11
|
+
PercentagePriceOscillatorShort: PPO with short denominator (aliases: PPOShort).
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
class MyStrategy(bt.Strategy):
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.ppo = bt.indicators.PPO(self.data, period1=12, period2=26)
|
|
17
|
+
|
|
18
|
+
def next(self):
|
|
19
|
+
if self.ppo.ppo[0] > self.ppo.signal[0]:
|
|
20
|
+
self.buy()
|
|
21
|
+
elif self.ppo.ppo[0] < self.ppo.signal[0]:
|
|
22
|
+
self.sell()
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import math
|
|
26
|
+
|
|
27
|
+
from . import Indicator, MovAv
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _PriceOscBase(Indicator):
|
|
31
|
+
params = (
|
|
32
|
+
("period1", 12),
|
|
33
|
+
("period2", 26),
|
|
34
|
+
("_movav", MovAv.Exponential),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
plotinfo = {"plothlines": [0.0]}
|
|
38
|
+
|
|
39
|
+
def __init__(self):
|
|
40
|
+
"""Initialize the price oscillator base class.
|
|
41
|
+
|
|
42
|
+
Creates two moving averages with configured periods.
|
|
43
|
+
"""
|
|
44
|
+
super().__init__()
|
|
45
|
+
self.ma1 = self.p._movav(self.data, period=self.p.period1)
|
|
46
|
+
self.ma2 = self.p._movav(self.data, period=self.p.period2)
|
|
47
|
+
|
|
48
|
+
def next(self):
|
|
49
|
+
"""Calculate oscillator value: ma1 - ma2."""
|
|
50
|
+
self.lines[0][0] = self.ma1[0] - self.ma2[0]
|
|
51
|
+
|
|
52
|
+
def once(self, start, end):
|
|
53
|
+
"""Calculate oscillator in runonce mode."""
|
|
54
|
+
ma1_array = self.ma1.lines[0].array
|
|
55
|
+
ma2_array = self.ma2.lines[0].array
|
|
56
|
+
larray = self.lines[0].array
|
|
57
|
+
|
|
58
|
+
while len(larray) < end:
|
|
59
|
+
larray.append(float("nan"))
|
|
60
|
+
|
|
61
|
+
for i in range(start, min(end, len(ma1_array), len(ma2_array))):
|
|
62
|
+
ma1_val = ma1_array[i] if i < len(ma1_array) else 0.0
|
|
63
|
+
ma2_val = ma2_array[i] if i < len(ma2_array) else 0.0
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
isinstance(ma1_val, float)
|
|
67
|
+
and math.isnan(ma1_val)
|
|
68
|
+
or isinstance(ma2_val, float)
|
|
69
|
+
and math.isnan(ma2_val)
|
|
70
|
+
):
|
|
71
|
+
larray[i] = float("nan")
|
|
72
|
+
else:
|
|
73
|
+
larray[i] = ma1_val - ma2_val
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Moving average difference
|
|
77
|
+
class PriceOscillator(_PriceOscBase):
|
|
78
|
+
"""
|
|
79
|
+
Shows the difference between a short and long exponential moving
|
|
80
|
+
averages expressed in points.
|
|
81
|
+
|
|
82
|
+
Formula:
|
|
83
|
+
- po = ema(short) - ema(long)
|
|
84
|
+
|
|
85
|
+
See:
|
|
86
|
+
- http://www.metastock.com/Customer/Resources/TAAZ/?c=3&p=94
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
alias = (
|
|
90
|
+
"PriceOsc",
|
|
91
|
+
"AbsolutePriceOscillator",
|
|
92
|
+
"APO",
|
|
93
|
+
"AbsPriceOsc",
|
|
94
|
+
)
|
|
95
|
+
lines = ("po",)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# Similar to MACD indicator, expressed in percentage
|
|
99
|
+
class PercentagePriceOscillator(_PriceOscBase):
|
|
100
|
+
"""
|
|
101
|
+
Shows the difference between a short and long exponential moving
|
|
102
|
+
averages expressed in percentage. The MACD does the same but expressed in
|
|
103
|
+
absolute points.
|
|
104
|
+
|
|
105
|
+
Expressing the difference in percentage allows to compare the indicator at
|
|
106
|
+
different points in time when the underlying value has significatnly
|
|
107
|
+
different values.
|
|
108
|
+
|
|
109
|
+
Formula:
|
|
110
|
+
- po = 100 * (ema(short) - ema(long)) / ema(long)
|
|
111
|
+
|
|
112
|
+
See:
|
|
113
|
+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:price_oscillators_ppo
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
_long = True
|
|
117
|
+
|
|
118
|
+
alias = (
|
|
119
|
+
"PPO",
|
|
120
|
+
"PercPriceOsc",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
lines = ("ppo", "signal", "histo")
|
|
124
|
+
params = (("period_signal", 9),)
|
|
125
|
+
|
|
126
|
+
plotlines = {"histo": {"_method": "bar", "alpha": 0.50, "width": 1.0}}
|
|
127
|
+
|
|
128
|
+
def __init__(self):
|
|
129
|
+
"""Initialize the PPO indicator.
|
|
130
|
+
|
|
131
|
+
Sets up signal line EMA parameters.
|
|
132
|
+
"""
|
|
133
|
+
super().__init__()
|
|
134
|
+
self.signal_alpha = 2.0 / (1.0 + self.p.period_signal)
|
|
135
|
+
self.signal_alpha1 = 1.0 - self.signal_alpha
|
|
136
|
+
|
|
137
|
+
def next(self):
|
|
138
|
+
"""Calculate PPO, signal, and histogram for current bar.
|
|
139
|
+
|
|
140
|
+
PPO = 100 * (ma1 - ma2) / ma2
|
|
141
|
+
Signal = EMA(PPO)
|
|
142
|
+
Histogram = PPO - Signal
|
|
143
|
+
"""
|
|
144
|
+
# Calculate base PO
|
|
145
|
+
po_val = self.ma1[0] - self.ma2[0]
|
|
146
|
+
|
|
147
|
+
# Calculate PPO
|
|
148
|
+
den = self.ma2[0] if self._long else self.ma1[0]
|
|
149
|
+
if den != 0:
|
|
150
|
+
ppo_val = 100.0 * po_val / den
|
|
151
|
+
else:
|
|
152
|
+
ppo_val = 0.0
|
|
153
|
+
self.lines.ppo[0] = ppo_val
|
|
154
|
+
|
|
155
|
+
# Calculate signal (EMA of PPO)
|
|
156
|
+
self.lines.signal[0] = (
|
|
157
|
+
self.lines.signal[-1] * self.signal_alpha1 + ppo_val * self.signal_alpha
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Calculate histogram
|
|
161
|
+
self.lines.histo[0] = self.lines.ppo[0] - self.lines.signal[0]
|
|
162
|
+
|
|
163
|
+
def nextstart(self):
|
|
164
|
+
"""Seed PPO calculation on first valid bar.
|
|
165
|
+
|
|
166
|
+
Initializes signal line with first PPO value.
|
|
167
|
+
"""
|
|
168
|
+
# Calculate base PO
|
|
169
|
+
po_val = self.ma1[0] - self.ma2[0]
|
|
170
|
+
|
|
171
|
+
# Calculate PPO
|
|
172
|
+
den = self.ma2[0] if self._long else self.ma1[0]
|
|
173
|
+
if den != 0:
|
|
174
|
+
ppo_val = 100.0 * po_val / den
|
|
175
|
+
else:
|
|
176
|
+
ppo_val = 0.0
|
|
177
|
+
self.lines.ppo[0] = ppo_val
|
|
178
|
+
|
|
179
|
+
# Seed signal with PPO
|
|
180
|
+
self.lines.signal[0] = ppo_val
|
|
181
|
+
|
|
182
|
+
# Calculate histogram
|
|
183
|
+
self.lines.histo[0] = 0.0
|
|
184
|
+
|
|
185
|
+
def once(self, start, end):
|
|
186
|
+
"""Calculate PPO in runonce mode."""
|
|
187
|
+
ma1_array = self.ma1.lines[0].array
|
|
188
|
+
ma2_array = self.ma2.lines[0].array
|
|
189
|
+
ppo_array = self.lines.ppo.array
|
|
190
|
+
signal_array = self.lines.signal.array
|
|
191
|
+
histo_array = self.lines.histo.array
|
|
192
|
+
signal_alpha = self.signal_alpha
|
|
193
|
+
signal_alpha1 = self.signal_alpha1
|
|
194
|
+
use_long = self._long
|
|
195
|
+
|
|
196
|
+
for arr in [ppo_array, signal_array, histo_array]:
|
|
197
|
+
while len(arr) < end:
|
|
198
|
+
arr.append(float("nan"))
|
|
199
|
+
|
|
200
|
+
prev_signal = 0.0
|
|
201
|
+
for i in range(start, min(end, len(ma1_array), len(ma2_array))):
|
|
202
|
+
ma1_val = ma1_array[i] if i < len(ma1_array) else 0.0
|
|
203
|
+
ma2_val = ma2_array[i] if i < len(ma2_array) else 0.0
|
|
204
|
+
|
|
205
|
+
if isinstance(ma1_val, float) and math.isnan(ma1_val):
|
|
206
|
+
ppo_array[i] = float("nan")
|
|
207
|
+
signal_array[i] = float("nan")
|
|
208
|
+
histo_array[i] = float("nan")
|
|
209
|
+
continue
|
|
210
|
+
if isinstance(ma2_val, float) and math.isnan(ma2_val):
|
|
211
|
+
ppo_array[i] = float("nan")
|
|
212
|
+
signal_array[i] = float("nan")
|
|
213
|
+
histo_array[i] = float("nan")
|
|
214
|
+
continue
|
|
215
|
+
|
|
216
|
+
po_val = ma1_val - ma2_val
|
|
217
|
+
|
|
218
|
+
den = ma2_val if use_long else ma1_val
|
|
219
|
+
if den != 0:
|
|
220
|
+
ppo_val = 100.0 * po_val / den
|
|
221
|
+
else:
|
|
222
|
+
ppo_val = 0.0
|
|
223
|
+
ppo_array[i] = ppo_val
|
|
224
|
+
|
|
225
|
+
# Update signal
|
|
226
|
+
if i > 0 and i - 1 < len(signal_array):
|
|
227
|
+
prev_val = signal_array[i - 1]
|
|
228
|
+
if not (isinstance(prev_val, float) and math.isnan(prev_val)):
|
|
229
|
+
prev_signal = prev_val
|
|
230
|
+
|
|
231
|
+
prev_signal = prev_signal * signal_alpha1 + ppo_val * signal_alpha
|
|
232
|
+
signal_array[i] = prev_signal
|
|
233
|
+
|
|
234
|
+
histo_array[i] = ppo_val - prev_signal
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class PercentagePriceOscillatorShort(PercentagePriceOscillator):
|
|
238
|
+
"""
|
|
239
|
+
Shows the difference between a short and long exponential moving
|
|
240
|
+
averages expressed in percentage. The MACD does the same but expressed in
|
|
241
|
+
absolute points.
|
|
242
|
+
|
|
243
|
+
Expressing the difference in percentage allows to compare the indicator at
|
|
244
|
+
different points in time when the underlying value has significatnly
|
|
245
|
+
different values.
|
|
246
|
+
|
|
247
|
+
Most on-line literature shows the percentage calculation having the long
|
|
248
|
+
exponential moving average as the denominator. Some sources like MetaStock
|
|
249
|
+
use the short one.
|
|
250
|
+
|
|
251
|
+
Formula:
|
|
252
|
+
- po = 100 * (ema(short) - ema(long)) / ema(short)
|
|
253
|
+
|
|
254
|
+
See:
|
|
255
|
+
- http://www.metastock.com/Customer/Resources/TAAZ/?c=3&p=94
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
_long = False
|
|
259
|
+
alias = (
|
|
260
|
+
"PPOShort",
|
|
261
|
+
"PercPriceOscShort",
|
|
262
|
+
)
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""PSAR Indicator Module - Parabolic SAR.
|
|
3
|
+
|
|
4
|
+
This module provides the Parabolic SAR (Stop and Reverse) indicator
|
|
5
|
+
developed by J. Welles Wilder, Jr. for trend following and reversal signals.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
ParabolicSAR: Parabolic SAR indicator (alias: PSAR).
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
class MyStrategy(bt.Strategy):
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.psar = bt.indicators.PSAR(self.data)
|
|
14
|
+
|
|
15
|
+
def next(self):
|
|
16
|
+
# PSAR dots below price indicate uptrend
|
|
17
|
+
if self.psar.psar[0] < self.data.low[0]:
|
|
18
|
+
self.buy()
|
|
19
|
+
# PSAR dots above price indicate downtrend
|
|
20
|
+
elif self.psar.psar[0] > self.data.high[0]:
|
|
21
|
+
self.sell()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from . import PeriodN
|
|
25
|
+
|
|
26
|
+
__all__ = ["ParabolicSAR", "PSAR"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class _SarStatus:
|
|
30
|
+
"""Internal status holder for Parabolic SAR calculations.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
sar: Stop and Reverse value for the current period.
|
|
34
|
+
tr: Trend direction (True for long/up, False for short/down).
|
|
35
|
+
af: Acceleration factor, controlling how quickly SAR responds.
|
|
36
|
+
ep: Extreme point - highest high in uptrend or lowest low in downtrend.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
sar = None
|
|
40
|
+
tr = None
|
|
41
|
+
af = 0.0
|
|
42
|
+
ep = 0.0
|
|
43
|
+
|
|
44
|
+
def __str__(self):
|
|
45
|
+
"""Return a string representation of the SAR status.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
str: Multi-line string containing sar, tr, af, and ep values.
|
|
49
|
+
"""
|
|
50
|
+
txt = []
|
|
51
|
+
txt.append(f"sar: {self.sar}")
|
|
52
|
+
txt.append(f"tr: {self.tr}")
|
|
53
|
+
txt.append(f"af: {self.af}")
|
|
54
|
+
txt.append(f"ep: {self.ep}")
|
|
55
|
+
return "\n".join(txt)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ParabolicSAR(PeriodN):
|
|
59
|
+
"""Parabolic SAR (Stop and Reverse) indicator.
|
|
60
|
+
|
|
61
|
+
Defined by J. Welles Wilder, Jr. in 1978 in his book *New Concepts in
|
|
62
|
+
Technical Trading Systems*. SAR stands for Stop and Reverse, and the
|
|
63
|
+
indicator is meant as a signal for entry (and reverse).
|
|
64
|
+
|
|
65
|
+
The indicator places dots above or below price bars to indicate the
|
|
66
|
+
current trend direction. When the dots flip from above to below (or
|
|
67
|
+
vice versa), it signals a potential trend reversal.
|
|
68
|
+
|
|
69
|
+
The initial trend direction is determined by comparing the close price
|
|
70
|
+
of the second bar to the first bar. The SAR value accelerates toward
|
|
71
|
+
the price as the trend extends, using the acceleration factor.
|
|
72
|
+
|
|
73
|
+
See:
|
|
74
|
+
https://en.wikipedia.org/wiki/Parabolic_SAR
|
|
75
|
+
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:parabolic_sar
|
|
76
|
+
|
|
77
|
+
Attributes:
|
|
78
|
+
psar: Line containing the calculated Parabolic SAR values.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
period: Bar number from which to start showing values (default: 2).
|
|
82
|
+
af: Acceleration factor (default: 0.02).
|
|
83
|
+
afmax: Maximum acceleration factor (default: 0.20).
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
alias = ("PSAR",)
|
|
87
|
+
lines = ("psar",)
|
|
88
|
+
params = (
|
|
89
|
+
("period", 2), # when to start showing values
|
|
90
|
+
("af", 0.02),
|
|
91
|
+
("afmax", 0.20),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
plotinfo = {"subplot": False}
|
|
95
|
+
plotlines = {
|
|
96
|
+
"psar": {"marker": ".", "markersize": 4.0, "color": "black", "fillstyle": "full", "ls": ""},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
def prenext(self):
|
|
100
|
+
"""Handle calculations before minimum period is reached.
|
|
101
|
+
|
|
102
|
+
Initializes status tracking and calculates initial PSAR values.
|
|
103
|
+
"""
|
|
104
|
+
if len(self) == 1:
|
|
105
|
+
self._status = [] # empty status
|
|
106
|
+
return # not enough data to do anything
|
|
107
|
+
|
|
108
|
+
if len(self) == 2:
|
|
109
|
+
self.nextstart() # kickstart calculation
|
|
110
|
+
else:
|
|
111
|
+
self.next() # regular calc
|
|
112
|
+
|
|
113
|
+
self.lines.psar[0] = float("NaN") # no return yet still prenext
|
|
114
|
+
|
|
115
|
+
def nextstart(self):
|
|
116
|
+
"""Initialize PSAR calculation on first valid bar.
|
|
117
|
+
|
|
118
|
+
Determines initial trend direction and sets up status tracking.
|
|
119
|
+
"""
|
|
120
|
+
if self._status: # some states have been calculated
|
|
121
|
+
self.next() # delegate
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
# Prepare a status holding array, for current and previous lengths
|
|
125
|
+
self._status = [_SarStatus(), _SarStatus()]
|
|
126
|
+
|
|
127
|
+
# Start by looking if price has gone up/down (close) in the 2nd day to
|
|
128
|
+
# get an *entry* signal and configure the values as they would have
|
|
129
|
+
# been in the previous trend, including a sar value which is
|
|
130
|
+
# immediately invalidated in next, which reverses and sets the trend to
|
|
131
|
+
# the actual up/down value calculated with the close
|
|
132
|
+
# Put the 4 status variables in a Status holder
|
|
133
|
+
plenidx = (len(self) - 1) % 2 # previous length index (0 or 1)
|
|
134
|
+
status = self._status[plenidx]
|
|
135
|
+
|
|
136
|
+
# Calculate the status for previous length
|
|
137
|
+
status.sar = (self.data.high[0] + self.data.low[0]) / 2.0
|
|
138
|
+
|
|
139
|
+
status.af = self.p.af
|
|
140
|
+
if self.data.close[0] >= self.data.close[-1]: # uptrend
|
|
141
|
+
status.tr = not True # uptrend when reversed
|
|
142
|
+
status.ep = self.data.low[-1] # ep from prev trend
|
|
143
|
+
else:
|
|
144
|
+
status.tr = not False # downtrend when reversed
|
|
145
|
+
status.ep = self.data.high[-1] # ep from prev trend
|
|
146
|
+
|
|
147
|
+
# With the fake prev trend in place and a sar which will be invalidated
|
|
148
|
+
# go to next to get the calculation done
|
|
149
|
+
self.next()
|
|
150
|
+
|
|
151
|
+
def next(self):
|
|
152
|
+
"""Calculate PSAR for the current bar.
|
|
153
|
+
|
|
154
|
+
Updates the stop-and-reverse point based on trend direction,
|
|
155
|
+
extreme price, and acceleration factor.
|
|
156
|
+
"""
|
|
157
|
+
hi = self.data.high[0]
|
|
158
|
+
lo = self.data.low[0]
|
|
159
|
+
|
|
160
|
+
plenidx = (len(self) - 1) % 2 # previous length index (0 or 1)
|
|
161
|
+
status = self._status[plenidx] # use prev status for calculations
|
|
162
|
+
|
|
163
|
+
tr = status.tr
|
|
164
|
+
sar = status.sar
|
|
165
|
+
|
|
166
|
+
# Check if the sar penetrated the price to switch the trend
|
|
167
|
+
if (tr and sar >= lo) or (not tr and sar <= hi):
|
|
168
|
+
tr = not tr # reverse the trend
|
|
169
|
+
sar = status.ep # new sar is prev SIP (Significant price)
|
|
170
|
+
ep = hi if tr else lo # select new SIP / Extreme Price
|
|
171
|
+
af = self.p.af # reset acceleration factor
|
|
172
|
+
|
|
173
|
+
else: # use the precalculated values
|
|
174
|
+
ep = status.ep
|
|
175
|
+
af = status.af
|
|
176
|
+
|
|
177
|
+
# Update sar value for today
|
|
178
|
+
self.lines.psar[0] = sar
|
|
179
|
+
|
|
180
|
+
# Update ep and af if needed
|
|
181
|
+
if tr: # long trade
|
|
182
|
+
if hi > ep:
|
|
183
|
+
ep = hi
|
|
184
|
+
af = min(af + self.p.af, self.p.afmax)
|
|
185
|
+
|
|
186
|
+
else: # downtrend
|
|
187
|
+
if lo < ep:
|
|
188
|
+
ep = lo
|
|
189
|
+
af = min(af + self.p.af, self.p.afmax)
|
|
190
|
+
|
|
191
|
+
sar = sar + af * (ep - sar) # calculate the sar for tomorrow
|
|
192
|
+
|
|
193
|
+
# make sure sar doesn't go into hi/lows
|
|
194
|
+
if tr: # long trade
|
|
195
|
+
lo1 = self.data.low[-1]
|
|
196
|
+
if sar > lo or sar > lo1:
|
|
197
|
+
sar = min(lo, lo1) # sar not above last 2 lows -> lower
|
|
198
|
+
else:
|
|
199
|
+
hi1 = self.data.high[-1]
|
|
200
|
+
if sar < hi or sar < hi1:
|
|
201
|
+
sar = max(hi, hi1) # sar not below last 2 highs -> highest
|
|
202
|
+
|
|
203
|
+
# new status has been calculated, keep it in current length
|
|
204
|
+
# will be used when length moves forward
|
|
205
|
+
newstatus = self._status[not plenidx]
|
|
206
|
+
newstatus.tr = tr
|
|
207
|
+
newstatus.sar = sar
|
|
208
|
+
newstatus.ep = ep
|
|
209
|
+
newstatus.af = af
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
PSAR = ParabolicSAR
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Relative Momentum Index Module - RMI indicator.
|
|
3
|
+
|
|
4
|
+
This module provides the Relative Momentum Index (RMI) developed by
|
|
5
|
+
Roger Altman as a variation of RSI.
|
|
6
|
+
|
|
7
|
+
Classes:
|
|
8
|
+
RelativeMomentumIndex: RMI indicator (alias: RMI).
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
class MyStrategy(bt.Strategy):
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.rmi = bt.indicators.RMI(self.data, period=20, lookback=5)
|
|
14
|
+
|
|
15
|
+
def next(self):
|
|
16
|
+
# RMI above 70 indicates overbought
|
|
17
|
+
if self.rmi.rmi[0] > 70:
|
|
18
|
+
self.sell()
|
|
19
|
+
# RMI below 30 indicates oversold
|
|
20
|
+
elif self.rmi.rmi[0] < 30:
|
|
21
|
+
self.buy()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from . import RSI
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RelativeMomentumIndex(RSI):
|
|
28
|
+
"""
|
|
29
|
+
Description:
|
|
30
|
+
The Relative Momentum Index was developed by Roger Altman and was
|
|
31
|
+
introduced in his article in the February 1993 issue of Technical Analysis
|
|
32
|
+
of Stocks & Commodities magazine.
|
|
33
|
+
|
|
34
|
+
While your typical RSI counts up and down days from close to close, the
|
|
35
|
+
Relative Momentum Index counts up and down days from the close relative to
|
|
36
|
+
a close x number of days ago. The result is an RSI that is a bit smoother.
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
Use in the same way you would any other RSI. There are overbought and
|
|
40
|
+
oversold zones, and can also be used for divergence and trend analysis.
|
|
41
|
+
|
|
42
|
+
See:
|
|
43
|
+
- https://www.marketvolume.com/technicalanalysis/relativemomentumindex.asp
|
|
44
|
+
- https://www.tradingview.com/script/UCm7fIvk-FREE-INDICATOR-Relative-Momentum-Index-RMI/
|
|
45
|
+
- https://www.prorealcode.com/prorealtime-indicators/relative-momentum-index-rmi/
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
alias = ("RMI",)
|
|
50
|
+
|
|
51
|
+
linealias = (
|
|
52
|
+
(
|
|
53
|
+
"rsi",
|
|
54
|
+
"rmi",
|
|
55
|
+
),
|
|
56
|
+
) # add an alias for this class rmi -> rsi
|
|
57
|
+
plotlines = {"rsi": {"_name": "rmi"}} # change line plotting name
|
|
58
|
+
|
|
59
|
+
params = (
|
|
60
|
+
("period", 20),
|
|
61
|
+
("lookback", 5),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def _plotlabel(self):
|
|
65
|
+
# override to always print the lookback label and do it before movav
|
|
66
|
+
plabels = [self.p.period]
|
|
67
|
+
plabels += [self.p.lookback]
|
|
68
|
+
plabels += [self.p.movav] * self.p.notdefault("movav")
|
|
69
|
+
return plabels
|