//+------------------------------------------------------------------+
//|                                                SupportLevels.mq4 |
//|                      Copyright © 2008, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Red
#property indicator_color3 Red
#property indicator_color4 Magenta
#property indicator_color5 Blue
#property indicator_color6 Blue
#property indicator_color7 Blue
//---- input parameters
extern double    Resistance3;
extern double    Resistance2;
extern double    Resistance1;
extern double    BalancePoint;
extern double    Support1;
extern double    Support2;
extern double    Support3;
//---- buffers
double Resistance3Buffer[];
double Resistance2Buffer[];
double Resistance1Buffer[];
double BalancePointBuffer[];
double Support1Buffer[];
double Support2Buffer[];
double Support3Buffer[];
datetime oldTime = 0, newTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   ObjectCreate ("DynamicResistance3", OBJ_HLINE, 0, 0, Resistance3);
   ObjectSet ("DynamicResistance3", OBJPROP_COLOR, indicator_color1);
   ObjectSet ("DynamicResistance3", OBJPROP_WIDTH, 2);
   ObjectCreate ("DynamicResistance2", OBJ_HLINE, 0, 0, Resistance2);
   ObjectSet ("DynamicResistance2", OBJPROP_COLOR, indicator_color2);
   ObjectSet ("DynamicResistance2", OBJPROP_WIDTH, 2);
   ObjectCreate ("DynamicResistance1", OBJ_HLINE, 0, 0, Resistance1);
   ObjectSet ("DynamicResistance1", OBJPROP_COLOR, indicator_color3);
   ObjectSet ("DynamicResistance1", OBJPROP_WIDTH, 2);
   
   ObjectCreate ("DynamicBalancePoint", OBJ_HLINE, 0, 0, BalancePoint);
   ObjectSet ("DynamicBalancePoint", OBJPROP_COLOR, indicator_color4);
   ObjectSet ("DynamicBalancePoint", OBJPROP_WIDTH, 2);
   
   ObjectCreate ("DynamicSupport1", OBJ_HLINE, 0, 0, Support1);
   ObjectSet ("DynamicSupport1", OBJPROP_COLOR, indicator_color5);
   ObjectSet ("DynamicSupport1", OBJPROP_WIDTH, 2);
   ObjectCreate ("DynamicSupport2", OBJ_HLINE, 0, 0, Support2);
   ObjectSet ("DynamicSupport2", OBJPROP_COLOR, indicator_color6);
    ObjectSet ("DynamicSupport2", OBJPROP_WIDTH, 2);
   ObjectCreate ("DynamicSupport3", OBJ_HLINE, 0, 0, Support3);
   ObjectSet ("DynamicSupport3", OBJPROP_COLOR, indicator_color7);
    ObjectSet ("DynamicSupport3", OBJPROP_WIDTH, 2);
//----

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   ObjectDelete ("DynamicResistance3");
   ObjectDelete ("DynamicResistance2");
   ObjectDelete ("DynamicResistance1");
   ObjectDelete ("DynamicBalancePoint");
   ObjectDelete ("DynamicSupport1");
   ObjectDelete ("DynamicSupport2");
   ObjectDelete ("DynamicSupport3");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
 //  newTime = TimeCurrent();
//   if (TimeDay (newTime) != TimeDay (oldTime))
//   {
      datetime today = TimeLocal (), serverTime = TimeCurrent ();
      int offset = 1, currentDay = TimeDayOfWeek (today), serverDay = TimeDayOfWeek (serverTime);
      if (currentDay == 0 ||
         ((currentDay == 6 || currentDay == 1) && serverDay == 5)) 
         offset = 0;
      
      double high = iHigh (0, PERIOD_D1, offset),
          low = iLow (0, PERIOD_D1, offset),
          close = iClose (0, PERIOD_D1, offset);
    
      BalancePoint = (high + low + close) / 3;

      Resistance1 = 2 * BalancePoint - low;
      Resistance2 = BalancePoint + (high - low);
      Resistance3 = high + 2 * (BalancePoint - low);

      Support1 = 2 * BalancePoint - high;
      Support2 = BalancePoint - (high - low);
      Support3 = low - 2 * (high - BalancePoint);
      
      datetime forecastDate = serverTime;
      if (currentDay == 6 || currentDay == 0)
         forecastDate += 26 * 3600 * 2;
         
      WriteLevelsToFile ("levelsData\\" + Symbol() + "_" + TimeToStr (forecastDate, TIME_DATE) + ".txt",
            Resistance3, Resistance2, Resistance1, BalancePoint, Support1, Support2, Support3);
      WriteForecastsToFile ("forecasts\\" + Symbol() + "_" + TimeToStr (forecastDate, TIME_DATE) + ".txt",
            Symbol(),forecastDate, Resistance3, Resistance2, Resistance1, BalancePoint, Support1, Support2, Support3);
         
      int err = GetLastError();
      if (err != 0)
            Print ("Error saving data to file: " + ErrorToString(err));
            
      Comment("Уровни " + Symbol() + "; Текущее время: " + TimeToStr (today) + "; Последнее время сервера: " + TimeToStr (serverTime) + "; Строим по оступу: " + offset);

      ObjectSet ("DynamicResistance1", OBJPROP_PRICE1, Resistance1);
      ObjectSet ("DynamicResistance2", OBJPROP_PRICE1, Resistance2);
      ObjectSet ("DynamicResistance3", OBJPROP_PRICE1, Resistance3);

      ObjectSet ("DynamicBalancePoint", OBJPROP_PRICE1, BalancePoint);

      ObjectSet ("DynamicSupport1", OBJPROP_PRICE1, Support1);
      ObjectSet ("DynamicSupport2", OBJPROP_PRICE1, Support2);
      ObjectSet ("DynamicSupport3", OBJPROP_PRICE1, Support3);
 //  }
 //  oldTime = newTime;
   return(0);
  }

