MAChannel_Close_MultiTF_AD

Author: Scriptong
Price Data Components
Series array that contains the lowest prices of each barSeries array that contains the highest prices of each barSeries array that contains close prices for each bar
Indicators Used
Moving average indicator
Miscellaneous
It issuies visual alerts to the screenImplements a curve of type %1
0 Views
0 Downloads
0 Favorites
MAChannel_Close_MultiTF_AD
#property copyright "Scriptong"
#property link      "http://advancetools.net"
#property description "English: Horizontal channel, based on extremums between the crossing of the two Moving Averages. Multi timeframes version.\nRussian: Ãîðèçîíòàëüíûé êàíàë, îïèðàþùèéñÿ íà ýêñòðåìóìû ìåæäó ïåðåñå÷åíèÿìè äâóõ Moving Average. Ìóëüòèïåðèîäíàÿ âåðñèÿ."
#property strict

#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 clrBlue
#property indicator_color2 clrRed
#property indicator_color3 clrBlue
#property indicator_color4 clrRed
#property indicator_color5 clrNONE

#property indicator_width1 2
#property indicator_width2 2

#property  indicator_style3 STYLE_DOT
#property  indicator_style4 STYLE_DOT

#define TF_AMOUNT                                        9
#define START_Y_OFFSET                                   12
#define STEP_Y                                           15
#define START_X_OFFSET                                   12
#define STEP_X                                           23
#define FONT_SIZE_TEXT                                   8
#define FONT_SIZE_ARROW                                  10
#define FONT_NAME_TEXT                                   "Constantia"
#define FONT_NAME_ARROW                                  "Wingdings"
#define PREFIX                                           "MACCMTF_"

#define LABEL_TF_NAME                                    "TF_NAME_"
#define LABEL_TREND                                      "TREND_"
#define LABEL_PRICE_LOC                                  "PRICE_LOC_"
#define VERT_LINE                                        "VERT_LINE"

#define VERT_LINE_COLOR                                  clrDodgerBlue
#define VERT_LINE_STYLE                                  STYLE_DOT

enum ENUM_YESNO
{
   NO,                                                                                             // No / Íåò
   YES                                                                                             // Yes / Äà   
};

input    uint                 i_maFastPeriod             = 1;                                      // Period of fast MA / Ïåðèîä ðàñ÷åòà áûñòðîé ÌÀ
input    ENUM_MA_METHOD       i_maFastMethod             = MODE_SMA;                               // Method of fast MA / Ìåòîä ðàñ÷åòà áûñòðîé ÌÀ
input    ENUM_APPLIED_PRICE   i_maFastPrice              = PRICE_WEIGHTED;                         // Applied price of fast MA / Öåíà ðàñ÷åòà áûñòðîé ÌÀ
input    uint                 i_maSlowPeriod             = 21;                                     // Period of slow MA / Ïåðèîä ðàñ÷åòà ìåäëåííîé ÌÀ
input    ENUM_MA_METHOD       i_maSlowMethod             = MODE_EMA;                               // Method of slow MA / Ìåòîä ðàñ÷åòà ìåäëåííîé ÌÀ
input    ENUM_APPLIED_PRICE   i_maSlowPrice              = PRICE_WEIGHTED;                         // Applied price od slow MA / Öåíà ðàñ÷åòà ìåäëåííîé ÌÀ
input    ENUM_BASE_CORNER     i_corner                   = CORNER_RIGHT_UPPER;                     // Corner for the summary / Óãîë äëÿ îòîáðàæåíèÿ ñàììàðè
input    ENUM_YESNO           i_useM1                    = YES;                                    // Show the data of M1 TF / Îòîáðàæàòü äàííûå ÒÔ Ì1
input    ENUM_YESNO           i_useM5                    = YES;                                    // Show the data of M5 TF / Îòîáðàæàòü äàííûå ÒÔ Ì5
input    ENUM_YESNO           i_useM15                   = YES;                                    // Show the data of M15 TF / Îòîáðàæàòü äàííûå ÒÔ Ì15
input    ENUM_YESNO           i_useM30                   = YES;                                    // Show the data of M30 TF / Îòîáðàæàòü äàííûå ÒÔ Ì30
input    ENUM_YESNO           i_useH1                    = YES;                                    // Show the data of H1 TF / Îòîáðàæàòü äàííûå ÒÔ H1
input    ENUM_YESNO           i_useH4                    = YES;                                    // Show the data of H4 TF / Îòîáðàæàòü äàííûå ÒÔ H4
input    ENUM_YESNO           i_useD1                    = YES;                                    // Show the data of D1 TF / Îòîáðàæàòü äàííûå ÒÔ D1
input    ENUM_YESNO           i_useW1                    = YES;                                    // Show the data of W1 TF / Îòîáðàæàòü äàííûå ÒÔ W1
input    ENUM_YESNO           i_useMN1                   = YES;                                    // Show the data of MN1 TF / Îòîáðàæàòü äàííûå ÒÔ ÌN1
input    color                i_upwardTrendColor         = clrBlue;                                // Color of arrow up / Öâåò ñòðåëêè ââåðõ
input    color                i_downwardTrendColor       = clrRed;                                 // Color of arrow down / Öâåò ñòðåëêè âíèç
input    color                i_undefinedTrendColor      = clrLime;                                // Color of arrow right / Öâåò ñòðåëêè âïðàâî
input    color                i_textColor                = clrGreen;                               // Color of table header / Öâåò øàïêè òàáëèöû
input    ENUM_YESNO           i_showFocusBar             = YES;                                    // Show the selected bar? / Îòîáðàæàòü ëè âûáðàííûé áàð?
input    int                  i_indBarsCount             = 10000;                                  // Number of bars to display / Êîë-âî áàðîâ îòîáðàæåíèÿ

