RD-Combo_v1

Download script
Author: Shimodax & RickyD
RD-Combo_v1

This indicator is a comprehensive technical analysis tool designed to synthesize multiple market data points into a single visual signal. Rather than relying on a single metric, it combines momentum, trend, and predictive smoothing to determine the overall "strength" of the market direction.

Core Logic and Methodology

The script operates by evaluating five distinct financial metrics simultaneously. For every new price movement, it calculates a score for each of these categories:

  • Trend Analysis (Moving Averages): It compares short-term moving averages against long-term ones to identify the fundamental direction of the price.
  • Momentum (CCI): It uses the Commodity Channel Index to determine if the current price is deviating significantly from its average, helping to spot overbought or oversold conditions.
  • Predictive Forecasting: A unique component of this script involves a custom forecasting calculation. It attempts to project potential price movement cycles based on historical regressions, providing a "look-ahead" sentiment.
  • Relative Volatility (RVI): This measures the relationship between the main price movement and its signal line to identify shifts in volatility and trend stability.
  • Trend Strength (ADX): The Average Directional Index is used specifically to confirm that a trend has enough power to be tradable, filtering out "choppy" or sideways markets.

Signal Generation

The script aggregates these five metrics into a cumulative score:

  1. The Scoring System: Each metric contributes either a positive value (bullish), a negative value (bearish), or neutral. These are added together to create a total "Combo" value.
  2. Threshold Filtering: The indicator does not trigger a signal based on minor fluctuations. It uses a user-defined "Color Threshold." Only when the combined score exceeds this threshold (indicating high agreement across all five metrics) does the script provide a clear signal.
  3. Visual Output:
    • Long Signals (Bullish): Represented visually as green histograms when the cumulative score is strongly positive.
    • Short Signals (Bearish): Represented visually as orange-red histograms when the cumulative score is strongly negative.
    • Neutral Zone: When the metrics are in conflict or too weak to form a trend, the indicator remains neutral.

Automated Alerts and Exit Logic

Beyond simple visual cues, the script includes an intelligent state machine to handle trade lifecycles:

  • Entry Alerts: The script can be configured to send a notification the moment a new signal appears (shifting from neutral to a strong bull/bear state).
  • Dynamic Exits: The logic includes specific "exit" parameters. For example, even if a trend is technically still active, the script may trigger an exit signal if the Relative Volatility (RVI) indicates a significant breakdown in momentum or a reversal in the price flow.

In summary, this tool acts as a "consensus engine," ensuring that a trade signal is only displayed when multiple independent technical indicators agree on the market's direction.

Indicators Used
Moving average indicatorCommodity channel indexRelative Vigor indexMovement directional index
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
15 Views
0 Downloads
0 Favorites
RD-Combo_v1

//+------------------------------------------------------------------+
//|                                                     RD.COmbo.mq4 |
//|                                                         Shimodax |
//|                                                                  |
//+------------------------------------------------------------------+

#property copyright "Shimodax & RickyD"
#property  link     "http://www.strategybuilderfx.com/forums/showthread.php?t=15187"


#property indicator_separate_window

#property indicator_buffers 4
#property indicator_color1 Gray
#property indicator_color2 OrangeRed
#property indicator_color3 LawnGreen
#property indicator_color4 Gold

#property indicator_maximum 5
#property indicator_minimum -5

#property indicator_level1 4
#property indicator_level2 -4

//---- buffers
extern bool DoAlertForEntry= false;
extern bool DoAlertForExit= false;
extern int HistorySize= 1000;
extern int ColorThreshold= 5;
extern double NoiseFilterRVI= 0.03;   // delay exit signal
extern bool DebugLogger= false;
extern bool DebugLoggerData= false;

double LongSignalBuffer[],
       ShortSignalBuffer[],
       NeutralBuffer[],
       SignalBuffer[];

double Osc[], 
       Osct3[];
       

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID,2);
   SetIndexBuffer(0,NeutralBuffer);
   SetIndexEmptyValue(0, 0.0);

   SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,2);
   SetIndexBuffer(1,ShortSignalBuffer);
   SetIndexEmptyValue(1, 0.0);

   SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID,2);
   SetIndexBuffer(2,LongSignalBuffer);
   SetIndexEmptyValue(2, 0.0);

   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,SignalBuffer);
   // SetIndexEmptyValue(3, 0.0);

   IndicatorShortName("RD-Combo()= ");

   return(0);
}



