Protraの出力を分析してみます。
Excelでも できないことはないですが、せっかくなので勉強中のPythonを使ってみます。
売買データを取り込む
Protraをご使用の方ならご存知の通り、PtSimで売買ストラテジを動作させると売買履歴が表示されます
※下の例はストラテジコードの1行目に# loop-type: date-only
を付けて、日付ごとの繰り返し実行したものです。詳しくはこちら(Protra公式)、もしくは当ブログの記事をご参照ください
銘柄コード,銘柄名,売買日,買値/売値,株数,買/売の順で並んでいます。
これをコピペし、エンコード形式「utf-8」、csvで保存します。
次いでPythonで 作成したcsvファイルを取り込みます。
pandasを使います。Protraの出力は、空白で区切られたデータのため、sep='\s+
を使用しています。
1 2 3 |
import pandas as pd td = pd.read_csv('testdata.csv', names = ('code','name','date','price','unit','buysell'), sep='\s+') td.head() |
うまく取り込めました。ちなみにJupyterを使っています。
取り込んだデータを出力する時は、以下のコードを使用します。
1 2 3 |
td.to_csv('testdate-2.csv') td.to_csv('testdate-3.csv', index = False) td.to_csv('testdate-4.csv', index = False, header = False) |
上から、普通に出力,インデックスなし,インデックスなし+ヘッダーなし、となります。
pandasの出力関数には、多くの引数(オプション)がありますが、まだまだ使いこなせていません…。
データを一列に並べる
さてProtraからの出力データは、買と売が別々の列で表示されます。
今後 データを扱う上での利便性を考え、同じ取引を一列にまとめます。
◆ 通常の出力結果の場合(# loop-type: date-only
を使わない)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import pandas as pd import numpy as np df = pd.DataFrame() for i, rows in td.iterrows(): if rows['buysell'] == '買': code = rows['code'] name = rows['name'] bprice = rows['price'] bdate = rows['date'] for j,rows in td.iterrows(): try: if code == rows['code'] and rows["buysell"] == '売': sdate = rows['date'] sprice = rows['price'] unit = rows['unit'] se = pd.Series([code,name,bdate,bprice,sdate,sprice,unit], ['code','name','bdate','bprice','sdate','sprice','unit']) df = df.append(se,ignore_index=True) #print(code, name, bdate, sdate) break except: print('e',bdate,name) df.to_csv('final.csv') print('finish') |
◆ # loop-type: date-only
を使う場合、時系列順に売買履歴が表示されるため少し改変
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import pandas as pd import numpy as np df = pd.DataFrame() for i, rows in td.iterrows(): if rows['buysell'] == '買': code = rows['code'] name = rows['name'] bprice = rows['price'] bdate = rows['date'] tdtemp = td.loc[i:] for j,rows in tdtemp.iterrows(): try: if code == rows['code'] and rows["buysell"] == '売': sdate = rows['date'] sprice = rows['price'] unit = rows['unit'] se = pd.Series([code,name,bdate,bprice,sdate,sprice,unit], ['code','name','bdate','bprice','sdate','sprice','unit']) df = df.append(se,ignore_index=True) #print(code, name, bdate, sdate) break except: print('e',bdate,name) df.to_csv('final.csv') print('finish') |
うーん、もっと簡潔に書ける気がする・・・。
何をやっているか見ていきます。
1 2 3 4 5 6 7 |
if rows['buysell'] == '買': code = rows['code'] name = rows['name'] bprice = rows['price'] bdate = rows['date'] tdtemp = td.loc[i:] |
まずはこちら。
もし、buysell列が「買」なら、コード,銘柄名,買値,買日付を変数に代入しています。
次いで、該当行以降のデータフレームを、tdtempとして作成します。単純に二重ループにしてしまうと、再度 一行目から検索を開始し、買い,売りの組み合わせがずれるためです。
イメージはこんな感じ↓
1 2 3 4 |
if code == rows['code'] and rows["buysell"] == '売': date = rows['date'] sprice = rows['price'] unit = rows['unit'] |
新しく作ったデータフレーム tdtmpで、直近の「売」を探します。
code番号が「買」と等しく、かつ buysell列が「売」なら、売日付,売値,株数を変数に代入しています。
あとは、出来上がったcsvファイルを”final.csv”として出力します。
final.csvを読み込んで、表示させます。
1 2 3 |
import pandas as pd td1 = pd.read_csv('final.csv', index_col=0) td1.head() |
別の行になっていた売り/買いを、一行にまとめることができました。
データの型変換
それぞれの列の型を見てみましょう。
1 2 3 4 5 6 7 8 9 10 |
td1.dtypes #bdate object #bprice object #code float64 #name object #sdate object #sprice object #unit object #dtype: object |
コード以外は文字列のようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
td1['code'] = td1['code'].astype(np.int64) td1['bprice'] = td1['bprice'].str.replace('円','') td1['bprice'] = td1['bprice'].astype(np.int64) td1['sprice'] = td1['sprice'].str.replace('円','') td1['sprice'] = td1['sprice'].astype(np.int64) td1['unit'] = td1['unit'].str.replace('株','') td1['unit'] = td1['unit'].astype(np.int64) td1.dtypes #bdate object #bprice int64 #code int64 #name object #sdate object #sprice int64 #unit int64 #dtype: object |
コード番号,買値/売値,株数は、不要な文字を消して、文字列→整数へ型変換しました。
1 2 3 4 5 6 7 |
td1['bdate'] = pd.to_datetime(td1['bdate']) td1['sdate'] = pd.to_datetime(td1['sdate']) td1.dtypes #bdate datetime64[ns] #sdate datetime64[ns] |
買/売日付は、文字列→日付に型変換しました。
さあ、型変換後のデータフレームを見てみましょう。
1 |
td1.head() |
あれ!?
01/07/17 が 2017-01-07となっています!!
それもそのはず、yy/mm/dd 表記は日本のローカル表記なんですよね…。mm/dd/yy が一般的な表記となります。
色々調べましたが 型変換でどうにかすることはできず、final.csvの出力を変更することにしました。
変更後はこちら↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import pandas as pd import numpy as np df = pd.DataFrame() for i, rows in td.iterrows(): if rows['buysell'] == '買': code = rows['code'] name = rows['name'] bprice = rows['price'] if int(rows['date'][:2]) >= 90: bdate = '19'+rows['date'] else: bdate = '20'+rows['date'] tdtemp = td.loc[i:] for j,rows in tdtemp.iterrows(): try: if code == rows['code'] and rows['buysell'] == '売': if int(rows['date'][:2]) >= 90: sdate = '19'+rows['date'] else: sdate = '20'+rows['date'] sprice = rows['price'] unit = rows['unit'] se = pd.Series([code,name,bdate,bprice,sdate,sprice,unit], ['code','name','bdate','bprice','sdate','sprice','unit']) df = df.append(se,ignore_index=True) #print(code, name, bdate, sdate) break except: print('e',bdate,name) df.to_csv('final.csv') print('finish') |
- bdate, sdate の頭2文字が90以上なら、yy/mm/dd ⇨ 19yy/mm/dd
- それ以外なら yy/mm/dd ⇨ 20yy/mm/dd
となるようにしました。
株価データが1990年以降にしかないことが前提の変更です。
こういうその場しのぎが、2000年問題やら2038年問題につながrムニャムニャ…
再度 final.csvを読み込んで、表示させます。
日付の年表記をyyyyにできました!(まだ文字列です)
同じように型変換し、最終的に以下のようになりました。今度は日付型でも ばっちり2001年になっています。
見た目は上の図と変わっていませんが、型は意図したように変換されています。
1 2 3 4 5 6 7 8 9 10 |
td1.dtypes #bdate datetime64[ns] #bprice int64 #code int64 #name object #sdate datetime64[ns] #sprice int64 #unit int64 #dtype: object |
今回はここまで!まだ準備が済んだ段階です。
次回、データをグラフ化していきます。