MA_with_canal

Download script
Author: Copyright � 2009, ������ ������ ������������
MA_with_canal

This script is designed as a technical analysis tool for the MetaTrader platform, specifically created to help traders visualize price trends and volatility through a dynamic "channel" system. Instead of showing just a single moving average line, it creates a corridor that adapts to market movements.

Core Logic Overview

The indicator functions by calculating three distinct lines on your chart: a central trend line (the Moving Average) and two outer boundary lines (the high and low limits of the channel).

1. The Central Trend (Moving Average) At its foundation, the script calculates a standard Moving Average (MA). It allows users to choose between different calculation methods (such as Simple, Exponential, Smoothed, or Linear Weighted) and decide which price data points to use (e.g., Close price, High price, Low price, etc.). This serves as the "spine" of the indicator, representing the general direction of the market.

2. The Dynamic Channel (Volatility Measurement) What makes this script unique is its "canal" logic. It measures the average range of price movement (the difference between the High and Low prices) over a specific period.

  • The script calculates the average size of these candles.
  • It then multiplies that average by a user-defined coefficient.
  • This result determines the width of the channel.

3. The Visual Boundaries Finally, the script combines these two pieces of information to draw three lines on the chart:

  • Upper Limit: The Moving Average plus the calculated channel width.
  • Lower Limit: The Moving Average minus the calculated channel width.
  • Center Line: The standard Moving Average itself.

User Experience and Safety Features

The script includes several "quality of life" features to ensure it runs smoothly for the user:

  • Input Validation: Before performing any calculations, the script checks if the settings provided by the user are valid (for example, ensuring that periods are not negative). If an incorrect value is entered, the script generates on-screen error messages and provides advice on the correct range of values.
  • Real-time Information Display: The script displays a summary in the corner of the screen. This tells the user exactly which parameters are currently active—such as the moving average period, the calculation method used, and the current "active" width of the channel based on recent market data.
  • Dynamic Adaptation: Because the channel width is based on the average range of candles, the "corridor" will automatically expand during periods of high volatility (large price swings) and contract during periods of low volatility (quiet markets).
Indicators Used
Moving average indicator
10 Views
0 Downloads
0 Favorites
MA_with_canal
//+------------------------------------------------------------------+
//|                                                MA_with_canal.mq4 |
//|                     Copyright © 2009, Áóãàåâ Äàíèèë Âëàäèìèðîâè÷ |
//|                                         e-mail: buga1922@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Áóãàåâ Äàíèèë Âëàäèìèðîâè÷"
#property link "mailto:buga1922@mail.ru"

#property indicator_chart_window          // Ñòðîèì èíäèêàòîð â ãëàâíîì îêíå
#property indicator_buffers 3             // Êîëè÷åñòâî èñïîëüçóåìûõ áóôåðîâ = 3
#property indicator_color1 Red            // Öâåò 1-îé ëèíèè - êðàñíûé
#property indicator_color2 Red            // Öâåò 2-îé ëèíèè - êðàñíûé
#property indicator_color3 Red            // Öâåò 3-åé ëèíèè - êðàñíûé
#property indicator_width3  2             // Òîëùèíà òðåòüåé ëèíèè - 2

// Ìàññèâû äëÿ õðàíåíèÿ çíà÷åíèé èíäèêàòîðà
double Buffer1[],
       Buffer2[],
       Buffer3[];

// Çàäàâàåìûå ïîëüçîâàòåëåì ïåðåìåííûå

extern double ma_canal = 2;               // Êîýôôèöèåíò èñïîëüçóåìûé äëÿ ðàññ÷åòà øèðèíû êàíàëà (ma_canal*ñðåäíèé_ðàçìåð_ñâå÷è)
extern int    ma_period = 21,             // Ïåðèîä äëÿ ðàññ÷åòà ñêîëüçÿùåé ñðåäíåé
              ma_method=3,                // Ìåòîä ðàññ÷åòà ñðåäíåé 0-ïðîñòàÿ SMA, 1-ýêñïîòåíöèàëüíàÿ EMA, 2-ñãëàæåííàÿ SMMA,
                                          //  3-ëèíåéíî-âçâåøåííàÿ LWMA
              ma_cena=0;                  // Öåíû ïî êîòîðûì ñòðîèòñÿ ÌÀ 0-öåíà çàêðûòèÿ, 1-öåíà îòêðûòèÿ, 2-ìàêñèìàëüíàÿ, 3-ìèíèìàëüíàÿ,
                                          //  4-ñðåäíÿÿ, 5-òèïè÷íàÿ, 6-âçâåøåííàÿ öåíà çàêðûòèÿ
                                          
// Ïåðåìåííûå äëÿ îòîáðàæåíèÿ íàñòðîåê èíäèêàòîðà
string ma_method_str,ma_cena_str;                                     

                         //---ÏÎËÜÇÎÂÀÒÅËÜÑÊÈÅ ÔÓÍÊÖÈÈ---//
                         
