TSSuperTrend

Download script
TSSuperTrend

This tool is a sophisticated technical analysis indicator designed to identify and visualize market trends in real-time. It functions by calculating the "momentum" of price action and providing clear visual cues—such as colored lines, arrows, and even custom candles—to help traders distinguish between upward (bullish) and downward (bearish) movements.

Core Logic and Functionality

1. Trend Detection Mechanics The script operates by comparing current market prices against a calculated "trend line." It uses three distinct modes to determine how much "breathing room" or volatility should be allowed before a trend is considered changed:

  • ATR Mode: Uses Average True Range to account for standard market volatility.
  • Adaptive Mode: Adjusts based on recent price fluctuations.
  • Dual Thrust: A custom calculation that looks at the highest highs, lowest lows, and recent closing prices to create a more responsive volatility buffer.

2. Smoothing and Filtering To ensure the indicator doesn't react to "noise" (small, insignificant price flickers), it incorporates a smoothing layer. It can calculate averages using several different mathematical methods (such as EMA, SMA, HMA, etc.). This ensures that the trend line remains fluid and represents the general direction of the market rather than erratic moment-to-moment changes.

3. Dynamic Trend Switching The logic continuously monitors the price. If the price closes above the previous downward trend line, the script triggers an "Upward Trend." Conversely, if the price drops below the upward trend line, it switches to a "Downward Trend."

When these transitions occur, the script performs several actions simultaneously:

  • Visual Updates: It changes the color of the trend lines and the bars on your chart (e.g., Blue for Up, Red for Down).
  • Alerts: It can trigger audible sounds and visual messages to notify you the moment a trend reversal is confirmed.
  • Markers: It can place arrows on the chart at the exact point where the trend flips.

4. Intelligent Trendline Plotting The indicator is programmed to be "smart" about how it draws lines. Instead of jumping around, the trend line is designed to stay constant until a new high or low is reached that breaks the current trend. This creates a "staircase" effect that helps traders visualize clear support and resistance levels based on the current trend.

5. Error Handling and Stability The script includes an internal diagnostic system. It constantly checks for data errors or calculation issues during its execution, providing feedback to ensure that the visual information on your chart remains accurate and reliable.

Indicators Used
Moving average indicatorIndicator of the average true range
Miscellaneous
Implements a curve of type %1It plays sound alerts
4 Views
0 Downloads
0 Favorites
TSSuperTrend
//+------------------------------------------------------------------+
//|                                                 TSSuperTrend.mq4 |
//+------------------------------------------------------------------+
#property link      "http://www.backtothefuturetrading.com/"
#include <stderror.mqh>
#include <stdlib.mqh>

#property indicator_chart_window
#property indicator_color1 Lime
#property indicator_color2 Red
#property indicator_color3 Lime
#property indicator_color4 Red
//#property indicator_width1 1
//#property indicator_width2 1
#property indicator_buffers 4

int FLAT = 0;
int UPTREND = 1;
int DOWNTREND = -1;
double TrendUpPlot[], TrendDownPlot[],ArrowsUp[], ArrowsDn[];
double smoothingMA[], trend[];
//bool changeOfTrend=false;
extern string Modes = "Key:  1-ATR, 2-Adaptive, 3-Dual Thrust";
extern int SuperTrendMode = 1;
extern int SuperTrendPeriod = 14;
extern double Multiplier = 2.618;
extern string SmoothingTypes ="Key:  1-EMA, 2-SMA, 3-HMA, 4-WMA, 5-TMA, 6-SMMA";
extern int SmoothingMAtype = 3;
extern int SmoothingPeriod = 14;
extern string msg1="- - - - Alerts - - - - -";
extern string BuySound = "Alert2.wav";
extern string SellSound = "Alert2.wav";
extern string msg2="- - - - Visual - - - - -";
extern bool ShowArrows = false;
extern bool ColorBars = false;
extern color UpTrendColor = Blue;
extern color DownTrendColor = Red;
extern int CandleWidth = 3;
extern int WickWidth = 1;
//==============================================

color BarColor=White;
color prevColor = White;

datetime currentbartime = 0;
double offset = 0;
int CurrentBar=-1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//   Comment(TimeToStr(TimeLocal(),TIME_MINUTES));

