トラリピEA改造

爆益

トラリピEAを改造していろいろやってます。プログラムは素人にて容赦ねがいます。

//+------------------------------------------------------------------+
//|                                                  MTR20250105.mq4 |
//|                                   Copyright 2025, bakueki-fx.com |
//|                                           https://bakueki-fx.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, bakueki-fx.com"
#property link      "https://bakueki-fx.com"
#property version   "1.00"
#property strict
//--- input parameters


// バックテスト時は、timerInterval = 0 にしないと動かない。
// トレンドフォロー時、stopOrderSpreadPips は、 doOrderRangePips 未満にしないとエントリーしない。
// backTestMode = false では、処理が重くバックテストに時間がかかる。

input string eaName = "MTR20250105"; 
input int timerInterval = 10;
input int magicNumber = 1110000;
input double lots = 0.01;
input bool isBuyTrap=true;
input double maxOpenPrice = 160;
input int trapCount = 600;
input int trapIntervalPips = 10;
input int doOrderRangePips = 50;
input bool isTrendFollowOnly = false;
input int stopOrderSpreadPips = 10;
input int minProfitPips = 10;      
input int trailingProfitPips = 5;
input int maxTakePosition=1000;
input int printInfomationLevel=0;
//input bool doPrintInformation = true;

input double lossCutBorderLine = 100;  

input int intervalTrapOrder = 10;
input int intervalTrailingStop = 20;
input bool backTestMode = false;


//--- Global parameters

int waitTime = 5;                    // 待機時間
int slippage = 3;                    // スリッページ

color arrowColor[6] = { Green, Red, Green, Red, Green, Red }; // 矢印の色
int ticketArray[];                   // チケット配列
int magicArray[];                    // マジックナンバー配列

datetime lastExecutionTrapOrder = 0;
datetime lastExecutionTrailingStop = 0;

double pointPerPips;     // 1pipsあたりのポイント
int slippagePips;
int digitMultiplier;


    double buySum = 0;        // Buyポジションの加重取得価格合計
    double sellSum = 0;       // Sellポジションの加重取得価格合計
    double buyLotSum = 0;     // Buyポジションのロット数合計
    double sellLotSum = 0;    // Sellポジションのロット数合計
    double buyAverage = 0;     // Buyポジションの平均取得価格
    double sellAverage = 0;    // Sellポジションの平均取得価格
    double buyLossCutLine =0 ;
    double sellLossCutLine =0 ;  
    int buyPositionCount = 0;
    int sellPositionCount =0;
    double buyLotProfit = 0;     // Buyポジションの利益合計
    double sellLotProfit = 0;    // Sellポジションの利益合計


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

    int mult = 1;
    if(Digits == 3 || Digits == 5) {
        mult = 10;
    }
    pointPerPips = Point * mult;
    slippagePips = slippage * mult;
    digitMultiplier = MathPow(10,Digits);  

    Print(" Digits= ",Digits," Point= ",Point," pointPerPips= ",pointPerPips," slippagePips= ",slippagePips," digitMultiplier= ",digitMultiplier," mult= ",mult );  
     
     
//--- create timer
    if (timerInterval > 0)
     {
      EventSetTimer(timerInterval); // 外部入力のタイマー間隔を設定
      Print("Timer enabled with interval: ", timerInterval, " seconds.");
     }
   else
     {
      Print("Timer disabled. Using OnTick() instead.");
     }
 
 
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if (timerInterval <= 0) 
     {
      main(); // TimerIntervalが0以下の場合、OnTick()で動作
     }
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
 if (timerInterval > 0)
     {
      main(); // TimerIntervalが有効の場合、OnTimerで動作
     }
   
  }
//+------------------------------------------------------------------+
//| main関数                                                   |
//+------------------------------------------------------------------+

void main()
  {
//---
    
    if (!backTestMode==true){
    if(initOrderTicketInfo()==false)return;
    doGetInfomation();
      }

   datetime nowO = TimeCurrent();
   datetime nowT = TimeCurrent()+10;
   
      if(nowO - lastExecutionTrapOrder >= intervalTrapOrder){
      if(initOrderTicketInfo()==false)return;
      if (printInfomationLevel>=2){
      Print("トラップ発注を実行 時間= ",nowO);
      }
     // doGetInfomation();
      doTrapRepeatIfDone();
      lastExecutionTrapOrder =nowO;
      }

      if(nowT - lastExecutionTrailingStop >= intervalTrailingStop){
      if(initOrderTicketInfo()==false)return;  
      if (printInfomationLevel>=2){
      Print("トレーリングストップを実行 時間= ",nowT);
    
      }
      doTrailing();
      lastExecutionTrailingStop =nowT;
      }
      
  }

