MQL4 お金の健康

FXの自動売買プログラムを自作したい!ボリンジャーバンドを使った順張り戦略

投資を自動でやってほしいなあ。
 
自分でプログラムを作れるの?
 
どんな戦略がいいの?

という悩みを解決できる記事になっています。

なぜなら、私はプログラミング言語MQL4で
FXの自動売買をしているからです。

結論だけ言うと、

プログラミング言語MQL4を使えば

誰でも自動売買できます。

この記事ではボリンジャーバンドを使った順張りプログラムを紹介します。

読み終えていただければ、

自動売買プログラムを自作できるようになります。

※おすすめの自動売買プログラムショップ

平均レビュー評価:★4.85の高評価!

FX自動売買プログラムのオンラインショップです。

自作する時間がもったいないと感じたら

購入して使うのもひとつの手です。

FXの自動売買プログラムを自作しよう

FXの自動売買プログラムを自作しよう

誰でも放置で稼げるシステムづくりを目指して

FXに挑戦しているうっちゃんです。

過去の記事ではMT4の使い方を紹介しました。

今回はより実践的なプログラムを考えました。

商品名はプロトレーディングリプレイ!

小学生の頃、プロアクションリプレイという

改造ゲームが流行っていたことを思い出し、

名前をパクりました。

戦略は上手くいっていませんが、商品名だけはしっかり考えています。

さて、今回のトレード戦略は次のとおりです。

FX自動売買プログラムのトレード戦略

分析指標

ボリンジャーバンド(BB)、期間21

EMA、期間200

買い注文の条件

EMAよりBBのミドルラインが上にあり、かつ

終値が+1σを上抜けたときに成行き

買いの手仕舞い条件

終値が-1σを下抜けたとき

売り注文の条件

EMAよりBBのミドルラインが下にあり、かつ

終値が-1σを上抜けたときに成行き

売りの手仕舞い条件

終値が+1σを上抜けたとき

複数のポジションは持たないようにしています。

チャートで表すとこんな感じ。

FX自動売買のチャート
買い注文

青が買い注文のエントリー、黄色が決済です。

なお、赤がEMAで長期トレンドを示し、

緑がボリンジャーバンドのミドルライン、+1σ、-1σを表します。

FX自動売買の売り注文
売り注文

赤は売り注文、黄色が決済です。

この戦略はこちらの本を参考に作成しました。

これをFXの自動売買プログラムに落とし込みます。

FX自動売買プログラムのコード

作り方はこちらの記事をご覧ください。

さっそくコードを書きます。

//+------------------------------------------------------------------+
//|                                               Moving Average.mq4 |
//|                                          Copyright 2021, uchida. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2021, uchida"
#property link        "http://tsumawosettoku20200808.com"
#property description "Instagram @uchy8893 present"

#define MAGICMA  2021102901

//--- Inputs
input double Lots          =0.01;
input double MaximumRisk   =0.02;
input double DecreaseFactor=3;
input int    MovingPeriod  =200;
input int    MovingShift   =0;

extern double TakeProfit   = 0; //利食い
extern double StopLoss     = 0; //損切り
extern int    Slippage     =10; 
extern string Comments     = "EA has traded";

extern int    BBPeriod     = 21;   //ボリンジャーバンドの期間
int           Adjusted_Slippage =0;
double        _point;       // Pips入力値用の変数

int          Ticket        =0;
bool         Closed        =false;

//スリッページの調整------------------------------------------------------
int AdjustSlippage(string Currency, int Slippage_Pips)
{
    int Symbol_Digits = MarketInfo(Currency, MODE_DIGITS);
    
    int Calculated_Slippage = 0;
    
    if(Symbol_Digits == 2 || Symbol_Digits ==4)
    {
        Calculated_Slippage = Slippage_Pips;    
    }
    else if(Symbol_Digits == 3 || Symbol_Digits == 5)
    {
        Calculated_Slippage = Slippage_Pips * 10;
    }
    
    return(Calculated_Slippage);
}

//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
        {
         if(OrderType()==OP_BUY)  buys++;
         if(OrderType()==OP_SELL) sells++;
        }
     }