//==============================================
   
   DeleteObject("ErrorLabel");
   if(!ObjectCreate("ErrorLabel", OBJ_LABEL, 0, 0, 0)) Print("Error creating error label");
   ObjectSetText("ErrorLabel", " ", 10, "Arial", Red);
   ObjectSet("ErrorLabel", OBJPROP_XDISTANCE, 10);
   ObjectSet("ErrorLabel", OBJPROP_YDISTANCE, 30);
   CheckError(74,Bars-1);
   IndicatorBuffers(6);
   SetIndexBuffer(0, TrendUpPlot);
   SetIndexStyle(0, DRAW_LINE, STYLE_DOT, 1);
   SetIndexLabel(0, "Trend Up");
   SetIndexBuffer(1, TrendDownPlot);
   SetIndexStyle(1, DRAW_LINE, STYLE_DOT, 1);
   SetIndexLabel(1, "Trend Down");
   SetIndexBuffer(2, ArrowsUp);
   SetIndexStyle(2, DRAW_ARROW, EMPTY,2);
   SetIndexArrow(2, 233);
   SetIndexLabel(2, "ArrowsUp");
   SetIndexBuffer(3, ArrowsDn);
   SetIndexStyle(3, DRAW_ARROW, EMPTY,2);
   SetIndexArrow(3, 234);
   SetIndexLabel(3, "ArrowsDn");
   SetIndexBuffer(4, smoothingMA);
   SetIndexBuffer(5, trend);
   prevColor = UpTrendColor;
   BarColor  = UpTrendColor;
   CheckError(94,Bars-1);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   int p = ObjectsTotal();
   while(p>=0) {
      string name = ObjectName(p);
      if(StringFind(name, "tssbar", 0)==0) ObjectDelete(name);
      p--;
   }

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() {

   int limit;
   int counted_bars = IndicatorCounted();
//---- check for possible errors
   if(counted_bars < 0) return(-1);
   limit=Bars-counted_bars-1;
   if(counted_bars!=0) limit++;
   
//----
   for (int i = limit; i >= 0; i--) {
      CurrentBar++;
      if(CurrentBar<MathMax(SmoothingPeriod,SuperTrendPeriod)*2) {
         trend[i] = UPTREND;
         TrendUpPlot[i]   = Close[i];
         TrendDownPlot[i] = Close[i];
      }
      CheckError(221,i);
      if(Time[i]!=currentbartime) { //this is the first tick of this new bar
         currentbartime = Time[i];
      }
      CheckError(225,i);

      if(SmoothingMAtype==1)      smoothingMA[i] = iMA(NULL,0,SmoothingPeriod, 0, MODE_EMA, PRICE_CLOSE, i);
      else if(SmoothingMAtype==2) smoothingMA[i] = iMA(NULL,0,SmoothingPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
      else if(SmoothingMAtype==3) smoothingMA[i] = iCustom(NULL, 0, "HMA", SmoothingPeriod, 0, 0, i);
      else if(SmoothingMAtype==4) smoothingMA[i] = iMA(NULL,0,SmoothingPeriod, 0, MODE_LWMA, PRICE_CLOSE, i);
      else if(SmoothingMAtype==5) smoothingMA[i] = iCustom(NULL, 0, "TMA", SmoothingPeriod, 0, 0, i);
      else if(SmoothingMAtype==6) smoothingMA[i] = iMA(NULL,0,SmoothingPeriod, 0, MODE_SMMA, PRICE_CLOSE, i);
 
      CheckError(234,i);
      if(SuperTrendMode == 1)      offset = iATR(NULL,0,SuperTrendPeriod,i)*Multiplier;
      else if(SuperTrendMode == 2) offset = iATR(NULL,0,SuperTrendPeriod,i)*Multiplier;
      else if(SuperTrendMode == 3) offset = DTT(SuperTrendPeriod, Multiplier, i);

      CheckError(239,i);
      if(i==0 || (counted_bars==0 && i!=limit)) {
         if (TrendDownPlot[i+1] != EMPTY_VALUE && Close[i]>TrendDownPlot[i+1]) {
            trend[i]=UPTREND;
         }
         else if (TrendUpPlot[i+1] != EMPTY_VALUE && Close[i]<TrendUpPlot[i+1]) {
            trend[i]=DOWNTREND;
         }
         else trend[i]=trend[i+1];
      }
      CheckError(249,i);


      if (trend[i]>FLAT && trend[i+1]<FLAT) {
         TrendDownPlot[i] = EMPTY_VALUE;
         TrendUpPlot[i] = smoothingMA[i]-offset;
         BarColor = UpTrendColor;
         if(ShowArrows) ArrowsUp[i] = TrendUpPlot[i]-Point;
         if(i==0) PlaySound(BuySound);
      }
      else if (trend[i]<FLAT && trend[i+1]>FLAT) {
         TrendDownPlot[i] = smoothingMA[i]+offset;
         TrendUpPlot[i] = EMPTY_VALUE;
         BarColor = DownTrendColor;
         if(ShowArrows) ArrowsDn[i] = TrendDownPlot[i]+Point;
         if(i==0) PlaySound(SellSound);
      } else {
         if (trend[i]>FLAT) {
            if(smoothingMA[i] - offset > TrendUpPlot[i+1]) TrendUpPlot[i] = smoothingMA[i] - offset; else TrendUpPlot[i] = TrendUpPlot[i+1];
         } else {
            if(smoothingMA[i] + offset < TrendDownPlot[i+1]) TrendDownPlot[i] = smoothingMA[i] + offset; else TrendDownPlot[i] = TrendDownPlot[i+1];
         }
         BarColor = prevColor;
      }
      CheckError(273,i);
      if(ColorBars && i<200) {
		    string linename = "tssbarw"+TimeStr(Time[i]);
		    if(ObjectFind(linename)>=0) ObjectDelete(linename);
		    if(High[i]!=Low[i]) {
   		    ObjectCreate(linename,OBJ_TREND,0,Time[i], High[i], Time[i], Low[i]);
             ObjectSet(linename, OBJPROP_COLOR, BarColor);
             ObjectSet(linename, OBJPROP_WIDTH, WickWidth);
             ObjectSet(linename, OBJPROP_RAY, false);
          }
		    linename = "tssbarb"+TimeStr(Time[i]);
		    if(ObjectFind(linename)>=0) ObjectDelete(linename);
		    if(Open[i]!=Close[i]) {
             ObjectCreate(linename,OBJ_TREND,0,Time[i], Open[i], Time[i], Close[i]);
             ObjectSet(linename, OBJPROP_COLOR, BarColor);
             ObjectSet(linename, OBJPROP_WIDTH, CandleWidth);
             ObjectSet(linename, OBJPROP_RAY, false);
          }
          prevColor = BarColor;
      }
   }
      
//----
   return(0);
  }
//=================================================================================
double DTT(int nDay, double mult, int shift)
{
	double HH = MAX(PRICE_HIGH, nDay, shift);
	double HC = MAX(PRICE_CLOSE,nDay, shift);
	double LL = MIN(PRICE_LOW, nDay, shift);
	double LC = MIN(PRICE_CLOSE, nDay, shift);
	return (mult * MathMax((HH - LC),(HC - LL)));
}
//=================================================================================
double MAX(int type, int period, int shift) {
   double p = -1000.0;
   for(int j = 0; j<period; j++){
      switch(type) {
         case PRICE_HIGH:  p = MathMax(High[j+shift],p);  break;
         case PRICE_LOW:   p = MathMax(Low[j+shift],p);   break;
         case PRICE_CLOSE: p = MathMax(Close[j+shift],p); break;
         case PRICE_OPEN:  p = MathMax(Open[j+shift],p);  break;
      }
   }
   return (p);
}
//=================================================================================
double MIN(int type, int period, int shift) {
   double p = Close[shift]*10;
   for(int j = 0; j<period; j++){
      switch(type) {
         case PRICE_HIGH:  p = MathMin(High[j+shift],p);  break;
         case PRICE_LOW:   p = MathMin(Low[j+shift],p);   break;
         case PRICE_CLOSE: p = MathMin(Close[j+shift],p); break;
         case PRICE_OPEN:  p = MathMin(Open[j+shift],p);  break;
      }
   }
   return (p);
}
//=================================================================================
string TimeStr(datetime t) {
   string result = DoubleToStr(TimeYear(t),0);
   string temp = DoubleToStr(TimeMonth(t),0);  if(StringLen(temp)==1) temp = "_"+temp;
   result = result + temp;
   temp = DoubleToStr(TimeDay(t),0);  if(StringLen(temp)==1) temp = "_"+temp;
   result = result + temp;
   temp = DoubleToStr(TimeHour(t),0);  if(StringLen(temp)==1) temp = "_"+temp;
   result = result + temp;
   temp = DoubleToStr(TimeMinute(t),0);  if(StringLen(temp)==1) temp = "_"+temp;
   result = result + temp;
   temp = DoubleToStr(TimeSeconds(t),0);
   result = result + temp;
   return(result);
}

//=================================================================================
void CheckError(int line, int RelBar)
{
   int err = GetLastError();
   if(err > ERR_NO_RESULT) {
//      ErrorPrintedAt = TimeLocal();
      string msg="";
      if(msg=="") msg = "RBT_Intel: "+TimeToStr(Time[0], TIME_MINUTES)+", "+ErrorDescription(err)+" (#"+err+"  ";
      Print(msg);
      if(RelBar>=0) {
         Comment(msg);
//         ObjectSetText("ErrorLabel"+RelBar, msg+" "+line+")", 12, "Arial", Red);
//         ObjectSet("ErrorLabel"+RelBar, OBJPROP_PRICE1, (WindowPriceMax() + WindowPriceMin())/2.0);
//         ObjectSet("ErrorLabel"+RelBar, OBJPROP_TIME1, Time[RelBar]);
      }
   }
}

//=================================================================================
void DeleteObject(string name) {
   if(ObjectFind(name)!=-1) ObjectDelete(name);
}
//=================================================================================

Comments