バイナリーオプション(ハイローオーストラリア)をMT4でバックテストする方法 その2
先日紹介した方法ではストラテジーテスターでビジュアルモードを利用してCSVに書き込みエクセルで検証といった感じですが、今回はビジュアルモードを使わずに高速でバイナリーオプションのバックテスト検証の方法の案内。
先日の記事
abitra.hatenablog.com
今回の方法は一般的ではない+こんな方法しなくてもいいんじゃないか疑惑ですのでご了承下さいませ。
色々手間が発生するので正直おすすめ出来ないです。
1分足のバックテストはビジュアルモードを利用しないので爆速ですがw
■検証を行うにあたって
MQL4だけでは完結しません。rubyを利用しています。
1分足の検証などは圧倒的に早いのですが、5分以上になると手間とか考えると今までと同じ様なビジュアルモードで動かした方がいいかなーと。
■ビジュアルモードなしでバイナリーオプションのバックテストを行う方法(本題)
●重要
エントリーは注文内容によって把握します。
注文内容の前提を以下に定義します。
Highエントリーの場合の注文内容は"buy"
勝ちはlotを0.01
負けはlotを0.02
コマはlotを0.03(0.02でもいいかも)
Lowエントリーの場合の注文内容は"sell"
勝ちはlotを0.01
負けはlotを0.02
コマはlotを0.03(0.02でもいいかも)
この方法で注文して"結果"からコピーしてCSV保存して集計するといった感じです。
勘の良い方であれば上記定義でやってる事が分かるかと考えます。
残高は気にしません。
エントリーの注文内容が全てそれ以外は気にしなくてもいいです。
※lot数を1とかにしちゃうと残高不足でバックテストが途中で終わる可能性があるので最小の0.01にて。
参考までに前足が陽線陰線で注文を変えるソースで説明。
※勝ち負けはランダムです。
int start() { int StopLoss = 20; int TakeProfit = 20; int order_m_number = 99999; static datetime time111 = Time[0]; if(Time[0] != time111) // 一回だけの処理 { time111 = Time[0]; int num = MathRand() % 2; // 0 から 1 if (Open[1] < Close[1]) // 陽線 { if (num == 0) {// 勝ち lot を0.01に OrderSend( Symbol(), OP_SELL, 0.01, Bid, 30, Bid+(StopLoss*Point), Bid-(TakeProfit*Point), NULL, order_m_number, 0, clrDeepPink ); } else if (num == 1) {// 負け lot を0.02 OrderSend( Symbol(), OP_SELL, 0.02, Bid, 30, Bid+(StopLoss*Point), Bid-(TakeProfit*Point), NULL, order_m_number, 0, clrDeepPink ); } } else if (Open[1] > Close[1]) // 陰線 { if (num == 0) {// 勝ち lot を0.01に OrderSend( Symbol(), OP_BUY, 0.01, Ask, 30, Ask-(StopLoss*Point), Ask+(TakeProfit*Point), NULL, order_m_number, 0, clrDeepPink ); } else if (num == 1) {// 負け lot を0.02 OrderSend( Symbol(), OP_BUY, 0.02, Ask, 30, Ask-(StopLoss*Point), Ask+(TakeProfit*Point), NULL, order_m_number, 0, clrDeepPink ); } } else if (Open[1] == Close[1]) // コマ { OrderSend( Symbol(), OP_BUY, 0.03, Ask, 30, Ask-(StopLoss*Point), Ask+(TakeProfit*Point), NULL, order_m_number, 0, clrDeepPink ); } } return(0); }
↑を動かすと注文され"結果"に注文履歴が表示されます。
結果の箇所で右クリックして"すべてコピー"を選択。
このままだと決済のデータが入っていたり日本時間ではないので管理しにくかったり余計な指値の金額など入っているので扱いやすいデータに精製してCSVに再出力します。
精製はrubyを利用しています。
※夏時間の計算もしています。
require 'json' require 'csv' require 'time' @csv_file_path = "C:/Users/xxxxxx/test_data/test_data.csv" # 保存したcsvのファイルパス def summertime(csv_time) csv_time = Time.parse(csv_time) @time_x = 25200 # 冬時間 if Time.parse("2005.3.13") <= csv_time && csv_time <= Time.parse("2005.11.6") @time_x = 21600 # 夏時間 elsif Time.parse("2006.3.12") <= csv_time && csv_time <= Time.parse("2006.11.5") @time_x = 21600 elsif Time.parse("2007.3.11") <= csv_time && csv_time <= Time.parse("2007.11.4") @time_x = 21600 elsif Time.parse("2008.3.9") <= csv_time && csv_time <= Time.parse("2008.11.2") @time_x = 21600 elsif Time.parse("2009.3.8") <= csv_time && csv_time <= Time.parse("2009.11.1") @time_x = 21600 elsif Time.parse("2010.3.14") <= csv_time && csv_time <= Time.parse("2010.11.7") @time_x = 21600 elsif Time.parse("2011.3.13") <= csv_time && csv_time <= Time.parse("2011.11.6") @time_x = 21600 elsif Time.parse("2012.3.11") <= csv_time && csv_time <= Time.parse("2012.11.4") @time_x = 21600 elsif Time.parse("2013.3.10") <= csv_time && csv_time <= Time.parse("2013.11.3") @time_x = 21600 elsif Time.parse("2014.3.9") <= csv_time && csv_time <= Time.parse("2014.11.2") @time_x = 21600 elsif Time.parse("2015.3.8") <= csv_time && csv_time <= Time.parse("2015.11.1") @time_x = 21600 elsif Time.parse("2016.3.13") <= csv_time && csv_time <= Time.parse("2016.11.6") @time_x = 21600 elsif Time.parse("2017.3.12") <= csv_time && csv_time <= Time.parse("2017.11.5") @time_x = 21600 elsif Time.parse("2018.3.11") <= csv_time && csv_time <= Time.parse("2018.11.4") @time_x = 21600 elsif Time.parse("2019.3.10") <= csv_time && csv_time <= Time.parse("2019.11.3") @time_x = 21600 elsif Time.parse("2020.3.8") <= csv_time && csv_time <= Time.parse("2020.11.1") @time_x = 21600 elsif Time.parse("2021.3.14") <= csv_time && csv_time <= Time.parse("2021.11.7") @time_x = 21600 elsif Time.parse("2022.3.13") <= csv_time && csv_time <= Time.parse("2022.11.6") @time_x = 21600 elsif Time.parse("2023.3.12") <= csv_time && csv_time <= Time.parse("2023.11.5") @time_x = 21600 elsif Time.parse("2024.3.10") <= csv_time && csv_time <= Time.parse("2024.11.3") @time_x = 21600 elsif Time.parse("2025.3.9") <= csv_time && csv_time <= Time.parse("2025.11.2") @time_x = 21600 elsif Time.parse("2026.3.8") <= csv_time && csv_time <= Time.parse("2026.11.1") @time_x = 21600 elsif Time.parse("2027.3.14") <= csv_time && csv_time <= Time.parse("2027.11.7") @time_x = 21600 elsif Time.parse("2028.3.12") <= csv_time && csv_time <= Time.parse("2028.11.5") @time_x = 21600 elsif Time.parse("2029.3.11") <= csv_time && csv_time <= Time.parse("2029.11.4") @time_x = 21600 elsif Time.parse("2030.3.10") <= csv_time && csv_time <= Time.parse("2030.11.3") @time_x = 21600 elsif Time.parse("2031.3.9") <= csv_time && csv_time <= Time.parse("2031.11.2") @time_x = 21600 elsif Time.parse("2032.3.14") <= csv_time && csv_time <= Time.parse("2032.11.7") @time_x = 21600 elsif Time.parse("2033.3.13") <= csv_time && csv_time <= Time.parse("2033.11.6") @time_x = 21600 elsif Time.parse("2034.3.12") <= csv_time && csv_time <= Time.parse("2034.11.5") @time_x = 21600 elsif Time.parse("2035.3.11") <= csv_time && csv_time <= Time.parse("2035.11.4") @time_x = 21600 elsif Time.parse("2036.3.9") <= csv_time && csv_time <= Time.parse("2036.11.2") @time_x = 21600 elsif Time.parse("2037.3.8") <= csv_time && csv_time <= Time.parse("2037.11.1") @time_x = 21600 elsif Time.parse("2038.3.14") <= csv_time && csv_time <= Time.parse("2038.11.7") @time_x = 21600 end end #summertime end def refining #CSVの精製 new_data = [] CSV.foreach(@csv_file_path).each_with_index do |row, i| # mt4のバックデータ読み込み処理 array = [] if row[0].include?("buy") row = row[0].gsub!(/\t/, ',').split(',') summertime(row[1]) # 夏時間検証 array << Time.parse(row[1]) + @time_x array << "high" if row[4] == "0.01" #0.01は勝ち array << "win" elsif row[4] == "0.02" # 0.02は負け array << "lose" elsif row[4] == "0.03" #コマ array << "lose" end new_data << array elsif row[0].include?("sell") row = row[0].gsub!(/\t/, ',').split(',') summertime(row[1]) array << Time.parse(row[1]) + @time_x array << "low" if row[4] == "0.01" #0.01は勝ち array << "win" elsif row[4] == "0.02" # 0.02は負け array << "lose" elsif row[4] == "0.03" #コマ array << "lose" end new_data << array end end #CSV.foreach end CSV.open("refined.csv","wb") do |csv| #精製したデータの書き込み処理 new_data.each do |csvArray| csv << csvArray end end end refining
コマは負けにしています。
精製した後のcsvデータはエクセル(google スプレッドシート)などで自由に検証してやれば完了。
■懸念点
途中で面倒になったのでプログラム書いていませんが、注文時間とエントリー時間は1足分ズレているのでそれを考慮してやる必要があります。ruby プログラムで修正してやればいいかなーと。
勝敗しか取得できないので値幅など取得したい他のデータなどが取得出来ません。注文のコメントが使えればなー
何かほかに良い方法がありそうだけど。。。うーん。とりまビジュアルモードを利用しなでもバイナリーオプションのバックテスト(過去検証)出来たって事で。