RD-Combo_v5

Author: Shimodax & RickyD
RD-Combo_v5

This script functions as a comprehensive multi-factor trading indicator designed to identify high-probability market trends by synthesizing several different technical analysis methods into a single visual signal. Instead of relying on just one type of data, it looks at price momentum, trend direction, and volume/strength indicators simultaneously to decide whether the market is leaning bullish, bearish, or staying neutral.

Core Logic and Methodology

The script operates by evaluating five distinct financial "votes" at every point in time:

  1. Moving Average Trends: It compares short-term price averages against longer-term averages to determine the primary direction of the market.
  2. Momentum (CCI): It uses a Commodity Channel Index to measure where the current price is relative to its average range, helping to identify overbought or oversold conditions.
  3. Predictive Forecasting: The script includes a specialized mathematical engine that calculates "forecast oscillators." This part of the logic attempts to project potential price paths based on historical data to anticipate upcoming movements.
  4. Relative Volatility (RVI): It analyzes the relationship between price movement and volatility to ensure that signals are backed by enough market activity.
  5. Trend Strength (ADX): It utilizes the Average Directional Index to filter out "choppy" or sideways markets, ensuring that the indicator only provides signals when a strong, clear trend is actually present.

How the Signals Are Generated

The script acts like a committee. Each of the five factors mentioned above produces a numerical value. The logic then performs the following:

  • Summation: It adds all these values together to create a "Combined Score."
  • Threshold Filtering: A user-defined threshold (the "Color Threshold") determines how strong the agreement must be. If the combined score is high enough in one direction, it triggers a Long (Buy) signal. If it is significantly low in the other direction, it triggers a Short (Sell) signal.
  • Neutral Zone: If the score isn't strong enough to meet the threshold either way, the script classifies the market as "Neutral," preventing the user from entering a trade during indecisive price action.

Exit Logic and Safety Features

Beyond just telling you when to enter a trade, the script contains logic to manage active positions:

  • Dynamic Exits: It monitors the Relative Volatility (RVI) specifically to identify when a trend is losing steam or reversing, providing a mechanism to exit a position before the trend completely collapses.
  • Alert System: The script can be configured to send real-time notifications (Alerts) to your platform the moment a new entry signal appears or an exit condition is met.
  • Data Logging: For advanced users, the script includes a "Debug" mode that records all the raw data points (Moving Averages, CCI values, etc.) into a log, allowing for deep analysis of why a specific signal was generated at a specific time.

Visual Presentation

On your trading chart, this logic is translated into a separate window where:

  • Histograms show the strength and direction of the trend.
  • Color Coding distinguishes between Bullish (Long), Bearish (Short), and Neutral states.
  • Lines provide a visual representation of the underlying signal state, helping you see the "flow" of market sentiment rather than just isolated points.
Indicators Used
Moving average indicatorCommodity channel indexRelative Vigor indexMovement directional index
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
14 Views
0 Downloads
0 Favorites
RD-Combo_v5
//+------------------------------------------------------------------+
//|                                                     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