int start()
{
   static bool didentryalert= false, didexitalert= false;
   int counted_bars= IndicatorCounted(),
         lastbar, result;

   if (Bars<=100) 
      return(0);
      
   if (counted_bars>0)
      counted_bars--;
      
   lastbar= Bars - counted_bars;
   lastbar= MathMin(HistorySize, lastbar);

   // 
   // precalc forecast oscillater array
   //   
   ArrayResize(Osc, Bars);
   ArrayResize(Osct3, Bars);
   ForecastOsc(0, Bars, Osc, Osct3, 15, 3, 0.7);

   // 
   // check for signals
   //   
   Combo(0, lastbar, LongSignalBuffer, ShortSignalBuffer, NeutralBuffer, SignalBuffer, ColorThreshold);
        
        
        
   //
   // do alerting
   //             
   if (DoAlertForEntry>0 && SignalBuffer[0]!=0 && SignalBuffer[1]==0) {
      if (!didentryalert) {
         Alert("RD signals trade entry on ", Symbol(),"/",Period());
         didentryalert= true;
      }
   }
   else {
      didentryalert= false;
   }  

   if (DoAlertForExit>0 && SignalBuffer[0]==0 && SignalBuffer[1]!=0) {
      if (!didexitalert) {
         Alert("RD signals trade exit on ", Symbol(),"/",Period());
         didexitalert= true;
      }
   }
   else {
      didexitalert= false;
   }

   return (0);
}




//+------------------------------------------------------------------+
//| Combo Indicator (All-In-One signal)                              |
//+------------------------------------------------------------------+
int Combo(int offset, int lastbar, double &longsignalbuf[], double &shortsignalbuf[], double &neutralbuffer[], double &signalbuffer[], int colthreshold)
{
   
   int  val, 
        lookupidx= 0,
        signalstate= 0;

   double 
         adxmain,
         adxplus,
         adxminus,
         adxmain2,
         adxplus2,
         adxminus2,
         cci, 
         rvimain,
         rvisignal, 
         ma5, 
         ma20, 
         ma100, 
         ma200,
         fcblue, 
         fcred;
         

   if (lastbar>Bars)
      lastbar= Bars;
  
       
   for (int i= lastbar+5; i>=offset; i--) {
  
      lookupidx= i;

      ma5= iMA(NULL, 0, 5, 0, MODE_LWMA, PRICE_CLOSE, lookupidx);
      ma20= iMA(NULL, 0, 20, 0, MODE_LWMA, PRICE_CLOSE, lookupidx);
      ma100= iMA(NULL, 0, 100, 0, MODE_LWMA, PRICE_CLOSE, lookupidx);
      ma200= iMA(NULL, 0, 200, 0, MODE_LWMA, PRICE_CLOSE, lookupidx);
   
      cci= iCCI(NULL, 0, 5, PRICE_CLOSE, lookupidx);
   
      rvimain= iRVI(NULL, 0, 1, MODE_MAIN, lookupidx);   
      rvisignal= iRVI(NULL, 0, 1, MODE_SIGNAL, lookupidx); 
   
      adxmain= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MAIN, lookupidx);
      adxplus= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_PLUSDI, lookupidx);
      adxminus= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MINUSDI, lookupidx);

      adxmain2= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MAIN, lookupidx+1);
      adxplus2= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_PLUSDI, lookupidx+1);
      adxminus2= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MINUSDI, lookupidx+1);
   
      fcblue= Osc[lookupidx];   // forecast
      fcred= Osct3[lookupidx];  // forecast

      /*     
         fcblue= iCustom(NULL, 0, "RD-ForecastOsc", 0, lookupidx);
         fcred= iCustom(NULL, 0, "RD-ForecastOsc", 1, lookupidx);
   
      double
         fc2blue= iCustom(NULL, 0, "RD-ForecastOsc", 0, lookupidx);
         fc2red= iCustom(NULL, 0, "RD-ForecastOsc", 1, lookupidx);
      
      if (fc2blue!=fcblue) 
         Print("#", lookupidx, "Blue ", fc2blue, " ", fcblue);
      
      if (fc2red!=fcred) 
         Print("#", lookupidx, "Red ", fc2red, " ", fcred);
      */
      
      
      //
      // calc entry signal
      //

      int maval= 0,
          ccival= 0,
          rvival= 0,
          adxval= 0,
          fcval= 0;
  
  
      if (ma5>ma20)
         maval= 1;
      else
         maval= -1;
         
         
      if (cci>0)
         ccival= 1;
      else
      if (cci<0)
         ccival= -1;
      else
         ccival= 0;

         
      if (fcblue>0 && fcred>0 && fcblue>fcred) 
         fcval= 1;
      else
      if (fcblue<0 && fcred<0 && fcblue<fcred) 
         fcval= -1;
      else
         fcval= 0;
         

      if (rvimain>0 && rvisignal>0 && rvimain-rvisignal>0)
         rvival= 1;
      else
      if (rvimain<0 && rvisignal<0 && rvimain-rvisignal<0)
         rvival= -1;
      else
         rvival= 0;

      
      if (adxmain>adxmain2 && adxplus>adxplus2 && adxmain>20 && adxplus>20)
         adxval= 1;
      else
      if (adxmain>adxmain2 && adxminus>adxminus2 && adxmain>20 && adxminus>20)
         adxval= -1;
      else
         adxval= 0;
         
              
      val= maval + ccival + fcval + rvival + adxval;
      
      
      //      
      // exit signal      
      //
      if (signalstate!=0) {

         if (signalstate==1 && (rvimain<0 || rvisignal-rvimain>0.2)) {
             signalstate= 0;
         }

         if (signalstate==-1 && (rvimain>0 || rvimain-rvisignal>0.2)) {
             signalstate= 0;
         }

         if (DebugLogger)
            Print(TimeToStr(Time[i]), " #", i, " rvimain= ", rvimain, ", rvisignal= ", rvisignal, ", diff= ", DoubleToStr(rvimain-rvisignal,2), 
                                               " => signalstate", signalstate);
      }

      
      if (i<=lastbar) {    // ignore the first few loops that were only used to catch previous signal state
      
         if (DebugLogger || DebugLoggerData){
            if (DebugLoggerData) {
               Print(TimeToStr(Time[i]), " # --------------------------------------------------------------------------");
               Print(TimeToStr(Time[i]), " #", i, " MA 5/20/100/200", ma5, "/", ma20, "/", ma100, "/", ma200);
               Print(TimeToStr(Time[i]), " #", i, " CCI ", cci, ", RVI ", rvimain, "/", rvisignal);
               Print(TimeToStr(Time[i]), " #", i, " ADX(now)  main/+DI/-DI ", adxmain, "/", adxplus, "/", adxminus);
               Print(TimeToStr(Time[i]), " #", i, " ADX(prev) main/+DI/-DI ", adxmain2, "/", adxplus2, "/", adxminus2);
               Print(TimeToStr(Time[i]), " #", i, " Forecast blue/red ", fcblue, "/", fcred);
            }
         
            if (DebugLogger || DebugLoggerData)
               Print(TimeToStr(Time[i]), " #", i, " MAtrend(", maval, ") + CCI(", ccival, ") + FC(", fcval, 
                                                  ") + RVItrend( ", rvival, ") + ADXtrend(", adxval, ") => ", val, " # trade state =", signalstate);
         }

 
         longsignalbuf[i]= 0;
         shortsignalbuf[i]= 0;
         neutralbuffer[i]= 0;

         if (val>=colthreshold) {
            longsignalbuf[i]= val;
            signalstate= 1;
         }
         else
         if (val<=-colthreshold) {
            shortsignalbuf[i]= val;
            signalstate= -1;
         }
         else
            neutralbuffer[i]= val;
            
         signalbuffer[i]= 2*signalstate;
      }
   }

   return (signalstate);
}