string ErrorToString (int errorCode)
{
   switch (errorCode)
   {
      case 4102 : return ("Too many opened files");
      case 4101 : return ("Wrong file name");
      case 4051 : return ("Invalid function parameter value");
      case 4100 : return ("Unknown file error");
      case 4103 : return ("Cannot open the file");
      case 4104 : return ("Incopatible file access mode");
      case 4099 : return ("Unexptected end of file");
      default : return (errorCode);
   }
}

  bool WriteLevelsToFile (string filename, double R3, double R2, double R1, double P, double S1, double S2, double S3)
  {
      int handle = FileOpen (filename, FILE_BIN | FILE_WRITE );
      if (handle < 1)
      {
         return (false);
      }
      FileWriteString (handle, "R3 " + R3, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "R2 " + R2, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "R1 " + R1, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "P " + P, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "S1 " + S1, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "S2 " + S2, 3+10);
      FileWriteString (handle, "\r\n", 2);
      FileWriteString (handle, "S3 " + S3, 3+10);
      FileClose (handle);
      return (true);
  }
  
  string GetMonth (int month)
  {
      switch (month - 1)
      {
         case 0: return (" января ");
         case 1: return (" февраля ");
         case 2: return (" марта ");
         case 3: return (" апреля ");
         case 4: return (" мая ");
         case 5: return (" июня ");
         case 6: return (" июля ");
         case 7: return (" августа ");
         case 8: return (" сентября ");
         case 9: return (" октября ");
         case 10: return (" ноября ");
         case 11: return (" декабря ");
      }
  }
  bool WriteForecastsToFile (string filename, string symbol, datetime forecastDate, double R3, double R2, double R1, double P, double S1, double S2, double S3)
  {
      int handle = FileOpen (filename, FILE_BIN | FILE_WRITE );
      if (handle < 1)
      {
         return (false);
      }
      FileWrite(handle, "<strong>Прогноз на " + TimeDay(forecastDate) + GetMonth(TimeMonth(forecastDate)) + TimeYear(forecastDate) + "</strong>");
      FileWrite(handle, CreateForecast (symbol, true, forecastDate, R3, R2, R1, P, S1, S2, S3) + "\n\n");
      
      FileWrite(handle, "<strong>Прогноз на " + TimeDay(forecastDate) + GetMonth(TimeMonth(forecastDate)) + TimeYear(forecastDate) + "</strong>");
      FileWrite(handle, CreateForecast (symbol, false, forecastDate, R3, R2, R1, P, S1, S2, S3) + "\n\n");
      FileClose (handle);
      return (true);
  }
  
  string CreateForecast (string symbol, bool direction, datetime forecastDate, double R3, double R2, double R1, double P, double S1, double S2, double S3)
  {
      int precision = 4;
      if (StringFind(symbol, "JPY") != -1)
         precision = 2; 
      if (direction)
         return ("<br>\nТочка разворота находится на уровне " + DoubleToStr(P, precision) + ".\n" + 
                 "<br>\nБазовый сценарий: ПОКУПАТЬ выше " + DoubleToStr(P, precision) + ". Цель - " + DoubleToStr(R1, precision) + " и " + DoubleToStr(R2, precision) + ".\n" +
                 "<br>\nАльтернативный сценарий: прорыв вниз уровня " + DoubleToStr(P, precision) + " откроет путь к " + DoubleToStr(S1, precision) + " и " + DoubleToStr(S2, precision) + ".\n");
      return ("<br>\nТочка разворота находится на уровне " + DoubleToStr(P, precision) + ".\n" + 
              "<br>\nБазовый сценарий: ПРОДАВАТЬ ниже " + DoubleToStr(P, precision) + ". Цель - " + DoubleToStr(S1, precision) + " и " + DoubleToStr(S2, precision) + ".\n" +
              "<br>\nАльтернативный сценарий: прорыв вверх уровня " + DoubleToStr(P, precision) + " откроет путь к " + DoubleToStr(R1, precision) + " и " + DoubleToStr(R2, precision) + ".\n");
  }
//+------------------------------------------------------------------+