Pythonでテクニカル指標を作成する

今回はテクニカル指標を作ってみます。対象とするFXデータとして、以下のコードで作成した日足データを使ってみます。

In [1]:
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas.tseries.offsets as offsets

# dfのデータからtfで指定するタイムフレームの4本足データを作成する関数
def TF_ohlc(df, tf):
    x = df.resample(tf).ohlc()
    ret = pd.DataFrame({'Open': x['Open']['open'],
                       'High': x['High']['high'],
                       'Low': x['Low']['low'],
                       'Close': x['Close']['close']},
                       columns=['Open','High','Low','Close'])
    return ret.dropna()
    
dataM1 = pd.read_csv('C:\Python\DAT_ASCII_EURUSD_M1_2015.csv', sep=';',
                     names=('Time','Open','High','Low','Close', ''),
                     index_col='Time', parse_dates=True)
dataM1.index += offsets.Hour(7) #7時間のオフセット

ohlcD1 = TF_ohlc(dataM1, 'D') #日足データの作成
ohlcD1
Out[1]:
Open High Low Close
Time
2015-01-01 1.20965 1.21041 1.20959 1.21002
2015-01-02 1.21037 1.21072 1.20002 1.20009
2015-01-05 1.19427 1.19763 1.18664 1.19327
2015-01-06 1.19329 1.19687 1.18841 1.18893
2015-01-07 1.18894 1.18965 1.18021 1.18392
2015-01-08 1.18377 1.18474 1.17541 1.17916
2015-01-09 1.17930 1.18459 1.17626 1.18407
2015-01-12 1.18499 1.18709 1.17862 1.18334
2015-01-13 1.18331 1.18595 1.17534 1.17722
2015-01-14 1.17722 1.18462 1.17272 1.17887
2015-01-15 1.17888 1.17924 1.15678 1.16299
2015-01-16 1.16304 1.16487 1.14600 1.15620
2015-01-19 1.15516 1.16389 1.15513 1.16019
2015-01-20 1.16068 1.16148 1.15405 1.15485
2015-01-21 1.15483 1.16802 1.15414 1.16092
2015-01-22 1.16095 1.16509 1.13159 1.13647
2015-01-23 1.13649 1.13738 1.11144 1.12024
2015-01-26 1.11511 1.12953 1.10978 1.12386
2015-01-27 1.12377 1.14225 1.12236 1.13805
2015-01-28 1.13761 1.13829 1.12760 1.12863
2015-01-29 1.12862 1.13678 1.12617 1.13192
2015-01-30 1.13183 1.13636 1.12786 1.12839
2015-02-02 1.13105 1.13620 1.12922 1.13411
2015-02-03 1.13407 1.15340 1.13123 1.14785
2015-02-04 1.14788 1.14847 1.13155 1.13433
2015-02-05 1.13433 1.14987 1.13038 1.14768
2015-02-06 1.14763 1.14856 1.13117 1.13154
2015-02-09 1.12964 1.13592 1.12702 1.13231
2015-02-10 1.13229 1.13454 1.12730 1.13202
2015-02-11 1.13200 1.13472 1.12799 1.13354
... ... ... ... ...
2015-11-19 1.06572 1.07630 1.06552 1.07346
2015-11-20 1.07323 1.07384 1.06397 1.06436
2015-11-23 1.06377 1.06568 1.05927 1.06356
2015-11-24 1.06354 1.06731 1.06195 1.06428
2015-11-25 1.06419 1.06892 1.05660 1.06236
2015-11-26 1.06237 1.06273 1.05998 1.06093
2015-11-27 1.06095 1.06380 1.05685 1.05900
2015-11-30 1.05881 1.05949 1.05578 1.05631
2015-12-01 1.05629 1.06370 1.05623 1.06313
2015-12-02 1.06312 1.06356 1.05508 1.06127
2015-12-03 1.06129 1.09811 1.05223 1.09376
2015-12-04 1.09376 1.09562 1.08359 1.08832
2015-12-07 1.08725 1.08876 1.07960 1.08369
2015-12-08 1.08362 1.09021 1.08300 1.08917
2015-12-09 1.08909 1.10425 1.08791 1.10240
2015-12-10 1.10226 1.10245 1.09251 1.09401
2015-12-11 1.09392 1.10308 1.09266 1.09886
2015-12-14 1.09823 1.10486 1.09455 1.09909
2015-12-15 1.09905 1.10594 1.09045 1.09280
2015-12-16 1.09284 1.10110 1.08879 1.09115
2015-12-17 1.09105 1.09138 1.08027 1.08251
2015-12-18 1.08238 1.08744 1.08050 1.08652
2015-12-21 1.08531 1.09389 1.08470 1.09145
2015-12-22 1.09137 1.09841 1.09021 1.09555
2015-12-23 1.09550 1.09565 1.08701 1.09093
2015-12-24 1.09093 1.09676 1.09028 1.09630
2015-12-28 1.09676 1.09924 1.09547 1.09652
2015-12-29 1.09650 1.09915 1.08992 1.09193
2015-12-30 1.09172 1.09436 1.09018 1.09312
2015-12-31 1.09309 1.09372 1.08527 1.08545

260 rows × 4 columns

テクニカル指標の計算には、終値を使うことが多いので、closeで参照できるようにしておきます。

