如何从财务图表的 x 轴删除周末日期时间差距?

How to remove weekend datetime gaps from x-axis of a financial chart?

我有一个用例,我在图表上以 ask and bid 的形式提取和绘制 Forex 数据,这是基于 minute, hour or day candlesticks 并且我只绘制 closing bid and ask 的值作为 spline

问题

我正在使用其 Forex 数据馈送的端点在 Friday 8pmSunday 9pm 期间不可用。假设我有以下用例

x-axis 上的 datetime 没有任何间隙时,该图是 prettysmooth。蜡烛时间戳以以下形式返回

2018-06-29T16:00:00.000000000Z
2018-06-29T17:00:00.000000000Z
2018-06-29T19:00:00.000000000Z
2018-06-29T20:00:00.000000000Z (Friday last candle 8pm)
2018-07-01T21:00:00.000000000Z (Sunday first candle 9pm) 
2018-07-01T22:00:00.000000000Z
2018-07-01T23:00:00.000000000Z
2018-07-02T00:00:00.000000000Z

一旦存在间隙(大约 47-49 hours),所有内容都会被压缩以适应图表的拉伸部分,如下所示(使用 plotly.js

大多数情况下,财务图表不会显示差距。例如,查看 TradingView 交互式图表,您将看到 weekend

的以下内容

如果您知道如何使用开源图表库(不包括 TradingView)解决此问题,请分享您的解决方案。

TL;DR

根据我的发现,您可以使用 Highcharts 库的 HighStock 排除间隙。 Highcharts 是开源的,仅供 Non-commercial 免费使用,有关详细信息,请参阅 highcharts licensing

plotly.js

我最初是从 plotly.js 开始的,因为老实说,它确实是一个非常好的图表库。在 x-axis 上遇到 datetime gap 问题(参见相关屏幕截图)后,我研究了解决方案并遇到了以下问题

https://community.plot.ly/t/tickformat-without-weekends/1286/5 (forum)

https://github.com/plotly/plotly.js/issues/1382 (locked github thread)

https://community.plot.ly/t/x-axis-without-weekends/1091/2

根据上面的 Github 问题 link,x-axisdatetime 的处理方式目前无法实现。有解决方法(如上面的第 3 个 link)但是,我尝试了一些但它要么不起作用,要么我丢失了一些信息。

我得出的结论是,尽管 plotly 是一个很棒的图书馆,但在这种情况下它根本无法帮助我。如果您认为可以,请分享您的解决方案:)

C3.js

在对图表库进行更多研究后,我尝试 C3.js 并在使用 datetime 为 x 轴编辑他们的现场演示示例后,我观察到相同的周末间隙问题(见下文)

我没有费心去研究为什么,这可能是因为像 plotly.js 一样基于 D3.js。如果您认为 C3.js 可以解决日期时间差距,那么请随时分享您的解决方案。

Highcharts

我终于遇到了 Highxxxxx 图表库系列,乍一看它非常漂亮,并提供了我想要的所有功能。我尝试了 Highchart,但我遇到了同样的周末间隙问题

好吧,我开始认为唯一的解决方案是 NOT TO PLOT x-axis 中的 datetime 并以某种方式在 tooltip 中显示日期时间,这似乎完成如下所示的工作

但是,由于太固执而不能放弃,我继续我的研究。我真的很想像 TradingView 和其他股票可视化那样完成图表。

我决定做更多的研究,我几乎不知道我是如此接近同一个图表库 Highcharts 的解决方案,它被称为 HighStock

Highcharts 的 Highstock

HighStock 默认情况下处理间隙,如下所示

我用了下面这一段Javascript

  Highcharts.setOptions({
    global: {
      useUTC: false
    }
  });

  Highcharts.StockChart('chart', {
    chart: {
        type: 'spline',
        events: {
            load: function () {
              console.log('Highcharts is Loaded! Creating a reference to Chart dom.')

              //store a reference to the chart to update the data series
              var index=$("#chart").data('highchartsChart');
              highchartRef = Highcharts.charts[index]; //global var

              //Initiating the data pull here
            }
        }
    },
    title: {
        text: 'Chart title'
    },
    series: [
      {
        name: 'Ask',
        data: [],
        tooltip: {
            valueDecimals: 7
        },
        marker: {
          enabled: true
        }
      },
      {
        name: 'Bid',
        data: [],
        tooltip: {
            valueDecimals: 7
        },
        marker: {
          enabled: true
        }
      }
    ]
  });

你有它,一个无缝的(不确定它是否是一个真实的词)财务图表,带有 datetime x 轴的财务数据。

