Re: Coding Help

1573
Hi everyone. I'm trying to create a function that moves the stoploss into a set number of profit after a certain number of candles have passed since the point of entry in mql5. It works for buys trades but never for sell trades for some reason. I've been staring at it for hours and can't figure out why.
Here's the function below. Much thanks in advance to anyone who can spot the problem.

Code: Select all

void UpdateTrailingStop()
{
    double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    double trailingStopPrice;

    if(PositionSelect(_Symbol))
    {
        // Get the time when the current candle opened
        datetime currentTime = TimeCurrent();
        datetime positionOpenTime = (datetime)PositionGetInteger(POSITION_TIME);
        int candleTimeframe = PeriodSeconds(_Period); // Timeframe of the chart in seconds

        // Calculate how many candles have closed since the trade was opened
        int candlesSinceOpen = (int)((currentTime - positionOpenTime) / candleTimeframe);

        // Check if the required number of candles have passed
        if(candlesSinceOpen >= CandlesBeforeTrailing)
        {
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
                double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                trailingStopPrice = NormalizeDouble(openPrice + TrailingStopPoints * point, _Digits);
                // Move stop loss into profit
                if(trailingStopPrice < SymbolInfoDouble(_Symbol, SYMBOL_BID) && trailingStopPrice > PositionGetDouble(POSITION_SL))
                    trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
            }
            else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            {
                double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                trailingStopPrice = NormalizeDouble(openPrice - TrailingStopPoints * point, _Digits);
                // Move stop loss into profit
                if(trailingStopPrice > SymbolInfoDouble(_Symbol, SYMBOL_ASK) && trailingStopPrice < PositionGetDouble(POSITION_SL))
                    trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
            }
        }
    }
}

Re: Coding Help

1574
DaffyTaffy wrote: Mon Apr 22, 2024 9:02 pm Hi everyone. I'm trying to create a function that moves the stoploss into a set number of profit after a certain number of candles have passed since the point of entry in mql5. It works for buys trades but never for sell trades for some reason. I've been staring at it for hours and can't figure out why.
Here's the function below. Much thanks in advance to anyone who can spot the problem.

Code: Select all

void UpdateTrailingStop()
{
    double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    double trailingStopPrice;

    if(PositionSelect(_Symbol))
    {
        // Get the time when the current candle opened
        datetime currentTime = TimeCurrent();
        datetime positionOpenTime = (datetime)PositionGetInteger(POSITION_TIME);
        int candleTimeframe = PeriodSeconds(_Period); // Timeframe of the chart in seconds

        // Calculate how many candles have closed since the trade was opened
        int candlesSinceOpen = (int)((currentTime - positionOpenTime) / candleTimeframe);

        // Check if the required number of candles have passed
        if(candlesSinceOpen >= CandlesBeforeTrailing)
        {
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
                double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                trailingStopPrice = NormalizeDouble(openPrice + TrailingStopPoints * point, _Digits);
                // Move stop loss into profit
                if(trailingStopPrice < SymbolInfoDouble(_Symbol, SYMBOL_BID) && trailingStopPrice > PositionGetDouble(POSITION_SL))
                    trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
            }
            else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            {
                double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                trailingStopPrice = NormalizeDouble(openPrice - TrailingStopPoints * point, _Digits);
                // Move stop loss into profit
                if(trailingStopPrice > SymbolInfoDouble(_Symbol, SYMBOL_ASK) && trailingStopPrice < PositionGetDouble(POSITION_SL))
                    trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
            }
        }
    }
}

I feel kinda slow right now. Or maybe I've just been at my screen for too long. Fixed it buy changing making both conditions "&& trailingStopPrice > PositionGetDouble(POSITION_SL)" but I don't get how that's supposed to work. Shouldn't it be the other way around? I also changed the name of the function as my intention was to lock in a bit of profit and not trail the stops. Removing the "&& trailingStopPrice > PositionGetDouble(POSITION_SL)" part of the code entirely alos works.

