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

如何消除Oanda API股票历史数据绘图中的周末间隙?

解决Oanda API回测图表周末间隙问题

我是编程新手,正在基于Oanda API编写回测代码。绘图时图表出现周末间隙,但检查数据的index(time)并未包含周末数据,请问如何消除这些间隙?

数据图表

以下是我的代码:

class Backtester():
    def __init__(self, symbol, timeframe, SMA_S, SMA_L, start, end):
        self.symbol = symbol
        self.timeframe = timeframe
        self.SMA_S = SMA_S
        self.SMA_L = SMA_L
        self.start = start
        self.end = end
        self.results = None
        self.get_data()

    def get_data(self):
        api = tpqoa.tpqoa('oanda.cfg')
        raw = api.get_history(instrument = self.symbol, \
                              start = self.start, \
                              end = self.end, \
                              granularity = self.timeframe, \
                              price = 'B')
        # raw = raw.dropna(inplace =True)
        # raw.rename(column = {'c':'close'})
        raw['returns'] = np.log(raw['c'] / raw['c'].shift(1))
        raw['SMA_S'] = raw['c'].rolling(self.SMA_S).mean()
        raw['SMA_L'] = raw['c'].rolling(self.SMA_L).mean()
        raw.dropna(inplace = True)
        self.data = raw
        return raw

    def test_strategy(self):
        data = self.data.copy().dropna()
        data["position"] = np.where(data["SMA_S"] > data["SMA_L"], 1, -1)
        data["strategy"] = data["position"].shift(1) * data["returns"]
        data.dropna(inplace=True)
        data["creturns"] = data["returns"].cumsum().apply(np.exp)
        data["cstrategy"] = data["strategy"].cumsum().apply(np.exp)
        self.results = data
        
        perf = data["cstrategy"].iloc[-1] # absolute performance
        outperf = perf - data["creturns"].iloc[-1] # outperformance 
        return round(perf, 6), round(outperf, 6)

    def plot_data(self):
        data = self.data.copy().dropna()

        candle = go.Candlestick(x = data.index,\
                                open = data['o'],\
                                close = data['c'],\
                                high = data['h'],\
                                low = data['l'],
                                name = 'Candlestick')
        fsma = go.Scatter(x = data.index,\
                          y = data['SMA_S'],\
                          name = 'SMA Short',\
                          line = dict(color = ('rgba(102, 207, 255, 50)')))
        lsma = go.Scatter(x = data.index,\
                          y = data['SMA_L'],\
                          name = 'SMA Long',\
                          line = dict(color = ('rgba(102, 107, 255, 50)')))

        data = [candle, fsma, lsma]
        data = [candle]
        layout = go.Layout(title = self.symbol)
        fig = go.Figure(data = data, layout = layout)
        plot(fig, filename = self.symbol)

解决方法

出现间隙的核心原因是:Plotly的时间轴默认会自动填充时间序列中的缺失区间,哪怕你的数据里没有周末记录,它也会按连续时间逻辑绘制,从而产生空白间隙。可以通过两种方式解决:

方法1:使用rangebreaks跳过周末(推荐,保留时间轴特性)

修改plot_data方法中的layout,给x轴添加rangebreaks配置,明确指定跳过周六到周一的区间:

layout = go.Layout(
    title = self.symbol,
    xaxis=dict(
        rangebreaks=[
            dict(bounds=["sat", "mon"])  # 跳过周六至周一的空白间隙
            # 可选:添加特定节假日,比如 dict(values=["2024-01-01", "2024-12-25"])
        ]
    )
)

方法2:将x轴设为分类类型(简单但失去时间轴缩放特性)

直接把x轴类型改为category,让图表只渲染数据中实际存在的时间点:

layout = go.Layout(
    title = self.symbol,
    xaxis=dict(type='category')
)

修改后的完整plot_data方法示例(采用方法1):

def plot_data(self):
    data = self.data.copy().dropna()

    candle = go.Candlestick(x = data.index,\
                            open = data['o'],\
                            close = data['c'],\
                            high = data['h'],\
                            low = data['l'],
                            name = 'Candlestick')
    fsma = go.Scatter(x = data.index,\
                      y = data['SMA_S'],\
                      name = 'SMA Short',\
                      line = dict(color = ('rgba(102, 207, 255, 50)')))
    lsma = go.Scatter(x = data.index,\
                      y = data['SMA_L'],\
                      name = 'SMA Long',\
                      line = dict(color = ('rgba(102, 107, 255, 50)')))

    data = [candle, fsma, lsma]
    layout = go.Layout(
        title = self.symbol,
        xaxis=dict(
            rangebreaks=[dict(bounds=["sat", "mon"])]
        )
    )
    fig = go.Figure(data = data, layout = layout)
    plot(fig, filename = self.symbol)

内容的提问来源于stack exchange,提问作者Han J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:55:10