Trying to create an Expert using Envelopes. Cant get it to work as I am a newb. Please help

 

I've been trying to create an Expert using the envelope indicator. Since adding automatic lot sizing it doesn't place anymore trades. Can someone send me in the general direction? As I'm not a programmer but willing to learn and dedicate a lot of time. It opens a buy and a sell and then it stops trading. please help. the notes at the bottom is what I want to add once im able to make this work so can be ignored.

//+------------------------------------------------------------------+
//|                                                        LMRv2.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include<Trade\Trade.mqh>

//-- Order Info
CTrade trade;
CPositionInfo positionInfo;
input double TakeProfit = 10;
input double StopLoss = 100;

//-- Order Management
input double TrailingStop = 10;
bool AutoLot = true;
double MaxLot = 100;
double Lots;
double LotsPer5K = 0.01;
//-- Envelope Signal
bool EnvelopeSELLSignal = 1;
bool EnvelopeBUYSignal = 1;



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//-- Automatic Lot Sizing
double MM_Size()
  {
   double AccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);

   if(AutoLot==false)
      Lots=MaxLot;
   if(AutoLot==true && Lots < MaxLot)
      Lots = ((AccountBalance / 5000)*LotsPer5K);
   if(Lots < 0.01)
      Lots=0.01;
   return(Lots);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {

//-- Opened Positions
   int TotalOpenOrders = PositionsTotal();
   double Bid;
   double Ask;
   double Spread;
   Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   Spread = Bid-Ask;
//-- Order SL/TP Calc
   double BUYTakeProfitLVL = Bid+TakeProfit*Point()-Spread;    //correct
   double BUYStopLossLVL = Bid-StopLoss*Point()-Spread;        //correct
   double SELLTakeProfitLVL = Ask-TakeProfit*Point()+Spread;   //correct
   double SELLStopLossLVL = Ask+StopLoss*Point()+Spread;       //correct
//-- Price Information Array
   MqlRates PriceInformation[];
   ArraySetAsSeries(PriceInformation,true);
   int PriceData = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInformation);
//-- Envelope Array
   double UpperBandArray[];
   double LowerBandArray[];
   ArraySetAsSeries(UpperBandArray,true);
   ArraySetAsSeries(LowerBandArray,true);
//-- Envelope Indicator
   int Envelopes = iEnvelopes(Symbol(),PERIOD_M5,3,0,MODE_SMA,PRICE_CLOSE,0.07);
   CopyBuffer(Envelopes,0,0,3,UpperBandArray);
   CopyBuffer(Envelopes,1,0,3,LowerBandArray);
   double UpperBandValue=NormalizeDouble(UpperBandArray[0],6);
   double LowerBandValue=NormalizeDouble(LowerBandArray[0],6);
//-- Envelope Signal
   if(PriceInformation[0].high > UpperBandValue)
      Comment("SELL SIGNAL");
   EnvelopeSELLSignal = true; // sell
   if(PriceInformation[0].low < LowerBandValue)
      Comment("BUY SIGNAL");
   EnvelopeBUYSignal = true; // buy
   if((PriceInformation[0].high < UpperBandValue) &&
      (PriceInformation[0].low > LowerBandValue))
      Comment("UpperBandValue: ", UpperBandValue, "\n",
              "LowerBandValue: ", LowerBandValue, "\n");




   if(TotalOpenOrders<1)
     {
      if(EnvelopeSELLSignal == true)
         trade.Sell(MM_Size(),NULL,Bid,SELLStopLossLVL,SELLTakeProfitLVL,NULL);
      if(EnvelopeBUYSignal == true)
         trade.Buy(MM_Size(),NULL,Ask,BUYStopLossLVL,BUYTakeProfitLVL,NULL);
     }








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






//trailing stop
//place pending order that moves with price. ~10 pips distance
 
And before it worked? Does it show any error messages in Journal?
 
Tobias Johannes Zimmer #:
And before it worked? Does it show any error messages in Journal?

Thanks for the response. It does not show any messages in the Journal.

 
  double BUYTakeProfitLVL = Bid+TakeProfit*Point()-Spread;    //correct
   double BUYStopLossLVL = Bid-StopLoss*Point()-Spread;        //correct
   double SELLTakeProfitLVL = Ask-TakeProfit*Point()+Spread;   //correct
   double SELLStopLossLVL = Ask+StopLoss*Point()+Spread;       //correct
Incorrect.

You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

  1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

  2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
              MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

  3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)

    Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
    My GBPJPY shows average spread = 26 points, average maximum spread = 134.
    My EURCHF shows average spread = 18 points, average maximum spread = 106.
    (your broker will be similar).
              Is it reasonable to have such a huge spreads (20 pip spreads) in EURCHF? - General - MQL5 programming forum (2022)

 
William Roeder #:
Incorrect.

You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

  1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

  2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
              MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

  3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)

    Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
    My GBPJPY shows average spread = 26 points, average maximum spread = 134.
    My EURCHF shows average spread = 18 points, average maximum spread = 106.
    (your broker will be similar).
              Is it reasonable to have such a huge spreads (20 pip spreads) in EURCHF? - General - MQL5 programming forum (2022)

