ExcelVBAではじめるバイナリーオプション自動取引

5. バックテストについて

e.テスト例


テスト例

テキストファイルからシートへの出力

 必要な通貨のみを分離したとはいえ、依然大量のテキストファイルを処理しなくてはなりません。

 ところで、実際にリアルタイムで自動取引ツールを稼働させる場合、レートの取得を行いますが、サーバ負荷を考えるとそこまで密度の高い情報を取得することは困難です。

 実際には数十秒単位でレートを取得し、その累積した情報を元にテクニカル指標を算出することになると思いますが、さしあたり単純化のために終了レート(分足の終値)のみを参考情報として採用したいと思います。

 後で指標を計算しやすいように、縦方向に並べて出力することにします。ここでは1シートに対して1月分のデータを出力してみましょう。

 実はこのヒストリカルデータにはたまにデータ抜けがあるという欠点があるのですが、ここではデータ抜けと週末等をまたぐ等の時間的ギャップを無視して一連のデータとして扱うことにします。

 ちなみに余談ですが、Excel2010でマクロを使用するブックを保存する際にマクロ有効ブックの場合".xlsm"形式を選択しますが、バイナリブック形式".xlsb"を選択することでファイルサイズを大幅に小さくすることができます。

必要な計算を行う

 ここで、ヒストリカルデータをシート上に展開するのと同時に、仮想シグナルの算出も行います。

 いろいろ試してみるとよいとは思いますが、最初に例に出した「3分間隔の終値が6連続同一方向へ動いたら、1分後に逆張り」という仮シグナルについてテストしてみましょう。

 3分×6回の次回購入ですから、仮にリアルタイムで算出する場合、最初の購入まで19分かかります。

 また、実際には購入まで1分を切ってからシグナルを算出した方が精度が高まると思われますので、分足終値の隣に、直前判定用の列を作ります。1分未満のデータはないので、ここでは1分前に判定を行うことにして、左のレートをコピーするようにします。

 今度は『正解』となる、結果を表示する列を作ります。購入から10分で結果が出るタイプを想定して、10分後のレートが円高なら-1を、円安なら+1を、それ以外(同値)なら0を表示するようにします。

 次に、円高か円安かの方向を示すために、3分前のレートと比較して円高なら-1を、円安なら+1を、それ以外なら0を表示する列を作ります。その隣に3分間隔の連続回数を示す列を作ります。

 更にその横に、連続回数に基づくシグナルの列を作ります。今回は6連続時の逆張りをテストするので、過去6回分の値を合計し、+6なら-1を、-6なら+1を、それ以外なら0を表示するようにします。この「-1」、「+1」がそれぞれ「円高」、「円安」を示すシグナルになります。

 その後、シグナルが正解(的中)したか否かを判定する列を作ります。具体的には同じ行のシグナルと結果を掛け算します。計算結果が『+1』なら的中、それ以外はハズレ又はシグナルなしを示すことになります。今回はトータルの成績だけを求めてみます。

 というようなシートを作るコード例が以下です。