//--- return orders volume
   if(buys>0) return(buys);
   else       return(-sells);
  }
  
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
int CheckForOpen(double bbU1,double bbL1,double middle1,double ema)
  {
   int    res;
   double sl = 0, tp = 0;
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return(Ticket);
//---bollingerbands
   
//--- buy conditions
   if(ema < middle1 &&  Close[0] > bbU1)// && rsi >= 30 && delta < 5* _point
     {
      if (StopLoss > 0) sl = Ask - StopLoss * _point;
      if (TakeProfit > 0) tp = Ask + TakeProfit * _point;
      
      res=OrderSend(Symbol(),
      OP_BUY,
      Lots,
      Ask,
      Adjusted_Slippage,
      sl,
      tp,
      Comments,
      MAGICMA,
      0, 
      Blue);
      return(Ticket);
     }
//--- sell conditions
   if(ema > middle1  && Close[0] < bbL1)  // && rsi <= 70 && delta < 5* _point
     {
      if (StopLoss > 0) sl = Bid + StopLoss * _point;
      if (TakeProfit > 0) tp = Bid - TakeProfit * _point;
      
      res=OrderSend(Symbol(),
      OP_SELL,
      Lots,
      Bid,
      Adjusted_Slippage,
      sl,
      tp,
      Comments,
      MAGICMA,
      0, 
      Red);
      return(Ticket);
     }
  
     
//---
  return(Ticket);
  }
  
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
int CheckForClose(double bbU1,double bbL1)
  {
     
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return(Ticket);

//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
      //--- check order type 
      if(OrderType()==OP_BUY)
        {
         if(bbL1 > Close[0])
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Bid,Adjusted_Slippage,White))
               Print("OrderClose error ",GetLastError());
           }
         //break;
        }
      if(OrderType()==OP_SELL)
        {
          if(bbU1 < Close[0])
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Ask,Adjusted_Slippage,White))
               Print("OrderClose error ",GetLastError());
           }
         //break;
        }
     }
  return(Ticket);
  }
  
  
//---------初期化関数------------------------------------------------
int init()
{
   _point = Point;
   if (Digits % 2 == 1)
   {
      _point *= 10;
      Slippage *= 10;
   }
    Adjusted_Slippage = AdjustSlippage(Symbol(), Slippage);
        
    return(0);
}

//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false) // ||AccountNumber()!=ACCOUNT
      return;
//---BB
    double bbU1 = iBands(NULL,0,BBPeriod,1,0,PRICE_CLOSE,MODE_UPPER,1);
    double bbL1 = iBands(NULL,0,BBPeriod,1,0,PRICE_CLOSE,MODE_LOWER,1);  
    
    double middle1 =iMA(NULL,0,BBPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,1);
//---EMA
    double ema = iMA(NULL,0,MovingPeriod,MovingShift,MODE_EMA,PRICE_CLOSE,1); 
       
   //--- calculate open orders by current symbol
   if(CalculateCurrentOrders(Symbol())==0) CheckForOpen(bbU1,bbL1,middle1,ema);
   else    CheckForClose(bbU1,bbL1);
   
   
   
//---
  }
//+------------------------------------------------------------------+

ボリンジャーバンドはこのようなコードを書きます。

double  iBands(
   string       symbol,        // 通貨ペア
   int          timeframe,     // 時間軸
   int          period,        // 平均期間
   double       deviation,     // 標準偏差
   int          bands_shift,   // バンドシフト
   int          applied_price, // 適用価格
   int          mode,          // ラインインデックス
   int          shift          // シフト
   );

ミドルラインはSMAにしました。

double  iMA(
   string       symbol,       // 通貨ペア
   int          timeframe,    // 時間軸
   int          ma_period,    // MAの平均期間
   int          ma_shift,     // MAシフト
   int          ma_method,    // MAの平均化メソッド
   int          applied_price,// 適用価格
   int          shift         // シフト
   );

EMAはSMAのコードを変更するだけです。

MODE_SMA→MODE_EMAに変えるだけ。

さて、気になるのは結果ですよね。

EURUSDのH1でバックテストを行いました。

結果はこちら

バックテストの結果

微増!

ロット数を0.01に抑えたので、

増えもせず減りもせずって感じです。

今後は戦略を見直して、改良を進めていきます。

※おすすめの自動売買プログラムショップ

平均レビュー評価:★4.85の高評価!

FX自動売買プログラムのオンラインショップです。

自作する時間がもったいないと感じたら

購入して使うのもひとつの手です。

ここまで読んでくださりありがとうございました。^^

-MQL4, お金の健康
-,