LoginSignup
13
20

More than 5 years have passed since last update.

plotlyでキャンドルチャートプロット

Last updated at Posted at 2017-04-12

下準備

サンプルデータの作成

np.random.seed(9)
from randomwalk import randomwalk
df = randomwalk(60 * 24 * 90, freq='T', tick=0.01, start=pd.datetime(2017, 3, 20)
                ).resample('B').ohlc() + 115  # 90日分の1分足を日足に直す

ランダムウォークの作成。
詳しくはpythonでローソク足(candle chart)の描画をご覧ください。

pd.DataFrame型をStockDataFrame型に変換

from stockstats import StockDataFrame
sdf = StockDataFrame(df.copy())

StockPlotクラスの使用方法

stockplot.pyのインポート

from stockplot import StockPlot
# StockPlotクラスのインスタンス化
x = StockPlot(sdf)
# キャンドルチャートのプロット
x.candle_plot()

graph1.png

キャンドルチャートが描かれました。

plotlyは基本的に画像をhtml形式で吐き出します。
マウスオーバーすると値が表示されたり、拡大縮小ができます。
わざわざgifファイルを作るのが面倒だったので、ここではpng形式で貼り付けております。

plotlyでぐりぐり動かせるグラフを見たい方は参考までにこちらをご覧ください。

Qiita - inoory様 - [Python] Plotlyでぐりぐり動かせるグラフを作る

指標

指標の追加

指標の追加はリスト型と同様にappendメソッドを使います。

# 終値25日移動平均線追加
x.append('close_25_sma')
2017-03-20    114.850000
2017-03-21    114.805000
2017-03-22    114.886667
2017-03-23    114.912500
2017-03-24    114.912000
2017-03-27    114.940000
2017-03-28    115.010000
2017-03-29    115.016250
2017-03-30    115.062222
2017-03-31    115.063000
2017-04-03    115.066364
2017-04-04    115.082500
2017-04-05    115.093846
2017-04-06    115.075714
2017-04-07    115.093333
2017-04-10    115.111250
2017-04-11    115.097059
2017-04-12    115.071111
2017-04-13    115.041579
2017-04-14    115.037000
2017-04-17    115.039048
2017-04-18    115.047273
2017-04-19    115.042609
2017-04-20    115.075417
2017-04-21    115.117200
2017-04-24    115.165600
2017-04-25    115.194000
2017-04-26    115.216800
2017-04-27    115.247600
2017-04-28    115.262800
                 ...    
2017-05-08    115.319600
2017-05-09    115.306800
2017-05-10    115.313600
2017-05-11    115.328400
2017-05-12    115.315600
2017-05-15    115.297600
2017-05-16    115.297600
2017-05-17    115.314800
2017-05-18    115.337600
2017-05-19    115.330000
2017-05-22    115.317200
2017-05-23    115.296000
2017-05-24    115.308800
2017-05-25    115.302000
2017-05-26    115.282800
2017-05-29    115.256800
2017-05-30    115.254000
2017-05-31    115.238000
2017-06-01    115.245200
2017-06-02    115.272800
2017-06-05    115.289600
2017-06-06    115.318400
2017-06-07    115.366000
2017-06-08    115.425600
2017-06-09    115.508400
2017-06-12    115.579200
2017-06-13    115.636800
2017-06-14    115.686800
2017-06-15    115.736000
2017-06-16    115.798000
Freq: B, Name: close_25_sma, dtype: float64

add_indicator関数の戻り値はStockDataFrameクラスでgetメソッドを使った時と同じ結果が返ってきます。

裏でplotly形式に直され、インスタンス変数self._figに追加されます。

# キャンドルチャートと追加された指標のプロット
x.candle_plot()

graph2.png

終値25日移動平均線が追加されました。

# 終値25日指数移動平均線の追加とプロット
x.append('close_25_ema')
x.candle_plot()

graph3.png

先ほど追加された終値25日移動平均線に加え、終値25日指数移動平均線が追加されました。

指標の削除

指標の削除はリストの削除と同様に'remove'メソッドを使います。