//+------------------------------------------------------------------+

bool initOrderTicketInfo(){

    // 対象通貨ペアの件数を取得
    int orderCount=0;
    for(int j=0; j < OrdersTotal(); j++) { 
        if(OrderSelect(j,SELECT_BY_POS,MODE_TRADES) == false) return(false);
        if(OrderSymbol() == Symbol()) {
            orderCount++;
        }
    }
    
    // 配列を初期化
    ArrayResize(ticketArray,orderCount);
    ArrayResize(magicArray,orderCount);
    ArrayInitialize(ticketArray, -1); // 初期化
    ArrayInitialize(magicArray, -1); // 初期化
    
    orderCount=0;

    // 配列にセット
    for(int j=0; j < OrdersTotal(); j++) { 
        if(OrderSelect(j,SELECT_BY_POS,MODE_TRADES) == false) return(false);
        if(OrderSymbol() == Symbol()) {
            ticketArray[orderCount] = OrderTicket();
            magicArray[orderCount] = OrderMagicNumber();
            orderCount++;
        }
    }
    return(true);   
}
//+------------------------------------------------------------------+
// 指定されたMAGIC注文があるかどうかをチェックする。なければ「-1」を返す
//
int getOrderTicket(int magic){

    int orderCount = 0;
    int ticket = -1;
    for(int i=0; i < ArraySize(magicArray); i++) { 
        if(magic == magicArray[i]) {
            ticket = ticketArray[i];
            orderCount++;
        }
    }

    if(orderCount > 1){
    }
    
    return(ticket);
} 

//+------------------------------------------------------------------+
//
int doTrapRepeatIfDone() {

    for(int i=0; i < trapCount; i++){ 
        double openPrice = maxOpenPrice - trapIntervalPips * i * pointPerPips;

        // 現値より大きく乖離した発注は出さない
        double currentPrice;
        if(isBuyTrap){
            currentPrice = Ask;
        } else {
            currentPrice = Bid;
        }
        if( doOrderRangePips != 0 &&
             (openPrice < currentPrice - doOrderRangePips * pointPerPips || openPrice > currentPrice + doOrderRangePips * pointPerPips) ){
            continue;
        }


        int magic = magicNumber+i;

        // 注文状態をチェックし、注文がなければリピートする
        int ticket = getOrderTicket(magic);
        if ( ticket <= 0) {
               ticket = doRepeatIfDone(openPrice, magic);
               }
        
    
    }
return(0);
}

// 指定された条件でリピートIfDone注文を実行する
int doRepeatIfDone(double openPrice,int magic) {

    // 注文形式を決定する
    int tradeType = -1;

    if( isTrendFollowOnly == true ) {
        // トレンドフォローモードの場合、トレンドフォローを確認するため、
        // ASK値が一旦、閾値以上の下値に達した後に建値まで戻ってきた場合にのみ
        // リピートするようにする
        // stopOrderSpreadPipsの値は、doOrderRangePipsより小さい値でないと発注しない!
        if(isBuyTrap && openPrice >= Ask + stopOrderSpreadPips * pointPerPips ) {
            tradeType = OP_BUYSTOP;
        } else if(!isBuyTrap && openPrice < Bid - stopOrderSpreadPips * pointPerPips ) {
            tradeType = OP_SELLSTOP;
        }
    } else {
        if(isBuyTrap && openPrice <= Ask) {
            // 買い注文で、建値 <= 現在価格(Ask) の場合は買い指値
            tradeType = OP_BUYLIMIT;
        } else if(isBuyTrap && openPrice > Ask) {
            // 買い注文で、建値 > 現在価格(Ask) の場合は買い逆指値
            tradeType = OP_BUYSTOP;
        } else if(!isBuyTrap && openPrice >= Bid) {
            // 売り注文で、建値 >= 現在価格(Bid) の場合は売り指値
            tradeType = OP_SELLLIMIT;
        } else if(!isBuyTrap && openPrice < Bid) {
            // 売り注文で、建値 < 現在価格(Bid) の場合は売り逆指値
            tradeType = OP_SELLSTOP;
        }
    }
  
     
    // 注文形式が注文不要の場合はそのまま終了する
    if(tradeType == -1) {
        return(-1);
    }
    
    int ticket = doOrderSend(tradeType,openPrice,magic);

    return(ticket);
}

