見出し画像

「Grid Free4」をさらにバージョンアップしてみた→「Grid Free5」

前回、Grid Free4を作ってみて、少し書き換えたほうがわかりやすいかなと思ったところがあったので、またバージョンアップしてみました。

今回の変更点は、
①RSIのエントリー条件を少し書き換え
②最大ポジション段数を設定

①RSIのエントリー条件を少し書き換え

Grid Free4では、
①1本前のローソク足で29より下、71より上
②現在のローソク足で29+1以上、71-1以下になったらエントリー
という条件になって、パラメーターの設定項目は
・RSI下ライン(買い)→29
・RSI下からの上げ幅(買い)→1
・RSI上ライン(売り)→71
・RSI上からの下げ幅(売り)→1
となっていました。

これが頭の中でこんがらがって、上げ幅と下げ幅は1にしているのに、2以上の上げ下げが必要になっていることに気づきました。

どういうことかというと、買いの条件を見ると、
①1本前のRSIが29より下=28以下
rsi < 29
②現在のRSIが29+1以上=30以上
rsi2 >= 29+1
となって、パラメーターを上げ幅1にしても、2上がらないとエントリーしないようになっていたんです。

そこで、1本前のRSIの条件にも=を入れて、
rsi <= 29
にすることで、パラメーターの上げ幅と下げ幅をわかりやすくしました。

これで、パラメーターを
・RSI下ライン(買い)→29
・RSI下からの上げ幅(買い)→1
にした場合、
①1本前のRSIが29以下
rsi <= 29
②現在のRSIが30以上
rsi2 >= 29+1
ということになります。

なので、Grid Free4の
・RSI下ライン(買い)→29
・RSI下からの上げ幅(買い)→1
が、Grid Free5では
・RSI下ライン(買い)→28
・RSI下からの上げ幅(買い)→2
とすれば同じ条件になります。

②最大ポジション段数を設定

このEAの原作であるGrid Freeの紹介ページを見ると、次のような注意書きがあります。↓

「Grid Freeはポジションが13段を超えると高確率で破綻します。(資金10,000ドル/0.05ロットの場合)保有ポジションが9段を超えたら、そのチャートのEAを停止して、手動で決済してください。」

この注意書きを見て、9段以上のポジションが入らないようにできたらいいなと思い、なんとか最大ポジション数を設定できるようにしてみました。
これで破綻確立を下げられると思います。
あとは一括決済EAを一緒に使うと処理しやすいと思います。

ナンピンエントリーの条件に、
posi_count(OP_BUY) < entrystop
というようなパーツを加え、パラメーターでentrystopのところを9にしたりできるように設定してみました。

Grid Free5でバックテスト

Grid Free4と比較するために、まずはGrid Free4のバックテスト結果を見てみます。

NZDCADの2017~2023年のバックテスト結果 ↓

次はGrid Free5で同じエントリー条件で、最大ポジション数を9にして、NZDCADのバックテスト結果 ↓

結果が変わったということは、ポジション数が9段以上の場面があったということだと思います。
利益、最大ドローダウン、総取引数が少し減っています。
プロフィットファクターは少し上がりました。
利益と総取引数が減ったのは少し残念ですが、最大ドローダウンが減って、プロフィットファクターが上がったのは良かったです。

あとはAUDCADとAUDNZDのGrid Free5のバックテスト結果を見てみます。
まずはAUDCAD ↓

良い成績ですが、利益と取引数が少ない感じもするので、少しエントリー条件を緩めてもいいかもと思いました。

次はAUDNZDのバックテスト結果 ↓

これはあんまり良くないですね。
パラメーターを調整する必要がありそうです。
最大ポジション数が9以上になる場面が多いようです。

Grid Free5のソースコード

#property copyright "けんじ2405"
#property link      "https://note.com/just_pothos4327"
#property version   "1.00"
#property strict

input int MagicNumber = 77701;//マジックナンバー
input double lots = 0.1;//ロット数
input int MaxSp = 45;//最大スプレッド
input int rikakuhaba = 150;//利確幅
input int nanpinhaba =300;//グリッド幅
input double lotbai = 1.5;//ロット倍率
input int entrystop = 9;//最大ポジション段数
input int rsikikan =14;//RSI計算期間
input int rsilow =28;//RSI下ライン(買い)
input int agehaba =2;//RSI下からの上げ幅(買い)
input int rsihigh =72;//RSI上ライン(売り)
input int sagehaba =2;//RSI上からの下げ幅(売り)
input int shift1 =100;//モメンタムフィルター1
input int shift2 =200;//モメンタムフィルター2

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//エントリー処理

   if(is_buy() && is_up_trend() && posi_count(OP_BUY) == 0)
     {
      position_entry(OP_BUY);
     }

   if(is_sell() && is_down_trend() && posi_count(OP_SELL) == 0)
     {
      position_entry(OP_SELL);
     }

//決済処理

   if(posi_count(OP_BUY) > 0)
     {
      if(position_average_price(0) + rikakuhaba * _Point < Bid)
        {
         position_close(0);
        }
     }

   if(posi_count(OP_SELL) > 0)
     {
      if(position_average_price(1) - rikakuhaba * _Point > Ask)
        {
         position_close(1);
        }
     }

