You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly绘制金融数据时X轴出现缺口的解决求助

问题描述

我在绘制泰国股市(SET)的市场宽度指标时,最后一个堆叠柱状图的X轴出现了股市休市日期的缺口,但我的DataFrame里根本没有这些日期。求去除X轴缺口的方法,相关代码如下:

import plotly.graph_objects as go
import pandas as pd
from tvDatafeed import TvDatafeed, Interval
from plotly.subplots import make_subplots

# Create TV Datafeed instance
tv = TvDatafeed()

# 1) Create Main CandleStick Chart
data_feed = tv.get_hist(symbol="SET", exchange='SET', interval=Interval.in_daily, n_bars=250)


# 6) Advance Decline Unchanged Chart
file_path_advance_decline_unchanged = "/content/drive/MyDrive/Stock Python/AdvanceDeclineUnchanged.csv"
AdvanceDeclineUnchanged_df = pd.read_csv(file_path_advance_decline_unchanged, index_col='Unnamed: 0')
last_250_days_data = AdvanceDeclineUnchanged_df.iloc[:, 0:250]
valid_dates = AdvanceDeclineUnchanged_df.loc["Advance", AdvanceDeclineUnchanged_df.loc["Advance"].notna()].index
plot_data = pd.DataFrame({
    'Date': data_feed.index,
    'Advance%': last_250_days_data.loc['Advance%', :].values,
    'Unchanged%': last_250_days_data.loc['Unchanged%', :].values,
    'Decline%': last_250_days_data.loc['Decline%', :].values
})

# Get only valid dates for x-axis
valid_dates = list(map(str, valid_dates))
plot_data = plot_data[plot_data['Date'].isin(valid_dates)]

# Create subplots
fig = make_subplots(rows=6, cols=1, shared_xaxes=True, vertical_spacing=0.04)

# Add traces to subplots
fig.add_trace(go.Candlestick(x=data_feed.index, open=data_feed.open, high=data_feed.high, low=data_feed.low, close=data_feed.close), row=1, col=1)

# 52Wks NHNL-Line Chart
_52WksNHNL_line = go.Scatter(x=_52WksNHNL_df.columns[0:249], y=_52WksNHNL_df.iloc[2, 0:250], mode='lines', name='52WksNewHighNewLow', line=dict(color='maroon'))
fig.add_trace(_52WksNHNL_line, row=2, col=1)

# 20Days NHNL-Line Chart
_20DaysNHNL_line = go.Scatter(x=_20DaysNHNL_df.columns[0:250], y=_20DaysNHNL_df.iloc[2, 0:250], mode='lines', name='20DaysNewHighNewLow', line=dict(color='green'))
fig.add_trace(_20DaysNHNL_line, row=3, col=1)

# 4% Gainer Chart
_4percent_line = go.Scatter(x=x_values_4percent, y=y_values_4percent, mode='lines', name='Amount of 4% Gainer', line=dict(color='blue'))
fig.add_trace(_4percent_line, row=4, col=1)

# EMA Breadth Chart
fig.add_trace(go.Scatter(x=_20EMA_Breadth_df.columns[0:250], y=_20EMA_Breadth_df.loc['Percent Above EMA', :].iloc[0:250], mode='lines', name='EMA20', line=dict(color='orange')), row=5, col=1)
fig.add_trace(go.Scatter(x=_50EMA_Breadth_df.columns[0:250], y=_50EMA_Breadth_df.loc['Percent Above EMA', :].iloc[0:250], mode='lines', name='EMA50', line=dict(color='red')), row=5, col=1)
fig.add_trace(go.Scatter(x=_200EMA_Breadth_df.columns[0:250], y=_200EMA_Breadth_df.loc['Percent Above EMA', :].iloc[0:250], mode='lines', name='EMA200', line=dict(color='purple')), row=5, col=1)

# Stacked bar chart for Advance Decline Unchanged Chart (Chart 6)
fig.add_trace(go.Bar(x=plot_data['Date'], y=plot_data['Decline%'], name='Decline%', marker_color='red'), row=6, col=1)
fig.add_trace(go.Bar(x=plot_data['Date'], y=plot_data['Unchanged%'], name='Unchanged%', marker_color='grey', base=plot_data['Decline%']), row=6, col=1)
fig.add_trace(go.Bar(x=plot_data['Date'], y=plot_data['Advance%'], name='Advance%', marker_color='green', base=plot_data['Unchanged%'] + plot_data['Decline%']), row=6, col=1)

# Update layout
fig.update_layout(xaxis_rangeslider_visible=False, height=2000, title_text="Thai StockMarket Market Breadth", xaxis=dict(type='category'))

图表示例

解决方法

这个问题的核心是子图共享X轴时,第一个蜡烛图的X轴默认是时间序列类型(type='date'),哪怕你全局设置了xaxis=dict(type='category'),共享轴的子图会继承第一个轴的类型,导致休市日期被自动填充出缺口。下面两种方法可以解决:

方法1:统一所有子图的X轴为类别类型

把所有子图的X轴数据都转成字符串格式,同时明确设置每个X轴的类型为category:

# 创建子图(保持原有配置)
fig = make_subplots(rows=6, cols=1, shared_xaxes=True, vertical_spacing=0.04)

# 把蜡烛图的日期转成字符串
data_feed_str_dates = data_feed.index.astype(str)
fig.add_trace(go.Candlestick(x=data_feed_str_dates, open=data_feed.open, high=data_feed.high, low=data_feed.low, close=data_feed.close), row=1, col=1)

# 其他子图的X轴数据也统一转成字符串(比如_52WksNHNL_df.columns等,要和plot_data的Date格式一致)
# 示例:_52WksNHNL_line的x参数修改为字符串日期
_52WksNHNL_line = go.Scatter(x=_52WksNHNL_df.columns[0:249].astype(str), y=_52WksNHNL_df.iloc[2, 0:250], mode='lines', name='52WksNewHighNewLow', line=dict(color='maroon'))
fig.add_trace(_52WksNHNL_line, row=2, col=1)

# ...其他子图都做类似修改...

# 最后更新布局,给所有X轴设置类别类型
fig.update_layout(
    xaxis_rangeslider_visible=False, 
    height=2000, 
    title_text="泰国股市市场宽度指标",
    xaxis=dict(type='category'),
    xaxis2=dict(type='category'),
    xaxis3=dict(type='category'),
    xaxis4=dict(type='category'),
    xaxis5=dict(type='category'),
    xaxis6=dict(type='category')
)

方法2:保留时间轴但跳过休市日期

如果想保留时间序列类型的X轴,直接设置rangebreaks跳过周末和法定节假日即可:

fig.update_layout(
    xaxis_rangeslider_visible=False, 
    height=2000, 
    title_text="泰国股市市场宽度指标",
    xaxis=dict(
        type='date',
        rangebreaks=[
            dict(bounds=['sat', 'mon']),  # 跳过周末
            # 手动添加泰国股市的法定节假日,比如宋干节等,根据实际日期调整
            dict(values=['2024-04-13', '2024-04-14', '2024-05-01'])
        ]
    )
)

这种方式适合需要保留时间刻度的场景,要是能通过API获取泰国股市的休市日历,还能自动生成values列表,不用手动维护。

注意事项

  • 所有共享X轴的子图,日期格式必须完全一致(要么全是datetime,要么全是字符串)
  • 共享轴时,全局的xaxis设置不会覆盖所有子轴,得单独指定每个xaxisN的参数

内容的提问来源于stack exchange,提问作者Phasin Opaspilai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:32:33