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.
- back_trader_python-1.4.0.dist-info/METADATA +1491 -0
- back_trader_python-1.4.0.dist-info/RECORD +465 -0
- back_trader_python-1.4.0.dist-info/WHEEL +5 -0
- back_trader_python-1.4.0.dist-info/licenses/LICENSE +674 -0
- back_trader_python-1.4.0.dist-info/top_level.txt +1 -0
- backtrader/__init__.py +148 -0
- backtrader/_cerebro/__init__.py +5 -0
- backtrader/_cerebro/channel.py +382 -0
- backtrader/_cerebro/execution.py +377 -0
- backtrader/_cerebro/lifecycle.py +143 -0
- backtrader/_cerebro/notifications.py +150 -0
- backtrader/_cerebro/presentation.py +230 -0
- backtrader/_cerebro/registry.py +593 -0
- backtrader/_cerebro/runnext.py +551 -0
- backtrader/_cerebro/runonce.py +142 -0
- backtrader/analyzer.py +594 -0
- backtrader/analyzers/__init__.py +50 -0
- backtrader/analyzers/annualreturn.py +226 -0
- backtrader/analyzers/calmar.py +165 -0
- backtrader/analyzers/drawdown.py +287 -0
- backtrader/analyzers/leverage.py +112 -0
- backtrader/analyzers/logreturnsrolling.py +190 -0
- backtrader/analyzers/periodstats.py +153 -0
- backtrader/analyzers/positions.py +119 -0
- backtrader/analyzers/pyfolio.py +470 -0
- backtrader/analyzers/returns.py +192 -0
- backtrader/analyzers/sharpe.py +307 -0
- backtrader/analyzers/sharpe_ratio_stats.py +534 -0
- backtrader/analyzers/sqn.py +112 -0
- backtrader/analyzers/timereturn.py +192 -0
- backtrader/analyzers/total_value.py +75 -0
- backtrader/analyzers/tradeanalyzer.py +278 -0
- backtrader/analyzers/transactions.py +141 -0
- backtrader/analyzers/vwr.py +245 -0
- backtrader/bokeh/__init__.py +155 -0
- backtrader/bokeh/analyzers/__init__.py +13 -0
- backtrader/bokeh/analyzers/plot.py +192 -0
- backtrader/bokeh/analyzers/recorder.py +181 -0
- backtrader/bokeh/app.py +1094 -0
- backtrader/bokeh/live/__init__.py +11 -0
- backtrader/bokeh/live/client.py +352 -0
- backtrader/bokeh/live/datahandler.py +346 -0
- backtrader/bokeh/plot_adapter.py +200 -0
- backtrader/bokeh/schemes/__init__.py +14 -0
- backtrader/bokeh/schemes/blackly.py +76 -0
- backtrader/bokeh/schemes/scheme.py +150 -0
- backtrader/bokeh/schemes/tradimo.py +82 -0
- backtrader/bokeh/tab.py +125 -0
- backtrader/bokeh/tabs/__init__.py +30 -0
- backtrader/bokeh/tabs/analyzer.py +120 -0
- backtrader/bokeh/tabs/config.py +154 -0
- backtrader/bokeh/tabs/live.py +109 -0
- backtrader/bokeh/tabs/log.py +185 -0
- backtrader/bokeh/tabs/metadata.py +182 -0
- backtrader/bokeh/tabs/performance.py +359 -0
- backtrader/bokeh/tabs/source.py +70 -0
- backtrader/bokeh/utils/__init__.py +8 -0
- backtrader/bokeh/utils/helpers.py +167 -0
- backtrader/bokeh/webapp.py +164 -0
- backtrader/broker.py +478 -0
- backtrader/brokers/__init__.py +36 -0
- backtrader/brokers/bbroker.py +2576 -0
- backtrader/brokers/btapibroker.py +8227 -0
- backtrader/brokers/hft/__init__.py +89 -0
- backtrader/brokers/hft/binance_bbo.py +625 -0
- backtrader/brokers/hft/binance_bbo_compare.py +1398 -0
- backtrader/brokers/hft/examples.py +1228 -0
- backtrader/brokers/hft/exchange.py +380 -0
- backtrader/brokers/hft/latency.py +309 -0
- backtrader/brokers/hft/matching_core.py +572 -0
- backtrader/brokers/hft/queue.py +238 -0
- backtrader/brokers/hft/recorder.py +88 -0
- backtrader/brokers/hft/state.py +138 -0
- backtrader/brokers/impact_models.py +118 -0
- backtrader/brokers/mixbroker.py +895 -0
- backtrader/brokers/tickbroker.py +1991 -0
- backtrader/btrun/__init__.py +12 -0
- backtrader/btrun/btrun.py +1218 -0
- backtrader/cerebro.py +828 -0
- backtrader/channel.py +682 -0
- backtrader/channels/__init__.py +23 -0
- backtrader/channels/bridge.py +186 -0
- backtrader/channels/funding.py +248 -0
- backtrader/channels/live_queue.py +216 -0
- backtrader/channels/live_validator.py +294 -0
- backtrader/channels/orderbook.py +257 -0
- backtrader/channels/tick.py +202 -0
- backtrader/comminfo.py +665 -0
- backtrader/commissions/__init__.py +106 -0
- backtrader/commissions/ctpoption.py +993 -0
- backtrader/configs/account_config_example.yaml +8 -0
- backtrader/dataseries.py +379 -0
- backtrader/errors.py +106 -0
- backtrader/events.py +980 -0
- backtrader/feed.py +1523 -0
- backtrader/feeds/__init__.py +75 -0
- backtrader/feeds/barrier.py +2006 -0
- backtrader/feeds/blaze.py +118 -0
- backtrader/feeds/btapifeed.py +1538 -0
- backtrader/feeds/btcsv.py +203 -0
- backtrader/feeds/chainer.py +114 -0
- backtrader/feeds/cryptohftdata.py +164 -0
- backtrader/feeds/csvgeneric.py +1205 -0
- backtrader/feeds/ctpcohort.py +1051 -0
- backtrader/feeds/influxfeed.py +158 -0
- backtrader/feeds/livefeed.py +71 -0
- backtrader/feeds/mixed_channel.py +108 -0
- backtrader/feeds/mt4csv.py +42 -0
- backtrader/feeds/pandafeed.py +381 -0
- backtrader/feeds/quandl.py +256 -0
- backtrader/feeds/rollover.py +229 -0
- backtrader/feeds/sierrachart.py +30 -0
- backtrader/feeds/vchart.py +162 -0
- backtrader/feeds/vchartcsv.py +84 -0
- backtrader/feeds/vchartfile.py +153 -0
- backtrader/feeds/yahoo.py +399 -0
- backtrader/fillers.py +148 -0
- backtrader/filters/__init__.py +34 -0
- backtrader/filters/bsplitter.py +127 -0
- backtrader/filters/calendardays.py +121 -0
- backtrader/filters/datafiller.py +192 -0
- backtrader/filters/datafilter.py +74 -0
- backtrader/filters/daysteps.py +96 -0
- backtrader/filters/heikinashi.py +63 -0
- backtrader/filters/renko.py +164 -0
- backtrader/filters/session.py +289 -0
- backtrader/flt.py +80 -0
- backtrader/functions.py +960 -0
- backtrader/indicator.py +449 -0
- backtrader/indicators/__init__.py +148 -0
- backtrader/indicators/accdecoscillator.py +110 -0
- backtrader/indicators/aroon.py +300 -0
- backtrader/indicators/atr.py +315 -0
- backtrader/indicators/awesomeoscillator.py +122 -0
- backtrader/indicators/basicops.py +834 -0
- backtrader/indicators/bollinger.py +223 -0
- backtrader/indicators/cci.py +89 -0
- backtrader/indicators/channels_ext.py +83 -0
- backtrader/indicators/contrib/__init__.py +228 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma.py +28 -0
- backtrader/indicators/contrib/absolutely_no_lag_lwma_color.py +44 -0
- backtrader/indicators/contrib/accumulation_distribution_line.py +92 -0
- backtrader/indicators/contrib/adx_cross_hull_style_indicator.py +249 -0
- backtrader/indicators/contrib/adxdmi.py +34 -0
- backtrader/indicators/contrib/ai_acceleration_deceleration_oscillator.py +34 -0
- backtrader/indicators/contrib/altr_trend_signal_v22.py +85 -0
- backtrader/indicators/contrib/anchored_momentum_line.py +115 -0
- backtrader/indicators/contrib/any_range_cld_tail_indicator.py +82 -0
- backtrader/indicators/contrib/aroon_horn_sign_indicator.py +96 -0
- backtrader/indicators/contrib/aroon_oscillator_sign_alert.py +50 -0
- backtrader/indicators/contrib/arrows_curves_indicator.py +112 -0
- backtrader/indicators/contrib/as_ctrend_indicator.py +143 -0
- backtrader/indicators/contrib/asimmetric_stoch_nr_indicator.py +187 -0
- backtrader/indicators/contrib/atr_normalize_histogram.py +118 -0
- backtrader/indicators/contrib/average_change_candle.py +165 -0
- backtrader/indicators/contrib/bb_squeeze_indicator.py +60 -0
- backtrader/indicators/contrib/bezier_st_dev_indicator.py +135 -0
- backtrader/indicators/contrib/binary_wave_indicator.py +233 -0
- backtrader/indicators/contrib/blau_c_momentum_indicator.py +123 -0
- backtrader/indicators/contrib/blau_cmi_indicator.py +141 -0
- backtrader/indicators/contrib/blau_csi.py +76 -0
- backtrader/indicators/contrib/blau_ergodic.py +53 -0
- backtrader/indicators/contrib/blau_t_stoch_i.py +72 -0
- backtrader/indicators/contrib/blau_ts_stochastic.py +85 -0
- backtrader/indicators/contrib/blau_tvi.py +55 -0
- backtrader/indicators/contrib/brain_trend2_indicator.py +128 -0
- backtrader/indicators/contrib/brain_trend_signal_proxy.py +47 -0
- backtrader/indicators/contrib/brake_parb_indicator.py +85 -0
- backtrader/indicators/contrib/breakout_bars_trend_v2.py +121 -0
- backtrader/indicators/contrib/bsi_indicator.py +87 -0
- backtrader/indicators/contrib/bulls_bears_eyes.py +67 -0
- backtrader/indicators/contrib/bulls_power.py +56 -0
- backtrader/indicators/contrib/bw_wise_man1_signal.py +102 -0
- backtrader/indicators/contrib/bykov_trend_indicator.py +85 -0
- backtrader/indicators/contrib/candle_stop_color.py +46 -0
- backtrader/indicators/contrib/candles_x_smoothed_indicator.py +69 -0
- backtrader/indicators/contrib/candlesticks_bw.py +45 -0
- backtrader/indicators/contrib/caudate_x_period_candle_color.py +56 -0
- backtrader/indicators/contrib/cci_histogram_indicator.py +53 -0
- backtrader/indicators/contrib/cci_woodies_indicator.py +80 -0
- backtrader/indicators/contrib/center_of_gravity_candle_indicator.py +83 -0
- backtrader/indicators/contrib/center_of_gravity_indicator.py +70 -0
- backtrader/indicators/contrib/cg_oscillator.py +40 -0
- backtrader/indicators/contrib/close_line_cci.py +38 -0
- backtrader/indicators/contrib/close_price_fractals.py +47 -0
- backtrader/indicators/contrib/color3rd_gen_xma_indicator.py +122 -0
- backtrader/indicators/contrib/color_bb_candles_indicator.py +108 -0
- backtrader/indicators/contrib/color_coppock_indicator.py +157 -0
- backtrader/indicators/contrib/color_hma.py +71 -0
- backtrader/indicators/contrib/color_j_variation_indicator.py +53 -0
- backtrader/indicators/contrib/color_metro_de_marker_indicator.py +78 -0
- backtrader/indicators/contrib/color_metro_stochastic_indicator.py +93 -0
- backtrader/indicators/contrib/color_metro_wpr_indicator.py +85 -0
- backtrader/indicators/contrib/color_schaff_de_marker_trend_cycle.py +92 -0
- backtrader/indicators/contrib/color_schaff_trend_cycle_indicator.py +203 -0
- backtrader/indicators/contrib/color_step_xccx_indicator.py +193 -0
- backtrader/indicators/contrib/color_x2_ma.py +49 -0
- backtrader/indicators/contrib/color_x_derivative.py +63 -0
- backtrader/indicators/contrib/color_zerolag_de_marker.py +84 -0
- backtrader/indicators/contrib/corrected_average_indicator.py +127 -0
- backtrader/indicators/contrib/darvas_boxes_system.py +73 -0
- backtrader/indicators/contrib/dema_range_channel_color.py +42 -0
- backtrader/indicators/contrib/derivative_indicator.py +95 -0
- backtrader/indicators/contrib/digital_ft01_indicator.py +112 -0
- backtrader/indicators/contrib/digital_macd.py +200 -0
- backtrader/indicators/contrib/donchian_channels_system.py +45 -0
- backtrader/indicators/contrib/dots_indicator.py +93 -0
- backtrader/indicators/contrib/ef_distance_indicator.py +82 -0
- backtrader/indicators/contrib/ema_rsi_va.py +80 -0
- backtrader/indicators/contrib/envelopes_jp_alonso.py +32 -0
- backtrader/indicators/contrib/f2a_ao_indicator.py +120 -0
- backtrader/indicators/contrib/fatl_filter.py +179 -0
- backtrader/indicators/contrib/fibo_candles_indicator.py +78 -0
- backtrader/indicators/contrib/fine_tuning_ma.py +100 -0
- backtrader/indicators/contrib/fisher_org_v1.py +102 -0
- backtrader/indicators/contrib/fisher_org_v1_sign.py +118 -0
- backtrader/indicators/contrib/force_index_ema.py +96 -0
- backtrader/indicators/contrib/force_index_ema_2.py +27 -0
- backtrader/indicators/contrib/forecast_oscilator.py +145 -0
- backtrader/indicators/contrib/fractal_amambk.py +81 -0
- backtrader/indicators/contrib/frama_series.py +84 -0
- backtrader/indicators/contrib/frasm_av2_indicator.py +104 -0
- backtrader/indicators/contrib/go_indicator.py +93 -0
- backtrader/indicators/contrib/hlr_indicator.py +95 -0
- backtrader/indicators/contrib/hma.py +50 -0
- backtrader/indicators/contrib/i4_drfv2.py +34 -0
- backtrader/indicators/contrib/i4_drfv3.py +38 -0
- backtrader/indicators/contrib/i_anch_mom_indicator.py +72 -0
- backtrader/indicators/contrib/i_de_marker_sign_indicator.py +64 -0
- backtrader/indicators/contrib/i_gap_indicator.py +45 -0
- backtrader/indicators/contrib/i_stoch_komposter_indicator.py +77 -0
- backtrader/indicators/contrib/i_trend_indicator.py +125 -0
- backtrader/indicators/contrib/iamma_indicator.py +39 -0
- backtrader/indicators/contrib/indexed_moving_average.py +33 -0
- backtrader/indicators/contrib/instantaneous_trend_filter_indicator.py +51 -0
- backtrader/indicators/contrib/inverse_reaction_indicator.py +41 -0
- backtrader/indicators/contrib/irsi_sign_indicator.py +95 -0
- backtrader/indicators/contrib/iwpr_sign_indicator.py +59 -0
- backtrader/indicators/contrib/j_brain_trend1_sig_indicator.py +233 -0
- backtrader/indicators/contrib/j_tpo_proxy.py +32 -0
- backtrader/indicators/contrib/jma_slope_indicator.py +73 -0
- backtrader/indicators/contrib/kalman_filter_indicator.py +119 -0
- backtrader/indicators/contrib/kalman_filter_line.py +127 -0
- backtrader/indicators/contrib/kama_indicator.py +150 -0
- backtrader/indicators/contrib/karacatica_indicator.py +99 -0
- backtrader/indicators/contrib/kdj_indicator.py +59 -0
- backtrader/indicators/contrib/kwan_ccc_indicator.py +195 -0
- backtrader/indicators/contrib/kwan_nrp_indicator.py +113 -0
- backtrader/indicators/contrib/kwan_rdp_indicator.py +192 -0
- backtrader/indicators/contrib/laguerre_adx_indicator.py +85 -0
- backtrader/indicators/contrib/laguerre_filter_indicator.py +66 -0
- backtrader/indicators/contrib/laguerre_plus_di_proxy.py +57 -0
- backtrader/indicators/contrib/laguerre_roc_indicator.py +81 -0
- backtrader/indicators/contrib/le_man_signal_indicator.py +63 -0
- backtrader/indicators/contrib/linear_reg_slope_v2_indicator.py +136 -0
- backtrader/indicators/contrib/loco_indicator.py +88 -0
- backtrader/indicators/contrib/lrma_indicator.py +185 -0
- backtrader/indicators/contrib/lsma_angle_indicator.py +106 -0
- backtrader/indicators/contrib/ma_rounding_channel_indicator.py +149 -0
- backtrader/indicators/contrib/macd2_indicator.py +61 -0
- backtrader/indicators/contrib/macd_candle_indicator.py +80 -0
- backtrader/indicators/contrib/malr_indicator.py +77 -0
- backtrader/indicators/contrib/momentum_candle_sign_indicator.py +51 -0
- backtrader/indicators/contrib/moving_average_fn_indicator.py +139 -0
- backtrader/indicators/contrib/mt5_stochastic_close_close.py +57 -0
- backtrader/indicators/contrib/muv_nor_diff_cloud_indicator.py +107 -0
- backtrader/indicators/contrib/non_lag_dot_indicator.py +124 -0
- backtrader/indicators/contrib/nrtr_extr_indicator.py +95 -0
- backtrader/indicators/contrib/nrtr_indicator.py +95 -0
- backtrader/indicators/contrib/p_channel_system.py +40 -0
- backtrader/indicators/contrib/percent_envelope.py +37 -0
- backtrader/indicators/contrib/percentage_crossover_channel.py +47 -0
- backtrader/indicators/contrib/pivot_zig_zag_proxy.py +47 -0
- backtrader/indicators/contrib/price_channel_stop_indicator.py +104 -0
- backtrader/indicators/contrib/price_extreme_channel.py +35 -0
- backtrader/indicators/contrib/qqe_cloud_indicator.py +129 -0
- backtrader/indicators/contrib/ravi_indicator.py +40 -0
- backtrader/indicators/contrib/raw_close_close_stochastic.py +74 -0
- backtrader/indicators/contrib/rd_trend_trigger_indicator.py +51 -0
- backtrader/indicators/contrib/renko_level.py +85 -0
- backtrader/indicators/contrib/renko_line_break.py +91 -0
- backtrader/indicators/contrib/rftl_indicator.py +41 -0
- backtrader/indicators/contrib/rkd_indicator.py +53 -0
- backtrader/indicators/contrib/roc2_vg_indicator.py +68 -0
- backtrader/indicators/contrib/rsi_histogram_indicator.py +43 -0
- backtrader/indicators/contrib/rsi_slowdown.py +57 -0
- backtrader/indicators/contrib/rsioma_v2.py +41 -0
- backtrader/indicators/contrib/rvi_histogram_indicator.py +107 -0
- backtrader/indicators/contrib/safe_adx.py +89 -0
- backtrader/indicators/contrib/shared_strategy_indicators.py +1651 -0
- backtrader/indicators/contrib/sidus_indicator.py +105 -0
- backtrader/indicators/contrib/silver_trend_indicator.py +79 -0
- backtrader/indicators/contrib/sliding_range_color.py +56 -0
- backtrader/indicators/contrib/slow_stoch.py +42 -0
- backtrader/indicators/contrib/smoothed_adx_indicator.py +86 -0
- backtrader/indicators/contrib/smoothed_rsi.py +31 -0
- backtrader/indicators/contrib/spearman_rank_correlation_histogram.py +60 -0
- backtrader/indicators/contrib/stalin_indicator.py +152 -0
- backtrader/indicators/contrib/starter_laguerre_filter.py +62 -0
- backtrader/indicators/contrib/step_manrtr_indicator.py +137 -0
- backtrader/indicators/contrib/stochastic_histogram_indicator.py +143 -0
- backtrader/indicators/contrib/t3_alarm_indicator.py +125 -0
- backtrader/indicators/contrib/t3_average.py +76 -0
- backtrader/indicators/contrib/t3_indicator.py +40 -0
- backtrader/indicators/contrib/the20s_v020_signal.py +93 -0
- backtrader/indicators/contrib/three_candles_indicator.py +70 -0
- backtrader/indicators/contrib/three_line_break_indicator.py +64 -0
- backtrader/indicators/contrib/time_line.py +57 -0
- backtrader/indicators/contrib/trading_channel_index_proxy.py +48 -0
- backtrader/indicators/contrib/trend_arrows_indicator.py +109 -0
- backtrader/indicators/contrib/trend_continuation_indicator.py +127 -0
- backtrader/indicators/contrib/trend_intensity_index_proxy.py +51 -0
- backtrader/indicators/contrib/trend_manager_indicator.py +39 -0
- backtrader/indicators/contrib/tri_x_candle_indicator.py +51 -0
- backtrader/indicators/contrib/trigger_line.py +66 -0
- backtrader/indicators/contrib/triple_ema_rate.py +34 -0
- backtrader/indicators/contrib/trvi_indicator.py +194 -0
- backtrader/indicators/contrib/two_pb_ideal_xosma_indicator.py +127 -0
- backtrader/indicators/contrib/ultra_absolutely_no_lag_lwma_color.py +92 -0
- backtrader/indicators/contrib/ultra_wpr_indicator.py +173 -0
- backtrader/indicators/contrib/up_down_candle_strength.py +68 -0
- backtrader/indicators/contrib/vinin_i_trend_indicator.py +139 -0
- backtrader/indicators/contrib/volume_weighted_ma_indicator.py +78 -0
- backtrader/indicators/contrib/volume_weighted_ma_st_dev_indicator.py +111 -0
- backtrader/indicators/contrib/vwap_close_indicator.py +65 -0
- backtrader/indicators/contrib/vwma_candle.py +57 -0
- backtrader/indicators/contrib/vwma_digit_system.py +70 -0
- backtrader/indicators/contrib/wami.py +43 -0
- backtrader/indicators/contrib/wprsi_signal_indicator.py +105 -0
- backtrader/indicators/contrib/x_de_marker_histogram_vol_direct_indicator.py +145 -0
- backtrader/indicators/contrib/x_fisher_indicator.py +64 -0
- backtrader/indicators/contrib/xcci_histogram_vol_direct_indicator.py +56 -0
- backtrader/indicators/contrib/xcci_histogram_vol_indicator.py +85 -0
- backtrader/indicators/contrib/xma_ichimoku.py +163 -0
- backtrader/indicators/contrib/xma_ishimoku_channel_indicator.py +65 -0
- backtrader/indicators/contrib/xma_ishimoku_line.py +68 -0
- backtrader/indicators/contrib/xma_range_bands_indicator.py +107 -0
- backtrader/indicators/contrib/xmacd_indicator.py +70 -0
- backtrader/indicators/contrib/xrsi_de_marker_histogram.py +67 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_direct_indicator.py +52 -0
- backtrader/indicators/contrib/xrsi_histogram_vol_indicator.py +81 -0
- backtrader/indicators/contrib/xrvi_indicator.py +130 -0
- backtrader/indicators/contrib/zero_lag_macd.py +36 -0
- backtrader/indicators/contrib/zig_zag_recent_pivot_signal.py +90 -0
- backtrader/indicators/contrib/zpf_indicator.py +115 -0
- backtrader/indicators/crossover.py +337 -0
- backtrader/indicators/dema.py +175 -0
- backtrader/indicators/demarker.py +270 -0
- backtrader/indicators/deviation.py +284 -0
- backtrader/indicators/directionalmove.py +1071 -0
- backtrader/indicators/dma.py +112 -0
- backtrader/indicators/dpo.py +96 -0
- backtrader/indicators/dv2.py +56 -0
- backtrader/indicators/ema.py +145 -0
- backtrader/indicators/envelope.py +475 -0
- backtrader/indicators/hadelta.py +198 -0
- backtrader/indicators/heikinashi.py +153 -0
- backtrader/indicators/hma.py +153 -0
- backtrader/indicators/hurst.py +151 -0
- backtrader/indicators/ichimoku.py +267 -0
- backtrader/indicators/kama.py +181 -0
- backtrader/indicators/kst.py +159 -0
- backtrader/indicators/lrsi.py +125 -0
- backtrader/indicators/mabase.py +147 -0
- backtrader/indicators/macd.py +322 -0
- backtrader/indicators/momentum.py +267 -0
- backtrader/indicators/moneyflow.py +237 -0
- backtrader/indicators/mt5atr.py +124 -0
- backtrader/indicators/myind.py +179 -0
- backtrader/indicators/obv.py +94 -0
- backtrader/indicators/ols.py +265 -0
- backtrader/indicators/oscillator.py +161 -0
- backtrader/indicators/percentchange.py +83 -0
- backtrader/indicators/percentrank.py +46 -0
- backtrader/indicators/pivotpoint.py +469 -0
- backtrader/indicators/prettygoodoscillator.py +113 -0
- backtrader/indicators/priceops_ext.py +123 -0
- backtrader/indicators/priceoscillator.py +262 -0
- backtrader/indicators/psar.py +212 -0
- backtrader/indicators/rmi.py +69 -0
- backtrader/indicators/rsi.py +440 -0
- backtrader/indicators/sma.py +141 -0
- backtrader/indicators/smma.py +116 -0
- backtrader/indicators/spread.py +54 -0
- backtrader/indicators/stochastic.py +263 -0
- backtrader/indicators/supertrend.py +436 -0
- backtrader/indicators/trend_ext.py +105 -0
- backtrader/indicators/trix.py +202 -0
- backtrader/indicators/tsi.py +155 -0
- backtrader/indicators/ultimateoscillator.py +158 -0
- backtrader/indicators/vortex.py +62 -0
- backtrader/indicators/williams.py +194 -0
- backtrader/indicators/wma.py +103 -0
- backtrader/indicators/zlema.py +135 -0
- backtrader/indicators/zlind.py +104 -0
- backtrader/linebuffer.py +3155 -0
- backtrader/lineiterator.py +2911 -0
- backtrader/lineroot.py +1106 -0
- backtrader/lineseries.py +2559 -0
- backtrader/live_trading/__init__.py +31 -0
- backtrader/live_trading/interface.py +404 -0
- backtrader/mathsupport.py +94 -0
- backtrader/metabase.py +1804 -0
- backtrader/mixins/__init__.py +21 -0
- backtrader/mixins/singleton.py +118 -0
- backtrader/observer.py +106 -0
- backtrader/observers/__init__.py +45 -0
- backtrader/observers/benchmark.py +126 -0
- backtrader/observers/broker.py +184 -0
- backtrader/observers/buysell.py +144 -0
- backtrader/observers/drawdown.py +161 -0
- backtrader/observers/logreturns.py +113 -0
- backtrader/observers/timereturn.py +86 -0
- backtrader/observers/trade_logger.py +2972 -0
- backtrader/observers/tradelogger.py +6 -0
- backtrader/observers/trades.py +258 -0
- backtrader/order.py +1114 -0
- backtrader/parameters.py +2345 -0
- backtrader/plot/__init__.py +54 -0
- backtrader/plot/finance.py +1022 -0
- backtrader/plot/formatters.py +200 -0
- backtrader/plot/locator.py +353 -0
- backtrader/plot/multicursor.py +495 -0
- backtrader/plot/plot.py +2500 -0
- backtrader/plot/plot_plotly.py +1351 -0
- backtrader/plot/scheme.py +253 -0
- backtrader/plot/utils.py +104 -0
- backtrader/position.py +290 -0
- backtrader/position_modes.py +132 -0
- backtrader/profiles.py +254 -0
- backtrader/reports/__init__.py +39 -0
- backtrader/reports/charts.py +371 -0
- backtrader/reports/performance.py +620 -0
- backtrader/reports/reporter.py +660 -0
- backtrader/resamplerfilter.py +1001 -0
- backtrader/signal.py +118 -0
- backtrader/signals/__init__.py +17 -0
- backtrader/sizer.py +114 -0
- backtrader/sizers/__init__.py +26 -0
- backtrader/sizers/fixedsize.py +161 -0
- backtrader/sizers/percents_sizer.py +119 -0
- backtrader/store.py +221 -0
- backtrader/stores/__init__.py +33 -0
- backtrader/stores/btapistore.py +15506 -0
- backtrader/stores/livestore.py +137 -0
- backtrader/stores/vchartfile.py +96 -0
- backtrader/strategy.py +3655 -0
- backtrader/talib.py +280 -0
- backtrader/test_helpers.py +96 -0
- backtrader/timer.py +358 -0
- backtrader/trade.py +442 -0
- backtrader/tradingcal.py +361 -0
- backtrader/utils/__init__.py +68 -0
- backtrader/utils/autodict.py +251 -0
- backtrader/utils/date.py +71 -0
- backtrader/utils/dateintern.py +509 -0
- backtrader/utils/flushfile.py +94 -0
- backtrader/utils/fractal.py +101 -0
- backtrader/utils/get_metrics.py +101 -0
- backtrader/utils/load_data.py +209 -0
- backtrader/utils/log_message.py +998 -0
- backtrader/utils/ordereddefaultdict.py +75 -0
- backtrader/utils/py3.py +296 -0
- backtrader/version.py +21 -0
- backtrader/writer.py +372 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Fractal Indicator Module - Fractal pattern detection.
|
|
3
|
+
|
|
4
|
+
This module provides the Fractal indicator for identifying fractal
|
|
5
|
+
patterns in price data. Fractals are reversal patterns that indicate
|
|
6
|
+
potential trend changes.
|
|
7
|
+
|
|
8
|
+
Classes:
|
|
9
|
+
Fractal: Identifies bullish and bearish fractal patterns.
|
|
10
|
+
|
|
11
|
+
References:
|
|
12
|
+
http://www.investopedia.com/articles/trading/06/fractals.asp
|
|
13
|
+
|
|
14
|
+
Example:
|
|
15
|
+
>>> from backtrader.utils.fractal import Fractal
|
|
16
|
+
>>> class MyStrategy(bt.Strategy):
|
|
17
|
+
... def __init__(self):
|
|
18
|
+
... self.fractal = Fractal(self.data)
|
|
19
|
+
... def next(self):
|
|
20
|
+
... if self.fractal.fractal_bullish[0] > 0:
|
|
21
|
+
... self.buy()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from ..indicators import PeriodN
|
|
25
|
+
|
|
26
|
+
__all__ = ["Fractal"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Fractal(PeriodN):
|
|
30
|
+
"""Fractal pattern indicator.
|
|
31
|
+
|
|
32
|
+
Identifies bullish and bearish fractal patterns which indicate
|
|
33
|
+
potential reversal points in price trends.
|
|
34
|
+
|
|
35
|
+
A bearish fractal occurs when there's a pattern with the highest
|
|
36
|
+
high in the middle and two lower highs on each side.
|
|
37
|
+
|
|
38
|
+
A bullish fractal occurs when there's a pattern with the lowest
|
|
39
|
+
low in the middle and two higher lows on each side.
|
|
40
|
+
|
|
41
|
+
Params:
|
|
42
|
+
period: Number of bars to check (default: 5).
|
|
43
|
+
bardist: Distance to max/min in percentage (default: 0.015).
|
|
44
|
+
shift_to_potential_fractal: Index of potential fractal (default: 2).
|
|
45
|
+
|
|
46
|
+
Lines:
|
|
47
|
+
fractal_bearish: Bearish fractal levels.
|
|
48
|
+
fractal_bullish: Bullish fractal levels.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
lines = ("fractal_bearish", "fractal_bullish")
|
|
52
|
+
|
|
53
|
+
plotinfo = {"subplot": False, "plotlinelabels": False, "plot": True}
|
|
54
|
+
|
|
55
|
+
plotlines = {
|
|
56
|
+
"fractal_bearish": {
|
|
57
|
+
"marker": "^",
|
|
58
|
+
"markersize": 4.0,
|
|
59
|
+
"color": "lightblue",
|
|
60
|
+
"fillstyle": "full",
|
|
61
|
+
"ls": "",
|
|
62
|
+
},
|
|
63
|
+
"fractal_bullish": {
|
|
64
|
+
"marker": "v",
|
|
65
|
+
"markersize": 4.0,
|
|
66
|
+
"color": "lightblue",
|
|
67
|
+
"fillstyle": "full",
|
|
68
|
+
"ls": "",
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
params = (
|
|
72
|
+
("period", 5),
|
|
73
|
+
("bardist", 0.015), # distance to max/min in absolute perc
|
|
74
|
+
("shift_to_potential_fractal", 2),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def next(self):
|
|
78
|
+
"""Calculate fractal patterns for the current bar.
|
|
79
|
+
|
|
80
|
+
Identifies bearish fractals (highest high in middle with two lower
|
|
81
|
+
highs on sides) and bullish fractals (lowest low in middle with two
|
|
82
|
+
higher lows on sides).
|
|
83
|
+
"""
|
|
84
|
+
# A bearish turning point occurs when there is a pattern with the
|
|
85
|
+
# highest high in the middle and two lower highs on each side. [Ref 1]
|
|
86
|
+
|
|
87
|
+
last_five_highs = self.data.high.get(size=self.p.period)
|
|
88
|
+
max_val = max(last_five_highs)
|
|
89
|
+
max_idx = last_five_highs.index(max_val)
|
|
90
|
+
|
|
91
|
+
if max_idx == self.p.shift_to_potential_fractal:
|
|
92
|
+
self.lines.fractal_bearish[-2] = max_val * (1 + self.p.bardist)
|
|
93
|
+
|
|
94
|
+
# A bullish turning point occurs when there is a pattern with the
|
|
95
|
+
# lowest low in the middle and two higher lowers on each side. [Ref 1]
|
|
96
|
+
last_five_lows = self.data.low.get(size=self.p.period)
|
|
97
|
+
min_val = min(last_five_lows)
|
|
98
|
+
min_idx = last_five_lows.index(min_val)
|
|
99
|
+
|
|
100
|
+
if min_idx == self.p.shift_to_potential_fractal:
|
|
101
|
+
self.l.fractal_bullish[-2] = min_val * (1 - self.p.bardist)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# pyright: reportAny=false, reportExplicitAny=false
|
|
2
|
+
"""Standard-metric extraction helpers for Cerebro backtests.
|
|
3
|
+
|
|
4
|
+
Exposes :data:`STANDARD_METRIC_FIELDS` (the canonical key list),
|
|
5
|
+
:func:`get_backtest_metrics` (which collects the raw values from a
|
|
6
|
+
completed run) and :func:`write_metrics` (which serialises the
|
|
7
|
+
result as JSON). An alias
|
|
8
|
+
:data:`extract_backtest_metrics` is also provided for callers that
|
|
9
|
+
prefer the longer name.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import absolute_import, annotations, division, print_function, unicode_literals
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
STANDARD_METRIC_FIELDS = (
|
|
19
|
+
"bar_num",
|
|
20
|
+
"buy_count",
|
|
21
|
+
"sell_count",
|
|
22
|
+
"win_count",
|
|
23
|
+
"loss_count",
|
|
24
|
+
"trade_num",
|
|
25
|
+
"final_value",
|
|
26
|
+
"sharpe_ratio",
|
|
27
|
+
"annual_return",
|
|
28
|
+
"max_drawdown",
|
|
29
|
+
"return_rate",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_backtest_metrics(cerebro: Any, config: dict[str, Any]) -> dict[str, Any]:
|
|
34
|
+
"""Extract raw standard metrics from a completed Cerebro backtest.
|
|
35
|
+
|
|
36
|
+
Pulls the strategy instance from ``cerebro.runstrats[0][0]`` and
|
|
37
|
+
reads the ``sharpe``, ``returns``, ``drawdown`` and ``trades``
|
|
38
|
+
analyzers plus the broker's final portfolio value. The returned
|
|
39
|
+
dict contains exactly the keys listed in
|
|
40
|
+
:data:`STANDARD_METRIC_FIELDS` and is the raw payload consumed by
|
|
41
|
+
downstream normalisation or reporting layers.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
cerebro: A Cerebro instance whose first run strategy has
|
|
45
|
+
already produced the four expected analyzers
|
|
46
|
+
(``sharpe``, ``returns``, ``drawdown``, ``trades``).
|
|
47
|
+
config: Configuration dict. Only ``config["backtest"]
|
|
48
|
+
["initial_cash"]`` is read, used as the baseline for
|
|
49
|
+
``return_rate``.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
dict: Mapping of standard metric name -> value (floats for
|
|
53
|
+
percentages and counts, broker value for ``final_value``).
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
strat = cerebro.runstrats[0][0]
|
|
57
|
+
initial_cash = float(config["backtest"]["initial_cash"])
|
|
58
|
+
final_value = float(cerebro.broker.getvalue())
|
|
59
|
+
|
|
60
|
+
sharpe = strat.analyzers.sharpe.get_analysis()
|
|
61
|
+
returns = strat.analyzers.returns.get_analysis()
|
|
62
|
+
drawdown = strat.analyzers.drawdown.get_analysis()
|
|
63
|
+
trades = strat.analyzers.trades.get_analysis()
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
"bar_num": strat.bar_num,
|
|
67
|
+
"buy_count": trades.get("long", {}).get("total"),
|
|
68
|
+
"sell_count": trades.get("short", {}).get("total"),
|
|
69
|
+
"win_count": trades.get("won", {}).get("total"),
|
|
70
|
+
"loss_count": trades.get("lost", {}).get("total"),
|
|
71
|
+
"trade_num": trades.get("total", {}).get("total"),
|
|
72
|
+
"final_value": final_value,
|
|
73
|
+
"sharpe_ratio": sharpe["sharperatio"],
|
|
74
|
+
"annual_return": returns["rnorm"],
|
|
75
|
+
"max_drawdown": drawdown["max"]["drawdown"],
|
|
76
|
+
"return_rate": (final_value / initial_cash - 1.0) * 100.0,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def write_metrics(metrics: dict[str, Any], base_dir: str, filename: str = "py_result.json") -> Path:
|
|
81
|
+
"""Serialize ``metrics`` as JSON inside ``base_dir``.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
metrics: Mapping of metric name -> JSON-serialisable value.
|
|
85
|
+
Typically the output of :func:`get_backtest_metrics`.
|
|
86
|
+
base_dir: Directory where the JSON file will be written.
|
|
87
|
+
Created implicitly by :class:`pathlib.Path` (the
|
|
88
|
+
underlying ``open`` will fail if it does not exist).
|
|
89
|
+
filename: JSON file name. Defaults to ``"py_result.json"``.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Path: The absolute (or relative) path to the written file.
|
|
93
|
+
"""
|
|
94
|
+
output_path = Path(base_dir) / filename
|
|
95
|
+
with output_path.open("w", encoding="utf-8") as handle:
|
|
96
|
+
json.dump(metrics, handle, ensure_ascii=False, indent=2)
|
|
97
|
+
return output_path
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
extract_backtest_metrics = get_backtest_metrics
|
|
101
|
+
extract_metrics = get_backtest_metrics
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Shared data-loading helpers for functional tests and examples."""
|
|
4
|
+
|
|
5
|
+
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
6
|
+
|
|
7
|
+
from functools import lru_cache
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
_BASE_COLUMNS = ["open", "high", "low", "close", "volume", "openinterest"]
|
|
11
|
+
_AUGMENT_COLUMNS = ("tick_volume", "real_volume", "spread")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resolve_repo_paths(node, repo=None, placeholder="{repo}"):
|
|
15
|
+
"""Resolve repo placeholders inside nested config data."""
|
|
16
|
+
if repo is None:
|
|
17
|
+
return node
|
|
18
|
+
|
|
19
|
+
repo_text = str(repo)
|
|
20
|
+
|
|
21
|
+
if isinstance(node, dict):
|
|
22
|
+
return {
|
|
23
|
+
key: resolve_repo_paths(value, repo=repo_text, placeholder=placeholder)
|
|
24
|
+
for key, value in node.items()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if isinstance(node, list):
|
|
28
|
+
return [
|
|
29
|
+
resolve_repo_paths(value, repo=repo_text, placeholder=placeholder) for value in node
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
if isinstance(node, tuple):
|
|
33
|
+
return tuple(
|
|
34
|
+
resolve_repo_paths(value, repo=repo_text, placeholder=placeholder) for value in node
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if isinstance(node, str):
|
|
38
|
+
return node.replace(placeholder, repo_text)
|
|
39
|
+
|
|
40
|
+
return node
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def load_config(config, repo=None, placeholder="{repo}"):
|
|
44
|
+
"""Return a deep-copied inline config with repo placeholders resolved."""
|
|
45
|
+
import copy
|
|
46
|
+
|
|
47
|
+
return resolve_repo_paths(
|
|
48
|
+
copy.deepcopy(config),
|
|
49
|
+
repo=repo,
|
|
50
|
+
placeholder=placeholder,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _first_non_empty_line(filepath):
|
|
55
|
+
with open(filepath, "r", encoding="utf-8", errors="ignore") as handle:
|
|
56
|
+
for line in handle:
|
|
57
|
+
line = line.strip()
|
|
58
|
+
if line:
|
|
59
|
+
return line.strip('"')
|
|
60
|
+
|
|
61
|
+
raise ValueError("MT5 CSV file is empty: %s" % filepath)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _read_cleaned_mt5_csv(filepath, sep):
|
|
65
|
+
import io
|
|
66
|
+
|
|
67
|
+
import pandas as pd
|
|
68
|
+
|
|
69
|
+
with open(filepath, "r", encoding="utf-8", errors="ignore") as handle:
|
|
70
|
+
lines = [line.strip().strip('"') for line in handle if line.strip()]
|
|
71
|
+
|
|
72
|
+
if not lines:
|
|
73
|
+
raise ValueError("MT5 CSV file is empty: %s" % filepath)
|
|
74
|
+
|
|
75
|
+
return pd.read_csv(io.StringIO("\n".join(lines)), sep=sep)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _needs_cleaned_read(df):
|
|
79
|
+
if "time" in df.columns:
|
|
80
|
+
return False
|
|
81
|
+
return "<DATE>" not in df.columns or "<TIME>" not in df.columns
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _read_mt5_csv(filepath, bar_shift_minutes=0):
|
|
85
|
+
"""Read MT5 data and keep standard plus known raw columns."""
|
|
86
|
+
return _read_mt5_csv_cached(*_mt5_cache_args(filepath, bar_shift_minutes))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _mt5_cache_args(filepath, bar_shift_minutes):
|
|
90
|
+
path = Path(filepath)
|
|
91
|
+
stat = path.stat()
|
|
92
|
+
return (
|
|
93
|
+
str(path),
|
|
94
|
+
stat.st_mtime_ns,
|
|
95
|
+
stat.st_size,
|
|
96
|
+
int(bar_shift_minutes or 0),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _datetime_cache_key(value):
|
|
101
|
+
if value is None:
|
|
102
|
+
return None
|
|
103
|
+
if hasattr(value, "isoformat"):
|
|
104
|
+
return value.isoformat()
|
|
105
|
+
return str(value)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@lru_cache(maxsize=64)
|
|
109
|
+
def _read_mt5_csv_cached(filepath, mtime_ns, size, bar_shift_minutes):
|
|
110
|
+
"""Read MT5 data once per file version and timestamp shift."""
|
|
111
|
+
import pandas as pd
|
|
112
|
+
|
|
113
|
+
sep = "\t" if "\t" in _first_non_empty_line(filepath) else ","
|
|
114
|
+
df = pd.read_csv(filepath, sep=sep, encoding="utf-8", encoding_errors="ignore")
|
|
115
|
+
if _needs_cleaned_read(df):
|
|
116
|
+
df = _read_cleaned_mt5_csv(filepath, sep)
|
|
117
|
+
|
|
118
|
+
if "time" in df.columns:
|
|
119
|
+
parsed = pd.to_datetime(df["time"], errors="coerce", utc=True).dt.tz_convert(None)
|
|
120
|
+
else:
|
|
121
|
+
dt_text = df["<DATE>"].astype(str) + " " + df["<TIME>"].astype(str)
|
|
122
|
+
parsed = pd.to_datetime(dt_text, format="%Y.%m.%d %H:%M", errors="coerce")
|
|
123
|
+
if parsed.isna().any():
|
|
124
|
+
parsed = pd.to_datetime(
|
|
125
|
+
dt_text,
|
|
126
|
+
format="%Y.%m.%d %H:%M:%S",
|
|
127
|
+
errors="coerce",
|
|
128
|
+
)
|
|
129
|
+
if parsed.isna().any():
|
|
130
|
+
parsed = pd.to_datetime(dt_text, errors="coerce")
|
|
131
|
+
|
|
132
|
+
if bar_shift_minutes:
|
|
133
|
+
parsed = parsed + pd.to_timedelta(int(bar_shift_minutes), unit="m")
|
|
134
|
+
|
|
135
|
+
df["datetime"] = parsed
|
|
136
|
+
df = df.rename(
|
|
137
|
+
columns={
|
|
138
|
+
"<OPEN>": "open",
|
|
139
|
+
"<HIGH>": "high",
|
|
140
|
+
"<LOW>": "low",
|
|
141
|
+
"<CLOSE>": "close",
|
|
142
|
+
"<TICKVOL>": "tick_volume",
|
|
143
|
+
"<VOL>": "real_volume",
|
|
144
|
+
"<SPREAD>": "spread",
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if "volume" not in df.columns:
|
|
149
|
+
if "tick_volume" in df.columns:
|
|
150
|
+
df["volume"] = df["tick_volume"]
|
|
151
|
+
elif "real_volume" in df.columns:
|
|
152
|
+
df["volume"] = df["real_volume"]
|
|
153
|
+
else:
|
|
154
|
+
df["volume"] = 0
|
|
155
|
+
if "openinterest" not in df.columns:
|
|
156
|
+
df["openinterest"] = df["real_volume"] if "real_volume" in df.columns else 0
|
|
157
|
+
|
|
158
|
+
columns = ["datetime"] + _BASE_COLUMNS
|
|
159
|
+
columns.extend(column for column in _AUGMENT_COLUMNS if column in df.columns)
|
|
160
|
+
|
|
161
|
+
return df[columns].dropna(subset=["datetime"]).set_index("datetime").sort_index()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@lru_cache(maxsize=64)
|
|
165
|
+
def _slice_mt5_csv_cached(filepath, mtime_ns, size, bar_shift_minutes, fromdate, todate):
|
|
166
|
+
"""Return a cached OHLCV slice for repeated functional-test date windows."""
|
|
167
|
+
import pandas as pd
|
|
168
|
+
|
|
169
|
+
df = _read_mt5_csv_cached(filepath, mtime_ns, size, bar_shift_minutes)
|
|
170
|
+
start = 0
|
|
171
|
+
stop = len(df)
|
|
172
|
+
if fromdate is not None:
|
|
173
|
+
start = df.index.searchsorted(pd.Timestamp(fromdate), side="left")
|
|
174
|
+
if todate is not None:
|
|
175
|
+
stop = df.index.searchsorted(pd.Timestamp(todate), side="right")
|
|
176
|
+
return df.iloc[start:stop].loc[:, _BASE_COLUMNS]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def load_mt5_csv(filepath, fromdate=None, todate=None, bar_shift_minutes=0):
|
|
180
|
+
"""Load MT5 CSV data into a normalized OHLCV DataFrame."""
|
|
181
|
+
df = _slice_mt5_csv_cached(
|
|
182
|
+
*_mt5_cache_args(filepath, bar_shift_minutes),
|
|
183
|
+
_datetime_cache_key(fromdate),
|
|
184
|
+
_datetime_cache_key(todate),
|
|
185
|
+
)
|
|
186
|
+
return df.copy()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def augment_mt5_csv_columns(frame, filepath, columns, bar_shift_minutes=0):
|
|
190
|
+
"""Add selected raw MT5 columns to a DataFrame returned by ``load_mt5_csv``."""
|
|
191
|
+
columns = tuple(columns)
|
|
192
|
+
if not columns:
|
|
193
|
+
return frame.copy()
|
|
194
|
+
|
|
195
|
+
unsupported = [column for column in columns if column not in _AUGMENT_COLUMNS]
|
|
196
|
+
if unsupported:
|
|
197
|
+
raise ValueError("Unsupported MT5 augment column: %s" % unsupported[0])
|
|
198
|
+
|
|
199
|
+
raw = _read_mt5_csv(filepath, bar_shift_minutes=bar_shift_minutes)
|
|
200
|
+
result = frame.copy()
|
|
201
|
+
available = [column for column in columns if column in raw.columns]
|
|
202
|
+
if available:
|
|
203
|
+
result.loc[:, available] = raw.loc[:, available].reindex(result.index).fillna(0)
|
|
204
|
+
|
|
205
|
+
for column in columns:
|
|
206
|
+
if column not in raw.columns:
|
|
207
|
+
result[column] = 0
|
|
208
|
+
|
|
209
|
+
return result
|