//ナンピンマーチン

   nanpin_martin_judge();

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool is_buy()
  {
   double rsi = iRSI(NULL,0,rsikikan,0,1);
   double rsi2 = iRSI(NULL,0,rsikikan,0,0);

   if(rsi <= rsilow && rsi2 >= rsilow+agehaba)
     {
      return true;
     }
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool is_sell()
  {
   double rsi = iRSI(NULL,0,rsikikan,0,1);
   double rsi2 = iRSI(NULL,0,rsikikan,0,0);

   if(rsi >= rsihigh && rsi2 <= rsihigh-sagehaba)
     {
      return true;
     }
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool is_up_trend()
  {

   double close = iClose(NULL,0,0);
   double close100 = iClose(NULL,0,shift1);
   double close200 = iClose(NULL,0,shift2);

   double mom100 = close - close100;
   double mom200 = close - close200;

//「momが0超え」なら上昇トレンド

   if(0 < mom100 && 0 < mom200)
     {
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool is_down_trend()
  {

   double close = iClose(NULL,0,0);
   double close100 = iClose(NULL,0,shift1);
   double close200 = iClose(NULL,0,shift2);

   double mom100 = close - close100;
   double mom200 = close - close200;

//「momが0未満」なら下降トレンド

   if(0 > mom100 && 0 > mom200)
     {
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int posi_count(int side)
  {

   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType() == side)
           {
            if(OrderSymbol()==Symbol())
              {
               if(OrderMagicNumber()==MagicNumber)
                 {
                  count++;
                 }
              }
           }
        }
     }
   return count;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void position_entry(int side)
  {
   double qty = lots;
   if(side==0 && MarketInfo(Symbol(),MODE_SPREAD) < MaxSp)
     {
      bool res= OrderSend(NULL,side,qty,Ask,0,0,0,NULL,MagicNumber,0,clrGreen);
     }
   if(side==1 && MarketInfo(Symbol(),MODE_SPREAD) < MaxSp)
     {
      bool res= OrderSend(NULL,side,qty,Bid,0,0,0,NULL,MagicNumber,0,clrRed);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void position_entry_nanpin(int side,double bairitu)
  {
   double qty = lots;

   if(side==0 && posi_count(OP_BUY) < entrystop && MarketInfo(Symbol(),MODE_SPREAD) < MaxSp)
     {
      bool res= OrderSend(NULL,side,qty * bairitu,Ask,0,0,0,NULL,MagicNumber,0,clrGreen);
     }
   if(side==1 && posi_count(OP_SELL) < entrystop && MarketInfo(Symbol(),MODE_SPREAD) < MaxSp)
     {
      bool res= OrderSend(NULL,side,qty * bairitu,Bid,0,0,0,NULL,MagicNumber,0,clrRed);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void position_close(int side)
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType() == side)
           {
            if(OrderSymbol()==Symbol())
              {
               if(OrderMagicNumber()==MagicNumber)
                 {
                  bool res=  OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0, clrBlue);
                 }
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double position_average_price(int side)
  {

   double lots_sum = 0;
   double price_sum = 0;
   double average_price = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType() == side)
           {
            if(OrderSymbol()==Symbol())
              {
               if(OrderMagicNumber()==MagicNumber)
                 {
                  lots_sum += OrderLots();
                  price_sum += OrderOpenPrice() * OrderLots();
                 }
              }
           }
        }
     }
   if(lots_sum && price_sum)
     {
      average_price = price_sum/lots_sum;
     }
   return average_price;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double position_entry_price(int side)
  {
   double entry_prices[50];
   double entry_price=0;

   ArrayInitialize(entry_prices,0.0);
   if(side ==1)
     {
      ArrayInitialize(entry_prices,9999999.0);
     }

   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType() == side)
           {
            if(OrderSymbol()==Symbol())
              {
               if(OrderMagicNumber()==MagicNumber)
                 {
                  entry_prices[i] = OrderOpenPrice();
                 }
              }
           }
        }
     }
   if(side==0)
     {
      entry_price = entry_prices[ArrayMaximum(entry_prices,WHOLE_ARRAY,0)];
     }
   if(side==1)
     {
      entry_price = entry_prices[ArrayMinimum(entry_prices,WHOLE_ARRAY,0)];
     }
   return entry_price;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void nanpin_martin_judge()
  {

   if(posi_count(OP_BUY) > 0)
     {
      int position_num = posi_count(OP_BUY);
      double entry_price = position_entry_price(OP_BUY);
      double nanpin_price = entry_price - (nanpinhaba * _Point) * position_num;
      double lots_bairitu = MathPow(lotbai,position_num);

      if(nanpin_price > Ask)
        {
         position_entry_nanpin(OP_BUY,lots_bairitu);
        }
     }
   if(posi_count(OP_SELL) > 0)
     {
      int position_num = posi_count(OP_SELL);
      double entry_price = position_entry_price(OP_SELL);
      double nanpin_price = entry_price + (nanpinhaba * _Point) * position_num;
      double lots_bairitu = MathPow(lotbai,position_num);
      if(nanpin_price < Bid)
        {
         position_entry_nanpin(OP_SELL,lots_bairitu);
        }
     }
  }
//+------------------------------------------------------------------+

ファイルのダウンロードはこちら ↓

もしよかったら、記事の下の「記事をサポート」をお願い致します。お金が稼げなくて困っています。奨学金の返済、生活費、病院代、勉強代などに使いたいと思っております。今使っているパソコンも古くなってきて、そろそろ買い換えたいなと思っています。ちなみに今使っているパソコンは、10年位前のVALUESTARです。なんとかよろしくお願いします。


この記事が気に入ったらサポートをしてみませんか?