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
backtrader/channel.py ADDED
@@ -0,0 +1,682 @@
1
+ """Data channel infrastructure for tick-level backtesting.
2
+
3
+ This module provides the core channel system:
4
+ - Event / EventPriority: Event wrapper with priority for queue ordering
5
+ - DataChannel: Base class for all data channels (Tick, OrderBook, Funding)
6
+ - DataValidationResult: Result container for data validation
7
+ - StreamingEventQueue: Memory-efficient event queue with adaptive preloading
8
+ - ChannelSharingMode: Enum for channel sharing between strategies
9
+
10
+ The channel system is independent of LineSeries and uses deque for buffering,
11
+ enabling high-frequency event processing without the overhead of the
12
+ traditional bar-based data system.
13
+
14
+ Example:
15
+ Basic event queue usage::
16
+
17
+ queue = StreamingEventQueue(channels=[tick_channel], bars=[])
18
+ while not queue.empty:
19
+ event = queue.pop()
20
+ process(event)
21
+ """
22
+
23
+ import heapq
24
+ from collections import deque
25
+ from dataclasses import dataclass, field
26
+ from enum import Enum, IntEnum
27
+ from typing import Any, Dict, Iterator, List, Optional, Tuple
28
+
29
+ from .utils.log_message import get_logger
30
+
31
+ logger = get_logger(__name__)
32
+
33
+
34
+ class EventPriority(IntEnum):
35
+ """Event processing priority (lower value = higher priority).
36
+
37
+ Within the same timestamp, events are processed in priority order.
38
+ """
39
+
40
+ SYSTEM = 0
41
+ FUNDING = 10
42
+ TICK = 20
43
+ ORDERBOOK = 30
44
+ BAR = 40
45
+
46
+
47
+ @dataclass(order=True)
48
+ class Event:
49
+ """Event wrapper for queue ordering.
50
+
51
+ Events are ordered by (timestamp, priority, sequence) for deterministic
52
+ processing order. The data field is excluded from comparison.
53
+
54
+ Attributes:
55
+ timestamp: Event timestamp (seconds).
56
+ priority: Processing priority (lower = first).
57
+ sequence: Insertion sequence number for stable sort.
58
+ channel_type: Source channel type identifier.
59
+ channel_name: Source channel/symbol name.
60
+ data: The actual event data (EventData subclass instance).
61
+ """
62
+
63
+ timestamp: float = 0.0
64
+ priority: int = field(default=EventPriority.TICK)
65
+ sequence: int = field(default=0, compare=True)
66
+ channel_type: str = field(default="", compare=False)
67
+ channel_name: str = field(default="", compare=False)
68
+ data: Any = field(default=None, compare=False, repr=False)
69
+
70
+
71
+ class ChannelDataRef:
72
+ """Lightweight data reference for channel-only strategies.
73
+
74
+ Channel-mode HFT strategies submit orders through the standard
75
+ ``Strategy.buy`` / ``Strategy.sell`` APIs but may not have LineSeries
76
+ data feeds. This object provides the minimal data identity expected by
77
+ brokers and order objects: ``_name``, ``name`` and ``symbol``.
78
+ """
79
+
80
+ def __init__(self, symbol, channel_name=None):
81
+ self._name = str(symbol)
82
+ self.name = str(symbol)
83
+ self.symbol = str(symbol)
84
+ self.channel_name = str(channel_name or symbol)
85
+
86
+ def __repr__(self):
87
+ return f"ChannelDataRef(symbol={self.symbol!r})"
88
+
89
+
90
+ class ChannelSharingMode(Enum):
91
+ """Channel sharing mode between strategies.
92
+
93
+ - EXCLUSIVE: One strategy owns the channel exclusively.
94
+ - SHARED_READONLY: Multiple strategies can read, none can modify.
95
+ - SHARED_ISOLATED: Each strategy gets its own cursor/state.
96
+ - SHARED_FULL: Full sharing with write access (use with caution).
97
+ """
98
+
99
+ EXCLUSIVE = "exclusive"
100
+ SHARED_READONLY = "shared_readonly"
101
+ SHARED_ISOLATED = "shared_isolated"
102
+ SHARED_FULL = "shared_full"
103
+
104
+
105
+ @dataclass
106
+ class DataValidationResult:
107
+ """Result of data validation.
108
+
109
+ Attributes:
110
+ valid: Whether the data passed validation.
111
+ errors: List of error descriptions.
112
+ warnings: List of warning descriptions.
113
+ auto_fixed: Whether the data was auto-fixed.
114
+ fixed_fields: Dict of field names to (original, fixed) values.
115
+ """
116
+
117
+ valid: bool = True
118
+ errors: List[str] = field(default_factory=list)
119
+ warnings: List[str] = field(default_factory=list)
120
+ auto_fixed: bool = False
121
+ fixed_fields: Dict[str, Tuple[Any, Any]] = field(default_factory=dict)
122
+
123
+
124
+ class DataChannel:
125
+ """Base class for all data channels.
126
+
127
+ Channels provide buffered, validated data streams independent of
128
+ the LineSeries system. Each channel type (Tick, OrderBook, Funding)
129
+ subclasses DataChannel and implements type-specific validation.
130
+
131
+ Attributes:
132
+ symbol: Trading pair symbol.
133
+ channel_type: Channel type identifier (set by subclasses).
134
+ maxlen: Maximum buffer size.
135
+ sharing_mode: How the channel is shared between strategies.
136
+
137
+ Args:
138
+ symbol: Trading pair symbol (e.g., 'BTC/USDT').
139
+ maxlen: Maximum number of events to buffer.
140
+ validate: Whether to validate incoming events.
141
+ auto_fix: Whether to attempt auto-fixing invalid data.
142
+ sharing_mode: Channel sharing mode.
143
+ **kwargs: Additional channel parameters.
144
+ """
145
+
146
+ channel_type = "generic"
147
+
148
+ def __init__(
149
+ self,
150
+ symbol,
151
+ maxlen=10000,
152
+ validate=True,
153
+ auto_fix=True,
154
+ sharing_mode=ChannelSharingMode.SHARED_READONLY,
155
+ **kwargs,
156
+ ):
157
+ """Initialize a DataChannel.
158
+
159
+ Args:
160
+ symbol: Trading pair symbol (e.g., 'BTC/USDT').
161
+ maxlen: Maximum number of events to buffer.
162
+ validate: Whether to validate incoming events.
163
+ auto_fix: Whether to attempt auto-fixing invalid data.
164
+ sharing_mode: Channel sharing mode between strategies.
165
+ **kwargs: Additional channel parameters.
166
+ """
167
+ self.symbol = symbol
168
+ self.maxlen = maxlen
169
+ self.params = kwargs
170
+ self._buffer: deque = deque(maxlen=maxlen)
171
+ self._event_count = 0
172
+ self._validate = validate
173
+ self._auto_fix = auto_fix
174
+ self._validation_errors = []
175
+ self._last_timestamp = None
176
+ self.sharing_mode = sharing_mode
177
+ self._strategy_states = {}
178
+ self._dataname = kwargs.get("dataname")
179
+
180
+ @property
181
+ def latest(self):
182
+ """Get the most recent event in the buffer."""
183
+ return self._buffer[-1] if self._buffer else None
184
+
185
+ @property
186
+ def event_count(self):
187
+ """Total number of events pushed to this channel."""
188
+ return self._event_count
189
+
190
+ @property
191
+ def buffer_size(self):
192
+ """Current number of events in the buffer."""
193
+ return len(self._buffer)
194
+
195
+ def push(self, event) -> bool:
196
+ """Push an event into the channel buffer.
197
+
198
+ If validation is enabled, the event is validated (and potentially
199
+ auto-fixed) before being added to the buffer.
200
+
201
+ Args:
202
+ event: An EventData subclass instance.
203
+
204
+ Returns:
205
+ True if the event was accepted, False if rejected.
206
+ """
207
+ if self._validate:
208
+ result = self._validate_event(event)
209
+ if not result.valid:
210
+ self._validation_errors.append(result)
211
+ return False
212
+ if result.auto_fixed:
213
+ logger.debug("Auto-fixed event for %s: %s", self.symbol, result.fixed_fields)
214
+
215
+ self._buffer.append(event)
216
+ self._event_count += 1
217
+ self._last_timestamp = event.timestamp
218
+ return True
219
+
220
+ def _validate_event(self, event) -> DataValidationResult:
221
+ """Validate an event. Override in subclasses for type-specific checks.
222
+
223
+ Args:
224
+ event: The event to validate.
225
+
226
+ Returns:
227
+ DataValidationResult with validation outcome.
228
+ """
229
+ result = DataValidationResult()
230
+
231
+ # Basic validation
232
+ if not hasattr(event, "timestamp"):
233
+ result.valid = False
234
+ result.errors.append("Event missing timestamp")
235
+ return result
236
+
237
+ if not hasattr(event, "validate") or not event.validate():
238
+ result.valid = False
239
+ result.errors.append("Event failed built-in validation")
240
+ return result
241
+
242
+ # Timestamp ordering check
243
+ if self._last_timestamp is not None:
244
+ if event.timestamp < self._last_timestamp:
245
+ if self._auto_fix:
246
+ result.warnings.append(
247
+ f"Out-of-order timestamp: {event.timestamp} < {self._last_timestamp}"
248
+ )
249
+ result.auto_fixed = True
250
+ result.fixed_fields["timestamp"] = (event.timestamp, self._last_timestamp)
251
+ event.timestamp = self._last_timestamp
252
+ else:
253
+ result.valid = False
254
+ result.errors.append(
255
+ f"Out-of-order timestamp: {event.timestamp} < {self._last_timestamp}"
256
+ )
257
+
258
+ return result
259
+
260
+ def get_state(self, strategy_id: str) -> dict:
261
+ """Get per-strategy state for isolated sharing mode.
262
+
263
+ Args:
264
+ strategy_id: Unique identifier for the strategy.
265
+
266
+ Returns:
267
+ Dict containing the strategy's channel state.
268
+ """
269
+ if strategy_id not in self._strategy_states:
270
+ self._strategy_states[strategy_id] = {
271
+ "cursor": 0,
272
+ "last_event": None,
273
+ }
274
+ return self._strategy_states[strategy_id]
275
+
276
+ def load(self) -> Iterator:
277
+ """Load events from the data source.
278
+
279
+ Subclasses should override this to implement data loading from
280
+ files, databases, or other sources.
281
+
282
+ Yields:
283
+ EventData instances.
284
+ """
285
+ raise NotImplementedError(f"{self.__class__.__name__} must implement load()")
286
+
287
+ def get_validation_errors(self) -> List[DataValidationResult]:
288
+ """Get all validation errors encountered."""
289
+ return list(self._validation_errors)
290
+
291
+ def clear_validation_errors(self):
292
+ """Clear accumulated validation errors."""
293
+ self._validation_errors.clear()
294
+
295
+ def __len__(self):
296
+ """Return the current number of events in the buffer.
297
+
298
+ Returns:
299
+ int: Number of events currently buffered.
300
+ """
301
+ return len(self._buffer)
302
+
303
+ def __iter__(self):
304
+ """Iterate over events in the buffer.
305
+
306
+ Returns:
307
+ Iterator over events in insertion order.
308
+ """
309
+ return iter(self._buffer)
310
+
311
+ def __repr__(self):
312
+ """Return a string representation of the channel.
313
+
314
+ Returns:
315
+ str: Representation showing symbol, type, and event counts.
316
+ """
317
+ return (
318
+ f"{self.__class__.__name__}(symbol={self.symbol!r}, "
319
+ f"type={self.channel_type!r}, "
320
+ f"events={self._event_count}, "
321
+ f"buffered={len(self._buffer)})"
322
+ )
323
+
324
+
325
+ class StreamingEventQueue:
326
+ """Memory-efficient event queue with adaptive preloading.
327
+
328
+ Merges events from multiple channels and bar data sources into a
329
+ single ordered stream. Uses a heap (priority queue) for efficient
330
+ merging and supports adaptive preload windows to control memory usage.
331
+
332
+ The queue loads data in chunks rather than all at once, keeping
333
+ memory usage bounded regardless of total data size.
334
+
335
+ Args:
336
+ channels: List of DataChannel instances.
337
+ bars: List of bar data iterators.
338
+ preload_window: Initial preload time window in seconds.
339
+ max_memory_mb: Maximum memory target in MB.
340
+ adaptive: Whether to adapt the preload window based on memory.
341
+ batch_size: Number of events to load per batch from each channel.
342
+
343
+ Example::
344
+
345
+ queue = StreamingEventQueue(
346
+ channels=[tick_channel, ob_channel],
347
+ bars=[bar_data],
348
+ preload_window=300.0,
349
+ max_memory_mb=200,
350
+ adaptive=True
351
+ )
352
+ while not queue.empty:
353
+ event = queue.pop()
354
+ # process event
355
+ """
356
+
357
+ def __init__(
358
+ self,
359
+ channels=None,
360
+ bars=None,
361
+ preload_window=300.0,
362
+ max_memory_mb=200,
363
+ adaptive=True,
364
+ batch_size=10000,
365
+ ):
366
+ """Initialize a StreamingEventQueue.
367
+
368
+ Args:
369
+ channels: List of DataChannel instances.
370
+ bars: List of bar data iterators.
371
+ preload_window: Initial preload time window in seconds.
372
+ max_memory_mb: Maximum memory target in MB.
373
+ adaptive: Whether to adapt the preload window based on memory.
374
+ batch_size: Number of events to load per batch from each channel.
375
+ """
376
+ self._channels = channels or []
377
+ self._bars = bars or []
378
+ self._window = preload_window
379
+ self._max_memory = max_memory_mb * 1024 * 1024
380
+ self._adaptive = adaptive
381
+ self._batch_size = batch_size
382
+
383
+ # Heap: (timestamp, priority, sequence, Event)
384
+ self._heap = []
385
+ self._sequence = 0
386
+
387
+ # Tracking
388
+ self._current_ts = float("-inf")
389
+ self._preload_up_to = float("-inf")
390
+
391
+ # Channel iterators (lazy initialized)
392
+ self._channel_iters = {}
393
+ self._bar_iters = {}
394
+ self._channel_exhausted = set()
395
+ self._bar_exhausted = set()
396
+
397
+ # Adaptive window parameters
398
+ self._window_min = 60.0
399
+ self._window_max = 600.0
400
+ self._adjustment_count = 0
401
+
402
+ # Statistics
403
+ self._total_events_popped = 0
404
+
405
+ # Initialize iterators
406
+ self._init_iterators()
407
+ # Initial preload
408
+ self._ensure_preload()
409
+
410
+ def _init_iterators(self):
411
+ """Initialize iterators for all channels and bar data."""
412
+ for i, channel in enumerate(self._channels):
413
+ try:
414
+ self._channel_iters[i] = iter(channel.load())
415
+ except Exception as e:
416
+ logger.warning("Failed to init iterator for channel %s: %s", channel, e)
417
+ self._channel_exhausted.add(i)
418
+
419
+ for i, bar_data in enumerate(self._bars):
420
+ try:
421
+ self._bar_iters[i] = iter(bar_data)
422
+ except Exception as e:
423
+ logger.warning("Failed to init iterator for bar data %d: %s", i, e)
424
+ self._bar_exhausted.add(i)
425
+
426
+ def _ensure_preload(self):
427
+ """Ensure events are preloaded up to the current window boundary.
428
+
429
+ Loads events from all channels and bar data sources up to the target
430
+ timestamp (current timestamp + preload window). Skips already-loaded
431
+ ranges to avoid redundant work.
432
+ """
433
+ if self._current_ts == float("-inf"):
434
+ # Initial load: use inf to load the first batch fully
435
+ target_ts = float("inf")
436
+ else:
437
+ target_ts = self._current_ts + self._window
438
+ if target_ts <= self._preload_up_to:
439
+ return
440
+
441
+ # Load from channels
442
+ for idx, ch_iter in list(self._channel_iters.items()):
443
+ if idx in self._channel_exhausted:
444
+ continue
445
+ self._load_from_channel(idx, ch_iter, target_ts)
446
+
447
+ # Load from bar data
448
+ for idx, bar_iter in list(self._bar_iters.items()):
449
+ if idx in self._bar_exhausted:
450
+ continue
451
+ self._load_from_bars(idx, bar_iter, target_ts)
452
+
453
+ self._preload_up_to = target_ts
454
+
455
+ def _load_from_channel(self, idx, ch_iter, target_ts):
456
+ """Load events from a channel iterator up to target timestamp.
457
+
458
+ Args:
459
+ idx: Index of the channel.
460
+ ch_iter: Iterator for the channel.
461
+ target_ts: Target timestamp to load up to.
462
+ """
463
+ channel = self._channels[idx]
464
+ loaded = 0
465
+
466
+ try:
467
+ while loaded < self._batch_size:
468
+ event = next(ch_iter)
469
+ if not hasattr(event, "timestamp"):
470
+ continue
471
+
472
+ wrapped = Event(
473
+ timestamp=event.timestamp,
474
+ priority=self._get_channel_priority(channel),
475
+ sequence=self._sequence,
476
+ channel_type=channel.channel_type,
477
+ channel_name=channel.symbol,
478
+ data=event,
479
+ )
480
+ self._sequence += 1
481
+ heapq.heappush(self._heap, wrapped)
482
+ loaded += 1
483
+
484
+ if event.timestamp > target_ts:
485
+ break
486
+
487
+ except StopIteration:
488
+ self._channel_exhausted.add(idx)
489
+
490
+ def _load_from_bars(self, idx, bar_iter, target_ts):
491
+ """Load events from a bar data iterator up to target timestamp.
492
+
493
+ Args:
494
+ idx: Index of the bar data source.
495
+ bar_iter: Iterator for the bar data source.
496
+ target_ts: Target timestamp to load up to.
497
+ """
498
+ loaded = 0
499
+
500
+ try:
501
+ while loaded < self._batch_size:
502
+ bar_event = next(bar_iter)
503
+ if not hasattr(bar_event, "timestamp"):
504
+ continue
505
+
506
+ wrapped = Event(
507
+ timestamp=bar_event.timestamp,
508
+ priority=EventPriority.BAR,
509
+ sequence=self._sequence,
510
+ channel_type="bar",
511
+ channel_name=getattr(bar_event, "symbol", ""),
512
+ data=bar_event,
513
+ )
514
+ self._sequence += 1
515
+ heapq.heappush(self._heap, wrapped)
516
+ loaded += 1
517
+
518
+ if bar_event.timestamp > target_ts:
519
+ break
520
+
521
+ except StopIteration:
522
+ self._bar_exhausted.add(idx)
523
+
524
+ def _get_channel_priority(self, channel) -> int:
525
+ """Map channel type to event priority."""
526
+ priority_map = {
527
+ "tick": EventPriority.TICK,
528
+ "orderbook": EventPriority.ORDERBOOK,
529
+ "funding_rate": EventPriority.FUNDING,
530
+ "funding": EventPriority.FUNDING,
531
+ "bar": EventPriority.BAR,
532
+ }
533
+ return priority_map.get(channel.channel_type, EventPriority.TICK)
534
+
535
+ @property
536
+ def empty(self) -> bool:
537
+ """Whether the queue is empty and all sources exhausted."""
538
+ if self._heap:
539
+ return False
540
+ # Try loading more
541
+ all_exhausted = self._channel_exhausted.issuperset(
542
+ self._channel_iters.keys()
543
+ ) and self._bar_exhausted.issuperset(self._bar_iters.keys())
544
+ if all_exhausted:
545
+ return True
546
+ # Try preloading ahead
547
+ self._preload_up_to = float("-inf")
548
+ self._ensure_preload()
549
+ return len(self._heap) == 0
550
+
551
+ def pop(self) -> Optional[Event]:
552
+ """Pop the next event from the queue.
553
+
554
+ Returns the event with the smallest (timestamp, priority, sequence).
555
+ Triggers preloading if needed.
556
+
557
+ Returns:
558
+ The next Event, or None if the queue is empty.
559
+ """
560
+ if not self._heap:
561
+ if self.empty:
562
+ return None
563
+
564
+ if not self._heap:
565
+ return None
566
+
567
+ event = heapq.heappop(self._heap)
568
+ self._current_ts = event.timestamp
569
+ self._total_events_popped += 1
570
+
571
+ # Trigger preload if we're getting close to the boundary
572
+ if self._current_ts + self._window * 0.5 >= self._preload_up_to:
573
+ self._ensure_preload()
574
+
575
+ # Adaptive window adjustment
576
+ if self._adaptive and self._total_events_popped % 1000 == 0:
577
+ self._adjust_window()
578
+
579
+ return event
580
+
581
+ def peek(self) -> Optional[Event]:
582
+ """Peek at the next event without removing it.
583
+
584
+ Returns:
585
+ The next Event, or None if the queue is empty.
586
+ """
587
+ if not self._heap:
588
+ if self.empty:
589
+ return None
590
+ return self._heap[0] if self._heap else None
591
+
592
+ def _adjust_window(self):
593
+ """Adjust preload window based on current memory usage.
594
+
595
+ Shrinks the window if memory usage exceeds 80% of the maximum,
596
+ grows it if usage is below 30% and the window is below maximum.
597
+ Adjustments are made gradually (multiply by 0.7 or 1.3) to avoid
598
+ oscillation.
599
+ """
600
+ mem_usage = self._estimate_memory_usage()
601
+
602
+ if mem_usage > self._max_memory * 0.8:
603
+ # Shrink window
604
+ self._window = max(self._window_min, self._window * 0.7)
605
+ self._adjustment_count += 1
606
+ logger.debug(
607
+ "Shrinking preload window to %.0fs (memory: %.1fMB)",
608
+ self._window,
609
+ mem_usage / 1024 / 1024,
610
+ )
611
+ elif mem_usage < self._max_memory * 0.3 and self._window < self._window_max:
612
+ # Grow window
613
+ self._window = min(self._window_max, self._window * 1.3)
614
+ self._adjustment_count += 1
615
+ logger.debug(
616
+ "Growing preload window to %.0fs (memory: %.1fMB)",
617
+ self._window,
618
+ mem_usage / 1024 / 1024,
619
+ )
620
+
621
+ def _estimate_memory_usage(self) -> int:
622
+ """Estimate current memory usage of the heap.
623
+
624
+ Returns:
625
+ Estimated memory usage in bytes.
626
+ """
627
+ # Rough estimate: each event ~200 bytes (dataclass + heap entry)
628
+ return len(self._heap) * 200
629
+
630
+ @property
631
+ def heap_size(self) -> int:
632
+ """Current number of events in the heap."""
633
+ return len(self._heap)
634
+
635
+ @property
636
+ def total_events_popped(self) -> int:
637
+ """Total number of events popped from the queue."""
638
+ return self._total_events_popped
639
+
640
+ @property
641
+ def current_timestamp(self) -> float:
642
+ """Current processing timestamp."""
643
+ return self._current_ts
644
+
645
+ def __len__(self):
646
+ """Return the current number of events in the heap.
647
+
648
+ Returns:
649
+ int: Number of events currently in the heap.
650
+ """
651
+ return len(self._heap)
652
+
653
+ def __iter__(self):
654
+ """Iterate over all events in timestamp order.
655
+
656
+ Yields:
657
+ Event: The next event in timestamp order.
658
+ """
659
+ while not self.empty:
660
+ event = self.pop()
661
+ if event is not None:
662
+ yield event
663
+
664
+ def __bool__(self):
665
+ """Return whether the queue has events available.
666
+
667
+ Returns:
668
+ bool: True if the queue is not empty, False otherwise.
669
+ """
670
+ return not self.empty
671
+
672
+ def __repr__(self):
673
+ """Return a string representation of the queue.
674
+
675
+ Returns:
676
+ str: Representation showing heap size, popped count, and window.
677
+ """
678
+ return (
679
+ f"StreamingEventQueue(heap={len(self._heap)}, "
680
+ f"popped={self._total_events_popped}, "
681
+ f"window={self._window:.0f}s)"
682
+ )
@@ -0,0 +1,23 @@
1
+ """Data channels package for tick-level backtesting.
2
+
3
+ Provides specialized data channels for different market data types:
4
+ - TickChannel: Trade/tick data
5
+ - OrderBookChannel: Order book depth snapshots
6
+ - FundingRateChannel: Funding rate data for perpetual contracts
7
+ """
8
+
9
+ from .bridge import ChannelBridge
10
+ from .funding import FundingRateChannel
11
+ from .live_queue import LiveEventQueue
12
+ from .live_validator import LiveDataValidator
13
+ from .orderbook import OrderBookChannel
14
+ from .tick import TickChannel
15
+
16
+ __all__ = [
17
+ "TickChannel",
18
+ "OrderBookChannel",
19
+ "FundingRateChannel",
20
+ "ChannelBridge",
21
+ "LiveEventQueue",
22
+ "LiveDataValidator",
23
+ ]