StochCross_CCI_v2

Download script
Author: Melvin Tan
StochCross_CCI_v2

This technical indicator is designed to identify high-probability trading entries by combining momentum, trend direction, and market volatility. Rather than relying on a single signal, it uses a multi-layered filtering system to ensure that buy and sell signals are only generated when several market conditions align simultaneously.

How the Logic Works

The script monitors four distinct types of market data to validate a trade signal:

1. Momentum Crossover (Stochastic Oscillator) The primary trigger is based on the Stochastic Oscillator. The tool looks for a "cross" between two specific internal lines of this oscillator. A bullish crossover occurs when the main line moves above the signal line, while a bearish crossover occurs when it moves below.

2. Trend Filtering (CCI - Commodity Channel Index) To avoid trading against the dominant market direction, the script uses the Commodity Channel Index (CCI). It evaluates two different timeframes of this indicator:

  • Long-Term Trend: It checks the broader market trend to ensure the overall "big picture" is favorable.
  • Entry Trend: It confirms that the immediate short-term momentum is moving in the same direction as the intended trade.

3. Volatility Confirmation (Bollinger Squeeze) One of the most important filters in this script is the volatility check. By calculating the relationship between standard deviation and the average range of price movement, the tool identifies "Squeezes." It effectively looks for periods where market activity is high enough to sustain a move; it filters out "choppy" or flat markets where signals are often unreliable (false positives).

4. Signal Execution & Alerts When all conditions—Momentum, Long-Term Trend, Short-Term Trend, and Volatility—align perfectly, the script generates a visual signal on your chart:

  • Buy Signals: Marked with an upward arrow placed below the price candle.
  • Sell Signals: Marked with a downward arrow placed above the price candle.

User Experience Features

  • Real-Time Alerts: The script can be configured to send instant notifications (pop-ups) when a signal is triggered, providing the current Ask and Bid prices along with the specific timestamp for the trade.
  • Dynamic Visuals: Signals are placed at a calculated distance from the candle based on recent price ranges, ensuring they remain clearly visible regardless of how volatile the market becomes.
Price Data Components
Series array that contains open time of each bar
Indicators Used
Indicator of the average true rangeStandard Deviation indicatorStochastic oscillatorCommodity channel index
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
8 Views
0 Downloads
0 Favorites
StochCross_CCI_v2
//+----------------------------------------------------------------------------------+
//|                                   Stochastic CCI filtered crossed over indicator |
//+----------------------------------------------------------------------------------+
//|                                         Stochastic CCI filtered crossed over.mq4 |
//|                                                     Copyright © 2008, Melvin Tan |
//|                                                                                  |
//+----------------------------------------------------------------------------------+

#property copyright "Melvin Tan"
#property link      "none at the moment"

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red

extern string note1 = "Stochastic settings";
extern int    KPeriod1     =  5;
extern int    DPeriod1     =  3;
extern int    Slowing1     =  3;
extern string note2 = "0=sma, 1=ema, 2=smma, 3=lwma";
extern int    MAMethod1    =   1;
extern string note3 = "0=high/low, 1=close/close";
extern int    PriceField1  =   0;
extern int    TrendCCI_Period = 50;
extern int    EntryCCI_Period = 14;
extern bool   AlertOn = false;
int       bolPrd=20;
double    bolDev=2.0;
int       keltPrd=20;
double    keltFactor=1.5;
double CrossUp[];
double CrossDown[];

string AlertPrefix;
string GetTimeFrameStr() {
   switch(Period())
   {
      case 1 : string TimeFrameStr="M1"; break;
      case 5 : TimeFrameStr="M5"; break;
      case 15 : TimeFrameStr="M15"; break;
      case 30 : TimeFrameStr="M30"; break;
      case 60 : TimeFrameStr="H1"; break;
      case 240 : TimeFrameStr="H4"; break;
      case 1440 : TimeFrameStr="D1"; break;
      case 10080 : TimeFrameStr="W1"; break;
      case 43200 : TimeFrameStr="MN1"; break;
      default : TimeFrameStr=Period();
   } 
   return (TimeFrameStr);
   }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
      SetIndexStyle(0,DRAW_ARROW);
      SetIndexArrow(0, 233);
      SetIndexStyle(1,DRAW_ARROW);
      SetIndexArrow(1, 234);
      SetIndexBuffer(0, CrossUp);
      SetIndexBuffer(1, CrossDown);

      SetIndexEmptyValue(0,EMPTY_VALUE);
      SetIndexEmptyValue(1,EMPTY_VALUE);
   
   
   AlertPrefix=Symbol()+" ("+GetTimeFrameStr()+"):  ";
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 

