Author: copyright© mladen
dsl_-_macd

This script is a specialized trading indicator designed for the MetaTrader platform. It functions by analyzing price action and momentum to identify specific trends and visual signals on a chart. Below is a breakdown of its logical flow in non-technical terms:

Core Purpose

The primary goal of this tool is to generate "discontinued signal lines." Instead of just showing a standard moving average or a simple trend line, it calculates a more complex relationship between fast and slow market movements. It aims to filter out "noise" and only display clear, continuous signals when certain momentum thresholds are met.

Key Components of the Logic

1. Data Source Selection The script is highly versatile in how it "reads" price. Rather than just looking at the standard closing price of a candle, you can configure it to calculate data based on several different metrics, including:

  • Standard prices (Open, High, Low, Close).
  • Averages like Median, Typical, and Weighted prices.
  • Advanced calculations like Heikin Ashi variants, which are often used to smooth out market fluctuations for clearer trend visualization.

2. Momentum & Smoothing The logic relies on two main moving average periods (a "Fast" and a "Slow" period). By subtracting the slow movement from the fast movement, the script determines the current momentum of the market.

  • If the result is positive, it suggests upward momentum.
  • If negative, it suggests downward momentum.

3. Dynamic Thresholds (The "Levels") One of the unique features of this logic is how it handles signals. Instead of triggering a signal every time the price ticks up or down, it uses "Level" buffers.

  • It tracks whether the current momentum is significantly higher than the previous "Up" level or lower than the previous "Down" level.
  • This creates a "buffer zone," ensuring that the indicator doesn't flicker or change signals rapidly during minor price колебаन (fluctuations).

4. State Management & Visualization The script maintains a "State" for the market (e.g., looking for an upward move, a downward move, or staying neutral). It uses this state to decide what to draw on your screen:

  • Trend Identification: When the momentum breaks through a calculated level, the script identifies a change in trend.
  • Clean Plotting: The logic includes specific "Cleanup" and "Plotting" routines. These ensure that the lines drawn on your chart are clean and connected properly. It prevents overlapping signals and ensures that when a new signal is detected, the previous one is handled gracefully so the visual output remains easy for a human trader to read.

Summary for the Trader

In plain terms, this script acts as an intelligent filter. It looks at the underlying "heartbeat" of the price (using your chosen price type), measures the strength of the current move compared to the recent past, and only draws a signal on your chart when that move is strong enough to cross a specific mathematical threshold. This helps in identifying sustained trends while ignoring small, insignificant price movements.

7 Views
0 Downloads
0 Favorites
dsl_-_macd
ÿþ//------------------------------------------------------------------

#property copyright   "copyright© mladen"

#property description "discontinued signal lines rsi"

#property description "made by mladen"

#property link        "mladenfx@gmail.com"

//------------------------------------------------------------------



#property indicator_separate_window

#property indicator_buffers 7

#property indicator_color1  clrDimGray

#property indicator_color2  clrDimGray

#property indicator_color3  clrSilver

#property indicator_color4  clrLimeGreen

#property indicator_color5  clrLimeGreen

#property indicator_color6  clrOrange

#property indicator_color7  clrOrange

#property indicator_style1  STYLE_DOT

#property indicator_style2  STYLE_DOT

#property indicator_width3  2

#property indicator_width4  2

#property indicator_width5  2

#property indicator_width6  2

#property indicator_width7  2

#property strict



//

//

//

//

//



enum enPrices

{

   pr_close,      // Close

   pr_open,       // Open

   pr_high,       // High

   pr_low,        // Low

   pr_median,     // Median

   pr_typical,    // Typical

   pr_weighted,   // Weighted

   pr_average,    // Average (high+low+open+close)/4

   pr_medianb,    // Average median body (open+close)/2

   pr_tbiased,    // Trend biased price

   pr_tbiased2,   // Trend biased (extreme) price

   pr_haclose,    // Heiken ashi close

   pr_haopen ,    // Heiken ashi open

   pr_hahigh,     // Heiken ashi high

   pr_halow,      // Heiken ashi low

   pr_hamedian,   // Heiken ashi median

   pr_hatypical,  // Heiken ashi typical

   pr_haweighted, // Heiken ashi weighted

   pr_haaverage,  // Heiken ashi average

   pr_hamedianb,  // Heiken ashi median body

   pr_hatbiased,  // Heiken ashi trend biased price

   pr_hatbiased2  // Heiken ashi trend biased (extreme) price

};



extern int      FastEma      = 12;       // Fast ema period

extern int      SlowEma      = 26;       // Slow ema period

extern double   SignalPeriod = 9;        // Signal period

extern enPrices Price        = pr_close; // Price



double val[],valua[],valub[],valda[],valdb[],levelu[],leveld[],state[];



//------------------------------------------------------------------

//

//------------------------------------------------------------------

//

//

//

//

//



int OnInit()

{

   IndicatorBuffers(8);

      SetIndexBuffer(0,levelu);

      SetIndexBuffer(1,leveld);

      SetIndexBuffer(2,val);

      SetIndexBuffer(3,valua);

      SetIndexBuffer(4,valub);

      SetIndexBuffer(5,valda);

      SetIndexBuffer(6,valdb);

      SetIndexBuffer(7,state);

   IndicatorShortName("dsl macd ("+(string)FastEma+","+(string)SlowEma+", dsl period : "+(string)SignalPeriod+")");

   return(INIT_SUCCEEDED);

}