Code: Select all

void LockInProfit()
  {
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double trailingStopPrice;

   if(PositionSelect(_Symbol))
     {
      // Get the time when the current candle opened
      datetime currentTime = TimeCurrent();
      datetime positionOpenTime = (datetime)PositionGetInteger(POSITION_TIME);
      int candleTimeframe = PeriodSeconds(_Period); // Timeframe of the chart in seconds

      // Calculate how many candles have closed since the trade was opened
      int candlesSinceOpen = (int)((currentTime - positionOpenTime) / candleTimeframe);

      // Check if the required number of candles have passed
      if(candlesSinceOpen >= CandlesBeforeTrailing)
        {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
           {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            trailingStopPrice = NormalizeDouble(openPrice + TrailingStopPoints * point, _Digits);
            // Move stop loss into profit
            if(trailingStopPrice < SymbolInfoDouble(_Symbol, SYMBOL_BID) && trailingStopPrice > PositionGetDouble(POSITION_SL))
               trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
           }
         else
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
              {
               double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
               trailingStopPrice = NormalizeDouble(openPrice - TrailingStopPoints * point, _Digits);
               // Move stop loss into profit
               // Ensure stop loss is set above the current ask price but does not need to be lower than the existing stop if the market moved favorably
               if(trailingStopPrice > SymbolInfoDouble(_Symbol, SYMBOL_ASK) && trailingStopPrice > PositionGetDouble(POSITION_SL))
                  trade.PositionModify(_Symbol, trailingStopPrice, PositionGetDouble(POSITION_TP));
              }
        }
     }
  }
These users thanked the author DaffyTaffy for the post:
mrtools

Re: Coding Help

1575
DaffyTaffy wrote: Mon Apr 22, 2024 9:59 pm I feel kinda slow right now. Or maybe I've just been at my screen for too long. Fixed it buy changing making both conditions "&& trailingStopPrice > PositionGetDouble(POSITION_SL)" but I don't get how that's supposed to work. Shouldn't it be the other way around? I also changed the name of the function as my intention was to lock in a bit of profit and not trail the stops. Removing the "&& trailingStopPrice > PositionGetDouble(POSITION_SL)" part of the code entirely alos works.
I suspect that your reference to PositionSelect is not returning the latest position data:

"Function PositionSelect() copies data about a position into the program environment, and further calls of PositionGetDouble(), PositionGetInteger() and PositionGetString() return the earlier copied data. This means that the position itself may no longer exist (or its volume, direction, etc. has changed), but data of this position still can be obtained. To ensure receipt of fresh data about a position, it is recommended to call PositionSelect() right before referring to them" (https://www.mql5.com/en/docs/trading/positionselect),

Try using PositionsTotal within a loop. Here's some code copied from a working EA without PositionSelect:

Code: Select all

   if(PositionsTotal() == 1)
    {
     for(int i = PositionsTotal() - 1; i >= 0; i--) // count all currency pair positions
      {
       // get the ticket number
       ulong PositionTicket=PositionGetTicket(i);
       ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
       ENUM_POSITION_PROPERTY_DOUBLE openprice = (ENUM_POSITION_PROPERTY_DOUBLE)PositionGetDouble(POSITION_PRICE_OPEN);
     
       if (type == POSITION_TYPE_BUY)
		  {
         lastBuyStopPrice = POSITION_PRICE_OPEN;
        }
     
       if (type == POSITION_TYPE_SELL)
        {
         lastSellStopPrice = POSITION_PRICE_OPEN;
        }     
      }     
    }
These users thanked the author JohnnyRy for the post:
DaffyTaffy
“[A]s we know, there are known knowns—there are things we know we know. We also know there are known unknowns—that is to say we know there are some things we do not know. But there are also unknown unknowns—the ones we don’t know we don’t know.”—Donald Rumsfeld, 2002


Who is online

Users browsing this forum: No registered users and 3 guests