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^)ノシ')



コメント