本格ナンピン&マーチンEA(一部サンプルソース有り)

記事内に商品プロモーションを含む場合があります
スポンサーリンク

今回は、MT4のEA(FX用)を公開します。

本格ナンピン&マーチンゲールEAという事で、以前がっつり作成したもの(EAファイルとソースコード一部)を無料公開しています。

今回は外国通貨に加えGOLD(ゴールド)でも使えるEAになっており、さらにナンピンの倍率や幅も自由にパラメータ設定で変更可能なので汎用性はかなり高めです。

EAはダウンロードして頂くと普通に使えるので是非色々試してみて下さい。

はじめに

ナンピン&マーチン型のEAはまず安定した利益が目指せるのでそこが魅力ですが、一度1方向に値段が動いてしまった場合、資金に余裕がない場合は一気に資金をなくしてしまう事があります。

資金に余裕が無くても、ナンピンするまでの値(pips)やナンピンの倍率を見直す事で耐えれる事もありますのでそこら辺をパラメータ設定できるEAに仕上げています。

あと、パラメータ設定でストキャスティクスかRSIかのどちらかで確認できるようにしています。

EAレポート結果

2024年のゴールドでのバックテスト結果です。良い感じにプラスの結果となっています。

パラメータ設定はこんな感じです。

詳細は後述しています。

ダウンロード

上記のEAファイルになります。

“ナンピンEA” をダウンロード NANPIN-EA-1.ex4 – 17 回のダウンロード – 23.62 KB

EAの仕様

それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。

エントリータイミング

ショートエントリー

RSIの一定値を上回った場合にショートエントリー 又は

ストキャスティクスの一定値を上回った場合にショートエントリー。

ロングエントリー

RSIの一定値を下回った場合にロングエントリー 又は

ストキャスティクスの一定値を下回った場合にロングエントリー。

エントリー例

初回のエントリーはローソク足が更新されたタイミングでエントリーしますが、ナンピン時はローソク足に関わらずpips数が条件を満たした場合にナンピンエントリーします。

両建てエントリー対応です。

決済タイミング

パラメータ設定(RIKAKU)に達した場合に全ポジション(ロング・ショートポジションは別々に)決済します。保有ポジション数で少し決済のタイミングが変わります。

1~2ポジションの場合

1ポジション目がパラメータ設定(RIKAKU)に達した場合に全決済します。

3ポジションの場合

2ポジション目がパラメータ設定(RIKAKU)に達した場合に全決済します。

4ポジション目以降

最新ポジションから2つ前のポジションがパラメータ設定(RIKAKU)に達した場合に全決済します。

その他の仕様

このEAは外国通貨やゴールドで動作確認しています。

保持できるポジションは最大100ポジションまでです。

最大ロット数は50.0Lotです。※ナンピン時でもそれ以上にはなりません

パラメータ設定

パラメータ設定値は以下の通りです。

ナンピン関連パラメータ

  1. 初期ロット= 0.01 ⇒ 初期ロットを設定(0.01=1000通貨)
  2. ナンピン倍率= 1.5 ⇒ ナンピン時のロット数倍率(2.0で1,2,4,8,16倍…になっていきます)
  3. ナンピン値= 30.0 ⇒ 最新エントリーから不利な状況になりナンピンする際のpips数(30.0 = 30pips)
  4. 最大ポジション数= 14 ⇒ 最大ポジション数で、ロング・ショートで別々です。
  5. 利確値= 10.0 ⇒ 利確する際のpips数(10.0 = 10pips)

インジ・エントリー根拠関連パラメータ

  1. SELECT_INDI= 0 ⇒ エントリー根拠を選択できます(0:ストキャスティクス 1:RSI)
  2. I_PRAM1= 5 ⇒ パラメータ1です(ストキャスティクスの場合は%K期間、 RSIの場合は期間)
  3. I_PRAM2= 3 ⇒ パラメータ2です(ストキャスティクスの場合は%D期間、 RSIの場合は設定不要です)
  4. I_PRAM3= 3 ⇒ パラメータ3です(ストキャスティクスの場合はスローイング、 RSIの場合は設定不要です)
  5. E_KAI= 30 ⇒ ストキャスティクス又はRSIの値がいくつになったら買いエントリーをするか
  6. E_URI= 70 ⇒ ストキャスティクス又はRSIの値がいくつになったら売りエントリーをするか

ストキャスティクスの設定例

