EA自作企画第7弾!準備がまだ!って人は先に準備しましょう!こっちのページを参照してね!

こちらのサイトのようなところへ行けば、EA自体は購入が可能です。

投資家の祭典 GogoJungle AWARD 2023

これまでに、エントリーは出来るようになりましたが、利確がされていませんでした。そこで今回は、一定の利益になったらポジションクローズするようにしてみます。

目標とするEAに近づけたい…

自作EAの条件

損切しない!

スワップが増える方向にだけエントリー

似たようなところでエントリーしない!

最大ポジション数を取った時にレバレッジ10倍を超えない!

年利と月利

年利 1% → 月利 0.08%

   2% →    0.17%

   5% →    0.41%

  10% →    0.8%

  30% →    2.21%

  50% →    3.44%

100%(2倍) →   5.95%

200%(3倍) →   9.59%

以下のようにしてみました。

//+------------------------------------------------------------------+
//|                                                 OnewayTrader.mq4 |
//|                                          Copyright 2025, FPshima |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, FPshima"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

extern bool LongOn = true;//ロングを許可
extern bool ShortOn = false;//ショートを許可

extern int zone = 50;//エントリー不可範囲
extern int maxPosition = 4;//最大ポジション数
extern double risk = 10;//取りうる最大リスク

extern double profitRate = 2;//新たに利確ラインを設定できるようにした

double calculateLotSize()
{
   double accountBalance = AccountBalance();
   double totalRiskAmount = accountBalance * risk/100;
   double eachPositionRisk = totalRiskAmount/maxPosition;
   double minLot = MarketInfo(NULL,MODE_MINLOT);
   double marginRequire = MarketInfo(NULL,MODE_MARGINREQUIRED)*minLot;
   double lotSize = (eachPositionRisk / marginRequire)*minLot;
   if(lotSize <= minLot)
   {
      lotSize = minLot;
   }
   if(lotSize <= 20.0)
   {
     lotSize = NormalizeDouble(lotSize,2);
   }
   if(lotSize > 20.0)
   {
      lotSize = 20.0;
   }
   return lotSize;
}

bool EntryJudge(int tradeType)
{
   double zonePips = zone *Point*10;
   int currentPositions = 0;
   

   
   for(int i = 0 ; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
         currentPositions++;
         if(OrderType() == tradeType && MathAbs(OrderOpenPrice()-Ask) <= zonePips && OrderType() == OP_BUY)
         {
            return false;
         }
         
         if(OrderType() == tradeType && MathAbs(OrderOpenPrice()-Bid) <= zonePips && OrderType() == OP_SELL)
         {
            return false;
         }
      }
   }
   if(currentPositions < maxPosition)
   {
      return true;
   }else{
   
      return false;
   }
}

void CheckAndClosePositions(double profitPercent)// 後々利確ラインをexternだけじゃない方法で決められるように引数設定
{
   double accountBalance = AccountBalance();
   int totalPositions = 0;
   double totalProfit = 0;
   
   for(int i = 0; i< OrdersTotal(); i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
         double positionProfit = OrderProfit() + OrderSwap() - OrderCommission();//利益を調査
         totalProfit += positionProfit;//どんどん足して、全ポジの合計にする
         totalPositions++;
      }
   }
   double eachProfit = accountBalance * profitPercent/100;//個々のポジションの利確ライン
   double targetTotalProfit = accountBalance * profitPercent/100;//トータルも一緒
   
   if(totalPositions >1)//トータルポジションが2個以上の時
   {
      targetTotalProfit /= totalPositions;//ポジションの数に応じて利確ラインを下げる
   }
   
   for(int i = OrdersTotal() -1 ; i>= 0 ; i--)//iがマイナスになってる点が味噌
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))//ポジションチェック
      {
         double positionProfit = OrderProfit() + OrderSwap() - OrderCommission();
         
         if(totalProfit >= targetTotalProfit)//現有ポジションが目的利益よりも儲かってたら
         {
            OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),5,clrBlue);//全部利確
         }
      
      if(positionProfit >= eachProfit)//単一のポジションで目的地を超えてたら
      {
         OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),5,clrBlue);//利確
      }
      }
   }
   
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---


   CheckAndClosePositions(profitRate);//新しい変数を参照して利確ラインを検討
   double tradeLot = calculateLotSize();
   Comment("lotSize",tradeLot,"  Zonejudge  " , EntryJudge(OP_BUY));
   if(EntryJudge(OP_BUY) && LongOn == true)
   {
     OrderSend(NULL,OP_BUY,tradeLot,Ask,5,0,0,"Long",0,0,clrRed);
   }
   if(EntryJudge(OP_SELL) && ShortOn != false)
   {
     OrderSend(NULL,OP_SELL,tradeLot,Bid,5,0,0,"Short",0,0,clrRed);
   }
  }