Sub SpreadHistDat() '///概要 '月別にシートを作成し、ヒストリカルデータを展開する。 '/// '/*変数リスト Dim sheetname As String '作成するシート名(yyyymm) Dim line As Variant 'ファイル内の文字列を一行読み込むための配列 Dim daydata(24 * 60) As Variant '1日分のline配列を格納する配列 Dim inputpath As String '入力元フォルダ Dim filelist(20 * 365) As String '処理対象のファイルリスト Dim filename As Variant 'ファイル名 Dim i As Long, n As Long 'カウンタ用変数 Dim buf As String '読み込み用バッファ Dim ff As Long 'フリーファイル変数 Dim newfile As String '新しいファイル Dim month As String '月名 Dim filedate As Variant 'データの日付 Dim filetime As Variant 'データの時間 Dim datnum As Long '処理番号 Dim minutenum As Long '抜け分データ検出用番号 Dim sheetnum As Long '*/ Application.ScreenUpdating = False '表示停止 Application.Calculation = xlCalculationManual '再計算停止 inputpath = ThisWorkbook.Path + "\USDJPY\" '"※\マークのHTMLエスケープ用。特に意味なし。 '入力フォルダ内のファイルリストを取得 i = 0 'カウンタクリア filename = Dir(inputpath + "*.txt") 'ファイル名(1件目)を取得 Do While filename <> "" filelist(i) = inputpath + filename 'パス+ファイル名をリストに保存 filename = Dir() 'ファイル名(2件目以降)を取得 i = i + 1 Loop 'ファイルを順に処理 For Each filename In filelist ff = FreeFile 'フリーファイル変数をセット buf = "" 'バッファを初期化 Erase daydata() '一日分の配列を初期化 i = 0 'カウンタ用変数を初期化 If filename = "" Then '終了 Exit For End If Open filename For Input As #ff '入力ファイルを読み込む Do Until EOF(1) Line Input #ff, buf line = Split(buf, ",") '一行分を分割して配列に格納 If line(0) = "USDJPY" Then '対象通貨ペア daydata(i) = line '分足データを配列に格納 i = i + 1 'カウンタ更新 End If Loop Close #ff '1ファイル読み込み終了 If IsEmpty(daydata(0)) = False Then 'シートを作成して必要なデータを並べる If month <> Left(daydata(0)(1), 6) Then '新しい月 month = Left(daydata(0)(1), 6) '月名取得 Application.ScreenUpdating = False '表示停止 sheetname = month 'シート名格納 Worksheets.Add(after:=Sheets(ActiveSheet.Name)).Name = sheetname 'シート作成 With Sheets(sheetname) datnum = 0 '処理番号初期化 sheetnum = sheetnum + 1 .Cells(5, 3) = "年月日" .Cells(5, 4) = "曜日" .Cells(5, 5) = "時間" .Cells(5, 6) = daydata(0)(0) '通貨 .Cells(5, 7) = "判定時レート" .Cells(5, 8) = "10分後の方向" .Cells(5, 9) = "3分前からの方向" .Cells(5, 10) = "同一方向連続回数" .Cells(5, 11) = "シグナル" .Cells(5, 12) = "シグナルの結果" .Cells(4, 13) = "円安シグナル" .Cells(5, 13) = "=COUNTIF(C[-2],1)" .Cells(4, 14) = "円高シグナル" .Cells(5, 14) = "=COUNTIF(C[-3],-1)" .Cells(4, 15) = "HIT数" .Cells(5, 15) = "=COUNTIF(C[-3],1)" End With End If With Sheets(sheetname) minutenum = 0 '抜け分検出用番号を初期化 For i = 0 To 24 * 60 '24時間×60分ループ If IsEmpty(daydata(i)) Then 'データがなくなったら終了 Exit For End If If minutenum < 60 Then minutenum = minutenum + 1 '1分進める datnum = datnum + 1 '処理番号を進める Else minutenum = 0 'リセット End If filedate = _ Left(daydata(i)(1), 4) + "/" + Mid(daydata(i)(1), 5, 2) + "/" + Right(daydata(i)(1), 2) '日付 filetime = _ Left(daydata(i)(2), 2) + ":" + Mid(daydata(i)(2), 3, 2) + ":" + Right(daydata(i)(2), 2) '時間 .Cells(5 + datnum, 3) = filedate '日付 .Cells(5 + datnum, 4) = Weekday(filedate) '曜日 .Cells(5 + datnum, 5) = filetime '時間 .Cells(5 + datnum, 6) = daydata(i)(3) '開始レート .Cells(5 + datnum, 7) = "=RC[-1]" 'バックテスト時は1分前の値 If Mid(filetime, 5, 1) = "4" Or Mid(filetime, 5, 1) = "9" Then '開始タイミングのみ判定 .Cells(5 + datnum, 8) = "=IF(AND(R[11]C6>0,R[1]C6>0),SIGN(R[11]C6-R[1]C6))" '十分後 If 5 + datnum >= 24 Then .Cells(5 + datnum, 10) = _ "=ABS(SUM(RC[-1],R[-3]C[-1],R[-6]C[-1],R[-9]C[-1],R[-12]C[-1],R[-15]C[-1]))" '連続数 .Cells(5 + datnum, 11) = "=ROUNDDOWN(RC[-1]/6,0)*RC[-2]*-1" 'シグナル .Cells(5 + datnum, 12) = "=RC[-1]*RC[-4]" 'シグナルの結果 End If End If If 5 + datnum >= 9 Then '毎分集計 .Cells(5 + datnum, 9) = "=SIGN(RC[-2]-R[-3]C[-3])" '3分前との差 End If Next End With End If Next Application.ScreenUpdating = True '表示更新 Application.Calculation = xlCalculationAutomatic '再計算 End Sub

 ※膨大な参照計算が含まれますので、再計算が有効になっているとフリーズレベルにパフォーマンスが低下します。今回は後にシート上で計算式を編集することを考えて、"Application.Calculation = xlCalculationManual"で再計算を停止させています。
 また、ここでは5分単位で購入可能なタイプを想定しており、上記例(コード)ではそのタイミングでのみシグナルを算出するようになっています。

