Author: Shimodax & RickyD
RD-Combo

The RD.Combo script is a comprehensive technical analysis tool designed to provide traders with a unified "all-in-one" signal on the MetaTrader platform. Rather than forcing a user to look at five different indicators separately, this script aggregates multiple market data points into a single visual representation to identify high-probability trading entries and exits.

Core Logic Overview

The script functions by scanning several different types of market data simultaneously—including moving averages, momentum oscillators, and trend strength metrics. It assigns a "score" to the current market price based on how many of these indicators are agreeing on the direction of the price movement.

The Components of the Analysis

To determine the final signal, the script evaluates five distinct technical perspectives:

  1. Moving Average Trends: It compares short-term and long-term averages (specifically 5, 20, 100, and 200 periods) to see if the immediate price trend aligns with the broader market direction.
  2. Momentum (CCI): It uses the Commodity Channel Index to determine if the price is overextended or moving with strength relative to its average.
  3. Relative Volatility Index (RVI): This is used to track the relationship between the main indicator and its signal line to identify shifts in trend momentum.
  4. Trend Strength (ADX): It analyzes the Average Directional Index to ensure that a move has enough "power" or strength behind it before confirming a signal. It specifically looks for moves exceeding a certain intensity threshold.
  5. Forecast Oscillators: A unique component of this script involves a mathematical projection. It uses historical price data to calculate a "forecast" oscillator, helping to smooth out noise and identify potential future price movements.

How Signals Are Generated

The logic works on a cumulative scoring system:

  • Bullish (Long) Signal: If the majority of the components above (Moving Averages, CCI, Forecasts, RVI, and ADX) all point upward and exceed a specific "Color Threshold," the script generates a Bullish signal.
  • Bearish (Short) Signal: Conversely, if the indicators collectively point downward and surpass the threshold, a Bearish signal is triggered.
  • Neutral State: If the indicators are conflicted (some pointing up, some pointing down), the script remains in a neutral state, indicating that there is no clear consensus on market direction.

Trade Management & Alerts

The script includes built-in logic to manage the lifecycle of a trade:

  • Entry/Exit Logic: It tracks the "state" of a trade. If a strong signal appears while the market was previously neutral, it considers this an entry point. If a signal disappears or reverses while a trade is active, it identifies this as a potential exit point.
  • Notifications: Users can opt-in to receive real-time pop-up alerts on their screen for both entries and exits, allowing for "hands-off" monitoring of the charts.
  • Visual Feedback: The script renders these signals as histograms in a separate window, making it easy to see the strength of the trend at a glance through different colors (e.g., Green/Gold for bullish, Orange/Red for bearish).
10 Views
0 Downloads
0 Favorites
RD-Combo

//+------------------------------------------------------------------+
//|                                                     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 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)
         rvival= 1;
      else
      if (rvimain<0 && rvisignal<0 && rvimain<rvisignal)
         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