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
backtrader/utils/date.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Date/Time Conversion Utilities Module.
|
|
3
|
+
|
|
4
|
+
This module provides functions for converting between datetime objects
|
|
5
|
+
and numeric representations used internally by backtrader. It also
|
|
6
|
+
provides timezone handling utilities.
|
|
7
|
+
|
|
8
|
+
Exports:
|
|
9
|
+
date2num: Convert datetime to internal float representation.
|
|
10
|
+
num2date: Convert internal float to datetime.
|
|
11
|
+
num2dt: Alias for num2date.
|
|
12
|
+
time2num: Convert time to internal float representation.
|
|
13
|
+
num2time: Convert internal float to time.
|
|
14
|
+
tzparse: Parse timezone string.
|
|
15
|
+
Localizer: Timezone localization helper.
|
|
16
|
+
TZLocal: Local timezone instance.
|
|
17
|
+
UTC: UTC timezone instance.
|
|
18
|
+
TIME_MAX/TIME_MIN: Maximum/minimum time values.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
>>> from backtrader.utils import date2num, num2date
|
|
22
|
+
>>> import datetime
|
|
23
|
+
>>> dt = datetime.datetime(2020, 1, 1)
|
|
24
|
+
>>> num = date2num(dt)
|
|
25
|
+
>>> print(num2date(num))
|
|
26
|
+
2020-01-01 00:00:00+00:00
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# from backtrader.utils.cython_func import date2num
|
|
30
|
+
# from backtrader.utils.cython_func import num2dt
|
|
31
|
+
# from backtrader.utils.cython_func import num2date
|
|
32
|
+
# from backtrader.utils.cython_func import time2num
|
|
33
|
+
# from backtrader.utils.cython_func import num2time
|
|
34
|
+
|
|
35
|
+
from .dateintern import (
|
|
36
|
+
TIME_MAX,
|
|
37
|
+
TIME_MIN,
|
|
38
|
+
UTC,
|
|
39
|
+
Localizer,
|
|
40
|
+
TZLocal,
|
|
41
|
+
date2num,
|
|
42
|
+
datetime2str,
|
|
43
|
+
datetime2timestamp,
|
|
44
|
+
get_last_timeframe_timestamp,
|
|
45
|
+
num2date,
|
|
46
|
+
num2dt,
|
|
47
|
+
num2time,
|
|
48
|
+
str2datetime,
|
|
49
|
+
time2num,
|
|
50
|
+
timestamp2datetime,
|
|
51
|
+
tzparse,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
__all__ = (
|
|
55
|
+
"num2date",
|
|
56
|
+
"num2dt",
|
|
57
|
+
"date2num",
|
|
58
|
+
"time2num",
|
|
59
|
+
"num2time",
|
|
60
|
+
"get_last_timeframe_timestamp",
|
|
61
|
+
"UTC",
|
|
62
|
+
"TZLocal",
|
|
63
|
+
"Localizer",
|
|
64
|
+
"tzparse",
|
|
65
|
+
"TIME_MAX",
|
|
66
|
+
"TIME_MIN",
|
|
67
|
+
"timestamp2datetime",
|
|
68
|
+
"datetime2timestamp",
|
|
69
|
+
"str2datetime",
|
|
70
|
+
"datetime2str",
|
|
71
|
+
)
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Date Internal Module - Date/time conversion and timezone utilities.
|
|
3
|
+
|
|
4
|
+
This module provides internal utilities for date/time conversions,
|
|
5
|
+
timezone handling, and numeric date representations used throughout
|
|
6
|
+
backtrader.
|
|
7
|
+
|
|
8
|
+
Classes:
|
|
9
|
+
_UTC: UTC timezone implementation.
|
|
10
|
+
_LocalTimezone: Local timezone with DST support.
|
|
11
|
+
|
|
12
|
+
Functions:
|
|
13
|
+
tzparse: Parse timezone specification.
|
|
14
|
+
Localizer: Add localize method to timezone objects.
|
|
15
|
+
num2date: Convert numeric date to datetime.
|
|
16
|
+
num2dt: Convert numeric date to date.
|
|
17
|
+
num2time: Convert numeric date to time.
|
|
18
|
+
date2num: Convert datetime to numeric format.
|
|
19
|
+
time2num: Convert time to numeric format.
|
|
20
|
+
|
|
21
|
+
Constants:
|
|
22
|
+
UTC: Singleton UTC timezone instance.
|
|
23
|
+
TZLocal: Singleton local timezone instance.
|
|
24
|
+
TIME_MAX: Maximum time value (23:59:59.999990).
|
|
25
|
+
TIME_MIN: Minimum time value (00:00:00).
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import datetime
|
|
29
|
+
import math
|
|
30
|
+
import time as _time
|
|
31
|
+
from functools import lru_cache
|
|
32
|
+
|
|
33
|
+
import pytz
|
|
34
|
+
|
|
35
|
+
from .py3 import string_types
|
|
36
|
+
|
|
37
|
+
# from numba import jit
|
|
38
|
+
|
|
39
|
+
# Time difference for 0
|
|
40
|
+
ZERO = datetime.timedelta(0)
|
|
41
|
+
# Use time module's timezone attribute to return local timezone's (without DST) offset seconds from Greenwich (>0 Americas, <=0 most Europe, Asia, Africa)
|
|
42
|
+
# STDOFFSET represents offset when not in DST
|
|
43
|
+
STDOFFSET = datetime.timedelta(seconds=-_time.timezone)
|
|
44
|
+
# time.daylight being 0 means no DST, non-zero means DST
|
|
45
|
+
if _time.daylight:
|
|
46
|
+
# time.altzone returns local DST timezone offset, seconds west of UTC (if one is defined)
|
|
47
|
+
# DSTOFFSET offset during DST
|
|
48
|
+
DSTOFFSET = datetime.timedelta(seconds=-_time.altzone)
|
|
49
|
+
else:
|
|
50
|
+
DSTOFFSET = STDOFFSET
|
|
51
|
+
# DSTDIFF represents difference between DST and non-DST offsets
|
|
52
|
+
DSTDIFF = DSTOFFSET - STDOFFSET
|
|
53
|
+
|
|
54
|
+
# To avoid rounding errors, taking dates to next day
|
|
55
|
+
# Set TIME_MAX to avoid rounding errors causing dates to enter next day
|
|
56
|
+
TIME_MAX = datetime.time(23, 59, 59, 999990)
|
|
57
|
+
|
|
58
|
+
# To avoid rounding errors, taking dates to next day
|
|
59
|
+
# Set TIME_MIN to avoid rounding errors causing dates to enter next day
|
|
60
|
+
TIME_MIN = datetime.time.min
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Get the most recent bar update time point
|
|
64
|
+
def get_last_timeframe_timestamp(timestamp, time_diff):
|
|
65
|
+
"""Get previous whole minute timestamp based on current timestamp
|
|
66
|
+
:params timestamp int, calculate from int(time.time())
|
|
67
|
+
:params time_diff int, e.g. 1m timeframe using 60
|
|
68
|
+
:returns timestamp int
|
|
69
|
+
:raises ValueError: if time_diff is <= 0 (would cause infinite loop)
|
|
70
|
+
"""
|
|
71
|
+
if time_diff <= 0:
|
|
72
|
+
raise ValueError(f"time_diff must be positive, got {time_diff}")
|
|
73
|
+
return timestamp - (timestamp % time_diff)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_string_tz_time(tz="Asia/Singapore", string_format="%Y-%m-%d %H:%M:%S.%f"):
|
|
77
|
+
"""generate string timezone datetime in particular timezone
|
|
78
|
+
param: tz (str): timezone in pytz.common_timezones
|
|
79
|
+
param: string_format (str): string format
|
|
80
|
+
|
|
81
|
+
Return: now (String): timestamp
|
|
82
|
+
"""
|
|
83
|
+
tz = pytz.timezone(tz)
|
|
84
|
+
now = datetime.datetime.now(tz).strftime(string_format)
|
|
85
|
+
return now
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def timestamp2datetime(timestamp):
|
|
89
|
+
"""Convert timestamp to datetime
|
|
90
|
+
param: timestamp timestamp
|
|
91
|
+
param: string_format (str): string format
|
|
92
|
+
Return: formatted_time (Str): timestamp
|
|
93
|
+
"""
|
|
94
|
+
# Convert timestamp to datetime object
|
|
95
|
+
dt_object = datetime.datetime.fromtimestamp(timestamp)
|
|
96
|
+
return dt_object
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def timestamp2datestr(timestamp):
|
|
100
|
+
"""Convert timestamp to string time
|
|
101
|
+
param: timestamp timestamp
|
|
102
|
+
param: string_format (str): string format
|
|
103
|
+
Return: formatted_time (Str): timestamp
|
|
104
|
+
"""
|
|
105
|
+
# Convert timestamp to datetime object
|
|
106
|
+
dt_object = datetime.datetime.fromtimestamp(timestamp)
|
|
107
|
+
# Format datetime object as string
|
|
108
|
+
formatted_time = dt_object.strftime("%Y-%m-%d %H:%M:%S.%f")
|
|
109
|
+
return formatted_time
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def datetime2timestamp(time_date, string_format="%Y-%m-%d %H:%M:%S.%f"):
|
|
113
|
+
"""Convert datetime to timestamp
|
|
114
|
+
param: datetime_string (str): timezone in pytz.common_timezones
|
|
115
|
+
param: string_format (str): string format
|
|
116
|
+
Return: timestamp
|
|
117
|
+
"""
|
|
118
|
+
# Format datetime object as timestamp
|
|
119
|
+
timestamp = time_date.timestamp()
|
|
120
|
+
return timestamp
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def datestr2timestamp(
|
|
124
|
+
datetime_string="2023-06-01 09:30:00.0", string_format="%Y-%m-%d %H:%M:%S.%f"
|
|
125
|
+
):
|
|
126
|
+
"""Convert datetime to timestamp
|
|
127
|
+
param: datetime_string (str): timezone in pytz.common_timezones
|
|
128
|
+
param: string_format (str): string format
|
|
129
|
+
Return: timestamp
|
|
130
|
+
"""
|
|
131
|
+
# Convert timestamp to datetime object
|
|
132
|
+
time_date = datetime.datetime.strptime(datetime_string, string_format)
|
|
133
|
+
# Format datetime object as timestamp
|
|
134
|
+
timestamp = time_date.timestamp()
|
|
135
|
+
return timestamp
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def str2datetime(datetime_string="2023-06-01 09:30:00.0", string_format="%Y-%m-%d %H:%M:%S.%f"):
|
|
139
|
+
"""Convert string format time to datetime
|
|
140
|
+
param: datetime_string (str): timezone in pytz.common_timezones
|
|
141
|
+
param: string_format (str): string format
|
|
142
|
+
Return: datetime
|
|
143
|
+
"""
|
|
144
|
+
return datetime.datetime.strptime(datetime_string, string_format)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def datetime2str(datetime_obj, string_format="%Y-%m-%d %H:%M:%S.%f"):
|
|
148
|
+
"""Convert datetime to string format time
|
|
149
|
+
param: datetime_obj (datetime): timezone in pytz.common_timezones
|
|
150
|
+
param: string_format (str): string format
|
|
151
|
+
Return: datetime_str
|
|
152
|
+
"""
|
|
153
|
+
return datetime_obj.strftime(string_format)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def tzparse(tz):
|
|
157
|
+
"""Parse a timezone specification into a tzinfo object.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
tz: Timezone specification (string, tzinfo object, or None).
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
A tzinfo object. If pytz is available and tz is a string,
|
|
164
|
+
returns the corresponding pytz timezone. Otherwise returns
|
|
165
|
+
a Localizer-wrapped tz object.
|
|
166
|
+
"""
|
|
167
|
+
# This function attempts to convert tz
|
|
168
|
+
# If no object has been provided by the user and a timezone can be
|
|
169
|
+
# found via contractdtails, then try to get it from pytz, which may or
|
|
170
|
+
# may not be available.
|
|
171
|
+
tzstr = isinstance(tz, string_types)
|
|
172
|
+
if tz is None or not tzstr:
|
|
173
|
+
return Localizer(tz)
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
import pytz # keep the import very local
|
|
177
|
+
except ImportError:
|
|
178
|
+
return Localizer(tz) # nothing can be done
|
|
179
|
+
|
|
180
|
+
tzs = tz
|
|
181
|
+
if tzs == "CST": # usual alias
|
|
182
|
+
tzs = "CST6CDT"
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
tz = pytz.timezone(tzs)
|
|
186
|
+
except pytz.UnknownTimeZoneError:
|
|
187
|
+
return None # unknown timezone, nothing can be done
|
|
188
|
+
|
|
189
|
+
return tz
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def Localizer(tz):
|
|
193
|
+
"""Add a localize method to a timezone object.
|
|
194
|
+
|
|
195
|
+
This function adds a localize method to tz objects that don't
|
|
196
|
+
have one, allowing consistent timezone localization across
|
|
197
|
+
different timezone implementations.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
tz: Timezone object to add localize method to.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
The same timezone object with a localize method added.
|
|
204
|
+
"""
|
|
205
|
+
# This function adds a localize method to tz, this localize method adds timezone info to dt
|
|
206
|
+
# tzparse and Localizer are mainly for handling different timezones during live trading
|
|
207
|
+
import types
|
|
208
|
+
|
|
209
|
+
def localize(self, dt):
|
|
210
|
+
return dt.replace(tzinfo=self)
|
|
211
|
+
|
|
212
|
+
if tz is not None and not hasattr(tz, "localize"):
|
|
213
|
+
# patch the tz instance with a bound method
|
|
214
|
+
tz.localize = types.MethodType(localize, tz)
|
|
215
|
+
|
|
216
|
+
return tz
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
# A UTC class, same as the one in the Python Docs
|
|
220
|
+
class _UTC(datetime.tzinfo):
|
|
221
|
+
"""UTC timezone implementation.
|
|
222
|
+
|
|
223
|
+
A simple UTC timezone class that implements the tzinfo interface
|
|
224
|
+
with zero offset (no DST).
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
# UTC class
|
|
228
|
+
def utcoffset(self, dt):
|
|
229
|
+
"""Return UTC offset (always zero)."""
|
|
230
|
+
return ZERO
|
|
231
|
+
|
|
232
|
+
def tzname(self, dt):
|
|
233
|
+
"""Return timezone name (UTC)."""
|
|
234
|
+
return "UTC"
|
|
235
|
+
|
|
236
|
+
def dst(self, dt):
|
|
237
|
+
"""Return DST offset (always zero - UTC has no DST)."""
|
|
238
|
+
return ZERO
|
|
239
|
+
|
|
240
|
+
def localize(self, dt):
|
|
241
|
+
"""Localize a naive datetime to UTC.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
dt: Naive datetime to localize.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Datetime with UTC timezone info.
|
|
248
|
+
"""
|
|
249
|
+
return dt.replace(tzinfo=self)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class _LocalTimezone(datetime.tzinfo):
|
|
253
|
+
"""Local timezone with DST support.
|
|
254
|
+
|
|
255
|
+
Implements the local system timezone with automatic DST
|
|
256
|
+
(daylight saving time) calculation.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
# Timezone offset
|
|
260
|
+
def utcoffset(self, dt):
|
|
261
|
+
"""Return the UTC offset for this timezone.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
dt: Datetime to calculate offset for.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Timedelta offset from UTC (includes DST if applicable).
|
|
268
|
+
"""
|
|
269
|
+
if self._isdst(dt):
|
|
270
|
+
return DSTOFFSET
|
|
271
|
+
return STDOFFSET
|
|
272
|
+
|
|
273
|
+
# DST offset, offset is 0 when not in DST
|
|
274
|
+
def dst(self, dt):
|
|
275
|
+
"""Return the DST offset.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
dt: Datetime to calculate DST offset for.
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Timedelta DST adjustment (zero if not in DST).
|
|
282
|
+
"""
|
|
283
|
+
if self._isdst(dt):
|
|
284
|
+
return DSTDIFF
|
|
285
|
+
return ZERO
|
|
286
|
+
|
|
287
|
+
# Possibly timezone name
|
|
288
|
+
def tzname(self, dt):
|
|
289
|
+
"""Return the timezone name.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
dt: Datetime to get name for.
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
String timezone name (e.g., 'EST' or 'EDT').
|
|
296
|
+
"""
|
|
297
|
+
return _time.tzname[self._isdst(dt)]
|
|
298
|
+
|
|
299
|
+
# Determine if current time is DST
|
|
300
|
+
def _isdst(self, dt):
|
|
301
|
+
tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, 0)
|
|
302
|
+
try:
|
|
303
|
+
stamp = _time.mktime(tt)
|
|
304
|
+
except (ValueError, OverflowError):
|
|
305
|
+
return False # Too far in the future, not relevant
|
|
306
|
+
|
|
307
|
+
tt = _time.localtime(stamp)
|
|
308
|
+
return tt.tm_isdst > 0
|
|
309
|
+
|
|
310
|
+
# Add timezone info to dt
|
|
311
|
+
def localize(self, dt):
|
|
312
|
+
"""Localize a naive datetime to this timezone.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
dt: Naive datetime to localize.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Datetime with local timezone info.
|
|
319
|
+
"""
|
|
320
|
+
return dt.replace(tzinfo=self)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
UTC = _UTC()
|
|
324
|
+
TZLocal = _LocalTimezone()
|
|
325
|
+
|
|
326
|
+
HOURS_PER_DAY = 24.0 # 24 hours in a day
|
|
327
|
+
MINUTES_PER_HOUR = 60.0 # 60 minutes in 1 hour
|
|
328
|
+
SECONDS_PER_MINUTE = 60.0 # 60 seconds in 1 minute
|
|
329
|
+
MUSECONDS_PER_SECOND = 1e6 # How many microseconds in 1 second
|
|
330
|
+
MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY # How many minutes in 1 day
|
|
331
|
+
SECONDS_PER_DAY = SECONDS_PER_MINUTE * MINUTES_PER_DAY # How many seconds in 1 day
|
|
332
|
+
MUSECONDS_PER_DAY = MUSECONDS_PER_SECOND * SECONDS_PER_DAY # How many microseconds in 1 day
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# The following four functions are frequently used, after comments are completed,
|
|
336
|
+
# try using cython to rewrite, see how much speed can be improved
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@lru_cache(maxsize=8192)
|
|
340
|
+
def _num2date_cached(x):
|
|
341
|
+
"""Cached core computation for num2date (tz=None, naive=True case).
|
|
342
|
+
|
|
343
|
+
PERFORMANCE OPTIMIZATION: Cache common datetime conversions.
|
|
344
|
+
Called 2.2M+ times, caching reduces repeated calculations.
|
|
345
|
+
"""
|
|
346
|
+
# CRITICAL FIX: Handle invalid datetime values (0, NaN, negative)
|
|
347
|
+
if x != x or x <= 0: # NaN check or invalid value
|
|
348
|
+
return datetime.datetime(1970, 1, 1)
|
|
349
|
+
|
|
350
|
+
ix = int(x)
|
|
351
|
+
if ix < 1:
|
|
352
|
+
ix = 1
|
|
353
|
+
dt = datetime.datetime.fromordinal(ix)
|
|
354
|
+
remainder = float(x) - ix
|
|
355
|
+
hour, remainder = divmod(HOURS_PER_DAY * remainder, 1)
|
|
356
|
+
minute, remainder = divmod(MINUTES_PER_HOUR * remainder, 1)
|
|
357
|
+
second, remainder = divmod(SECONDS_PER_MINUTE * remainder, 1)
|
|
358
|
+
microsecond = int(MUSECONDS_PER_SECOND * remainder)
|
|
359
|
+
|
|
360
|
+
if microsecond < 10:
|
|
361
|
+
microsecond = 0
|
|
362
|
+
|
|
363
|
+
dt = datetime.datetime(
|
|
364
|
+
dt.year, dt.month, dt.day, int(hour), int(minute), int(second), microsecond
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
if microsecond > 999990:
|
|
368
|
+
dt += datetime.timedelta(microseconds=1e6 - microsecond)
|
|
369
|
+
|
|
370
|
+
return dt
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def num2date(x, tz=None, naive=True):
|
|
374
|
+
# Same as matplotlib except if tz is None, a naive datetime object
|
|
375
|
+
# will be returned.
|
|
376
|
+
"""
|
|
377
|
+
*x* is a float value that gives the number of days
|
|
378
|
+
(fraction part represents hours, minutes, seconds) since
|
|
379
|
+
0001-01-01 00:00:00 UTC *plus* *one*.
|
|
380
|
+
The addition of one here is a historical artifact. Also, note
|
|
381
|
+
that the Gregorian calendar is assumed; this is not universal
|
|
382
|
+
practice. For details, see the module docstring.
|
|
383
|
+
Return value is a: class:`datetime` instance in timezone *tz* (default to
|
|
384
|
+
rcparams TZ value).
|
|
385
|
+
If *x* is a sequence, a sequence of: class:`datetime` objects will
|
|
386
|
+
be returned.
|
|
387
|
+
"""
|
|
388
|
+
# PERFORMANCE OPTIMIZATION: Fast path for most common case (tz=None, naive=True)
|
|
389
|
+
if tz is None:
|
|
390
|
+
return _num2date_cached(x)
|
|
391
|
+
|
|
392
|
+
# Slow path: handle timezone conversion
|
|
393
|
+
# CRITICAL FIX: Handle invalid datetime values (0, NaN, negative)
|
|
394
|
+
if x != x or x <= 0: # NaN check or invalid value
|
|
395
|
+
return datetime.datetime(1970, 1, 1)
|
|
396
|
+
|
|
397
|
+
ix = int(x)
|
|
398
|
+
if ix < 1:
|
|
399
|
+
ix = 1
|
|
400
|
+
dt = datetime.datetime.fromordinal(ix)
|
|
401
|
+
remainder = float(x) - ix
|
|
402
|
+
hour, remainder = divmod(HOURS_PER_DAY * remainder, 1)
|
|
403
|
+
minute, remainder = divmod(MINUTES_PER_HOUR * remainder, 1)
|
|
404
|
+
second, remainder = divmod(SECONDS_PER_MINUTE * remainder, 1)
|
|
405
|
+
microsecond = int(MUSECONDS_PER_SECOND * remainder)
|
|
406
|
+
|
|
407
|
+
if microsecond < 10:
|
|
408
|
+
microsecond = 0
|
|
409
|
+
|
|
410
|
+
# Compose time with timezone
|
|
411
|
+
dt = datetime.datetime(
|
|
412
|
+
dt.year, dt.month, dt.day, int(hour), int(minute), int(second), microsecond, tzinfo=UTC
|
|
413
|
+
)
|
|
414
|
+
dt = dt.astimezone(tz)
|
|
415
|
+
if naive:
|
|
416
|
+
dt = dt.replace(tzinfo=None)
|
|
417
|
+
|
|
418
|
+
if microsecond > 999990:
|
|
419
|
+
dt += datetime.timedelta(microseconds=1e6 - microsecond)
|
|
420
|
+
|
|
421
|
+
return dt
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
# Convert number to date
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def num2dt(num, tz=None, naive=True):
|
|
428
|
+
"""Convert numeric date to date object.
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
num: Numeric date value (days since 0001-01-01 UTC + 1).
|
|
432
|
+
tz: Timezone for the result (optional).
|
|
433
|
+
naive: If True, return naive date without timezone info.
|
|
434
|
+
|
|
435
|
+
Returns:
|
|
436
|
+
date: Date object extracted from the datetime.
|
|
437
|
+
"""
|
|
438
|
+
return num2date(num, tz=tz, naive=naive).date()
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
# Convert number to time
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def num2time(num, tz=None, naive=True):
|
|
445
|
+
"""Convert numeric date to time object.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
num: Numeric date value (days since 0001-01-01 UTC + 1).
|
|
449
|
+
tz: Timezone for the result (optional).
|
|
450
|
+
naive: If True, return naive time without timezone info.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
time: Time object extracted from the datetime.
|
|
454
|
+
"""
|
|
455
|
+
return num2date(num, tz=tz, naive=naive).time()
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
# Convert datetime to number
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def date2num(dt, tz=None):
|
|
462
|
+
"""
|
|
463
|
+
Convert: mod:`datetime` to the Gregorian date as UTC float days,
|
|
464
|
+
preserving hours, minutes, seconds and microseconds. Return value
|
|
465
|
+
is a: func:`float`.
|
|
466
|
+
"""
|
|
467
|
+
if tz is not None:
|
|
468
|
+
dt = tz.localize(dt)
|
|
469
|
+
|
|
470
|
+
if hasattr(dt, "tzinfo") and dt.tzinfo is not None:
|
|
471
|
+
delta = dt.tzinfo.utcoffset(dt)
|
|
472
|
+
if delta is not None:
|
|
473
|
+
dt -= delta
|
|
474
|
+
|
|
475
|
+
base = float(dt.toordinal())
|
|
476
|
+
if hasattr(dt, "hour"):
|
|
477
|
+
# base += (dt.hour / HOURS_PER_DAY +
|
|
478
|
+
# dt.minute / MINUTES_PER_DAY +
|
|
479
|
+
# dt.second / SECONDS_PER_DAY +
|
|
480
|
+
# dt.microsecond / MUSECONDS_PER_DAY)
|
|
481
|
+
base = math.fsum(
|
|
482
|
+
(
|
|
483
|
+
base,
|
|
484
|
+
dt.hour / HOURS_PER_DAY,
|
|
485
|
+
dt.minute / MINUTES_PER_DAY,
|
|
486
|
+
dt.second / SECONDS_PER_DAY,
|
|
487
|
+
dt.microsecond / MUSECONDS_PER_DAY,
|
|
488
|
+
)
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
return base
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
# Convert time to number
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def time2num(tm):
|
|
498
|
+
"""
|
|
499
|
+
Converts the hour/minute/second/microsecond part of tm (datetime.datetime
|
|
500
|
+
or time) to a num
|
|
501
|
+
"""
|
|
502
|
+
num = (
|
|
503
|
+
tm.hour / HOURS_PER_DAY
|
|
504
|
+
+ tm.minute / MINUTES_PER_DAY
|
|
505
|
+
+ tm.second / SECONDS_PER_DAY
|
|
506
|
+
+ tm.microsecond / MUSECONDS_PER_DAY
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
return num
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Flush File Module - Auto-flushing file wrapper for Windows.
|
|
3
|
+
|
|
4
|
+
This module provides a wrapper for file-like objects that automatically
|
|
5
|
+
flushes after each write. On Windows platforms, it replaces sys.stdout
|
|
6
|
+
and sys.stderr with auto-flushing versions to ensure immediate output.
|
|
7
|
+
|
|
8
|
+
Classes:
|
|
9
|
+
flushfile: Wrapper that auto-flushes after each write.
|
|
10
|
+
StdOutDevNull: Null output device that suppresses stdout.
|
|
11
|
+
|
|
12
|
+
Note:
|
|
13
|
+
This is primarily for Windows compatibility where output buffering
|
|
14
|
+
can cause delayed display of stdout/stderr.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# By literal meaning, this class should flush output during output to make it display immediately, but looking at the usage of this class, it doesn't seem to serve this purpose
|
|
21
|
+
# Only in btrun file is this file imported, import backtrader.utils.flushfile, when imported it will directly check if this system
|
|
22
|
+
# Is win32, if win32 it uses flushfile to create two instances, during initialization uses sys.stdout, sys.stderr these two methods
|
|
23
|
+
# In reality, it doesn't seem to serve any purpose. Similar to the py3 file, it may be for compatibility purposes, but who uses python2 anymore, almost never
|
|
24
|
+
# So the entire framework appears to have quite a few redundant functions and classes
|
|
25
|
+
class flushfile:
|
|
26
|
+
"""File wrapper that auto-flushes after each write.
|
|
27
|
+
|
|
28
|
+
This class wraps a file-like object and ensures that each write
|
|
29
|
+
operation is immediately flushed to the underlying file descriptor.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
f: The underlying file-like object.
|
|
33
|
+
|
|
34
|
+
Note:
|
|
35
|
+
On Windows, this module automatically wraps sys.stdout and
|
|
36
|
+
sys.stderr with flushfile instances.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, f):
|
|
40
|
+
"""Initialize the flushfile wrapper.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
f: File-like object to wrap (typically sys.stdout or sys.stderr).
|
|
44
|
+
"""
|
|
45
|
+
self.f = f
|
|
46
|
+
|
|
47
|
+
def write(self, x):
|
|
48
|
+
"""Write data to the file and immediately flush.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
x: Data to write to the file.
|
|
52
|
+
"""
|
|
53
|
+
self.f.write(x)
|
|
54
|
+
self.f.flush()
|
|
55
|
+
|
|
56
|
+
def flush(self):
|
|
57
|
+
"""Flush the underlying file buffer."""
|
|
58
|
+
self.f.flush()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if sys.platform == "win32":
|
|
62
|
+
sys.stdout = flushfile(sys.stdout)
|
|
63
|
+
sys.stderr = flushfile(sys.stderr)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Unused class, by type it should be for output
|
|
67
|
+
class StdOutDevNull:
|
|
68
|
+
"""Null output device that suppresses stdout.
|
|
69
|
+
|
|
70
|
+
When active, all writes to stdout are discarded. The original
|
|
71
|
+
stdout can be restored by calling the stop() method.
|
|
72
|
+
|
|
73
|
+
Attributes:
|
|
74
|
+
stdout: The original sys.stdout saved for restoration.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self):
|
|
78
|
+
"""Initialize StdOutDevNull and replace sys.stdout."""
|
|
79
|
+
self.stdout = sys.stdout
|
|
80
|
+
sys.stdout = self
|
|
81
|
+
|
|
82
|
+
def write(self, x):
|
|
83
|
+
"""Discard written data instead of outputting.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
x: Data to discard.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
def flush(self):
|
|
90
|
+
"""No-op flush method for compatibility."""
|
|
91
|
+
|
|
92
|
+
def stop(self):
|
|
93
|
+
"""Restore the original sys.stdout."""
|
|
94
|
+
sys.stdout = self.stdout
|