Thank you for the response.
Points 1 - 3, that did clear things up. got it mixed up. thanks a lot. 

   double BUYTakeProfitLVL = Ask+TakeProfit*Point();    
   double BUYStopLossLVL = Ask-StopLoss*Point();        
   double SELLTakeProfitLVL = Bid-TakeProfit*Point();   
   double SELLStopLossLVL = Bid+StopLoss*Point();

       
/* -----------changed below to above, works wonderfully :)
   double BUYTakeProfitLVL = Bid+TakeProfit*Point()-Spread;    //correct
   double BUYStopLossLVL = Bid-StopLoss*Point()-Spread;        //correct
   double SELLTakeProfitLVL = Ask-TakeProfit*Point()+Spread;   //correct
   double SELLStopLossLVL = Ask+StopLoss*Point()+Spread;       //correct
*/

Now it does open 2 positions when initially running, a SELL and a BUY. Correct TP and SL. But those positions are not what I thought it would do. It doesn't open a new position when receiving a signal. Might there be something wrong with reading the signal value?

 

I'll try to explain what im trying to accoplish. Im trying to make a scalper that uses the Bollinger Bands and Envelope indicators to scalp extremes. It looks as follows:
www tradingview com/x/pOXqoMoq/

I filled in the background of those indicators so that it is easier to see what i mean. I want the expert to open a short pending order, that moves up with the price, if price breaks the blue border. So that once price comes back down after breaking it to the up side, it scalps a few pips using a trailingstop and a small stoploss. I just cant wrap my head around how to code it, as im a trader. But im really eager to learn how to code. So if someone could please help me with this its much appreciated. I got the following code, but i got some hickups on how to write it correctly. I could really use some help. Thanks.



//+------------------------------------------------------------------+
//|                                                        LMRv2.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include<Trade\Trade.mqh>

//-- Order Info
CTrade trade;
CPositionInfo positionInfo;
input double TakeProfit = 10;
input double StopLoss = 100;
//-- Order Management
input double TrailingStop = 10;
bool AutoLot = true;
double MaxLot = 100;
double Lots;
double LotsPer5K = 0.1;

//--Indi Input Param
input int BBperiod = 5;
input int BBdev = 2;
input int ENVperiod = 3;
input double ENVpercent = 0.07;
input int MAperiod = 10;



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//-- Automatic Lot Sizing
double MM_Size()
  {
   double AccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);

   if(AutoLot==false)
      Lots=MaxLot;
   if(AutoLot==true && Lots < MaxLot)
      Lots = ((AccountBalance / 5000)*LotsPer5K);
   if(Lots < 0.01)
      Lots=0.01;
   return(Lots);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//-- Opened Positions
   int TotalOpenOrders = PositionsTotal();
   double Bid;
   double Ask;
   double Spread;
   Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   Spread = (Bid-Ask);
//-- Order SL/TP Calc
   double BUYTakeProfitLVL = Ask+TakeProfit*Point();
   double BUYStopLossLVL = Ask-StopLoss*Point();
   double SELLTakeProfitLVL = Bid-TakeProfit*Point();
   double SELLStopLossLVL = Bid+StopLoss*Point();
//-- Price Information Array
   MqlRates PriceInformation[];
   ArraySetAsSeries(PriceInformation,true);
   int PriceData = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInformation);

//ENVELOPE SIGNAL
//-- Envelope Array
   double ENVUpperBandArray[];
   double ENVLowerBandArray[];
   ArraySetAsSeries(ENVUpperBandArray,true);
   ArraySetAsSeries(ENVLowerBandArray,true);
//-- Envelope Indicator
   int Envelopes = iEnvelopes(Symbol(),PERIOD_M5,ENVperiod,0,MODE_SMA,PRICE_CLOSE,ENVpercent);
   CopyBuffer(Envelopes,0,0,3,ENVUpperBandArray);
   CopyBuffer(Envelopes,1,0,3,ENVLowerBandArray);
   double ENVUpperBandValue=NormalizeDouble(ENVUpperBandArray[0],6);
   double ENVLowerBandValue=NormalizeDouble(ENVLowerBandArray[0],6);
//-- Envelope Signal
   bool EnvelopePriceAtUpperBand = false;
   bool EnvelopePriceAtLowerBand = false;
   if(PriceInformation[0].high > ENVUpperBandValue && PriceInformation[0].low > ENVLowerBandValue)
      EnvelopePriceAtUpperBand = true; // sell
      Comment("SELL SIGNAL");
   if(PriceInformation[0].low < ENVLowerBandValue && PriceInformation[0].high < ENVLowerBandValue)
      EnvelopePriceAtLowerBand = true; // buy
      Comment("BUY SIGNAL");
   if((PriceInformation[0].high < ENVUpperBandValue) &&
      (PriceInformation[0].low > ENVLowerBandValue))
      EnvelopePriceAtUpperBand = false;
   EnvelopePriceAtLowerBand = false;
   Comment("UpperBandValue: ", ENVUpperBandValue, "\n",
              "LowerBandValue: ", ENVLowerBandValue, "\n");

