plotlyでローソク足とインジケータの両方表示する方法

「Pythonでローソク足の表示方法」でplotlyを使ったローソク足を表示できるようになりました。

例えば、移動平均等のインジケータを同時に表示するにはどうしたらよいか?

その方法を調べたので、その結果を記事にします。

インジケータのデータを作成する

まず、ヒストリカルデータは、「PythonでFXのヒストリカルデータ分析 導入編」で作成したticksを使います。
ただし、長いので、3時間分だけ切り取りって使います。

>>> df = ticks[60:240]
>>> df.head(5)
                        open     high      low    close
t                                                      
2018-03-12 01:01:00  1.23090  1.23093  1.23090  1.23092
2018-03-12 01:02:00  1.23090  1.23105  1.23090  1.23103
2018-03-12 01:03:00  1.23103  1.23123  1.23103  1.23123
2018-03-12 01:04:00  1.23123  1.23125  1.23122  1.23122
2018-03-12 01:05:00  1.23122  1.23122  1.23102  1.23102

次に、やりたかった単純移動平均のインジケータのヒストリカルデータを作ります。

移動平均は、終値(df.close)で作成します。旧来はpd.rolling_meanで作ってましたが、Series.rollingができたので、こちら(Series)を使うようにしましょう。
わかりやすいように期間10分の移動平均(sma10)を計算します。

# 期間10分の移動平均を計算
>>> sma10 = df.close.rolling(window=10).mean()

# 戻りのデータタイプはSeries
>>> type(sma10)
<class 'pandas.core.series.Series'>

# 値はこんな感じ
>>> sma10.head(5)
t
2018-03-12 01:01:00   NaN
2018-03-12 01:02:00   NaN
2018-03-12 01:03:00   NaN
2018-03-12 01:04:00   NaN
2018-03-12 01:05:00   NaN
Name: close, dtype: float64

ローソク足の表示方法の振り返り

まず、インジケータを追加表示するために、「Pythonでローソク足の表示方法」の手順で何をしていたのか理解します。
何を作成していたのか見てみます。

# ローソク足の図を作る
>>> fig = plotly.figure_factory.create_candlestick(df.open, df.high, df.low, df.close, dates=df.index)

# オフラインで描画するために、htmlを作成する
>>> plotly.offline.plot(fig, filename='work')

plotの引数へ渡しているのは、figだけですので、figに情報が詰め込まれているようです。
なので、figが何か調べてみました。

# figの型は?
>>> type(fig)
<class 'plotly.graph_objs.graph_objs.Figure'>

# どんな属性がある?
>>> dir(fig)
['data', 'frames', 'layout']

# 属性の中身どうなっている?
>>> fig.data
[{'y': [1.2309, 1.2309, 1.23092, 1.23092, 1.23092, 1.2309299999999999, ... # 長いので省略
>>> fig.frames
[]
>>> fig.layout
{}

属性を見ると、[‘data’, ‘frames’, ‘layout’]あり、create_candlestickでは、データを作っているだけでした。

dataは出力内容を見るとData型ですがシーケンスIFを持っていて、更にシーケンスの要素はディクショナリに近いようです。

# dataの要素はPlotlyDict型でディクショナリと同じkeys()がある。
>>> type(fig.data[0])
<class 'plotly.graph_objs.graph_objs.PlotlyDict'>
>>> fig.data[0].keys()
dict_keys(['y', 'whiskerwidth', 'x', 'type', 'line', 'showlegend', 'boxpoints', 'name', 'fillcolor'])

では、create_candlestickの結果のdata:Dataの要素が、なぜ2つあるのか?想像できるかと思いますが、中身を見てみます。

>>> fig.data[0].name, fig.data[0].fillcolor
('Increasing', '#3D9970')
>>> fig.data[1].name, fig.data[1].fillcolor
('Decreasing', '#FF4136')

Dataには、陽線と陰線の2つ分けて入っていました。なんか見たことあるなと思ったんですが、「Bokehのローソク足」のデータの持ち方と似てますね。

調査はここまでにして、本筋のインジケータのグラフを追加する方法を考えると、create_candlestickの戻りのfigのdataに追加してやれば良さそうです。

ここまでの結果から以下と推測しました。

  • plotly.figure_factory.create_candlestick は高級関数でdataとlayoutとかをパックで作ってくれる
  • このdataにローソク足のdata[0]に近いプロットデータを作って追加してからplotすれば良さそう

インジケータのプロットデータを作る

今回のインジケータ:移動平均のグラフは、ただの折れ線グラフなので、ネットにサンプルいっぱいあります。でも調べた結果Lineじゃないんですね。plotly.graph_objs.Scatterでした。

とりあえず、オプションはあまり考えず、Scatterを作ってみます。

# 作成してみる
>>> fig_data_sma10 = plotly.graph_objs.Scatter(x=sma10.index, y=sma10.values, mode='lines', name='sma10')

# 型はそのままScatter
>>> type(fig_data_sma10)
<class 'plotly.graph_objs.graph_objs.Scatter'>

# 中身はディクショナリに近い
>>> fig_data_sma10
{'type': 'scatter', 'mode': 'lines', 'y': array([     nan,      nan,      nan,      nan,      nan,      nan,
            nan,      nan,      nan, 1.231112, 1.231145, 1.231151,
       1.231137, 1.23112 , 1.231117, 1.231118, 1.231106, 1.231074,

# 親クラスを見るとPlotlyDict
>>> plotly.graph_objs.graph_objs.Scatter.__bases__
(<class 'plotly.graph_objs.graph_objs.PlotlyDict'>,)

最後の型がPlotlyDictであることが重要で、先程調査したcreate_candlestickの結果のfig.dataの要素になっていたものを同じです。
ということは、そこに追加して良さそうです。

先程の推測に、今回の結果を追加します。

  • plotly.figure_factory.create_candlestick は高級関数でdataとlayoutとかをパックで作ってくれる
  • plotly.graph_objs.*の各グラフオブジェクトはdataの要素にできる
  • このdataにローソク足のdata[0]に近いプロットデータを作って追加してからplotすれば良さそう

ローソク足とインジケータの両方プロットしてみる

これまでの結果を踏まえ、ローソク足(df)と移動平均(sma10)を重ねて表示する手順は下記です。

# ローソク足の図を作る
>>> fig = plotly.figure_factory.create_candlestick(df.open, df.high, df.low, df.close, dates=df.index)

# 移動平均のグラフオブジェクトを作る
>>> fig_data_sma10 = plotly.graph_objs.Scatter(x=sma10.index, y=sma10.values, mode='lines', name='sma10')

# 図に移動平均のオブジェクトを追加
>>> fig.data.append(fig_data_sma10)

# オフラインで描画するために、htmlを作成する
>>> plotly.offline.plot(fig, filename='work')

結果のhtmlは「fx_plotly_indicator.html」 (ファイル名変えました、サイズ大きいです2MB)

画像だとこんな感じです。

plotlyで重ねて表示

検証まとめ記事へのリンク

システムトレードの他のネタを纏めています。参考になれば嬉しいです。

↓↓↓検証まとめページはこちら↓↓↓
【保存版】PythonでのFXのシステムトレード検証

シェアする

  • このエントリーをはてなブックマークに追加

フォローする