//+------------------------------------------------------------------+
//| Calc forecast buffers  from lastbar down to offset               |
//+------------------------------------------------------------------+
void ForecastOsc(int offset, int lastbar, double &osc[], double &osct3[], int regress, int t3, double b)
{

   int shift, length;
   double b2=b*b,
            b3=b2*b, 
            c1=-b3,
            c2=(3*(b2+b3)),
            c3=-3*(2*b2+b+b3),
            c4=(1+3*b+b3+3*b2), 
            n = 1 + 0.5*(t3-1),
            w1 = 2 / (n + 1),
            w2 = 1 - w1,
            wt,forecastosc,t3_fosc,sum,
            e1,e2,e3,e4,e5,e6,tmp,tmp2;
          
   lastbar= MathMin(Bars-31-regress, lastbar);   
 
   for (shift= lastbar+30; shift>=offset; shift--)   {

      length= regress; 
      sum = 0; 
      for (int i = length; i>0; i--) {
         tmp = length+1;
         tmp = tmp/3;
         tmp2 = i;
         tmp = tmp2 - tmp;
         sum = sum + tmp*Close[shift+length-i]; 
      }
      tmp = length;

      wt = sum*6/(tmp*(tmp+1)); 

      forecastosc= (Close[shift]-wt)/wt*100; 

      e1 = w1*forecastosc + w2*e1; 
      e2 = w1*e1 + w2*e2; 
      e3 = w1*e2 + w2*e3; 
      e4 = w1*e3 + w2*e4; 
      e5 = w1*e4 + w2*e5; 
      e6 = w1*e5 + w2*e6; 

      t3_fosc = c1*e6 + c2*e5 + c3*e4 + c4*e3; 

      if (shift<=lastbar) {   // don't put swing in cycle into the signal buffers
         osc[shift] = forecastosc;
         osct3[shift] = t3_fosc;
      }
      
    }
  
   return(0);
}


Comments