In [2]:
close = ohlcD1['Close']
close
Out[2]:
Time
2015-01-01    1.21002
2015-01-02    1.20009
2015-01-05    1.19327
2015-01-06    1.18893
2015-01-07    1.18392
2015-01-08    1.17916
2015-01-09    1.18407
2015-01-12    1.18334
2015-01-13    1.17722
2015-01-14    1.17887
2015-01-15    1.16299
2015-01-16    1.15620
2015-01-19    1.16019
2015-01-20    1.15485
2015-01-21    1.16092
2015-01-22    1.13647
2015-01-23    1.12024
2015-01-26    1.12386
2015-01-27    1.13805
2015-01-28    1.12863
2015-01-29    1.13192
2015-01-30    1.12839
2015-02-02    1.13411
2015-02-03    1.14785
2015-02-04    1.13433
2015-02-05    1.14768
2015-02-06    1.13154
2015-02-09    1.13231
2015-02-10    1.13202
2015-02-11    1.13354
               ...   
2015-11-19    1.07346
2015-11-20    1.06436
2015-11-23    1.06356
2015-11-24    1.06428
2015-11-25    1.06236
2015-11-26    1.06093
2015-11-27    1.05900
2015-11-30    1.05631
2015-12-01    1.06313
2015-12-02    1.06127
2015-12-03    1.09376
2015-12-04    1.08832
2015-12-07    1.08369
2015-12-08    1.08917
2015-12-09    1.10240
2015-12-10    1.09401
2015-12-11    1.09886
2015-12-14    1.09909
2015-12-15    1.09280
2015-12-16    1.09115
2015-12-17    1.08251
2015-12-18    1.08652
2015-12-21    1.09145
2015-12-22    1.09555
2015-12-23    1.09093
2015-12-24    1.09630
2015-12-28    1.09652
2015-12-29    1.09193
2015-12-30    1.09312
2015-12-31    1.08545
Name: Close, dtype: float64

移動平均

まずは、終値の時系列に対して移動平均(MA)を取ってみます。移動平均のなかで最も簡単なのが単純移動平均(SMA)で、過去のサンプルの平均を取るだけです。これは、Seriesのメソッド関数を使うことで簡単に書けます。rolling()で期間を指定して、mean()で平均を取るだけです。

In [3]:
#SMA
MA_period = 10 #期間
SMA = close.rolling(MA_period).mean()
SMA
Out[3]:
Time
2015-01-01         NaN
2015-01-02         NaN
2015-01-05         NaN
2015-01-06         NaN
2015-01-07         NaN
2015-01-08         NaN
2015-01-09         NaN
2015-01-12         NaN
2015-01-13         NaN
2015-01-14    1.187889
2015-01-15    1.183186
2015-01-16    1.178797
2015-01-19    1.175489
2015-01-20    1.172081
2015-01-21    1.169781
2015-01-22    1.165512
2015-01-23    1.159129
2015-01-26    1.153181
2015-01-27    1.149264
2015-01-28    1.144240
2015-01-29    1.141133
2015-01-30    1.138352
2015-02-02    1.135744
2015-02-03    1.135044
2015-02-04    1.132385
2015-02-05    1.133506
2015-02-06    1.134636
2015-02-09    1.135481
2015-02-10    1.134878
2015-02-11    1.135369
                ...   
2015-11-19    1.072516
2015-11-20    1.071585
2015-11-23    1.070440
2015-11-24    1.069631
2015-11-25    1.068459
2015-11-26    1.066439
2015-11-27    1.064632
2015-11-30    1.063409
2015-12-01    1.063318
2015-12-02    1.062866
2015-12-03    1.064896
2015-12-04    1.067292
2015-12-07    1.069305
2015-12-08    1.071794
2015-12-09    1.075798
2015-12-10    1.079106
2015-12-11    1.083092
2015-12-14    1.087370
2015-12-15    1.090337
2015-12-16    1.093325
2015-12-17    1.092200
2015-12-18    1.092020
2015-12-21    1.092796
2015-12-22    1.093434
2015-12-23    1.092287
2015-12-24    1.092516
2015-12-28    1.092282
2015-12-29    1.091566
2015-12-30    1.091598
2015-12-31    1.091028
Name: Close, dtype: float64

チャートへの表示は、後でまとめてやります。続いて指数平滑移動平均(EMA)です。これには専用のメソッド関数が用意されていて、ewm()を使います。spanというパラメータで値を指定すると、平滑化係数$\alpha$に、$\alpha=2/(1+span)$として渡されます。なので、spanにEMAの期間を指定して、ewm()を呼び出せばよいことになります。mean()を続けるところはSMAの場合と同じです。

In [4]:
#EMA
EMA_period = 10 #期間
EMA = close.ewm(span=EMA_period).mean()
EMA
Out[4]:
Time
2015-01-01    1.210020
2015-01-02    1.204559
2015-01-05    1.200021
2015-01-06    1.196367
2015-01-07    1.192794
2015-01-08    1.189252
2015-01-09    1.188004
2015-01-12    1.186943
2015-01-13    1.184827
2015-01-14    1.183576
2015-01-15    1.179371
2015-01-16    1.174741
2015-01-19    1.171885
2015-01-20    1.168589
2015-01-21    1.167123
2015-01-22    1.161315
2015-01-23    1.153592
2015-01-26    1.148036
2015-01-27    1.146180
2015-01-28    1.142930
2015-01-29    1.140898
2015-01-30    1.138596
2015-02-02    1.137772
2015-02-03    1.139620
2015-02-04    1.138651
2015-02-05    1.140302
2015-02-06    1.138702
2015-02-09    1.137535
2015-02-10    1.136530
2015-02-11    1.135985
                ...   
2015-11-19    1.075023
2015-11-20    1.073085
2015-11-23    1.071353
2015-11-24    1.070067
2015-11-25    1.068666
2015-11-26    1.067259
2015-11-27    1.065757
2015-11-30    1.064040
2015-12-01    1.063874
2015-12-02    1.063401
2015-12-03    1.068921
2015-12-04    1.072448
2015-12-07    1.074492
2015-12-08    1.077161
2015-12-09    1.081750
2015-12-10    1.083979
2015-12-11    1.086684
2015-12-14    1.088940
2015-12-15    1.089642
2015-12-16    1.089916
2015-12-17    1.088569
2015-12-18    1.088197
2015-12-21    1.088788
2015-12-22    1.090018
2015-12-23    1.090184
2015-12-24    1.091296
2015-12-28    1.092246
2015-12-29    1.092188
2015-12-30    1.092358
2015-12-31    1.091102
Name: Close, dtype: float64

