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.
Files changed (465) hide show
  1. back_trader_python-1.4.0.dist-info/METADATA +1491 -0
  2. back_trader_python-1.4.0.dist-info/RECORD +465 -0
  3. back_trader_python-1.4.0.dist-info/WHEEL +5 -0
  4. back_trader_python-1.4.0.dist-info/licenses/LICENSE +674 -0
  5. back_trader_python-1.4.0.dist-info/top_level.txt +1 -0
  6. backtrader/__init__.py +148 -0
  7. backtrader/_cerebro/__init__.py +5 -0
  8. backtrader/_cerebro/channel.py +382 -0
  9. backtrader/_cerebro/execution.py +377 -0
  10. backtrader/_cerebro/lifecycle.py +143 -0
  11. backtrader/_cerebro/notifications.py +150 -0
  12. backtrader/_cerebro/presentation.py +230 -0
  13. backtrader/_cerebro/registry.py +593 -0
  14. backtrader/_cerebro/runnext.py +551 -0
  15. backtrader/_cerebro/runonce.py +142 -0
  16. backtrader/analyzer.py +594 -0
  17. backtrader/analyzers/__init__.py +50 -0
  18. backtrader/analyzers/annualreturn.py +226 -0
  19. backtrader/analyzers/calmar.py +165 -0
  20. backtrader/analyzers/drawdown.py +287 -0
  21. backtrader/analyzers/leverage.py +112 -0
  22. backtrader/analyzers/logreturnsrolling.py +190 -0
  23. backtrader/analyzers/periodstats.py +153 -0
  24. backtrader/analyzers/positions.py +119 -0
  25. backtrader/analyzers/pyfolio.py +470 -0
  26. backtrader/analyzers/returns.py +192 -0
  27. backtrader/analyzers/sharpe.py +307 -0
  28. backtrader/analyzers/sharpe_ratio_stats.py +534 -0
  29. backtrader/analyzers/sqn.py +112 -0
  30. backtrader/analyzers/timereturn.py +192 -0
  31. backtrader/analyzers/total_value.py +75 -0
  32. backtrader/analyzers/tradeanalyzer.py +278 -0
  33. backtrader/analyzers/transactions.py +141 -0
  34. backtrader/analyzers/vwr.py +245 -0
  35. backtrader/bokeh/__init__.py +155 -0
  36. backtrader/bokeh/analyzers/__init__.py +13 -0
  37. backtrader/bokeh/analyzers/plot.py +192 -0
  38. backtrader/bokeh/analyzers/recorder.py +181 -0
  39. backtrader/bokeh/app.py +1094 -0
  40. backtrader/bokeh/live/__init__.py +11 -0
  41. backtrader/bokeh/live/client.py +352 -0
  42. backtrader/bokeh/live/datahandler.py +346 -0
  43. backtrader/bokeh/plot_adapter.py +200 -0
  44. backtrader/bokeh/schemes/__init__.py +14 -0
  45. backtrader/bokeh/schemes/blackly.py +76 -0
  46. backtrader/bokeh/schemes/scheme.py +150 -0
  47. backtrader/bokeh/schemes/tradimo.py +82 -0
  48. backtrader/bokeh/tab.py +125 -0
  49. backtrader/bokeh/tabs/__init__.py +30 -0
  50. backtrader/bokeh/tabs/analyzer.py +120 -0
  51. backtrader/bokeh/tabs/config.py +154 -0
  52. backtrader/bokeh/tabs/live.py +109 -0
  53. backtrader/bokeh/tabs/log.py +185 -0
  54. backtrader/bokeh/tabs/metadata.py +182 -0
  55. backtrader/bokeh/tabs/performance.py +359 -0
  56. backtrader/bokeh/tabs/source.py +70 -0
  57. backtrader/bokeh/utils/__init__.py +8 -0
  58. backtrader/bokeh/utils/helpers.py +167 -0
  59. backtrader/bokeh/webapp.py +164 -0
  60. backtrader/broker.py +478 -0
  61. backtrader/brokers/__init__.py +36 -0
  62. backtrader/brokers/bbroker.py +2576 -0
  63. backtrader/brokers/btapibroker.py +8227 -0
  64. backtrader/brokers/hft/__init__.py +89 -0
  65. backtrader/brokers/hft/binance_bbo.py +625 -0
  66. backtrader/brokers/hft/binance_bbo_compare.py +1398 -0
  67. backtrader/brokers/hft/examples.py +1228 -0
  68. backtrader/brokers/hft/exchange.py +380 -0
  69. backtrader/brokers/hft/latency.py +309 -0
  70. backtrader/brokers/hft/matching_core.py +572 -0
  71. backtrader/brokers/hft/queue.py +238 -0
  72. backtrader/brokers/hft/recorder.py +88 -0
  73. backtrader/brokers/hft/state.py +138 -0
  74. backtrader/brokers/impact_models.py +118 -0
  75. backtrader/brokers/mixbroker.py +895 -0
  76. backtrader/brokers/tickbroker.py +1991 -0
  77. backtrader/btrun/__init__.py +12 -0
  78. backtrader/btrun/btrun.py +1218 -0
  79. backtrader/cerebro.py +828 -0
  80. backtrader/channel.py +682 -0
  81. backtrader/channels/__init__.py +23 -0
  82. backtrader/channels/bridge.py +186 -0
  83. backtrader/channels/funding.py +248 -0
  84. backtrader/channels/live_queue.py +216 -0
  85. backtrader/channels/live_validator.py +294 -0
  86. backtrader/channels/orderbook.py +257 -0
  87. backtrader/channels/tick.py +202 -0
  88. backtrader/comminfo.py +665 -0
  89. backtrader/commissions/__init__.py +106 -0
  90. backtrader/commissions/ctpoption.py +993 -0
  91. backtrader/configs/account_config_example.yaml +8 -0
  92. backtrader/dataseries.py +379 -0
  93. backtrader/errors.py +106 -0
  94. backtrader/events.py +980 -0
  95. backtrader/feed.py +1523 -0
  96. backtrader/feeds/__init__.py +75 -0
  97. backtrader/feeds/barrier.py +2006 -0
  98. backtrader/feeds/blaze.py +118 -0
  99. backtrader/feeds/btapifeed.py +1538 -0
  100. backtrader/feeds/btcsv.py +203 -0
  101. backtrader/feeds/chainer.py +114 -0
  102. backtrader/feeds/cryptohftdata.py +164 -0
  103. backtrader/feeds/csvgeneric.py +1205 -0
  104. backtrader/feeds/ctpcohort.py +1051 -0
  105. backtrader/feeds/influxfeed.py +158 -0
  106. backtrader/feeds/livefeed.py +71 -0
  107. backtrader/feeds/mixed_channel.py +108 -0
  108. backtrader/feeds/mt4csv.py +42 -0
  109. backtrader/feeds/pandafeed.py +381 -0
  110. backtrader/feeds/quandl.py +256 -0
  111. backtrader/feeds/rollover.py +229 -0
  112. backtrader/feeds/sierrachart.py +30 -0
  113. backtrader/feeds/vchart.py +162 -0
  114. backtrader/feeds/vchartcsv.py +84 -0
  115. backtrader/feeds/vchartfile.py +153 -0
  116. backtrader/feeds/yahoo.py +399 -0
  117. backtrader/fillers.py +148 -0
  118. backtrader/filters/__init__.py +34 -0
  119. backtrader/filters/bsplitter.py +127 -0
  120. backtrader/filters/calendardays.py +121 -0
  121. backtrader/filters/datafiller.py +192 -0
  122. backtrader/filters/datafilter.py +74 -0
  123. backtrader/filters/daysteps.py +96 -0
  124. backtrader/filters/heikinashi.py +63 -0
  125. backtrader/filters/renko.py +164 -0
  126. backtrader/filters/session.py +289 -0
  127. backtrader/flt.py +80 -0
  128. backtrader/functions.py +960 -0
  129. backtrader/indicator.py +449 -0
  130. backtrader/indicators/__init__.py +148 -0
  131. backtrader/indicators/accdecoscillator.py +110 -0
  132. backtrader/indicators/aroon.py +300 -0
  133. backtrader/indicators/atr.py +315 -0
  134. backtrader/indicators/awesomeoscillator.py +122 -0
  135. backtrader/indicators/basicops.py +834 -0
  136. backtrader/indicators/bollinger.py +223 -0
  137. backtrader/indicators/cci.py +89 -0
  138. backtrader/indicators/channels_ext.py +83 -0
  139. backtrader/indicators/contrib/__init__.py +228 -0
  140. backtrader/indicators/contrib/absolutely_no_lag_lwma.py +28 -0
  141. backtrader/indicators/contrib/absolutely_no_lag_lwma_color.py +44 -0
  142. backtrader/indicators/contrib/accumulation_distribution_line.py +92 -0
  143. backtrader/indicators/contrib/adx_cross_hull_style_indicator.py +249 -0
  144. backtrader/indicators/contrib/adxdmi.py +34 -0
  145. backtrader/indicators/contrib/ai_acceleration_deceleration_oscillator.py +34 -0
  146. backtrader/indicators/contrib/altr_trend_signal_v22.py +85 -0
  147. backtrader/indicators/contrib/anchored_momentum_line.py +115 -0
  148. backtrader/indicators/contrib/any_range_cld_tail_indicator.py +82 -0
  149. backtrader/indicators/contrib/aroon_horn_sign_indicator.py +96 -0
  150. backtrader/indicators/contrib/aroon_oscillator_sign_alert.py +50 -0
  151. backtrader/indicators/contrib/arrows_curves_indicator.py +112 -0
  152. backtrader/indicators/contrib/as_ctrend_indicator.py +143 -0
  153. backtrader/indicators/contrib/asimmetric_stoch_nr_indicator.py +187 -0
  154. backtrader/indicators/contrib/atr_normalize_histogram.py +118 -0
  155. backtrader/indicators/contrib/average_change_candle.py +165 -0
  156. backtrader/indicators/contrib/bb_squeeze_indicator.py +60 -0
  157. backtrader/indicators/contrib/bezier_st_dev_indicator.py +135 -0
  158. backtrader/indicators/contrib/binary_wave_indicator.py +233 -0
  159. backtrader/indicators/contrib/blau_c_momentum_indicator.py +123 -0
  160. backtrader/indicators/contrib/blau_cmi_indicator.py +141 -0
  161. backtrader/indicators/contrib/blau_csi.py +76 -0
  162. backtrader/indicators/contrib/blau_ergodic.py +53 -0
  163. backtrader/indicators/contrib/blau_t_stoch_i.py +72 -0
  164. backtrader/indicators/contrib/blau_ts_stochastic.py +85 -0
  165. backtrader/indicators/contrib/blau_tvi.py +55 -0
  166. backtrader/indicators/contrib/brain_trend2_indicator.py +128 -0
  167. backtrader/indicators/contrib/brain_trend_signal_proxy.py +47 -0
  168. backtrader/indicators/contrib/brake_parb_indicator.py +85 -0
  169. backtrader/indicators/contrib/breakout_bars_trend_v2.py +121 -0
  170. backtrader/indicators/contrib/bsi_indicator.py +87 -0
  171. backtrader/indicators/contrib/bulls_bears_eyes.py +67 -0
  172. backtrader/indicators/contrib/bulls_power.py +56 -0
  173. backtrader/indicators/contrib/bw_wise_man1_signal.py +102 -0
  174. backtrader/indicators/contrib/bykov_trend_indicator.py +85 -0
  175. backtrader/indicators/contrib/candle_stop_color.py +46 -0
  176. backtrader/indicators/contrib/candles_x_smoothed_indicator.py +69 -0
  177. backtrader/indicators/contrib/candlesticks_bw.py +45 -0
  178. backtrader/indicators/contrib/caudate_x_period_candle_color.py +56 -0
  179. backtrader/indicators/contrib/cci_histogram_indicator.py +53 -0
  180. backtrader/indicators/contrib/cci_woodies_indicator.py +80 -0
  181. backtrader/indicators/contrib/center_of_gravity_candle_indicator.py +83 -0
  182. backtrader/indicators/contrib/center_of_gravity_indicator.py +70 -0
  183. backtrader/indicators/contrib/cg_oscillator.py +40 -0
  184. backtrader/indicators/contrib/close_line_cci.py +38 -0
  185. backtrader/indicators/contrib/close_price_fractals.py +47 -0
  186. backtrader/indicators/contrib/color3rd_gen_xma_indicator.py +122 -0
  187. backtrader/indicators/contrib/color_bb_candles_indicator.py +108 -0
  188. backtrader/indicators/contrib/color_coppock_indicator.py +157 -0
  189. backtrader/indicators/contrib/color_hma.py +71 -0
  190. backtrader/indicators/contrib/color_j_variation_indicator.py +53 -0
  191. backtrader/indicators/contrib/color_metro_de_marker_indicator.py +78 -0
  192. backtrader/indicators/contrib/color_metro_stochastic_indicator.py +93 -0
  193. backtrader/indicators/contrib/color_metro_wpr_indicator.py +85 -0
  194. backtrader/indicators/contrib/color_schaff_de_marker_trend_cycle.py +92 -0
  195. backtrader/indicators/contrib/color_schaff_trend_cycle_indicator.py +203 -0
  196. backtrader/indicators/contrib/color_step_xccx_indicator.py +193 -0
  197. backtrader/indicators/contrib/color_x2_ma.py +49 -0
  198. backtrader/indicators/contrib/color_x_derivative.py +63 -0
  199. backtrader/indicators/contrib/color_zerolag_de_marker.py +84 -0
  200. backtrader/indicators/contrib/corrected_average_indicator.py +127 -0
  201. backtrader/indicators/contrib/darvas_boxes_system.py +73 -0
  202. backtrader/indicators/contrib/dema_range_channel_color.py +42 -0
  203. backtrader/indicators/contrib/derivative_indicator.py +95 -0
  204. backtrader/indicators/contrib/digital_ft01_indicator.py +112 -0
  205. backtrader/indicators/contrib/digital_macd.py +200 -0
  206. backtrader/indicators/contrib/donchian_channels_system.py +45 -0
  207. backtrader/indicators/contrib/dots_indicator.py +93 -0
  208. backtrader/indicators/contrib/ef_distance_indicator.py +82 -0
  209. backtrader/indicators/contrib/ema_rsi_va.py +80 -0
  210. backtrader/indicators/contrib/envelopes_jp_alonso.py +32 -0
  211. backtrader/indicators/contrib/f2a_ao_indicator.py +120 -0
  212. backtrader/indicators/contrib/fatl_filter.py +179 -0
  213. backtrader/indicators/contrib/fibo_candles_indicator.py +78 -0
  214. backtrader/indicators/contrib/fine_tuning_ma.py +100 -0
  215. backtrader/indicators/contrib/fisher_org_v1.py +102 -0
  216. backtrader/indicators/contrib/fisher_org_v1_sign.py +118 -0
  217. backtrader/indicators/contrib/force_index_ema.py +96 -0
  218. backtrader/indicators/contrib/force_index_ema_2.py +27 -0
  219. backtrader/indicators/contrib/forecast_oscilator.py +145 -0
  220. backtrader/indicators/contrib/fractal_amambk.py +81 -0
  221. backtrader/indicators/contrib/frama_series.py +84 -0
  222. backtrader/indicators/contrib/frasm_av2_indicator.py +104 -0
  223. backtrader/indicators/contrib/go_indicator.py +93 -0
  224. backtrader/indicators/contrib/hlr_indicator.py +95 -0
  225. backtrader/indicators/contrib/hma.py +50 -0
  226. backtrader/indicators/contrib/i4_drfv2.py +34 -0
  227. backtrader/indicators/contrib/i4_drfv3.py +38 -0
  228. backtrader/indicators/contrib/i_anch_mom_indicator.py +72 -0
  229. backtrader/indicators/contrib/i_de_marker_sign_indicator.py +64 -0
  230. backtrader/indicators/contrib/i_gap_indicator.py +45 -0
  231. backtrader/indicators/contrib/i_stoch_komposter_indicator.py +77 -0
  232. backtrader/indicators/contrib/i_trend_indicator.py +125 -0
  233. backtrader/indicators/contrib/iamma_indicator.py +39 -0
  234. backtrader/indicators/contrib/indexed_moving_average.py +33 -0
  235. backtrader/indicators/contrib/instantaneous_trend_filter_indicator.py +51 -0
  236. backtrader/indicators/contrib/inverse_reaction_indicator.py +41 -0
  237. backtrader/indicators/contrib/irsi_sign_indicator.py +95 -0
  238. backtrader/indicators/contrib/iwpr_sign_indicator.py +59 -0
  239. backtrader/indicators/contrib/j_brain_trend1_sig_indicator.py +233 -0
  240. backtrader/indicators/contrib/j_tpo_proxy.py +32 -0
  241. backtrader/indicators/contrib/jma_slope_indicator.py +73 -0
  242. backtrader/indicators/contrib/kalman_filter_indicator.py +119 -0
  243. backtrader/indicators/contrib/kalman_filter_line.py +127 -0
  244. backtrader/indicators/contrib/kama_indicator.py +150 -0
  245. backtrader/indicators/contrib/karacatica_indicator.py +99 -0
  246. backtrader/indicators/contrib/kdj_indicator.py +59 -0
  247. backtrader/indicators/contrib/kwan_ccc_indicator.py +195 -0
  248. backtrader/indicators/contrib/kwan_nrp_indicator.py +113 -0
  249. backtrader/indicators/contrib/kwan_rdp_indicator.py +192 -0
  250. backtrader/indicators/contrib/laguerre_adx_indicator.py +85 -0
  251. backtrader/indicators/contrib/laguerre_filter_indicator.py +66 -0
  252. backtrader/indicators/contrib/laguerre_plus_di_proxy.py +57 -0
  253. backtrader/indicators/contrib/laguerre_roc_indicator.py +81 -0
  254. backtrader/indicators/contrib/le_man_signal_indicator.py +63 -0
  255. backtrader/indicators/contrib/linear_reg_slope_v2_indicator.py +136 -0
  256. backtrader/indicators/contrib/loco_indicator.py +88 -0
  257. backtrader/indicators/contrib/lrma_indicator.py +185 -0
  258. backtrader/indicators/contrib/lsma_angle_indicator.py +106 -0
  259. backtrader/indicators/contrib/ma_rounding_channel_indicator.py +149 -0
  260. backtrader/indicators/contrib/macd2_indicator.py +61 -0
  261. backtrader/indicators/contrib/macd_candle_indicator.py +80 -0
  262. backtrader/indicators/contrib/malr_indicator.py +77 -0
  263. backtrader/indicators/contrib/momentum_candle_sign_indicator.py +51 -0
  264. backtrader/indicators/contrib/moving_average_fn_indicator.py +139 -0
  265. backtrader/indicators/contrib/mt5_stochastic_close_close.py +57 -0
  266. backtrader/indicators/contrib/muv_nor_diff_cloud_indicator.py +107 -0
  267. backtrader/indicators/contrib/non_lag_dot_indicator.py +124 -0
  268. backtrader/indicators/contrib/nrtr_extr_indicator.py +95 -0
  269. backtrader/indicators/contrib/nrtr_indicator.py +95 -0
  270. backtrader/indicators/contrib/p_channel_system.py +40 -0
  271. backtrader/indicators/contrib/percent_envelope.py +37 -0
  272. backtrader/indicators/contrib/percentage_crossover_channel.py +47 -0
  273. backtrader/indicators/contrib/pivot_zig_zag_proxy.py +47 -0
  274. backtrader/indicators/contrib/price_channel_stop_indicator.py +104 -0
  275. backtrader/indicators/contrib/price_extreme_channel.py +35 -0
  276. backtrader/indicators/contrib/qqe_cloud_indicator.py +129 -0
  277. backtrader/indicators/contrib/ravi_indicator.py +40 -0
  278. backtrader/indicators/contrib/raw_close_close_stochastic.py +74 -0
  279. backtrader/indicators/contrib/rd_trend_trigger_indicator.py +51 -0
  280. backtrader/indicators/contrib/renko_level.py +85 -0
  281. backtrader/indicators/contrib/renko_line_break.py +91 -0
  282. backtrader/indicators/contrib/rftl_indicator.py +41 -0
  283. backtrader/indicators/contrib/rkd_indicator.py +53 -0
  284. backtrader/indicators/contrib/roc2_vg_indicator.py +68 -0
  285. backtrader/indicators/contrib/rsi_histogram_indicator.py +43 -0
  286. backtrader/indicators/contrib/rsi_slowdown.py +57 -0
  287. backtrader/indicators/contrib/rsioma_v2.py +41 -0
  288. backtrader/indicators/contrib/rvi_histogram_indicator.py +107 -0
  289. backtrader/indicators/contrib/safe_adx.py +89 -0
  290. backtrader/indicators/contrib/shared_strategy_indicators.py +1651 -0
  291. backtrader/indicators/contrib/sidus_indicator.py +105 -0
  292. backtrader/indicators/contrib/silver_trend_indicator.py +79 -0
  293. backtrader/indicators/contrib/sliding_range_color.py +56 -0
  294. backtrader/indicators/contrib/slow_stoch.py +42 -0
  295. backtrader/indicators/contrib/smoothed_adx_indicator.py +86 -0
  296. backtrader/indicators/contrib/smoothed_rsi.py +31 -0
  297. backtrader/indicators/contrib/spearman_rank_correlation_histogram.py +60 -0
  298. backtrader/indicators/contrib/stalin_indicator.py +152 -0
  299. backtrader/indicators/contrib/starter_laguerre_filter.py +62 -0
  300. backtrader/indicators/contrib/step_manrtr_indicator.py +137 -0
  301. backtrader/indicators/contrib/stochastic_histogram_indicator.py +143 -0
  302. backtrader/indicators/contrib/t3_alarm_indicator.py +125 -0
  303. backtrader/indicators/contrib/t3_average.py +76 -0
  304. backtrader/indicators/contrib/t3_indicator.py +40 -0
  305. backtrader/indicators/contrib/the20s_v020_signal.py +93 -0
  306. backtrader/indicators/contrib/three_candles_indicator.py +70 -0
  307. backtrader/indicators/contrib/three_line_break_indicator.py +64 -0
  308. backtrader/indicators/contrib/time_line.py +57 -0
  309. backtrader/indicators/contrib/trading_channel_index_proxy.py +48 -0
  310. backtrader/indicators/contrib/trend_arrows_indicator.py +109 -0
  311. backtrader/indicators/contrib/trend_continuation_indicator.py +127 -0
  312. backtrader/indicators/contrib/trend_intensity_index_proxy.py +51 -0
  313. backtrader/indicators/contrib/trend_manager_indicator.py +39 -0
  314. backtrader/indicators/contrib/tri_x_candle_indicator.py +51 -0
  315. backtrader/indicators/contrib/trigger_line.py +66 -0
  316. backtrader/indicators/contrib/triple_ema_rate.py +34 -0
  317. backtrader/indicators/contrib/trvi_indicator.py +194 -0
  318. backtrader/indicators/contrib/two_pb_ideal_xosma_indicator.py +127 -0
  319. backtrader/indicators/contrib/ultra_absolutely_no_lag_lwma_color.py +92 -0
  320. backtrader/indicators/contrib/ultra_wpr_indicator.py +173 -0
  321. backtrader/indicators/contrib/up_down_candle_strength.py +68 -0
  322. backtrader/indicators/contrib/vinin_i_trend_indicator.py +139 -0
  323. backtrader/indicators/contrib/volume_weighted_ma_indicator.py +78 -0
  324. backtrader/indicators/contrib/volume_weighted_ma_st_dev_indicator.py +111 -0
  325. backtrader/indicators/contrib/vwap_close_indicator.py +65 -0
  326. backtrader/indicators/contrib/vwma_candle.py +57 -0
  327. backtrader/indicators/contrib/vwma_digit_system.py +70 -0
  328. backtrader/indicators/contrib/wami.py +43 -0
  329. backtrader/indicators/contrib/wprsi_signal_indicator.py +105 -0
  330. backtrader/indicators/contrib/x_de_marker_histogram_vol_direct_indicator.py +145 -0
  331. backtrader/indicators/contrib/x_fisher_indicator.py +64 -0
  332. backtrader/indicators/contrib/xcci_histogram_vol_direct_indicator.py +56 -0
  333. backtrader/indicators/contrib/xcci_histogram_vol_indicator.py +85 -0
  334. backtrader/indicators/contrib/xma_ichimoku.py +163 -0
  335. backtrader/indicators/contrib/xma_ishimoku_channel_indicator.py +65 -0
  336. backtrader/indicators/contrib/xma_ishimoku_line.py +68 -0
  337. backtrader/indicators/contrib/xma_range_bands_indicator.py +107 -0
  338. backtrader/indicators/contrib/xmacd_indicator.py +70 -0
  339. backtrader/indicators/contrib/xrsi_de_marker_histogram.py +67 -0
  340. backtrader/indicators/contrib/xrsi_histogram_vol_direct_indicator.py +52 -0
  341. backtrader/indicators/contrib/xrsi_histogram_vol_indicator.py +81 -0
  342. backtrader/indicators/contrib/xrvi_indicator.py +130 -0
  343. backtrader/indicators/contrib/zero_lag_macd.py +36 -0
  344. backtrader/indicators/contrib/zig_zag_recent_pivot_signal.py +90 -0
  345. backtrader/indicators/contrib/zpf_indicator.py +115 -0
  346. backtrader/indicators/crossover.py +337 -0
  347. backtrader/indicators/dema.py +175 -0
  348. backtrader/indicators/demarker.py +270 -0
  349. backtrader/indicators/deviation.py +284 -0
  350. backtrader/indicators/directionalmove.py +1071 -0
  351. backtrader/indicators/dma.py +112 -0
  352. backtrader/indicators/dpo.py +96 -0
  353. backtrader/indicators/dv2.py +56 -0
  354. backtrader/indicators/ema.py +145 -0
  355. backtrader/indicators/envelope.py +475 -0
  356. backtrader/indicators/hadelta.py +198 -0
  357. backtrader/indicators/heikinashi.py +153 -0
  358. backtrader/indicators/hma.py +153 -0
  359. backtrader/indicators/hurst.py +151 -0
  360. backtrader/indicators/ichimoku.py +267 -0
  361. backtrader/indicators/kama.py +181 -0
  362. backtrader/indicators/kst.py +159 -0
  363. backtrader/indicators/lrsi.py +125 -0
  364. backtrader/indicators/mabase.py +147 -0
  365. backtrader/indicators/macd.py +322 -0
  366. backtrader/indicators/momentum.py +267 -0
  367. backtrader/indicators/moneyflow.py +237 -0
  368. backtrader/indicators/mt5atr.py +124 -0
  369. backtrader/indicators/myind.py +179 -0
  370. backtrader/indicators/obv.py +94 -0
  371. backtrader/indicators/ols.py +265 -0
  372. backtrader/indicators/oscillator.py +161 -0
  373. backtrader/indicators/percentchange.py +83 -0
  374. backtrader/indicators/percentrank.py +46 -0
  375. backtrader/indicators/pivotpoint.py +469 -0
  376. backtrader/indicators/prettygoodoscillator.py +113 -0
  377. backtrader/indicators/priceops_ext.py +123 -0
  378. backtrader/indicators/priceoscillator.py +262 -0
  379. backtrader/indicators/psar.py +212 -0
  380. backtrader/indicators/rmi.py +69 -0
  381. backtrader/indicators/rsi.py +440 -0
  382. backtrader/indicators/sma.py +141 -0
  383. backtrader/indicators/smma.py +116 -0
  384. backtrader/indicators/spread.py +54 -0
  385. backtrader/indicators/stochastic.py +263 -0
  386. backtrader/indicators/supertrend.py +436 -0
  387. backtrader/indicators/trend_ext.py +105 -0
  388. backtrader/indicators/trix.py +202 -0
  389. backtrader/indicators/tsi.py +155 -0
  390. backtrader/indicators/ultimateoscillator.py +158 -0
  391. backtrader/indicators/vortex.py +62 -0
  392. backtrader/indicators/williams.py +194 -0
  393. backtrader/indicators/wma.py +103 -0
  394. backtrader/indicators/zlema.py +135 -0
  395. backtrader/indicators/zlind.py +104 -0
  396. backtrader/linebuffer.py +3155 -0
  397. backtrader/lineiterator.py +2911 -0
  398. backtrader/lineroot.py +1106 -0
  399. backtrader/lineseries.py +2559 -0
  400. backtrader/live_trading/__init__.py +31 -0
  401. backtrader/live_trading/interface.py +404 -0
  402. backtrader/mathsupport.py +94 -0
  403. backtrader/metabase.py +1804 -0
  404. backtrader/mixins/__init__.py +21 -0
  405. backtrader/mixins/singleton.py +118 -0
  406. backtrader/observer.py +106 -0
  407. backtrader/observers/__init__.py +45 -0
  408. backtrader/observers/benchmark.py +126 -0
  409. backtrader/observers/broker.py +184 -0
  410. backtrader/observers/buysell.py +144 -0
  411. backtrader/observers/drawdown.py +161 -0
  412. backtrader/observers/logreturns.py +113 -0
  413. backtrader/observers/timereturn.py +86 -0
  414. backtrader/observers/trade_logger.py +2972 -0
  415. backtrader/observers/tradelogger.py +6 -0
  416. backtrader/observers/trades.py +258 -0
  417. backtrader/order.py +1114 -0
  418. backtrader/parameters.py +2345 -0
  419. backtrader/plot/__init__.py +54 -0
  420. backtrader/plot/finance.py +1022 -0
  421. backtrader/plot/formatters.py +200 -0
  422. backtrader/plot/locator.py +353 -0
  423. backtrader/plot/multicursor.py +495 -0
  424. backtrader/plot/plot.py +2500 -0
  425. backtrader/plot/plot_plotly.py +1351 -0
  426. backtrader/plot/scheme.py +253 -0
  427. backtrader/plot/utils.py +104 -0
  428. backtrader/position.py +290 -0
  429. backtrader/position_modes.py +132 -0
  430. backtrader/profiles.py +254 -0
  431. backtrader/reports/__init__.py +39 -0
  432. backtrader/reports/charts.py +371 -0
  433. backtrader/reports/performance.py +620 -0
  434. backtrader/reports/reporter.py +660 -0
  435. backtrader/resamplerfilter.py +1001 -0
  436. backtrader/signal.py +118 -0
  437. backtrader/signals/__init__.py +17 -0
  438. backtrader/sizer.py +114 -0
  439. backtrader/sizers/__init__.py +26 -0
  440. backtrader/sizers/fixedsize.py +161 -0
  441. backtrader/sizers/percents_sizer.py +119 -0
  442. backtrader/store.py +221 -0
  443. backtrader/stores/__init__.py +33 -0
  444. backtrader/stores/btapistore.py +15506 -0
  445. backtrader/stores/livestore.py +137 -0
  446. backtrader/stores/vchartfile.py +96 -0
  447. backtrader/strategy.py +3655 -0
  448. backtrader/talib.py +280 -0
  449. backtrader/test_helpers.py +96 -0
  450. backtrader/timer.py +358 -0
  451. backtrader/trade.py +442 -0
  452. backtrader/tradingcal.py +361 -0
  453. backtrader/utils/__init__.py +68 -0
  454. backtrader/utils/autodict.py +251 -0
  455. backtrader/utils/date.py +71 -0
  456. backtrader/utils/dateintern.py +509 -0
  457. backtrader/utils/flushfile.py +94 -0
  458. backtrader/utils/fractal.py +101 -0
  459. backtrader/utils/get_metrics.py +101 -0
  460. backtrader/utils/load_data.py +209 -0
  461. backtrader/utils/log_message.py +998 -0
  462. backtrader/utils/ordereddefaultdict.py +75 -0
  463. backtrader/utils/py3.py +296 -0
  464. backtrader/version.py +21 -0
  465. backtrader/writer.py +372 -0
