8時間足を使った自動売買

8時間足での自動売買の考え方

突然だけど,個人的には8時間足が好きだ.日足より短いスパンだけど,長期トレンドを見やすいし,1日3本の足が日本時間,ロンドン時間,アメリカ時間を順を追っているようなのも良い.この8時間足を使って,大まかなトレンドを把握しながら自動売買してみたくて,pythonでコードを書いてみた.

…で,今,VPSでは,pythonで記載した自動売買コードを回して,システムトレードを行っている.これは,oandaAPIで8時間足をダウンロードし,ある独自のアルゴリズムに従って売買を行うものだ.
例によってコードの考え方など忘れそうなので,メモを残しておくことにした.
考え方としては,下記手順を取る.

  1. 8時間足なので,1日3回コードを呼び出す.
  2. 売買するときに,履歴データをcsvで残す.
  3. コードを呼び出して,履歴ファイルの最新日時と,ダウンロードした足の最新日時に相違があるなら,「データ更新」と見做して自動売買開始

ブロック図とコード

最初に,プログラム全体のブロック図を書いてみた.基本的に己の頭の悪さを自覚しているので,最初に紙でプログラムの流れを書きだしてからコーディングしたほうがミスが少ない.…それでもバグは出るけどさ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^)ノシ')

 

コメント

タイトルとURLをコピーしました