SELECT_INDIは0にし、I_PRAM1の%K期間は5、I_PRAM2の%D期間は3、I_PRAM3のスローイングは3に設定しいます。

ストキャスティクスの値が20(E_KAI)で買い、80(E_URI)で売りエントリーの例です。

RSIの設定例

SELECT_INDIは1にし、I_PRAM1の期間は14に設定しいます。I_PRAM2、I_PRAM3は何を設定しても参照しないため変化はありません。

RSIの値が30(E_KAI)で買い、70(E_URI)で売りエントリーの例です。

スポンサーリンク

状況確認機能

現在のポジション数や次回のナンピンpipsを表示する機能付きです。

制約

今回は無償版のためマジックナンバーを0固定としており変更できません。

ソースコード(一部)

以下ナンピンEAのサンプルソースコードの一部(前半部)になります。

//+------------------------------------------------------------------+
//|                                                    NANPIN-EA.mq4 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020-2024 ぷろぐらむFX"
#property link      "https://fx-prog.com/"
#property version   "1.00"
#property strict

extern string p01="--- MAIN Settings ---";
input double LOTS = 0.01;   //初期ロット
input double NANPIN_BAIRITU = 1.50;   //ナンピン倍率
input double NANPIN_HABA = 20;   //ナンピン値(pips)
input int MAX_POSISION = 10;   //最大ポジション数

input double RIKAKU = 10;   //利確値(pips)

extern string p02="--- INDI Settings ---";
input int SELECT_INDI = 0;
input int I_PRAM1 = 5;
input int I_PRAM2 = 3;
input int I_PRAM3 = 3;

input int E_KAI = 20;
input int E_URI = 80;

int MAGIC_NO = 0;   //マジックナンバー

datetime prevtime;
int Main_ea_ticket[100]; //ポジションのチケット番号保有用(2だと3ポジまで) 5ポジ持たせたい場合は4にすること

double lot_buf_L;  //ロングロット数保持
double lot_buf_S;  //ショートロット数保持
int total_buf_L;  //ロングポジション数保持
int total_buf_S;  //ショートポジション数保持

double Start_Shikin; //EA開始時の口座資金を保持

string objectName = "SHOW_PROFIT";
string objectName2 = "SHOW_PROFIT2";
double LOT_MAX = 50.0;

string nanpin_message_L ="";
string nanpin_message_S ="";



double ZigTop[5];     //ジグザグの山保存用
double ZigBottom[5];  //ジグザグの谷保存用
int TopPoint;
int BottomPoint;

double ZigTop_H[5];     //ジグザグの山保存用(大きい足用)
double ZigBottom_H[5];  //ジグザグの谷保存用(大きい足用)
int TopPoint_H=0,BottomPoint_H=0;