次にMT4における平滑移動平均(SMMA)ですが、これは基本的にはEMAと同じです。平滑化係数alphaが期間の逆数となっているので、ewm()で、alphaというパラメータに期間の逆数を代入します。

In [5]:
#SMMA
SMMA_period = 10 #期間
SMMA = close.ewm(alpha=1/SMMA_period).mean()
SMMA
Out[5]:
Time
2015-01-01    1.210020
2015-01-02    1.204794
2015-01-05    1.200541
2015-01-06    1.197165
2015-01-07    1.193931
2015-01-08    1.190778
2015-01-09    1.189492
2015-01-12    1.188412
2015-01-13    1.186585
2015-01-14    1.185401
2015-01-15    1.182135
2015-01-16    1.178520
2015-01-19    1.176063
2015-01-20    1.173312
2015-01-21    1.171752
2015-01-22    1.167421
2015-01-23    1.161759
2015-01-26    1.157299
2015-01-27    1.155074
2015-01-28    1.152063
2015-01-29    1.149802
2015-01-30    1.147427
2015-02-02    1.145965
2015-02-03    1.146170
2015-02-04    1.144895
2015-02-05    1.145192
2015-02-06    1.143743
2015-02-09    1.142536
2015-02-10    1.141433
2015-02-11    1.140609
                ...   
2015-11-19    1.084273
2015-11-20    1.082281
2015-11-23    1.080409
2015-11-24    1.078796
2015-11-25    1.077153
2015-11-26    1.075530
2015-11-27    1.073877
2015-11-30    1.072121
2015-12-01    1.071222
2015-12-02    1.070226
2015-12-03    1.072580
2015-12-04    1.074154
2015-12-07    1.075107
2015-12-08    1.076514
2015-12-09    1.079102
2015-12-10    1.080593
2015-12-11    1.082420
2015-12-14    1.084087
2015-12-15    1.084958
2015-12-16    1.085577
2015-12-17    1.085271
2015-12-18    1.085396
2015-12-21    1.086001
2015-12-22    1.086956
2015-12-23    1.087353
2015-12-24    1.088248
2015-12-28    1.089075
2015-12-29    1.089361
2015-12-30    1.089737
2015-12-31    1.089308
Name: Close, dtype: float64

MT4ではもう一つ、線形加重移動平均(LWMA)というのがあります。rolling()で窓関数の形状を指定するパラメータがあったので、それでできるかと思ったのですが、ちょっと用途が違っていました。LWMAの実装はちょっとコード書かないといけないので省略します。

以上、SMA、EMA、SMMAの各移動平均の結果をプロットすると以下のようになります。DataFrame型にしてプロットすると、凡例も勝手に付くので便利です。

In [7]:
pd.DataFrame({'Close': close, 'SMA': SMA, 'EMA': EMA, 'SMMA': SMMA},
            columns=['Close', 'SMA', 'EMA', 'SMMA']).plot(figsize=(8,6))
Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb8187ba8>

モメンタム

モメンタムも一定期間前の価格との差を取るだけだったら、diff()を呼ぶだけでいいのですが、ここでは、MT4のモメンタムに合わせて、一定期間前の価格との比(%)を取ってみます。そのために、shift()を使って、一定期間シフトした系列を作っておきます。そして、終値との比を取って100倍すれば完成です。

In [8]:
#Momentum
Mom_period = 10
shift = close.shift(Mom_period)
Mom = close/shift*100
Mom
Out[8]:
Time
2015-01-01           NaN
2015-01-02           NaN
2015-01-05           NaN
2015-01-06           NaN
2015-01-07           NaN
2015-01-08           NaN
2015-01-09           NaN
2015-01-12           NaN
2015-01-13           NaN
2015-01-14           NaN
2015-01-15     96.113287
2015-01-16     96.342774
2015-01-19     97.227786
2015-01-20     97.133557
2015-01-21     98.057301
2015-01-22     96.379626
2015-01-23     94.609271
2015-01-26     94.973549
2015-01-27     96.672670
2015-01-28     95.738292
2015-01-29     97.328438
2015-01-30     97.594707
2015-02-02     97.752092
2015-02-03     99.393861
2015-02-04     97.709575
2015-02-05    100.986388
2015-02-06    101.008712
2015-02-09    100.751873
2015-02-10     99.470146
2015-02-11    100.435041
                 ...    
2015-11-19     98.636405
2015-11-20     99.132881
2015-11-23     98.934894
2015-11-24     99.245596
2015-11-25     98.908834
2015-11-26     98.131585
2015-11-27     98.322300
2015-11-30     98.855448
2015-12-01     99.914477
2015-12-02     99.575901
2015-12-03    101.891081
2015-12-04    102.251118
2015-12-07    101.892700
2015-12-08    102.338670
2015-12-09    103.768967
2015-12-10    103.118019
2015-12-11    103.763928
2015-12-14    104.049947
2015-12-15    102.790816
2015-12-16    102.815495
2015-12-17     98.971438
2015-12-18     99.834607
2015-12-21    100.716072
2015-12-22    100.585767
2015-12-23     98.959543
2015-12-24    100.209322
2015-12-28     99.787052
2015-12-29     99.348552
2015-12-30    100.029283
2015-12-31     99.477615
Name: Close, dtype: float64

