Heiken_Ashi_LSMA_Smoothed
Download scriptThis indicator is designed to provide a smoother, more refined view of price action on a trading chart. It works by combining two popular charting concepts: Heiken Ashi candles and Linear Weighted Moving Averages (LSMA).
Instead of showing you the raw, often "noisy" price fluctuations of every second, this tool processes the data through multiple layers of smoothing to help traders identify the underlying trend more clearly. Here is a breakdown of how that logic works:
1. The Foundation: Linear Smoothing
The script begins by calculating a Linear Weighted Moving Average (LSMA) for four specific price points: the Open, High, Low, and Close of the candles. Unlike a simple average where every day carries equal weight, this method gives more importance to the most recent data. This helps the indicator react more quickly to new price movements while still filtering out minor "jitter."
2. Constructing the "Heiken Ashi" Logic
Once these smoothed values are established, the script uses them to build "synthetic" candles. Rather than using the actual market prices, it calculates:
- A Synthetic Open: Based on averaged values from previous calculations.
- A Synthetic Close: Derived from the average of the smoothed Open, High, Low, and Close prices.
- Synthetic Highs and Lows: Determined by comparing the smoothed price points to ensure the candle boundaries encompass all relevant price activity.
By using these synthetic values, the script creates a visual representation where the trend (upward or downward) is more distinct and less interrupted by "wicks" or minor retracements that don't change the overall direction.
3. The Final Polish: Double Smoothing
To ensure the final visual output is as clean as possible, the script performs one final layer of processing. It takes the data derived from the Heiken Ashi calculations and applies a second moving average to it.
This two-step "smoothing of a smoothed value" serves two purposes:
- Noise Reduction: It eliminates erratic price spikes that can often trigger false signals.
- Trend Clarity: It highlights the momentum of the market. Because the final result is plotted as a histogram, it allows you to see the strength and direction of the trend at a glance—making it easier to identify when a trend is gaining power or beginning to exhaust itself.
Summary for the Trader
In simple terms, this tool takes raw market data, smooths it out to remove "noise," converts it into a cleaner candle-like format, and then smooths it one last time. The result is a visual guide that emphasizes the current trend direction, helping you stay on the right side of the market move without getting distracted by minor price fluctuations.
//+------------------------------------------------------------------+
//| Heiken Ashi Smoothed.mq4 |
//+------------------------------------------------------------------+
//| mod by Raff |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Forex-TSD.com "
#property link "http://www.forex-tsd.com/"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Red
#property indicator_color2 RoyalBlue
#property indicator_color3 Red
#property indicator_color4 RoyalBlue
//---- parameters
//extern int MaMetod = 2;
extern int MaPeriod = 6;
extern int MaMetod2 = 3;
extern int MaPeriod2 = 2;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];
double ExtMapBuffer5[];
double ExtMapBuffer6[];
double ExtMapBuffer7[];
double ExtMapBuffer8[];
//----
int ExtCountedBars=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//|------------------------------------------------------------------|
int init()
{
//---- indicators
IndicatorBuffers(8);
SetIndexStyle(0,DRAW_HISTOGRAM, 0, 1, Red);
SetIndexBuffer(0, ExtMapBuffer1);
SetIndexStyle(1,DRAW_HISTOGRAM, 0, 1, RoyalBlue);
SetIndexBuffer(1, ExtMapBuffer2);
SetIndexStyle(2,DRAW_HISTOGRAM, 0, 3, Red);
SetIndexBuffer(2, ExtMapBuffer3);
SetIndexStyle(3,DRAW_HISTOGRAM, 0, 3, RoyalBlue);
SetIndexBuffer(3, ExtMapBuffer4);
//----
SetIndexDrawBegin(0,5);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexBuffer(2,ExtMapBuffer3);
SetIndexBuffer(3,ExtMapBuffer4);
SetIndexBuffer(4,ExtMapBuffer5);
SetIndexBuffer(5,ExtMapBuffer6);
SetIndexBuffer(6,ExtMapBuffer7);
SetIndexBuffer(7,ExtMapBuffer8);
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//---- TODO: add your code here
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
double maOpen, maClose, maLow, maHigh;
double haOpen, haHigh, haLow, haClose;
if(Bars<=10) return(0);
ExtCountedBars=IndicatorCounted();
//---- check for possible errors
if (ExtCountedBars<0) return(-1);
//---- last counted bar will be recounted
if (ExtCountedBars>0) ExtCountedBars--;
int pos=Bars-ExtCountedBars-1;
while(pos>=0)
{
//maOpen=iMA(NULL,0,MaPeriod,0,MaMetod,MODE_OPEN,pos);
//maClose=iMA(NULL,0,MaPeriod,0,MaMetod,MODE_CLOSE,pos);
//maLow=iMA(NULL,0,MaPeriod,0,MaMetod,MODE_LOW,pos);
//maHigh=iMA(NULL,0,MaPeriod,0,MaMetod,MODE_HIGH,pos);
maOpen =LSMA(pos,MaPeriod,MODE_OPEN);
maClose=LSMA(pos,MaPeriod,MODE_CLOSE);
maLow =LSMA(pos,MaPeriod,MODE_LOW);
maHigh =LSMA(pos,MaPeriod,MODE_HIGH);
haOpen=(ExtMapBuffer5[pos+1]+ExtMapBuffer6[pos+1])/2;
haClose=(maOpen+maHigh+maLow+maClose)/4;
haHigh=MathMax(maHigh, MathMax(haOpen, haClose));
haLow=MathMin(maLow, MathMin(haOpen, haClose));
if (haOpen<haClose)
{
ExtMapBuffer7[pos]=haLow;
ExtMapBuffer8[pos]=haHigh;
}
else
{
ExtMapBuffer7[pos]=haHigh;
ExtMapBuffer8[pos]=haLow;
}
ExtMapBuffer5[pos]=haOpen;
ExtMapBuffer6[pos]=haClose;
pos--;
}
int i;
for(i=0; i<Bars; i++) ExtMapBuffer1[i]=iMAOnArray(ExtMapBuffer7,Bars,MaPeriod2,0,MaMetod2,i);
for(i=0; i<Bars; i++) ExtMapBuffer2[i]=iMAOnArray(ExtMapBuffer8,Bars,MaPeriod2,0,MaMetod2,i);
for(i=0; i<Bars; i++) ExtMapBuffer3[i]=iMAOnArray(ExtMapBuffer5,Bars,MaPeriod2,0,MaMetod2,i);
for(i=0; i<Bars; i++) ExtMapBuffer4[i]=iMAOnArray(ExtMapBuffer6,Bars,MaPeriod2,0,MaMetod2,i);
//----
return(0);
}
//+------------------------------------------------------------------+
double LSMA(int mybar, int myperiod, int myprice)
{
int i;
double sum=0;
double lengthvar = ( myperiod + 1.0 ) / 3.0;
for(i = myperiod; i >= 1 ; i--)
{
if(myprice==0) sum += ( i - lengthvar)*Open[myperiod - i + mybar];
if(myprice==1) sum += ( i - lengthvar)*Close[myperiod - i + mybar];
if(myprice==2) sum += ( i - lengthvar)*High[myperiod - i + mybar];
if(myprice==3) sum += ( i - lengthvar)*Low[myperiod - i + mybar];
}
return(sum * 6 / (myperiod*(myperiod + 1)) );
}
Comments