//BOLLINGERBANDS
//-- Bollinger Bands Array
   double BBUpperBandArray[];
   double BBLowerBandArray[];
   ArraySetAsSeries(BBUpperBandArray,true);
   ArraySetAsSeries(BBLowerBandArray,true);
//-- Bollinger Bands Indi
   int BollingerBands = iBands(Symbol(),PERIOD_M5,BBperiod,0,BBdev,PRICE_CLOSE);
   CopyBuffer(BollingerBands,1,0,3,BBUpperBandArray);
   CopyBuffer(BollingerBands,2,0,3,BBLowerBandArray);
   double BBUpperBandValue = NormalizeDouble(BBUpperBandArray[0],6);
   double BBLowerBandValue = NormalizeDouble(BBLowerBandArray[0],6);
//-- Bollinger Bands Signal
   bool BBPriceAtUpperBand = false;
   bool BBPriceAtLowerBand = false;
   if(PriceInformation[0].high > BBUpperBandValue)
      BBPriceAtUpperBand = true; // sell
   if(PriceInformation[0].low < BBLowerBandValue)
      EnvelopePriceAtLowerBand = true; // buy
   if((PriceInformation[0].high < BBUpperBandValue) &&
      (PriceInformation[0].low > BBLowerBandValue))
      BBPriceAtUpperBand = false;
   BBPriceAtLowerBand = false;

// MOVING AVERAGE SIGNAL
//-- Moving Average Array
   double MovingAverageArray[];
   ArraySetAsSeries(MovingAverageArray, true);
//-- Moving Average Indi
   int CurrMovingAverage = iMA(Symbol(),PERIOD_M5,MAperiod,0,MODE_SMA,PRICE_CLOSE);
   CopyBuffer(CurrMovingAverage,0,0,3,MovingAverageArray);
   double CurrMovingAverageValue = MovingAverageArray[0];
   bool PriceAboveMA = false;
   bool PriceBelowMA = false;
//-- Moving Average Signal
   if(PriceInformation[0].high > CurrMovingAverageValue)
      PriceAboveMA = true; //sell
   if(PriceInformation[0].low < CurrMovingAverageValue)
      PriceBelowMA = true; //buy
   if((PriceInformation[0].high < CurrMovingAverageValue) &&
      (PriceInformation[0].low > CurrMovingAverageValue))
      PriceAboveMA = false;
   PriceBelowMA = false;




   if(TotalOpenOrders >= 1)
      for(int i=PositionsTotal()-1; i>=0; i--)
        {
         ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
         ulong CurrOrderType = PositionGetInteger(POSITION_TYPE);
         
         double CurrSL = PositionGetDouble(POSITION_SL);
         double CurrBUYPrice = Ask;
         double OrderOpenPrice = 0;
         
         //modify trailing
         //buy order
         if(CurrOrderType == POSITION_TYPE_BUY && CurrSL > Ask)
         trade.PositionModify(PositionTicket,(CurrSL+TrailingStop*Point()),BUYTakeProfitLVL);
         
         

        }






      if(EnvelopePriceAtUpperBand == true)
         trade.Sell(MM_Size(),NULL,Bid,SELLStopLossLVL,SELLTakeProfitLVL,NULL);
   if(EnvelopePriceAtLowerBand == true)
      trade.Buy(MM_Size(),NULL,Ask,BUYStopLossLVL,BUYTakeProfitLVL,NULL);









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






//trailing stop
//place pending order that moves with price. ~10 pips distance
 
   double BUYTakeProfitLVL = Ask+TakeProfit*Point();    
   double BUYStopLossLVL = Ask-StopLoss*Point();        
   double SELLTakeProfitLVL = Bid-TakeProfit*Point();   
   double SELLStopLossLVL = Bid+StopLoss*Point();
What part of “Using Ask±n, makes your SL shorter and your TP longer, by the spread” was unclear?
 
William Roeder #:
What part of “Using Ask±n, makes your SL shorter and your TP longer, by the spread” was unclear?

thanks for the quick response. what do you mean by ±n? sorry for my ignorance. did you mean it as n = tp/sl? I thought, as the lvls are showing correctly in the back test, it should be good? 

 
I think I understood you correctly @William Roeder. Correct me if I'm wrong, please. Thanks.
 
The last posts were about this: A buy position is opened by a buy deal with ask price, but closed by a sell deal with bid price and vis versa.

So you have to calculate tp/sl from bid price for a buy and from ask price for a sell position.
Otherwise it would be inaccurate by the span of the spread which can be quite considerate.
 
Elmer013:

I've been trying to create an Expert using the envelope indicator. Since adding automatic lot sizing it doesn't place anymore trades. Can someone send me in the general direction? As I'm not a programmer but willing to learn and dedicate a lot of time. It opens a buy and a sell and then it stops trading. please help. the notes at the bottom is what I want to add once im able to make this work so can be ignored.

Not related to your question, but I note that you are calling iBands/iEnvelopes in the OnTick() loop. This is not recommended - You should only call them once from OnInit() then reference the handle in OnTick().

Reason: