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,132 @@
|
|
|
1
|
+
"""Shared helpers for net and dual-side position handling."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
POSITION_MODE_NET = "net"
|
|
6
|
+
POSITION_MODE_DUAL_SIDE = "dual_side"
|
|
7
|
+
|
|
8
|
+
POSITION_SIDE_LONG = "long"
|
|
9
|
+
POSITION_SIDE_SHORT = "short"
|
|
10
|
+
|
|
11
|
+
POSITION_OFFSET_OPEN = "open"
|
|
12
|
+
POSITION_OFFSET_CLOSE = "close"
|
|
13
|
+
POSITION_OFFSET_CLOSE_TODAY = "close_today"
|
|
14
|
+
POSITION_OFFSET_CLOSE_YESTERDAY = "close_yesterday"
|
|
15
|
+
|
|
16
|
+
_VALID_POSITION_MODES = {
|
|
17
|
+
POSITION_MODE_NET,
|
|
18
|
+
POSITION_MODE_DUAL_SIDE,
|
|
19
|
+
}
|
|
20
|
+
_VALID_POSITION_SIDES = {
|
|
21
|
+
POSITION_SIDE_LONG,
|
|
22
|
+
POSITION_SIDE_SHORT,
|
|
23
|
+
}
|
|
24
|
+
_VALID_POSITION_OFFSETS = {
|
|
25
|
+
POSITION_OFFSET_OPEN,
|
|
26
|
+
POSITION_OFFSET_CLOSE,
|
|
27
|
+
POSITION_OFFSET_CLOSE_TODAY,
|
|
28
|
+
POSITION_OFFSET_CLOSE_YESTERDAY,
|
|
29
|
+
}
|
|
30
|
+
_VALID_DUAL_SIDE_COMBOS = {
|
|
31
|
+
(True, POSITION_SIDE_LONG, POSITION_OFFSET_OPEN),
|
|
32
|
+
(False, POSITION_SIDE_LONG, POSITION_OFFSET_CLOSE),
|
|
33
|
+
(False, POSITION_SIDE_SHORT, POSITION_OFFSET_OPEN),
|
|
34
|
+
(True, POSITION_SIDE_SHORT, POSITION_OFFSET_CLOSE),
|
|
35
|
+
(False, POSITION_SIDE_LONG, POSITION_OFFSET_CLOSE_TODAY),
|
|
36
|
+
(False, POSITION_SIDE_LONG, POSITION_OFFSET_CLOSE_YESTERDAY),
|
|
37
|
+
(True, POSITION_SIDE_SHORT, POSITION_OFFSET_CLOSE_TODAY),
|
|
38
|
+
(True, POSITION_SIDE_SHORT, POSITION_OFFSET_CLOSE_YESTERDAY),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def normalize_position_mode(mode):
|
|
43
|
+
"""Normalize and validate a broker position mode."""
|
|
44
|
+
mode = POSITION_MODE_NET if mode in (None, "") else str(mode).strip().lower()
|
|
45
|
+
if mode not in _VALID_POSITION_MODES:
|
|
46
|
+
raise ValueError(f"Unsupported position_mode {mode!r}. Expected 'net' or 'dual_side'")
|
|
47
|
+
return mode
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def normalize_position_side(side):
|
|
51
|
+
"""Normalize and validate a position side."""
|
|
52
|
+
if side in (None, ""):
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
side = str(side).strip().lower()
|
|
56
|
+
if side not in _VALID_POSITION_SIDES:
|
|
57
|
+
raise ValueError(f"Unsupported position_side {side!r}. Expected 'long' or 'short'")
|
|
58
|
+
return side
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def normalize_position_offset(offset):
|
|
62
|
+
"""Normalize and validate a position offset."""
|
|
63
|
+
if offset in (None, ""):
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
offset = str(offset).strip().lower()
|
|
67
|
+
if offset not in _VALID_POSITION_OFFSETS:
|
|
68
|
+
raise ValueError(f"Unsupported offset {offset!r}. Expected 'open' or 'close'")
|
|
69
|
+
return offset
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def validate_dual_side_action(isbuy, position_side, offset):
|
|
73
|
+
"""Validate a dual-side order action."""
|
|
74
|
+
position_side = normalize_position_side(position_side)
|
|
75
|
+
offset = normalize_position_offset(offset)
|
|
76
|
+
|
|
77
|
+
if position_side is None or offset is None:
|
|
78
|
+
raise ValueError("dual_side mode requires both position_side and offset to be specified")
|
|
79
|
+
|
|
80
|
+
if (bool(isbuy), position_side, offset) not in _VALID_DUAL_SIDE_COMBOS:
|
|
81
|
+
action = "buy" if isbuy else "sell"
|
|
82
|
+
raise ValueError(
|
|
83
|
+
f"Invalid dual-side order combination: action={action}, "
|
|
84
|
+
f"position_side={position_side}, offset={offset}"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return position_side, offset
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def normalize_order_position_meta(mode, isbuy, position_side=None, offset=None):
|
|
91
|
+
"""Normalize broker order metadata for the configured position mode."""
|
|
92
|
+
mode = normalize_position_mode(mode)
|
|
93
|
+
position_side = normalize_position_side(position_side)
|
|
94
|
+
offset = normalize_position_offset(offset)
|
|
95
|
+
|
|
96
|
+
if mode == POSITION_MODE_DUAL_SIDE:
|
|
97
|
+
return validate_dual_side_action(isbuy, position_side, offset)
|
|
98
|
+
|
|
99
|
+
return position_side, offset
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def infer_position_side(isbuy, offset):
|
|
103
|
+
"""Infer the target leg from order direction and offset."""
|
|
104
|
+
offset = normalize_position_offset(offset)
|
|
105
|
+
if offset is None:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
if offset == POSITION_OFFSET_OPEN:
|
|
109
|
+
return POSITION_SIDE_LONG if isbuy else POSITION_SIDE_SHORT
|
|
110
|
+
|
|
111
|
+
return POSITION_SIDE_SHORT if isbuy else POSITION_SIDE_LONG
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def trade_key_from_order(order):
|
|
115
|
+
"""Return the trade-group key used by strategy notifications."""
|
|
116
|
+
raw_position_side = getattr(getattr(order, "info", None), "position_side", None)
|
|
117
|
+
try:
|
|
118
|
+
position_side = normalize_position_side(raw_position_side)
|
|
119
|
+
except ValueError:
|
|
120
|
+
position_side = None
|
|
121
|
+
if position_side is None:
|
|
122
|
+
return order.tradeid
|
|
123
|
+
return (order.tradeid, position_side)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def signed_position_size(position_side, quantity):
|
|
127
|
+
"""Convert a positive leg quantity into backtrader signed size semantics."""
|
|
128
|
+
position_side = normalize_position_side(position_side)
|
|
129
|
+
quantity = abs(float(quantity or 0.0))
|
|
130
|
+
if position_side == POSITION_SIDE_SHORT:
|
|
131
|
+
return -quantity
|
|
132
|
+
return quantity
|
backtrader/profiles.py
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Predefined Cerebro profiles for common live/backtest setups.
|
|
2
|
+
|
|
3
|
+
Provides :class:`LiveProfile`, a declarative description of a run (mode,
|
|
4
|
+
strategy, data source, broker, frequency) plus :func:`build_cerebro` to turn a
|
|
5
|
+
profile into a wired-up :class:`~backtrader.cerebro.Cerebro` instance. Keeps the
|
|
6
|
+
boilerplate of selecting broker/data classes for backtest vs live in one place.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Any, Callable, Dict, Iterable, Optional, Tuple
|
|
13
|
+
|
|
14
|
+
from .brokers.bbroker import BackBroker
|
|
15
|
+
from .cerebro import Cerebro
|
|
16
|
+
from .feeds.btcsv import BacktraderCSVData
|
|
17
|
+
from .stores.btapistore import BtApiStore
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class LiveProfile:
|
|
22
|
+
"""Declarative description of a single Cerebro run.
|
|
23
|
+
|
|
24
|
+
Captures the run mode (``backtest`` or ``live``), the strategy
|
|
25
|
+
class plus its args/kwargs, the data source description
|
|
26
|
+
(``dataname``, ``symbols`` or a custom ``data_factory``), the
|
|
27
|
+
broker construction knobs and the optional live store
|
|
28
|
+
configuration. ``__post_init__`` normalizes the inputs and runs
|
|
29
|
+
a set of consistency checks so that :func:`build_cerebro` can
|
|
30
|
+
produce a fully wired Cerebro without further validation.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
mode: ``"backtest"`` or ``"live"``. Validated in
|
|
34
|
+
``__post_init__``.
|
|
35
|
+
strategy: The strategy class to register on the Cerebro.
|
|
36
|
+
frequency: One of ``"lowfreq"``, ``"midfreq"`` or ``"hft"``.
|
|
37
|
+
Used by downstream broker/feed wiring to pick the right
|
|
38
|
+
defaults.
|
|
39
|
+
dataname: Optional single-source identifier (e.g. CSV path).
|
|
40
|
+
symbols: Optional tuple of symbol identifiers for multi-feed
|
|
41
|
+
runs.
|
|
42
|
+
strategy_args: Positional arguments forwarded to the
|
|
43
|
+
strategy constructor.
|
|
44
|
+
strategy_kwargs: Keyword arguments forwarded to the strategy
|
|
45
|
+
constructor.
|
|
46
|
+
data_cls: Optional explicit data feed class.
|
|
47
|
+
data_factory: Optional callable returning one or more
|
|
48
|
+
pre-built data instances. Mutually exclusive with
|
|
49
|
+
``dataname``/``symbols``.
|
|
50
|
+
data_kwargs: Keyword arguments forwarded to the data feed
|
|
51
|
+
constructor.
|
|
52
|
+
data_name: Optional explicit name attached to the (single)
|
|
53
|
+
data feed.
|
|
54
|
+
broker_cls: Optional explicit broker class.
|
|
55
|
+
broker_factory: Optional callable returning a broker instance.
|
|
56
|
+
broker_kwargs: Keyword arguments forwarded to the broker
|
|
57
|
+
constructor.
|
|
58
|
+
store_factory: Optional callable returning a live store
|
|
59
|
+
instance.
|
|
60
|
+
store_kwargs: Keyword arguments forwarded to the live store
|
|
61
|
+
constructor.
|
|
62
|
+
store_provider: Live-store provider name (``"btapi"`` by
|
|
63
|
+
default).
|
|
64
|
+
cerebro_kwargs: Keyword arguments forwarded to the
|
|
65
|
+
:class:`Cerebro` constructor.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
mode: str
|
|
69
|
+
strategy: type
|
|
70
|
+
frequency: str = "lowfreq"
|
|
71
|
+
dataname: Optional[str] = None
|
|
72
|
+
symbols: Tuple[str, ...] = ()
|
|
73
|
+
strategy_args: Tuple[Any, ...] = ()
|
|
74
|
+
strategy_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
75
|
+
data_cls: Optional[type] = None
|
|
76
|
+
data_factory: Optional[Callable[[], Any]] = None
|
|
77
|
+
data_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
78
|
+
data_name: Optional[str] = None
|
|
79
|
+
broker_cls: Optional[type] = None
|
|
80
|
+
broker_factory: Optional[Callable[..., Any]] = None
|
|
81
|
+
broker_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
82
|
+
store_factory: Optional[Callable[[], Any]] = None
|
|
83
|
+
store_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
84
|
+
store_provider: str = "btapi"
|
|
85
|
+
cerebro_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
86
|
+
|
|
87
|
+
def __post_init__(self):
|
|
88
|
+
"""Run every input-normalization and validation pass."""
|
|
89
|
+
self._normalize_mode_frequency()
|
|
90
|
+
self._validate_store_config()
|
|
91
|
+
self._normalize_symbols()
|
|
92
|
+
self._validate_data_source()
|
|
93
|
+
|
|
94
|
+
def _normalize_mode_frequency(self) -> None:
|
|
95
|
+
"""Lower-case and validate ``mode`` and ``frequency``."""
|
|
96
|
+
self.mode = str(self.mode or "").lower()
|
|
97
|
+
if self.mode not in {"backtest", "live"}:
|
|
98
|
+
raise ValueError("LiveProfile.mode must be 'backtest' or 'live'")
|
|
99
|
+
self.frequency = str(self.frequency or "").lower()
|
|
100
|
+
if self.frequency not in {"lowfreq", "midfreq", "hft"}:
|
|
101
|
+
raise ValueError("LiveProfile.frequency must be 'lowfreq', 'midfreq', or 'hft'")
|
|
102
|
+
|
|
103
|
+
def _validate_store_config(self) -> None:
|
|
104
|
+
"""Reject live store configuration on backtest profiles."""
|
|
105
|
+
if self.mode == "backtest" and (
|
|
106
|
+
self.store_factory is not None or self.store_kwargs or self.store_provider != "btapi"
|
|
107
|
+
):
|
|
108
|
+
raise ValueError("Backtest profiles cannot use live store configuration")
|
|
109
|
+
|
|
110
|
+
def _normalize_symbols(self) -> None:
|
|
111
|
+
"""Coerce ``symbols`` into a tuple of non-empty strings."""
|
|
112
|
+
symbols = self.symbols
|
|
113
|
+
if isinstance(symbols, str):
|
|
114
|
+
symbols = (symbols,)
|
|
115
|
+
self.symbols = tuple(str(symbol) for symbol in (symbols or ()) if str(symbol))
|
|
116
|
+
|
|
117
|
+
def _validate_data_source(self) -> None:
|
|
118
|
+
"""Ensure exactly one coherent data source is configured."""
|
|
119
|
+
if self.data_factory is not None and (self.dataname not in (None, "") or self.symbols):
|
|
120
|
+
raise ValueError("LiveProfile.data_factory cannot be used with dataname or symbols")
|
|
121
|
+
if self.data_factory is None and self.dataname in (None, "") and not self.symbols:
|
|
122
|
+
raise ValueError("LiveProfile requires dataname, symbols, or data_factory")
|
|
123
|
+
if self.dataname not in (None, "") and self.symbols:
|
|
124
|
+
raise ValueError("LiveProfile cannot use both dataname and symbols")
|
|
125
|
+
if self.data_name not in (None, "") and len(self.symbols) > 1:
|
|
126
|
+
raise ValueError("LiveProfile.data_name cannot be used with multiple symbols")
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def is_live(self) -> bool:
|
|
130
|
+
"""Return ``True`` when the profile's ``mode`` is ``"live"``.
|
|
131
|
+
|
|
132
|
+
Used by :func:`build_cerebro` and friends to branch between
|
|
133
|
+
the live (store-backed) and backtest (CSV-backed) wiring
|
|
134
|
+
paths without re-comparing the raw ``mode`` string.
|
|
135
|
+
"""
|
|
136
|
+
return self.mode == "live"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def build_cerebro(profile: LiveProfile) -> Cerebro:
|
|
140
|
+
"""Construct a fully wired-up :class:`Cerebro` from ``profile``.
|
|
141
|
+
|
|
142
|
+
The function instantiates the store (for live profiles), the
|
|
143
|
+
broker and the data feeds according to ``profile``, attaches
|
|
144
|
+
them to a fresh :class:`Cerebro`, and registers the strategy.
|
|
145
|
+
The profile and store are exposed back on the Cerebro as
|
|
146
|
+
``live_profile`` and ``profile_store`` for downstream
|
|
147
|
+
introspection.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
profile: The :class:`LiveProfile` describing the run.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Cerebro: A Cerebro instance with the broker, data feed(s)
|
|
154
|
+
and strategy attached.
|
|
155
|
+
"""
|
|
156
|
+
cerebro = Cerebro(**dict(profile.cerebro_kwargs))
|
|
157
|
+
store = _build_store(profile) if profile.is_live else None
|
|
158
|
+
broker = _build_broker(profile, store)
|
|
159
|
+
datas = list(_build_datas(profile, store))
|
|
160
|
+
|
|
161
|
+
if profile.data_name not in (None, "") and len(datas) > 1:
|
|
162
|
+
raise ValueError("LiveProfile.data_name cannot be used with multiple data feeds")
|
|
163
|
+
|
|
164
|
+
cerebro.setbroker(broker)
|
|
165
|
+
for data in datas:
|
|
166
|
+
data_name = profile.data_name
|
|
167
|
+
if data_name in (None, ""):
|
|
168
|
+
data_name = getattr(data, "_name", None) or getattr(data, "_dataname", None)
|
|
169
|
+
if data_name is None:
|
|
170
|
+
cerebro.adddata(data)
|
|
171
|
+
else:
|
|
172
|
+
cerebro.adddata(data, name=data_name)
|
|
173
|
+
cerebro.addstrategy(profile.strategy, *profile.strategy_args, **dict(profile.strategy_kwargs))
|
|
174
|
+
cerebro.live_profile = profile
|
|
175
|
+
cerebro.profile_store = store
|
|
176
|
+
return cerebro
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _build_store(profile: LiveProfile):
|
|
180
|
+
"""Instantiate the live store declared by ``profile``.
|
|
181
|
+
|
|
182
|
+
When ``profile.store_factory`` is set it is called with no
|
|
183
|
+
arguments and its return value is used. Otherwise a
|
|
184
|
+
:class:`BtApiStore` is constructed using
|
|
185
|
+
``profile.store_provider`` and ``profile.store_kwargs``.
|
|
186
|
+
"""
|
|
187
|
+
if profile.store_factory is not None:
|
|
188
|
+
return profile.store_factory()
|
|
189
|
+
return BtApiStore(provider=profile.store_provider, **dict(profile.store_kwargs))
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _build_broker(profile: LiveProfile, store):
|
|
193
|
+
"""Instantiate the broker declared by ``profile``.
|
|
194
|
+
|
|
195
|
+
``profile.broker_factory`` short-circuits the standard flow
|
|
196
|
+
when set (and must return a non-``None`` broker). For live
|
|
197
|
+
profiles the broker is obtained via ``store.getbroker``; for
|
|
198
|
+
backtest profiles a :class:`BackBroker` (or
|
|
199
|
+
``profile.broker_cls``) is constructed directly.
|
|
200
|
+
"""
|
|
201
|
+
if profile.broker_factory is not None:
|
|
202
|
+
broker = profile.broker_factory(store=store, profile=profile)
|
|
203
|
+
if broker is None:
|
|
204
|
+
raise ValueError("LiveProfile.broker_factory must return a broker instance")
|
|
205
|
+
return broker
|
|
206
|
+
|
|
207
|
+
broker_kwargs = dict(profile.broker_kwargs)
|
|
208
|
+
if profile.is_live:
|
|
209
|
+
if store is None:
|
|
210
|
+
raise ValueError("Live profiles require a store instance")
|
|
211
|
+
if profile.broker_cls is None:
|
|
212
|
+
return store.getbroker(**broker_kwargs)
|
|
213
|
+
return store.getbroker(broker_cls=profile.broker_cls, **broker_kwargs)
|
|
214
|
+
|
|
215
|
+
broker_cls = profile.broker_cls or BackBroker
|
|
216
|
+
return broker_cls(**broker_kwargs)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _build_datas(profile: LiveProfile, store) -> Iterable[Any]:
|
|
220
|
+
"""Instantiate the data feed(s) declared by ``profile``.
|
|
221
|
+
|
|
222
|
+
``profile.data_factory`` short-circuits the standard flow when
|
|
223
|
+
set; the factory may return a single data instance or a list /
|
|
224
|
+
tuple of them. Otherwise the data feeds are constructed via the
|
|
225
|
+
store (live) or via :class:`BacktraderCSVData` (backtest), one
|
|
226
|
+
per ``dataname``/``symbol``.
|
|
227
|
+
"""
|
|
228
|
+
if profile.data_factory is not None:
|
|
229
|
+
data_obj = profile.data_factory()
|
|
230
|
+
if isinstance(data_obj, (list, tuple)):
|
|
231
|
+
datas = list(data_obj)
|
|
232
|
+
else:
|
|
233
|
+
datas = [data_obj]
|
|
234
|
+
if not datas or any(data is None for data in datas):
|
|
235
|
+
raise ValueError("LiveProfile.data_factory must return one or more data instances")
|
|
236
|
+
return datas
|
|
237
|
+
|
|
238
|
+
data_kwargs = dict(profile.data_kwargs)
|
|
239
|
+
datanames = list(profile.symbols) if profile.symbols else [profile.dataname]
|
|
240
|
+
if profile.is_live:
|
|
241
|
+
if store is None:
|
|
242
|
+
raise ValueError("Live profiles require a store instance")
|
|
243
|
+
if profile.data_cls is None:
|
|
244
|
+
return [store.getdata(dataname=dataname, **data_kwargs) for dataname in datanames]
|
|
245
|
+
return [
|
|
246
|
+
store.getdata(dataname=dataname, data_cls=profile.data_cls, **data_kwargs)
|
|
247
|
+
for dataname in datanames
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
data_cls = profile.data_cls or BacktraderCSVData
|
|
251
|
+
return [data_cls(dataname=dataname, **data_kwargs) for dataname in datanames]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
__all__ = ["LiveProfile", "build_cerebro"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Report generation module.
|
|
4
|
+
|
|
5
|
+
Provides backtest report generation functionality, including:
|
|
6
|
+
- PerformanceCalculator: Performance metrics calculation
|
|
7
|
+
- ReportChart: Report-specific chart generation
|
|
8
|
+
- ReportGenerator: Main report generator
|
|
9
|
+
|
|
10
|
+
Usage example:
|
|
11
|
+
import backtrader as bt
|
|
12
|
+
from backtrader.reports import ReportGenerator, PerformanceCalculator
|
|
13
|
+
|
|
14
|
+
# Run strategy
|
|
15
|
+
cerebro = bt.Cerebro()
|
|
16
|
+
cerebro.addstrategy(MyStrategy)
|
|
17
|
+
cerebro.adddata(data)
|
|
18
|
+
results = cerebro.run()
|
|
19
|
+
|
|
20
|
+
# Method 1: Generate report
|
|
21
|
+
report = ReportGenerator(results[0])
|
|
22
|
+
report.generate_html('report.html')
|
|
23
|
+
report.generate_pdf('report.pdf')
|
|
24
|
+
|
|
25
|
+
# Method 2: Get metrics only
|
|
26
|
+
calc = PerformanceCalculator(results[0])
|
|
27
|
+
metrics = calc.get_all_metrics()
|
|
28
|
+
print(metrics['sharpe_ratio'])
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from .charts import ReportChart
|
|
32
|
+
from .performance import PerformanceCalculator
|
|
33
|
+
from .reporter import ReportGenerator
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"PerformanceCalculator",
|
|
37
|
+
"ReportChart",
|
|
38
|
+
"ReportGenerator",
|
|
39
|
+
]
|