超初心者がMQL5でSMAを使った自動売買をデモ環境で試してみた

MetaTrader5で試しました。インターネット上ではMQL4の情報が多く、MQL5の情報を調べるのに結構苦労しました。MetaTrader5の中にサンプルを発見してからはそちらを参考にしつつ作業しました。サンプルはスタンダードなロジックのものが多いみたいで、結構わかりやすく、勉強になりそうな予感です。

## 参考

[【MQL】ゴールデンクロスとデッドクロスでエントリーするEA【初級編】](https://creator.fx-ea-system-project.com/mt4-expert-adviser/gc-dc/)

<p>MQL4の記事ですが、シンプルな記述なので参考にしやすかったです。</p>

## コード

使ってないプロパティとかありますけど許してちょんまげ。あと抜粋です。

``` c
input int      TakeProfit=5;
input int      StopLoss=5;
input double   Lots=0.1;
input int      MagicNumber=12345;

input int FastMAPeriod = 20;  //短期移動平均の期間
input int SlowMAPeriod = 50;  //長期移動平均の期間

int FastMAHandle;
int SlowMAHandle;
CTrade ExtTrade;

string my_symbol = "USDJPY";

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   Comment("OnInit");
//--- create timer
   EventSetTimer(60);
   
//---
   ExtTrade.SetExpertMagicNumber(MagicNumber);
   ExtTrade.SetMarginMode();
   ExtTrade.SetTypeFillingBySymbol(Symbol());
   
   //SMA
   FastMAHandle = iMA(Symbol(), Period(), FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   if(FastMAHandle==INVALID_HANDLE)
   {
      PrintFormat("FastMAHandle: Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
   }
   SlowMAHandle = iMA(Symbol(), Period(), SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   if(SlowMAHandle==INVALID_HANDLE)
   {
      PrintFormat("SlowMAHandle: Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

void OnTick()
{
//---
   Comment("OnTick");
   
   double FastMA[];
   double SlowMA[];
   ArraySetAsSeries(FastMA,true);
   ArraySetAsSeries(SlowMA,true);
   
   int start_pos=0,count=2;
   if(!CopyBuffer(FastMAHandle,0,start_pos,count,FastMA))
      return;
   if(!CopyBuffer(SlowMAHandle,0,start_pos,count,SlowMA))
      return;

   if(SelectPosition())
      CheckForClose(FastMA, SlowMA);
   else
      CheckForOpen(FastMA, SlowMA);
}

void CheckForClose(double &FastMA[], double &SlowMA[])
{
   bool signal = false;
   if(FastMA[1] >= SlowMA[1] && FastMA[0] < SlowMA[0])
      signal = true;
   
   if(signal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
      ExtTrade.PositionClose(_Symbol,3);
}

void CheckForOpen(double &FastMA[], double &SlowMA[])
{
   ENUM_ORDER_TYPE signal = WRONG_VALUE;
   if(FastMA[1] <= SlowMA[1] && FastMA[0] > SlowMA[0])
      signal=ORDER_TYPE_BUY;
   
   if(signal!=WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      bool err = ExtTrade.PositionOpen(_Symbol, signal, Lots,
                               SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
                               0,0);
      Print(err);
   }
}

bool SelectPosition()
{
   if(PositionSelect(_Symbol))
      return(PositionGetInteger(POSITION_MAGIC)==MagicNumber);
   
   return false;
}

```

## バックテストの結果

![スクリーンショット 2021-08-09 092126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69727/285ae4a7-8898-462f-9ec6-3cced778349a.png)

ですよねー…な結果。

## ちょっと説明

やってることはゴールデンクロスとデッドクロスを判定して、ゴールデンクロスのときに買い、デッドクロスで売っています。

## 完走した感想

修正できそうなところで今のところ思いつくのは…

- 損切りと利食いの設定
- ロットの計算
- レンジ相場のときとそうでないときの判定を追加

損切りと利食いの設定にはストップレベルという問題がつきまとっているらしい。よくわかんない（＞_＜）（参考：[OrderSend Error 130 (invalid stops) エラーの原因と対策](https://autofx100.com/2021/02/17/ordersend-error-130-invalid-stops/)）