y = StockPlot(sdf)
# 10,11,12,13足移動平均線
for i in range(10, 14):
    y.append('close_{}_sma'.format(i))
y.candle_plot()

graph4.png

新たなインスタンスを作成し、10, 11, 12, 13足移動平均線を追加しました。

ここでは省略されていますが、remove戻り値は削除したStockDataFrameのカラムです。

# 10, 12足移動平均線の削除
for i in (10, 12):
    y.remove('close_{}_sma'.format(i))
y.candle_plot()

graph5.png

10足、12足移動平均線だけを指定して削除しました。

ファイルへのエクスポート

StockPlotクラスはPlotlyのhtmlエクスポートするplotly.offline.iplot(Jupyter Notebook形式)で図を吐き出します。
つまり、ファイルへのエクスポートがされません。

ファイルとして吐き出したいときは以下のメソッドを使います。

  • html形式: plotly.offline.plot(figure_or_data, filename=<拡張子htmlにしないとワーニング(勝手に拡張子つけられちゃう)>, )
  • png, svg, jpeg, webp形式: plotly.offline.plot(figure_or_data, image=<png|svg|jpeg|webp>, imagefilename=<拡張子抜きのファイル名>)
import plotly.offline as pyo
pyo.plot(y._fig, filename='candle_y.html', validate=False)  # 新しいタブを開いてhtml表示します
pyo.plot(y._fig, image='png', image_filename='candle_y')
# 新しいtmpタブを開いて
# imageに指定した拡張子として
# デフォルトのダウンロードディレクトリに保存します

パッケージ紹介

Plotly

グラフ描画はPlotlyに行わせます。
簡単なことだったら無料で使えます。

インストールは

conda install plotly

または

pip install plotly

有名だと思うのでここでは言及しません。

stockstats

データ操作はstockstatsというパッケージを使います。

インストールは

pip install stockstats

stockstatsは金融指標を簡単に取得できる改造pandas.DataFrameクラスです。

# 使い方
np.random.seed(2)
df = pd.DataFrame(np.random.randn(10,4), columns=['open', 'high', 'low', 'close'])
from stockstats import StockDataFrame
sdf = StockDataFrame(df)  # pandasデータフレームをStockDataFrameに入れてあげる
sdf
open high low close
0 -0.416758 -0.056267 -2.136196 1.640271
1 -1.793436 -0.841747 0.502881 -1.245288
2 -1.057952 -0.909008 0.551454 2.292208
3 0.041539 -1.117925 0.539058 -0.596160
4 -0.019130 1.175001 -0.747871 0.009025
5 -0.878108 -0.156434 0.256570 -0.988779
6 -0.338822 -0.236184 -0.637655 -1.187612
7 -1.421217 -0.153495 -0.269057 2.231367
8 -2.434768 0.112727 0.370445 1.359634
9 0.501857 -0.844214 0.000010 0.542353

見た目に変化はありませんが金融指標をstockstatsの文法に従ってgetメソッド、またはディクショナリの取得をすると、金融指標のカラムが追加されます。

sdf.get('close_5_sma'); sdf
open high low close close_5_sma
0 -0.416758 -0.056267 -2.136196 1.640271 1.640271
1 -1.793436 -0.841747 0.502881 -1.245288 0.197491
2 -1.057952 -0.909008 0.551454 2.292208 0.895730
3 0.041539 -1.117925 0.539058 -0.596160 0.522758
4 -0.019130 1.175001 -0.747871 0.009025 0.420011
5 -0.878108 -0.156434 0.256570 -0.988779 -0.105799
6 -0.338822 -0.236184 -0.637655 -1.187612 -0.094264
7 -1.421217 -0.153495 -0.269057 2.231367 -0.106432
8 -2.434768 0.112727 0.370445 1.359634 0.284727
9 0.501857 -0.844214 0.000010 0.542353 0.391392

close_5_sma: 終値の5足移動平均線が追加されました。

