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,182 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Metadata tab.
4
+
5
+ Displays metadata info for strategy and backtest.
6
+ """
7
+
8
+ import datetime
9
+
10
+ from backtrader.utils.log_message import get_logger
11
+
12
+ from ..tab import BokehTab
13
+
14
+ logger = get_logger(__name__)
15
+
16
+ try:
17
+ from bokeh.layouts import column
18
+ from bokeh.models import ColumnDataSource, DataTable, TableColumn
19
+ from bokeh.models.widgets import Div
20
+
21
+ BOKEH_AVAILABLE = True
22
+ except ImportError:
23
+ BOKEH_AVAILABLE = False
24
+
25
+
26
+ class MetadataTab(BokehTab):
27
+ """Metadata tab.
28
+
29
+ Displays metadata info for strategy, data, indicators, etc.
30
+ """
31
+
32
+ def _is_useable(self):
33
+ """Metadata tab is always useable."""
34
+ return BOKEH_AVAILABLE
35
+
36
+ @staticmethod
37
+ def _collect_metadata(strategy):
38
+ """Collect the backtest metadata dict (time/strategy/data/indicator/
39
+ analyzer/broker info) shown in the metadata table. Extracted from
40
+ _get_panel."""
41
+ metadata = {}
42
+
43
+ # Time info
44
+ metadata["Generated"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
45
+
46
+ if strategy is None:
47
+ return metadata
48
+
49
+ # Strategy info
50
+ metadata["Strategy"] = strategy.__class__.__name__
51
+
52
+ # Data info
53
+ if hasattr(strategy, "datas") and strategy.datas:
54
+ metadata["Data Feeds"] = len(strategy.datas)
55
+
56
+ # Data range
57
+ data = strategy.datas[0]
58
+ if hasattr(data, "datetime") and len(data) > 0:
59
+ try:
60
+ # Get start and end dates
61
+ start_dt = data.datetime.date(0)
62
+ if hasattr(data.datetime, "date"):
63
+ end_dt = data.datetime.date(-1) if len(data) > 1 else start_dt
64
+ else:
65
+ end_dt = start_dt
66
+ metadata["Start Date"] = str(start_dt)
67
+ metadata["End Date"] = str(end_dt)
68
+ metadata["Total Bars"] = len(data)
69
+ except Exception as e:
70
+ logger.warning("Failed to get data range: %s", e)
71
+
72
+ # Indicator info
73
+ if hasattr(strategy, "_lineiterators"):
74
+ ind_count = len(strategy._lineiterators.get(1, [])) # IndType = 1
75
+ obs_count = len(strategy._lineiterators.get(2, [])) # ObsType = 2
76
+ metadata["Indicators"] = ind_count
77
+ metadata["Observers"] = obs_count
78
+
79
+ # Analyzer info
80
+ if hasattr(strategy, "analyzers"):
81
+ metadata["Analyzers"] = len(strategy.analyzers)
82
+
83
+ # Broker info
84
+ if hasattr(strategy, "broker"):
85
+ broker = strategy.broker
86
+ try:
87
+ metadata["Final Value"] = f"{broker.getvalue():.2f}"
88
+ metadata["Final Cash"] = f"{broker.getcash():.2f}"
89
+ except Exception as e:
90
+ logger.warning("Failed to get broker info: %s", e)
91
+
92
+ return metadata
93
+
94
+ def _get_panel(self):
95
+ """Get panel content.
96
+
97
+ Returns:
98
+ tuple: (widget, title)
99
+ """
100
+ strategy = self.strategy
101
+ scheme = self.scheme
102
+ text_color = scheme.text_color if scheme else "#333"
103
+
104
+ widgets = []
105
+
106
+ # Basic info
107
+ widgets.append(
108
+ Div(
109
+ text=f'<h3 style="color: {text_color};">Backtest Metadata</h3>',
110
+ sizing_mode="stretch_width",
111
+ )
112
+ )
113
+
114
+ metadata = self._collect_metadata(strategy)
115
+
116
+ # Create table
117
+ if metadata:
118
+ source = ColumnDataSource(
119
+ data={
120
+ "property": list(metadata.keys()),
121
+ "value": [str(v) for v in metadata.values()],
122
+ }
123
+ )
124
+
125
+ columns = [
126
+ TableColumn(field="property", title="Property"),
127
+ TableColumn(field="value", title="Value"),
128
+ ]
129
+
130
+ table = DataTable(
131
+ source=source,
132
+ columns=columns,
133
+ width=400,
134
+ height=min(len(metadata) * 25 + 30, 400),
135
+ index_position=None,
136
+ )
137
+ widgets.append(table)
138
+
139
+ # Indicator list
140
+ if strategy is not None and hasattr(strategy, "_lineiterators"):
141
+ indicators = strategy._lineiterators.get(1, [])
142
+ if indicators:
143
+ widgets.append(
144
+ Div(
145
+ text=f'<h3 style="color: {text_color};">Indicators</h3>',
146
+ sizing_mode="stretch_width",
147
+ )
148
+ )
149
+
150
+ ind_data = []
151
+ for ind in indicators:
152
+ ind_data.append(
153
+ {
154
+ "name": ind.__class__.__name__,
155
+ "lines": ", ".join(getattr(ind.lines, "_getlinealiases", list)()),
156
+ }
157
+ )
158
+
159
+ if ind_data:
160
+ source = ColumnDataSource(
161
+ data={
162
+ "name": [d["name"] for d in ind_data],
163
+ "lines": [d["lines"] for d in ind_data],
164
+ }
165
+ )
166
+
167
+ columns = [
168
+ TableColumn(field="name", title="Indicator"),
169
+ TableColumn(field="lines", title="Lines"),
170
+ ]
171
+
172
+ table = DataTable(
173
+ source=source,
174
+ columns=columns,
175
+ width=400,
176
+ height=min(len(ind_data) * 25 + 30, 200),
177
+ index_position=None,
178
+ )
179
+ widgets.append(table)
180
+
181
+ content = column(*widgets, sizing_mode="stretch_width")
182
+ return content, "Metadata"
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Performance metrics tab.
4
+
5
+ Displays key performance metrics of the strategy.
6
+ """
7
+
8
+ from backtrader.utils.log_message import get_logger
9
+
10
+ from ..tab import BokehTab
11
+
12
+ logger = get_logger(__name__)
13
+
14
+ try:
15
+ from bokeh.layouts import column
16
+ from bokeh.models import ColumnDataSource, DataTable, TableColumn
17
+ from bokeh.models.widgets import Div
18
+
19
+ BOKEH_AVAILABLE = True
20
+ except ImportError:
21
+ BOKEH_AVAILABLE = False
22
+
23
+
24
+ class PerformanceTab(BokehTab):
25
+ """Performance metrics tab.
26
+
27
+ Displays key performance metrics of the strategy, including:
28
+ - Total return
29
+ - Annual return
30
+ - Sharpe ratio
31
+ - Maximum drawdown
32
+ - Win rate
33
+ - Profit/loss ratio
34
+ - Trade statistics
35
+ """
36
+
37
+ def _is_useable(self):
38
+ """Useable when strategy exists."""
39
+ if not BOKEH_AVAILABLE:
40
+ return False
41
+ return self.strategy is not None
42
+
43
+ def _get_panel(self):
44
+ """Get panel content.
45
+
46
+ Returns:
47
+ tuple: (widget, title)
48
+ """
49
+ strategy = self.strategy
50
+ scheme = self.scheme
51
+
52
+ # Get theme colors
53
+ title_color = scheme.text_color if scheme else "#333333"
54
+
55
+ widgets = []
56
+
57
+ # Title
58
+ widgets.append(
59
+ Div(
60
+ text=f'<h2 style="color: {title_color}; margin-bottom: 20px;">Performance Metrics</h2>',
61
+ sizing_mode="stretch_width",
62
+ )
63
+ )
64
+
65
+ # Collect performance data
66
+ metrics = self._collect_metrics(strategy)
67
+
68
+ # Create summary cards
69
+ summary_html = self._create_summary_cards(metrics, scheme)
70
+ widgets.append(Div(text=summary_html, sizing_mode="stretch_width"))
71
+
72
+ # Returns metrics table
73
+ returns_data = self._get_returns_metrics(metrics)
74
+ if returns_data:
75
+ widgets.append(
76
+ Div(
77
+ text=f'<h3 style="color: {title_color}; margin-top: 20px;">Returns</h3>',
78
+ sizing_mode="stretch_width",
79
+ )
80
+ )
81
+ widgets.append(self._create_metrics_table(returns_data))
82
+
83
+ # Risk metrics table
84
+ risk_data = self._get_risk_metrics(metrics)
85
+ if risk_data:
86
+ widgets.append(
87
+ Div(
88
+ text=f'<h3 style="color: {title_color}; margin-top: 20px;">Risk</h3>',
89
+ sizing_mode="stretch_width",
90
+ )
91
+ )
92
+ widgets.append(self._create_metrics_table(risk_data))
93
+
94
+ # Trade statistics table
95
+ trade_data = self._get_trade_metrics(metrics)
96
+ if trade_data:
97
+ widgets.append(
98
+ Div(
99
+ text=f'<h3 style="color: {title_color}; margin-top: 20px;">Trade Statistics</h3>',
100
+ sizing_mode="stretch_width",
101
+ )
102
+ )
103
+ widgets.append(self._create_metrics_table(trade_data))
104
+
105
+ content = column(*widgets, sizing_mode="stretch_width")
106
+ return content, "Performance"
107
+
108
+ def _collect_metrics(self, strategy):
109
+ """Collect all performance metrics.
110
+
111
+ Args:
112
+ strategy: Strategy instance
113
+
114
+ Returns:
115
+ dict: Performance metrics dictionary
116
+ """
117
+ metrics = {}
118
+
119
+ # Get metrics from analyzers
120
+ for analyzer in getattr(strategy, "analyzers", []):
121
+ analyzer_name = analyzer.__class__.__name__
122
+ try:
123
+ analysis = analyzer.get_analysis()
124
+
125
+ if analyzer_name == "SharpeRatio":
126
+ metrics["sharpe_ratio"] = analysis.get("sharperatio", None)
127
+
128
+ elif analyzer_name == "DrawDown":
129
+ analysis.get("drawdown", {})
130
+ metrics["max_drawdown"] = analysis.get("max", {}).get("drawdown", None)
131
+ metrics["max_drawdown_len"] = analysis.get("max", {}).get("len", None)
132
+
133
+ elif analyzer_name == "TradeAnalyzer":
134
+ total = analysis.get("total", {})
135
+ metrics["total_trades"] = total.get("total", 0)
136
+ metrics["total_open"] = total.get("open", 0)
137
+ metrics["total_closed"] = total.get("closed", 0)
138
+
139
+ won = analysis.get("won", {})
140
+ lost = analysis.get("lost", {})
141
+ metrics["won_trades"] = won.get("total", 0)
142
+ metrics["lost_trades"] = lost.get("total", 0)
143
+
144
+ if metrics["total_closed"] > 0:
145
+ metrics["win_rate"] = metrics["won_trades"] / metrics["total_closed"] * 100
146
+
147
+ pnl = analysis.get("pnl", {})
148
+ metrics["gross_pnl"] = pnl.get("gross", {}).get("total", None)
149
+ metrics["net_pnl"] = pnl.get("net", {}).get("total", None)
150
+
151
+ streak = analysis.get("streak", {})
152
+ metrics["max_win_streak"] = streak.get("won", {}).get("longest", 0)
153
+ metrics["max_lose_streak"] = streak.get("lost", {}).get("longest", 0)
154
+
155
+ elif analyzer_name == "AnnualReturn":
156
+ if analysis:
157
+ # Calculate average annual return
158
+ returns = list(analysis.values())
159
+ if returns:
160
+ metrics["annual_returns"] = analysis
161
+ metrics["avg_annual_return"] = sum(returns) / len(returns) * 100
162
+
163
+ elif analyzer_name == "SQN":
164
+ metrics["sqn"] = analysis.get("sqn", None)
165
+
166
+ elif analyzer_name == "TimeReturn":
167
+ if analysis:
168
+ returns = list(analysis.values())
169
+ if returns:
170
+ total_return = 1
171
+ for r in returns:
172
+ total_return *= 1 + r
173
+ metrics["total_return"] = (total_return - 1) * 100
174
+
175
+ except Exception as e:
176
+ logger.warning("Failed to extract analyzer metrics: %s", e)
177
+
178
+ # Get capital info from broker
179
+ if hasattr(strategy, "broker"):
180
+ try:
181
+ broker = strategy.broker
182
+ start_cash = getattr(broker, "startingcash", 100000)
183
+ end_value = broker.getvalue()
184
+ metrics["start_cash"] = start_cash
185
+ metrics["end_value"] = end_value
186
+ if "total_return" not in metrics and start_cash > 0:
187
+ metrics["total_return"] = (end_value - start_cash) / start_cash * 100
188
+ except Exception as e:
189
+ logger.warning("Failed to get broker capital info: %s", e)
190
+
191
+ return metrics
192
+
193
+ def _create_summary_cards(self, metrics, scheme):
194
+ """Create summary cards HTML.
195
+
196
+ Args:
197
+ metrics: Metrics dictionary
198
+ scheme: Theme
199
+
200
+ Returns:
201
+ str: HTML string
202
+ """
203
+ bg_color = scheme.body_background_color if scheme else "#f5f5f5"
204
+ text_color = scheme.text_color if scheme else "#333"
205
+
206
+ cards = []
207
+
208
+ # Total return
209
+ total_return = metrics.get("total_return")
210
+ if total_return is not None:
211
+ color = "#4caf50" if total_return >= 0 else "#f44336"
212
+ cards.append(f"""
213
+ <div style="background: {bg_color}; padding: 15px; border-radius: 8px; text-align: center; min-width: 150px;">
214
+ <div style="color: {text_color}; font-size: 12px; opacity: 0.8;">Total Return</div>
215
+ <div style="color: {color}; font-size: 24px; font-weight: bold;">{total_return:+.2f}%</div>
216
+ </div>
217
+ """)
218
+
219
+ # Sharpe ratio
220
+ sharpe = metrics.get("sharpe_ratio")
221
+ if sharpe is not None:
222
+ color = "#4caf50" if sharpe >= 1 else ("#ff9800" if sharpe >= 0 else "#f44336")
223
+ cards.append(f"""
224
+ <div style="background: {bg_color}; padding: 15px; border-radius: 8px; text-align: center; min-width: 150px;">
225
+ <div style="color: {text_color}; font-size: 12px; opacity: 0.8;">Sharpe Ratio</div>
226
+ <div style="color: {color}; font-size: 24px; font-weight: bold;">{sharpe:.2f}</div>
227
+ </div>
228
+ """)
229
+
230
+ # Maximum drawdown
231
+ max_dd = metrics.get("max_drawdown")
232
+ if max_dd is not None:
233
+ color = "#4caf50" if max_dd < 10 else ("#ff9800" if max_dd < 20 else "#f44336")
234
+ cards.append(f"""
235
+ <div style="background: {bg_color}; padding: 15px; border-radius: 8px; text-align: center; min-width: 150px;">
236
+ <div style="color: {text_color}; font-size: 12px; opacity: 0.8;">Max Drawdown</div>
237
+ <div style="color: {color}; font-size: 24px; font-weight: bold;">{max_dd:.2f}%</div>
238
+ </div>
239
+ """)
240
+
241
+ # Win rate
242
+ win_rate = metrics.get("win_rate")
243
+ if win_rate is not None:
244
+ color = "#4caf50" if win_rate >= 50 else "#f44336"
245
+ cards.append(f"""
246
+ <div style="background: {bg_color}; padding: 15px; border-radius: 8px; text-align: center; min-width: 150px;">
247
+ <div style="color: {text_color}; font-size: 12px; opacity: 0.8;">Win Rate</div>
248
+ <div style="color: {color}; font-size: 24px; font-weight: bold;">{win_rate:.1f}%</div>
249
+ </div>
250
+ """)
251
+
252
+ # Total trades
253
+ total_trades = metrics.get("total_trades", 0)
254
+ cards.append(f"""
255
+ <div style="background: {bg_color}; padding: 15px; border-radius: 8px; text-align: center; min-width: 150px;">
256
+ <div style="color: {text_color}; font-size: 12px; opacity: 0.8;">Total Trades</div>
257
+ <div style="color: {text_color}; font-size: 24px; font-weight: bold;">{total_trades}</div>
258
+ </div>
259
+ """)
260
+
261
+ html = f"""
262
+ <div style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 20px;">
263
+ {"".join(cards)}
264
+ </div>
265
+ """
266
+ return html
267
+
268
+ def _get_returns_metrics(self, metrics):
269
+ """Get returns-related metrics.
270
+
271
+ Returns:
272
+ dict: Metrics dictionary
273
+ """
274
+ data = {}
275
+
276
+ if "start_cash" in metrics:
277
+ data["Starting Capital"] = f"${metrics['start_cash']:,.2f}"
278
+ if "end_value" in metrics:
279
+ data["Ending Value"] = f"${metrics['end_value']:,.2f}"
280
+ if "total_return" in metrics:
281
+ data["Total Return"] = f"{metrics['total_return']:+.2f}%"
282
+ if "avg_annual_return" in metrics:
283
+ data["Avg Annual Return"] = f"{metrics['avg_annual_return']:+.2f}%"
284
+ if "net_pnl" in metrics and metrics["net_pnl"] is not None:
285
+ data["Net P&L"] = f"${metrics['net_pnl']:,.2f}"
286
+
287
+ return data
288
+
289
+ def _get_risk_metrics(self, metrics):
290
+ """Get risk-related metrics.
291
+
292
+ Returns:
293
+ dict: Metrics dictionary
294
+ """
295
+ data = {}
296
+
297
+ if "sharpe_ratio" in metrics and metrics["sharpe_ratio"] is not None:
298
+ data["Sharpe Ratio"] = f"{metrics['sharpe_ratio']:.3f}"
299
+ if "sqn" in metrics and metrics["sqn"] is not None:
300
+ data["SQN"] = f"{metrics['sqn']:.2f}"
301
+ if "max_drawdown" in metrics and metrics["max_drawdown"] is not None:
302
+ data["Max Drawdown"] = f"{metrics['max_drawdown']:.2f}%"
303
+ if "max_drawdown_len" in metrics and metrics["max_drawdown_len"] is not None:
304
+ data["Max DD Duration"] = f"{metrics['max_drawdown_len']} bars"
305
+
306
+ return data
307
+
308
+ def _get_trade_metrics(self, metrics):
309
+ """Get trade statistics metrics.
310
+
311
+ Returns:
312
+ dict: Metrics dictionary
313
+ """
314
+ data = {}
315
+
316
+ if "total_trades" in metrics:
317
+ data["Total Trades"] = str(metrics["total_trades"])
318
+ if "total_closed" in metrics:
319
+ data["Closed Trades"] = str(metrics["total_closed"])
320
+ if "total_open" in metrics:
321
+ data["Open Trades"] = str(metrics["total_open"])
322
+ if "won_trades" in metrics:
323
+ data["Winning Trades"] = str(metrics["won_trades"])
324
+ if "lost_trades" in metrics:
325
+ data["Losing Trades"] = str(metrics["lost_trades"])
326
+ if "win_rate" in metrics:
327
+ data["Win Rate"] = f"{metrics['win_rate']:.1f}%"
328
+ if "max_win_streak" in metrics:
329
+ data["Max Win Streak"] = str(metrics["max_win_streak"])
330
+ if "max_lose_streak" in metrics:
331
+ data["Max Lose Streak"] = str(metrics["max_lose_streak"])
332
+
333
+ return data
334
+
335
+ def _create_metrics_table(self, data):
336
+ """Create metrics table.
337
+
338
+ Args:
339
+ data: Metrics dictionary
340
+
341
+ Returns:
342
+ DataTable
343
+ """
344
+ source = ColumnDataSource(data={"metric": list(data.keys()), "value": list(data.values())})
345
+
346
+ columns = [
347
+ TableColumn(field="metric", title="Metric", width=200),
348
+ TableColumn(field="value", title="Value", width=150),
349
+ ]
350
+
351
+ table = DataTable(
352
+ source=source,
353
+ columns=columns,
354
+ width=400,
355
+ height=min(len(data) * 28 + 30, 300),
356
+ index_position=None,
357
+ )
358
+
359
+ return table
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Source code tab.
4
+
5
+ Displays strategy source code.
6
+ """
7
+
8
+ import inspect
9
+
10
+ from ..tab import BokehTab
11
+
12
+ try:
13
+ from bokeh.layouts import column
14
+ from bokeh.models.widgets import Div, PreText
15
+
16
+ BOKEH_AVAILABLE = True
17
+ except ImportError:
18
+ BOKEH_AVAILABLE = False
19
+
20
+
21
+ class SourceTab(BokehTab):
22
+ """Source code tab.
23
+
24
+ Displays the strategy's Python source code.
25
+ """
26
+
27
+ def _is_useable(self):
28
+ """Useable when strategy exists."""
29
+ if not BOKEH_AVAILABLE:
30
+ return False
31
+ return self.strategy is not None
32
+
33
+ def _get_panel(self):
34
+ """Get panel content.
35
+
36
+ Returns:
37
+ tuple: (widget, title)
38
+ """
39
+ strategy = self.strategy
40
+ scheme = self.scheme
41
+
42
+ widgets = []
43
+
44
+ # Get theme colors
45
+ title_color = scheme.text_color if scheme else "#333"
46
+
47
+ # Title
48
+ widgets.append(
49
+ Div(
50
+ text=f'<h3 style="color: {title_color};">Strategy Source Code</h3>',
51
+ sizing_mode="stretch_width",
52
+ )
53
+ )
54
+
55
+ # Get source code
56
+ try:
57
+ source_code = inspect.getsource(strategy.__class__)
58
+ except (TypeError, OSError):
59
+ source_code = "# Source code not available"
60
+
61
+ # Create source code display component
62
+ source_pre = PreText(
63
+ text=source_code,
64
+ width=800,
65
+ height=500,
66
+ )
67
+ widgets.append(source_pre)
68
+
69
+ content = column(*widgets, sizing_mode="stretch_width")
70
+ return content, "Source"
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Utility functions module.
4
+ """
5
+
6
+ from .helpers import get_datanames, get_strategy_label, sanitize_source_name
7
+
8
+ __all__ = ["get_datanames", "get_strategy_label", "sanitize_source_name"]