enum ENUM_TREND_TYPE
{
   TREND_TYPE_NONE,
   TREND_TYPE_UPWARD,
   TREND_TYPE_DOWNWARD
};

enum ENUM_MESSAGE_CODE
{
   MESSAGE_CODE_MA_FAST_LESS_THAN_ZERO,
   MESSAGE_CODE_MA_SLOW_LESS_THAN_ZERO,
   MESSAGE_CODE_TERMINAL_FATAL_ERROR1,
   MESSAGE_CODE_BIND_ERROR
};

struct TFInfo
{
   bool            isShow;
   ENUM_TIMEFRAMES tf;
   string          tfName;
   double          highLimit;
   double          lowLimit;
   ENUM_TREND_TYPE curTrend;
};

// Global variables
bool g_activate;

int      g_maxMAPeriod;

datetime g_focusBarTime;                                                                            

double   g_point,                                                                                  
         g_delta;              
         
ENUM_ANCHOR_POINT g_anchor;                                                                             
         
TFInfo   g_tfInfo[TF_AMOUNT];

// Arrays for buffers of the indicators
double g_highSolid[];                                                                              
double g_lowSolid[];                                                                               
double g_highDot[];                                                                                
double g_lowDot[];                                                                                 
double g_curTrend[];

//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
   g_activate = false;
   
   if (!TuningParameters())                        
      return INIT_FAILED;    
      
   FormTheTFArray();                      
       
   if (!BuffersBind())                             
      return INIT_FAILED;  
      
   g_anchor = (i_corner == CORNER_RIGHT_UPPER || i_corner == CORNER_LEFT_UPPER)? ANCHOR_UPPER : ANCHOR_LOWER;  
   g_focusBarTime = 0;  
   if (i_showFocusBar == YES)
      ShowVLine(Time[0]);
     
   ShowSummaryTitle();                        
                                                   
   g_activate = true;
   
   return INIT_SUCCEEDED;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the correctness of values of tuning parameters                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool TuningParameters()
{
   string name = WindowExpertName();

   if (i_maFastPeriod < 1)
   {
      Alert(name, GetStringByMessageCode(MESSAGE_CODE_MA_FAST_LESS_THAN_ZERO));
      return false;
   } 
   
   if (i_maSlowPeriod < 1)
   {
      Alert(name, GetStringByMessageCode(MESSAGE_CODE_MA_SLOW_LESS_THAN_ZERO));
      return false;
   } 

   g_point = Point;
   g_delta = -g_point / 10;
   if (g_point == 0)
   {
      Alert(name, GetStringByMessageCode(MESSAGE_CODE_TERMINAL_FATAL_ERROR1));
      return false;
   } 
   
   g_maxMAPeriod = (int)MathMax(i_maFastPeriod, i_maSlowPeriod);
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Formation the data of the TFs array                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void FormTheTFArray()
{
   SaveTheTF(0, i_useM1 == YES, PERIOD_M1, "M1");
   SaveTheTF(1, i_useM5 == YES, PERIOD_M5, "M5");
   SaveTheTF(2, i_useM15 == YES, PERIOD_M15, "M15");
   SaveTheTF(3, i_useM30 == YES, PERIOD_M30, "M30");
   SaveTheTF(4, i_useH1 == YES, PERIOD_H1, "H1");
   SaveTheTF(5, i_useH4 == YES, PERIOD_H4, "H4");
   SaveTheTF(6, i_useD1 == YES, PERIOD_D1, "D1");
   SaveTheTF(7, i_useW1 == YES, PERIOD_W1, "W1");
   SaveTheTF(8, i_useMN1 == YES, PERIOD_MN1, "MN1");
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Save the data of one TF                                                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void SaveTheTF(const int index, const bool isShow, const ENUM_TIMEFRAMES tf, const string tfName)
{
   g_tfInfo[index].isShow = isShow;
   g_tfInfo[index].tf = tf;
   g_tfInfo[index].tfName = tfName;   
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show one TF name                                                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowOneTFName(const int tfIndex, const int yCoord, int& xCoord)
{
   if (!g_tfInfo[tfIndex].isShow)
      return;
      
   ShowLabel(LABEL_TF_NAME + (string)tfIndex, xCoord, yCoord, g_tfInfo[tfIndex].tfName, i_textColor, FONT_NAME_TEXT, FONT_SIZE_TEXT);
   xCoord += STEP_X;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show the title for summary                                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowSummaryTitle()
{
   int y = START_Y_OFFSET;
   if (i_corner == CORNER_RIGHT_LOWER || i_corner == CORNER_LEFT_LOWER)
      y += 2 * STEP_Y;

   int x = START_X_OFFSET;
   
   if (i_corner == CORNER_RIGHT_LOWER || i_corner == CORNER_RIGHT_UPPER)
   {
      for (int  i = TF_AMOUNT - 1; i >= 0; i--)
         ShowOneTFName(i, y, x);
   }
   else
      for (int i = 0; i < TF_AMOUNT; i++)
         ShowOneTFName(i, y, x);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator deinitialization function                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   DeleteObjectsAll();
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Deleting the objects created by program                                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void DeleteObjectsAll()
{
   for (int i = ObjectsTotal() - 1; i >= 0; i--)     
      if (StringSubstr(ObjectName(i), 0, StringLen(PREFIX)) == PREFIX)
         ObjectDelete(ObjectName(i));
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Binding of array and the indicator buffers                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool BuffersBind()
{
   string name = WindowExpertName();
   
   // Ñâÿçûâàíèå áóôåðîâ èíäèêàòîðà ñ ìàññèâàìè
   if (!SetIndexBuffer(0, g_highSolid)                      ||
       !SetIndexBuffer(1, g_lowSolid)                       ||
       !SetIndexBuffer(2, g_highDot)                        ||
       !SetIndexBuffer(3, g_lowDot)                         ||
       !SetIndexBuffer(4, g_curTrend))
   {
      Alert(name, GetStringByMessageCode(MESSAGE_CODE_BIND_ERROR), GetLastError());
      return false;
   }

   // Çàäàíèå ãðàôè÷åñêîãî òèïà áóôåðîâ
   for (int i = 0; i < 4; i++)
      SetIndexStyle(i, DRAW_LINE);
      
   SetIndexStyle(4, DRAW_NONE);
      
   SetIndexLabel(0, "Resistance of downward trend");
   SetIndexLabel(1, "Support of upward trend");
   SetIndexLabel(2, "Breaking resistance");
   SetIndexLabel(3, "Breaking support");
   SetIndexLabel(4, "Trend Direction");
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Initialize of all indicator buffers                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void BuffersInitializeAll()
{
   ArrayInitialize(g_highSolid, EMPTY_VALUE);  
   ArrayInitialize(g_lowSolid, EMPTY_VALUE);  
   ArrayInitialize(g_highDot, EMPTY_VALUE);  
   ArrayInitialize(g_lowDot, EMPTY_VALUE);  
   ArrayInitialize(g_curTrend, TREND_TYPE_NONE);  
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of bar index which needed to recalculate                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex(int &total, const int ratesTotal, const int prevCalculated)
{
   total = ratesTotal - g_maxMAPeriod - 2;                                                                         
                                                   
   if (i_indBarsCount > 0 && i_indBarsCount < total)
      total = MathMin(i_indBarsCount, total);                      
                                                   
   if (prevCalculated < ratesTotal - 1)                     
   {       
      BuffersInitializeAll();
      return total;
   }
   
   return (MathMin(ratesTotal - prevCalculated, total));                            
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| The minimal price at the downtrend interval                                                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
double GetLowPrice(const int barIndex, const ENUM_TIMEFRAMES tf)
{
   double lowPrice = iLow(NULL, tf, barIndex);
   int total = iBars(NULL, tf);
   for (int i = barIndex + 1; i < total; i++)
   {
      double maFast = iMA(NULL, tf, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, i);  
      double maSlow = iMA(NULL, tf, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, i);
      if (maFast > maSlow)
         return lowPrice;
         
      lowPrice = MathMin(lowPrice, iLow(NULL, tf, i));
   }
   
   return lowPrice;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|  The maximal price at the downtrend interval                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
double GetHighPrice(const int barIndex, const ENUM_TIMEFRAMES tf)
{
   double highPrice = iHigh(NULL, tf, barIndex);

   int total = iBars(NULL, tf);
   for (int i = barIndex + 1; i < total; i++)
   {
      double maFast = iMA(NULL, tf, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, i);  
      double maSlow = iMA(NULL, tf, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, i);
      if (maFast < maSlow)
         return highPrice;
         
      highPrice = MathMax(highPrice, iHigh(NULL, tf, i));
   }
   
   return highPrice;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| The continuity of the indicator buffers values                                                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ContinuityBuffers(int barIndex)
{
   if (g_curTrend[barIndex + 1] == TREND_TYPE_UPWARD)
   {
      g_lowDot[barIndex + 1] = EMPTY_VALUE;
      g_highSolid[barIndex + 1] = EMPTY_VALUE;
   }

   if (g_curTrend[barIndex + 1] == TREND_TYPE_DOWNWARD)
   {
      g_highDot[barIndex + 1] = EMPTY_VALUE;
      g_lowSolid[barIndex + 1] = EMPTY_VALUE;
   }

   g_highSolid[barIndex] = g_highSolid[barIndex + 1];
   g_lowSolid[barIndex] = g_lowSolid[barIndex + 1]; 
   g_highDot[barIndex] = g_highDot[barIndex + 1];
   g_lowDot[barIndex] = g_lowDot[barIndex + 1]; 
   g_curTrend[barIndex] = g_curTrend[barIndex + 1];
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| To process the upward MA cross                                                                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessUpwardMACross(int barIndex)
{
   if (g_curTrend[barIndex + 1] == TREND_TYPE_DOWNWARD)
   {
      g_lowDot[barIndex] = GetLowPrice(barIndex, (ENUM_TIMEFRAMES)_Period);
      g_lowSolid[barIndex] = EMPTY_VALUE;
      if (g_lowDot[barIndex + 1] == EMPTY_VALUE)
         g_lowDot[barIndex + 1] = g_lowDot[barIndex];
         
      return;
   }

   g_lowSolid[barIndex] = GetLowPrice(barIndex, (ENUM_TIMEFRAMES)_Period);
   g_lowDot[barIndex] = EMPTY_VALUE;
   if (g_lowSolid[barIndex + 1] == EMPTY_VALUE)
      g_lowSolid[barIndex + 1] = g_lowSolid[barIndex];
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| To process the downward MA cross                                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessDownwardMACross(int barIndex)
{
   if (g_curTrend[barIndex + 1] == TREND_TYPE_UPWARD)
   {
      g_highDot[barIndex] = GetHighPrice(barIndex, (ENUM_TIMEFRAMES)_Period);
      g_highSolid[barIndex] = EMPTY_VALUE;
      if (g_highDot[barIndex + 1] == EMPTY_VALUE)
         g_highDot[barIndex + 1] = g_highDot[barIndex];
      return;
   }

   g_highSolid[barIndex] = GetHighPrice(barIndex, (ENUM_TIMEFRAMES)_Period);
   g_highDot[barIndex] = EMPTY_VALUE;
   if (g_highSolid[barIndex + 1] == EMPTY_VALUE)
      g_highSolid[barIndex + 1] = g_highSolid[barIndex];
      
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| To process of breakout of resistance level                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessResistanceBreak(int barIndex)
{
   g_curTrend[barIndex] = TREND_TYPE_UPWARD;

   g_highDot[barIndex + 1] = g_highSolid[barIndex + 1];
   g_highDot[barIndex] = (g_highSolid[barIndex] == EMPTY_VALUE)? g_highSolid[barIndex + 1] : g_highSolid[barIndex];
   g_highSolid[barIndex] = EMPTY_VALUE;
   
   if (g_lowDot[barIndex + 1] == EMPTY_VALUE)
      return;
      
   g_lowSolid[barIndex + 1] = g_lowDot[barIndex + 1];
   g_lowSolid[barIndex] = (g_lowDot[barIndex] == EMPTY_VALUE)? g_lowDot[barIndex + 1] : g_lowDot[barIndex];
   g_lowDot[barIndex] = EMPTY_VALUE;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| To process of breakout of the support level                                                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessSupportBreak(int barIndex)
{
   g_curTrend[barIndex] = TREND_TYPE_DOWNWARD;

   g_lowDot[barIndex + 1] = g_lowSolid[barIndex + 1];
   g_lowDot[barIndex] = (g_lowSolid[barIndex] == EMPTY_VALUE)? g_lowSolid[barIndex + 1] : g_lowSolid[barIndex];
   g_lowSolid[barIndex] = EMPTY_VALUE;

   if (g_highDot[barIndex + 1] == EMPTY_VALUE)
      return;

   g_highSolid[barIndex + 1] = g_highDot[barIndex + 1];
   g_highSolid[barIndex] = (g_highDot[barIndex] == EMPTY_VALUE)? g_highDot[barIndex + 1] : g_highDot[barIndex];
   g_highDot[barIndex] = EMPTY_VALUE;   
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculation of the indicators values at the specified bar                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void CalculateOneBarMA(int barIndex)
{
   double maFast = iMA(NULL, 0, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, barIndex);  
   double maSlow = iMA(NULL, 0, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, barIndex);
   double maFast2 = iMA(NULL, 0, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, barIndex + 1);  
   double maSlow2 = iMA(NULL, 0, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, barIndex + 1);
   
   ContinuityBuffers(barIndex);

   if (maFast > maSlow && maFast2 < maSlow2)
      ProcessUpwardMACross(barIndex);

   if (maFast < maSlow && maFast2 > maSlow2)
      ProcessDownwardMACross(barIndex);   
   
   if (g_curTrend[barIndex] != TREND_TYPE_UPWARD && Close[barIndex] > g_highSolid[barIndex])
   {
      ProcessResistanceBreak(barIndex);
      return;
   }
   
   if (g_curTrend[barIndex] != TREND_TYPE_DOWNWARD && Close[barIndex] < g_lowSolid[barIndex] && g_lowSolid[barIndex] != EMPTY_VALUE)
      ProcessSupportBreak(barIndex);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Data at all TFs need to recalculate on all history interval                                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void RecalculateTFsData(const int total)
{
   for (uint i = 0; i < TF_AMOUNT; i++)
   {
      if (!g_tfInfo[i].isShow)
         continue;
   
      g_tfInfo[i].lowLimit = EMPTY_VALUE;
      g_tfInfo[i].highLimit = EMPTY_VALUE;
      g_tfInfo[i].curTrend = TREND_TYPE_NONE;
      
      int toBarIndex = 0;
      if (g_focusBarTime != 0)
         toBarIndex = (int)MathMax(iBarShift(NULL, g_tfInfo[i].tf, g_focusBarTime), 0);
      
      for (int j = total; j > toBarIndex; j--)
         CalculateTFData(j, i);
   }
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculation data for all used TFs                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void CalculateTFData(const int tfBarIndex, const int tfIndex)
{
   // Do not calculate data for unformed candle
   if (tfBarIndex <= 0 || tfBarIndex >= iBars(NULL, g_tfInfo[tfIndex].tf))
      return;
      
   // Calculate MAs values
   double maFast = iMA(NULL, g_tfInfo[tfIndex].tf, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, tfBarIndex);  
   double maSlow = iMA(NULL, g_tfInfo[tfIndex].tf, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, tfBarIndex);
   double maFast2 = iMA(NULL, g_tfInfo[tfIndex].tf, i_maFastPeriod, 0, i_maFastMethod, i_maFastPrice, tfBarIndex + 1);  
   double maSlow2 = iMA(NULL, g_tfInfo[tfIndex].tf, i_maSlowPeriod, 0, i_maSlowMethod, i_maSlowPrice, tfBarIndex + 1);
   
   // Upward MA cross
   if (maFast > maSlow && maFast2 < maSlow2)
      g_tfInfo[tfIndex].lowLimit = GetLowPrice(tfBarIndex, g_tfInfo[tfIndex].tf);

   // Downward MA cross
   if (maFast < maSlow && maFast2 > maSlow2)
      g_tfInfo[tfIndex].highLimit = GetHighPrice(tfBarIndex, g_tfInfo[tfIndex].tf);
   
   // Breaking the resistance level
   if (g_tfInfo[tfIndex].curTrend != TREND_TYPE_UPWARD && iClose(NULL, g_tfInfo[tfIndex].tf, tfBarIndex) > g_tfInfo[tfIndex].highLimit)
   {
      g_tfInfo[tfIndex].curTrend = TREND_TYPE_UPWARD;
      return;
   }
   
   // Breaking the support level
   if (g_tfInfo[tfIndex].curTrend != TREND_TYPE_DOWNWARD && iClose(NULL, g_tfInfo[tfIndex].tf, tfBarIndex) < g_tfInfo[tfIndex].lowLimit && g_tfInfo[tfIndex].lowLimit != EMPTY_VALUE)
      g_tfInfo[tfIndex].curTrend = TREND_TYPE_DOWNWARD;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Convert the trend type to arrow                                                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetStringTrend(const ENUM_TREND_TYPE trendType)
{
   switch (trendType)
   {
      case TREND_TYPE_DOWNWARD: return CharToString(226);
      case TREND_TYPE_UPWARD: return CharToString(225);
   }
   
   return CharToString(251);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Convert the trend type to color                                                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
color GetColorTrend(const ENUM_TREND_TYPE trendType)
{
   switch (trendType)
   {
      case TREND_TYPE_DOWNWARD: return i_downwardTrendColor;
      case TREND_TYPE_UPWARD: return i_upwardTrendColor;
   }
   
   return i_undefinedTrendColor;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show the text label                                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowLabel(string labelID, int x, int y, string text, color clr, string fontName, int fontSize)
{
   string name = PREFIX + labelID;

   if (ObjectFind(0, name) < 0)
   {
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, i_corner);
      ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
      ObjectSetString(0, name, OBJPROP_TEXT, text);
      ObjectSetInteger(0, name, OBJPROP_ANCHOR, g_anchor);
      ObjectSetString(0, name, OBJPROP_FONT, fontName);
      
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
      return;
   }
   
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
   ObjectSetString(0, name, OBJPROP_TEXT, text);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show the vertical line                                                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowVLine(datetime time)
{
   string name = PREFIX + VERT_LINE;

   if (ObjectFind(0, name) < 0)
   {
      ObjectCreate(0, name, OBJ_VLINE, 0, time, 1);
      ObjectSetInteger(0, name, OBJPROP_COLOR, VERT_LINE_COLOR);
      ObjectSetInteger(0, name, OBJPROP_STYLE, VERT_LINE_STYLE);
      
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
      return;
   }
   
   ObjectSetInteger(0, name, OBJPROP_TIME1, time);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show one character                                                                                                                                                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowOneChar(const int tfIndex, const int yCoord, int& xCoord)
{
   if (!g_tfInfo[tfIndex].isShow)
      return;
      
   ShowLabel(LABEL_TREND + (string)tfIndex, xCoord, yCoord, GetStringTrend(g_tfInfo[tfIndex].curTrend), GetColorTrend(g_tfInfo[tfIndex].curTrend), FONT_NAME_ARROW, FONT_SIZE_ARROW);
   xCoord += STEP_X;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Define the arrow that correspond to the relative location of price and channel                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetStringPriceLocation(const TFInfo& tfInfo, const double price, color& clr)
{
   clr = i_undefinedTrendColor;

   // Undefined trend direction 
   if (tfInfo.curTrend == TREND_TYPE_NONE)
      return CharToString(251);
      
   // Price is located higher than channel
   if (tfInfo.highLimit < price)
   {
      clr = i_upwardTrendColor;
      return CharToString(217);
   }

   // Price is located lower than channel
   if (tfInfo.lowLimit > price)
   {
      clr = i_downwardTrendColor;
      return CharToString(218);
   }
   
   // Price is located in a channel
   return CharToString(216);   
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show line of the summary that displaying the direction of trend                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowTrendDirectionLine(const int y)
{
   int x = START_X_OFFSET;
   
   if (i_corner == CORNER_RIGHT_LOWER || i_corner == CORNER_RIGHT_UPPER)
   {
      for (int  i = TF_AMOUNT - 1; i >= 0; i--)
         ShowOneChar(i, y, x);
   }
   else
      for (int i = 0; i < TF_AMOUNT; i++)
         ShowOneChar(i, y, x);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show price location one character                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowOneCharPriceLocation(const int tfIndex, const int yCoord, int& xCoord, const double price)
{
   if (!g_tfInfo[tfIndex].isShow)
      return;
      
   color arrowColor = clrNONE;
   string arrow = GetStringPriceLocation(g_tfInfo[tfIndex], price, arrowColor);
   ShowLabel(LABEL_PRICE_LOC + (string)tfIndex, xCoord, yCoord, arrow, arrowColor, FONT_NAME_ARROW, FONT_SIZE_ARROW);
   xCoord += STEP_X;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show line of summary that displaying price location relative to the channel                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowPriceLocation(const int y, const double price)
{
   int x = START_X_OFFSET;
   
   if (i_corner == CORNER_RIGHT_LOWER || i_corner == CORNER_RIGHT_UPPER)
   {
      for (int  i = TF_AMOUNT - 1; i >= 0; i--)
         ShowOneCharPriceLocation(i, y, x, price);
   }
   else
      for (int i = 0; i < TF_AMOUNT; i++)
         ShowOneCharPriceLocation(i, y, x, price);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Show the data from timeframes                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowSummary(const double price)
{
   if (i_corner == CORNER_LEFT_UPPER || i_corner == CORNER_RIGHT_UPPER)
   {
      int y = START_Y_OFFSET + STEP_Y;
      ShowTrendDirectionLine(y);
      y += STEP_Y;
      ShowPriceLocation(y, price);
   }
   else
   {
      int y = START_Y_OFFSET;
      ShowPriceLocation(y, price);
      y += STEP_Y;
      ShowTrendDirectionLine(y);
   }
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculation of indicators values                                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void CalcIndicatorData(int limit, int total)
{
   // Initialize the start data
   if (limit > 1)
      RecalculateTFsData(total);

   // Calculate all data of indicator
   for (int i = limit; i >= 0; i--)
   {
      CalculateOneBarMA(i);
      
      if (g_focusBarTime != 0)
         continue;

      for (int j = 0; j < TF_AMOUNT; j++)
      {
         if (!g_tfInfo[j].isShow)
            continue;

         int tfBarIndex = iBarShift(NULL, g_tfInfo[j].tf, Time[i]); 
         if (tfBarIndex == 1)
            CalculateTFData(1, j);
      }
   }
   
   // Show the data from timeframes
   if (g_focusBarTime == 0)
      ShowSummary(Bid);

   // Show the focus bar   
   if (limit == 1 && i_showFocusBar == YES)
      ShowVLine((g_focusBarTime == 0)? Time[0] : g_focusBarTime);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator iteration function                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
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[])
{
   if (!g_activate)                                                                                
      return rates_total;                                 
    
   int total;   
   int limit = GetRecalcIndex(total, rates_total, prev_calculated);                                

   CalcIndicatorData(limit, total);                                                                
   
   return rates_total;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Process the events on a chart                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam)
{
   // Processing only one event - click of left mouse button
   if (id != CHARTEVENT_CLICK)
      return;
      
   // Convert the decart coordinates to the coordinates of time and price
   double price = 0.0;
   datetime time = 0;
   int subWindow = 0;
   if (!ChartXYToTimePrice(0, (int)lparam, (int)dparam, subWindow, time, price))
      return;
      
   // Find the bar index by place where mouse click has occurred 
   int barIndex = iBarShift(NULL, 0, time);
   if (barIndex < 0 || barIndex >= Bars)
      return;
      
   // Processing the click if mouse coordinates are inside the bar 
   if (price > High[barIndex] || price < Low[barIndex])
      return;
     
   // Show new position of vertical line 
   g_focusBarTime = (barIndex == 0)? 0 : Time[barIndex];      
   if (i_showFocusBar == YES)
      ShowVLine((g_focusBarTime == 0)? Time[0] : g_focusBarTime);
      
   // Recalculate TFs data
   int total = i_indBarsCount;
   if (total == 0 || total > Bars - g_maxMAPeriod - 2)
      total = Bars - g_maxMAPeriod - 2;
   RecalculateTFsData(total);
   
   // Show calculated data
   ShowSummary(Open[barIndex]);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message and terminal language                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetStringByMessageCode(ENUM_MESSAGE_CODE messageCode)
{
   string language = TerminalInfoString(TERMINAL_LANGUAGE);
   if (language == "Russian")
      return GetRussianMessage(messageCode);
      
   return GetEnglishMessage(messageCode);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message for russian language                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetRussianMessage(ENUM_MESSAGE_CODE messageCode)
{
   switch (messageCode)
   {
      case MESSAGE_CODE_MA_FAST_LESS_THAN_ZERO:            return ": ïåðèîä ðàñ÷åòà áûñòðîãî ñðåäíåãî äîëæåí áûòü áîëüøå íóëÿ. Èíäèêàòîð îòêëþ÷åí.";
      case MESSAGE_CODE_MA_SLOW_LESS_THAN_ZERO:            return ": ïåðèîä ðàñ÷åòà ìåäëåííîãî ñðåäíåãî äîëæåí áûòü áîëüøå íóëÿ. Èíäèêàòîð îòêëþ÷åí.";
      case MESSAGE_CODE_TERMINAL_FATAL_ERROR1:             return ": ôàòàëüíàÿ îøèáêà òåðìèíàëà - ïóíêò ðàâåí íóëþ. Èíäèêàòîð îòêëþ÷åí.";
      case MESSAGE_CODE_BIND_ERROR:                        return ": îøèáêà ñâÿçûâàíèÿ ìàññèâîâ ñ áóôåðàìè èíäèêàòîðà. Îøèáêà ¹";
   }
   
   return "";
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message for english language                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetEnglishMessage(ENUM_MESSAGE_CODE messageCode)
{
   switch (messageCode)
   {
      case MESSAGE_CODE_MA_FAST_LESS_THAN_ZERO:            return ": calculation period of fast MA must be more than zero. The indicator is turned off.";
      case MESSAGE_CODE_MA_SLOW_LESS_THAN_ZERO:            return ": calculation period of slow MA must be more than zero. The indicator is turned off.";
      case MESSAGE_CODE_TERMINAL_FATAL_ERROR1:             return ": terminal fatal error - point equals to zero. The indicator is turned off.";
      case MESSAGE_CODE_BIND_ERROR:                        return ": error of binding of the arrays and the indicator buffers. Error N";
   }

   return "";
}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---