モメンタムはオシレーター系なので、チャートウィンドウとは別のサブウィンドウに表示させる必要があります。ここでは簡単にできる方法として、二つのチャートを上下に並べてみることにします。plot.figure()の引数を変えると、別々のグラフになるようなので、二つのチャートを表示させるために下のように書きます。あと、figsizeでサブウィンドウの縦軸がちょっと短くなるようにします。

In [9]:
plt.figure(0)
close.plot(figsize=(8,6))
plt.figure(1)
Mom.plot(figsize=(8,2))
Out[9]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb831dba8>

ボリンジャーバンド

ボリンジャーバンドは、SMAの上下に標準偏差を何倍かをプラスマイナスしたラインを引きます。SMAは前述のようにrolling().mean()で算出されます。標準偏差もメソッド関数が用意されていて、std()を呼ぶだけです。ただし、サンプル数での標準偏差を取るためにddof=0というパラメータを付けておきます。

In [10]:
#Bolinger Band
Bands_period = 10 #期間
Deviation = 2 #偏差の倍率
Base = close.rolling(Bands_period).mean()
sigma = close.rolling(Bands_period).std(ddof=0)
Upper = Base+sigma*Deviation
Lower = Base-sigma*Deviation
Upper,Lower
Out[10]:
(Time
 2015-01-01         NaN
 2015-01-02         NaN
 2015-01-05         NaN
 2015-01-06         NaN
 2015-01-07         NaN
 2015-01-08         NaN
 2015-01-09         NaN
 2015-01-12         NaN
 2015-01-13         NaN
 2015-01-14    1.207800
 2015-01-15    1.202160
 2015-01-16    1.200244
 2015-01-19    1.197189
 2015-01-20    1.194941
 2015-01-21    1.192034
 2015-01-22    1.194338
 2015-01-23    1.195872
 2015-01-26    1.191543
 2015-01-27    1.184910
 2015-01-28    1.175695
 2015-01-29    1.170644
 2015-01-30    1.166884
 2015-02-02    1.160307
 2015-02-03    1.157715
 2015-02-04    1.147152
 2015-02-05    1.150825
 2015-02-06    1.149669
 2015-02-09    1.148854
 2015-02-10    1.148277
 2015-02-11    1.148162
                 ...   
 2015-11-19    1.082288
 2015-11-20    1.082453
 2015-11-23    1.082013
 2015-11-24    1.081673
 2015-11-25    1.080818
 2015-11-26    1.076179
 2015-11-27    1.072296
 2015-11-30    1.072031
 2015-12-01    1.071931
 2015-12-02    1.071386
 2015-12-03    1.084720
 2015-12-04    1.091569
 2015-12-07    1.095289
 2015-12-08    1.100045
 2015-12-09    1.108556
 2015-12-10    1.111871
 2015-12-11    1.114784
 2015-12-14    1.114695
 2015-12-15    1.112433
 2015-12-16    1.104040
 2015-12-17    1.104709
 2015-12-18    1.104796
 2015-12-21    1.104336
 2015-12-22    1.104806
 2015-12-23    1.102004
 2015-12-24    1.102489
 2015-12-28    1.101746
 2015-12-29    1.099874
 2015-12-30    1.099927
 2015-12-31    1.100144
 Name: Close, dtype: float64, Time
 2015-01-01         NaN
 2015-01-02         NaN
 2015-01-05         NaN
 2015-01-06         NaN
 2015-01-07         NaN
 2015-01-08         NaN
 2015-01-09         NaN
 2015-01-12         NaN
 2015-01-13         NaN
 2015-01-14    1.167978
 2015-01-15    1.164212
 2015-01-16    1.157350
 2015-01-19    1.153789
 2015-01-20    1.149221
 2015-01-21    1.147528
 2015-01-22    1.136686
 2015-01-23    1.122386
 2015-01-26    1.114819
 2015-01-27    1.113618
 2015-01-28    1.112785
 2015-01-29    1.111622
 2015-01-30    1.109820
 2015-02-02    1.111181
 2015-02-03    1.112373
 2015-02-04    1.117618
 2015-02-05    1.116187
 2015-02-06    1.119603
 2015-02-09    1.122108
 2015-02-10    1.121479
 2015-02-11    1.122576
                 ...   
 2015-11-19    1.062744
 2015-11-20    1.060717
 2015-11-23    1.058867
 2015-11-24    1.057589
 2015-11-25    1.056100
 2015-11-26    1.056699
 2015-11-27    1.056968
 2015-11-30    1.054787
 2015-12-01    1.054705
 2015-12-02    1.054346
 2015-12-03    1.045072
 2015-12-04    1.043015
 2015-12-07    1.043321
 2015-12-08    1.043543
 2015-12-09    1.043040
 2015-12-10    1.046341
 2015-12-11    1.051400
 2015-12-14    1.060045
 2015-12-15    1.068241
 2015-12-16    1.082610
 2015-12-17    1.079691
 2015-12-18    1.079244
 2015-12-21    1.081256
 2015-12-22    1.082062
 2015-12-23    1.082570
 2015-12-24    1.082543
 2015-12-28    1.082818
 2015-12-29    1.083258
 2015-12-30    1.083269
 2015-12-31    1.081912
 Name: Close, dtype: float64)

ボリンジャーバンドはチャートウィンドウに表示するので、終値と一緒にDataFrame型にしてプロットします。

In [11]:
pd.DataFrame({'Close': close, 'Upper': Upper, 'Base': Base, 'Lower': Lower},
            columns=['Close', 'Upper', 'Base', 'Lower']).plot(figsize=(8,6))
Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb8372668>

MACD

こんどは、移動平均絡みでMACDを作ってみます。 MACDのメインのラインは、短期EMAと長期EMAの差です。さらにシグナルラインは、メインのSMAを取ったものです。このように移動平均の計算しか出てこないので、コードは以下のように簡単です。

