Help us understand the problem. What is going on with this article?

# pythonでローソク足(candle chart)の描画

More than 1 year has passed since last update.

# matplotlib.financeでローソク足

## データの作成

ランダムウォークで架空の為替チャートを作成します。

```import numpy as np
import pandas as pd

def randomwalk(periods=None, start=None, end=None, freq='B', tz=None,
normalize=False, name=None, closed=None, tick=1, **kwargs):
"""Returns random up/down pandas Series.

Usage:
```
import datetime
randomwalk(100)  # Returns +-1up/down 100days from now.
randomwalk(100, freq='H')  # Returns +-1up/down 100hours from now.
randomwalk(100, ,tick=0.1 freq='S')  # Returns +-0.1up/down 100seconds from now.
randomwalk(100, start=datetime.datetime.today())  # Returns +-1up/down 100days from now.
randomwalk(100, end=datetime.datetime.today())
# Returns +-1up/down back to 100 days from now.
randomwalk(start=datetime.datetime(2000,1,1), end=datetime.datetime.today())
# Returns +-1up/down from 2000-1-1 to now.
randomwalk(100, freq='H').resample('D').ohlc()  # random OHLC data
```

Args:
periods: int
start: start time (default datetime.now())
end: end time
freq: ('M','W','D','B','H','T','S') (default 'B')
tz: time zone
tick: up/down unit size (default 1)

Returns:
pandas Series with datetime index
"""
if not start and not end:
start = pd.datetime.today().date()  # default arg of `start`
index = pd.DatetimeIndex(start=start, end=end, periods=periods, freq=freq, tz=tz,
normalize=normalize, name=name, closed=closed, **kwargs)
bullbear = pd.Series(tick * np.random.randint(-1, 2, len(index)),
index=index, name=name, **kwargs)  # tick * (-1,0,1のどれか)
price = bullbear.cumsum()  # 累積和
return price
```
```np.random.seed(1)  # ランダムステートのリセット。常に同じランダムウォークが出来上がる
rw = randomwalk(60*24*90, freq='T', tick=0.01)
```
```2017-03-19 00:00:00    0.00
2017-03-19 00:01:00   -0.01
2017-03-19 00:02:00   -0.02
2017-03-19 00:03:00   -0.02
2017-03-19 00:04:00   -0.02
Freq: T, dtype: float64
```
```rw.plot()
```

```df = rw.resample('B').ohlc() + 115  # 初期値は115円
```
open high low close
2017-03-17 115.00 115.38 114.76 115.36
2017-03-20 115.37 115.49 115.03 115.15
2017-03-21 115.14 115.69 115.07 115.65
2017-03-22 115.66 116.22 115.64 116.21
2017-03-23 116.20 116.47 115.93 116.11

resampleメソッド使って平日のみの日足(オプション how='B')に直し、open, high, low, closeの4本値(ohcl)にまとめました。

```df.plot()
```

4本値グラフは上のように見づらいので、ローソク足に直します。

## 参考1

```import numpy as np
import matplotlib.pyplot as plt
import matplotlib.finance as mpf
from matplotlib import ticker
import matplotlib.dates as mdates
import pandas as pd

def candlechart(ohlc, width=0.8):
"""入力されたデータフレームに対してローソク足チャートを返す
引数:
* ohlc:
*データフレーム
* 列名に'open'", 'close', 'low', 'high'を入れること
* 順不同"
* widrh: ローソクの線幅
戻り値: ax: subplot"""
fig, ax = plt.subplots()
# ローソク足
mpf.candlestick2_ohlc(ax, opens=ohlc.open.values, closes=ohlc.close.values,
lows=ohlc.low.values, highs=ohlc.high.values,
width=width, colorup='r', colordown='b')

# x軸を時間にする
xdate = ohlc.index
ax.xaxis.set_major_locator(ticker.MaxNLocator(6))

def mydate(x, pos):
try:
return xdate[int(x)]
except IndexError:
return ''

ax.xaxis.set_major_formatter(ticker.FuncFormatter(mydate))
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')

fig.autofmt_xdate()
fig.tight_layout()

return fig, ax

candlechart(df)
```
```(<matplotlib.figure.Figure at 0x207a86dd080>,
<matplotlib.axes._subplots.AxesSubplot at 0x207a6a225c0>)
```

## 参考2

```import numpy as np
import matplotlib.pyplot as plt
import matplotlib.finance as mpf
from matplotlib import ticker
import matplotlib.dates as mdates
import pandas as pd

fig = plt.figure()
ax = plt.subplot()

ohlc = np.vstack((range(len(df)), df.values.T)).T #x軸データを整数に
mpf.candlestick_ohlc(ax, ohlc, width=0.8, colorup='r', colordown='b')

xtick0 = (5-df.index[0].weekday())%5 #最初の月曜日のインデックス

plt.xticks(range(xtick0,len(df),5), [x.strftime('%Y-%m-%d') for x in df.index][xtick0::5])
ax.grid(True) #グリッド表示
ax.set_xlim(-1, len(df)) #x軸の範囲
fig.autofmt_xdate() #x軸のオートフォーマット
```

