CatFx50K
Download scriptThis technical indicator is designed to identify trading opportunities by analyzing price trends, momentum shifts, and specific time-based constraints. It combines multiple analytical layers—including Moving Averages, Stochastic oscillators, and custom trend filters—to generate visual buy and sell signals on a trading chart.
Core Logic Overview
The script functions by scanning the market data to find "confluence," which is when multiple independent technical conditions align simultaneously. It filters out noise by ensuring that a signal only appears when the overall trend supports the specific entry point.
Key Components of the Analysis
1. Time-Based Filtering The indicator respects specific trading windows. It identifies "Off-Trade" periods (based on user-defined hours) where it will ignore standard signals, effectively restricting the tool's activity to the most active or preferred market sessions.
2. Trend and Momentum Detection The logic relies heavily on three primary components:
- Moving Averages: It tracks a long-term Exponential Moving Average (EMA) to determine the primary direction of the market. It looks for specific "price crosses," where the candle wicks interact with this average line to confirm a shift in momentum.
- Stochastic Oscillators: The script monitors two distinct internal lines (referred to as yellow and blue). It looks for specific "crossover" events where these lines intersect, signaling potential overbought or oversold conditions.
- Inverse Indicators: It utilizes an additional "Inverse" filter to validate that the price action (bullish or bearish) aligns with the underlying mathematical trend of the market.
3. Signal Generation Logic The indicator generates two types of signals:
- Primary Signals: These are larger visual markers (arrows) produced when a Stochastic crossover occurs in harmony with the long-term EMA trend and price confirmation.
- Secondary (Small) Dots: Depending on the user's settings, the script can display smaller dots that highlight minor momentum shifts, providing a more granular view of the market's pulse without requiring a full primary signal.
4. Visual Trend Coloring The script includes a dynamic coloring system for the price bars. By calculating the distance between the internal Stochastic lines, it can change the visual style of the chart bars to reflect whether the current momentum is leaning upward or downward. This provides an immediate visual cue of market sentiment.
User Customization Options
The logic allows for different "Strictness" levels:
- Strict Rules: When enabled, the script requires much higher confirmation (Price Cross + Stochastic Cross + Inverse Filter + Candle Color) before displaying a signal.
- Flexible Rules: When disabled, the script is more sensitive and will provide signals based on fewer concurrent conditions, making it faster but potentially less selective.
//+------------------------------------------------------------------+
//| CatFx50K.mq4 |
//| Kalenzo |
//| simone@konto.pl |
//+------------------------------------------------------------------+
#property copyright "Kalenzo"
#property link "simone@konto.pl"
#property indicator_chart_window
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_color3 Lime
#property indicator_color4 Red
#property indicator_color5 Gray
#property indicator_color6 Gray
#property indicator_color7 Lime
#property indicator_color8 Red
#property indicator_buffers 8
extern int StochCrossBars = 3;
extern int EmaCrossBars = 3;
extern bool useStrictRules = true;
extern bool showSmallDots = true;
extern bool colorBars = true;
extern int startTrade = 8;
extern int endTrade = 18;
double UpBuffer[];
double DnBuffer[];
double UpTrend[];
double DnTrend[];
double OffTrade_a[];
double OffTrade_b[];
double UpSmallBuffer[];
double DnSmallBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_ARROW,EMPTY,3);
SetIndexStyle(1,DRAW_ARROW,EMPTY,3);
SetIndexStyle(2,DRAW_HISTOGRAM,0,1);
SetIndexStyle(3,DRAW_HISTOGRAM,0,1);
SetIndexStyle(4,DRAW_HISTOGRAM,0,1);
SetIndexStyle(5,DRAW_HISTOGRAM,0,1);
SetIndexStyle(6,DRAW_ARROW,EMPTY,1);
SetIndexStyle(7,DRAW_ARROW,EMPTY,1);
SetIndexBuffer(0,UpBuffer);
SetIndexBuffer(1,DnBuffer);
SetIndexBuffer(2,UpTrend);
SetIndexBuffer(3,DnTrend);
SetIndexBuffer(4,OffTrade_a);
SetIndexBuffer(5,OffTrade_b);
SetIndexBuffer(6,UpSmallBuffer);
SetIndexBuffer(7,DnSmallBuffer);
SetIndexArrow(0,159);
SetIndexArrow(1,159);
SetIndexArrow(6,159);
SetIndexArrow(7,159);
SetIndexLabel(0,"Up Signal");
SetIndexLabel(1,"Down Signal");
SetIndexLabel(2,"Up Trend");
SetIndexLabel(3,"Down Trend");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int limit;
int counted_bars=IndicatorCounted();
if(counted_bars<0) counted_bars=0;
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
//----
for(int i = 0 ;i < limit ;i++)
{
if(TimeHour(Time[i]) > endTrade || TimeHour(Time[i]) < startTrade)
{
OffTrade_a[i]=High[i];
OffTrade_b[i]=Low[i];
continue;
}
else
{
OffTrade_a[i]=EMPTY_VALUE;
OffTrade_b[i]=EMPTY_VALUE;
}
int cross = 0;//cross 1-buy | cross 2-sell
for(int c =i+StochCrossBars; c>=i; c--)
{
double yellow = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,0,c);//yellow
double pyellow = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,0,c+1);//yellow
double blue = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,1,c);//blue
double pblue = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,1,c+1);//blue
if(pyellow <= yellow && pblue >= blue && pyellow <= pblue && yellow > blue)
{
cross = 1;//buy stoch
}
else if(pyellow >= yellow && pblue <= blue && pyellow >= pblue && yellow < blue)
{
cross = 2;//sell stoch
}
}
double longMA = iMA(Symbol(),30,50,0,MODE_EMA,PRICE_CLOSE,i);
double INV = iCustom(Symbol(),30,"IND Inverse",1,0,i);
double blueStoch = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,1,i);//blue
double yellowStoch = iCustom(Symbol(),30,"StepMA_Stoch_v1",10,1,0,0,i);//yellow
bool emaCross = false;
for(int e =i+EmaCrossBars; e>=i; e--)
{
double longMACross = iMA(Symbol(),30,50,0,MODE_EMA,PRICE_CLOSE,e+1);
if(High[e+1] > longMACross && Low[e+1] < longMACross)
{
emaCross = true;
break;
}
}
if(emaCross)
{//PRICE CROSSES
if(!useStrictRules)
{
if(!showSmallDots)
{
if(Open[i] > longMA && cross == 1 )
{
UpBuffer[i]=Low[i]-(20*Point);
DnBuffer[i]=EMPTY_VALUE;
}
else if(Open[i] < longMA && cross == 2 )
{
UpBuffer[i]=EMPTY_VALUE;
DnBuffer[i]=High[i]+(20*Point);
}
UpSmallBuffer[i] = EMPTY_VALUE;
DnSmallBuffer[i] = EMPTY_VALUE;
}
else
{
if(Open[i] > longMA && cross == 1 )
{
UpBuffer[i]=Low[i]-(20*Point);
DnBuffer[i]=EMPTY_VALUE;
}
else if(Open[i] < longMA && cross == 2 )
{
UpBuffer[i]=EMPTY_VALUE;
DnBuffer[i]=High[i]+(20*Point);
}
if(Open[i] < longMA && blueStoch > yellowStoch )
{
UpSmallBuffer[i]=EMPTY_VALUE;
DnSmallBuffer[i]=High[i]+(10*Point);
}
else if(Open[i] > longMA && blueStoch < yellowStoch)
{
UpSmallBuffer[i]=Low[i]-(10*Point);
DnSmallBuffer[i]=EMPTY_VALUE;
}
}
}
else
{
if(!showSmallDots)
{
if(Open[i] > longMA && cross == 1 && INV > 0 && Close[i]>Open[i] )
{
UpBuffer[i]=Low[i]-(20*Point);
DnBuffer[i]=EMPTY_VALUE;
}
else if(Open[i] < longMA && cross == 2 && INV < 0 && Close[i]<Open[i])
{
UpBuffer[i]=EMPTY_VALUE;
DnBuffer[i]=High[i]+(20*Point);
}
UpSmallBuffer[i] = EMPTY_VALUE;
DnSmallBuffer[i] = EMPTY_VALUE;
}
else
{
if(Open[i] > longMA && cross == 1 && INV > 0 && Close[i]>Open[i] )
{
UpBuffer[i]=Low[i]-(20*Point);
DnBuffer[i]=EMPTY_VALUE;
}
else if(Open[i] < longMA && cross == 2 && INV < 0 && Close[i]<Open[i])
{
UpBuffer[i]=EMPTY_VALUE;
DnBuffer[i]=High[i]+(20*Point);
}
if(Open[i] > longMA && blueStoch < yellowStoch && INV > 0 && Close[i]>Open[i] )
{
UpSmallBuffer[i]=Low[i]-(10*Point);
DnSmallBuffer[i]=EMPTY_VALUE;
}
else if(Open[i] < longMA && blueStoch > yellowStoch && INV < 0 && Close[i]<Open[i])
{
UpSmallBuffer[i]=EMPTY_VALUE;
DnSmallBuffer[i]=High[i]+(10*Point);
}
}
}
}
if(colorBars)
{
if(blueStoch>yellowStoch && MathAbs(blueStoch-yellowStoch)>=0.1)
{
DnTrend[i] = High[i];
UpTrend[i] = Low[i];
}
else if(blueStoch<yellowStoch && MathAbs(blueStoch-yellowStoch)>=0.1)
{
UpTrend[i] = High[i];
DnTrend[i] = Low[i];
}
}
else
{
UpTrend[i] = EMPTY_VALUE;
DnTrend[i] = EMPTY_VALUE;
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
Comments