MAChannel_Close_MultiTF_AD

Author: Scriptong
4 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