## SMA(Simple Moving Average)の追加

```import matplotlib.pyplot as plt
import matplotlib.finance as mpf
from randomwalk import *

fig = plt.figure()
ax = plt.subplot()

# candle
ohlc = np.vstack((range(len(df)), df.values.T)).T  # x軸データを整数に
mpf.candlestick_ohlc(ax, ohlc, width=0.8, colorup='r', colordown='b')

# sma
sma = df.close.rolling(5).mean()
vstack = np.vstack((range(len(sma)), sma.values.T)).T  # x軸データを整数に
ax.plot(vstack[:, 0], vstack[:, 1])

# xticks
xtick0 = (5 - df.index[0].weekday()) % 5  # 最初の月曜日のインデックス
plt.xticks(range(xtick0, len(df), 5), [x.strftime('%Y-%m-%d') for x in df.index][xtick0::5])
ax.grid(True)  # グリッド表示
ax.set_xlim(-1, len(df))  # x軸の範囲
fig.autofmt_xdate()  # x軸のオートフォーマット
plt.show()

```

```import matplotlib.pyplot as plt
import matplotlib.finance as mpf

def sma(ohlc, period):
sma = ohlc.close.rolling(period).mean()
vstack = np.vstack((range(len(sma)), sma.values.T)).T  # x軸データを整数に
return vstack

fig = plt.figure()
ax = plt.subplot()

# candle
ohlc = np.vstack((range(len(df)), df.values.T)).T  # x軸データを整数に
mpf.candlestick_ohlc(ax, ohlc, width=0.8, colorup='r', colordown='b')

# sma
sma5 = sma(df, 5)
sma25 = sma(df, 25)
ax.plot(sma5[:, 0], sma5[:, 1])
ax.plot(sma25[:, 0], sma25[:, 1])

# xticks
xtick0 = (5 - df.index[0].weekday()) % 5  # 最初の月曜日のインデックス
plt.xticks(range(xtick0, len(df), 5), [x.strftime('%Y-%m-%d') for x in df.index][xtick0::5])
ax.grid(True)  # グリッド表示
ax.set_xlim(-1, len(df))  # x軸の範囲
fig.autofmt_xdate()  # x軸のオートフォーマット
plt.show()

```

# plotlyでローソク足

## plotlyの練習

`conda install plotly`

でインストールして以下のようにインポートします。

アカウントを作る必要あるやらないやら情報がいろいろありますが、規制緩和されて、今では無料である程度やりたい放題みたいです。

```import plotly as py
py.offline.init_notebook_mode(connected=False)
```

```fo = [[2000,1190547,1.36],
[2001,1170662,1.33],
[2002,1153855,1.32],
[2003,1123610,1.29],
[2004,1110721,1.29],
[2005,1062530,1.26],
[2006,1092674,1.32],
[2007,1089818,1.34],
[2008,1091156,1.37],
[2009,1070035,1.37],
[2010,1071304,1.39],
[2011,1050806,1.39],
[2012,1037101,1.41],
[2013,1029816,1.43],
[2014,1003532,1.42],
[2015,1005656,1.46]]
raw = pd.DataFrame(fo, columns=['year', 'births', 'birth rate'])
raw
```
year births birth rate
0 2000 1190547 1.36
1 2001 1170662 1.33
2 2002 1153855 1.32
3 2003 1123610 1.29
4 2004 1110721 1.29
5 2005 1062530 1.26
6 2006 1092674 1.32
7 2007 1089818 1.34
8 2008 1091156 1.37
9 2009 1070035 1.37
10 2010 1071304 1.39
11 2011 1050806 1.39
12 2012 1037101 1.41
13 2013 1029816 1.43
14 2014 1003532 1.42
15 2015 1005656 1.46
```data = [
py.graph_objs.Scatter(y=raw["births"], name="births"),
]
layout = py.graph_objs.Layout(
title="title",
legend={"x":0.8, "y":0.1},
xaxis={"title":""},
yaxis={"title":""},
)
fig = py.graph_objs.Figure(data=data, layout=layout)
```

```data = [
py.graph_objs.Bar(x=raw["year"], y=raw["births"], name="Births"),
py.graph_objs.Scatter(x=raw["year"], y=raw["birth rate"], name="Birth Rate", yaxis="y2")
]
layout = py.graph_objs.Layout(
title="Births and Birth Rate in Japan",
legend={"x":0.8, "y":0.1},
xaxis={"title":"Year"},
yaxis={"title":"Births"},
yaxis2={"title":"Birth Rate", "overlaying":"y", "side":"right"},
)
fig = py.graph_objs.Figure(data=data, layout=layout)
py.offline.iplot(fig)
#py.offline.plot(fig)
```