@@ -0,0 +1,1071 @@
1
+ #!/usr/bin/env python
2
+ """Directional Movement Indicator Module - ADX and DI indicators.
3
+
4
+ This module provides the ADX (Average Directional Index) and
5
+ Directional Indicators developed by J. Welles Wilder, Jr. for
6
+ measuring trend strength.
7
+
8
+ Classes:
9
+ UpMove: Upward move calculation.
10
+ DownMove: Downward move calculation.
11
+ _DirectionalIndicator: Base class for DI calculations.
12
+ DirectionalIndicator: DI indicator (alias: DI).
13
+ PlusDirectionalIndicator: +DI indicator (aliases: PlusDI, +DI).
14
+ MinusDirectionalIndicator: -DI indicator (aliases: MinusDI, -DI).
15
+ AverageDirectionalMovementIndex: ADX indicator (alias: ADX).
16
+ AverageDirectionalMovementIndexRating: ADXR indicator (alias: ADXR).
17
+ DirectionalMovementIndex: DMI with ADX and DI (alias: DMI).
18
+ DirectionalMovement: Complete DM system (alias: DM).
19
+
20
+ Example:
21
+ class MyStrategy(bt.Strategy):
22
+ def __init__(self):
23
+ # Calculate ADX to measure trend strength
24
+ self.adx = bt.indicators.ADX(self.data, period=14)
25
+
26
+ # Or use DI for +DI and -DI
27
+ self.di = bt.indicators.DI(self.data, period=14)
28
+
29
+ def next(self):
30
+ # Buy when trend is strong (ADX > 25) and +DI crosses above -DI
31
+ if self.adx[0] > 25 and self.di.plusDI[0] > self.di.minusDI[0]:
32
+ self.buy()
33
+ """
34
+
35
+ from ..lineroot import LineRoot
36
+ from . import ATR, And, If, Indicator, MovAv
37
+
38
+
39
+ class UpMove(Indicator):
40
+ """
41
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
42
+ Technical Trading Systems"* as part of the Directional Move System to
43
+ calculate Directional Indicators.
44
+
45
+ Positive if the given data has moved higher than the previous day
46
+
47
+ Formula:
48
+ - upmove = data - data(-1)
49
+
50
+ See:
51
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
52
+ """
53
+
54
+ lines = ("upmove",)
55
+
56
+ def __init__(self):
57
+ """Initialize the UpMove indicator.
58
+
59
+ Sets minimum period to 2 for difference calculation.
60
+ """
61
+ super().__init__()
62
+ self.addminperiod(2)
63
+
64
+ def next(self):
65
+ """Calculate up move for the current bar.
66
+
67
+ Returns data - data(-1), the positive price change.
68
+ """
69
+ self.lines.upmove[0] = self.data[0] - self.data[-1]
70
+
71
+ def once(self, start, end):
72
+ """Calculate up moves in runonce mode.
73
+
74
+ Computes data[i] - data[i-1] for each bar.
75
+ """
76
+ darray = self.data.array
77
+ larray = self.lines.upmove.array
78
+
79
+ while len(larray) < end:
80
+ larray.append(float("nan"))
81
+
82
+ for i in range(1, min(end, len(darray))):
83
+ larray[i] = darray[i] - darray[i - 1]
84
+
85
+
86
+ class DownMove(Indicator):
87
+ """
88
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
89
+ Technical Trading Systems"* as part of the Directional Move System to
90
+ calculate Directional Indicators.
91
+
92
+ Positive if the given data has moved lower than the previous day
93
+
94
+ Formula:
95
+ - downmove = data(-1) - data
96
+
97
+ See:
98
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
99
+ """
100
+
101
+ lines = ("downmove",)
102
+
103
+ def __init__(self):
104
+ """Initialize the DownMove indicator.
105
+
106
+ Sets minimum period to 2 for difference calculation.
107
+ """
108
+ super().__init__()
109
+ self.addminperiod(2)
110
+
111
+ def next(self):
112
+ """Calculate down move for the current bar.
113
+
114
+ Returns data(-1) - data, the negative price change as positive value.
115
+ """
116
+ self.lines.downmove[0] = self.data[-1] - self.data[0]
117
+
118
+ def once(self, start, end):
119
+ """Calculate down moves in runonce mode.
120
+
121
+ Computes data[i-1] - data[i] for each bar.
122
+ """
123
+ darray = self.data.array
124
+ larray = self.lines.downmove.array
125
+
126
+ while len(larray) < end:
127
+ larray.append(float("nan"))
128
+
129
+ for i in range(1, min(end, len(darray))):
130
+ larray[i] = darray[i - 1] - darray[i]
131
+
132
+
133
+ class _DirectionalIndicator(Indicator):
134
+ """
135
+ This class serves as the root base class for all "Directional Movement
136
+ System" related indicators, given that the calculations are first common
137
+ and then derived from the common calculations.
138
+
139
+ It can calculate the +DI and -DI values (using kwargs as the hint as to
140
+ what to calculate) but doesn't assign them to lines. This is left for
141
+ sublcases of this class.
142
+ """
143
+
144
+ params = (("period", 14), ("movav", MovAv.Smoothed))
145
+
146
+ plotlines = {"plusDI": {"_name": "+DI"}, "minusDI": {"_name": "-DI"}}
147
+
148
+ def _plotlabel(self):
149
+ plabels = [self.p.period]
150
+ plabels += [self.p.movav] * self.p.notdefault("movav")
151
+ return plabels
152
+
153
+ def __init__(self, _plus=True, _minus=True):
154
+ """Initialize the directional indicator base.
155
+
156
+ Calculates +DI and -DI values based on directional movement.
157
+
158
+ Args:
159
+ _plus: Whether to calculate plus DI.
160
+ _minus: Whether to calculate minus DI.
161
+ """
162
+ self._di_atr = ATR(self.data, period=self.p.period, movav=self.p.movav)
163
+
164
+ upmove = self.data.high - self.data.high(-1)
165
+ downmove = self.data.low(-1) - self.data.low
166
+
167
+ if _plus:
168
+ plus = And(upmove > downmove, upmove > 0.0)
169
+ plusDM = If(plus, upmove, 0.0)
170
+ self._plusDMav = self.p.movav(plusDM, period=self.p.period)
171
+
172
+ self.DIplus = 100.0 * self._plusDMav / self._di_atr
173
+
174
+ if _minus:
175
+ minus = And(downmove > upmove, downmove > 0.0)
176
+ minusDM = If(minus, downmove, 0.0)
177
+ self._minusDMav = self.p.movav(minusDM, period=self.p.period)
178
+
179
+ self.DIminus = 100.0 * self._minusDMav / self._di_atr
180
+
181
+ super().__init__()
182
+
183
+
184
+ class DirectionalIndicator(_DirectionalIndicator):
185
+ """
186
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
187
+ Technical Trading Systems"*.
188
+
189
+ Intended to measure trend strength
190
+
191
+ This indicator shows +DI, -DI:
192
+ - Use PlusDirectionalIndicator (PlusDI) to get +DI
193
+ - Use MinusDirectionalIndicator (MinusDI) to get -DI
194
+ - Use AverageDirectionalIndex (ADX) to get ADX
195
+ - Use AverageDirectionalIndexRating (ADXR) to get ADX, ADXR
196
+ - Use DirectionalMovementIndex (DMI) to get ADX, +DI, -DI
197
+ - Use DirectionalMovement (DM) to get ADX, ADXR, +DI, -DI
198
+
199
+ Formula:
200
+ - upmove = high - high(-1)
201
+ - downmove = low(-1) - low
202
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
203
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
204
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
205
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
206
+
207
+ The moving average used is the one originally defined by Wilder,
208
+ the SmoothedMovingAverage
209
+
210
+ See:
211
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
212
+ """
213
+
214
+ alias = ("DI",)
215
+ lines = (
216
+ "plusDI",
217
+ "minusDI",
218
+ )
219
+
220
+ def __init__(self):
221
+ """Initialize the Directional Indicator.
222
+
223
+ Calculates both +DI and -DI from raw OHLC using Wilder smoothing.
224
+ """
225
+ super().__init__()
226
+ self.lines.plusDI = self.DIplus
227
+ self.lines.minusDI = self.DIminus
228
+ # State for Wilder smoothing (used by next/prenext)
229
+ self._sm_tr = 0.0
230
+ self._sm_pdm = 0.0
231
+ self._sm_mdm = 0.0
232
+ self._bar_count = 0
233
+
234
+ def prenext(self):
235
+ """Accumulate during warmup period."""
236
+ self._di_accumulate()
237
+
238
+ def nextstart(self):
239
+ """Transition from warmup to live calculation."""
240
+ self._di_accumulate()
241
+
242
+ def next(self):
243
+ """Calculate +DI and -DI for the current bar."""
244
+ self._di_accumulate()
245
+
246
+ def _di_accumulate(self):
247
+ """Accumulate TR/DM and compute DI using Wilder smoothing."""
248
+ period = self.p.period
249
+ high = self.data.high[0]
250
+ low = self.data.low[0]
251
+ if len(self.data) <= 1:
252
+ return
253
+ try:
254
+ prev_high = self.data.high[-1]
255
+ prev_low = self.data.low[-1]
256
+ prev_close = self.data.close[-1]
257
+ except IndexError:
258
+ return
259
+
260
+ true_high = max(high, prev_close)
261
+ true_low = min(low, prev_close)
262
+ tr = true_high - true_low
263
+
264
+ upmove = high - prev_high
265
+ downmove = prev_low - low
266
+ pdm = upmove if (upmove > downmove and upmove > 0) else 0.0
267
+ mdm = downmove if (downmove > upmove and downmove > 0) else 0.0
268
+
269
+ self._bar_count += 1
270
+
271
+ if self._bar_count <= period:
272
+ # Accumulate sums for seeding
273
+ self._sm_tr += tr
274
+ self._sm_pdm += pdm
275
+ self._sm_mdm += mdm
276
+ else:
277
+ # Wilder smoothing: val = val - val/period + new
278
+ self._sm_tr = self._sm_tr - self._sm_tr / period + tr
279
+ self._sm_pdm = self._sm_pdm - self._sm_pdm / period + pdm
280
+ self._sm_mdm = self._sm_mdm - self._sm_mdm / period + mdm
281
+
282
+ if self._sm_tr > 0:
283
+ self.lines.plusDI[0] = 100.0 * self._sm_pdm / self._sm_tr
284
+ self.lines.minusDI[0] = 100.0 * self._sm_mdm / self._sm_tr
285
+ else:
286
+ self.lines.plusDI[0] = 0.0
287
+ self.lines.minusDI[0] = 0.0
288
+
289
+ def once(self, start, end):
290
+ """Calculate DI values in runonce mode from raw OHLC."""
291
+ period = self.p.period
292
+ high_arr = self.data.high.array
293
+ low_arr = self.data.low.array
294
+ close_arr = self.data.close.array
295
+ dst_plus = self.lines.plusDI.array
296
+ dst_minus = self.lines.minusDI.array
297
+
298
+ while len(dst_plus) < end:
299
+ dst_plus.append(float("nan"))
300
+ while len(dst_minus) < end:
301
+ dst_minus.append(float("nan"))
302
+
303
+ sm_tr = 0.0
304
+ sm_pdm = 0.0
305
+ sm_mdm = 0.0
306
+ bar_count = 0
307
+
308
+ for i in range(1, min(end, len(high_arr), len(low_arr), len(close_arr))):
309
+ high = high_arr[i]
310
+ low = low_arr[i]
311
+ prev_high = high_arr[i - 1]
312
+ prev_low = low_arr[i - 1]
313
+ prev_close = close_arr[i - 1]
314
+
315
+ true_high = max(high, prev_close)
316
+ true_low = min(low, prev_close)
317
+ tr = true_high - true_low
318
+
319
+ upmove = high - prev_high
320
+ downmove = prev_low - low
321
+ pdm = upmove if (upmove > downmove and upmove > 0) else 0.0
322
+ mdm = downmove if (downmove > upmove and downmove > 0) else 0.0
323
+
324
+ bar_count += 1
325
+ if bar_count <= period:
326
+ sm_tr += tr
327
+ sm_pdm += pdm
328
+ sm_mdm += mdm
329
+ else:
330
+ sm_tr = sm_tr - sm_tr / period + tr
331
+ sm_pdm = sm_pdm - sm_pdm / period + pdm
332
+ sm_mdm = sm_mdm - sm_mdm / period + mdm
333
+
334
+ if sm_tr > 0:
335
+ dst_plus[i] = 100.0 * sm_pdm / sm_tr
336
+ dst_minus[i] = 100.0 * sm_mdm / sm_tr
337
+ else:
338
+ dst_plus[i] = 0.0
339
+ dst_minus[i] = 0.0
340
+
341
+ prenext = LineRoot.prenext # noqa: F811
342
+ nextstart = LineRoot.nextstart # noqa: F811
343
+ next = LineRoot.next # noqa: F811
344
+ preonce = LineRoot.preonce # noqa: F811
345
+ oncestart = LineRoot.oncestart # noqa: F811
346
+ once = LineRoot.once # noqa: F811
347
+
348
+
349
+ class PlusDirectionalIndicator(_DirectionalIndicator):
350
+ """
351
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
352
+ Technical Trading Systems"*.
353
+
354
+ Intended to measure trend strength
355
+
356
+ This indicator shows +DI:
357
+ - Use MinusDirectionalIndicator (MinusDI) to get -DI
358
+ - Use Directional Indicator (DI) to get +DI, -DI
359
+ - Use AverageDirectionalIndex (ADX) to get ADX
360
+ - Use AverageDirectionalIndexRating (ADXR) to get ADX, ADXR
361
+ - Use DirectionalMovementIndex (DMI) to get ADX, +DI, -DI
362
+ - Use DirectionalMovement (DM) to get ADX, ADXR, +DI, -DI
363
+
364
+ Formula:
365
+ - upmove = high - high(-1)
366
+ - downmove = low(-1) - low
367
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
368
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
369
+
370
+ The moving average used is the one originally defined by Wilder,
371
+ the SmoothedMovingAverage
372
+
373
+ See:
374
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
375
+ """
376
+
377
+ alias = (("PlusDI", "+DI"),)
378
+ lines = ("plusDI",)
379
+
380
+ plotinfo = {"plotname": "+DirectionalIndicator"}
381
+
382
+ def __init__(self):
383
+ """Initialize the +DI indicator."""
384
+ super().__init__(_minus=False)
385
+ self.lines.plusDI = self.DIplus
386
+ self._sm_tr = 0.0
387
+ self._sm_pdm = 0.0
388
+ self._bar_count = 0
389
+
390
+ def _pdi_accumulate(self):
391
+ period = self.p.period
392
+ high = self.data.high[0]
393
+ low = self.data.low[0]
394
+ if len(self.data) <= 1:
395
+ return
396
+ try:
397
+ prev_high = self.data.high[-1]
398
+ prev_low = self.data.low[-1]
399
+ prev_close = self.data.close[-1]
400
+ except IndexError:
401
+ return
402
+ tr = max(high, prev_close) - min(low, prev_close)
403
+ upmove = high - prev_high
404
+ downmove = prev_low - low
405
+ pdm = upmove if (upmove > downmove and upmove > 0) else 0.0
406
+ self._bar_count += 1
407
+ if self._bar_count <= period:
408
+ self._sm_tr += tr
409
+ self._sm_pdm += pdm
410
+ else:
411
+ self._sm_tr = self._sm_tr - self._sm_tr / period + tr
412
+ self._sm_pdm = self._sm_pdm - self._sm_pdm / period + pdm
413
+ self.lines.plusDI[0] = (100.0 * self._sm_pdm / self._sm_tr) if self._sm_tr > 0 else 0.0
414
+
415
+ def prenext(self):
416
+ """Called before minimum period is met.
417
+
418
+ Accumulates +DI values during the warmup period.
419
+ """
420
+ self._pdi_accumulate()
421
+
422
+ def nextstart(self):
423
+ """Called once minimum period is first met.
424
+
425
+ Accumulates +DI values at the start of normal operation.
426
+ """
427
+ self._pdi_accumulate()
428
+
429
+ def next(self):
430
+ """Called on each bar after minimum period is met.
431
+
432
+ Accumulates +DI values for the current bar.
433
+ """
434
+ self._pdi_accumulate()
435
+
436
+ def once(self, start, end):
437
+ """Vectorized calculation of +DI values.
438
+
439
+ Args:
440
+ start: Start index for calculation.
441
+ end: End index for calculation.
442
+ """
443
+ period = self.p.period
444
+ high_arr = self.data.high.array
445
+ low_arr = self.data.low.array
446
+ close_arr = self.data.close.array
447
+ dst = self.lines.plusDI.array
448
+ while len(dst) < end:
449
+ dst.append(float("nan"))
450
+ sm_tr = 0.0
451
+ sm_pdm = 0.0
452
+ bc = 0
453
+ for i in range(1, min(end, len(high_arr), len(low_arr), len(close_arr))):
454
+ tr = max(high_arr[i], close_arr[i - 1]) - min(low_arr[i], close_arr[i - 1])
455
+ upmove = high_arr[i] - high_arr[i - 1]
456
+ downmove = low_arr[i - 1] - low_arr[i]
457
+ pdm = upmove if (upmove > downmove and upmove > 0) else 0.0
458
+ bc += 1
459
+ if bc <= period:
460
+ sm_tr += tr
461
+ sm_pdm += pdm
462
+ else:
463
+ sm_tr = sm_tr - sm_tr / period + tr
464
+ sm_pdm = sm_pdm - sm_pdm / period + pdm
465
+ dst[i] = (100.0 * sm_pdm / sm_tr) if sm_tr > 0 else 0.0
466
+
467
+ prenext = LineRoot.prenext # noqa: F811
468
+ nextstart = LineRoot.nextstart # noqa: F811
469
+ next = LineRoot.next # noqa: F811
470
+ preonce = LineRoot.preonce # noqa: F811
471
+ oncestart = LineRoot.oncestart # noqa: F811
472
+ once = LineRoot.once # noqa: F811
473
+
474
+
475
+ class MinusDirectionalIndicator(_DirectionalIndicator):
476
+ """
477
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
478
+ Technical Trading Systems"*.
479
+
480
+ Intended to measure trend strength
481
+
482
+ This indicator shows -DI:
483
+ - Use PlusDirectionalIndicator (PlusDI) to get +DI
484
+ - Use Directional Indicator (DI) to get +DI, -DI
485
+ - Use AverageDirectionalIndex (ADX) to get ADX
486
+ - Use AverageDirectionalIndexRating (ADXR) to get ADX, ADXR
487
+ - Use DirectionalMovementIndex (DMI) to get ADX, +DI, -DI
488
+ - Use DirectionalMovement (DM) to get ADX, ADXR, +DI, -DI
489
+
490
+ Formula:
491
+ - upmove = high - high(-1)
492
+ - downmove = low(-1) - low
493
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
494
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
495
+
496
+ The moving average used is the one originally defined by Wilder,
497
+ the SmoothedMovingAverage
498
+
499
+ See:
500
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
501
+ """
502
+
503
+ alias = (("MinusDI", "-DI"),)
504
+ lines = ("minusDI",)
505
+
506
+ plotinfo = {"plotname": "-DirectionalIndicator"}
507
+
508
+ def __init__(self):
509
+ """Initialize the -DI indicator."""
510
+ super().__init__(_plus=False)
511
+ self.lines.minusDI = self.DIminus
512
+ self._sm_tr = 0.0
513
+ self._sm_mdm = 0.0
514
+ self._bar_count = 0
515
+
516
+ def _mdi_accumulate(self):
517
+ period = self.p.period
518
+ high = self.data.high[0]
519
+ low = self.data.low[0]
520
+ if len(self.data) <= 1:
521
+ return
522
+ try:
523
+ prev_high = self.data.high[-1]
524
+ prev_low = self.data.low[-1]
525
+ prev_close = self.data.close[-1]
526
+ except IndexError:
527
+ return
528
+ tr = max(high, prev_close) - min(low, prev_close)
529
+ upmove = high - prev_high
530
+ downmove = prev_low - low
531
+ mdm = downmove if (downmove > upmove and downmove > 0) else 0.0
532
+ self._bar_count += 1
533
+ if self._bar_count <= period:
534
+ self._sm_tr += tr
535
+ self._sm_mdm += mdm
536
+ else:
537
+ self._sm_tr = self._sm_tr - self._sm_tr / period + tr
538
+ self._sm_mdm = self._sm_mdm - self._sm_mdm / period + mdm
539
+ self.lines.minusDI[0] = (100.0 * self._sm_mdm / self._sm_tr) if self._sm_tr > 0 else 0.0
540
+
541
+ def prenext(self):
542
+ """Called before minimum period is met.
543
+
544
+ Accumulates -DI values during the warmup period.
545
+ """
546
+ self._mdi_accumulate()
547
+
548
+ def nextstart(self):
549
+ """Called once minimum period is first met.
550
+
551
+ Accumulates -DI values at the start of normal operation.
552
+ """
553
+ self._mdi_accumulate()
554
+
555
+ def next(self):
556
+ """Called on each bar after minimum period is met.
557
+
558
+ Accumulates -DI values for the current bar.
559
+ """
560
+ self._mdi_accumulate()
561
+
562
+ def once(self, start, end):
563
+ """Vectorized calculation of -DI values.
564
+
565
+ Args:
566
+ start: Start index for calculation.
567
+ end: End index for calculation.
568
+ """
569
+ period = self.p.period
570
+ high_arr = self.data.high.array
571
+ low_arr = self.data.low.array
572
+ close_arr = self.data.close.array
573
+ dst = self.lines.minusDI.array
574
+ while len(dst) < end:
575
+ dst.append(float("nan"))
576
+ sm_tr = 0.0
577
+ sm_mdm = 0.0
578
+ bc = 0
579
+ for i in range(1, min(end, len(high_arr), len(low_arr), len(close_arr))):
580
+ tr = max(high_arr[i], close_arr[i - 1]) - min(low_arr[i], close_arr[i - 1])
581
+ upmove = high_arr[i] - high_arr[i - 1]
582
+ downmove = low_arr[i - 1] - low_arr[i]
583
+ mdm = downmove if (downmove > upmove and downmove > 0) else 0.0
584
+ bc += 1
585
+ if bc <= period:
586
+ sm_tr += tr
587
+ sm_mdm += mdm
588
+ else:
589
+ sm_tr = sm_tr - sm_tr / period + tr
590
+ sm_mdm = sm_mdm - sm_mdm / period + mdm
591
+ dst[i] = (100.0 * sm_mdm / sm_tr) if sm_tr > 0 else 0.0
592
+
593
+ prenext = LineRoot.prenext # noqa: F811
594
+ nextstart = LineRoot.nextstart # noqa: F811
595
+ next = LineRoot.next # noqa: F811
596
+ preonce = LineRoot.preonce # noqa: F811
597
+ oncestart = LineRoot.oncestart # noqa: F811
598
+ once = LineRoot.once # noqa: F811
599
+
600
+
601
+ class AverageDirectionalMovementIndex(Indicator):
602
+ """
603
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
604
+ Technical Trading Systems"*.
605
+
606
+ Intended to measure trend strength. Rewritten following MACD pattern
607
+ with explicit next()/once() methods for reliable calculation.
608
+
609
+ Formula:
610
+ - upmove = high - high(-1)
611
+ - downmove = low(-1) - low
612
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
613
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
614
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
615
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
616
+ - dx = 100 * abs(+di - -di) / (+di + -di)
617
+ - adx = MovingAverage(dx, period)
618
+ """
619
+
620
+ alias = ("ADX",)
621
+ lines = ("adx",)
622
+ params = (("period", 14), ("movav", MovAv.Smoothed))
623
+ plotlines = {"adx": {"_name": "ADX"}}
624
+
625
+ def __init__(self):
626
+ """Initialize the ADX indicator.
627
+
628
+ Sets up ATR, DM smoothing, and state for ADX calculation.
629
+ """
630
+ super().__init__()
631
+ period = self.p.period
632
+
633
+ atr = ATR(self.data, period=period, movav=self.p.movav)
634
+ upmove = self.data.high - self.data.high(-1)
635
+ downmove = self.data.low(-1) - self.data.low
636
+
637
+ plus = And(upmove > downmove, upmove > 0.0)
638
+ plusDM = If(plus, upmove, 0.0)
639
+ plusDMav = self.p.movav(plusDM, period=period)
640
+ self.DIplus = 100.0 * plusDMav / atr
641
+
642
+ minus = And(downmove > upmove, downmove > 0.0)
643
+ minusDM = If(minus, downmove, 0.0)
644
+ minusDMav = self.p.movav(minusDM, period=period)
645
+ self.DIminus = 100.0 * minusDMav / atr
646
+
647
+ dx = abs(self.DIplus - self.DIminus) / (self.DIplus + self.DIminus)
648
+ self.lines.adx = 100.0 * self.p.movav(dx, period=period)
649
+
650
+ # Store sub-indicators for direct array access (like MACD)
651
+ self.atr = ATR(self.data, period=period, movav=self.p.movav)
652
+ self.plusDMav = self.p.movav(period=period)
653
+ self.minusDMav = self.p.movav(period=period)
654
+
655
+ # Calculate minperiod: ATR needs period, then DI smoothing needs period, then ADX smoothing needs period
656
+ # Total: approximately 2*period for DI + period for ADX smoothing
657
+ adx_minperiod = 2 * period
658
+ self._minperiod = max(self._minperiod, adx_minperiod)
659
+
660
+ # Propagate minperiod to lines
661
+ for line in self.lines:
662
+ line.updateminperiod(self._minperiod)
663
+
664
+ # For SMMA calculation
665
+ self.alpha = 1.0 / period
666
+ self.alpha1 = 1.0 - self.alpha
667
+
668
+ # State for smoothed values
669
+ self._plusDMav_val = 0.0
670
+ self._minusDMav_val = 0.0
671
+ self._adx_val = 0.0
672
+ self._adx_bootstrapped = False
673
+ self._last_adx_idx = None
674
+
675
+ def prenext(self):
676
+ """Track previous high/low during warmup.
677
+
678
+ Stores high and low values for directional move calculation.
679
+ """
680
+
681
+ def _adx_atr_value(self, atr_array, index):
682
+ import math
683
+
684
+ atr_val = atr_array[index]
685
+ if atr_val == 0 or (isinstance(atr_val, float) and math.isnan(atr_val)):
686
+ return 0.0001
687
+ return atr_val
688
+
689
+ def _adx_dx(self, plus_dmav, minus_dmav, atr_val):
690
+ diplus = 100.0 * plus_dmav / atr_val
691
+ diminus = 100.0 * minus_dmav / atr_val
692
+ disum = diplus + diminus
693
+ return 100.0 * abs(diplus - diminus) / disum if disum != 0 else 0.0
694
+
695
+ def _adx_bootstrap(self, target_idx):
696
+ high_array = self.data.high.array
697
+ low_array = self.data.low.array
698
+ atr_array = self.atr.lines[0].array
699
+
700
+ period = self.p.period
701
+ seed_idx = 2 * period - 1
702
+ data_len = min(len(high_array), len(low_array), len(atr_array))
703
+ if target_idx < seed_idx or data_len <= seed_idx:
704
+ return False
705
+
706
+ dm_plus_sum = 0.0
707
+ dm_minus_sum = 0.0
708
+ for i in range(1, period + 1):
709
+ upmove = high_array[i] - high_array[i - 1]
710
+ downmove = low_array[i - 1] - low_array[i]
711
+ dm_plus_sum += upmove if (upmove > downmove and upmove > 0) else 0.0
712
+ dm_minus_sum += downmove if (downmove > upmove and downmove > 0) else 0.0
713
+
714
+ plus_dmav = dm_plus_sum / period
715
+ minus_dmav = dm_minus_sum / period
716
+ dx_values = [self._adx_dx(plus_dmav, minus_dmav, self._adx_atr_value(atr_array, period))]
717
+
718
+ for i in range(period + 1, seed_idx + 1):
719
+ upmove = high_array[i] - high_array[i - 1]
720
+ downmove = low_array[i - 1] - low_array[i]
721
+ plus_dm = upmove if (upmove > downmove and upmove > 0) else 0.0
722
+ minus_dm = downmove if (downmove > upmove and downmove > 0) else 0.0
723
+ plus_dmav = plus_dmav * self.alpha1 + plus_dm * self.alpha
724
+ minus_dmav = minus_dmav * self.alpha1 + minus_dm * self.alpha
725
+ dx_values.append(self._adx_dx(plus_dmav, minus_dmav, self._adx_atr_value(atr_array, i)))
726
+
727
+ self._plusDMav_val = plus_dmav
728
+ self._minusDMav_val = minus_dmav
729
+ self._adx_val = sum(dx_values[:period]) / period
730
+ self._last_adx_idx = seed_idx
731
+ self._adx_bootstrapped = True
732
+ return True
733
+
734
+ def _adx_advance_to(self, target_idx):
735
+ if not self._adx_bootstrapped and not self._adx_bootstrap(target_idx):
736
+ return False
737
+
738
+ high_array = self.data.high.array
739
+ low_array = self.data.low.array
740
+ atr_array = self.atr.lines[0].array
741
+ data_len = min(len(high_array), len(low_array), len(atr_array))
742
+ if target_idx >= data_len:
743
+ return False
744
+
745
+ for i in range(self._last_adx_idx + 1, target_idx + 1):
746
+ upmove = high_array[i] - high_array[i - 1]
747
+ downmove = low_array[i - 1] - low_array[i]
748
+ plus_dm = upmove if (upmove > downmove and upmove > 0) else 0.0
749
+ minus_dm = downmove if (downmove > upmove and downmove > 0) else 0.0
750
+ self._plusDMav_val = self._plusDMav_val * self.alpha1 + plus_dm * self.alpha
751
+ self._minusDMav_val = self._minusDMav_val * self.alpha1 + minus_dm * self.alpha
752
+ dx = self._adx_dx(
753
+ self._plusDMav_val,
754
+ self._minusDMav_val,
755
+ self._adx_atr_value(atr_array, i),
756
+ )
757
+ self._adx_val = self._adx_val * self.alpha1 + dx * self.alpha
758
+ self._last_adx_idx = i
759
+
760
+ return True
761
+
762
+ def nextstart(self):
763
+ """Seed ADX calculation on first valid bar.
764
+
765
+ Calculates initial DM, DI, DX, and ADX values.
766
+ """
767
+ idx = self.lines[0].idx
768
+ if self._adx_advance_to(idx):
769
+ self.lines.adx[0] = self._adx_val
770
+ else:
771
+ self.lines.adx[0] = float("nan")
772
+
773
+ def next(self):
774
+ """Calculate ADX for the current bar.
775
+
776
+ Calculates DM smoothing, DI, DX, and ADX values.
777
+ """
778
+ idx = self.lines[0].idx
779
+ if self._adx_advance_to(idx):
780
+ self.lines.adx[0] = self._adx_val
781
+ else:
782
+ self.lines.adx[0] = float("nan")
783
+
784
+ def once(self, start, end):
785
+ """Calculate ADX in runonce mode using proper Wilder seeding.
786
+
787
+ Implements the standard Wilder ADX algorithm:
788
+ Phase 1: Seed smoothed DM with SMA of first N DM values (bars 1..period)
789
+ Phase 2: Continue SMMA for DM, accumulate DX (bars period..2*period-1)
790
+ Phase 3: Seed ADX with SMA of first N DX values
791
+ Phase 4: Continue SMMA for all components (bars 2*period..end)
792
+ """
793
+ import math
794
+
795
+ # Get source arrays
796
+ high_array = self.data.high.array
797
+ low_array = self.data.low.array
798
+ atr_array = self.atr.lines[0].array
799
+ adx_array = self.lines.adx.array
800
+
801
+ period = self.p.period
802
+ alpha = self.alpha
803
+ alpha1 = self.alpha1
804
+
805
+ # Ensure arrays are sized
806
+ while len(adx_array) < end:
807
+ adx_array.append(float("nan"))
808
+
809
+ data_len = min(end, len(high_array), len(low_array), len(atr_array))
810
+
811
+ # Pre-fill warmup with NaN
812
+ for i in range(min(2 * period, data_len)):
813
+ adx_array[i] = float("nan")
814
+
815
+ # Need at least 2*period + 1 bars for proper seeding
816
+ if data_len <= 2 * period:
817
+ return
818
+
819
+ # Phase 1: Calculate raw DM values for bars 1..period
820
+ # Seed smoothed DM with SMA (average) of first period values
821
+ dm_plus_sum = 0.0
822
+ dm_minus_sum = 0.0
823
+
824
+ for i in range(1, period + 1):
825
+ upmove = high_array[i] - high_array[i - 1]
826
+ downmove = low_array[i - 1] - low_array[i]
827
+ plusDM = upmove if (upmove > downmove and upmove > 0) else 0.0
828
+ minusDM = downmove if (downmove > upmove and downmove > 0) else 0.0
829
+ dm_plus_sum += plusDM
830
+ dm_minus_sum += minusDM
831
+
832
+ plusDMav = dm_plus_sum / period
833
+ minusDMav = dm_minus_sum / period
834
+
835
+ # Phase 2: Calculate DI and DX for bars period..2*period-1
836
+ # Continue SMMA for DM, accumulate DX values for ADX seeding
837
+ dx_list = []
838
+
839
+ # First DX at bar period (using seeded DM averages)
840
+ atr_val = atr_array[period]
841
+ if atr_val == 0 or (isinstance(atr_val, float) and math.isnan(atr_val)):
842
+ atr_val = 0.0001
843
+ diplus = 100.0 * plusDMav / atr_val
844
+ diminus = 100.0 * minusDMav / atr_val
845
+ disum = diplus + diminus
846
+ dx = 100.0 * abs(diplus - diminus) / disum if disum != 0 else 0.0
847
+ dx_list.append(dx)
848
+
849
+ # Continue for bars period+1 to 2*period-1
850
+ for i in range(period + 1, 2 * period):
851
+ upmove = high_array[i] - high_array[i - 1]
852
+ downmove = low_array[i - 1] - low_array[i]
853
+ plusDM = upmove if (upmove > downmove and upmove > 0) else 0.0
854
+ minusDM = downmove if (downmove > upmove and downmove > 0) else 0.0
855
+
856
+ plusDMav = plusDMav * alpha1 + plusDM * alpha
857
+ minusDMav = minusDMav * alpha1 + minusDM * alpha
858
+
859
+ atr_val = atr_array[i]
860
+ if atr_val == 0 or (isinstance(atr_val, float) and math.isnan(atr_val)):
861
+ atr_val = 0.0001
862
+
863
+ diplus = 100.0 * plusDMav / atr_val
864
+ diminus = 100.0 * minusDMav / atr_val
865
+ disum = diplus + diminus
866
+ dx = 100.0 * abs(diplus - diminus) / disum if disum != 0 else 0.0
867
+ dx_list.append(dx)
868
+
869
+ # Phase 3: Seed ADX with SMA of first period DX values
870
+ adx_val = sum(dx_list[:period]) / period
871
+ adx_array[2 * period - 1] = adx_val
872
+
873
+ # Phase 4: Continue SMMA for everything from 2*period onwards
874
+ for i in range(2 * period, data_len):
875
+ upmove = high_array[i] - high_array[i - 1]
876
+ downmove = low_array[i - 1] - low_array[i]
877
+ plusDM = upmove if (upmove > downmove and upmove > 0) else 0.0
878
+ minusDM = downmove if (downmove > upmove and downmove > 0) else 0.0
879
+
880
+ plusDMav = plusDMav * alpha1 + plusDM * alpha
881
+ minusDMav = minusDMav * alpha1 + minusDM * alpha
882
+
883
+ atr_val = atr_array[i]
884
+ if atr_val == 0 or (isinstance(atr_val, float) and math.isnan(atr_val)):
885
+ atr_val = 0.0001
886
+
887
+ diplus = 100.0 * plusDMav / atr_val
888
+ diminus = 100.0 * minusDMav / atr_val
889
+ disum = diplus + diminus
890
+ dx = 100.0 * abs(diplus - diminus) / disum if disum != 0 else 0.0
891
+
892
+ adx_val = adx_val * alpha1 + dx * alpha
893
+ adx_array[i] = adx_val
894
+
895
+ prenext = LineRoot.prenext # noqa: F811
896
+ nextstart = LineRoot.nextstart # noqa: F811
897
+ next = LineRoot.next # noqa: F811
898
+ preonce = LineRoot.preonce # noqa: F811
899
+ oncestart = LineRoot.oncestart # noqa: F811
900
+ once = LineRoot.once # noqa: F811
901
+
902
+
903
+ class AverageDirectionalMovementIndexRating(AverageDirectionalMovementIndex):
904
+ """
905
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
906
+ Technical Trading Systems"*.
907
+
908
+ Intended to measure trend strength.
909
+
910
+ ADXR is the average of ADX with a value period bars ago
911
+
912
+ This indicator shows the ADX and ADXR:
913
+ - Use PlusDirectionalIndicator (PlusDI) to get +DI
914
+ - Use MinusDirectionalIndicator (MinusDI) to get -DI
915
+ - Use Directional Indicator (DI) to get +DI, -DI
916
+ - Use AverageDirectionalIndex (ADX) to get ADX
917
+ - Use DirectionalMovementIndex (DMI) to get ADX, +DI, -DI
918
+ - Use DirectionalMovement (DM) to get ADX, ADXR, +DI, -DI
919
+
920
+ Formula:
921
+ - upmove = high - high(-1)
922
+ - downmove = low(-1) - low
923
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
924
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
925
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
926
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
927
+ - dx = 100 * abs(+di - -di) / (+di + -di)
928
+ - adx = MovingAverage(dx, period)
929
+ - adxr = (adx + adx(-period)) / 2
930
+
931
+ The moving average used is the one originally defined by Wilder,
932
+ the SmoothedMovingAverage
933
+
934
+ See:
935
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
936
+ """
937
+
938
+ alias = ("ADXR",)
939
+
940
+ lines = ("adxr",)
941
+ plotlines = {"adxr": {"_name": "ADXR"}}
942
+
943
+ def __init__(self):
944
+ """Initialize the ADXR indicator.
945
+
946
+ Extends ADX with rating line.
947
+ """
948
+ super().__init__()
949
+ self.lines.adxr = (self.l.adx + self.l.adx(-self.p.period)) / 2.0
950
+
951
+ def next(self):
952
+ """Calculate ADX and ADXR for the current bar.
953
+
954
+ ADXR = (ADX + ADX(-period)) / 2
955
+ """
956
+ super().next()
957
+ self.lines.adxr[0] = (self.lines.adx[0] + self.lines.adx[-self.p.period]) / 2.0
958
+
959
+ def once(self, start, end):
960
+ """Calculate ADXR in runonce mode.
961
+
962
+ Computes ADXR as average of current ADX and ADX from period ago.
963
+ """
964
+ super().once(start, end)
965
+ import math
966
+
967
+ adx_array = self.lines.adx.array
968
+ adxr_array = self.lines.adxr.array
969
+ period = self.p.period
970
+
971
+ while len(adxr_array) < end:
972
+ adxr_array.append(float("nan"))
973
+
974
+ for i in range(start, min(end, len(adx_array))):
975
+ if i >= period:
976
+ adx_curr = adx_array[i] if i < len(adx_array) else 0.0
977
+ adx_prev = (
978
+ adx_array[i - period]
979
+ if i - period >= 0 and i - period < len(adx_array)
980
+ else 0.0
981
+ )
982
+
983
+ if (
984
+ isinstance(adx_curr, float)
985
+ and math.isnan(adx_curr)
986
+ or isinstance(adx_prev, float)
987
+ and math.isnan(adx_prev)
988
+ ):
989
+ adxr_array[i] = float("nan")
990
+ else:
991
+ adxr_array[i] = (adx_curr + adx_prev) / 2.0
992
+ else:
993
+ adxr_array[i] = float("nan")
994
+
995
+ prenext = LineRoot.prenext # noqa: F811
996
+ nextstart = LineRoot.nextstart # noqa: F811
997
+ next = LineRoot.next # noqa: F811
998
+ preonce = LineRoot.preonce # noqa: F811
999
+ oncestart = LineRoot.oncestart # noqa: F811
1000
+ once = LineRoot.once # noqa: F811
1001
+
1002
+
1003
+ class DirectionalMovementIndex(AverageDirectionalMovementIndex, DirectionalIndicator):
1004
+ """
1005
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
1006
+ Technical Trading Systems"*.
1007
+
1008
+ Intended to measure trend strength
1009
+
1010
+ This indicator shows the ADX, +DI, -DI:
1011
+ - Use PlusDirectionalIndicator (PlusDI) to get +DI
1012
+ - Use MinusDirectionalIndicator (MinusDI) to get -DI
1013
+ - Use Directional Indicator (DI) to get +DI, -DI
1014
+ - Use AverageDirectionalIndex (ADX) to get ADX
1015
+ - Use AverageDirectionalIndexRating (ADXRating) to get ADX, ADXR
1016
+ - Use DirectionalMovement (DM) to get ADX, ADXR, +DI, -DI
1017
+
1018
+ Formula:
1019
+ - upmove = high - high(-1)
1020
+ - downmove = low(-1) - low
1021
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
1022
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
1023
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
1024
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
1025
+ - dx = 100 * abs(+di - -di) / (+di + -di)
1026
+ - adx = MovingAverage(dx, period)
1027
+
1028
+ The moving average used is the one originally defined by Wilder,
1029
+ the SmoothedMovingAverage
1030
+
1031
+ See:
1032
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
1033
+ """
1034
+
1035
+ alias = ("DMI",)
1036
+
1037
+
1038
+ class DirectionalMovement(AverageDirectionalMovementIndexRating, DirectionalIndicator):
1039
+ """
1040
+ Defined by J. Welles Wilder, Jr. in 1978 in his book *"New Concepts in
1041
+ Technical Trading Systems"*.
1042
+
1043
+ Intended to measure trend strength
1044
+
1045
+ This indicator shows ADX, ADXR, +DI, -DI.
1046
+
1047
+ - Use PlusDirectionalIndicator (PlusDI) to get +DI
1048
+ - Use MinusDirectionalIndicator (MinusDI) to get -DI
1049
+ - Use Directional Indicator (DI) to get +DI, -DI
1050
+ - Use AverageDirectionalIndex (ADX) to get ADX
1051
+ - Use AverageDirectionalIndexRating (ADXR) to get ADX, ADXR
1052
+ - Use DirectionalMovementIndex (DMI) to get ADX, +DI, -DI
1053
+
1054
+ Formula:
1055
+ - upmove = high - high(-1)
1056
+ - downmove = low(-1) - low
1057
+ - +dm = upmove if upmove > downmove and upmove > 0 else 0
1058
+ - -dm = downmove if downmove > upmove and downmove > 0 else 0
1059
+ - +di = 100 * MovingAverage(+dm, period) / atr(period)
1060
+ - -di = 100 * MovingAverage(-dm, period) / atr(period)
1061
+ - dx = 100 * abs(+di - -di) / (+di + -di)
1062
+ - adx = MovingAverage(dx, period)
1063
+
1064
+ The moving average used is the one originally defined by Wilder,
1065
+ the SmoothedMovingAverage
1066
+
1067
+ See:
1068
+ - https://en.wikipedia.org/wiki/Average_directional_movement_index
1069
+ """
1070
+
1071
+ alias = ("DM",)