double ZigTopBar_H[5];     //ジグザグの山位置保存用(大きい足用)
double ZigBottomBar_H[5];  //ジグザグの谷位置保存用(大きい足用)

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
//---
   //ラベルオブジェクトの作成
   if(!ObjectCreate(0, objectName, OBJ_LABEL, 0, 0, 0))
   {
      //return(INIT_FAILED);
   }
   // 座標のアンカー位置
   ObjectSetInteger(0, objectName ,OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
   // X位置
   ObjectSetInteger(0, objectName, OBJPROP_XDISTANCE, 35);
   // Y位置
   ObjectSetInteger(0, objectName, OBJPROP_YDISTANCE, 25);
   // 色
   ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrWhite);
   // 読み取り専用
   ObjectSetInteger(0, objectName, OBJPROP_READONLY, true);
   // 選択不可
   ObjectSetInteger(0, objectName, OBJPROP_SELECTABLE, false);
   // フォント名
   ObjectSetString(0, objectName, OBJPROP_FONT, "MS ゴシック");
   // フォントサイズ
   ObjectSetInteger(0, objectName, OBJPROP_FONTSIZE, 8);

   //ラベルオブジェクトの作成
   if(!ObjectCreate(0, objectName2, OBJ_LABEL, 0, 0, 0))
   {
      //return(INIT_FAILED);
   }
   // 座標のアンカー位置
   ObjectSetInteger(0, objectName2 ,OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
   // X位置
   ObjectSetInteger(0, objectName2, OBJPROP_XDISTANCE, 35);
   // Y位置
   ObjectSetInteger(0, objectName2, OBJPROP_YDISTANCE, 35);
   // 色
   ObjectSetInteger(0, objectName2, OBJPROP_COLOR, clrWhite);
   // 読み取り専用
   ObjectSetInteger(0, objectName2, OBJPROP_READONLY, true);
   // 選択不可
   ObjectSetInteger(0, objectName2, OBJPROP_SELECTABLE, false);
   // フォント名
   ObjectSetString(0, objectName2, OBJPROP_FONT, "MS ゴシック");
   // フォントサイズ
   ObjectSetInteger(0, objectName2, OBJPROP_FONTSIZE, 8);

   Start_Shikin = AccountBalance();

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
   ObjectDelete(0,objectName); 
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
   int total=0,orderPtn=0;
   bool OrderKekka=false;
   string message;

//***決済判断箇所***//   
   //ポジション決済処理
   Posi_CntDel(OP_BUY);
   Posi_CntDel(OP_SELL);
//***決済判断箇所***//

//***売買箇所***//
   orderPtn = Entry_Chk(OP_BUY);
   OrderKekka = Main_Syori(OP_BUY,orderPtn);  //ロング処理   
   
   orderPtn = Entry_Chk(OP_SELL);
   OrderKekka = Main_Syori(OP_SELL,orderPtn);  //ショート処理
//***売買箇所***//

   total=funcOrder_Select(OP_BUY,0,MAGIC_NO,Main_ea_ticket);
   total_buf_L = total;
   
   total=funcOrder_Select(OP_SELL,0,MAGIC_NO,Main_ea_ticket);
   total_buf_S = total;


   message="Lポジション数:" + IntegerToString(total_buf_L) + " Sポジション数:" + IntegerToString(total_buf_S);
   ObjectSetString(0, objectName, OBJPROP_TEXT, message);
   
   message= nanpin_message_L + " " + nanpin_message_S;
   ObjectSetString(0, objectName2, OBJPROP_TEXT, message);    

}
//+------------------------------------------------------------------+

int Entry_Chk(int e_type){
int orderPtn=0,total=0;

   total=funcOrder_Select(e_type,0,MAGIC_NO,Main_ea_ticket);

   //基本エントリー
   if(total == 0){
   
      if(SELECT_INDI == 0){
         //ストキャスティクスの値取得
         double STOC_atai1 = iStochastic(NULL,0,I_PRAM1,I_PRAM2,I_PRAM3,MODE_SMA,0,0,1);
         double STOC_atai2 = iStochastic(NULL,0,I_PRAM1,I_PRAM2,I_PRAM3,MODE_SMA,0,0,2);   
      
         //ローソク足の1つ前のクローズ値情報を取得しておく
   
         if(e_type == OP_BUY){
            if(STOC_atai1 < E_KAI && STOC_atai2 > STOC_atai1)
            {
               orderPtn=1;
            }
         }
         if(e_type == OP_SELL){      
            if(STOC_atai1 > E_URI && STOC_atai2 < STOC_atai1)
            {
               orderPtn=2;
            }
         }
      }
      if(SELECT_INDI == 1){
         //RSIの値取得
         double RSI_atai1   = iRSI(NULL, 0, I_PRAM1, PRICE_CLOSE, 1);    //RSIの値を取得
         double RSI_atai2   = iRSI(NULL, 0, I_PRAM1, PRICE_CLOSE, 2);    //RSIの値を取得
      
         //ローソク足の1つ前のクローズ値情報を取得しておく
   
         if(e_type == OP_BUY){
            if(RSI_atai1 < E_KAI && RSI_atai2 > E_KAI)
            {
               orderPtn=1;
            }
         }
         if(e_type == OP_SELL){      
            if(RSI_atai1 > E_URI && RSI_atai2 < E_URI)
            {
               orderPtn=2;
            }
         }
      }
   

      
      //新しい足ができた時だけ新規エントリーする(ナンピンは常時監視)
      if(Time[0] != prevtime){
         if(e_type == OP_SELL){
            prevtime = Time[0];
         }
      }else{
         orderPtn=0;   
      }
   
   
   //ナンピンエントリー
   }else{
      double GP = getProfit(e_type,0,MAGIC_NO);
         
      double nanpin_H;
      nanpin_H = NANPIN_HABA * -1;
   
      //ナンピン幅を超えればエントリー
      if(GP<= nanpin_H - MarketInfo(NULL,MODE_SPREAD) / 10 ){
         if(e_type==OP_BUY){
            orderPtn=1;
         }
         if(e_type==OP_SELL){
            orderPtn=2;
         }
      }
      
      double Pips_keisan = ((nanpin_H * -1)  + MarketInfo(NULL,MODE_SPREAD) / 10) + GP;
      
      if(e_type==OP_BUY){
         nanpin_message_L ="Lナンピン目安:あと"+ DoubleToString(Pips_keisan,1) + "pips";
      }
      if(e_type==OP_SELL){
         nanpin_message_S ="Sナンピン目安:あと"+ DoubleToString(Pips_keisan,1) + "pips" ;
      }
      
      
   }

///画面ログ出力///

   if(total==0 && orderPtn!=0){
      if(orderPtn==1){
         Print("【買いエントリー】");   
      }
      if(orderPtn==2){
         Print("【売りエントリー】");   

      }
   }
   if(total>0 && orderPtn!=0 && total < MAX_POSISION){
      if(orderPtn==1){
         Print("【買いナンピン】 "+IntegerToString(total) + "回目");   
      }
      if(orderPtn==2){
         Print("【売りナンピン】 "+IntegerToString(total) + "回目");   

      }
   }

   return(orderPtn);
}