In [12]:
FastEMA_period = 12 #短期EMAの期間
SlowEMA_period = 26 #長期EMAの期間
SignalSMA_period = 9 #SMAを取る期間
MACD = close.ewm(span=FastEMA_period).mean() - close.ewm(span=SlowEMA_period).mean()
Signal = MACD.rolling(SignalSMA_period).mean()
MACD,Signal
Out[12]:
(Time
 2015-01-01    0.000000
 2015-01-02   -0.000223
 2015-01-05   -0.000495
 2015-01-06   -0.000764
 2015-01-07   -0.001093
 2015-01-08   -0.001474
 2015-01-09   -0.001470
 2015-01-12   -0.001479
 2015-01-13   -0.001766
 2015-01-14   -0.001859
 2015-01-15   -0.002746
 2015-01-16   -0.003732
 2015-01-19   -0.004189
 2015-01-20   -0.004785
 2015-01-21   -0.004814
 2015-01-22   -0.006258
 2015-01-23   -0.008286
 2015-01-26   -0.009510
 2015-01-27   -0.009424
 2015-01-28   -0.009858
 2015-01-29   -0.009858
 2015-01-30   -0.009977
 2015-02-02   -0.009562
 2015-02-03   -0.008183
 2015-02-04   -0.007953
 2015-02-05   -0.006744
 2015-02-06   -0.006868
 2015-02-09   -0.006829
 2015-02-10   -0.006740
 2015-02-11   -0.006482
                 ...   
 2015-11-19   -0.012971
 2015-11-20   -0.013028
 2015-11-23   -0.012988
 2015-11-24   -0.012752
 2015-11-25   -0.012574
 2015-11-26   -0.012406
 2015-11-27   -0.012286
 2015-11-30   -0.012267
 2015-12-01   -0.011569
 2015-12-02   -0.011038
 2015-12-03   -0.007904
 2015-12-04   -0.005793
 2015-12-07   -0.004442
 2015-12-08   -0.002896
 2015-12-09   -0.000597
 2015-12-10    0.000543
 2015-12-11    0.001816
 2015-12-14    0.002811
 2015-12-15    0.003057
 2015-12-16    0.003083
 2015-12-17    0.002379
 2015-12-18    0.002121
 2015-12-21    0.002287
 2015-12-22    0.002719
 2015-12-23    0.002657
 2015-12-24    0.003007
 2015-12-28    0.003264
 2015-12-29    0.003063
 2015-12-30    0.002965
 2015-12-31    0.002242
 Name: Close, dtype: float64, Time
 2015-01-01         NaN
 2015-01-02         NaN
 2015-01-05         NaN
 2015-01-06         NaN
 2015-01-07         NaN
 2015-01-08         NaN
 2015-01-09         NaN
 2015-01-12         NaN
 2015-01-13   -0.000974
 2015-01-14   -0.001180
 2015-01-15   -0.001461
 2015-01-16   -0.001821
 2015-01-19   -0.002201
 2015-01-20   -0.002611
 2015-01-21   -0.002982
 2015-01-22   -0.003514
 2015-01-23   -0.004271
 2015-01-26   -0.005131
 2015-01-27   -0.005972
 2015-01-28   -0.006762
 2015-01-29   -0.007442
 2015-01-30   -0.008086
 2015-02-02   -0.008616
 2015-02-03   -0.008991
 2015-02-04   -0.009179
 2015-02-05   -0.009008
 2015-02-06   -0.008714
 2015-02-09   -0.008426
 2015-02-10   -0.008079
 2015-02-11   -0.007704
                 ...   
 2015-11-19   -0.012896
 2015-11-20   -0.013022
 2015-11-23   -0.013049
 2015-11-24   -0.013009
 2015-11-25   -0.012996
 2015-11-26   -0.012981
 2015-11-27   -0.012905
 2015-11-30   -0.012768
 2015-12-01   -0.012538
 2015-12-02   -0.012323
 2015-12-03   -0.011754
 2015-12-04   -0.010954
 2015-12-07   -0.010031
 2015-12-08   -0.008956
 2015-12-09   -0.007644
 2015-12-10   -0.006218
 2015-12-11   -0.004653
 2015-12-14   -0.003056
 2015-12-15   -0.001490
 2015-12-16   -0.000269
 2015-12-17    0.000639
 2015-12-18    0.001369
 2015-12-21    0.001945
 2015-12-22    0.002313
 2015-12-23    0.002548
 2015-12-24    0.002680
 2015-12-28    0.002731
 2015-12-29    0.002731
 2015-12-30    0.002718
 2015-12-31    0.002703
 Name: Close, dtype: float64)

これをプロットすると、以下のようになります。

In [13]:
plt.figure(0)
close.plot(figsize=(8,6))
plt.figure(1)
pd.DataFrame({'MACD': MACD, 'Signal': Signal},
            columns=['MACD', 'Signal']).plot(figsize=(8,2))
Out[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb97c0898>
<matplotlib.figure.Figure at 0x17fb972def0>

RSI

RSIは一定期間の上昇分と下降分を平滑化して、その比を0から100の範囲で表したものです。今までのテクニカル指標に比べると、ちょっと複雑ですが、やはりメソッド関数をうまく使うと簡単に書けます。

まず、前日との差をdiff()関数で算出します。そして、そのなかで上昇した分(正の値)だけを取り出すために、一定値以下をクリップするclip_lower()関数を使います。これで、プラスだけの系列ができます。同様にclip_upper()関数を使うと、マイナスだけの系列ができます。さらにそれぞれの系列を、前述のSMMAと同じ方法で平滑化します。最後に比を取って範囲を調整して終わりです。思ったより簡単にできました。

In [14]:
#RSI
RSI_period = 14
diff = close.diff(1)
positive = diff.clip_lower(0).ewm(alpha=1/RSI_period).mean()
negative = diff.clip_upper(0).ewm(alpha=1/RSI_period).mean()
RSI = 100-100/(1-positive/negative)
RSI
Out[14]:
Time
2015-01-01          NaN
2015-01-02     0.000000
2015-01-05     0.000000
2015-01-06     0.000000
2015-01-07     0.000000
2015-01-08     0.000000
2015-01-09    16.901647
2015-01-12    16.456311
2015-01-13    13.293865
2015-01-14    17.876100
2015-01-15    11.549768
2015-01-16     9.931347
2015-01-19    17.267713
2015-01-20    15.453504
2015-01-21    25.088137
2015-01-22    16.788919
2015-01-23    13.578003
2015-01-26    17.373765
2015-01-27    30.297336
2015-01-28    27.250227
2015-01-29    29.901897
2015-01-30    28.693433
2015-02-02    33.391009
2015-02-03    43.089652
2015-02-04    37.329834
2015-02-05    45.129311
2015-02-06    38.836413
2015-02-09    39.271480
2015-02-10    39.158505
2015-02-11    40.130668
                ...    
2015-11-19    37.661556
2015-11-20    33.343418
2015-11-23    32.985361
2015-11-24    33.675668
2015-11-25    32.708100
2015-11-26    31.971307
2015-11-27    30.957711
2015-11-30    29.551459
2015-12-01    37.324785
2015-12-02    36.153145
2015-12-03    59.857315
2015-12-04    56.101586
2015-12-07    53.050641
2015-12-08    56.094093
2015-12-09    62.426670
2015-12-10    56.828917
2015-12-11    59.111414
2015-12-14    59.221522
2015-12-15    54.869831
2015-12-16    53.753978
2015-12-17    48.223684
2015-12-18    50.755935
2015-12-21    53.750735
2015-12-22    56.139686
2015-12-23    52.828285
2015-12-24    56.071705
2015-12-28    56.204561
2015-12-29    52.628271
2015-12-30    53.455168
2015-12-31    47.678373
Name: Close, dtype: float64

プロットするとこんな感じです。

In [15]:
plt.figure(0)
close.plot(figsize=(8,6))
plt.figure(1)
RSI.plot(figsize=(8,2))
Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb988c5f8>

HLバンド

HLバンドは一定期間の最高値、最安値を結んだラインです。ここでは、max()min()という最大値と最小値を求めるメソッド関数を使います。

まずは、終値の最高値、最安値を求めるHLバンドの例です。rolling()で期間を指定して、max()min()を呼ぶだけです。

In [16]:
#HLband
band_period = 20 #期間
Hline = close.rolling(band_period).max()
Lline = close.rolling(band_period).min()
Hline, Lline
Out[16]:
(Time
 2015-01-01        NaN
 2015-01-02        NaN
 2015-01-05        NaN
 2015-01-06        NaN
 2015-01-07        NaN
 2015-01-08        NaN
 2015-01-09        NaN
 2015-01-12        NaN
 2015-01-13        NaN
 2015-01-14        NaN
 2015-01-15        NaN
 2015-01-16        NaN
 2015-01-19        NaN
 2015-01-20        NaN
 2015-01-21        NaN
 2015-01-22        NaN
 2015-01-23        NaN
 2015-01-26        NaN
 2015-01-27        NaN
 2015-01-28    1.21002
 2015-01-29    1.20009
 2015-01-30    1.19327
 2015-02-02    1.18893
 2015-02-03    1.18407
 2015-02-04    1.18407
 2015-02-05    1.18407
 2015-02-06    1.18334
 2015-02-09    1.17887
 2015-02-10    1.17887
 2015-02-11    1.16299
                ...   
 2015-11-19    1.10561
 2015-11-20    1.10561
 2015-11-23    1.10486
 2015-11-24    1.10147
 2015-11-25    1.10147
 2015-11-26    1.10147
 2015-11-27    1.10147
 2015-11-30    1.09622
 2015-12-01    1.08830
 2015-12-02    1.08830
 2015-12-03    1.09376
 2015-12-04    1.09376
 2015-12-07    1.09376
 2015-12-08    1.09376
 2015-12-09    1.10240
 2015-12-10    1.10240
 2015-12-11    1.10240
 2015-12-14    1.10240
 2015-12-15    1.10240
 2015-12-16    1.10240
 2015-12-17    1.10240
 2015-12-18    1.10240
 2015-12-21    1.10240
 2015-12-22    1.10240
 2015-12-23    1.10240
 2015-12-24    1.10240
 2015-12-28    1.10240
 2015-12-29    1.10240
 2015-12-30    1.10240
 2015-12-31    1.10240
 Name: Close, dtype: float64, Time
 2015-01-01        NaN
 2015-01-02        NaN
 2015-01-05        NaN
 2015-01-06        NaN
 2015-01-07        NaN
 2015-01-08        NaN
 2015-01-09        NaN
 2015-01-12        NaN
 2015-01-13        NaN
 2015-01-14        NaN
 2015-01-15        NaN
 2015-01-16        NaN
 2015-01-19        NaN
 2015-01-20        NaN
 2015-01-21        NaN
 2015-01-22        NaN
 2015-01-23        NaN
 2015-01-26        NaN
 2015-01-27        NaN
 2015-01-28    1.12024
 2015-01-29    1.12024
 2015-01-30    1.12024
 2015-02-02    1.12024
 2015-02-03    1.12024
 2015-02-04    1.12024
 2015-02-05    1.12024
 2015-02-06    1.12024
 2015-02-09    1.12024
 2015-02-10    1.12024
 2015-02-11    1.12024
                ...   
 2015-11-19    1.06404
 2015-11-20    1.06404
 2015-11-23    1.06356
 2015-11-24    1.06356
 2015-11-25    1.06236
 2015-11-26    1.06093
 2015-11-27    1.05900
 2015-11-30    1.05631
 2015-12-01    1.05631
 2015-12-02    1.05631
 2015-12-03    1.05631
 2015-12-04    1.05631
 2015-12-07    1.05631
 2015-12-08    1.05631
 2015-12-09    1.05631
 2015-12-10    1.05631
 2015-12-11    1.05631
 2015-12-14    1.05631
 2015-12-15    1.05631
 2015-12-16    1.05631
 2015-12-17    1.05631
 2015-12-18    1.05631
 2015-12-21    1.05631
 2015-12-22    1.05631
 2015-12-23    1.05631
 2015-12-24    1.05631
 2015-12-28    1.05631
 2015-12-29    1.06127
 2015-12-30    1.06127
 2015-12-31    1.08251
 Name: Close, dtype: float64)

終値と一緒にチャートに表示させると、こんな感じになります。

In [17]:
pd.DataFrame({'Close': close, 'Hline': Hline, 'Lline': Lline},
            columns=['Close', 'Hline', 'Lline']).plot(figsize=(8,6))
Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb982f940>

次に高値の最高値、安値の最安値を結ぶHLバンドの場合です。あらかじめ、高値の系列と安値の系列をhighlowとして参照できるようにしておきます。あとは、closeのところをhighlowに変えるだけです。

In [18]:
high = ohlcD1['High']
low = ohlcD1['Low']
Hline = high.rolling(band_period).max()
Lline = low.rolling(band_period).min()
Hline, Lline
Out[18]:
(Time
 2015-01-01        NaN
 2015-01-02        NaN
 2015-01-05        NaN
 2015-01-06        NaN
 2015-01-07        NaN
 2015-01-08        NaN
 2015-01-09        NaN
 2015-01-12        NaN
 2015-01-13        NaN
 2015-01-14        NaN
 2015-01-15        NaN
 2015-01-16        NaN
 2015-01-19        NaN
 2015-01-20        NaN
 2015-01-21        NaN
 2015-01-22        NaN
 2015-01-23        NaN
 2015-01-26        NaN
 2015-01-27        NaN
 2015-01-28    1.21072
 2015-01-29    1.21072
 2015-01-30    1.19763
 2015-02-02    1.19687
 2015-02-03    1.18965
 2015-02-04    1.18709
 2015-02-05    1.18709
 2015-02-06    1.18709
 2015-02-09    1.18595
 2015-02-10    1.18462
 2015-02-11    1.17924
                ...   
 2015-11-19    1.11396
 2015-11-20    1.10957
 2015-11-23    1.10957
 2015-11-24    1.10957
 2015-11-25    1.10726
 2015-11-26    1.10726
 2015-11-27    1.10525
 2015-11-30    1.10299
 2015-12-01    1.09678
 2015-12-02    1.08974
 2015-12-03    1.09811
 2015-12-04    1.09811
 2015-12-07    1.09811
 2015-12-08    1.09811
 2015-12-09    1.10425
 2015-12-10    1.10425
 2015-12-11    1.10425
 2015-12-14    1.10486
 2015-12-15    1.10594
 2015-12-16    1.10594
 2015-12-17    1.10594
 2015-12-18    1.10594
 2015-12-21    1.10594
 2015-12-22    1.10594
 2015-12-23    1.10594
 2015-12-24    1.10594
 2015-12-28    1.10594
 2015-12-29    1.10594
 2015-12-30    1.10594
 2015-12-31    1.10594
 Name: High, dtype: float64, Time
 2015-01-01        NaN
 2015-01-02        NaN
 2015-01-05        NaN
 2015-01-06        NaN
 2015-01-07        NaN
 2015-01-08        NaN
 2015-01-09        NaN
 2015-01-12        NaN
 2015-01-13        NaN
 2015-01-14        NaN
 2015-01-15        NaN
 2015-01-16        NaN
 2015-01-19        NaN
 2015-01-20        NaN
 2015-01-21        NaN
 2015-01-22        NaN
 2015-01-23        NaN
 2015-01-26        NaN
 2015-01-27        NaN
 2015-01-28    1.10978
 2015-01-29    1.10978
 2015-01-30    1.10978
 2015-02-02    1.10978
 2015-02-03    1.10978
 2015-02-04    1.10978
 2015-02-05    1.10978
 2015-02-06    1.10978
 2015-02-09    1.10978
 2015-02-10    1.10978
 2015-02-11    1.10978
                ...   
 2015-11-19    1.06168
 2015-11-20    1.06168
 2015-11-23    1.05927
 2015-11-24    1.05927
 2015-11-25    1.05660
 2015-11-26    1.05660
 2015-11-27    1.05660
 2015-11-30    1.05578
 2015-12-01    1.05578
 2015-12-02    1.05508
 2015-12-03    1.05223
 2015-12-04    1.05223
 2015-12-07    1.05223
 2015-12-08    1.05223
 2015-12-09    1.05223
 2015-12-10    1.05223
 2015-12-11    1.05223
 2015-12-14    1.05223
 2015-12-15    1.05223
 2015-12-16    1.05223
 2015-12-17    1.05223
 2015-12-18    1.05223
 2015-12-21    1.05223
 2015-12-22    1.05223
 2015-12-23    1.05223
 2015-12-24    1.05223
 2015-12-28    1.05223
 2015-12-29    1.05223
 2015-12-30    1.05223
 2015-12-31    1.05223
 Name: Low, dtype: float64)

こんどは、高値、安値と一緒にチャートに表示させてみます。

In [19]:
pd.DataFrame({'High': high, 'Low': low, 'Hline': Hline, 'Lline': Lline},
            columns=['High', 'Low', 'Hline', 'Lline']).plot(figsize=(8,6))
Out[19]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb8322be0>

ストキャスティックス

最後にストキャスティックスです。これは、一定期間の最高値と最安値のバンドのなかで、現在の価格がどのあたりになるかというのを0から100の範囲で示したものです。まず、HLバンドと同じくKperiodの期間で最高値と最安値を求めます。そして、バンドの幅と終値の位置をslowingの期間で平滑化します。ここでは、後で比を取るので、平均ではなく、sum()で総和を取っています。最後に比をとったものをストキャスティックスのメインのラインとします。さらにシグナルのラインは、Dperiodの期間でSMAを取ります。

In [20]:
#Stochastics
Kperiod = 14 #%K期間
Dperiod = 3  #%D期間
Slowing = 3  #平滑化期間
Hline = high.rolling(Kperiod).max()
Lline = low.rolling(Kperiod).min()
sumlow = (close-Lline).rolling(Slowing).sum()
sumhigh = (Hline-Lline).rolling(Slowing).sum()
Stoch = sumlow/sumhigh*100
Signal = Stoch.rolling(Dperiod).mean()
Stoch,Signal
Out[20]:
(Time
 2015-01-01          NaN
 2015-01-02          NaN
 2015-01-05          NaN
 2015-01-06          NaN
 2015-01-07          NaN
 2015-01-08          NaN
 2015-01-09          NaN
 2015-01-12          NaN
 2015-01-13          NaN
 2015-01-14          NaN
 2015-01-15          NaN
 2015-01-16          NaN
 2015-01-19          NaN
 2015-01-20          NaN
 2015-01-21          NaN
 2015-01-22    14.656231
 2015-01-23    13.229104
 2015-01-26    11.999654
 2015-01-27    21.083220
 2015-01-28    26.099194
 2015-01-29    29.862459
 2015-01-30    25.824342
 2015-02-02    28.503854
 2015-02-03    36.744228
 2015-02-04    42.929792
 2015-02-05    54.060450
 2015-02-06    48.197115
 2015-02-09    47.040980
 2015-02-10    38.727516
 2015-02-11    43.602469
                 ...    
 2015-11-19    12.644368
 2015-11-20    14.234248
 2015-11-23    15.319879
 2015-11-24    10.961662
 2015-11-25    14.949375
 2015-11-26    16.845158
 2015-11-27    14.594531
 2015-11-30     9.069332
 2015-12-01    12.711760
 2015-12-02    17.355372
 2015-12-03    55.224629
 2015-12-04    70.803413
 2015-12-07    79.250218
 2015-12-08    75.915432
 2015-12-09    82.466268
 2015-12-10    85.972519
 2015-12-11    88.799180
 2015-12-14    86.340716
 2015-12-15    84.655216
 2015-12-16    78.944080
 2015-12-17    68.125116
 2015-12-18    64.227642
 2015-12-21    64.413827
 2015-12-22    72.506672
 2015-12-23    70.177931
 2015-12-24    67.064574
 2015-12-28    56.515635
 2015-12-29    57.427909
 2015-12-30    52.928191
 2015-12-31    38.553435
 dtype: float64, Time
 2015-01-01          NaN
 2015-01-02          NaN
 2015-01-05          NaN
 2015-01-06          NaN
 2015-01-07          NaN
 2015-01-08          NaN
 2015-01-09          NaN
 2015-01-12          NaN
 2015-01-13          NaN
 2015-01-14          NaN
 2015-01-15          NaN
 2015-01-16          NaN
 2015-01-19          NaN
 2015-01-20          NaN
 2015-01-21          NaN
 2015-01-22          NaN
 2015-01-23          NaN
 2015-01-26    13.294996
 2015-01-27    15.437326
 2015-01-28    19.727356
 2015-01-29    25.681624
 2015-01-30    27.261998
 2015-02-02    28.063552
 2015-02-03    30.357475
 2015-02-04    36.059291
 2015-02-05    44.578156
 2015-02-06    48.395786
 2015-02-09    49.766182
 2015-02-10    44.655204
 2015-02-11    43.123655
                 ...    
 2015-11-19     8.827028
 2015-11-20    10.526145
 2015-11-23    14.066165
 2015-11-24    13.505263
 2015-11-25    13.743638
 2015-11-26    14.252065
 2015-11-27    15.463021
 2015-11-30    13.503007
 2015-12-01    12.125208
 2015-12-02    13.045488
 2015-12-03    28.430587
 2015-12-04    47.794471
 2015-12-07    68.426087
 2015-12-08    75.323021
 2015-12-09    79.210639
 2015-12-10    81.451406
 2015-12-11    85.745989
 2015-12-14    87.037472
 2015-12-15    86.598371
 2015-12-16    83.313337
 2015-12-17    77.241471
 2015-12-18    70.432280
 2015-12-21    65.588862
 2015-12-22    67.049380
 2015-12-23    69.032810
 2015-12-24    69.916392
 2015-12-28    64.586046
 2015-12-29    60.336039
 2015-12-30    55.623912
 2015-12-31    49.636512
 dtype: float64)

これをサブウィンドウに表示させます。チャートウィンドウの方には、終値に加えて高値と安値のラインも表示させます。

In [21]:
plt.figure(0)
pd.DataFrame({'Close': close, 'High': high, 'Low': low},
            columns=['Close', 'High', 'Low']).plot(figsize=(8,6))
plt.figure(1)
pd.DataFrame({'Stoch': Stoch, 'Signal': Signal},
            columns=['Stoch', 'Signal']).plot(figsize=(8,2))
Out[21]:
<matplotlib.axes._subplots.AxesSubplot at 0x17fb998eb00>
<matplotlib.figure.Figure at 0x17fb8388a58>

以上、簡単に書けるテクニカル指標をいくつか紹介しました。