我没试过的库

我研究过但没有尝试以下图表库

  • Google 图表(由于未知原因感觉不对)
  • Chartist(没有看到很多交互性和财务相关的图表类型和示例
  • Chartjs(与 Chartist 相同)
  • TradingView(看完他们的使用条款后我放弃了——奇怪的条款,我的观点)
  • 大多数其他人缺乏文档、交互性、财务相关图表的水平,例如 PlotlyHighcharts

最终想法

我发现 Highcharts

  1. 有据可查
  2. 大量 jsfiddles 示例
  3. 很多有用的 SO 答案
  4. 漂亮又实用
  5. 多种选择
  6. 易于使用

gaps

相关的类似 SO 问题

How can I hide data gaps in plotly?

HighCharts datetime xAxis without missing values (weekends)(Highcharts)

(蜡烛图,枪图)

(c3/d3 - 小提琴不工作所以很难看到解决方案)

(c3.js - 差距有点差距)

使用类别作为 xaxis 类型非常适合我(注意 go.Layout 对象):

    import plotly.graph_objects as go

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

    fig = go.Figure(data=[go.Candlestick(x=self.price_df.index.to_series(),
                                         open=self.price_df[e.OHLCV.OPEN.value],
                                         high=self.price_df[e.OHLCV.HIGH.value],
                                         low=self.price_df[e.OHLCV.LOW.value],
                                         close=self.price_df[e.OHLCV.CLOSE.value])],
                    layout=layout)

    fig.show()

根据documentation

尝试在 fig.show()

之前添加这个
fig.update_xaxes(
    rangebreaks=[
        dict(bounds=["sat", "sun"]), #hide weekends
    ]
)

fig.layout.xaxis.type = 'category'

Plotly 现在支持借助范围突破在图表中隐藏周末和假期。检查此 link:https://plotly.com/python/time-series/ 转到部分:“隐藏周末和假期”

下面是从 link 复制的部分,示例适用于 plotly.express,但它也适用于 plotly.graph_objects

隐藏周末和假期 日期类型的 x 轴和 y 轴上可用的 rangebreaks 属性可用于隐藏某些时间段。在下面的示例中,我们展示了两个图表:一个在默认模式下显示数据中的缺口,另一个我们隐藏周末和假期以显示不间断的交易历史。请注意 12 月 21 日和 1 月 4 日的网格线之间的差距较小,其中假期被删除。查看参考以获取更多选项:https://plotly.com/python/reference/#layout-xaxis-rangebreaks

import plotly.express as px
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig = px.scatter(df, x='Date', y='AAPL.High', range_x=['2015-12-01', '2016-01-15'],
                 title="Default Display with Gaps")
fig.show()

无间隙显示

import plotly.express as px
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig = px.scatter(df, x='Date', y='AAPL.High', range_x=['2015-12-01', '2016-01-15'],
                 title="Hide Gaps with rangebreaks")
fig.update_xaxes(
    rangebreaks=[
        dict(bounds=["sat", "mon"]), #hide weekends
        dict(values=["2015-12-25", "2016-01-01"])  # hide Christmas and New Year's
    ]
)
fig.show()

首先,无需退出 Plotly。使用 rangebreaks 确实是要使用的工具,但这只是它的一方面。我这样说是因为对于股票数据来说,与数值相比,界限并不实用,但你会为每年的许多假期指定日期,而且大多数假期从一年到另一年都在变化。因此,使用 rangebreaks 的值并为其提供一个列表,其中包含您正在加载的 CSV 文件中没有的每个日期。如果您需要更大的推动力来解决这个问题,我的意思是将“日期”列放在一边,遍历它,并附加另一个列表中不存在的日期。然后你可以去 fig.update_xaxes(rangebreaks=[dict(values=mylistofdates)]) 希望这能让你回到 Plotly!

要使用 plotly 从财务数据中删除周末等空列,请使用以下代码。

代码-

import plotly.express as px


#Daily Percentage change in Nifty 50 Index
daily_returns = np.log(1+df_close.pct_change())*100

fig = px.bar(daily_returns,y = "Close", orientation='v')
fig.update_xaxes( rangeslider_visible=True, rangebreaks=[
        dict(bounds=["sat", "mon"]), #hide weekends
    ])
fig.update_layout(
    title='Nifty 50 Daily Returns in %',
    yaxis_title='Daily % Change')
fig.update_layout( xaxis_tickformat = ' %d %B (%a)<br> %Y')

fig.show()

快照-