//+------------------------------------------------------------------+
//
// 発注する
int doOrderSend(int type, double openPrice, int magic) {


 // 0時23時は動作しない。
    if(Hour()==23||Hour()==0||DayOfWeek()==6||DayOfWeek()==0){
     return(-1);
    }

doGetInfomation();


  if (!backTestMode==true){

   if( buyPositionCount >= maxTakePosition|| sellPositionCount >= maxTakePosition){
   if (printInfomationLevel>=1){
   Print("これ以上の発注はできません。 "," BuyPosition= ",buyPositionCount," SellPosition= ",sellPositionCount);
   }
     return(-1);
    }

if(isBuyTrap==true){

  if( buyLossCutLine >= lossCutBorderLine){
   if (printInfomationLevel>=1||printInfomationLevel==-1){
   Print("これ以上の発注はできません。 "," buyLossCutLine= ",buyLossCutLine," lossCutBorderLine= ",lossCutBorderLine," 余剰証拠金= ",AccountFreeMargin()," 買いLot数= ",buyLotSum," 買い平均価格= ",buyAverage);
   }
     return(-1);
    }
}
else{

  if( sellLossCutLine <= lossCutBorderLine){
   if (printInfomationLevel>=1||printInfomationLevel==-1){
   Print("これ以上の発注はできません。 "," sellLossCutLine= ",sellLossCutLine," lossCutBorderLine= ",lossCutBorderLine," 余剰証拠金= ",AccountFreeMargin()," 売りLot数= ",sellLotSum," 売り平均価格= ",sellAverage);
   }
     return(-1);
    }
}
}

    openPrice = NormalizeDouble(openPrice, Digits);

    while(true) {
        if(IsTradeAllowed() == true) {
            RefreshRates();
            int ticket = OrderSend(Symbol(), type, lots, openPrice, slippage, 0, 0, magic, magic, 0, arrowColor[type]);
             if( ticket > 0) {
                 if (printInfomationLevel>=1){
               Print("発注しました magic= ",magic ," ticket= ",ticket," openPrice= ",openPrice);
                }
                Sleep(waitTime*1000); 
                return(ticket);
               }
                  if (printInfomationLevel>=1){
            Print("発注エラー magic= ",magic ," ticket= ",ticket," エラーコード: ", GetLastError());
            }
            Sleep(waitTime*2000); 
            break;
            }           
        }  
        
    return(-1);
}



//+------------------------------------------------------------------+
//
int doTrailing() {

    for(int i=0; i < trapCount; i++){
        int magic = magicNumber+i;

        // 注文状態をチェックし、注文があれば 実行する。
        int ticket = getOrderTicket(magic);
         if (ticket > 0) {
         doTrailingOrderModify(ticket);
        }          
        
    }
    return(0);
    }

//+------------------------------------------------------------------+
//
int doTrailingOrderModify(int ticket){

 // 0時23時は動作しない。
    if(Hour()==23||Hour()==0||DayOfWeek()==6||DayOfWeek()==0){
     return(-1);
    }




    if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES) ==true)
         {
         
           if(OrderType() > 1) {
           return(-1);
             }
         
               
        RefreshRates();
         double orderDifference = (OrderType() == OP_BUY) ? (Bid - OrderOpenPrice())  : (OrderOpenPrice()-Ask);
         orderDifference =orderDifference /pointPerPips;
         
         if(orderDifference < minProfitPips )return(-1);
         
            if (printInfomationLevel>=1){
        Print("★ トレール利益を超えた  Bid= ",Bid,"  OrderOpenPrice()= ",OrderOpenPrice(),"   doTrailingOrderModify  ticket= ",ticket,"   orderDifferenc Point= ",orderDifference);
         }
         
            // 現在の逆指値価格を計算 
            double newStopLoss = (OrderType() == OP_BUY) ? Bid - trailingProfitPips * pointPerPips : Ask + trailingProfitPips * pointPerPips;

            // 既存の逆指値を更新
            if ((OrderType() == OP_BUY && (OrderStopLoss() < newStopLoss || OrderStopLoss() == 0)) ||
                (OrderType() == OP_SELL && (OrderStopLoss() > newStopLoss || OrderStopLoss() == 0)))
            {
               if (!OrderModify(ticket, 0, NormalizeDouble(newStopLoss, Digits), 0, 0, clrYellow))
               
               //  if (!OrderModify(ticket, 0, newStopLoss, 0, 0, clrYellow))
               {
                  if (printInfomationLevel>=1){
               Print("OrderModify failed: ", GetLastError(), " OrderTicket: ", OrderTicket(),"OrderMagicNumber= ", OrderMagicNumber());
               }
               }
               else
               {
                  if (printInfomationLevel>=1){
               Print("OrderModify succeeded for ticket: ", OrderTicket(), " New StopLoss: ", DoubleToString(newStopLoss, Digits));
               }
               }
            }
         }



