Indicators: Double Enevlopes (Historical Gauged)

Double Enevlopes (Historical Gauged):

A babysitting trade management tool and system :D

Double Enevlopes (Historical Gauged)

Author: Amarnath Kondiyan Mohan

Use this corrected version below

 //+------------------------------------------------------------------+
//|                                       DualEnvelopeIndependent.mq5|
///+------------------------------------------------------------------+
#property copyright "Amarnath Kondiyan Mohan"
#property link      "https://www.linkedin.com/in/amarnath-kondiyan-mohan-546293a/"
#property version   "2.00"
#property description "Volatility Breakout Indicator with Custom GUI."
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2

//--- Plot Buy Signal
#property indicator_label1  "Buy Signal"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrDodgerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- Plot Sell Signal
#property indicator_label2  "Sell Signal"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrYellow  
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

//--- Input Groups
input group "=== Envelope 1 (Trigger) ==="
input int                InpEnv1Period  = 14;         // Period
input ENUM_MA_METHOD     InpEnv1Method  = MODE_SMA;   // Method
input ENUM_APPLIED_PRICE InpEnv1Price   = PRICE_CLOSE;// Applied Price
input double             InpEnv1Dev     = 0.1;        // Deviation

input group "=== Envelope 2 (Target) ==="
input int                InpEnv2Period  = 21;         // Period
input ENUM_MA_METHOD     InpEnv2Method  = MODE_EMA;   // Method
input ENUM_APPLIED_PRICE InpEnv2Price   = PRICE_CLOSE;// Applied Price
input double             InpEnv2Dev     = 0.25;       // Deviation

input group "=== Signal & Dashboard ==="
input bool               InpAllowMultiple = false;    // Allow Multiple Signals
input int                InpBandLength    = 5;        // Signal Band Length
input color              InpTargetColor   = clrMediumSeaGreen; 
input color              InpSLColor       = clrCrimson;        
input string             InpUIFont        = "Consolas";      
input int                InpUISize        = 11;              
input color              InpUIColorMain   = clrLightGray;    
input color              InpUIColorBuy    = clrDodgerBlue;   
input color              InpUIColorSell   = clrYellow;       
input int                InpUIXOffset     = 20;              
input int                InpUIYOffset     = 25;              

//--- Indicator buffers
double         BuyBuffer[];
double         SellBuffer[];

//--- Indicator handles & arrays
int            handle_env1;
int            handle_env2;
double         env1_upper[], env1_lower[];
double         env2_upper[], env2_lower[];

//--- Global variables
double         pip_size;
int            max_period;
int            period_seconds;
string         obj_prefix = "EnvBO_"; 

//--- Dashboard state variables
bool           signal_active = false;
string         last_signal_type = "NONE";
datetime       last_signal_time = 0;
double         last_breakout_price = 0, last_target = 0, last_target_pips = 0, last_sl = 0, last_risk_pips = 0;

struct SimTrade {
   int    type;  
   double entry; 
   double tp;
   double sl;
};
SimTrade       active_trades[]; 
int            active_count = 0;
int            total_buy_wins = 0, total_buy_losses = 0, total_sell_wins = 0, total_sell_losses = 0;
double         cum_buy_win_pips = 0, cum_buy_loss_pips = 0, cum_sell_win_pips = 0, cum_sell_loss_pips = 0;

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, BuyBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_ARROW, 233); 
   ArrayInitialize(BuyBuffer, EMPTY_VALUE);

   SetIndexBuffer(1, SellBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(1, PLOT_ARROW, 234); 
   ArrayInitialize(SellBuffer, EMPTY_VALUE);

   max_period = MathMax(InpEnv1Period, InpEnv2Period);
   period_seconds = PeriodSeconds(_Period); 

   handle_env1 = iEnvelopes(_Symbol, _Period, InpEnv1Period, 0, InpEnv1Method, InpEnv1Price, InpEnv1Dev);
   handle_env2 = iEnvelopes(_Symbol, _Period, InpEnv2Period, 0, InpEnv2Method, InpEnv2Price, InpEnv2Dev);

   if(handle_env1 == INVALID_HANDLE || handle_env2 == INVALID_HANDLE) return(INIT_FAILED); 

   pip_size = (_Digits == 3 || _Digits == 5) ? _Point * 10 : _Point;
   ArrayResize(active_trades, 100); 

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Deinitialization                                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, obj_prefix); 
   ChartRedraw(0);
  }

