#!/usr/bin/env python # coding: utf-8 # # Price Channel, Donchian Channel, High Low(HL) Bands # In[1]: import numpy as np import pandas as pd from highcharts import Highstock # ## データ # # [ヒストリカルデータ取得 :: デューカスコピー・ジャパン | 自動売買も裁量もJForex!](https://www.dukascopy.jp/marketwatch/historical/) # # ``` # $ head USDJPY_1\ Min_Bid_2000.01.01_2018.01.01.csv # Time (UTC),Open,High,Low,Close,Volume # 2003.05.04 21:00:00,118.94,118.952,118.94,118.952,253 # 2003.05.04 21:01:00,118.961,118.967,118.958,118.967,154.6 # 2003.05.04 21:02:00,118.972,118.972,118.955,118.955,219.7 # 2003.05.04 21:03:00,118.953,118.961,118.949,118.949,309.9 # 2003.05.04 21:04:00,118.953,118.953,118.946,118.946,229.4 # 2003.05.04 21:05:00,118.952,118.954,118.944,118.944,112.2 # 2003.05.04 21:06:00,118.95,118.952,118.945,118.945,170.2 # 2003.05.04 21:07:00,118.947,118.956,118.947,118.947,124.5 # 2003.05.04 21:08:00,118.946,118.954,118.934,118.934,355 # $ wc -l USDJPY_1\ Min_Bid_2000.01.01_2018.01.01.csv # 5509561 USDJPY_1 Min_Bid_2000.01.01_2018.01.01.csv # ``` # ## データを読み込む # In[2]: filepath1 = 'USDJPY_1 Min_Bid_2000.01.01_2018.01.01.csv' dtype1 = { 'time': str, 'open': float, 'high': float, 'low': float, 'close': float, 'volume': float } names1 = ['time', 'open', 'high', 'low', 'close', 'volume'] get_ipython().run_line_magic('time', "df = pd.read_csv(filepath_or_buffer=filepath1, dtype=dtype1, header=0, index_col='time', names=names1, parse_dates=['time'])") # CPU times: user 15.5 s, sys: 3.77 s, total: 19.2 s # Wall time: 20.5 s df.head() # ## 日足のローソク足を 5 本にするため時間の計算 # # UTC → UTC+3 # In[3]: #%time pd.DataFrame({ 'open': df['open'], 'high': df['high'], 'low': df['low'], 'close': df['close'], 'volume': df['volume'] }, index=df.index + pd.DateOffset(hours=3)) #%time pd.DataFrame({ 'open': df['open'].values, 'high': df['high'].values, 'low': df['low'].values, 'close': df['close'].values, 'volume': df['volume'].values }, index=df.index + pd.DateOffset(hours=3)) # index を変える場合、 Series だと DataFrame を生成するのに 6 秒程度、 ndarray だと DataFrame を生成するのに 1 秒程度 data2 = { 'open': df['open'].values, 'high': df['high'].values, 'low': df['low'].values, 'close': df['close'].values, 'volume': df['volume'].values } columns2 = ['open', 'high', 'low', 'close', 'volume'] index2 = df.index + pd.DateOffset(hours=3) get_ipython().run_line_magic('time', 'df2 = pd.DataFrame(data=data2, columns=columns2, index=index2)') # CPU times: user 62.5 ms, sys: 453 ms, total: 516 ms # Wall time: 524 ms df2.head() # ## リサンプリング # In[4]: # 日足の始値、高値、安値、終値を計算する # Series ごとに始値、高値、安値、終値の計算結果が得られる # 始値を参照する場合は df['open']['open'] のように記述する get_ipython().run_line_magic('time', "df3 = df2.resample(rule='D').ohlc()") # CPU times: user 250 ms, sys: 78.1 ms, total: 328 ms # Wall time: 348 ms # 日足の出来高を計算する get_ipython().run_line_magic('time', "df4 = df2.resample(rule='D').sum()") # CPU times: user 156 ms, sys: 93.8 ms, total: 250 ms # Wall time: 241 ms # 日足の DataFrame # 土日も計算結果に含まれるため dropna で取り除く data5 = { 'open': df3['open']['open'].values, 'high': df3['high']['high'].values, 'low': df3['low']['low'].values, 'close': df3['close']['close'].values, 'volume': df4['volume'].values } columns5 = ['open', 'high', 'low', 'close', 'volume'] get_ipython().run_line_magic('time', 'df5 = pd.DataFrame(data=data5, columns=columns5, index=df3.index).dropna()') # CPU times: user 0 ns, sys: 0 ns, total: 0 ns # Wall time: 2.91 ms df5.head() # ## 高値と安値を計算する # # * [pandas.DataFrame.rolling — pandas 0.23.0 documentation](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html) # In[5]: # high = pd.rolling_max(df2, 20) # /path/to/dir/lib/python3.5/site-packages/ipykernel_launcher.py:1: FutureWarning: pd.rolling_max is deprecated for DataFrame and will be removed in a future version, replace with # DataFrame.rolling(window=20,center=False).max() # """Entry point for launching an IPython kernel. # pd.rolling_max と pd.rolling_min は deprecated になったみたい period = 20 # %time df5.rolling(window=period).max() # CPU times: user 0 ns, sys: 0 ns, total: 0 ns # Wall time: 48.3 ms get_ipython().run_line_magic('time', "high = df5['high'].rolling(window=period).max()") get_ipython().run_line_magic('time', "low = df5['low'].rolling(window=period).min()") get_ipython().run_line_magic('time', "pd.DataFrame(data={ 'high': high, 'low': low }).tail()") # ## Highstock 向けの DataFrame を作る # In[6]: time6 = (df5.index.values // pd.Timedelta('1ms')).astype(np.int64) data6 = { 'time': time6, 'open': df5['open'].values, 'high': df5['high'].values, 'low': df5['low'].values, 'close': df5['close'].values } columns6 = ['time', 'open', 'high', 'low', 'close'] df6 = pd.DataFrame(data=data6, columns=columns6) data7 = { 'time': time6, 'hlhigh': high.values } columns7 = ['time', 'hlhigh'] df7 = pd.DataFrame(data=data7, columns=columns7) data8 = { 'time': time6, 'hllow': low.values } columns8 = ['time', 'hllow'] df8 = pd.DataFrame(data=data8, columns=columns8) df6.merge(df7).merge(df8).tail() # ## Highstock のローソク足を表示する # In[7]: H = Highstock() H.add_data_set(df6.values.tolist(), 'candlestick', '米ドル/円') H.add_data_set(df7.values.tolist(), 'line', 'High') H.add_data_set(df8.values.tolist(), 'line', 'Low') options = { 'plotOptions': { 'line': { 'lineWidth': 1 } }, 'rangeSelector': { 'selected': 1 }, 'title': { 'text': '米ドル/円 daily' } } H.set_dict_options(options) H # ## Highstock の SMA を表示する # # chart types の sma に対応していない。 # [highstock_types.py](https://github.com/kyper-data/python-highcharts/blob/developer/highcharts/highstock/highstock_types.py) の `PLOT_OPTION_ALLOWED_ARGS` を見ると sma がない。 # In[8]: H2 = Highstock() H2.add_data_set(df6.values.tolist(), 'candlestick', '米ドル/円', id='USDJPY') #H2.add_data_set(linkedTo='USDJPY', params={ 'index': 3, 'period': 20 }, type='sma') #KeyError: 'sma' #TypeError: add_data_set() missing 1 required positional argument: 'data' options2 = { # 'plotOptions': { # 'sma': { # 'linkedTo': 'USDJPY', # 'lineWidth': 1 # } # }, 'rangeSelector': { 'selected': 1 }, 'title': { 'text': '米ドル/円 daily' } } #OptionTypeError: Not An Accepted Option Type: sma H2.set_dict_options(options2) H2