// Ôóíêöèÿ, ïîìîãàþùàÿ âûâåñòè íàñòðîéêè èíäèêàòîðà
void PARAMETRY()
 {
  switch(ma_method)
   {
    case 0:  ma_method_str = "ïðîñòàÿ ñðåäíÿÿ (SMA)";             break;
    case 1:  ma_method_str = "ýêñïîòåíöèàëüíàÿ ñðåäíÿÿ (EMA)";    break;
    case 2:  ma_method_str = "ñãëàæåííàÿ ñðåäíÿÿ (SMMA)";         break;
    case 3:  ma_method_str = "ëèíåéíî-âçâåøåííàÿ ñðåäíÿÿ (LWMA)"; break;
    default: ma_method_str = "ââåäåí íåêîððåêòíûé ïàðàìåòð";      break;
   }
  switch(ma_cena)
   {
    case 0:  ma_cena_str = "öåíà çàêðûòèÿ (PRICE_CLOSE)";               break;
    case 1:  ma_cena_str = "öåíà îòêðûòèÿ (PRICE_OPEN)";                break;
    case 2:  ma_cena_str = "ìàêñèìàëüíàÿ öåíà (PRICE_HIGH)";            break;
    case 3:  ma_cena_str = "ìèíèìàëüíàÿ öåíà (PRICE_LOW)";              break;
    case 4:  ma_cena_str = "ñðåäíÿÿ öåíà (PRICE_MEDIAN)";               break;
    case 5:  ma_cena_str = "òèïè÷íàÿ öåíà (PRICE_TYPICAL)";             break;
    case 6:  ma_cena_str = "âçâåøåííàÿ öåíà çàêðûòèÿ (PRICE_WEIGHTED)"; break;
    default: ma_cena_str = "ââåäåí íåêîððåêòíûé ïàðàìåòð";              break;
   }
 }

// Ôóíêöèÿ âûïîëíÿåò ïðîâåðêó íà êîððåêòíîñòü ââåäåííûõ ïàðàìåòðîâ,
//  â ñëó÷àå íåîáõîäèìîñòè âûâîäèò îøèáêó. Âîçâðàùàåò true, åñëè âñå ïàðàìåòðû êîððåêòíû.
bool PROVERKA()
 {
  // Óäàëÿåì ñóùåñòâóþùèå ñîîáùåíèÿ îá îøèáêå
  ObjectDelete("error"); 
  ObjectDelete("advice");
  return(true);
  // Ïðîèçâîäèì ïðîâåðêó íà íàëè÷èå îøèáîê
  if ( ma_canal < 0)
   {
    VYVOD(": Èçìåíèòå ïàðàìåòð ma_canal.","Ïàðàìåòð äîëæåí áûòü ïîëîæèòåëüíûì");return(false);
   }
  else 
   {
    if ( ( ma_period < 0) || ( ma_period > Bars-2) )
     {
      VYVOD(": Èçìåíèòå ïàðàìåòð ma_period.","Çíà÷åíèå ïàðàìåòðà äîëæíî ïðèíàäëåæàòü äèàïàçîíó [0;"+(Bars-2)+"]");return(false);
     }
    else
     {
      if ( ( ma_method < 0) || ( ma_method > 3) )
       {
        VYVOD(": Èçìåíèòå ïàðàìåòð ma_method.","Çíà÷åíèå ïàðàìåòðà äîëæíî ïðèíàäëåæàòü äèàïàçîíó [0;3]");return(false);
       }
      else
       {
        if ( ( ma_cena < 0) || ( ma_cena > 6) )
         {
          VYVOD(": Èçìåíèòå ïàðàìåòð ma_cena.","Çíà÷åíèå ïàðàìåòðà äîëæíî ïðèíàäëåæàòü äèàïàçîíó [0;6]");return(false);
         }
       } 
     }
   }
 }  

