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/comminfo.py ADDED
@@ -0,0 +1,665 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Refactored CommInfo system (Day 44)
4
+
5
+ Migrated CommInfo system from MetaParams to new ParameterizedBase system.
6
+ Maintains fully backward compatible API interface.
7
+ """
8
+
9
+ import inspect
10
+
11
+ from .parameters import BoolParam, Float, ParameterDescriptor, ParameterizedBase, _BoolValidator
12
+
13
+
14
+ class _StockLikeDescriptor(ParameterDescriptor):
15
+ def __get__(self, obj, objtype=None):
16
+ if obj is None:
17
+ return self
18
+
19
+ try:
20
+ return object.__getattribute__(obj, "_stocklike")
21
+ except AttributeError:
22
+ return super().__get__(obj, objtype)
23
+
24
+
25
+ class CommInfoBase(ParameterizedBase):
26
+ """Base Class for the Commission Schemes.
27
+
28
+ Migrated from MetaParams to ParameterizedBase system for better
29
+ parameter management and validation.
30
+
31
+ Params:
32
+ - commission (def: 0.0): base commission value in percentage or monetary units
33
+ - mult (def 1.0): multiplier applied to the asset for value/profit
34
+ - margin (def: None): amount of monetary units needed to open/hold an operation
35
+ - automargin (def: False): Used by get_margin to automatically calculate margin
36
+ - commtype (def: None): Commission type (COMM_PERC/COMM_FIXED)
37
+ - stocklike (def: False): Indicates if the instrument is Stock-like or Futures-like
38
+ - percabs (def: False): whether commission is XX% or 0.XX when commtype is COMM_PERC
39
+ - interest (def: 0.0): yearly interest charged for holding short selling position
40
+ - interest_long (def: False): whether to charge interest on long positions
41
+ - leverage (def: 1.0): amount of leverage for the asset
42
+ """
43
+
44
+ # Commission type constants
45
+ COMM_PERC, COMM_FIXED = 0, 1
46
+
47
+ # Parameter descriptor definitions
48
+ commission = ParameterDescriptor(
49
+ default=0.0,
50
+ type_=float,
51
+ validator=Float(min_val=0.0), # Non-negative validation
52
+ doc="Base commission, percentage or monetary units",
53
+ )
54
+
55
+ maker_commission = ParameterDescriptor(
56
+ default=None,
57
+ doc="Optional maker commission override, percentage or monetary units",
58
+ )
59
+
60
+ taker_commission = ParameterDescriptor(
61
+ default=None,
62
+ doc="Optional taker commission override, percentage or monetary units",
63
+ )
64
+
65
+ open_commission = ParameterDescriptor(
66
+ default=None,
67
+ doc="Optional opening commission override, percentage or monetary units",
68
+ )
69
+
70
+ close_commission = ParameterDescriptor(
71
+ default=None,
72
+ doc="Optional closing commission override, percentage or monetary units",
73
+ )
74
+
75
+ close_today_commission = ParameterDescriptor(
76
+ default=None,
77
+ doc="Optional close-today commission override, percentage or monetary units",
78
+ )
79
+
80
+ close_yesterday_commission = ParameterDescriptor(
81
+ default=None,
82
+ doc="Optional close-yesterday commission override, percentage or monetary units",
83
+ )
84
+
85
+ mult = ParameterDescriptor(
86
+ default=1.0,
87
+ type_=float,
88
+ validator=Float(min_val=0.001),
89
+ doc="Asset multiplier", # Must be positive
90
+ )
91
+
92
+ margin = ParameterDescriptor(default=None, doc="Margin amount")
93
+
94
+ commtype = ParameterDescriptor(
95
+ default=None, type_=(int, type(None)), doc="Commission type (COMM_PERC/COMM_FIXED)"
96
+ )
97
+
98
+ stocklike = _StockLikeDescriptor(
99
+ default=False, type_=bool, validator=_BoolValidator(), doc="Whether stock type"
100
+ )
101
+
102
+ percabs = BoolParam(default=False, doc="Whether percentage is absolute value")
103
+
104
+ interest = ParameterDescriptor(
105
+ default=0.0,
106
+ type_=float,
107
+ validator=Float(min_val=0.0),
108
+ doc="Annual interest rate", # Non-negative validation
109
+ )
110
+
111
+ interest_long = BoolParam(default=False, doc="Whether to charge interest on long positions")
112
+
113
+ leverage = ParameterDescriptor(
114
+ default=1.0,
115
+ type_=float,
116
+ validator=Float(min_val=0.001),
117
+ doc="Leverage level", # Must be positive
118
+ )
119
+
120
+ automargin = ParameterDescriptor(
121
+ default=False, type_=(bool, float), doc="Automatic margin calculation"
122
+ )
123
+
124
+ def __init__(self, **kwargs):
125
+ """Initialize CommInfo object"""
126
+ super().__init__()
127
+
128
+ # Special handling for margin parameter None value validation
129
+ if "margin" in kwargs:
130
+ margin_value = kwargs["margin"]
131
+ if margin_value is not None and margin_value < 0.0:
132
+ raise ValueError(f"margin must be non-negative, got {margin_value}")
133
+
134
+ # Set passed parameters
135
+ for name, value in kwargs.items():
136
+ if name in self._param_manager._descriptors:
137
+ # Skip margin standard validation, already handled above
138
+ if name == "margin":
139
+ self._param_manager.set(name, value, skip_validation=True)
140
+ else:
141
+ self.set_param(name, value)
142
+
143
+ # Execute parameter post-processing and compatibility settings
144
+ self._post_init_setup()
145
+
146
+ def _post_init_setup(self):
147
+ """Parameter post-processing and internal state setup"""
148
+ # Get initial values from parameters
149
+ self._stocklike = self.get_param("stocklike")
150
+ self._commtype = self.get_param("commtype")
151
+
152
+ # Compatibility logic: if commtype is None, set type based on margin (consistent with original implementation)
153
+ if self._commtype is None:
154
+ if self.get_param("margin"):
155
+ self._stocklike = False
156
+ self._commtype = self.COMM_FIXED
157
+ else:
158
+ self._stocklike = True
159
+ self._commtype = self.COMM_PERC
160
+
161
+ # PERFORMANCE OPTIMIZATION: Cache mult parameter (called 1.55M+ times)
162
+ self._mult = self.get_param("mult")
163
+
164
+ # Parameter post-processing (consistent with original implementation)
165
+ if not self._stocklike and not self.get_param("margin"):
166
+ # Directly modify value in parameter manager to avoid validation issues
167
+ self._param_manager.set("margin", 1.0, skip_validation=True)
168
+
169
+ # Handle percentage commission conversion (important! consistent with original implementation)
170
+ if self._commtype == self.COMM_PERC and not self.get_param("percabs"):
171
+ current_commission = self.get_param("commission")
172
+ # Directly modify parameter value to avoid duplicate conversion
173
+ self._param_manager.set("commission", current_commission / 100.0, skip_validation=True)
174
+ for name in (
175
+ "maker_commission",
176
+ "taker_commission",
177
+ "open_commission",
178
+ "close_commission",
179
+ "close_today_commission",
180
+ "close_yesterday_commission",
181
+ ):
182
+ value = self.get_param(name)
183
+ if value is not None:
184
+ self._param_manager.set(name, value / 100.0, skip_validation=True)
185
+
186
+ # Calculate interest rate (guard against None interest)
187
+ interest = self.get_param("interest")
188
+ self._creditrate = (interest or 0.0) / 365.0
189
+ self._margin = self.get_param("margin")
190
+ self._automargin = self.get_param("automargin")
191
+ self._leverage_param = self.get_param("leverage")
192
+ self._interest_long = self.get_param("interest_long")
193
+
194
+ __getattribute__ = object.__getattribute__
195
+
196
+ def set_param(self, name, value, validate=True):
197
+ super().set_param(name, value, validate=validate)
198
+ if name == "margin":
199
+ self._margin = value
200
+ elif name == "automargin":
201
+ self._automargin = value
202
+ elif name == "leverage":
203
+ self._leverage_param = value
204
+ elif name == "interest_long":
205
+ self._interest_long = value
206
+ elif name == "interest":
207
+ self._creditrate = (value or 0.0) / 365.0
208
+ elif name == "mult":
209
+ self._mult = value
210
+ elif name == "stocklike":
211
+ self._stocklike = value
212
+ elif name == "commtype":
213
+ self._commtype = value
214
+
215
+ def get_margin(self, price):
216
+ """Returns the actual margin/guarantees needed for a single item of the
217
+ asset at the given price. The default implementation has this policy:
218
+
219
+ - Use param ``margin`` if param ``automargin`` evaluates to ``False``
220
+ - Use param ``mult`` * ``price`` if ``automargin < 0``
221
+ - Use param ``automargin`` * ``price`` if ``automargin > 0``
222
+ """
223
+ automargin = self._automargin
224
+ if not automargin:
225
+ return self._margin
226
+ if automargin < 0:
227
+ return price * self._mult
228
+ return price * automargin
229
+
230
+ def get_leverage(self):
231
+ """Returns the level of leverage allowed for this commission scheme"""
232
+ return self._leverage_param
233
+
234
+ def getsize(self, price, cash):
235
+ """Returns the needed size to meet a cash operation at a given price"""
236
+ if not price:
237
+ return 0
238
+ leverage = self._leverage_param
239
+ if not self._stocklike:
240
+ margin = self.get_margin(price)
241
+ if not margin:
242
+ return 0
243
+ return leverage * (cash // margin)
244
+ return leverage * (cash // price)
245
+
246
+ def getoperationcost(self, size, price):
247
+ """Returns the needed amount of cash an operation would cost"""
248
+ if not self._stocklike:
249
+ return abs(size) * self.get_margin(price)
250
+ return abs(size) * price
251
+
252
+ def getvaluesize(self, size, price):
253
+ """Returns the value of size for given a price. For future-like
254
+ objects it is fixed at size * margin"""
255
+ if not self._stocklike:
256
+ return abs(size) * self.get_margin(price)
257
+ return size * price
258
+
259
+ def getvalue(self, position, price):
260
+ """Returns the value of a position given a price. For future-like
261
+ objects it is fixed at size * margin"""
262
+ if not self._stocklike:
263
+ return abs(position.size) * self.get_margin(price)
264
+
265
+ size = position.size
266
+ if size >= 0:
267
+ return size * price
268
+
269
+ # With stocks, a short position is worth more as the price goes down
270
+ value = position.price * size # original value
271
+ value += (position.price - price) * size # increased value
272
+ return value
273
+
274
+ def _resolve_commission_rate(self, role=None):
275
+ """Return the commission rate for the requested fill role."""
276
+ role_text = str(role or "").strip().lower()
277
+ if role_text in {"open", "opened"}:
278
+ open_commission = self.get_param("open_commission")
279
+ if open_commission is not None:
280
+ return open_commission
281
+
282
+ if role_text in {"close_today", "closetoday"}:
283
+ close_today_commission = self.get_param("close_today_commission")
284
+ if close_today_commission is not None:
285
+ return close_today_commission
286
+ close_commission = self.get_param("close_commission")
287
+ if close_commission is not None:
288
+ return close_commission
289
+
290
+ if role_text in {"close_yesterday", "closeyesterday"}:
291
+ close_yesterday_commission = self.get_param("close_yesterday_commission")
292
+ if close_yesterday_commission is not None:
293
+ return close_yesterday_commission
294
+ close_commission = self.get_param("close_commission")
295
+ if close_commission is not None:
296
+ return close_commission
297
+
298
+ if role_text in {"close", "closed"}:
299
+ close_commission = self.get_param("close_commission")
300
+ if close_commission is not None:
301
+ return close_commission
302
+
303
+ if role == "maker":
304
+ maker_commission = self.get_param("maker_commission")
305
+ if maker_commission is not None:
306
+ return maker_commission
307
+
308
+ if role == "taker":
309
+ taker_commission = self.get_param("taker_commission")
310
+ if taker_commission is not None:
311
+ return taker_commission
312
+
313
+ return self.get_param("commission")
314
+
315
+ def _getcommission(self, size, price, pseudoexec, role=None):
316
+ """Calculates the commission of an operation at a given price
317
+
318
+ pseudoexec: if True the operation has not yet been executed
319
+ """
320
+ _ = pseudoexec
321
+ commission = self._resolve_commission_rate(role)
322
+ if self._commtype == self.COMM_PERC:
323
+ return abs(size) * commission * price
324
+ return abs(size) * commission
325
+
326
+ def _call_getcommission(self, size, price, pseudoexec, role=None):
327
+ """Call custom _getcommission overrides with backwards compatibility."""
328
+ accepts_role = getattr(self, "_getcommission_accepts_role", None)
329
+ if accepts_role is None:
330
+ try:
331
+ parameters = inspect.signature(self._getcommission).parameters
332
+ accepts_role = "role" in parameters or any(
333
+ param.kind == inspect.Parameter.VAR_KEYWORD for param in parameters.values()
334
+ )
335
+ except (TypeError, ValueError):
336
+ accepts_role = True
337
+ self._getcommission_accepts_role = accepts_role
338
+
339
+ if accepts_role:
340
+ return self._getcommission(size, price, pseudoexec=pseudoexec, role=role)
341
+ return self._getcommission(size, price, pseudoexec)
342
+
343
+ def getcommission(self, size, price, role=None):
344
+ """Calculates the commission of an operation at a given price."""
345
+ return self._call_getcommission(size, price, pseudoexec=True, role=role)
346
+
347
+ def confirmexec(self, size, price, role=None):
348
+ """Confirms execution and returns commission."""
349
+ return self._call_getcommission(size, price, pseudoexec=False, role=role)
350
+
351
+ def profitandloss(self, size, price, newprice):
352
+ """Return actual profit and loss a position has"""
353
+ # PERFORMANCE OPTIMIZATION: Use cached _mult
354
+ return size * (newprice - price) * self._mult
355
+
356
+ def cashadjust(self, size, price, newprice):
357
+ """Calculates cash adjustment for a given price difference"""
358
+ if not self._stocklike:
359
+ # PERFORMANCE OPTIMIZATION: Use cached _mult
360
+ return size * (newprice - price) * self._mult
361
+ return 0.0
362
+
363
+ def get_credit_interest(self, data, pos, dt):
364
+ """Calculates the credit due for short selling or product specific"""
365
+ size, price = pos.size, pos.price
366
+
367
+ if size > 0 and not self._interest_long:
368
+ return 0.0 # long positions not charged
369
+
370
+ dt0 = dt.date()
371
+ dt1 = pos.datetime.date()
372
+
373
+ if dt0 <= dt1:
374
+ return 0.0
375
+
376
+ return self._get_credit_interest(data, size, price, (dt0 - dt1).days, dt0, dt1)
377
+
378
+ def _get_credit_interest(self, data, size, price, days, dt0, dt1):
379
+ """
380
+ This method returns the cost in terms of credit interest charged by
381
+ the broker.
382
+
383
+ The formula: ``days * price * abs(size) * (interest / 365)``
384
+ """
385
+ return days * self._creditrate * abs(size) * price
386
+
387
+
388
+ class CommissionInfo(CommInfoBase):
389
+ """Base Class for the actual Commission Schemes.
390
+
391
+ CommInfoBase was created to keep support for the original, incomplete,
392
+ support provided by *backtrader*. New commission schemes derive from this
393
+ class which subclasses ``CommInfoBase``.
394
+
395
+ The default value of ``percabs`` is also changed to ``True``
396
+ """
397
+
398
+ percabs = BoolParam(default=True, doc="Whether percentage is absolute value")
399
+
400
+
401
+ class ComminfoDC(CommInfoBase):
402
+ """Digital currency commission class"""
403
+
404
+ stocklike = ParameterDescriptor(default=False, type_=bool)
405
+ commtype = ParameterDescriptor(default=CommInfoBase.COMM_PERC, type_=int)
406
+ percabs = ParameterDescriptor(default=True, type_=bool)
407
+ interest = ParameterDescriptor(default=3.0, type_=float)
408
+
409
+ def _getcommission(self, size, price, pseudoexec, role=None):
410
+ _ = pseudoexec
411
+ commission = self._resolve_commission_rate(role)
412
+ mult = self.get_param("mult")
413
+ return abs(size) * price * mult * commission
414
+
415
+ def get_margin(self, price):
416
+ """Calculate the margin required for digital currency trading.
417
+
418
+ Args:
419
+ price: Current price of the asset.
420
+
421
+ Returns:
422
+ float: Margin calculated as price * mult * margin parameter.
423
+ """
424
+ mult = self.get_param("mult")
425
+ margin = self.get_param("margin")
426
+ if margin is None:
427
+ margin = 1.0
428
+ return price * mult * margin
429
+
430
+ def get_credit_interest(self, data, pos, dt):
431
+ """Simplified implementation for digital currency interest calculation"""
432
+ size, price = pos.size, pos.price
433
+ dt0 = dt
434
+ dt1 = pos.datetime
435
+ gap_seconds = (dt0 - dt1).total_seconds()
436
+ days = gap_seconds / (24.0 * 60.0 * 60.0)
437
+
438
+ mult = self.get_param("mult")
439
+ position_value = size * price * mult
440
+
441
+ # Simplified interest calculation logic
442
+ total_value = self.broker.getvalue() if hasattr(self, "broker") else abs(position_value)
443
+ if size > 0 and position_value > total_value:
444
+ return days * self._creditrate * (position_value - total_value)
445
+ if size > 0 and position_value <= total_value:
446
+ return 0
447
+ if size < 0:
448
+ return days * self._creditrate * position_value
449
+ return 0
450
+
451
+
452
+ class ComminfoFuturesPercent(CommInfoBase):
453
+ """Futures percentage commission class"""
454
+
455
+ commission = ParameterDescriptor(default=0.0, type_=float)
456
+ mult = ParameterDescriptor(default=1.0, type_=float)
457
+ margin = ParameterDescriptor(default=None)
458
+ margin_amount = ParameterDescriptor(default=None)
459
+ stocklike = ParameterDescriptor(default=False, type_=bool)
460
+ commtype = ParameterDescriptor(default=CommInfoBase.COMM_PERC, type_=int)
461
+ percabs = ParameterDescriptor(default=True, type_=bool)
462
+
463
+ def _getcommission(self, size, price, pseudoexec, role=None):
464
+ _ = pseudoexec
465
+ commission = self._resolve_commission_rate(role)
466
+ mult = self.get_param("mult")
467
+ return abs(size) * price * mult * commission
468
+
469
+ def get_margin(self, price):
470
+ """Calculate the margin required for futures percentage commission.
471
+
472
+ Args:
473
+ price: Current price of the asset.
474
+
475
+ Returns:
476
+ float: Margin calculated as price * mult * margin parameter.
477
+ """
478
+ margin_amount = self.get_param("margin_amount")
479
+ if margin_amount is not None and margin_amount > 0:
480
+ return margin_amount
481
+ mult = self.get_param("mult")
482
+ margin = self.get_param("margin")
483
+ if margin is None:
484
+ margin = 1.0
485
+ return price * mult * margin
486
+
487
+
488
+ class ComminfoFuturesMixed(ComminfoFuturesPercent):
489
+ """Futures commission with both percentage and fixed per-lot components."""
490
+
491
+ commission_amount = ParameterDescriptor(default=0.0, type_=float)
492
+ open_commission_amount = ParameterDescriptor(default=None)
493
+ close_commission_amount = ParameterDescriptor(default=None)
494
+ close_today_commission_amount = ParameterDescriptor(default=None)
495
+ close_yesterday_commission_amount = ParameterDescriptor(default=None)
496
+
497
+ def _resolve_commission_amount(self, role=None):
498
+ role_text = str(role or "").strip().lower()
499
+ if role_text in {"open", "opened"}:
500
+ open_amount = self.get_param("open_commission_amount")
501
+ if open_amount is not None:
502
+ return open_amount
503
+
504
+ if role_text in {"close_today", "closetoday"}:
505
+ close_today_amount = self.get_param("close_today_commission_amount")
506
+ if close_today_amount is not None:
507
+ return close_today_amount
508
+ close_amount = self.get_param("close_commission_amount")
509
+ if close_amount is not None:
510
+ return close_amount
511
+
512
+ if role_text in {"close_yesterday", "closeyesterday"}:
513
+ close_yesterday_amount = self.get_param("close_yesterday_commission_amount")
514
+ if close_yesterday_amount is not None:
515
+ return close_yesterday_amount
516
+ close_amount = self.get_param("close_commission_amount")
517
+ if close_amount is not None:
518
+ return close_amount
519
+
520
+ if role_text in {"close", "closed"}:
521
+ close_amount = self.get_param("close_commission_amount")
522
+ if close_amount is not None:
523
+ return close_amount
524
+
525
+ return self.get_param("commission_amount")
526
+
527
+ def _getcommission(self, size, price, pseudoexec, role=None):
528
+ _ = pseudoexec
529
+ percent_commission = self._resolve_commission_rate(role)
530
+ fixed_commission = self._resolve_commission_amount(role)
531
+ mult = self.get_param("mult")
532
+ return abs(size) * price * mult * percent_commission + abs(size) * fixed_commission
533
+
534
+
535
+ class ComminfoFuturesInverse(ComminfoFuturesMixed):
536
+ """Inverse futures commission and PnL using fixed contract notional.
537
+
538
+ Crypto inverse contracts quote PnL and fees from a fixed contract value,
539
+ for example BTC-USD-SWAP with a 100 USD contract value. Their quote-value
540
+ PnL changes with the price ratio rather than a linear ``price * mult``
541
+ notional.
542
+ """
543
+
544
+ def _contract_notional(self, size):
545
+ return abs(size) * self.get_param("mult")
546
+
547
+ def _getcommission(self, size, price, pseudoexec, role=None):
548
+ _ = price, pseudoexec
549
+ percent_commission = self._resolve_commission_rate(role)
550
+ fixed_commission = self._resolve_commission_amount(role)
551
+ return self._contract_notional(size) * percent_commission + abs(size) * fixed_commission
552
+
553
+ def get_margin(self, price):
554
+ """Return per-contract margin from fixed contract notional."""
555
+ _ = price
556
+ margin_amount = self.get_param("margin_amount")
557
+ if margin_amount is not None and margin_amount > 0:
558
+ return margin_amount
559
+ margin = self.get_param("margin")
560
+ if margin is None:
561
+ margin = 1.0
562
+ return self.get_param("mult") * margin
563
+
564
+ def profitandloss(self, size, price, newprice):
565
+ """Return quote-equivalent inverse-contract PnL."""
566
+ if not price or not newprice:
567
+ return 0.0
568
+ return size * self.get_param("mult") * ((newprice / price) - 1.0)
569
+
570
+ def cashadjust(self, size, price, newprice):
571
+ """Mark inverse futures with the same quote-equivalent PnL rule."""
572
+ return self.profitandloss(size, price, newprice)
573
+
574
+
575
+ class ComminfoFuturesFixed(CommInfoBase):
576
+ """Futures fixed commission class"""
577
+
578
+ commission = ParameterDescriptor(default=0.0, type_=float)
579
+ mult = ParameterDescriptor(default=1.0, type_=float)
580
+ margin = ParameterDescriptor(default=None)
581
+ margin_amount = ParameterDescriptor(default=None)
582
+ stocklike = ParameterDescriptor(default=False, type_=bool)
583
+ commtype = ParameterDescriptor(default=CommInfoBase.COMM_FIXED, type_=int)
584
+ percabs = ParameterDescriptor(default=True, type_=bool)
585
+
586
+ def _getcommission(self, size, price, pseudoexec, role=None):
587
+ _ = pseudoexec
588
+ commission = self._resolve_commission_rate(role)
589
+ return abs(size) * commission
590
+
591
+ def get_margin(self, price):
592
+ """Calculate the margin required for futures fixed commission.
593
+
594
+ Args:
595
+ price: Current price of the asset.
596
+
597
+ Returns:
598
+ float: Margin calculated as price * mult * margin parameter.
599
+ """
600
+ margin_amount = self.get_param("margin_amount")
601
+ if margin_amount is not None and margin_amount > 0:
602
+ return margin_amount
603
+ mult = self.get_param("mult")
604
+ margin = self.get_param("margin")
605
+ if margin is None:
606
+ margin = 1.0
607
+ return price * mult * margin
608
+
609
+
610
+ class ComminfoFundingRate(CommInfoBase):
611
+ """Funding rate class"""
612
+
613
+ commission = ParameterDescriptor(default=0.0, type_=float)
614
+ mult = ParameterDescriptor(default=1.0, type_=float)
615
+ margin = ParameterDescriptor(default=None)
616
+ stocklike = ParameterDescriptor(default=False, type_=bool)
617
+ commtype = ParameterDescriptor(default=CommInfoBase.COMM_PERC, type_=int)
618
+ percabs = ParameterDescriptor(default=True, type_=bool)
619
+
620
+ def _getcommission(self, size, price, pseudoexec, role=None):
621
+ _ = pseudoexec
622
+ commission = self._resolve_commission_rate(role)
623
+ mult = self.get_param("mult")
624
+ total_commission = abs(size) * price * mult * commission
625
+ return total_commission
626
+
627
+ def get_margin(self, price):
628
+ """Calculate the margin required for funding rate trading.
629
+
630
+ Args:
631
+ price: Current price of the asset.
632
+
633
+ Returns:
634
+ float: Margin calculated as price * mult * margin parameter.
635
+ """
636
+ mult = self.get_param("mult")
637
+ margin = self.get_param("margin")
638
+ if margin is None:
639
+ margin = 1.0
640
+ return price * mult * margin
641
+
642
+ def get_credit_interest(self, data, pos, dt):
643
+ """Calculate funding rate for Binance futures"""
644
+ size, price = pos.size, pos.price
645
+
646
+ # Calculate current position value
647
+ try:
648
+ current_price = data.mark_price_open[1]
649
+ except (IndexError, AttributeError):
650
+ try:
651
+ current_price = data.mark_price_close[0]
652
+ except (IndexError, AttributeError):
653
+ current_price = price
654
+
655
+ mult = self.get_param("mult")
656
+ position_value = size * current_price * mult
657
+
658
+ # Get current funding rate
659
+ try:
660
+ funding_rate = data.current_funding_rate[1]
661
+ except (IndexError, AttributeError):
662
+ funding_rate = 0.0
663
+
664
+ total_funding_rate = funding_rate * position_value
665
+ return total_funding_rate