return(ticket);
}

//+------------------------------------------------------------------+
//
int doGetInfomation(){


    buySum = 0;        // Buyポジションの加重取得価格合計
    sellSum = 0;       // Sellポジションの加重取得価格合計
    buyLotSum = 0;     // Buyポジションのロット数合計
    sellLotSum = 0;    // Sellポジションのロット数合計
    buyAverage = 0;     // Buyポジションの平均取得価格
    sellAverage = 0;    // Sellポジションの平均取得価格
    buyLossCutLine =0 ;
    sellLossCutLine =0 ;  
    buyPositionCount = 0;
    sellPositionCount =0;
    buyLotProfit = 0;     // Buyポジションの利益合計
    sellLotProfit = 0;    // Sellポジションの利益合計


    // ポジションのサーチ
    for (int i = 0; i < OrdersTotal(); i++)
    {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) // すべての注文をチェック
        {
          //  if (OrderSymbol() == symbol) // 現在の通貨ペアが一致する場合
               
               
               
        for(int j=0; j < trapCount; j++){
        int magic = magicNumber+j;

        // 注文状態をチェック
        int ticket = getOrderTicket(magic);
         if (ticket == OrderTicket() )          
        
            {
                double lotSize = OrderLots(); // ポジションのロット数を取得
                double openPrice = OrderOpenPrice(); // ポジションの取得価格を取得

                if (OrderType() == OP_BUY) // Buyポジションの場合
                {
                    buySum += openPrice * lotSize; // ロット数で加重した取得価格を合計
                    buyLotSum += lotSize;          // Buyポジションのロット数を合計
                    buyPositionCount++;
                    buyLotProfit += OrderProfit();
                }
                else if (OrderType() == OP_SELL) // Sellポジションの場合
                {
                    sellSum += openPrice * lotSize; // ロット数で加重した取得価格を合計
                    sellLotSum += lotSize;          // Sellポジションのロット数を合計
                    sellPositionCount++;
                    sellLotProfit += OrderProfit();
                }
            }
        }
    }
   }
    // Buyポジションの平均取得価格を計算
    buyAverage = buyLotSum > 0 ? buySum / buyLotSum : 0;
  
  
    // Sellポジションの平均取得価格を計算
    sellAverage = sellLotSum > 0 ? sellSum / sellLotSum : 0;


   buyLossCutLine = buyLotSum > 0 
    ? Bid - (AccountFreeMargin() / (buyLotSum * 100))/digitMultiplier
    : 0;

   
   sellLossCutLine = sellLotSum > 0 
    ? Bid + (AccountFreeMargin() / (sellLotSum * 100))/digitMultiplier
    : 0;
    
    
buyAverage = NormalizeDouble(buyAverage,Digits);
sellAverage = NormalizeDouble(sellAverage,Digits);


buyLotSum=NormalizeDouble(buyLotSum,Digits);
sellLotSum=NormalizeDouble(sellLotSum,Digits);

buyLossCutLine= NormalizeDouble(buyLossCutLine,Digits);
sellLossCutLine=NormalizeDouble(sellLossCutLine,Digits);

buyLotProfit= NormalizeDouble(buyLotProfit,Digits);
sellLotProfit=NormalizeDouble(sellLotProfit,Digits);

   if (printInfomationLevel>=2){
Print("Buy Average: ", buyAverage, ", Buy Lot Sum: ", buyLotSum);
Print("Sell Average: ", sellAverage, ", Sell Lot Sum: ", sellLotSum);
Print("buyPositionCount : ", buyPositionCount, ", sellPositionCount: ", sellPositionCount);
Print("Buy Loss Cut Line: ", buyLossCutLine, ", Sell Loss Cut Line: ", sellLossCutLine);

}





return(0);

}

タイトルとURLをコピーしました