Last Updated on 2021-01-17 by toshiikuo
FXの自動売買のためにMT5のEAを作ってみたので、内容をまとめる。
EAを作るのが初めてだったので、基本は以下のサイトを参考にした。
https://www.mql5.com/en/articles/100
考え方
市場参加者の中にはデイトレーダーと呼ばれる、1日の中で取引を取引を完結させる取引を行う人が存在する。
デイトレーダーは長期でポジションを持つ投資家に比べて取れる値幅が小さいことから、同じだけの利益を上げるためには、大きな数量のポジションを持つ必要がある。
そのため、デイトレーダーが1日の中での値動きに与える影響が大きいと推測できるが、ポジションをとったその日のうちに反対売買をして決済をすることから、1日の終わりにはデイトレーダーが動かした分の値幅は戻ると考えられる。
その戻りを利益にするためのEAを作った。
売買ロジック
1日の取引の始値から、乖離したら逆張りでエントリー。
始値に戻ったら利益確定。
その日の取引終了時には全決済。
MQL5のコード
ご自由にお使いください。投資は自己責任で。
//+------------------------------------------------------------------+
//| My_First_EA.mq5 |
//| Copyright 2010, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property version "1.00"
#include<Trade\Trade.mqh>
CTrade trade;
//--- input parameters
input int StartHour=1;
input datetime StartTime=D'2020.01.02 06:00:00';
input int CloseHour=23;
input datetime CloseTime=D'2020.01.02 06:00:00';
input int endtime;
input int EA_Magic=104190;
input double Lot=0.01; // Lots to Trade
input double step=0.05;
//--- Other parameters
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- set MagicNumber for your orders identification
trade.SetExpertMagicNumber(EA_Magic);
//--- set available slippage in points when buying/selling
int deviation=10;
trade.SetDeviationInPoints(deviation);
//--- order filling mode, the mode allowed by the server should be used
trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- logging mode: it would be better not to declare this method at all, the class will set the best mode on its own
trade.LogLevel(1);
//--- what function is to be used for trading: true - OrderSendAsync(), false - OrderSend()
trade.SetAsyncMode(true);
//---
return(0);
}
void OnTick()
{
MqlTick latest_price; // To be used for getting recent/latest price quotes
MqlTradeRequest mrequest; // To be used for sending our trade requests
MqlTradeResult mresult; // To be used to get our trade results
MqlRates mrate[]; // To be used to store the prices, volumes and spread of each bar
ZeroMemory(mrequest); // Initialization of mrequest structure
datetime ct=TimeCurrent();
MqlDateTime mqlct;
TimeToStruct(ct,mqlct);
int cthour=mqlct.hour;
MqlDateTime mqlst;
mqlst=mqlct;
mqlst.hour=StartHour;
mqlst.min=0;
mqlst.sec=0;
datetime StartTime=StructToTime(mqlst);
MqlDateTime mqlet;
mqlet=mqlct;
mqlet.hour=CloseHour;
mqlet.min=0;
mqlet.sec=0;
datetime CloseTime=StructToTime(mqlet);
//--- Get the last price quote using the MQL5 MqlTick Structure
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
return;
}
//--- Get the details of the latest 3 bars
if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
{
Alert("Error copying rates/history data - error:",GetLastError(),"!!");
ResetLastError();
return;
}
//---入力された時間の値段を取得
MqlRates rates[];
CopyRates(_Symbol,_Period,StartTime,1,rates);
ArrayPrint(rates);
double openrate=NormalizeDouble(rates[0].open,_Digits);
//---現在の値段を取得
MqlTick CurrentTick;
SymbolInfoTick(_Symbol,CurrentTick);
double CurrentRate=NormalizeDouble(CurrentTick.bid,_Digits);
//---差
double diff = CurrentRate-openrate;
//---エントリー
bool isdealtime = (StartTime<=ct && ct<CloseTime);
if(isdealtime){
int x;
for(x=1;diff<=-step*x;x++){
if(PositionsTotal()<x){
ZeroMemory(mrequest);
mrequest.action = TRADE_ACTION_DEAL; // immediate order execution
mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // latest ask price
mrequest.symbol = _Symbol; // currency pair
mrequest.volume = Lot; // number of lots to trade
mrequest.magic = EA_Magic; // Order Magic Number
mrequest.type = ORDER_TYPE_BUY; // Buy Order
mrequest.type_filling = ORDER_FILLING_FOK; // Order execution type
mrequest.deviation=100; // Deviation from current price
mrequest.tp = NormalizeDouble(openrate,_Digits); // Take Profit
//--- send order
OrderSend(mrequest,mresult);
// get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("A Buy order has been successfully placed with Ticket#:",mresult.order,"!!");
}
else
{
Alert("The Buy order request could not be completed -error:",GetLastError());
ResetLastError();
return;
}
}
}
for(x=1;diff>=step*x;x++){
if(PositionsTotal()<x){
ZeroMemory(mrequest);
mrequest.action = TRADE_ACTION_DEAL; // immediate order execution
mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // latest bid price
mrequest.symbol = _Symbol; // currency pair
mrequest.volume = Lot; // number of lots to trade
mrequest.magic = EA_Magic; // Order Magic Number
mrequest.type = ORDER_TYPE_SELL; // Buy Order
mrequest.type_filling = ORDER_FILLING_FOK; // Order execution type
mrequest.deviation=100; // Deviation from current price
mrequest.tp = NormalizeDouble(openrate,_Digits); // Take Profit
//--- send order
OrderSend(mrequest,mresult);
// get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("A Sell order has been successfully placed with Ticket#:",mresult.order,"!!");
}
else
{
Alert("The Sell order request could not be completed -error:",GetLastError());
ResetLastError();
return;
}
}
}
}
//---時間決済
if(mqlct.hour==mqlet.hour){
trade.PositionClose(Symbol());
}
return;
}
//+------------------------------------------------------------------+
バックテスト結果
散々な結果。買いと売りを逆にすれば勝てるかな?
私が使っている口座
MT5でスプレッド、手数料を最小限に抑えるためには、
TradeViewのMT5のILC口座をTariTaliというキャッシュバックサイトから口座開設するのがベストです。(私調べ)2021/1/17追記
売りと買いを逆にしたEAを作ってみた。
ピンバック: 初めて作ったMT5のEAのバックテスト結果が散々だったので、買いと売りを逆にしてみた。 - Akinai Life