Untitled

 avatar
unknown
plain_text
2 months ago
6.9 kB
2
Indexable
#include <Trade/Trade.mqh>
#include <Arrays/ArrayLong.mqh>

// Lot sizes for up to 20 orders in one cycle
static double lotSizes[20] = {0.01, 0.02, 0.02, 0.03, 0.05, 0.08, 0.11, 0.17, 0.26, 0.38,
                              0.58, 0.86, 1.30, 1.95, 2.92, 4.38, 6.75, 9.85, 10, 10};

// Adjustable parameters
input double  StepPercent   = 0.2;   // Percentage change relative to the open price to trigger step-in
input double  ProfitLotStep = 10;    // Profit threshold (scaled by lot) to close the cycle
input double  StopLoss      = 300;   // Stop-loss threshold (in account currency) to cut losses

// Separate arrays to store tickets for BUY and SELL orders
CArrayLong buyTickets;
CArrayLong sellTickets;
int barsTotal = 0;

int OnInit()
{
   barsTotal = iBars(_Symbol, PERIOD_M15); // Initialize barsTotal
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
}

// Function to close all BUY positions
void CloseBuyPositions(CTrade &trade)
{
   for (int i = buyTickets.Total() - 1; i >= 0; i--)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(buyTickets.At(i)))
      {
         if (trade.PositionClose(pos.Ticket()))
         {
            buyTickets.Delete(i);
         }
      }
   }
}

// Function to close all SELL positions
void CloseSellPositions(CTrade &trade)
{
   for (int i = sellTickets.Total() - 1; i >= 0; i--)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(sellTickets.At(i)))
      {
         if (trade.PositionClose(pos.Ticket()))
         {
            sellTickets.Delete(i);
         }
      }
   }
}

void OnTick()
{
   // Update barsTotal if a new M15 bar is formed
   int currentBars = iBars(_Symbol, PERIOD_M15);
   if(currentBars != barsTotal)
   {
      barsTotal = currentBars;
   }

   CTrade trade;
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   // Calculate profit and total lot separately for BUY orders
   double buyProfit = 0, buyLots = 0;
   for (int i = 0; i < buyTickets.Total(); i++)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(buyTickets.At(i)))
      {
         buyProfit += pos.Profit() + pos.Swap();
         buyLots   += pos.Volume();
      }
   }
   
   // Calculate profit and total lot separately for SELL orders
   double sellProfit = 0, sellLots = 0;
   for (int i = 0; i < sellTickets.Total(); i++)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(sellTickets.At(i)))
      {
         sellProfit += pos.Profit() + pos.Swap();
         sellLots   += pos.Volume();
      }
   }
   
   double lotstep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   // --- STEP-IN for BUY cycle ---
   if (buyTickets.Total() > 0 && buyTickets.Total() < 20)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(buyTickets.At(buyTickets.Total() - 1)))
      {
         double newLot = lotSizes[buyTickets.Total()];
         // If the current bid is sufficiently lower than the open price of the last BUY order
         if (bid < pos.PriceOpen() - pos.PriceOpen() * StepPercent / 100)
         {
            Print(__FUNCTION__, " > Step buy Signal with lot ", newLot, "...");
            if (trade.Buy(newLot) && trade.ResultOrder() > 0 && trade.ResultRetcode() == TRADE_RETCODE_DONE)
               buyTickets.Add(trade.ResultOrder());
         }
      }
   }
   
   // --- STEP-IN for SELL cycle ---
   if (sellTickets.Total() > 0 && sellTickets.Total() < 20)
   {
      CPositionInfo pos;
      if (pos.SelectByTicket(sellTickets.At(sellTickets.Total() - 1)))
      {
         double newLot = lotSizes[sellTickets.Total()];
         // If the current bid is sufficiently higher than the open price of the last SELL order
         if (bid > pos.PriceOpen() + pos.PriceOpen() * StepPercent / 100)
         {
            Print(__FUNCTION__, " > Step sell Signal with lot ", newLot, "...");
            if (trade.Sell(newLot) && trade.ResultOrder() > 0 && trade.ResultRetcode() == TRADE_RETCODE_DONE)
               sellTickets.Add(trade.ResultOrder());
         }
      }
   }
   
   // --- Activate initial orders for each independent cycle ---
   double openPrevious = iOpen(_Symbol, PERIOD_M15, 1);
   double openCurrent  = iOpen(_Symbol, PERIOD_M15, 0);
   
   // If there are no BUY orders and the market is falling, then enter a BUY order
   if (buyTickets.Total() == 0 && openCurrent < openPrevious)
   {
      double newLot = lotSizes[0];
      Print(__FUNCTION__, " Initial buy Signal with lot ", newLot, "...");
      if (trade.Buy(newLot) && trade.ResultOrder() > 0 && trade.ResultRetcode() == TRADE_RETCODE_DONE)
         buyTickets.Add(trade.ResultOrder());
   }
   
   // If there are no SELL orders and the market is rising, then enter a SELL order
   if (sellTickets.Total() == 0 && openCurrent > openPrevious)
   {
      double newLot = lotSizes[0];
      Print(__FUNCTION__, " Initial sell Signal with lot ", newLot, "...");
      if (trade.Sell(newLot) && trade.ResultOrder() > 0 && trade.ResultRetcode() == TRADE_RETCODE_DONE)
         sellTickets.Add(trade.ResultOrder());
   }
   
   // --- Risk management for BUY cycle ---
   if (buyTickets.Total() > 0)
   {
      // If the profit target for the BUY cycle is reached
      if (buyProfit > ProfitLotStep * buyLots / lotstep)
      {
         Print(__FUNCTION__, " > BUY cycle hit profit target, closing BUY positions...");
         CloseBuyPositions(trade);
      }
      // If loss exceeds the StopLoss for the BUY cycle
      if (buyProfit <= -StopLoss)
      {
         Print(__FUNCTION__, " > BUY cycle StopLoss reached (loss ", buyProfit, "), closing BUY positions...");
         CloseBuyPositions(trade);
      }
      // If 20 BUY orders are reached in the cycle
      if (buyTickets.Total() >= 20)
      {
         Print(__FUNCTION__, " > 20 BUY orders reached, closing BUY cycle...");
         CloseBuyPositions(trade);
      }
   }
   
   // --- Risk management for SELL cycle ---
   if (sellTickets.Total() > 0)
   {
      // If the profit target for the SELL cycle is reached
      if (sellProfit > ProfitLotStep * sellLots / lotstep)
      {
         Print(__FUNCTION__, " > SELL cycle hit profit target, closing SELL positions...");
         CloseSellPositions(trade);
      }
      // If loss exceeds the StopLoss for the SELL cycle
      if (sellProfit <= -StopLoss)
      {
         Print(__FUNCTION__, " > SELL cycle StopLoss reached (loss ", sellProfit, "), closing SELL positions...");
         CloseSellPositions(trade);
      }
      // If 20 SELL orders are reached in the cycle
      if (sellTickets.Total() >= 20)
      {
         Print(__FUNCTION__, " > 20 SELL orders reached, closing SELL cycle...");
         CloseSellPositions(trade);
      }
   }
}
Editor is loading...
Leave a Comment