void OnDeinit(const int reason) { return; }



//------------------------------------------------------------------

//

//------------------------------------------------------------------

//

//

//

//

//



int OnCalculate (const int       rates_total,

                 const int       prev_calculated,

                 const datetime& time[],

                 const double&   open[],

                 const double&   high[],

                 const double&   low[],

                 const double&   close[],

                 const long&     tick_volume[],

                 const long&     volume[],

                 const int&      spread[])

{

   int limit=MathMax(rates_total-prev_calculated-1,0);



   //

   //

   //

   //

   //



   double alpha = 2.0/(1.0+SignalPeriod);

      if (state[limit]== 1) CleanPoint(limit,valua,valub);

      if (state[limit]==-1) CleanPoint(limit,valda,valdb);

      int i=limit; for(; i>=0 && !_StopFlag; i--)

      {

         double price = getPrice(Price,open,close,high,low,i,Bars);

         val[i]    = iEma(price,FastEma,i,Bars,0)-iEma(price,SlowEma,i,Bars,1);

         levelu[i] = (i<Bars-1) ? (val[i]>0) ? levelu[i+1]+alpha*(val[i]-levelu[i+1]) : levelu[i+1] : 0;

         leveld[i] = (i<Bars-1) ? (val[i]<0) ? leveld[i+1]+alpha*(val[i]-leveld[i+1]) : leveld[i+1] : 0;

         state[i]  = (val[i]>levelu[i]) ? 1 : (val[i]<leveld[i]) ? -1 :  0;

         valda[i]  = EMPTY_VALUE;

         valdb[i]  = EMPTY_VALUE;

         valua[i]  = EMPTY_VALUE;

         valub[i]  = EMPTY_VALUE;

            if (state[i]== 1) PlotPoint(i,valua,valub,val);

            if (state[i]==-1) PlotPoint(i,valda,valdb,val);

      }

   return(rates_total-i-1);

}



//------------------------------------------------------------------

//

//------------------------------------------------------------------

//

//

//

//

//

//



double workEma[][2];

double iEma(double price, double period, int r, int bars, int instanceNo=0)

{

   if (ArrayRange(workEma,0)!= bars) ArrayResize(workEma,bars); r=bars-r-1;



   //

   //

   //

   //

   //

      

   workEma[r][instanceNo] = price;

   if (r>0 && period>1)

          workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]);

   return(workEma[r][instanceNo]);

}



//------------------------------------------------------------------

//

//------------------------------------------------------------------

//

//

//

//

//

//



#define _priceInstances     1

#define _priceInstancesSize 4

double workHa[][_priceInstances*_priceInstancesSize];

double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int bars, int instanceNo=0)

{

  if (tprice>=pr_haclose)

   {

      if (ArrayRange(workHa,0)!= bars) ArrayResize(workHa,bars); instanceNo*=_priceInstancesSize; int r = bars-i-1;

         

         //

         //

         //

         //

         //

         

         double haOpen;

         if (r>0)

                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;

         else   haOpen  = (open[i]+close[i])/2;

         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;

         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));

         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));



         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 

         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 

                                workHa[r][instanceNo+2] = haOpen;

                                workHa[r][instanceNo+3] = haClose;

         //

         //

         //

         //

         //

         

         switch (tprice)

         {

            case pr_haclose:     return(haClose);

            case pr_haopen:      return(haOpen);

            case pr_hahigh:      return(haHigh);

            case pr_halow:       return(haLow);

            case pr_hamedian:    return((haHigh+haLow)/2.0);

            case pr_hamedianb:   return((haOpen+haClose)/2.0);

            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);

            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);

            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);

            case pr_hatbiased:

               if (haClose>haOpen)

                     return((haHigh+haClose)/2.0);

               else  return((haLow+haClose)/2.0);        

            case pr_hatbiased2:

               if (haClose>haOpen)  return(haHigh);

               if (haClose<haOpen)  return(haLow);

                                    return(haClose);        

         }

   }

   

   //

   //

   //

   //

   //

   

   switch (tprice)

   {

      case pr_close:     return(close[i]);

      case pr_open:      return(open[i]);

      case pr_high:      return(high[i]);

      case pr_low:       return(low[i]);

      case pr_median:    return((high[i]+low[i])/2.0);

      case pr_medianb:   return((open[i]+close[i])/2.0);

      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);

      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);

      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);

      case pr_tbiased:   

               if (close[i]>open[i])

                     return((high[i]+close[i])/2.0);

               else  return((low[i]+close[i])/2.0);        

      case pr_tbiased2:   

               if (close[i]>open[i]) return(high[i]);

               if (close[i]<open[i]) return(low[i]);

                                     return(close[i]);        

   }

   return(0);

}   



//-------------------------------------------------------------------

//                                                                  

//-------------------------------------------------------------------

//

//

//

//

//



void CleanPoint(int i,double& first[],double& second[])

{

   if (i>=Bars-2) return;

   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))

        second[i+1] = EMPTY_VALUE;

   else

      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))

          first[i+1] = EMPTY_VALUE;

}



void PlotPoint(int i,double& first[],double& second[],double& from[])

{

   if (i>=Bars-2) return;

   if (first[i+1] == EMPTY_VALUE)

      if (first[i+2] == EMPTY_VALUE) 

            { first[i]  = from[i]; first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }

      else  { second[i] = from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }

   else     { first[i]  = from[i];                          second[i] = EMPTY_VALUE; }

}

Comments