8時間足での自動売買の考え方
突然だけど,個人的には8時間足が好きだ.日足より短いスパンだけど,長期トレンドを見やすいし,1日3本の足が日本時間,ロンドン時間,アメリカ時間を順を追っているようなのも良い.この8時間足を使って,大まかなトレンドを把握しながら自動売買してみたくて,pythonでコードを書いてみた.
…で,今,VPSでは,pythonで記載した自動売買コードを回して,システムトレードを行っている.これは,oandaAPIで8時間足をダウンロードし,ある独自のアルゴリズムに従って売買を行うものだ.
例によってコードの考え方など忘れそうなので,メモを残しておくことにした.
考え方としては,下記手順を取る.
- 8時間足なので,1日3回コードを呼び出す.
- 売買するときに,履歴データをcsvで残す.
- コードを呼び出して,履歴ファイルの最新日時と,ダウンロードした足の最新日時に相違があるなら,「データ更新」と見做して自動売買開始
ブロック図とコード
最初に,プログラム全体のブロック図を書いてみた.基本的に己の頭の悪さを自覚しているので,最初に紙でプログラムの流れを書きだしてからコーディングしたほうがミスが少ない.…それでもバグは出るけどさorz
このブロック図で表したコードを,1日3回実行する.具体的には,朝イチは日付変更の直前(夏時間なら5時53分,冬時間なら6時53分),それ以外は,夏時間なら14時01分と22時01分,冬時間なら15時01分と23時01分に実行する.
朝イチの1回はその瞬間でのレートを売買判断に用いる.後者の2回は8時間足が更新され,終値未確定の最新の足が始まっているので,最新の足の一つ前の足の終値データを売買判断に用いる.
以下,コードの全体を掲載する.我ながら雑多なコードだわ…コード内で使っている自作関数は,順を追って,ブログにメモとしてアップする…と思う…
import os import pandas as pd import datetime from oandapyV20 import API import FuncOanda2 #OandaAPIを用いる自作関数 import FuncFX #OandaAPIを用いない,FX計算用の関数 import FuncGeneral #その他一般用途の関数 #本番用 アカウント情報 accountID = "123-456-7890123-456" access_token = "12345678901234567890123456789012-12345678901234567890123456789012" api = API(access_token=access_token, environment="live") Amount=500#取引通貨量 CurrencyPairList=["USD_JPY","EUR_JPY","GBP_JPY","AUD_JPY","NZD_JPY","CAD_JPY"] # 通貨ペア AshiInfo = "H8" PriceInfo="B" cnt_C=200#自動売買時に取得する足数 toAddress='********@*******' #実行結果をメールで送るときの,送り先アドレス #履歴ファイルの読み込み HistoryDataPath = "E:/ML_Training/WorkSpace/201004_FX/SysTraHistory/" FullFileName=HistoryDataPath+'HistoryH8.csv' FuncGeneral.SendMail(toAddress, 'Opened', 'Batch-file is Opened!!') def SysTraGO(): # まずは足データの最新時刻を取得する params = { "granularity": AshiInfo, # 取得する足 "count": 2, # 取得する足数.最新だけ欲しいので1で良い "price": PriceInfo, # Bid } (candle_temp_DF, time_temp_DF) = FuncOanda2.get_fx_ohlc5(api,"USD_JPY", params) # 通貨ペアは何でもいいのでUSDにしといた #最新の足データのダウンロードが終わったところで,プログラム起動時刻を取得 time_Now = datetime.datetime.now() time_exe = time_Now.strftime("%Y-%m-%d %H:%M:%S") HH_exe = int(time_Now.hour) # ↓datetime型で日時を取得 if HH_exe != 5 and HH_exe != 6: jNow=1 else: jNow=0 IndexList = list(range(cnt_C - 1, -1, -1))# 最新の足が0,さかのぼるごとに1,2,3,…となるように設定 time_ReadLatest = time_temp_DF[['time_str']][1-jNow:2-jNow].iloc[0, 0] print('売買判断に使う足データの日時は', time_ReadLatest) if os.path.exists(FullFileName)==False: print('履歴ファイルがないので,自動売買かつ履歴ファイル作成ルートね') F_Ini = 1 # 初回トレードフラグを立てる F_SysTra=1 #自動売買実行フラグを立てる else: print('履歴ファイルがあるね') F_Ini = 0 #履歴ファイルの最新日時を取得する HisData_DF = pd.read_csv(FullFileName) time_HistoryLatest = HisData_DF[['time_str']].tail(1).iloc[0, 0] # tail(1)でラスト1行目のDataFrame(ここでは一つ)を抽出,iloc[0,0]で値を抽出 print('履歴ファイルの最新の日時は', time_HistoryLatest) time_HistoryLatest=FuncGeneral.Str2DateTime(time_HistoryLatest)#読み込んだ日時の文字列を,柔軟にdatetime形式に読み替える関数 if time_ReadLatest==time_HistoryLatest: print('足データの更新なし') F_SysTra=0 else: print('足データの更新あり,自動売買処理へ') F_SysTra=1 if F_SysTra==1:#自動売買開始 params = { "granularity": AshiInfo, # 取得する足 "count": cnt_C, # 取得する足数 "price": PriceInfo, # Bid } CntPair=0 for InputCurrencyPair in CurrencyPairList: print('売買処理する通貨ペア=',InputCurrencyPair) #足データ読み込み (candle_DF, time_DF) = FuncOanda2.get_fx_ohlc5(api,InputCurrencyPair, params) Vc_DF = candle_DF[["c"]] # 終値抽出 #終値データ→入力用データに変換 time_DF.index = IndexList # 最新の足が0,さかのぼるごとに1,2,3,…となるように変更 CalValue_DF = FuncFX.Cal_FxTech_3(Vc_DF) InputData_DF=pd.concat([Vc_DF,CalValue_DF],axis=1) InputData_DF.index=IndexList #最新の足が0,さかのぼるごとに1,2,3,…となるように変更 InputData_DF=InputData_DF.rename(columns={'o': 'Vo','h': 'Vh','l': 'Vl','c': 'Vc'}) Vc=InputData_DF.at[jNow, 'Vc'] #現在のポジション情報取得 Posi_Long,PriceAve_Long,PL_Long,Posi_Short,PriceAve_Short,PL_Short=FuncOanda2.PosiCheck_Oanda_ver0(accountID,api,InputCurrencyPair) Posi_pre=Posi_Long+Posi_Short if Posi_pre==0: Vposi_pre=InputData_DF.at[jNow,'Vc'] else: Vposi_pre=PriceAve_Long+PriceAve_Short #両建てなし #売買するかを判断する (Settle, Order) = FuncFX.OS_OF_ver3(InputData_DF, jNow,Posi_pre, Vposi_pre, Amount) #決済 if Settle!=0: (SetUnits,SetPrice,F_SetError)\ =FuncOanda2.MarketSettle_Oanda_ver0(accountID,api,InputCurrencyPair, Settle, 0) else: (SetUnits, SetPrice, F_SetError)=(0,0,0) #新規注文 if Order!=0: (OrderUnits,OrdPrice,F_OrdError)\ =FuncOanda2.MarketOrder_Oanda_ver1(accountID,api,InputCurrencyPair, Order) else: (OrderUnits, OrdPrice, F_OrdError)=(0,0,0) #取引後のポジション情報 (Posi_Long, PriceAve_Long, PL_Long, Posi_Short, PriceAve_Short, PL_Short) \ = FuncOanda2.PosiCheck_Oanda_ver0(accountID,api,InputCurrencyPair) Posi=Posi_Long+Posi_Short PriceAve=PriceAve_Long+PriceAve_Short PL=PL_Long+PL_Short #取引後の情報をデータフレーム化 LabelList = ["Vc","Settle", "Order", "SetUnits", "SetPrice", "F_SetError", "OrderUnits", "OrdPrice", "F_OrdError", "Posi","PriceAve", "PL"] LabelList=FuncGeneral.LabelInList_AddStr(LabelList, "("+InputCurrencyPair+")")#リスト内の各ラベルに通貨ペア名を追加 TradeDataList = [[Vc, Settle, Order, SetUnits, SetPrice, F_SetError, OrderUnits, OrdPrice, F_OrdError, Posi, PriceAve,PL]] TradeData_DF=pd.DataFrame(TradeDataList,columns=LabelList) LatestTime_DF=pd.DataFrame([[time_ReadLatest,time_exe]],columns=["time_str","time_exe"]) if CntPair==0: print('最初のペア') AddHistory_DF=pd.concat([LatestTime_DF,TradeData_DF],axis=1) #ついでにメール本文を作成 bodyText='Used Data='+str(time_ReadLatest)+'\n\n' bodyText=bodyText+InputCurrencyPair+',Vc='+str(Vc)+'\nSettle='+str(Settle)+',Order='+str(Order)+'\n\n' else: print(CntPair+1,'つ目以降のペア') AddHistory_DF = pd.concat([AddHistory_DF, TradeData_DF],axis=1) # ついでにメール本文を作成 bodyText =bodyText+ InputCurrencyPair+',Vc='+str(Vc)+'\nSettle='+str(Settle)+',Order='+str(Order)+'\n\n' #ここまででデータフレーム化完了 CntPair=CntPair+1 print(AddHistory_DF) #履歴データ作成,保存 if F_Ini==1: print('新規に履歴ファイルを作成') HisData_DF=AddHistory_DF else: print('履歴ファイルを更新') #print(HisData_DF) HisData_DF=pd.concat([HisData_DF, AddHistory_DF]) HisData_DF.to_csv(FullFileName,index=False) #全部終わったらメール送信 FuncGeneral.SendMail(toAddress, 'time='+time_exe, bodyText) # 以下,メイン処理 Time_Now=datetime.datetime.now()#プログラム実行時の時刻を抽出 (SummerCheck,MarketCheck)=FuncFX.Judge_SummerAndMarketOpen_ver2(Time_Now)#プログラム実行時が夏時刻か否かを抽出 HH_Now=int(Time_Now.hour) print('処理開始時刻:',Time_Now,' / SummerCheck=',SummerCheck) F_SysTraGo=0 if MarketCheck==1: if HH_Now >= 5 and HH_Now <= 6: if SummerCheck == 1: # 夏時刻用の処理 HHMM_Sta = "05:53:00" else: HHMM_Sta = "06:53:00" F_SysTraGo=1 elif HH_Now >= 13 and HH_Now <= 14: if SummerCheck == 1: # 夏時刻用の処理 HHMM_Sta = "14:01:00" else: HHMM_Sta = "15:01:00" F_SysTraGo=1 elif HH_Now >= 21 and HH_Now <= 22: if SummerCheck == 1: # 夏時刻用の処理 HHMM_Sta = "22:01:00" else: HHMM_Sta = "23:01:00" F_SysTraGo=1 if F_SysTraGo==1: FuncGeneral.ProcessTimer(HHMM_Sta, SysTraGO)#自作タイマー関数で,システムトレードプログラムを実行する print('処理終了(^o^)ノシ')
コメント