SchaffTrendCycle1Test
Download scriptThe Schaff Trend Cycle (STC) is a sophisticated technical analysis tool designed to identify trend cycles by combining three distinct types of mathematical movements: momentum, smoothing, and relative positioning. Unlike standard indicators that might lag behind price action, this script processes data through multiple layers to filter out market "noise" and highlight significant shifts in trend direction.
How the Logic Works
The indicator functions by passing price data through a four-stage refinement process:
1. Momentum Identification The logic begins by calculating the difference between two Exponential Moving Averages (EMA). By comparing a fast-moving average against a slow-moving average, the script identifies the immediate "velocity" of the price. If the fast average is significantly above the slow average, it indicates upward momentum; if below, it suggests downward momentum.
2. Signal Smoothing (The MACD Component) To prevent the raw momentum data from being too erratic, the script applies a smoothing calculation. This acts as a stabilizer, ensuring that minor price fluctuations do not trigger false signals. It creates a "cleaner" line that represents the underlying trend of the momentum.
3. Double Stochastic Processing The smoothed data is then fed into a dual-layer Stochastic calculation. Think of this as a "percentage of the range" logic. It looks at the highs and lows over a specific period to determine where the current price sits relative to its recent boundaries.
- The first layer transforms the smoothed data into a percentage value.
- The second layer takes that percentage and smoothes it again.
This "double-smoothing" technique is what gives the indicator its unique ability to stay stable during choppy markets while still reacting quickly when a real trend change occurs.
4. Visual Cues and Alerts The final output is a cycle that moves between 0 and 100. The script is programmed to automatically detect specific "breakout" points in this cycle:
- Bullish Signals: When the indicator value crosses upward from below the 20 level, the script places a Lime Green vertical line on the chart. This suggests that momentum is shifting toward an uptrend.
- Bearish Signals: When the indicator value crosses downward from above the 80 level, the script places a Red vertical line on the chart. This suggests that the cycle is turning toward a downtrend.
Summary for the Trader
Essentially, this script takes raw price data, measures its speed, cleans up the jagged edges of that speed, and then translates it into a percentage of its recent range. By doing this, it provides you with clear visual "markers" (the green and red lines) to help identify when a market trend is likely beginning or exhausting itself.
//+------------------------------------------------------------------+
//| Schaff Trend Cycle 1.mq4 |
//| mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link "mladenfx@gmail.com"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//
//
//
//
//
extern int STCPeriod = 10;
extern int CDPeriod = 25;
extern int FastMAPeriod = 23;
extern int SlowMAPeriod = 50;
extern double sm = 2;
//
//
//
//
//
double stcBuffer[];
double macdBuffer[];
double cdBuffer[];
double fastKBuffer[];
double fastDBuffer[];
double fastKKBuffer[];
string ObjectID = "stc1vline";
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
int init()
{
IndicatorBuffers(6);
SetIndexBuffer(0,stcBuffer);
SetIndexBuffer(1,macdBuffer);
SetIndexBuffer(2,cdBuffer);
SetIndexBuffer(3,fastKBuffer);
SetIndexBuffer(4,fastDBuffer);
SetIndexBuffer(5,fastKKBuffer);
IndicatorShortName("Schaff TC1 ("+STCPeriod+","+FastMAPeriod+","+SlowMAPeriod+","+CDPeriod+")");
return(0);
}
int deinit()
{
int obj_total=ObjectsTotal(OBJ_VLINE);
string name;
for(int i=obj_total-1;i>=0;i--)
{
name=ObjectName(i);
if (StringFind(name,ObjectID, 0) >= 0) ObjectDelete(name);
}
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
int start()
{
// double alphaCD = 2.0 / (1.0 + CDPeriod);
double alphaCD = sm / (1.0 + CDPeriod);
int counted_bars = IndicatorCounted();
int limit,i;
if(counted_bars < 0) return(-1);
if(counted_bars>0) counted_bars--;
limit = Bars-counted_bars;
//
//
//
//
//
for(i = limit; i >= 0; i--)
{
macdBuffer[i] = iMA(NULL,0,FastMAPeriod,0,MODE_EMA,PRICE_CLOSE,i)-
iMA(NULL,0,SlowMAPeriod,0,MODE_EMA,PRICE_CLOSE,i);
cdBuffer[i] = cdBuffer[i+1]+alphaCD*(macdBuffer[i]-cdBuffer[i+1]);
//
//
//
//
//
double lowCd = minValue(cdBuffer,i);
double highCd = maxValue(cdBuffer,i)-lowCd;
if (highCd > 0)
fastKBuffer[i] = 100*((cdBuffer[i]-lowCd)/highCd);
else fastKBuffer[i] = fastKBuffer[i+1];
fastDBuffer[i] = fastDBuffer[i+1]+0.5*(fastKBuffer[i]-fastDBuffer[i+1]);
//
//
//
//
//
double lowStoch = minValue(fastDBuffer,i);
double highStoch = maxValue(fastDBuffer,i)-lowStoch;
if (highStoch > 0)
fastKKBuffer[i] = 100*((fastDBuffer[i]-lowStoch)/highStoch);
else fastKKBuffer[i] = fastKKBuffer[i+1];
stcBuffer[i] = stcBuffer[i+1]+0.5*(fastKKBuffer[i]-stcBuffer[i+1]);
if (stcBuffer[i]>20 && stcBuffer[i+1]<20)
{
ObjectCreate(ObjectID + "1"+Time[i], OBJ_VLINE, 0, Time[i], 0);
ObjectSet(ObjectID + "1"+Time[i], OBJPROP_WIDTH,3);
ObjectSet(ObjectID + "1"+Time[i], OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(ObjectID + "1"+Time[i], OBJPROP_COLOR, LimeGreen);
}
if (stcBuffer[i+1]>80 && stcBuffer[i]<80)
{
ObjectCreate(ObjectID + "2"+Time[i], OBJ_VLINE, 0, Time[i], 0);
ObjectSet(ObjectID + "2"+Time[i], OBJPROP_WIDTH,3);
ObjectSet(ObjectID + "2"+Time[i], OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(ObjectID + "2"+Time[i], OBJPROP_COLOR, Red);
}
}
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
double minValue(double& array[],int shift)
{
double minValue = array[shift];
for (int i=1; i<STCPeriod; i++) minValue = MathMin(minValue,array[shift+i]);
return(minValue);
}
double maxValue(double& array[],int shift)
{
double maxValue = array[shift];
for (int i=1; i<STCPeriod; i++) maxValue = MathMax(maxValue,array[shift+i]);
return(maxValue);
}
Comments