Heiken_Ashi_LSMA_Smoothed

Download script
Author: Copyright � 2006, Forex-TSD.com
Heiken_Ashi_LSMA_Smoothed

This 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.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
9 Views
0 Downloads
0 Favorites
Heiken_Ashi_LSMA_Smoothed
//+------------------------------------------------------------------+
//|                                         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