// Ôóíêöèÿ âûâîäèò èíôîðìàöèþ îòíîñèòåëüíî íåêîððåêòíûõ ïàðàìåòðàõ èíäèêàòîðà
void VYVOD(string error, string advice)
 {
  ObjectCreate  ( "error", OBJ_LABEL,0,0,0);                                 // Ñîçäàåì ìåòêó, êîòîðàÿ áóäåò ñîîáùàòü î
                                                                             //  íåêîððåêòíûõ çàäàííûõ ïàðàìåòðàõ
  ObjectSetText ( "error", "Èíäèêàòîð MA_with_canal"+error,12,"Arial", Red); // Çàäàåì òåêñò ìåòêè îá îøèáêå
  ObjectSet     ( "error", OBJPROP_CORNER,    1);                            // Çàäàåì óãîë ïðèâÿçêè ìåòêè (ïðàâûé âåðõíèé)
  ObjectSet     ( "error", OBJPROP_XDISTANCE,15);                            // Çàäàåì ñäâèã îòíîñèòåëüíî ìåòêè ïî ãîðèçîíòàëè
  ObjectSet     ( "error", OBJPROP_YDISTANCE,15);                            // Çàäàåì ñäâèã îòíîñèòåëüíî ìåòêè ïî âåðòèêàëè
  
  ObjectCreate  ( "advice", OBJ_LABEL,0,0,0);                                // Ñîçäàåì ìåòêó, êîòîðàÿ áóäåò ñîîáùàòü ðåêîìåíäàöèè
                                                                             //  î äîïóñòèìîì äèàïàçîíå ïàðàìåòðîâ
  ObjectSetText ( "advice", advice,12,"Arial", Red);                         // Çàäàåì òåêñò ìåòêè ñ ðåêîìåíäàöèÿìè
  ObjectSet     ( "advice", OBJPROP_CORNER,    1);                           // Çàäàåì óãîë ïðèâÿçêè ìåòêè (ïðàâûé âåðõíèé)          
  ObjectSet     ( "advice", OBJPROP_XDISTANCE,15);                           // Çàäàåì ñäâèã îòíîñèòåëüíî ìåòêè ïî ãîðèçîíòàëè
  ObjectSet     ( "advice", OBJPROP_YDISTANCE,40);                           // Çàäàåì ñäâèã îòíîñèòåëüíî ìåòêè ïî âåðòèêàëè
 }

double canal(int lag)
 {
  int i;
  double sum=0;
  for (i=lag; i<=lag+ma_period; i++)  sum=sum+(High[i]-Low[i]);
  return(sum/ma_period*ma_canal);
 }
 
// Ôóíêöèÿ ïðîèçâîäèò ðàññ÷åò çíà÷åíèé èíäèêàòîðà
void RASSCHET(int counted_bars)
  {
   double MA;
   int bars=counted_bars-1;
   while ( bars > 0 )
      {
       MA=iMA(Symbol(),0,ma_period,0,ma_method,ma_cena,bars);
       Buffer1[bars]=( MA + canal(bars));
       Buffer2[bars]=( MA - canal(bars));
       Buffer3[bars]=MA;
       bars--;
      }
  }

// Ôóíêöèÿ èíèöèàëèçàöèè
void init()
  {
   // Óñòàíàâëèâàåì ñòèëü îòðèñîâêè - ïðîñòàÿ ëèíèÿ,ñòèëü ëèíèè - ñïëîøíàÿ, äëÿ âñåõ ëèíèé èíäèêàòîðà
   SetIndexStyle (0, DRAW_LINE, STYLE_SOLID); 
   SetIndexStyle (1, DRAW_LINE, STYLE_SOLID);
   SetIndexStyle (2, DRAW_LINE, STYLE_SOLID);
   
   // Ñâÿçûâàåì ìàññèâû Buffer ñ áóôåðàìè ïîëüçîâàòåëüñêîãî èíäèêàòîðà
   SetIndexBuffer (0, Buffer1);              
   SetIndexBuffer (1, Buffer2);
   SetIndexBuffer (2, Buffer3);
  
   // Çàäàåì èìÿ ëèíèé èíäèêàòîðà
   SetIndexLabel (0, "high_limit");
   SetIndexLabel (1, "low_limit");
   SetIndexLabel (2, "MA");
   
   // Çàäàåì êîðîòêîå èìÿ èíäèêàòîðà
   IndicatorShortName("MA_with_canal ("+ma_period+";"+ DoubleToStr(ma_canal,1)+")");
   
   PARAMETRY(); // Îïðåäåëÿåì êàêèì ñïîñîáîì ïðîèçâîäèòñÿ ðàññ÷åò ñêîëüçÿùåé ñðåäíåé
  }

// Ôóíêöèÿ äåèíèöèàëèçàöèè
void deinit()
  { 
   // Óäàëÿåì âûâåäåííûå êîììåíòàðèè è ñîîáùåíèå îá îøèáêå
   Comment("");
   ObjectDelete("error"); 
   ObjectDelete("advice");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
void start()
  {
   int counted_bars=IndicatorCounted();
   if ( PROVERKA() == true)
    {
     RASSCHET(counted_bars);
    }
   Comment("Èíäèêàòîð MA_with_canal\nÏåðèîä ñêîëüçÿùåé ñðåäíåé="+ma_period+
           "; Êîýôôèöèåíò äëÿ ðàññ÷åòà êàíàëà="+DoubleToStr(ma_canal,1)+
           "\nÄëÿ ðàññ÷åòà ÌÀ èñïîëüçîâàëàñü "+ma_cena_str+
           "\nÌåòîä âû÷èñëåíèÿ ñêîëüçÿùåé ñðåäíåé - "+ma_method_str+
           "\nÔàêòè÷åñêàÿ øèðèíà êàíàëà="+DoubleToStr(canal(0),4));
  }
 
//+------------------------------------------------------------------+

Comments