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,1022 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Financial plotting utilities for backtrader.
|
|
3
|
+
|
|
4
|
+
This module provides plot handlers and functions for rendering various
|
|
5
|
+
financial chart types including candlestick, OHLC, volume, and line-on-close
|
|
6
|
+
plots using matplotlib.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import matplotlib.collections as mcol
|
|
10
|
+
import matplotlib.colors as mcolors
|
|
11
|
+
import matplotlib.legend as mlegend
|
|
12
|
+
import matplotlib.lines as mlines
|
|
13
|
+
|
|
14
|
+
from ..utils.py3 import range, zip
|
|
15
|
+
from .utils import shade_color
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CandlestickPlotHandler:
|
|
19
|
+
"""Handler for creating and managing candlestick plot collections.
|
|
20
|
+
|
|
21
|
+
This class creates matplotlib collections for rendering candlestick charts
|
|
22
|
+
with customizable colors for up and down bars. It also provides custom
|
|
23
|
+
legend rendering for candlestick patterns.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
legend_opens: Open prices for legend sample candles.
|
|
27
|
+
legend_highs: High prices for legend sample candles.
|
|
28
|
+
legend_lows: Low prices for legend sample candles.
|
|
29
|
+
legend_closes: Close prices for legend sample candles.
|
|
30
|
+
colorup: RGBA color for up bars (close > open).
|
|
31
|
+
colordown: RGBA color for down bars (close < open).
|
|
32
|
+
edgeup: RGBA edge color for up bars.
|
|
33
|
+
edgedown: RGBA edge color for down bars.
|
|
34
|
+
tickup: RGBA color for up tick marks.
|
|
35
|
+
tickdown: RGBA color for down tick marks.
|
|
36
|
+
barcol: PolyCollection containing the candlestick bodies.
|
|
37
|
+
tickcol: LineCollection containing the candlestick wicks.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
legend_opens = [0.50, 0.50, 0.50]
|
|
41
|
+
legend_highs = [1.00, 1.00, 1.00]
|
|
42
|
+
legend_lows = [0.00, 0.00, 0.00]
|
|
43
|
+
legend_closes = [0.80, 0.00, 1.00]
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
ax,
|
|
48
|
+
x,
|
|
49
|
+
opens,
|
|
50
|
+
highs,
|
|
51
|
+
lows,
|
|
52
|
+
closes,
|
|
53
|
+
colorup="k",
|
|
54
|
+
colordown="r",
|
|
55
|
+
edgeup=None,
|
|
56
|
+
edgedown=None,
|
|
57
|
+
tickup=None,
|
|
58
|
+
tickdown=None,
|
|
59
|
+
width=1,
|
|
60
|
+
tickwidth=1,
|
|
61
|
+
edgeadjust=0.05,
|
|
62
|
+
edgeshading=-10,
|
|
63
|
+
alpha=1.0,
|
|
64
|
+
label="_nolegend",
|
|
65
|
+
fillup=True,
|
|
66
|
+
filldown=True,
|
|
67
|
+
**kwargs,
|
|
68
|
+
):
|
|
69
|
+
"""Initialize the candlestick plot handler.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
ax: Matplotlib axes object to add collections to.
|
|
73
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
74
|
+
opens: Array of opening prices.
|
|
75
|
+
highs: Array of high prices.
|
|
76
|
+
lows: Array of low prices.
|
|
77
|
+
closes: Array of closing prices.
|
|
78
|
+
colorup: Color for up bars (close > open). Default is "k" (black).
|
|
79
|
+
colordown: Color for down bars (close < open). Default is "r" (red).
|
|
80
|
+
edgeup: Edge color for up bars. If None, derived from colorup with shading.
|
|
81
|
+
edgedown: Edge color for down bars. If None, derived from colordown with shading.
|
|
82
|
+
tickup: Color for up tick marks (wicks). If None, uses edgeup.
|
|
83
|
+
tickdown: Color for down tick marks (wicks). If None, uses edgedown.
|
|
84
|
+
width: Width of candlestick bodies. Default is 1.
|
|
85
|
+
tickwidth: Width of candlestick wicks. Default is 1.
|
|
86
|
+
edgeadjust: Adjustment for edge width. Default is 0.05.
|
|
87
|
+
edgeshading: Shading factor for edge colors. Default is -10.
|
|
88
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
89
|
+
label: Label for legend. Default is "_nolegend".
|
|
90
|
+
fillup: Whether to fill up bars. Default is True.
|
|
91
|
+
filldown: Whether to fill down bars. Default is True.
|
|
92
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
ValueError: If color conversion fails.
|
|
96
|
+
"""
|
|
97
|
+
# Manager up/down bar colors
|
|
98
|
+
r, g, b = mcolors.colorConverter.to_rgb(colorup)
|
|
99
|
+
self.colorup = r, g, b, alpha
|
|
100
|
+
r, g, b = mcolors.colorConverter.to_rgb(colordown)
|
|
101
|
+
self.colordown = r, g, b, alpha
|
|
102
|
+
# Manage the edge up/down colors for the bars
|
|
103
|
+
if edgeup:
|
|
104
|
+
r, g, b = mcolors.colorConverter.to_rgb(edgeup)
|
|
105
|
+
self.edgeup = ((r, g, b, alpha),)
|
|
106
|
+
else:
|
|
107
|
+
self.edgeup = shade_color(self.colorup, edgeshading)
|
|
108
|
+
|
|
109
|
+
if edgedown:
|
|
110
|
+
r, g, b = mcolors.colorConverter.to_rgb(edgedown)
|
|
111
|
+
self.edgedown = ((r, g, b, alpha),)
|
|
112
|
+
else:
|
|
113
|
+
self.edgedown = shade_color(self.colordown, edgeshading)
|
|
114
|
+
|
|
115
|
+
# Manage the up/down tick colors
|
|
116
|
+
if tickup:
|
|
117
|
+
r, g, b = mcolors.colorConverter.to_rgb(tickup)
|
|
118
|
+
self.tickup = ((r, g, b, alpha),)
|
|
119
|
+
else:
|
|
120
|
+
self.tickup = self.edgeup
|
|
121
|
+
|
|
122
|
+
if tickdown:
|
|
123
|
+
r, g, b = mcolors.colorConverter.to_rgb(tickdown)
|
|
124
|
+
self.tickdown = ((r, g, b, alpha),)
|
|
125
|
+
else:
|
|
126
|
+
self.tickdown = self.edgedown
|
|
127
|
+
|
|
128
|
+
self.barcol, self.tickcol = self.barcollection(
|
|
129
|
+
x,
|
|
130
|
+
opens,
|
|
131
|
+
highs,
|
|
132
|
+
lows,
|
|
133
|
+
closes,
|
|
134
|
+
width,
|
|
135
|
+
tickwidth,
|
|
136
|
+
edgeadjust,
|
|
137
|
+
label=label,
|
|
138
|
+
fillup=fillup,
|
|
139
|
+
filldown=filldown,
|
|
140
|
+
**kwargs,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# add collections to the axis and return them
|
|
144
|
+
ax.add_collection(self.tickcol)
|
|
145
|
+
ax.add_collection(self.barcol)
|
|
146
|
+
|
|
147
|
+
# Update the axis
|
|
148
|
+
ax.update_datalim(((0, min(lows)), (len(opens), max(highs))))
|
|
149
|
+
ax.autoscale_view()
|
|
150
|
+
|
|
151
|
+
# Add self as legend handler for this object
|
|
152
|
+
mlegend.Legend.update_default_handler_map({self.barcol: self})
|
|
153
|
+
|
|
154
|
+
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
|
|
155
|
+
"""Create a custom legend artist for candlestick plots.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
legend: The legend object being created.
|
|
159
|
+
orig_handle: The original handle for which the artist is created.
|
|
160
|
+
fontsize: The font size for the legend.
|
|
161
|
+
handlebox: The handlebox container for positioning the legend artist.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Tuple of (barcol, tickcol): The bar and tick collections for the legend.
|
|
165
|
+
"""
|
|
166
|
+
x0 = handlebox.xdescent
|
|
167
|
+
y0 = handlebox.ydescent
|
|
168
|
+
width = handlebox.width / len(self.legend_opens)
|
|
169
|
+
height = handlebox.height
|
|
170
|
+
|
|
171
|
+
# Generate the x-axis coordinates (handlebox based)
|
|
172
|
+
xs = [x0 + width * (i + 0.5) for i in range(len(self.legend_opens))]
|
|
173
|
+
|
|
174
|
+
barcol, tickcol = self.barcollection(
|
|
175
|
+
xs,
|
|
176
|
+
self.legend_opens,
|
|
177
|
+
self.legend_highs,
|
|
178
|
+
self.legend_lows,
|
|
179
|
+
self.legend_closes,
|
|
180
|
+
width=width,
|
|
181
|
+
tickwidth=2,
|
|
182
|
+
scaling=height,
|
|
183
|
+
bot=y0,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
barcol.set_transform(handlebox.get_transform())
|
|
187
|
+
handlebox.add_artist(barcol)
|
|
188
|
+
tickcol.set_transform(handlebox.get_transform())
|
|
189
|
+
handlebox.add_artist(tickcol)
|
|
190
|
+
|
|
191
|
+
return barcol, tickcol
|
|
192
|
+
|
|
193
|
+
def barcollection(
|
|
194
|
+
self,
|
|
195
|
+
xs,
|
|
196
|
+
opens,
|
|
197
|
+
highs,
|
|
198
|
+
lows,
|
|
199
|
+
closes,
|
|
200
|
+
width,
|
|
201
|
+
tickwidth=1,
|
|
202
|
+
edgeadjust=0,
|
|
203
|
+
label="_nolegend",
|
|
204
|
+
scaling=1.0,
|
|
205
|
+
bot=0,
|
|
206
|
+
fillup=True,
|
|
207
|
+
filldown=True,
|
|
208
|
+
**kwargs,
|
|
209
|
+
):
|
|
210
|
+
"""Create matplotlib collections for candlestick bars and wicks.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
xs: Array of x-axis coordinates.
|
|
214
|
+
opens: Array of opening prices.
|
|
215
|
+
highs: Array of high prices.
|
|
216
|
+
lows: Array of low prices.
|
|
217
|
+
closes: Array of closing prices.
|
|
218
|
+
width: Width of candlestick bodies.
|
|
219
|
+
tickwidth: Width of candlestick wicks. Default is 1.
|
|
220
|
+
edgeadjust: Adjustment for edge width. Default is 0.
|
|
221
|
+
label: Label for legend. Default is "_nolegend".
|
|
222
|
+
scaling: Vertical scaling factor. Default is 1.0.
|
|
223
|
+
bot: Bottom offset for vertical positioning. Default is 0.
|
|
224
|
+
fillup: Whether to fill up bars. Default is True.
|
|
225
|
+
filldown: Whether to fill down bars. Default is True.
|
|
226
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
Tuple of (barcol, tickcol): PolyCollection for bodies and LineCollection for wicks.
|
|
230
|
+
"""
|
|
231
|
+
# Prepack different zips of the series values
|
|
232
|
+
oc = lambda: zip(opens, closes) # NOQA: E731
|
|
233
|
+
xoc = lambda: zip(xs, opens, closes) # NOQA: E731
|
|
234
|
+
iohlc = lambda: zip(xs, opens, highs, lows, closes) # NOQA: E731
|
|
235
|
+
|
|
236
|
+
colorup = self.colorup if fillup else "None"
|
|
237
|
+
colordown = self.colordown if filldown else "None"
|
|
238
|
+
colord = {True: colorup, False: colordown}
|
|
239
|
+
colors = [colord[o < c] for o, c in oc()]
|
|
240
|
+
|
|
241
|
+
edgecolord = {True: self.edgeup, False: self.edgedown}
|
|
242
|
+
edgecolors = [edgecolord[o < c] for o, c in oc()]
|
|
243
|
+
|
|
244
|
+
tickcolord = {True: self.tickup, False: self.tickdown}
|
|
245
|
+
tickcolors = [tickcolord[o < c] for o, c in oc()]
|
|
246
|
+
|
|
247
|
+
delta = width / 2 - edgeadjust
|
|
248
|
+
|
|
249
|
+
def barbox(i, open_, close):
|
|
250
|
+
# delta seen as closure
|
|
251
|
+
left, right = i - delta, i + delta
|
|
252
|
+
open_ = open_ * scaling + bot
|
|
253
|
+
close = close * scaling + bot
|
|
254
|
+
return (left, open_), (left, close), (right, close), (right, open_)
|
|
255
|
+
|
|
256
|
+
barareas = [barbox(i, o, c) for i, o, c in xoc()]
|
|
257
|
+
|
|
258
|
+
def tup(i, open_, high, close):
|
|
259
|
+
high = high * scaling + bot
|
|
260
|
+
open_ = open_ * scaling + bot
|
|
261
|
+
close = close * scaling + bot
|
|
262
|
+
|
|
263
|
+
return (i, high), (i, max(open_, close))
|
|
264
|
+
|
|
265
|
+
tickrangesup = [tup(i, o, h, c) for i, o, h, low, c in iohlc()]
|
|
266
|
+
|
|
267
|
+
def tdown(i, open_, low, close):
|
|
268
|
+
low = low * scaling + bot
|
|
269
|
+
open_ = open_ * scaling + bot
|
|
270
|
+
close = close * scaling + bot
|
|
271
|
+
|
|
272
|
+
return (i, low), (i, min(open_, close))
|
|
273
|
+
|
|
274
|
+
tickrangesdown = [tdown(i, o, low, c) for i, o, h, low, c in iohlc()]
|
|
275
|
+
|
|
276
|
+
# Extra variables for the collections
|
|
277
|
+
useaa = (0,) # use tuple here
|
|
278
|
+
lw = (0.5,) # and here
|
|
279
|
+
tlw = (tickwidth,)
|
|
280
|
+
|
|
281
|
+
# Bar collection for the candles
|
|
282
|
+
barcol = mcol.PolyCollection(
|
|
283
|
+
barareas,
|
|
284
|
+
facecolors=colors,
|
|
285
|
+
edgecolors=edgecolors,
|
|
286
|
+
antialiaseds=useaa,
|
|
287
|
+
linewidths=lw,
|
|
288
|
+
label=label,
|
|
289
|
+
**kwargs,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# LineCollections have a higher zorder than PolyCollections
|
|
293
|
+
# to ensure the edges of the bars are not overwriten by the Lines
|
|
294
|
+
# we need to put the bars slightly over the LineCollections
|
|
295
|
+
kwargs["zorder"] = barcol.get_zorder() * 0.9999
|
|
296
|
+
|
|
297
|
+
# Up/down ticks from the body
|
|
298
|
+
tickcol = mcol.LineCollection(
|
|
299
|
+
tickrangesup + tickrangesdown,
|
|
300
|
+
colors=tickcolors,
|
|
301
|
+
linewidths=tlw,
|
|
302
|
+
antialiaseds=useaa,
|
|
303
|
+
**kwargs,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# return barcol, tickcol
|
|
307
|
+
return barcol, tickcol
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def plot_candlestick(
|
|
311
|
+
ax,
|
|
312
|
+
x,
|
|
313
|
+
opens,
|
|
314
|
+
highs,
|
|
315
|
+
lows,
|
|
316
|
+
closes,
|
|
317
|
+
colorup="k",
|
|
318
|
+
colordown="r",
|
|
319
|
+
edgeup=None,
|
|
320
|
+
edgedown=None,
|
|
321
|
+
tickup=None,
|
|
322
|
+
tickdown=None,
|
|
323
|
+
width=1,
|
|
324
|
+
tickwidth=1.25,
|
|
325
|
+
edgeadjust=0.05,
|
|
326
|
+
edgeshading=-10,
|
|
327
|
+
alpha=1.0,
|
|
328
|
+
label="_nolegend",
|
|
329
|
+
fillup=True,
|
|
330
|
+
filldown=True,
|
|
331
|
+
**kwargs,
|
|
332
|
+
):
|
|
333
|
+
"""Plot candlestick chart on given axes.
|
|
334
|
+
|
|
335
|
+
Convenience function that creates a CandlestickPlotHandler and returns
|
|
336
|
+
the matplotlib collections for the candlestick chart.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
ax: Matplotlib axes object to add collections to.
|
|
340
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
341
|
+
opens: Array of opening prices.
|
|
342
|
+
highs: Array of high prices.
|
|
343
|
+
lows: Array of low prices.
|
|
344
|
+
closes: Array of closing prices.
|
|
345
|
+
colorup: Color for up bars (close > open). Default is "k" (black).
|
|
346
|
+
colordown: Color for down bars (close < open). Default is "r" (red).
|
|
347
|
+
edgeup: Edge color for up bars. If None, derived from colorup with shading.
|
|
348
|
+
edgedown: Edge color for down bars. If None, derived from colordown with shading.
|
|
349
|
+
tickup: Color for up tick marks (wicks). If None, uses edgeup.
|
|
350
|
+
tickdown: Color for down tick marks (wicks). If None, uses edgedown.
|
|
351
|
+
width: Width of candlestick bodies. Default is 1.
|
|
352
|
+
tickwidth: Width of candlestick wicks. Default is 1.25.
|
|
353
|
+
edgeadjust: Adjustment for edge width. Default is 0.05.
|
|
354
|
+
edgeshading: Shading factor for edge colors. Default is -10.
|
|
355
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
356
|
+
label: Label for legend. Default is "_nolegend".
|
|
357
|
+
fillup: Whether to fill up bars. Default is True.
|
|
358
|
+
filldown: Whether to fill down bars. Default is True.
|
|
359
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
Tuple of (barcol, tickcol): PolyCollection for bodies and LineCollection for wicks.
|
|
363
|
+
"""
|
|
364
|
+
chandler = CandlestickPlotHandler(
|
|
365
|
+
ax,
|
|
366
|
+
x,
|
|
367
|
+
opens,
|
|
368
|
+
highs,
|
|
369
|
+
lows,
|
|
370
|
+
closes,
|
|
371
|
+
colorup,
|
|
372
|
+
colordown,
|
|
373
|
+
edgeup,
|
|
374
|
+
edgedown,
|
|
375
|
+
tickup,
|
|
376
|
+
tickdown,
|
|
377
|
+
width,
|
|
378
|
+
tickwidth,
|
|
379
|
+
edgeadjust,
|
|
380
|
+
edgeshading,
|
|
381
|
+
alpha,
|
|
382
|
+
label,
|
|
383
|
+
fillup,
|
|
384
|
+
filldown,
|
|
385
|
+
**kwargs,
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
# Return the collections.
|
|
389
|
+
# The barcol goes first because it
|
|
390
|
+
# is the larger, has the dominant zorder and defines the legend
|
|
391
|
+
return chandler.barcol, chandler.tickcol
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
class VolumePlotHandler:
|
|
395
|
+
"""Handler for creating and managing volume plot collections.
|
|
396
|
+
|
|
397
|
+
This class creates matplotlib collections for rendering volume bars
|
|
398
|
+
with customizable colors for up and down periods based on price movement.
|
|
399
|
+
|
|
400
|
+
Attributes:
|
|
401
|
+
legend_vols: Sample volumes for legend rendering.
|
|
402
|
+
legend_opens: Sample open prices for legend rendering.
|
|
403
|
+
legend_closes: Sample close prices for legend rendering.
|
|
404
|
+
colorup: RGBA color for up volume bars (close > open).
|
|
405
|
+
colordown: RGBA color for down volume bars (close < open).
|
|
406
|
+
edgeup: RGBA edge color for up bars.
|
|
407
|
+
edgedown: RGBA edge color for down bars.
|
|
408
|
+
barcol: PolyCollection containing the volume bars.
|
|
409
|
+
"""
|
|
410
|
+
|
|
411
|
+
legend_vols = [0.5, 1.0, 0.75]
|
|
412
|
+
legend_opens = [0, 1, 0]
|
|
413
|
+
legend_closes = [1, 0, 1]
|
|
414
|
+
|
|
415
|
+
def __init__(
|
|
416
|
+
self,
|
|
417
|
+
ax,
|
|
418
|
+
x,
|
|
419
|
+
opens,
|
|
420
|
+
closes,
|
|
421
|
+
volumes,
|
|
422
|
+
colorup="k",
|
|
423
|
+
colordown="r",
|
|
424
|
+
edgeup=None,
|
|
425
|
+
edgedown=None,
|
|
426
|
+
edgeshading=-5,
|
|
427
|
+
edgeadjust=0.05,
|
|
428
|
+
width=1,
|
|
429
|
+
alpha=1.0,
|
|
430
|
+
**kwargs,
|
|
431
|
+
):
|
|
432
|
+
"""Initialize the volume plot handler.
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
ax: Matplotlib axes object to add collections to.
|
|
436
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
437
|
+
opens: Array of opening prices.
|
|
438
|
+
closes: Array of closing prices.
|
|
439
|
+
volumes: Array of volume values.
|
|
440
|
+
colorup: Color for up volume bars (close > open). Default is "k" (black).
|
|
441
|
+
colordown: Color for down volume bars (close < open). Default is "r" (red).
|
|
442
|
+
edgeup: Edge color for up bars. If None, derived from colorup with shading.
|
|
443
|
+
edgedown: Edge color for down bars. If None, derived from colordown with shading.
|
|
444
|
+
edgeshading: Shading factor for edge colors. Default is -5.
|
|
445
|
+
edgeadjust: Adjustment for edge width. Default is 0.05.
|
|
446
|
+
width: Width of volume bars. Default is 1.
|
|
447
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
448
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
449
|
+
|
|
450
|
+
Raises:
|
|
451
|
+
ValueError: If color conversion fails.
|
|
452
|
+
"""
|
|
453
|
+
# Manage the up/down colors
|
|
454
|
+
r, g, b = mcolors.colorConverter.to_rgb(colorup)
|
|
455
|
+
self.colorup = r, g, b, alpha
|
|
456
|
+
r, g, b = mcolors.colorConverter.to_rgb(colordown)
|
|
457
|
+
self.colordown = r, g, b, alpha
|
|
458
|
+
|
|
459
|
+
# Prepare the edge colors
|
|
460
|
+
if not edgeup:
|
|
461
|
+
self.edgeup = shade_color(self.colorup, edgeshading)
|
|
462
|
+
else:
|
|
463
|
+
r, g, b = mcolors.colorConverter.to_rgb(edgeup)
|
|
464
|
+
self.edgeup = r, g, b, alpha
|
|
465
|
+
|
|
466
|
+
if not edgedown:
|
|
467
|
+
self.edgedown = shade_color(self.colordown, edgeshading)
|
|
468
|
+
else:
|
|
469
|
+
r, g, b = mcolors.colorConverter.to_rgb(edgedown)
|
|
470
|
+
self.edgedown = r, g, b, alpha
|
|
471
|
+
|
|
472
|
+
corners = (0, 0), (len(closes), max(volumes))
|
|
473
|
+
ax.update_datalim(corners)
|
|
474
|
+
ax.autoscale_view()
|
|
475
|
+
|
|
476
|
+
self.barcol = self.barcollection(
|
|
477
|
+
x, opens, closes, volumes, width=width, edgeadjust=edgeadjust, **kwargs
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
# add to axes
|
|
481
|
+
ax.add_collection(self.barcol)
|
|
482
|
+
|
|
483
|
+
# Add a legend handler for this object
|
|
484
|
+
mlegend.Legend.update_default_handler_map({self.barcol: self})
|
|
485
|
+
|
|
486
|
+
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
|
|
487
|
+
"""Create a custom legend artist for volume plots.
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
legend: The legend object being created.
|
|
491
|
+
orig_handle: The original handle for which the artist is created.
|
|
492
|
+
fontsize: The font size for the legend.
|
|
493
|
+
handlebox: The handlebox container for positioning the legend artist.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
barcol: The volume bar collection for the legend.
|
|
497
|
+
"""
|
|
498
|
+
x0 = handlebox.xdescent
|
|
499
|
+
y0 = handlebox.ydescent
|
|
500
|
+
width = handlebox.width / len(self.legend_vols)
|
|
501
|
+
height = handlebox.height
|
|
502
|
+
|
|
503
|
+
# Generate the x-axis coordinates (handlebox based)
|
|
504
|
+
xs = [x0 + width * (i + 0.5) for i in range(len(self.legend_vols))]
|
|
505
|
+
|
|
506
|
+
barcol = self.barcollection(
|
|
507
|
+
xs,
|
|
508
|
+
self.legend_opens,
|
|
509
|
+
self.legend_closes,
|
|
510
|
+
self.legend_vols,
|
|
511
|
+
width=width,
|
|
512
|
+
vscaling=height,
|
|
513
|
+
vbot=y0,
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
barcol.set_transform(handlebox.get_transform())
|
|
517
|
+
handlebox.add_artist(barcol)
|
|
518
|
+
|
|
519
|
+
return barcol
|
|
520
|
+
|
|
521
|
+
def barcollection(
|
|
522
|
+
self, x, opens, closes, vols, width, edgeadjust=0, vscaling=1.0, vbot=0, **kwargs
|
|
523
|
+
):
|
|
524
|
+
"""Create matplotlib collection for volume bars.
|
|
525
|
+
|
|
526
|
+
Args:
|
|
527
|
+
x: Array of x-axis coordinates.
|
|
528
|
+
opens: Array of opening prices.
|
|
529
|
+
closes: Array of closing prices.
|
|
530
|
+
vols: Array of volume values.
|
|
531
|
+
width: Width of volume bars.
|
|
532
|
+
edgeadjust: Adjustment for edge width. Default is 0.
|
|
533
|
+
vscaling: Vertical scaling factor. Default is 1.0.
|
|
534
|
+
vbot: Bottom offset for vertical positioning. Default is 0.
|
|
535
|
+
**kwargs: Additional keyword arguments passed to collection.
|
|
536
|
+
|
|
537
|
+
Returns:
|
|
538
|
+
barcol: PolyCollection containing the volume bars.
|
|
539
|
+
"""
|
|
540
|
+
# Prepare the data
|
|
541
|
+
openclose = lambda: zip(opens, closes) # NOQA: E731
|
|
542
|
+
|
|
543
|
+
# Calculate bars colors
|
|
544
|
+
colord = {True: self.colorup, False: self.colordown}
|
|
545
|
+
colors = [colord[open_ < close] for open_, close in openclose()]
|
|
546
|
+
edgecolord = {True: self.edgeup, False: self.edgedown}
|
|
547
|
+
edgecolors = [edgecolord[open_ < close] for open_, close in openclose()]
|
|
548
|
+
|
|
549
|
+
# bar width to the sides
|
|
550
|
+
delta = width / 2 - edgeadjust
|
|
551
|
+
|
|
552
|
+
# small auxiliary func to return the bar coordinates
|
|
553
|
+
def volbar(i, v):
|
|
554
|
+
left, right = i - delta, i + delta
|
|
555
|
+
v = vbot + v * vscaling
|
|
556
|
+
return (left, vbot), (left, v), (right, v), (right, vbot)
|
|
557
|
+
|
|
558
|
+
barareas = [volbar(i, v) for i, v in zip(x, vols)]
|
|
559
|
+
barcol = mcol.PolyCollection(
|
|
560
|
+
barareas,
|
|
561
|
+
facecolors=colors,
|
|
562
|
+
edgecolors=edgecolors,
|
|
563
|
+
antialiaseds=(0,),
|
|
564
|
+
linewidths=(0.5,),
|
|
565
|
+
**kwargs,
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
return barcol
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
def plot_volume(
|
|
572
|
+
ax,
|
|
573
|
+
x,
|
|
574
|
+
opens,
|
|
575
|
+
closes,
|
|
576
|
+
volumes,
|
|
577
|
+
colorup="k",
|
|
578
|
+
colordown="r",
|
|
579
|
+
edgeup=None,
|
|
580
|
+
edgedown=None,
|
|
581
|
+
edgeshading=-5,
|
|
582
|
+
edgeadjust=0.05,
|
|
583
|
+
width=1,
|
|
584
|
+
alpha=1.0,
|
|
585
|
+
**kwargs,
|
|
586
|
+
):
|
|
587
|
+
"""Plot volume chart on given axes.
|
|
588
|
+
|
|
589
|
+
Convenience function that creates a VolumePlotHandler and returns
|
|
590
|
+
the matplotlib collection for the volume chart.
|
|
591
|
+
|
|
592
|
+
Args:
|
|
593
|
+
ax: Matplotlib axes object to add collections to.
|
|
594
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
595
|
+
opens: Array of opening prices.
|
|
596
|
+
closes: Array of closing prices.
|
|
597
|
+
volumes: Array of volume values.
|
|
598
|
+
colorup: Color for up volume bars (close > open). Default is "k" (black).
|
|
599
|
+
colordown: Color for down volume bars (close < open). Default is "r" (red).
|
|
600
|
+
edgeup: Edge color for up bars. If None, derived from colorup with shading.
|
|
601
|
+
edgedown: Edge color for down bars. If None, derived from colordown with shading.
|
|
602
|
+
edgeshading: Shading factor for edge colors. Default is -5.
|
|
603
|
+
edgeadjust: Adjustment for edge width. Default is 0.05.
|
|
604
|
+
width: Width of volume bars. Default is 1.
|
|
605
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
606
|
+
**kwargs: Additional keyword arguments passed to collection.
|
|
607
|
+
|
|
608
|
+
Returns:
|
|
609
|
+
Tuple containing the volume bar collection.
|
|
610
|
+
"""
|
|
611
|
+
vhandler = VolumePlotHandler(
|
|
612
|
+
ax,
|
|
613
|
+
x,
|
|
614
|
+
opens,
|
|
615
|
+
closes,
|
|
616
|
+
volumes,
|
|
617
|
+
colorup,
|
|
618
|
+
colordown,
|
|
619
|
+
edgeup,
|
|
620
|
+
edgedown,
|
|
621
|
+
edgeshading,
|
|
622
|
+
edgeadjust,
|
|
623
|
+
width,
|
|
624
|
+
alpha,
|
|
625
|
+
**kwargs,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
return (vhandler.barcol,)
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
class OHLCPlotHandler:
|
|
632
|
+
"""Handler for creating and managing OHLC (Open-High-Low-Close) plot collections.
|
|
633
|
+
|
|
634
|
+
This class creates matplotlib line collections for rendering OHLC bar charts
|
|
635
|
+
with customizable colors for up and down bars.
|
|
636
|
+
|
|
637
|
+
Attributes:
|
|
638
|
+
legend_opens: Open prices for legend sample bars.
|
|
639
|
+
legend_highs: High prices for legend sample bars.
|
|
640
|
+
legend_lows: Low prices for legend sample bars.
|
|
641
|
+
legend_closes: Close prices for legend sample bars.
|
|
642
|
+
colorup: RGBA color for up bars (close > open).
|
|
643
|
+
colordown: RGBA color for down bars (close < open).
|
|
644
|
+
barcol: LineCollection containing the vertical high-low lines.
|
|
645
|
+
opencol: LineCollection containing the open tick marks.
|
|
646
|
+
closecol: LineCollection containing the close tick marks.
|
|
647
|
+
"""
|
|
648
|
+
|
|
649
|
+
legend_opens = [0.50, 0.50, 0.50]
|
|
650
|
+
legend_highs = [1.00, 1.00, 1.00]
|
|
651
|
+
legend_lows = [0.00, 0.00, 0.00]
|
|
652
|
+
legend_closes = [0.80, 0.20, 0.90]
|
|
653
|
+
|
|
654
|
+
def __init__(
|
|
655
|
+
self,
|
|
656
|
+
ax,
|
|
657
|
+
x,
|
|
658
|
+
opens,
|
|
659
|
+
highs,
|
|
660
|
+
lows,
|
|
661
|
+
closes,
|
|
662
|
+
colorup="k",
|
|
663
|
+
colordown="r",
|
|
664
|
+
width=1,
|
|
665
|
+
tickwidth=0.5,
|
|
666
|
+
alpha=1.0,
|
|
667
|
+
label="_nolegend",
|
|
668
|
+
**kwargs,
|
|
669
|
+
):
|
|
670
|
+
"""Initialize the OHLC plot handler.
|
|
671
|
+
|
|
672
|
+
Args:
|
|
673
|
+
ax: Matplotlib axes object to add collections to.
|
|
674
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
675
|
+
opens: Array of opening prices.
|
|
676
|
+
highs: Array of high prices.
|
|
677
|
+
lows: Array of low prices.
|
|
678
|
+
closes: Array of closing prices.
|
|
679
|
+
colorup: Color for up bars (close > open). Default is "k" (black).
|
|
680
|
+
colordown: Color for down bars (close < open). Default is "r" (red).
|
|
681
|
+
width: Width of vertical high-low lines. Default is 1.
|
|
682
|
+
tickwidth: Width of open/close tick marks. Default is 0.5.
|
|
683
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
684
|
+
label: Label for legend. Default is "_nolegend".
|
|
685
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
686
|
+
|
|
687
|
+
Raises:
|
|
688
|
+
ValueError: If color conversion fails.
|
|
689
|
+
"""
|
|
690
|
+
# Manager up/down bar colors
|
|
691
|
+
r, g, b = mcolors.colorConverter.to_rgb(colorup)
|
|
692
|
+
self.colorup = r, g, b, alpha
|
|
693
|
+
r, g, b = mcolors.colorConverter.to_rgb(colordown)
|
|
694
|
+
self.colordown = r, g, b, alpha
|
|
695
|
+
|
|
696
|
+
bcol, ocol, ccol = self.barcollection(
|
|
697
|
+
x, opens, highs, lows, closes, width=width, tickwidth=tickwidth, label=label, **kwargs
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
self.barcol = bcol
|
|
701
|
+
self.opencol = ocol
|
|
702
|
+
self.closecol = ccol
|
|
703
|
+
|
|
704
|
+
# add collections to the axis and return them
|
|
705
|
+
ax.add_collection(self.barcol)
|
|
706
|
+
ax.add_collection(self.opencol)
|
|
707
|
+
ax.add_collection(self.closecol)
|
|
708
|
+
|
|
709
|
+
# Update the axis
|
|
710
|
+
ax.update_datalim(((0, min(lows)), (len(opens), max(highs))))
|
|
711
|
+
ax.autoscale_view()
|
|
712
|
+
|
|
713
|
+
# Add self as legend handler for this object
|
|
714
|
+
mlegend.Legend.update_default_handler_map({self.barcol: self})
|
|
715
|
+
|
|
716
|
+
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
|
|
717
|
+
"""Create a custom legend artist for OHLC plots.
|
|
718
|
+
|
|
719
|
+
Args:
|
|
720
|
+
legend: The legend object being created.
|
|
721
|
+
orig_handle: The original handle for which the artist is created.
|
|
722
|
+
fontsize: The font size for the legend.
|
|
723
|
+
handlebox: The handlebox container for positioning the legend artist.
|
|
724
|
+
|
|
725
|
+
Returns:
|
|
726
|
+
Tuple of (barcol, opencol, closecol): The line collections for the legend.
|
|
727
|
+
"""
|
|
728
|
+
x0 = handlebox.xdescent
|
|
729
|
+
y0 = handlebox.ydescent
|
|
730
|
+
width = handlebox.width / len(self.legend_opens)
|
|
731
|
+
height = handlebox.height
|
|
732
|
+
|
|
733
|
+
# Generate the x-axis coordinates (handlebox based)
|
|
734
|
+
xs = [x0 + width * (i + 0.5) for i in range(len(self.legend_opens))]
|
|
735
|
+
|
|
736
|
+
barcol, opencol, closecol = self.barcollection(
|
|
737
|
+
xs,
|
|
738
|
+
self.legend_opens,
|
|
739
|
+
self.legend_highs,
|
|
740
|
+
self.legend_lows,
|
|
741
|
+
self.legend_closes,
|
|
742
|
+
width=1.5,
|
|
743
|
+
tickwidth=2,
|
|
744
|
+
scaling=height,
|
|
745
|
+
bot=y0,
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
barcol.set_transform(handlebox.get_transform())
|
|
749
|
+
handlebox.add_artist(barcol)
|
|
750
|
+
# opencol.set_transform(handlebox.get_transform())
|
|
751
|
+
handlebox.add_artist(opencol)
|
|
752
|
+
# closecol.set_transform(handlebox.get_transform())
|
|
753
|
+
handlebox.add_artist(closecol)
|
|
754
|
+
|
|
755
|
+
return barcol, opencol, closecol
|
|
756
|
+
|
|
757
|
+
def barcollection(
|
|
758
|
+
self,
|
|
759
|
+
xs,
|
|
760
|
+
opens,
|
|
761
|
+
highs,
|
|
762
|
+
lows,
|
|
763
|
+
closes,
|
|
764
|
+
width,
|
|
765
|
+
tickwidth,
|
|
766
|
+
label="_nolegend",
|
|
767
|
+
scaling=1.0,
|
|
768
|
+
bot=0,
|
|
769
|
+
**kwargs,
|
|
770
|
+
):
|
|
771
|
+
"""Create matplotlib collections for OHLC bars and tick marks.
|
|
772
|
+
|
|
773
|
+
Args:
|
|
774
|
+
xs: Array of x-axis coordinates.
|
|
775
|
+
opens: Array of opening prices.
|
|
776
|
+
highs: Array of high prices.
|
|
777
|
+
lows: Array of low prices.
|
|
778
|
+
closes: Array of closing prices.
|
|
779
|
+
width: Width of vertical high-low lines.
|
|
780
|
+
tickwidth: Width of open/close tick marks.
|
|
781
|
+
label: Label for legend. Default is "_nolegend".
|
|
782
|
+
scaling: Vertical scaling factor. Default is 1.0.
|
|
783
|
+
bot: Bottom offset for vertical positioning. Default is 0.
|
|
784
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
785
|
+
|
|
786
|
+
Returns:
|
|
787
|
+
Tuple of (barcol, opencol, closecol): LineCollection for bars,
|
|
788
|
+
open ticks, and close ticks.
|
|
789
|
+
"""
|
|
790
|
+
# Prepack different zips of the series values
|
|
791
|
+
ihighlow = lambda: zip(xs, highs, lows) # NOQA: E731
|
|
792
|
+
iopen = lambda: zip(xs, opens) # NOQA: E731
|
|
793
|
+
iclose = lambda: zip(xs, closes) # NOQA: E731
|
|
794
|
+
openclose = lambda: zip(opens, closes) # NOQA: E731
|
|
795
|
+
|
|
796
|
+
colord = {True: self.colorup, False: self.colordown}
|
|
797
|
+
colors = [colord[open_ < close] for open_, close in openclose()]
|
|
798
|
+
|
|
799
|
+
# Extra variables for the collections
|
|
800
|
+
useaa = (0,)
|
|
801
|
+
lw = (width,)
|
|
802
|
+
tlw = (tickwidth,)
|
|
803
|
+
|
|
804
|
+
# Calculate the barranges
|
|
805
|
+
def barrange(i, high, low):
|
|
806
|
+
return (i, low * scaling + bot), (i, high * scaling + bot)
|
|
807
|
+
|
|
808
|
+
barranges = [barrange(i, high, low) for i, high, low in ihighlow()]
|
|
809
|
+
|
|
810
|
+
barcol = mcol.LineCollection(
|
|
811
|
+
barranges, colors=colors, linewidths=lw, antialiaseds=useaa, label=label, **kwargs
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
def tickopen(i, open_):
|
|
815
|
+
open_ = open_ * scaling + bot
|
|
816
|
+
return (i - tickwidth, open_), (i, open_)
|
|
817
|
+
|
|
818
|
+
openticks = [tickopen(i, open_) for i, open_ in iopen()]
|
|
819
|
+
opencol = mcol.LineCollection(
|
|
820
|
+
openticks,
|
|
821
|
+
colors=colors,
|
|
822
|
+
antialiaseds=useaa,
|
|
823
|
+
linewidths=tlw,
|
|
824
|
+
label="_nolegend",
|
|
825
|
+
**kwargs,
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
def tickclose(i, close):
|
|
829
|
+
close = close * scaling + bot
|
|
830
|
+
return (i, close), (i + tickwidth, close)
|
|
831
|
+
|
|
832
|
+
closeticks = [tickclose(i, close) for i, close in iclose()]
|
|
833
|
+
closecol = mcol.LineCollection(
|
|
834
|
+
closeticks,
|
|
835
|
+
colors=colors,
|
|
836
|
+
antialiaseds=useaa,
|
|
837
|
+
linewidths=tlw,
|
|
838
|
+
label="_nolegend",
|
|
839
|
+
**kwargs,
|
|
840
|
+
)
|
|
841
|
+
|
|
842
|
+
# return barcol, tickcol
|
|
843
|
+
return barcol, opencol, closecol
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
def plot_ohlc(
|
|
847
|
+
ax,
|
|
848
|
+
x,
|
|
849
|
+
opens,
|
|
850
|
+
highs,
|
|
851
|
+
lows,
|
|
852
|
+
closes,
|
|
853
|
+
colorup="k",
|
|
854
|
+
colordown="r",
|
|
855
|
+
width=1.5,
|
|
856
|
+
tickwidth=0.5,
|
|
857
|
+
alpha=1.0,
|
|
858
|
+
label="_nolegend",
|
|
859
|
+
**kwargs,
|
|
860
|
+
):
|
|
861
|
+
"""Plot OHLC (Open-High-Low-Close) chart on given axes.
|
|
862
|
+
|
|
863
|
+
Convenience function that creates an OHLCPlotHandler and returns
|
|
864
|
+
the matplotlib collections for the OHLC chart.
|
|
865
|
+
|
|
866
|
+
Args:
|
|
867
|
+
ax: Matplotlib axes object to add collections to.
|
|
868
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
869
|
+
opens: Array of opening prices.
|
|
870
|
+
highs: Array of high prices.
|
|
871
|
+
lows: Array of low prices.
|
|
872
|
+
closes: Array of closing prices.
|
|
873
|
+
colorup: Color for up bars (close > open). Default is "k" (black).
|
|
874
|
+
colordown: Color for down bars (close < open). Default is "r" (red).
|
|
875
|
+
width: Width of vertical high-low lines. Default is 1.5.
|
|
876
|
+
tickwidth: Width of open/close tick marks. Default is 0.5.
|
|
877
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
878
|
+
label: Label for legend. Default is "_nolegend".
|
|
879
|
+
**kwargs: Additional keyword arguments passed to collections.
|
|
880
|
+
|
|
881
|
+
Returns:
|
|
882
|
+
Tuple of (barcol, opencol, closecol): LineCollection for bars,
|
|
883
|
+
open ticks, and close ticks.
|
|
884
|
+
"""
|
|
885
|
+
handler = OHLCPlotHandler(
|
|
886
|
+
ax,
|
|
887
|
+
x,
|
|
888
|
+
opens,
|
|
889
|
+
highs,
|
|
890
|
+
lows,
|
|
891
|
+
closes,
|
|
892
|
+
colorup,
|
|
893
|
+
colordown,
|
|
894
|
+
width,
|
|
895
|
+
tickwidth,
|
|
896
|
+
alpha,
|
|
897
|
+
label,
|
|
898
|
+
**kwargs,
|
|
899
|
+
)
|
|
900
|
+
|
|
901
|
+
return handler.barcol, handler.opencol, handler.closecol
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
class LineOnClosePlotHandler:
|
|
905
|
+
"""Handler for creating and managing line-on-close plot collections.
|
|
906
|
+
|
|
907
|
+
This class creates matplotlib line objects for rendering a simple line
|
|
908
|
+
chart of closing prices.
|
|
909
|
+
|
|
910
|
+
Attributes:
|
|
911
|
+
legend_closes: Sample close prices for legend rendering.
|
|
912
|
+
color: Color of the line.
|
|
913
|
+
alpha: Transparency level (0-1).
|
|
914
|
+
loc: Line2D object containing the close price line.
|
|
915
|
+
"""
|
|
916
|
+
|
|
917
|
+
legend_closes = [0.00, 0.66, 0.33, 1.00]
|
|
918
|
+
|
|
919
|
+
def __init__(self, ax, x, closes, color="k", width=1, alpha=1.0, label="_nolegend", **kwargs):
|
|
920
|
+
"""Initialize the line-on-close plot handler.
|
|
921
|
+
|
|
922
|
+
Args:
|
|
923
|
+
ax: Matplotlib axes object to add the line to.
|
|
924
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
925
|
+
closes: Array of closing prices.
|
|
926
|
+
color: Color of the line. Default is "k" (black).
|
|
927
|
+
width: Width of the line. Default is 1.
|
|
928
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
929
|
+
label: Label for legend. Default is "_nolegend".
|
|
930
|
+
**kwargs: Additional keyword arguments passed to Line2D.
|
|
931
|
+
"""
|
|
932
|
+
self.color = color
|
|
933
|
+
self.alpha = alpha
|
|
934
|
+
|
|
935
|
+
(self.loc,) = self.barcollection(x, closes, width=width, label=label, **kwargs)
|
|
936
|
+
|
|
937
|
+
# add collections to the axis and return them
|
|
938
|
+
ax.add_line(self.loc)
|
|
939
|
+
|
|
940
|
+
# Update the axis
|
|
941
|
+
ax.update_datalim(((x[0], min(closes)), (x[-1], max(closes))))
|
|
942
|
+
ax.autoscale_view()
|
|
943
|
+
|
|
944
|
+
# Add self as legend handler for this object
|
|
945
|
+
mlegend.Legend.update_default_handler_map({self.loc: self})
|
|
946
|
+
|
|
947
|
+
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
|
|
948
|
+
"""Create a custom legend artist for line-on-close plots.
|
|
949
|
+
|
|
950
|
+
Args:
|
|
951
|
+
legend: The legend object being created.
|
|
952
|
+
orig_handle: The original handle for which the artist is created.
|
|
953
|
+
fontsize: The font size for the legend.
|
|
954
|
+
handlebox: The handlebox container for positioning the legend artist.
|
|
955
|
+
|
|
956
|
+
Returns:
|
|
957
|
+
Tuple containing the line collection for the legend.
|
|
958
|
+
"""
|
|
959
|
+
x0 = handlebox.xdescent
|
|
960
|
+
y0 = handlebox.ydescent
|
|
961
|
+
width = handlebox.width / len(self.legend_closes)
|
|
962
|
+
height = handlebox.height
|
|
963
|
+
|
|
964
|
+
# Generate the x-axis coordinates (handlebox based)
|
|
965
|
+
xs = [x0 + width * (i + 0.5) for i in range(len(self.legend_closes))]
|
|
966
|
+
|
|
967
|
+
(linecol,) = self.barcollection(xs, self.legend_closes, width=1.5, scaling=height, bot=y0)
|
|
968
|
+
|
|
969
|
+
linecol.set_transform(handlebox.get_transform())
|
|
970
|
+
handlebox.add_artist(linecol)
|
|
971
|
+
|
|
972
|
+
return (linecol,)
|
|
973
|
+
|
|
974
|
+
def barcollection(self, xs, closes, width, label="_nolegend", scaling=1.0, bot=0, **kwargs):
|
|
975
|
+
"""Create matplotlib line object for close prices.
|
|
976
|
+
|
|
977
|
+
Args:
|
|
978
|
+
xs: Array of x-axis coordinates.
|
|
979
|
+
closes: Array of closing prices.
|
|
980
|
+
width: Width of the line.
|
|
981
|
+
label: Label for legend. Default is "_nolegend".
|
|
982
|
+
scaling: Vertical scaling factor. Default is 1.0.
|
|
983
|
+
bot: Bottom offset for vertical positioning. Default is 0.
|
|
984
|
+
**kwargs: Additional keyword arguments passed to Line2D.
|
|
985
|
+
|
|
986
|
+
Returns:
|
|
987
|
+
Tuple containing the Line2D object.
|
|
988
|
+
"""
|
|
989
|
+
# Prepack different zips of the series values
|
|
990
|
+
scaled = [close * scaling + bot for close in closes]
|
|
991
|
+
|
|
992
|
+
loc = mlines.Line2D(
|
|
993
|
+
xs, scaled, color=self.color, lw=width, label=label, alpha=self.alpha, **kwargs
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
return (loc,)
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
def plot_lineonclose(ax, x, closes, color="k", width=1.5, alpha=1.0, label="_nolegend", **kwargs):
|
|
1000
|
+
"""Plot line-on-close chart on given axes.
|
|
1001
|
+
|
|
1002
|
+
Convenience function that creates a LineOnClosePlotHandler and returns
|
|
1003
|
+
the matplotlib line object for the line chart.
|
|
1004
|
+
|
|
1005
|
+
Args:
|
|
1006
|
+
ax: Matplotlib axes object to add the line to.
|
|
1007
|
+
x: Array of x-axis coordinates (typically bar indices).
|
|
1008
|
+
closes: Array of closing prices.
|
|
1009
|
+
color: Color of the line. Default is "k" (black).
|
|
1010
|
+
width: Width of the line. Default is 1.5.
|
|
1011
|
+
alpha: Transparency level (0-1). Default is 1.0.
|
|
1012
|
+
label: Label for legend. Default is "_nolegend".
|
|
1013
|
+
**kwargs: Additional keyword arguments passed to Line2D.
|
|
1014
|
+
|
|
1015
|
+
Returns:
|
|
1016
|
+
Tuple containing the Line2D object.
|
|
1017
|
+
"""
|
|
1018
|
+
handler = LineOnClosePlotHandler(
|
|
1019
|
+
ax, x, closes, color=color, width=width, alpha=alpha, label=label, **kwargs
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
return (handler.loc,)
|