//----
   return(0);
  }
//+------------------------------------------------------------------+
bool NewBar()
{
   static datetime lastbar;
   datetime curbar = Time[0];
   if(lastbar!=curbar)
   {
      lastbar=curbar;
      return (true);
   }
   else
   {
      return(false);
   }
}   
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() {
   int limit, i, counter;
   double stochastic1now, stochastic2now, stochastic1previous, stochastic2previous, stochastic1after, stochastic2after;
   double Range, AvgRange;
   double TrendCCI, EntryCCInow, EntryCCIprevious;
   double diff, std, bbs;   
        
   int counted_bars=IndicatorCounted();
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;

   limit=Bars-counted_bars;
   
   for(i = 0; i <= limit; i++) {
   
      counter=i;
      Range=0;
      AvgRange=0;
      for (counter=i ;counter<=i+9;counter++)
      {
         AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]);
      }
      Range=AvgRange/10;      

      diff = iATR(NULL,0,keltPrd,i)*keltFactor;
      std = iStdDev(NULL,0,bolPrd,MODE_SMA,0,PRICE_CLOSE,i);
      bbs = bolDev * std / diff;  //Bollinger Squeeze
      
      stochastic1now = iStochastic(NULL,0,KPeriod1,DPeriod1,Slowing1,MAMethod1,PriceField1,0,i);
      stochastic1previous = iStochastic(NULL,0,KPeriod1,DPeriod1,Slowing1,MAMethod1,PriceField1,0,i+1);
      stochastic2now = iStochastic(NULL,0,KPeriod1,DPeriod1,Slowing1,MAMethod1,PriceField1,1,i);
      stochastic2previous = iStochastic(NULL,0,KPeriod1,DPeriod1,Slowing1,MAMethod1,PriceField1,1,i+1);
      TrendCCI = iCCI(NULL, 0, TrendCCI_Period, PRICE_TYPICAL, i);
      EntryCCInow = iCCI(NULL, 0, EntryCCI_Period, PRICE_TYPICAL, i);
      EntryCCIprevious = iCCI(NULL, 0, EntryCCI_Period, PRICE_TYPICAL, i+1);
                  
      if ((stochastic1now > stochastic2now) && (stochastic1previous < stochastic2previous) && (TrendCCI > 0) && (EntryCCInow > EntryCCIprevious) && (bbs > 1))
      {
                   CrossUp[i] = Low[i] - Range*1.5;
                   if (AlertOn && NewBar()) {
                      Alert(AlertPrefix+"Stoch ("+KPeriod1+","+DPeriod1+","+Slowing1+") %K crosses UP %D\nBUY signal @ Ask = ",Ask,"; Bid = ",Bid,"\nDate & Time = ",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime()));
                   }   
      }
      else if ((stochastic1now < stochastic2now) && (stochastic1previous > stochastic2previous) && (TrendCCI < 0) && (EntryCCInow < EntryCCIprevious) && (bbs > 1))
      {
                 CrossDown[i] = High[i] + Range*1.5;
                   if (AlertOn && NewBar()){
                      Alert(AlertPrefix+"Stoch ("+KPeriod1+","+DPeriod1+","+Slowing1+") %K crosses DOWN %D\nSELL signal @ Ask = ",Ask,"; Bid = ",Bid,"\nDate & Time = ",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime()));
                   }
      }
      else 
      {
      CrossUp[i] = EMPTY_VALUE;
      CrossDown[i] = EMPTY_VALUE;
      }

   }
   return(0);
}

Comments