This script is a sophisticated technical analysis tool designed to track momentum and trend direction in financial markets. It takes the core concept of a "TRIX" indicator—which identifies price trends by looking at the rate of change of moving averages—and adds several layers of smoothing, visual signals, and automated alerts to help traders identify high-probability entry points.
Core Logic and Processing
The logic follows a multi-stage calculation process to filter out market "noise":
- Data Input & Primary Smoothing: The tool starts by looking at specific price types (like Close or Typical prices) and applies three consecutive layers of Moving Averages. This creates a stabilized baseline of the price action.
- Rate of Change Calculation: Instead of just looking at where the price is, the script calculates the percentage change between these smoothed averages. This allows the indicator to focus on the velocity of the trend rather than just the direction.
- Secondary Smoothing (The "Super" Layer): The script takes that velocity data and applies another round of smoothing. By doing this twice, it removes minor fluctuations, ensuring that the resulting signals are based on significant market moves.
Visual Elements & Indicators
The script provides several visual layers to help a trader interpret the data:
- Dynamic Histograms: It translates the smoothed data into a histogram. This makes it very easy to see whether momentum is expanding or contracting.
- Trend Lines: A continuous line tracks the net difference between current momentum and its average, providing a "clean" view of the trend's path.
- Trigger Levels: The script calculates a "Standard Deviation" style volatility band (based on an adjustable smoothing period). This creates dynamic boundary lines that help traders understand how much price variation is currently normal for the market.
- Visual Signals (Arrows): The logic automatically identifies specific "crossovers." When the momentum shifts from negative to positive (or vice versa) in a statistically significant way, the script places visual arrows on the chart to highlight potential Buy and Sell opportunities.
Automated Notifications
Beyond just visual cues, the script includes an active monitoring system:
- Real-Time Alerts: The logic constantly monitors the "Zero Line" crossover—the point where momentum flips from bearish to bullish.
- Smart Filtering: It is programmed to ensure that alerts are only sent once per trend change (using "TurnedUp/TurnedDown" flags). This prevents the script from spamming the user with multiple notifications during a single sustained move.
- Multi-Channel Communication: Depending on user settings, these alerts can be triggered as pop-up windows on the trading platform or sent directly to the user's email.
Summary for the User
Essentially, this tool acts as a "momentum filter." It takes raw price data, smooths it through multiple mathematical layers to find the true trend, and then signals you exactly when that trend gains enough strength to be actionable. It moves beyond basic indicators by combining velocity, volatility boundaries, and automated notifications into one comprehensive system.
//+------------------------------------------------------------------+
//| smSuper TRIX_PV_v2.mq4 |
//| © 2009.08.05, SwingMan |
//| |
//+------------------------------------------------------------------+
#property copyright "© 2009.08.05, SwingMan"
#property link ""
// Source:
//+------------------------------------------------------------------+
//| TRIX.mq4 |
//| by Raff |
//+------------------------------------------------------------------+
//#property copyright "Copyright © 2006, raff1410@o2.pl"
/* 2009.07.12 - choice of moving averages
- choice of prices (close, log(close) )
2009.07.16 - Peeks & Valeys
2009.08.05 - Trigger MA of histograms
*/
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1 Gray // line
#property indicator_color2 SeaGreen // histogram
#property indicator_color3 Maroon
#property indicator_color4 DeepSkyBlue
#property indicator_color5 Red
#property indicator_color6 Red
#property indicator_color7 Red
#property indicator_width1 1
#property indicator_width2 3
#property indicator_width3 3
#property indicator_width4 1
#property indicator_width5 1
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID
#property indicator_level1 0
//---- indicator parameters
//-------------------------------------------------------------------
extern int TRIX_Period = 3;
//extern bool DefaultAvg_SMMA_SMMA_EMA = true;
//extern string p1 = "_____TRIX_studies____";
extern string _____Averages_____ = "0=SMA, 1=EMA, 2=SMMA, 3=LWMA";
extern int Mode_Average_1 = 1;
extern int Mode_Average_2 = 1;
extern int Mode_Average_3 = 1;
extern string _____Input_Price_____ = "0=C,4=Median,5=Typical,6=Weighted";
extern int Input_Price = 0;
//extern string _____Mode_Price_____ = "0=Price,1=ln(Price)";
//extern int Mode_Price = 0;
//extern string _____Mode_TRIX_____ = "0=RateOfChange,1=Divided";
//extern int Mode_TRIX = 1;
extern string p2 = "_____Signals_____";
extern bool Draw_Signals = true;
extern bool Alert_Signals = false;
extern bool EMail_Signals = false;
extern int CountBars = 500;
extern int Period_SmoothHistograms = 55;
extern double Factor_TriggerLine = 0.5;
//-------------------------------------------------------------------
int Signal_Period = 0;
double Scale = 1000.0;
//---- indicator buffers
double ind_buffer1a[];
double ind_buffer2a[];
double ind_buffer3[];
double ind_buffer4[];
double ind_buffer5[];
double ind_buffer6up[], ind_buffer6upPV[];
double ind_buffer6dn[], ind_buffer6dnPV[];
double ind_buffer7[];
double SignalUP[], SignalDN[];
double HistogramLineUP[], HistogramLineDN[], absHistogramBuffer[], avgHistogramBuffer[];
//---- variables
bool TurnedUp = false;
bool TurnedDown = false;
int ModeAvg1, ModeAvg2, ModeAvg3;
int inputPrice;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
ArraySetAsSeries(ind_buffer1a,true);
ArraySetAsSeries(ind_buffer2a,true);
ArraySetAsSeries(ind_buffer3,true);
ArraySetAsSeries(ind_buffer4,true);
ArraySetAsSeries(ind_buffer7,true);
ArraySetAsSeries(ind_buffer6upPV,true);
ArraySetAsSeries(ind_buffer6dnPV,true);
ArraySetAsSeries(absHistogramBuffer, true);
ArraySetAsSeries(avgHistogramBuffer, true);
//---- indicator buffers mapping
IndicatorDigits(4);
SetIndexBuffer(0,ind_buffer5); SetIndexStyle(0,DRAW_LINE); SetIndexLabel(0,NULL);
SetIndexBuffer(1,ind_buffer6up); SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexBuffer(2,ind_buffer6dn); SetIndexStyle(2,DRAW_HISTOGRAM);
SetIndexBuffer(3,SignalUP); SetIndexStyle(3,DRAW_ARROW); SetIndexArrow(3,233); SetIndexLabel(3,NULL);
SetIndexBuffer(4,SignalDN); SetIndexStyle(4,DRAW_ARROW); SetIndexArrow(4,234); SetIndexLabel(4,NULL);
SetIndexBuffer(5,HistogramLineUP); SetIndexStyle(5,DRAW_LINE); SetIndexLabel(5,NULL);
SetIndexBuffer(6,HistogramLineDN); SetIndexStyle(6,DRAW_LINE); SetIndexLabel(6,NULL);
//---- parameters
//-- default
ModeAvg1 = MODE_SMMA;
ModeAvg2 = MODE_SMMA;
ModeAvg3 = MODE_EMA;
inputPrice = PRICE_CLOSE;
//-- TRIX studies
string sPrice, sAvg1, sAvg2, sAvg3;
//moving averages
// if (DefaultAvg_SMMA_SMMA_EMA == false) {
switch (Mode_Average_1) {
case 0: ModeAvg1 = MODE_SMA; sAvg1 = "S"; break;
case 1: ModeAvg1 = MODE_EMA; sAvg1 = "E"; break;
case 2: ModeAvg1 = MODE_SMMA; sAvg1 = "M"; break;
case 3: ModeAvg1 = MODE_LWMA; sAvg1 = "W"; break;
}
switch (Mode_Average_2) {
case 0: ModeAvg2 = MODE_SMA; sAvg2 = "S"; break;
case 1: ModeAvg2 = MODE_EMA; sAvg2 = "E"; break;
case 2: ModeAvg2 = MODE_SMMA; sAvg2 = "M"; break;
case 3: ModeAvg2 = MODE_LWMA; sAvg2 = "W"; break;
}
switch (Mode_Average_3) {
case 0: ModeAvg3 = MODE_SMA; sAvg3 = "S"; break;
case 1: ModeAvg3 = MODE_EMA; sAvg3 = "E"; break;
case 2: ModeAvg3 = MODE_SMMA; sAvg3 = "M"; break;
case 3: ModeAvg3 = MODE_LWMA; sAvg3 = "W"; break;
}
//-- prices
switch(Input_Price) {
case 0: inputPrice = PRICE_CLOSE; sPrice = "C"; break;
case 4: inputPrice = PRICE_MEDIAN; sPrice = "M"; break;
case 5: inputPrice = PRICE_TYPICAL; sPrice = "T"; break;
case 6: inputPrice = PRICE_WEIGHTED; sPrice = "W"; break;
}
/*//-- mode prices
switch(Mode_Price) {
case 0: modePrice = inputPrice; break;
case 1: modePrice = MathLog(inputPrice); break;
}*/
// }
//---- name for DataWindow and indicator subwindow label
//IndicatorShortName("SwingMan SuperTRIX_v1 ("+TRIX_Period+", "+Signal_Period+")");
//string sParameters = ", "+ModeAvg1+","+ModeAvg2+","+ModeAvg3+", "+sPrice;
string sParameters = ", "+sAvg1+","+sAvg2+","+sAvg3+", "+sPrice;
IndicatorShortName("SwingMan UltraSuperTRIX_PV_v2 ("+TRIX_Period+sParameters+")");
SetIndexLabel(1,"TRIX up");
SetIndexLabel(2,"TRIX dn");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| TRIX |
//+------------------------------------------------------------------+
int start()
{
if (TRIX_Period==Signal_Period) return(0);
ArrayResize(ind_buffer1a,Bars);
ArrayResize(ind_buffer2a,Bars);
ArrayResize(ind_buffer3,Bars);
ArrayResize(ind_buffer4,Bars);
ArrayResize(ind_buffer7,Bars);
ArrayResize(ind_buffer6upPV,Bars);
ArrayResize(ind_buffer6dnPV,Bars);
ArrayResize(absHistogramBuffer,Bars);
ArrayResize(avgHistogramBuffer,Bars);
int i, limit=CountBars;
if (limit>Bars) limit=Bars-1;
//---- trix
//-- calculation
for(i=0; i<limit; i++) ind_buffer1a[i]=iMA(Symbol(),Period(),TRIX_Period,0,ModeAvg1,inputPrice,i);
for(i=0; i<limit; i++) ind_buffer2a[i]=iMAOnArray(ind_buffer1a,0,TRIX_Period,0,ModeAvg2,i);
for(i=0; i<limit; i++) ind_buffer7[i]=iMAOnArray(ind_buffer2a,0,TRIX_Period,0,ModeAvg3,i);
//-- TRIX
for(i=0; i<limit-1; i++) {
//-- Rate of change
if (ind_buffer7[i+1] != 0)
ind_buffer1a[i] = Scale * (ind_buffer7[i]-ind_buffer7[i+1]) / ind_buffer7[i+1];
}
for(i=0; i<limit-1; i++) ind_buffer2a[i]=iMAOnArray(ind_buffer1a,0,Signal_Period,0,MODE_EMA,i);
for(i=limit-1; i>=0; i--) {
double diff = ind_buffer1a[i]-ind_buffer2a[i];
ind_buffer5[i]=diff; // line
double diff2 = ind_buffer5[i] - ind_buffer5[i+1];
//-- histogram
if (diff2 >= 0) {
ind_buffer6up[i]=diff;
ind_buffer6dn[i]=EMPTY_VALUE;
}
else {
ind_buffer6up[i] =EMPTY_VALUE;
ind_buffer6dn[i]=diff;
}
//-- signals cross 0 line
if (diff >= 0) {
ind_buffer6upPV[i]=diff;
ind_buffer6dnPV[i]=EMPTY_VALUE;
}
else {
ind_buffer6upPV[i] =EMPTY_VALUE;
ind_buffer6dnPV[i]=diff;
}
//--Difference for StdDev
absHistogramBuffer[i] = MathAbs(diff);
}
//---- average differences
for(i=0; i<limit-1; i++) {
avgHistogramBuffer[i] = iMAOnArray(absHistogramBuffer,0,Period_SmoothHistograms,0,MODE_SMA,i);
HistogramLineUP[i] = avgHistogramBuffer[i] * Factor_TriggerLine;
HistogramLineDN[i] = -avgHistogramBuffer[i] * Factor_TriggerLine;
}
//---- Signals
i=limit-1;
while(i>=0)
{
//-- draw signals
if (Draw_Signals == true) {
int shift = 0;
SignalUP[i+shift] = EMPTY_VALUE;
SignalDN[i+shift] = EMPTY_VALUE;
//-- long
bool bSignalUP = (ind_buffer6upPV[i+shift] > 0 && ind_buffer6upPV[i+shift] != EMPTY_VALUE && ind_buffer6dnPV[i+1+shift] < 0);
//-- short
bool bSignalDN = (ind_buffer6dnPV[i+shift] < 0 && ind_buffer6upPV[i+1+shift] != EMPTY_VALUE && ind_buffer6upPV[i+1+shift] > 0);
if (bSignalUP == true) {
SignalUP[i+shift] = 0;
SignalDN[i+shift] = EMPTY_VALUE;
}
if (bSignalDN == true) {
SignalUP[i+shift] = EMPTY_VALUE;
SignalDN[i+shift] = 0;
}
//-- repainting ?
shift = 1;
SignalUP[i+shift] = EMPTY_VALUE;
SignalDN[i+shift] = EMPTY_VALUE;
//-- long
bSignalUP = (ind_buffer6upPV[i+shift] > 0 && ind_buffer6upPV[i+shift] != EMPTY_VALUE && ind_buffer6dnPV[i+1+shift] < 0);
//-- short
bSignalDN = (ind_buffer6dnPV[i+shift] < 0 && ind_buffer6upPV[i+1+shift] != EMPTY_VALUE && ind_buffer6upPV[i+1+shift] > 0);
if (bSignalUP == true) {
SignalUP[i+shift] = 0;
SignalDN[i+shift] = EMPTY_VALUE;
}
if (bSignalDN == true) {
SignalUP[i+shift] = EMPTY_VALUE;
SignalDN[i+shift] = 0;
}
}
//=============================================================
//-- alerts new
string st;
string sPeriod = Get_sPeriod(Period());
if (i == 0)
{
if (Alert_Signals==true || EMail_Signals == true) {
if (ind_buffer5[i] >= 0) bool bTurnUP = (ind_buffer5[i] >= 0 && ind_buffer5[i+1] < 0); else
if (ind_buffer5[i] < 0) bool bTurnDN = (ind_buffer5[i] < 0 && ind_buffer5[i+1] >= 0);
if (bTurnUP == true) {
if (TurnedUp == false) {
st = "Trix BUY: "+Symbol()+"-"+sPeriod+" at "+ DoubleToStr(Close[0],Digits)+" "+ TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS);
if (Alert_Signals == true) Alert(st);
if (EMail_Signals == true) SendMail("Trix alert",st);
TurnedUp = true;
TurnedDown = false;
}
}
else
if (bTurnDN == true) {
if (TurnedDown == false) {
st = "Trix SELL: "+Symbol()+"-"+sPeriod+" at "+ DoubleToStr(Close[0],Digits) +" "+ TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS);
if (Alert_Signals == true) Alert(st);
if (EMail_Signals == true) SendMail("Trix alert",st);
TurnedUp = false;
TurnedDown = true;
}
}
}
}
/* //-- alerts (original conditions)
if (Alert_Signals==true || EMail_Signals == true) {
if (ind_buffer2a[i]<ind_buffer1a[i] && ind_buffer2a[i+1]>=ind_buffer1a[i+1]) ind_buffer3[i]=ind_buffer2a[i]-0.0001;
if (ind_buffer2a[i]>ind_buffer1a[i] && ind_buffer2a[i+1]<=ind_buffer1a[i+1]) ind_buffer4[i]=ind_buffer2a[i]+0.0001;
if (ind_buffer3[0]==ind_buffer2a[0]-0.0001 && TurnedUp==false) {
st = "Trix BUY: "+Symbol()+"-"+sPeriod+" at "+ DoubleToStr(Close[0],Digits)+" "+ TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS);
if (Alert_Signals == true) Alert(st);
if (EMail_Signals == true) SendMail("TRIX alert",st);
TurnedDown = false;
TurnedUp = true;
}
if (ind_buffer4[0]==ind_buffer2a[0]+0.0001 && TurnedDown==false) {
st = "Trix SELL: "+Symbol()+"-"+sPeriod+" at "+ DoubleToStr(Close[0],Digits)+" "+ TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS);
if (Alert_Signals == true) Alert(st);
if (EMail_Signals == true) SendMail("TRIX alert",st);
TurnedDown = true;
TurnedUp = false;
}
}
*/
i--;
}
//---- done
return(0);
}
//+------------------------------------------------------------------+
// Get sPeriod
//+------------------------------------------------------------------+
string Get_sPeriod(int timeframe)
{
if (timeframe == PERIOD_M1) return("M1");
if (timeframe == PERIOD_M5) return("M5");
if (timeframe == PERIOD_M15) return("M15");
if (timeframe == PERIOD_M30) return("M30");
if (timeframe == PERIOD_H1) return("H1");
if (timeframe == PERIOD_H4) return("H4");
if (timeframe == PERIOD_D1) return("D1");
if (timeframe == PERIOD_W1) return("W1");
if (timeframe == PERIOD_MN1) return("MN1");
}
Comments