//+------------------------------------------------------------------+

ポジションをチェックする関数を入れました。

見てみましょう。

void CheckAndClosePositions(double profitPercent)// 後々利確ラインをexternだけじゃない方法で決められるように引数設定
{
   double accountBalance = AccountBalance();
   int totalPositions = 0;
   double totalProfit = 0;
   
   for(int i = 0; i< OrdersTotal(); i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
      {
         double positionProfit = OrderProfit() + OrderSwap() - OrderCommission();//利益を調査
         totalProfit += positionProfit;//どんどん足して、全ポジの合計にする
         totalPositions++;
      }
   }
   double eachProfit = accountBalance * profitPercent/100;//個々のポジションの利確ライン
   double targetTotalProfit = accountBalance * profitPercent/100;//トータルも一緒
   
   if(totalPositions >1)//トータルポジションが2個以上の時
   {
      targetTotalProfit /= totalPositions;//ポジションの数に応じて利確ラインを下げる
   }
   
   for(int i = OrdersTotal() -1 ; i>= 0 ; i--)//iがマイナスになってる点が味噌
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))//ポジションチェック
      {
         double positionProfit = OrderProfit() + OrderSwap() - OrderCommission();
         
         if(totalProfit >= targetTotalProfit)//現有ポジションが目的利益よりも儲かってたら
         {
            OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),5,clrBlue);//全部利確
         }
      
      if(positionProfit >= eachProfit)//単一のポジションで目的地を超えてたら
      {
         OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),5,clrBlue);//利確
      }
      }
   }
   
}

ここまで読んでくれているとある程度分かってくることもあると思うので、新規なところを説明します。

OrderProfit() + OrderSwap() - OrderCommission()は、順に、含み益、含みスワップポイント、手数料です。したがって、これを合算することで、そのポジションの利益がわかります。

totalProfit += positionProfit ポジションが複数あると、for文でループするので、ポジションごとに利益が加算され、合計損益となります。

double eachProfit = accountBalance * profitPercent/100
double targetTotalProfit = accountBalance * profitPercent/100 この2つは同じ式ですが、次の式で意味が変わるようになっています。一方、単一ポジションならいずれにしても利確されます。

targetTotalProfit /= totalPositions ポジションが複数あるときは、証拠金的にもリスクがありますし、出来る限り早く逃げたいので、利確ラインをポジション数分減らしていっています。ループ処理ではないので、数に応じて割っています。

後半のfor文は、利確のためのfor文なのですが、ポジションをクローズする際に、ひとつずつクローズされます。この時、下から順にクローズすると、ポジション総数が変わってしまうため、i++だとうまく決済されません。したがって、i--として、ポジション数を最大値から減らしていってすべて決済できるように書きます

2ポジション持った時、同時に同じ位置で決済されていますね!これはナンピンした結果、より有利な位置から入れた分の利益で、あまり良くないポジションをうまい事決済しています。

ただ、エントリーに関してまだロジックが無いので、決済したと同時エントリーし、そこからzone離れた部分で次のポジションをとっています。このままだと、そもそも決済した意味があまりないですね…

次回はついにロジックです!といっても大したロジックにはしません!損切しませんし!

楽天証券(FX)

おすすめFXアイテム

過去検証や分析はMT4かFT4、Trading viewがおすすめです。

無料が良い人はMT4で、MT4を使わせてくれる口座を使用すると良いです。おすすめはFXTF

ガチで過去検証をやりたい人はFT4、

チャート分析に毎月課金してもいいよって人はTrading viewがおすすめです。無料もあります

Twitterでフォローしよう

おすすめの記事