//+------------------------------------------------------------------+
//|【関数】全決済関数
//| 
//|【引数】 mode 0:ロングポジション 1:ショートポジション 2:両ポジション 
//|
//|【戻値】true
//| 
bool all_Del(int type){
   int del_total=0;
   int Del_ticket[100];

   //配列を初期化
   ArrayInitialize(Del_ticket,0);

   
   if(type==0 || type==1){
      if(funcOrder_Select(type,0,MAGIC_NO,Main_ea_ticket) > 0){
         for(int cnt = 0; cnt < OrdersTotal(); cnt++){
            if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) == true){    
               if(OrderMagicNumber() == MAGIC_NO && OrderType() == type){
                  Del_ticket[cnt] = OrderTicket();
                  del_total = del_total +1;
                  
               }
            }
         }
      }     
   }if(type==2){
      if(funcOrder_Select(type,0,MAGIC_NO,Main_ea_ticket) > 0){
         for(int cnt = 0; cnt < OrdersTotal(); cnt++){
            if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) == true){    
               if(OrderMagicNumber() == MAGIC_NO){
                  Del_ticket[cnt] = OrderTicket();
                  del_total = del_total +1;
               }
            }
         }
      }
   }
   for(int cnt = 0; cnt < del_total; cnt++){
      bool OrderKekka = funcOrder_Close(type,Del_ticket[cnt],10000,MAGIC_NO,clrCyan);
   } 
   
   
   return(true);
}

//+------------------------------------------------------------------+
//|【関数】決済関数(ナンピン時、付随ポジションも削除)
//| 
//|【引数】 mode 0:ロングポジション 1:ショートポジション 2:両ポジション 
//|
//|【戻値】true
//| 
bool Posi_CntDel(int e_type){
   double rieki_buf = 0; 
   int ticket_cnt = 0;
   
   int total=funcOrder_Select(e_type,0,MAGIC_NO,Main_ea_ticket);

   if(total > 0){
      //最終ポジションから2つ前のpipsを確認し満たしていれば決済する
      if(total ==1){
         rieki_buf = RIKAKU;
         ticket_cnt = 0;    
      }   
      if(total ==2){
         rieki_buf = RIKAKU;
         ticket_cnt = 0;    
      }   
      if(total ==3){
         rieki_buf = RIKAKU;
         ticket_cnt = 1;       
      }
   
      if(total > 3){  
         rieki_buf = RIKAKU;
         ticket_cnt = total-3; 
      }   

      //対象ポジションを決済
      if(getProfit(e_type,Main_ea_ticket[ticket_cnt],MAGIC_NO) > rieki_buf){
         bool OrderKekka = funcOrder_Close(e_type,OrderTicket(),10000,MAGIC_NO,clrCyan);
         
         //付随ポジション全削除処理
         all_Del(e_type);
      }
   }
   return(true);
}

~~~~

基本の処理と決済処理まで(上半分)を公開しています。

スポンサーリンク

さいごに

以上、本格的なナンピンEAでした。

ナンピンEAはとにかくポジション管理が大事になってきますので、整理しながら作らないと訳が分からなくなりますので気を付けましょう。

もし上記ソースコードを全て知りたい方・学びたい方・改良したものを購入したい方がおられましたら、オンラインレッスンやEA作成依頼からお願いします。

※ EAのサンプルソースを一覧表にまとめました

※オンラインレッスンやってます


コメント