6連続で逆張りを行う仮想シグナルの2012年における成績

 以上のような流れでオリジナルのシグナルをヒストリカルデータに適用して成績を確認することができます。

 大量の計算式の出力もVBAを使えば簡単に行うことができますが、これについては省略し、以下に結果だけ記載しておきますので、自分で試してみてください。

 また、実際にやってみれば分かりますが、シート上に大量の複雑な数式を入力した場合、再計算によりまともな作業ができないレベルに動作が重くなる場合があります。

 一度にいろいろなシグナルを検証する場合は注意してください。大量の数式を出力する場合、再計算を行わない設定にした方が良いです。

 シート上での編集、再計算が可能な点はエクセルの特徴の一つですが、せっかくVBAが使えるのですから、シート上の計算ではなくプログラムでデータを処理し、結果だけを出力することも一つの方法です。特に複数のシグナルについて検証を行いたい場合、そのようにした方が効率がよいかもしれません。

 以下はこのシグナルについて2012年分のバックテストを行った結果の簡易的な表です。期待収支は、毎分購入可能で倍率が1.85倍固定、同値引けは購入金額没収、10分後に結果が出るタイプの仮想バイナリーオプションでシグナル通りに1回あたり30000円の取引を行った場合の期待値です。

購入してから10分後に結果が出るタイプの成績(2012年)
シグナル数HIT数HIT率倍率購入金額(1回)期待収支
155回95回61.29%1.85倍30000円622500円

6連続で逆張りを行う仮想シグナルの2012年における成績

 バックテストの結果から何が読み取れるでしょうか。

 単純な1パターンだけの1年分のテストですから何とも言えない面はありますが、手がかりにはなると思います。

 ここで使用したヒストリカルデータは0.01円単位ということもあり、それが6連続で同一方向へ動くということはあまりなく、シグナルの出現回数自体はかなり少なかったと思います。

 結論としては、2012年に前記逆張りシグナルにもとづいて全ての取引(仮想のバイナリーオプションですが)に参加した場合、年間で+622500円という高成績だったことが確認できました。

 他の年度で試してみてもそこそこの好成績のはずであり、ひとまずこの逆張りシグナル例は有効と結論づけて良さそうです。

まとめ

 基本的には以上のような流れで有効なシグナルを見つけ出す作業を行うわけですが、これは地味なようで最も重要(だと思う)な作業です。

 今回使用したヒストリカルデータは0.01円単位のものでしたが、実際の取引では普通0.001円単位のレートであったり、シグナルを決定するタイミングを1分前より短い時間にすることもできたり、異なる部分はありますが、傾向を分析するのには十分有効です。

 むしろ仮定した倍率以外は現実よりも厳しい条件ともいえますから、この条件で好成績のシグナルが見つかればそのまま使うことだってできるはずです。

 様々なテクニカル指標を組み合わせ、自分だけのオリジナルシグナル探しを楽しみ、充実した投資生活を過ごしていただけたら幸いです。

 また、このサイトが何かの参考になりましたら、ご意見、ご感想などいただけると嬉しいです。