• マウスオーバーで数値の表示
• ドラッグで拡大
• ダブルクリックで元のビューに戻る

## 為替チャート

```from plotly.offline import init_notebook_mode, iplot
from plotly.tools import FigureFactory as FF
init_notebook_mode(connected=True) # Jupyter notebook用設定
```

### 通常のプロット

candleチャートの関数が用意されているので、open, high, low, closeのデータが用意できればローソク足のグラフは簡単に作成できます。

ただし、平日のみの表示ができません。土日も表示されます。

```fig = FF.create_candlestick(df.open, df.high, df.low, df.close, dates=df.index)
py.offline.iplot(fig)
```

### 平日のみのプロット

```fig = FF.create_candlestick(df.open, df.high, df.low, df.close)

xtick0 = (5-df.index[0].weekday())%5 #最初の月曜日のインデックス
fig['layout'].update({
'xaxis':{
'showgrid': True,↔
'ticktext': [x.strftime('%Y-%m-%d') for x in df.index][xtick0::5],
'tickvals': np.arange(xtick0,len(df),5)
}
})

py.offline.iplot(fig)
```

## 指標の追加

```def sma(data, window, columns='close'):
return data[columns].rolling(window).mean()

sma5 = sma(df, 5)
```
```fig = FF.create_candlestick(df.open, df.high, df.low, df.close, dates=df.index)

add_line = Scatter( x=df.index,  y=df.close,  name= 'close values',
line=Line(color='black'))
↔
py.offline.iplot(fig, filename='candlestick_and_trace', validate=False)
```

```from plotly.graph_objs import *
fig = FF.create_candlestick(df.open, df.high, df.low, df.close, dates=df.index)
add_line = [Scatter(x=df.index, y=df.close.rolling(5).mean(), name='SMA5', line=Line(color='r')),
Scatter(x=df.index, y=df.close.rolling(15).mean(), name='SMA15', line=Line(color='b')),
Scatter(x=df.index, y=df.close.rolling(25).mean(), name='SMA25', line=Line(color='g'))]
↔
fig['layout'].update({'xaxis':{'showgrid': True}})

py.offline.iplot(fig, filename='candlestick_and_trace', validate=False)
```

## SMA, EMA比較

```np.random.seed(10)
ra = randomwalk(60*24*360, freq='T', tick=0.01) + 115
df1 = ra.resample('B').ohlc()
```
```import plotly.graph_objs as go
fig = FF.create_candlestick(df1.open, df1.high, df1.low, df1.close, dates=df1.index)
add_line = [go.Scatter(x=df1.index, y=df1.close.rolling(75).mean(), name='SMA75', line=Line(color='r')),
go.Scatter(x=df1.index, y=df1.close.ewm(75).mean(), name='EMA75', line=Line(color='b'))]

fig['layout'].update({'xaxis':{'showgrid': True}})

py.offline.iplot(fig, filename='candlestick_and_trace', validate=False)
```

```import plotly.graph_objs as pyg
from datetime import datetime

def to_unix_time(*dt):
"""datetimeをunix秒に変換
引数: datetimeの入ったリスト
戻り値: unix秒に直されたリスト"""
epoch =  datetime.utcfromtimestamp(0)
ep = [(i - epoch).total_seconds() * 1000 for i in list(*dt)]
return ep

fig = FF.create_candlestick(df1.open, df1.high, df1.low, df1.close, dates=df1.index)
add_line = [pyg.Scatter(x=df1.index, y=df1.close.rolling(75).mean(), name='SMA75', line=Line(color='r')),
pyg.Scatter(x=df1.index, y=df1.close.ewm(75).mean(), name='EMA75', line=Line(color='b')),
pyg.Scatter(x=df1.index, y=df1.close.rolling(75).mean(), name='SMA75', mode='markers'),
pyg.Scatter(x=df1.index, y=df1.close.ewm(75).mean(), name='EMA75', mode='markers')]

fig['layout'].update(xaxis = {'showgrid': True,
'type': 'date',
'range':to_unix_time([datetime(2017,9,1), datetime(2018,1,1)])})  # レイアウトの変更

py.offline.iplot(fig, filename='candlestick_and_trace', validate=False)
```

ちなみに参考の人がやっていたようにlayoutでxaxisを無理やり平日だけにするとSAM, EMAがプロットされなくなりました。
これは休日をなくすべくxaxisをstringとfloatに無理やり直す処理をしているから、SMAとEMAのindexとあわなくなったためでしょう。
SMA, EMAのindexもstring, float混合のindexにすれば平日のみxaxisにできなくもないでしょうが、今後時間足を任意の長さに変更することを想定していますので、無理にdatetime型を崩したくありません。

そのため休日が入って少し見づらいですが、plotlyのAPIをそのまま受け入れていきます。

まだまだplotlyのことよくわかっていないです。

Why do not you register as a user and use Qiita more conveniently?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away