sdf['close_5_sma']; sdf
open high low close close_5_sma
0 -0.416758 -0.056267 -2.136196 1.640271 1.640271
1 -1.793436 -0.841747 0.502881 -1.245288 0.197491
2 -1.057952 -0.909008 0.551454 2.292208 0.895730
3 0.041539 -1.117925 0.539058 -0.596160 0.522758
4 -0.019130 1.175001 -0.747871 0.009025 0.420011
5 -0.878108 -0.156434 0.256570 -0.988779 -0.105799
6 -0.338822 -0.236184 -0.637655 -1.187612 -0.094264
7 -1.421217 -0.153495 -0.269057 2.231367 -0.106432
8 -2.434768 0.112727 0.370445 1.359634 0.284727
9 0.501857 -0.844214 0.000010 0.542353 0.391392

sdf.get('close_5_sma')と全く同じです。
getの方がありえない指標を打ち込んだときエラーが発生しません。
どちら良いかは用途次第でしょう。

指標できる指標は以下の通りです。

  • change (in percent)
  • delta
  • permutation (zero based)
  • log return
  • max in range
  • min in range
  • middle = (close + high + low) / 3
  • SMA: simple moving average
  • EMA: exponential moving average
  • MSTD: moving standard deviation
  • MVAR: moving variance
  • RSV: raw stochastic value
  • RSI: relative strength index
  • KDJ: Stochastic oscillator
  • Bolling: including upper band and lower band.
  • MACD: moving average convergence divergence. Including signal and histogram.
  • CR:
  • WR: Williams Overbought/Oversold index
  • CCI: Commodity Channel Index
  • TR: true range
  • ATR: average true range
  • line cross check, cross up or cross down.
  • DMA: Different of Moving Average (10, 50)
  • DMI: Directional Moving Index, including
  • +DI: Positive Directional Indicator
  • -DI: Negative Directional Indicator
  • ADX: Average Directional Movement Index
  • ADXR: Smoothed Moving Average of ADX
  • TRIX: Triple Exponential Moving Average
  • VR: Volatility Volume Ratio

詳しくは公式をご覧ください。

stockplot

私が作ったやつです。
stockstatsを楽にplotするためのクラスStockPlotを作成しました。

stockplot.pyのソースコード

import numpy as np
import pandas as pd
# ----------User Module----------
from randomwalk import randomwalk
import stockstats as ss
# ----------Plotly Module----------
from plotly.tools import FigureFactory as FF
import plotly.offline as pyo
import plotly.graph_objs as go
pyo.init_notebook_mode(connected=True)


class StockPlot:
    """StockDataFrameの可視化ツール
    # TODO
    * heikin_plot
    * pop
    * subplot
    """

    def __init__(self, sdf: ss.StockDataFrame):
        self.StockDataFrame = sdf
        self._fig = FF.create_candlestick(self.StockDataFrame.open,
                                         self.StockDataFrame.high,
                                         self.StockDataFrame.low,
                                         self.StockDataFrame.close,
                                         dates=self.StockDataFrame.index)

    def candle_plot(self, filebasename='candlestick_and_trace'):
        """StockDataFrameをキャンドルチャート化する
        引数: dfs: StockDataFrame
        戻り値: plotly plot"""
        self._fig['layout'].update(xaxis={'showgrid': True})
        ax = pyo.iplot(self._fig, filename=filebasename + '.html', validate=False)
        # pyo.plot(self._fig, image='png', image_filename=filebasename, validate=False)
        return ax

    def append(self, indicator):
        indi = self.StockDataFrame.get(indicator)
        plotter = go.Scatter(x=indi.index, y=indi,
                             name=indicator.upper().replace('_', ' '))  # グラフに追加する形式変換
        self._fig['data'].append(plotter)
        return indi

    def remove(self, indicator):
        indi = indicator.lower().replace(' ', '_')
        INDI = indicator.upper().replace('_', ' ')
        rem = self.StockDataFrame.pop(indi)
        for dicc in self._fig['data']:
            if dicc['name'] == INDI:
                self._fig['data'].remove(dicc)
                return rem

github
u1and0/stockplot

NEXT
Plotlyでぐりぐり動かせる為替チャートを作る(1)

13
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
20