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,534 @@
1
+ """Sharpe Ratio Statistics Module - Advanced Sharpe ratio calculations.
2
+
3
+ This module provides functions for calculating Sharpe ratio statistics
4
+ including estimated, probabilistic, and defecto Sharpe ratios, along
5
+ with their confidence intervals and significance tests.
6
+
7
+ Functions:
8
+ estimated_sharpe_ratio: Calculate basic Sharpe ratio.
9
+ ann_estimated_sharpe_ratio: Calculate annualized Sharpe ratio.
10
+ estimated_sharpe_ratio_stdev: Standard deviation of Sharpe estimation.
11
+ probabilistic_sharpe_ratio: PSR calculation.
12
+ min_track_record_length: Minimum track record for significance.
13
+ sharpe_ratio_defacto: Defacto Sharpe ratio calculation.
14
+ """
15
+
16
+ import numpy as np
17
+ import pandas as pd
18
+ from scipy import stats as scipy_stats
19
+
20
+ from ..utils.log_message import get_logger
21
+
22
+ logger = get_logger(__name__)
23
+
24
+
25
+ def _is_integer_like(value):
26
+ try:
27
+ return (
28
+ not isinstance(value, (bool, np.bool_))
29
+ and np.isscalar(value)
30
+ and np.isfinite(value)
31
+ and float(value).is_integer()
32
+ )
33
+ except (TypeError, ValueError):
34
+ return False
35
+
36
+
37
+ def _is_finite_value(value):
38
+ try:
39
+ return bool(np.all(np.isfinite(np.asarray(value))))
40
+ except (TypeError, ValueError):
41
+ return False
42
+
43
+
44
+ def _average_upper_triangle_correlation(trials_returns):
45
+ """Compute the mean pairwise correlation across trial return columns."""
46
+ corr_matrix = trials_returns.corr()
47
+ if corr_matrix.empty:
48
+ return 0.0
49
+
50
+ upper = corr_matrix.values[np.triu_indices_from(corr_matrix.values, 1)]
51
+ if upper.size == 0:
52
+ return 0.0
53
+
54
+ avg_corr = np.nanmean(upper)
55
+ if not np.isfinite(avg_corr):
56
+ return 0.0
57
+
58
+ return float(avg_corr)
59
+
60
+
61
+ def estimated_sharpe_ratio(returns):
62
+ """
63
+ Calculate the estimated sharpe ratio (risk_free=0).
64
+
65
+ Parameters
66
+ ----------
67
+ returns: `np.array`, pd.Series, pd.DataFrame
68
+
69
+ Returns
70
+ -------
71
+ float, pd.Series
72
+ """
73
+ if returns is None:
74
+ raise ValueError("estimated_sharpe_ratio requires returns")
75
+ if len(returns) <= 1:
76
+ raise ValueError("estimated_sharpe_ratio requires at least 2 return samples")
77
+
78
+ return returns.mean() / returns.std(ddof=1)
79
+
80
+
81
+ def ann_estimated_sharpe_ratio(returns=None, periods=261, *, sr=None):
82
+ """
83
+ Calculate the annualized estimated sharpe ratio (risk_free=0).
84
+
85
+ Parameters
86
+ ----------
87
+ returns: `np.array`, pd.Series, pd.DataFrame
88
+
89
+ periods: int
90
+ How many items in `returns` complete a Year.
91
+ If returns are daily: 261, weekly: 52, monthly: 12, ...
92
+
93
+ sr: float, `np.array`, pd.Series, pd.DataFrame
94
+ Sharpe ratio to be annualized, its frequency must be coherent with `periods`
95
+
96
+ Returns
97
+ -------
98
+ float, pd.Series
99
+ """
100
+ if returns is None and sr is None:
101
+ raise ValueError("ann_estimated_sharpe_ratio requires returns or sr")
102
+ if not _is_integer_like(periods):
103
+ raise ValueError("ann_estimated_sharpe_ratio requires integer periods")
104
+ periods = int(periods)
105
+ if periods <= 0:
106
+ raise ValueError("ann_estimated_sharpe_ratio requires periods > 0")
107
+ if sr is not None and not _is_finite_value(sr):
108
+ raise ValueError("ann_estimated_sharpe_ratio requires finite sr")
109
+
110
+ if sr is None:
111
+ if len(returns) <= 1:
112
+ raise ValueError(
113
+ "ann_estimated_sharpe_ratio requires at least 2 return samples when sr is None"
114
+ )
115
+ sr = estimated_sharpe_ratio(returns)
116
+ sr = sr * np.sqrt(periods)
117
+ return sr
118
+
119
+
120
+ def _validate_srstdev_params(_returns, n, skew, kurtosis, sr):
121
+ """Validate/normalize estimated_sharpe_ratio_stdev inputs; return int n.
122
+
123
+ Resolves n from _returns when not given, enforces integer n > 1 and finite
124
+ skew/kurtosis/sr. Extracted from estimated_sharpe_ratio_stdev.
125
+ """
126
+ if _returns is not None and n is None:
127
+ n = len(_returns)
128
+ if not _is_integer_like(n):
129
+ raise ValueError("estimated_sharpe_ratio_stdev requires integer n")
130
+ n = int(n)
131
+ if n <= 1:
132
+ raise ValueError("estimated_sharpe_ratio_stdev requires n > 1")
133
+ if skew is not None and not _is_finite_value(skew):
134
+ raise ValueError("estimated_sharpe_ratio_stdev requires finite skew")
135
+ if kurtosis is not None and not _is_finite_value(kurtosis):
136
+ raise ValueError("estimated_sharpe_ratio_stdev requires finite kurtosis")
137
+ if sr is not None and not _is_finite_value(sr):
138
+ raise ValueError("estimated_sharpe_ratio_stdev requires finite sr")
139
+ return n
140
+
141
+
142
+ def estimated_sharpe_ratio_stdev(returns=None, *, n=None, skew=None, kurtosis=None, sr=None):
143
+ """
144
+ Calculate the standard deviation of the sharpe ratio estimation.
145
+
146
+ Parameters
147
+ ----------
148
+ returns: `np.array`, pd.Series, pd.DataFrame
149
+ If no `returns` are passed it is mandatory to pass the other four parameters.
150
+
151
+ n: int
152
+ Number of returns samples used for calculating `skew`, `kurtosis` and `sr`.
153
+
154
+ skew: float, `np.array`, pd.Series, pd.DataFrame
155
+ The third moment expressed in the same frequency as the other parameters.
156
+ `Skew`=0 for normal returns.
157
+
158
+ kurtosis: float, `np.array`, pd.Series, pd.DataFrame
159
+ The fourth moment expressed in the same frequency as the other parameters.
160
+ `Kurtosis`=3 for normal returns.
161
+
162
+ sr: float, `np.array`, pd.Series, pd.DataFrame
163
+ Sharpe ratio expressed in the same frequency as the other parameters.
164
+
165
+ Returns
166
+ -------
167
+ float, pd.Series
168
+
169
+ Notes
170
+ -----
171
+ This formula generalizes for both normal and non-normal returns.
172
+ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1821643
173
+ """
174
+ # if type(returns) != pd.DataFrame:
175
+ # _returns = pd.DataFrame(returns)
176
+ # else:
177
+ # _returns = returns.copy()
178
+
179
+ if returns is None:
180
+ if any(param is None for param in (n, skew, kurtosis, sr)):
181
+ raise ValueError(
182
+ "estimated_sharpe_ratio_stdev requires n, skew, kurtosis, and sr when returns is None"
183
+ )
184
+ _returns = None
185
+ elif isinstance(returns, pd.DataFrame):
186
+ _returns = pd.DataFrame(returns)
187
+ else:
188
+ _returns = returns.copy()
189
+
190
+ n = _validate_srstdev_params(_returns, n, skew, kurtosis, sr)
191
+
192
+ if _returns is not None and skew is None:
193
+ skew_values = scipy_stats.skew(_returns)
194
+ if isinstance(_returns, pd.DataFrame):
195
+ skew = pd.Series(skew_values, index=_returns.columns)
196
+ else:
197
+ skew = skew_values
198
+ if _returns is not None and kurtosis is None:
199
+ kurtosis_values = scipy_stats.kurtosis(_returns, fisher=False)
200
+ if isinstance(_returns, pd.DataFrame):
201
+ kurtosis = pd.Series(kurtosis_values, index=_returns.columns)
202
+ else:
203
+ kurtosis = kurtosis_values
204
+ if _returns is not None and sr is None:
205
+ sr = estimated_sharpe_ratio(_returns)
206
+
207
+ sr_std = np.sqrt((1 + (0.5 * sr**2) - (skew * sr) + (((kurtosis - 3) / 4) * sr**2)) / (n - 1))
208
+
209
+ if isinstance(returns, pd.DataFrame):
210
+ sr_std = pd.Series(sr_std, index=returns.columns)
211
+ elif type(sr_std) not in (float, np.float64, pd.DataFrame):
212
+ sr_std = sr_std.values[0]
213
+
214
+ return sr_std
215
+
216
+
217
+ def probabilistic_sharpe_ratio(returns=None, sr_benchmark=0.0, *, sr=None, sr_std=None):
218
+ """
219
+ Calculate the Probabilistic Sharpe Ratio (PSR).
220
+
221
+ Parameters
222
+ ----------
223
+ returns: `np.array`, pd.Series, pd.DataFrame
224
+ If no `returns` are passed it is mandatory to pass a `sr` and `sr_std`.
225
+
226
+ sr_benchmark: float
227
+ Benchmark sharpe ratio expressed in the same frequency as the other parameters.
228
+ By default, set to zero (comparing against no investment skill).
229
+
230
+ sr: float, `np.array`, pd.Series, pd.DataFrame
231
+ Sharpe ratio expressed in the same frequency as the other parameters.
232
+
233
+ sr_std: float, `np.array`, pd.Series, pd.DataFrame
234
+ Standard deviation fo the Estimated sharpe ratio,
235
+ expressed in the same frequency as the other parameters.
236
+
237
+ Returns
238
+ -------
239
+ float, pd.Series
240
+
241
+ Notes
242
+ -----
243
+ PSR(SR*) = probability that SR^ > SR*
244
+ SR^ = sharpe ratio estimated with `returns`, or `sr`
245
+ SR* = `sr_benchmark`
246
+
247
+ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1821643
248
+ """
249
+ if returns is None and any(param is None for param in (sr, sr_std)):
250
+ raise ValueError("probabilistic_sharpe_ratio requires sr and sr_std when returns is None")
251
+ if sr is not None and not _is_finite_value(sr):
252
+ raise ValueError("probabilistic_sharpe_ratio requires finite sr")
253
+ if not _is_finite_value(sr_benchmark):
254
+ raise ValueError("probabilistic_sharpe_ratio requires finite sr_benchmark")
255
+
256
+ if sr is None:
257
+ sr = estimated_sharpe_ratio(returns)
258
+ if sr_std is None:
259
+ sr_std = estimated_sharpe_ratio_stdev(returns, sr=sr)
260
+ if np.any(~np.isfinite(np.asarray(sr_std))) or np.any(np.asarray(sr_std) <= 0):
261
+ raise ValueError("probabilistic_sharpe_ratio requires finite sr_std > 0")
262
+
263
+ psr = scipy_stats.norm.cdf((sr - sr_benchmark) / sr_std)
264
+
265
+ if isinstance(returns, pd.DataFrame):
266
+ psr = pd.Series(psr, index=returns.columns)
267
+ elif type(psr) not in (float, np.float64):
268
+ psr = psr.iloc[0] if isinstance(psr, pd.Series) else psr[0]
269
+
270
+ return psr
271
+
272
+
273
+ def min_track_record_length(
274
+ returns=None, sr_benchmark=0.0, prob=0.95, *, n=None, sr=None, sr_std=None
275
+ ):
276
+ """
277
+ Calculate the MIn Track Record Length (minTRL).
278
+
279
+ Parameters
280
+ ----------
281
+ returns: `np.array`, pd.Series, pd.DataFrame
282
+ If no `returns` are passed it is mandatory to pass a `sr` and `sr_std`.
283
+
284
+ sr_benchmark: float
285
+ Benchmark sharpe ratio expressed in the same frequency as the other parameters.
286
+ By default, set to zero (comparing against no investment skill).
287
+
288
+ prob: float
289
+ Confidence level used for calculating the minTRL.
290
+ Between 0 and 1, by default=0.95
291
+
292
+ n: int
293
+ Number of returns samples used for calculating `sr` and `sr_std`.
294
+
295
+ sr: float, `np.array`, pd.Series, pd.DataFrame
296
+ Sharpe ratio expressed in the same frequency as the other parameters.
297
+
298
+ sr_std: float, `np.array`, pd.Series, pd.DataFrame
299
+ Standard deviation fo the Estimated sharpe ratio,
300
+ expressed in the same frequency as the other parameters.
301
+
302
+ Returns
303
+ -------
304
+ float, pd.Series
305
+
306
+ Notes
307
+ -----
308
+ minTRL = minimum of returns/samples needed (with same SR and SR_STD) to accomplish a PSR(SR*) > `prob`
309
+ PSR(SR*) = probability that SR^ > SR*
310
+ SR^ = sharpe ratio estimated with `returns`, or `sr`
311
+ SR* = `sr_benchmark`
312
+
313
+ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1821643
314
+ """
315
+ if returns is None and any(param is None for param in (n, sr, sr_std)):
316
+ raise ValueError("min_track_record_length requires n, sr, and sr_std when returns is None")
317
+ if not 0 < prob < 1:
318
+ raise ValueError("min_track_record_length requires 0 < prob < 1")
319
+ if not _is_finite_value(sr_benchmark):
320
+ raise ValueError("min_track_record_length requires finite sr_benchmark")
321
+
322
+ if n is None:
323
+ n = len(returns)
324
+ if not _is_integer_like(n):
325
+ raise ValueError("min_track_record_length requires integer n")
326
+ n = int(n)
327
+ if n <= 1:
328
+ raise ValueError("min_track_record_length requires n > 1")
329
+ if sr is not None and not _is_finite_value(sr):
330
+ raise ValueError("min_track_record_length requires finite sr")
331
+ if sr is None:
332
+ sr = estimated_sharpe_ratio(returns)
333
+ if sr_std is None:
334
+ sr_std = estimated_sharpe_ratio_stdev(returns, sr=sr)
335
+ if np.any(~np.isfinite(np.asarray(sr_std))) or np.any(np.asarray(sr_std) <= 0):
336
+ raise ValueError("min_track_record_length requires finite sr_std > 0")
337
+
338
+ min_trl = 1 + (sr_std**2 * (n - 1)) * (scipy_stats.norm.ppf(prob) / (sr - sr_benchmark)) ** 2
339
+
340
+ if isinstance(returns, pd.DataFrame):
341
+ min_trl = pd.Series(min_trl, index=returns.columns)
342
+ elif type(min_trl) not in (float, np.float64):
343
+ min_trl = min_trl.iloc[0] if isinstance(min_trl, pd.Series) else min_trl[0]
344
+
345
+ return min_trl
346
+
347
+
348
+ def num_independent_trials(trials_returns=None, *, m=None, p=None):
349
+ """
350
+ Calculate the number of independent trials.
351
+
352
+ Parameters
353
+ ----------
354
+ trials_returns: pd.DataFrame
355
+ All trials returns, not only the independent trials.
356
+
357
+ m: int
358
+ Number of total trials.
359
+
360
+ p: float
361
+ Average correlation between all the trials.
362
+
363
+ Returns
364
+ -------
365
+ int
366
+ """
367
+ if trials_returns is None and any(param is None for param in (m, p)):
368
+ raise ValueError(
369
+ "num_independent_trials requires trials_returns when m or p is not provided"
370
+ )
371
+ if m is not None and not _is_integer_like(m):
372
+ raise ValueError("num_independent_trials requires integer m")
373
+ if m is not None:
374
+ m = int(m)
375
+ if m is not None and m <= 0:
376
+ raise ValueError("num_independent_trials requires m > 0")
377
+
378
+ if m is None:
379
+ m = trials_returns.shape[1]
380
+
381
+ if p is None:
382
+ p = _average_upper_triangle_correlation(trials_returns)
383
+ else:
384
+ if isinstance(p, (bool, np.bool_)) or not np.isscalar(p):
385
+ raise ValueError("num_independent_trials requires scalar p")
386
+ try:
387
+ p = float(p)
388
+ except (TypeError, ValueError):
389
+ logger.error("sharpe_ratio_stats:387 re-raising TypeError,ValueError", exc_info=True)
390
+ raise ValueError("num_independent_trials requires scalar p") from None
391
+ if not np.isfinite(p):
392
+ p = 0.0
393
+ elif not -1 <= p <= 1:
394
+ raise ValueError("num_independent_trials requires -1 <= p <= 1")
395
+
396
+ n = p + (1 - p) * m
397
+
398
+ n = int(n) + 1 # round up
399
+
400
+ return n
401
+
402
+
403
+ def expected_maximum_sr(
404
+ trials_returns=None, expected_mean_sr=0.0, *, independent_trials=None, trials_sr_std=None
405
+ ):
406
+ """
407
+ Compute the expected maximum Sharpe ratio (Analytically)
408
+
409
+ Parameters
410
+ ----------
411
+ trials_returns: pd.DataFrame
412
+ All trials returns, not only the independent trials.
413
+
414
+ expected_mean_sr: float
415
+ Expected mean SR, usually 0. We assume that random startegies will have a mean SR of 0,
416
+ expressed in the same frequency as the other parameters.
417
+
418
+ independent_trials: int
419
+ Number of independent trials must be between 1 and `trials_returns.shape[1]`
420
+
421
+ trials_sr_std: float
422
+ Standard deviation for the Estimated sharpe ratios of all trials,
423
+ expressed in the same frequency as the other parameters.
424
+
425
+ Returns
426
+ -------
427
+ float
428
+ """
429
+ emc = 0.5772156649 # Euler-Mascheroni constant
430
+ if not _is_finite_value(expected_mean_sr):
431
+ raise ValueError("expected_maximum_sr requires finite expected_mean_sr")
432
+
433
+ if independent_trials is None:
434
+ if trials_returns is None:
435
+ raise ValueError("expected_maximum_sr requires trials_returns or independent_trials")
436
+ independent_trials = num_independent_trials(trials_returns)
437
+
438
+ if not _is_integer_like(independent_trials):
439
+ raise ValueError("expected_maximum_sr requires integer independent_trials")
440
+ independent_trials = int(independent_trials)
441
+ if independent_trials < 1:
442
+ raise ValueError("expected_maximum_sr requires independent_trials >= 1")
443
+ if trials_returns is not None and independent_trials > trials_returns.shape[1]:
444
+ raise ValueError(
445
+ "expected_maximum_sr requires independent_trials <= number of trial return columns"
446
+ )
447
+
448
+ if independent_trials <= 1:
449
+ return expected_mean_sr
450
+
451
+ if trials_sr_std is None:
452
+ if trials_returns is None:
453
+ raise ValueError(
454
+ "expected_maximum_sr requires trials_returns or trials_sr_std when independent_trials > 1"
455
+ )
456
+ srs = estimated_sharpe_ratio(trials_returns)
457
+ trials_sr_std = srs.std()
458
+ if np.any(np.isfinite(np.asarray(trials_sr_std)) & (np.asarray(trials_sr_std) < 0)):
459
+ raise ValueError("expected_maximum_sr requires trials_sr_std >= 0")
460
+
461
+ if not np.isfinite(trials_sr_std):
462
+ return expected_mean_sr
463
+
464
+ max_z = (1 - emc) * scipy_stats.norm.ppf(
465
+ 1 - 1.0 / independent_trials
466
+ ) + emc * scipy_stats.norm.ppf(1 - 1.0 / (independent_trials * np.e))
467
+ expected_max_sr = expected_mean_sr + (trials_sr_std * max_z)
468
+
469
+ return expected_max_sr
470
+
471
+
472
+ def deflated_sharpe_ratio(
473
+ trials_returns=None,
474
+ returns_selected=None,
475
+ expected_mean_sr=0.0,
476
+ independent_trials=10,
477
+ expected_max_sr=None,
478
+ ):
479
+ """
480
+ Calculate the Deflated Sharpe Ratio (PSR).
481
+
482
+ Parameters
483
+ ----------
484
+ trials_returns: pd.DataFrame
485
+ All trials returns, not only the independent trials.
486
+
487
+ returns_selected: pd.Series
488
+
489
+ expected_mean_sr: float
490
+ Expected mean SR, usually 0. We assume that random startegies will have a mean SR of 0,
491
+ expressed in the same frequency as the other parameters.
492
+
493
+ expected_max_sr: float
494
+ The expected maximum sharpe ratio expected after running all the trials,
495
+ expressed in the same frequency as the other parameters.
496
+ independent_trials: int
497
+
498
+ Returns
499
+ -------
500
+ float
501
+
502
+ Notes
503
+ -----
504
+ DFS = PSR(SR⁰) = probability that SR^ > SR⁰
505
+ SR^ = sharpe ratio estimated with `returns`, or `sr`
506
+ SR⁰ = `max_expected_sr`
507
+
508
+ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2460551
509
+ """
510
+ if returns_selected is None:
511
+ raise ValueError("deflated_sharpe_ratio requires returns_selected")
512
+ if expected_max_sr is None and trials_returns is None:
513
+ raise ValueError(
514
+ "deflated_sharpe_ratio requires trials_returns when expected_max_sr is None"
515
+ )
516
+ if expected_max_sr is not None and not _is_finite_value(expected_max_sr):
517
+ raise ValueError("deflated_sharpe_ratio requires finite expected_max_sr")
518
+
519
+ if expected_max_sr is None:
520
+ effective_independent_trials = independent_trials
521
+ if trials_returns is not None:
522
+ effective_independent_trials = min(
523
+ effective_independent_trials, trials_returns.shape[1]
524
+ )
525
+
526
+ expected_max_sr = expected_maximum_sr(
527
+ trials_returns=trials_returns,
528
+ expected_mean_sr=expected_mean_sr,
529
+ independent_trials=effective_independent_trials,
530
+ )
531
+
532
+ dsr = probabilistic_sharpe_ratio(returns=returns_selected, sr_benchmark=expected_max_sr)
533
+
534
+ return dsr
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env python
2
+ """SQN Analyzer Module - System Quality Number calculation.
3
+
4
+ This module provides the SQN (System Quality Number) analyzer, defined
5
+ by Van K. Tharp to categorize trading systems.
6
+
7
+ Classes:
8
+ SQN: Analyzer that calculates System Quality Number.
9
+
10
+ Example:
11
+ >>> cerebro = bt.Cerebro()
12
+ >>> cerebro.addanalyzer(bt.analyzers.SQN, _name='sqn')
13
+ >>> results = cerebro.run()
14
+ >>> print(results[0].analyzers.sqn.get_analysis())
15
+ """
16
+
17
+ import math
18
+
19
+ from ..analyzer import Analyzer
20
+ from ..mathsupport import average, standarddev
21
+ from ..utils import AutoOrderedDict
22
+
23
+ __all__ = ["SQN"]
24
+
25
+ _PNL_EPSILON = 1e-10
26
+
27
+
28
+ # Get SQN indicator
29
+ class SQN(Analyzer):
30
+ """SQN or SystemQualityNumber. Defined by Van K. Tharp to categorize trading
31
+ systems.
32
+
33
+ - 1.6 - 1.9 Below average
34
+ - 2.0 - 2.4 Average
35
+ - 2.5 - 2.9 Good
36
+ - 3.0 - 5.0 Excellent
37
+ - 5.1 - 6.9 Superb
38
+ - 7.0 - Holy Grail?
39
+
40
+ The formula:
41
+
42
+ - SquareRoot(NumberTrades) * Average(TradesProfit) / StdDev(TradesProfit)
43
+
44
+ The sqn value should be deemed reliable when the number of trades >= 30
45
+
46
+ Methods:
47
+
48
+ - get_analysis
49
+
50
+ Returns a dictionary with keys "sqn" and "trades" (number of
51
+ considered trades)
52
+
53
+ """
54
+
55
+ # System quality number
56
+ alias = ("SystemQualityNumber",)
57
+
58
+ # Create analysis
59
+ def create_analysis(self):
60
+ """Replace default implementation to instantiate an AutoOrderedDict
61
+ rather than an OrderedDict"""
62
+ self.rets = AutoOrderedDict()
63
+
64
+ # Start, initialize pnl and count
65
+ def start(self):
66
+ """Initialize the analyzer at the start of the backtest.
67
+
68
+ Initializes lists to store trade P&L values for SQN calculation.
69
+ """
70
+ super().start()
71
+ self.pnl = []
72
+ self.count = 0
73
+
74
+ # Trade notification, if trade is closed, add profit/loss
75
+ def notify_trade(self, trade):
76
+ """Collect P&L from closed trades.
77
+
78
+ Args:
79
+ trade: The trade object that was closed.
80
+ """
81
+ if trade.status == trade.Closed:
82
+ self.pnl.append(trade.pnlcomm)
83
+ self.count += 1
84
+
85
+ # Stop, calculate SQN indicator, if trade count > 0, SQN equals average trade profit * sqrt(trade count) / standard deviation of trade profit
86
+ def stop(self):
87
+ """Calculate the System Quality Number when backtest ends.
88
+
89
+ SQN = sqrt(N) * average(P&L) / std(P&L)
90
+
91
+ The result is stored in self.rets.sqn along with the number of
92
+ trades in self.rets.trades.
93
+ """
94
+ if self.count > 1:
95
+ try:
96
+ pnl_values = [0.0 if abs(value) <= _PNL_EPSILON else value for value in self.pnl]
97
+ pnl_av = average(pnl_values)
98
+ pnl_stddev = standarddev(pnl_values)
99
+ except (TypeError, ValueError, ZeroDivisionError):
100
+ sqn = None
101
+ else:
102
+ if not math.isfinite(pnl_av) or not math.isfinite(pnl_stddev) or pnl_stddev == 0.0:
103
+ sqn = None
104
+ else:
105
+ sqn = math.sqrt(len(self.pnl)) * pnl_av / pnl_stddev
106
+ if not math.isfinite(sqn):
107
+ sqn = None
108
+ else:
109
+ sqn = 0
110
+ # Set SQN value and trades value
111
+ self.rets.sqn = sqn
112
+ self.rets.trades = self.count