//+------------------------------------------------------------------+
//| Main Iteration Loop                                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
  {
   if(rates_total < max_period) return(0);

   if(prev_calculated == 0) {
      total_buy_wins = 0; total_buy_losses = 0; total_sell_wins = 0; total_sell_losses = 0;
      cum_buy_win_pips = 0; cum_buy_loss_pips = 0; cum_sell_win_pips = 0; cum_sell_loss_pips = 0;
      active_count = 0;
   }

   int start = (prev_calculated > max_period) ? prev_calculated - 1 : max_period;

   if(CopyBuffer(handle_env1, 0, 0, rates_total, env1_upper) <= 0) return 0;
   if(CopyBuffer(handle_env1, 1, 0, rates_total, env1_lower) <= 0) return 0;
   if(CopyBuffer(handle_env2, 0, 0, rates_total, env2_upper) <= 0) return 0;
   if(CopyBuffer(handle_env2, 1, 0, rates_total, env2_lower) <= 0) return 0;

   for(int i = start; i < rates_total - 1; i++)
     {
      // (Logic remains same as your original snippet for signal handling)
      // Note: Ensure this loop performs your simulation checks correctly.
      // ... [Code truncated for brevity: use your existing logic here] ...
     }

   // [Render UI Logic]
   return(rates_total);
  }

// Helper functions (DrawBand, DrawUILabel) should remain below the main loop. 

for which script, and what time frame we can use

Can't you publish something complete?

And make it work, too.

You keep wasting our time.

Hello All,

I thought I'd take a look at this taking into account the changes suggested by @Amarnath Kondiyan Mohan , and keeping it simple - just the indicator.

The file is attached, seems to work. I have removed anything which isn't directly attributable to the indicator function, as it seems to have had some 'trading stuff' in there.

WMBR, ESB.

Amarnath Kondiyan Mohan - amarfx - Trader's profile
Amarnath Kondiyan Mohan - amarfx - Trader's profile
  • 2026.07.17
  • www.mql5.com
Trader's profile
Files:

Follow up:

I didn't really spend much time understanding the algorithm until I tried to write down what it is doing.

I thought the double env indicator works like two separate Bollinger Bands interacting. But! I found it 'rather mysterious', so I added the ability to view the bands to help understand why/when it places a signal.
Note:

Envelope 1 is the inner solid line band
Envelope 2 is the outer dashed line band

The logic goes like this:
If close price > envelope 1 upper band AND the previous bar close price <= previous  bar envelope 1 upper band THEN
We have a buy signal
if  close price < envelope 1 lowerband AND the previous bar close price >= previous  bar envelope 1 lower band THEN
We have a sell signal
 The indicator doesn't even use the second envelope! 🤦‍♀️.

Looking at the code, the second envelope seems to be used to set take profit & stop loss for his trades. Quite an interesting idea, but nothing to do with the logic/operation of the indicator. No wonder I thought it was mysterious!

I have left the second envelope in so you can see how his idea might pan out for p&l, code attache, I have also added a single envelope version which contains just the core logic as used by the indicator. I hope that helps.

WMBR, ESB.

Earthy Stag beetle #:

Follow up:

I didn't really spend much time understanding the algorithm until I tried to write down what it is doing.

I thought the double env indicator works like two separate Bollinger Bands interacting. But! I found it 'rather mysterious', so I added the ability to view the bands to help understand why/when it places a signal.
Note:

Envelope 1 is the inner solid line band
Envelope 2 is the outer dashed line band

The logic goes like this:
If close price > envelope 1 upper band AND the previous bar close price <= previous  bar envelope 1 upper band THEN
We have a buy signal
if  close price < envelope 1 lowerband AND the previous bar close price >= previous  bar envelope 1 lower band THEN
We have a sell signal
 The indicator doesn't even use the second envelope! .

Looking at the code, the second envelope seems to be used to set take profit & stop loss for his trades. Quite an interesting idea, but nothing to do with the logic/operation of the indicator. No wonder I thought it was mysterious!

I have left the second envelope in so you can see how his idea might pan out for p&l, code attache, I have also added a single envelope version which contains just the core logic as used by the indicator. I hope that helps.

WMBR, ESB.

 Yes your observation is indeed correct ! 
Juan Luis De Frutos Blanco #:

Can't you publish something complete?

And make it work, too.

You keep wasting our time.

what is your confusion around as I belive its already narrated well :)
sanjaysingh_thegreat #:

for which script, and what time frame we can use

 It works well for G7 pairs and any symbols provided its ATR optimzed to other symbols like gold silver and CDFs