データフレームを取り扱うトレーニング
前回は、米国のテスラ社の株価と日本のトヨタ社の株価を2021年1月1日~2022年5月27日の株価データをYahooから読みだし、移動平均やMACDのテクニカル分析を行いました。
今回は、簡易的な売買アルゴリズムと、そのアルゴリズムに従った株価の売買を実施した際の損益を計算する検証ツールを作成します。
検証ツールがあれば、売買アルゴリズムの設計に集中できるし、先ずは、データフレームの扱いをトレーニングするつもりでご覧ください。
MACDの演算をモジュール化して汎用性を高める
短期指数、長期指数、MACDの指数をそれぞれ、short,long,macdというパラメータで受け渡し、あとで色々な指数で売買を実行してみようと思います。今回は、短期指数12、長期指数26、MACD指数9という一般的なパラメーターで実行しています。
import pandas_datareader.data as data
import pandas as pd
import numpy as np
import datetime
st = '2021-01-01'
ed = datetime.datetime.now()
us_stock = data.DataReader('TSLA','yahoo',st,ed)
def MACD(df,short,long,macd) :
MACD = df
MACD = MACD.drop(['High','Low','Open','Volume','Adj Close'], axis=1)
MACD = MACD.rename(columns={'Close':'株価'})
MACD['ShortEMA'] = MACD['株価'].ewm(span=short, adjust=False).mean()
MACD['LongEMA'] = MACD['株価'].ewm(span=long, adjust=False).mean()
MACD['MACD'] = MACD['ShortEMA'] - MACD['LongEMA']
MACD['Signal'] = MACD['MACD'].ewm(span=macd,adjust=False).mean()
return MACD
MACD = MACD(us_stock,12,26,9)
実行結果(MACDデータフレーム)は以下の通りです。
株価 ShortEMA LongEMA MACD Signal
Date
2020-12-31 705.669983 705.669983 705.669983 0.000000 0.000000
2021-01-04 729.770020 709.377681 707.455171 1.922510 0.384502
2021-01-05 735.109985 713.336497 709.503676 3.832821 1.074166
2021-01-06 755.979980 719.897033 712.946365 6.950668 2.249466
2021-01-07 816.039978 734.688255 720.582929 14.105326 4.620638
... ... ... ... ... ... ... ...
2022-06-06 714.840027 729.369651 769.738128 -40.368478 -51.413420
2022-06-07 716.659973 727.414316 765.806413 -38.392097 -48.809156
2022-06-08 725.599976 727.135186 762.828158 -35.692972 -46.185919
2022-06-09 719.119995 725.902080 759.590517 -33.688437 -43.686423
2022-06-10 696.690002 721.407914 754.931219 -33.523305 -41.653799
364 rows × 5 columns
MACDを使った初歩的な売買アルゴリズムを作ってみる
売買のタイミングは以下の通りです。
- MACDがSignalを超えた(買いシグナル点灯)の翌日に成買い投入
- MACDがSignalを下回った(売りシグナル点灯)の翌日に成売り投入
これを実現するため、MACDデータフレームに「買値」と「売値」の空データ(nan)を入れて用意しておき、MACDとSiganalがクロスした時に、us_stockの翌日(index[i+1]) の'Open'値を入力する様になります。
flagは、トレンドの方向性を示し、'0'で下降トレンド。'1'で上昇トレンド。最初はどちらから始まるかわからないので、初期値を'-1'としています。つまり「売り」からスタートすることもあるので検証ツール側で対応しています。
def trade(MACD) :
flag = -1
MACD['買値'] = np.nan
MACD['売値'] = np.nan
for i in range(0,len(MACD)-1) :
if MACD.at[str(MACD.index[i])[0:10],'MACD'] > MACD.at[str(MACD.index[i])[0:10],'Signal']:
if flag == 0 :
MACD.at[str(MACD.index[i+1])[0:10],'buy'] = us_stock.at[str(MACD.index[i+1])[0:10],'Open']
flag = 1
elif MACD.at[str(MACD.index[i])[0:10],'MACD'] < MACD.at[str(MACD.index[i])[0:10],'Signal']:
if flag == 1 :
MACD.at[str(MACD.index[i+1])[0:10],'sell'] = us_stock.at[str(MACD.index[i+1])[0:10],'Open']
flag = 0
else :
pass
return MACD
もしも当日(今日)、MACDとSignalのクロスが発生すると、まだ用意できていない翌日(index[i+1])のデータを読みにいってエラーが発生してしまうので前日で処理が止まる様にfor文はrange(0,len(MACD)-1)としています。
compare_dateは、「買値」と「売値」の日付の前後関係をチェックするモジュールとなります。「売値」が先に来ていたら、「売値」を消して、常に「買値」→「売値」の順番になるように調整しています。
dropnaは、空データの行を消す関数で、「買値」が入った行だけを残したdf_buyデータフレームと「売値」が入った行だけを残したdf_sellデータフレームに分けて集計しています。
def compare_date(buy,sell,line) :
buyDay = str(buy.index[line])
sellDay = str(sell.index[line])
buy_date = datetime.date(int(buyDay[0:4]), int(buyDay[5:7]), int(buyDay[8:10]))
sell_date = datetime.date(int(sellDay[0:4]), int(sellDay[5:7]), int(sellDay[8:10]))
if buy_date < sell_date :
compare_result = True
else :
compare_result = False
return compare_result
df_buy = MACD.dropna(subset=['buy'])
df_sell = MACD.dropna(subset=['sell'])
compare_result = compare_date(df_buy,df_sell,0)
if not compare_result :
print('delete top of df_sell')
df_sell = df_sell.drop(df_sell.index[0])
df_buyのデータフレームは以下の通りです。
株価 ShortEMA LongEMA MACD Signal buy sell
Date
2021-03-15 707.940002 682.511950 713.631807 -31.119856 -37.675577 694.090027 NaN
2021-03-31 667.929993 650.116518 674.170400 -24.053883 -27.049232 646.619995 NaN
2021-05-27 630.849976 609.850086 630.708062 -20.857976 -25.777063 620.239990 NaN
2021-07-13 668.539978 662.842883 651.191190 11.651693 11.405484 686.320007 NaN
2021-08-02 709.669983 668.073834 659.092429 8.981405 5.079759 700.000000 NaN
2021-08-31 735.719971 709.426132 697.292239 12.133894 9.797616 733.000000 NaN
2021-09-28 777.559998 759.322573 742.458842 16.863731 15.062808 787.200012 NaN
2021-10-08 785.489990 777.149640 760.955110 16.194531 16.254005 796.210022 NaN
2021-10-13 811.080017 787.718074 769.706103 18.011972 16.726700 810.469971 NaN
2021-12-28 1088.469971 1020.703096 1023.387065 -2.683969 -14.426391 1109.489990 NaN
2022-01-13 1031.560059 1066.715098 1056.977137 9.737961 11.906165 1109.069946 NaN
2022-02-09 932.000000 925.901006 957.499236 -31.598231 -34.241718 935.000000 NaN
2022-02-16 923.390015 911.713725 938.760253 -27.046528 -31.846541 914.049988 NaN
2022-03-02 879.890015 858.873873 889.552889 -30.679016 -35.729036 872.130005 NaN
2022-03-17 871.599976 832.015790 853.048312 -21.032522 -27.633338 830.989990 NaN
2022-05-31 758.260010 728.482053 783.341565 -54.859512 -63.585998 773.840027 NaN
df_sellのデータフレームは以下の通りです。
株価 ShortEMA LongEMA MACD Signal buy sell
Date
2021-03-30 635.619995 646.877704 674.669633 -27.791929 -27.798070 NaN 601.750000
2021-04-29 677.000000 709.030460 704.119302 4.911158 8.656600 NaN 699.510010
2021-07-12 685.700012 661.807047 649.803287 12.003760 11.343932 NaN 662.200012
2021-07-15 650.599976 659.727504 651.297521 8.429984 10.590903 NaN 658.390015
2021-08-17 665.710022 695.070968 684.222777 10.848190 14.016113 NaN 672.659973
2021-09-21 739.380005 741.976170 729.006247 12.969923 15.036459 NaN 734.789978
2021-10-07 793.609985 775.633213 758.992319 16.640894 16.268874 NaN 785.460022
2021-10-11 791.940002 779.425081 763.250287 16.174794 16.238163 NaN 787.650024
2021-11-11 1063.510010 1091.187309 1015.065071 76.122239 88.897272 NaN 1102.770020
2022-01-12 1106.219971 1073.106924 1059.010504 14.096420 12.448217 NaN 1078.849976
2022-01-14 1049.609985 1064.083542 1056.431423 7.652120 11.055356 NaN 1019.880005
2022-02-14 875.760010 907.256358 941.394663 -34.138305 -33.708402 NaN 861.570007
2022-02-23 764.039978 867.929821 908.914070 -40.984249 -33.289836 NaN 830.429993
2022-03-15 801.890015 822.016608 852.470914 -30.454307 -29.918049 NaN 775.270020
2022-04-11 975.929993 1034.072818 993.467041 40.605778 48.490256 NaN 980.400024
「買値」と「売値」から収益計算を行う
まずは、df_buyデータフレームとdf_sellデータフレームの長さを揃えて、一行づつ買った日と売った日の前後関係をチェックし、損益を計算します。
損益の計算は、一行づつ行いList形式で計算結果を蓄え、List形式をデータフレームに変換してから、to_html関数でHTMLのテーブル形式に変換します。
buySellList = []
total_gain = 0
write_table = 'html/revenue.html'
if len(df_buy) != len(df_sell) :
df_buy = df_buy.drop(df_buy.index[len(df_buy)-1])
print('Drop df_buy line : ',(len(df_buy)-1))
for line in range(len(df_buy)) :
compare_result = compare_date(df_buy,df_sell,line)
gain = int( df_sell.at[str(df_sell.index[line])[0:10],'sell'] - df_buy.at[str(df_buy.index[line])[0:10],'buy'] )
total_gain = total_gain + gain
if compare_result :
tmp = [ str(df_buy.index[line])[0:10] , #買った日
int(df_buy.at[str(df_buy.index[line])[0:10],'buy']) , #買った株価
str(df_sell.index[line])[0:10] , #売った日
int(df_sell.at[str(df_sell.index[line])[0:10],'sell']) , #売った株価
gain , #損益
round((gain * 100 / int(df_buy.at[str(df_buy.index[line])[0:10],'buy'])) , 1) , #損益率
total_gain #トータル損益
]
else :
tmp = ['0000-01-01',0,'0000-01-01',0,0,0,0]
buySellList.append(tmp)
cols = ['買った日', '買った株価','売った日', '売った株価','損益','損益率','トータル損益']
df_revenue = pd.DataFrame(buySellList,columns=cols)
f = open(write_table, 'w',encoding='utf-8')
try :
f.write(df_revenue.to_html(index=False))
finally :
f.close()
HTMLのテーブルは以下の通りです。
買った日 | 買った株価 | 売った日 | 売った株価 | 損益 | 損益率 | トータル損益 |
---|---|---|---|---|---|---|
2021-03-15 | 694 | 2021-03-30 | 601 | -92 | -13.3 | -92 |
2021-03-31 | 646 | 2021-04-29 | 699 | 52 | 8.0 | -40 |
2021-05-27 | 620 | 2021-07-12 | 662 | 41 | 6.6 | 1 |
2021-07-13 | 686 | 2021-07-15 | 658 | -27 | -3.9 | -26 |
2021-08-02 | 700 | 2021-08-17 | 672 | -27 | -3.9 | -53 |
2021-08-31 | 733 | 2021-09-21 | 734 | 1 | 0.1 | -52 |
2021-09-28 | 787 | 2021-10-07 | 785 | -1 | -0.1 | -53 |
2021-10-08 | 796 | 2021-10-11 | 787 | -8 | -1.0 | -61 |
2021-10-13 | 810 | 2021-11-11 | 1102 | 292 | 36.0 | 231 |
2021-12-28 | 1109 | 2022-01-12 | 1078 | -30 | -2.7 | 201 |
2022-01-13 | 1109 | 2022-01-14 | 1019 | -89 | -8.0 | 112 |
2022-02-09 | 935 | 2022-02-14 | 861 | -73 | -7.8 | 39 |
2022-02-16 | 914 | 2022-02-23 | 830 | -83 | -9.1 | -44 |
2022-03-02 | 872 | 2022-03-15 | 775 | -96 | -11.0 | -140 |
2022-03-17 | 830 | 2022-04-11 | 980 | 149 | 18.0 | 9 |
- 最高値が36.0%増の292
- 最低値が13.3%減の-92
今回は比較的値動きの激しいテスラの株価で検証しましたが、値動きの小さい株価で検証したり、MACDのパラメーターを変更したり、平均移動やRSIのデータ分析を加えたり、利益を増やす手段は無限大ですよ~(^^♪
更新履歴
- 2022.06.12
- 新規作成
0 件のコメント:
コメントを投稿