//+------------------------------------------------------------------+
//|                                                  HandChannel.mq4 |
//| Ручное построение каналов                                        |
//|                                                                  |
//| Версия 2.                                                        |
//|                                                                  |
//| Канал строится по трём точкам: две опорные с одной стороны и     |
//| одна с другой. Терминология: опорные точки - левая и правая,     |
//| противоположная точка - средняя. Координаты каждой точки -       |
//| время. Привязка к конкретному бару по времени необходима, иначе  |
//| получите ошибку задания данных. Цены берутся от указанных баров. |
//|                                                                  |
//| Параметры:                                                       |
//| ExtTimeLeft       = дата левой точки                             |
//| ExtTimeMiddle     = дата средней точки                           |
//| ExtTimeRight      = дата правой точки                            |
//| ExtColor          = цвет канала                                  |
//| ExtGetFromFile    = флаг получения данных из файла               |
//| ExtRegetFromFile  = флаг перечитывания данных из файла           |
//| ExtDrawPoints     = рисовать точки привязки                      |
//| ExtDrawMiddleLine = рисовать среднюю линию канала                |
//| ExtDeleteObject   = удалять линии канала при деинициализации     |
//|                                                                  |
//| При вводе данных в панели настройки строится один канал.         |
//| При вводе данных из файла можно задать несколько каналов.        |
//|                                                                  |
//| Все даты задаются в виде: YYYY.MM.DD HH:MM                       |
//| Например: 2006.08.12 12:00                                       |
//|                                                                  |
//| Данные в файле:                                                  |
//| Имя файла должно соответствовать валютной паре, например:        |
//| USDJPY.TXT, EURUSD.TXT. Расширение .TXT обязательно.             |
//| Файл располагается в подкаталоге \Experts\Files.                 |
//| Данные в файле располагаются следующим образом:                  |
//| Канал 1             - любой текст (исключительно для удобства)   |
//| 2006.08.12 12:00    - дата левой точки                           |
//| 2006.08.13 16:00    - дата средней точки                         |
//| 2006.08.14 08:00    - дата правой точки                          |
//| Blue                - цвет канала                                |
//| Далее может следовать ещё несколько таких же блоков для других   |
//| каналов                                                          |
//| Поддерживаются следующие цвета:                                  |
//| Black, Green, Purple, Maroon, Brown, Orange, Gold, Yellow, Lime, |
//| Aqua, Blue, Magenta, Red, Gray, Silver, Pink, Beige, White.      |
//|                                                                  |
//| Сообщения об ошибках чтения данных выводятся в Терминале         |
//| в закладке Эксперты.                                             |
//|                                                                  |
//| Параметр ExtRegetFromFile введён для того, чтобы данные из файла |
//| не читались при каждом тике. При добавлении в файл новых данных  |
//| по новому каналу или удаления старых нужно поставить данному     |
//| параметру значение True, а после обновления снова поставить      |
//| False. Владельцы мощных компьютеров могут сразу поставить True   |
//| и более не беспокоиться. :-) (хотя постоянное обращение к диску  |
//| не есть хорошо). При перечитывании данных линии построенных      |
//| каналов удаляются принудительно и строятся заново.               |
//|                                                                  |
//| Изменения версии 2:                                              |
//| Цены не задаются, а берутся от указанных баров.                  |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Karakurt"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  Yellow

extern datetime ExtTimeLeft       = D'2006.08.01 00:00';
extern datetime ExtTimeMiddle     = D'2006.08.01 00:00';
extern datetime ExtTimeRight      = D'2006.08.01 00:00';
extern color    ExtColor          = Lime;
extern bool     ExtGetFromFile    = True;
extern bool     ExtRegetFromFile  = False;
extern bool     ExtDrawPoints     = False;
extern bool     ExtDrawMiddleLine = False;
extern bool     ExtDeleteObject   = False;

double ExtMapBuffer1[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
  SetIndexStyle(  0, DRAW_ARROW, EMPTY, 1, indicator_color1 );
  SetIndexArrow(  0, 251 );
  SetIndexBuffer( 0, ExtMapBuffer1 );
  SetIndexEmptyValue( 0, 0.0 );

  return ( 0 );
}

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int deinit()
{
  if ( ExtDeleteObject )
    DelObj();
  
  return ( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
  static bool bGettingFromFile = False;
  
  string sFileName;
  string sIdentChannel; // идентификатор канала - для удобства - ни на что не влияет
  int    iFileHandle;
  int    i;
  
  if ( ExtGetFromFile ) { // данные берутся из файла
    
    if ( ExtRegetFromFile ) // надо перечитывать данные
      DelObj(); // принудительное удаление всех имеющихся каналов
      
    else { // не надо перечитывать данные
      if ( bGettingFromFile  ) // данные уже были считаны
        return ( 0 );
      
    } // не надо перечитывать данные
    
    sFileName   = Symbol() + ".txt";
    iFileHandle = FileOpen( sFileName, FILE_READ );
    
    if ( iFileHandle < 1 ) {
      Print( "Ошибка открытия файла " + sFileName + " ", GetLastError() );
      return ( -1 );
    } // if
    
    for ( i = 1; i < 10; i++ ) {
    
      if ( FileIsEnding( iFileHandle ) ) {
        Print( "Конец файла" );
        break;
      } // if
      
      //=== Считывание данных текущего канала
      sIdentChannel = FileReadString( iFileHandle );
      ExtTimeLeft   = StrToTime(  FileReadString( iFileHandle ) );
      ExtTimeMiddle = StrToTime(  FileReadString( iFileHandle ) );
      ExtTimeRight  = StrToTime(  FileReadString( iFileHandle ) );
      ExtColor      = StrToColor( FileReadString( iFileHandle ) );
      
      Print( sIdentChannel );
      /*Print( "ExtTimeLeft= ", TimeToStr( ExtTimeLeft, TIME_DATE|TIME_MINUTES ) );
      Print( "ExtTimeMiddle= ", TimeToStr( ExtTimeMiddle, TIME_DATE|TIME_MINUTES ) );
      Print( "ExtTimeRight= ", TimeToStr( ExtTimeRight, TIME_DATE|TIME_MINUTES ) );*/
      Print( "Считан ", i, "-й канал" );
      
      DrawLines(); // рисуется текущий канал
      
    } // for
    
    Print( "Считано каналов: ", i-1 );
    
    bGettingFromFile = True;
    
    FileClose( iFileHandle );
  } // if ( данные берутся из файла
  
  else { // данные берутся из настройки
    DrawLines(); // канал рисуется один раз
  } // else
  
  return ( 0 );
} // int start()
  
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int DrawLines()
{
  int    iNumBarLeft;     // номер левого бара 
  int    iNumBarMiddle;   // номер среднего бара
  int    iNumBarRight;    // номер правого бара
  double dPriceLeft;      // цена левого бара
  double dPriceMiddle;    // цена среднего бара
  double dPriceRight;     // цена правого бара
  double dDrawPriceRight; // цены на опорных барах
  double dDrawPriceLeft;  //   для линии через 3-ю точку
  double dPriceDelta;     // шаг цены одного бара между левым и правым барами
  string sNameObject;
  
  //=== Вычисляем номера баров
  iNumBarLeft   = iBarShift( NULL, 0, ExtTimeLeft  , True );
  iNumBarMiddle = iBarShift( NULL, 0, ExtTimeMiddle, True );
  iNumBarRight  = iBarShift( NULL, 0, ExtTimeRight , True );
  
  if ( iNumBarLeft   < 0 ) { Print( "Ошибка задания левой даты"  , ExtTimeLeft   ); return ( -1 ); }
  if ( iNumBarMiddle < 0 ) { Print( "Ошибка задания средней даты", ExtTimeMiddle ); return ( -1 ); }
  if ( iNumBarRight  < 0 ) { Print( "Ошибка задания правой даты" , ExtTimeRight  ); return ( -1 ); }
  
  if ( High[ iNumBarLeft  ] > Low[ iNumBarMiddle ] &&
       High[ iNumBarRight ] > Low[ iNumBarMiddle ] ) { // опорная линия сверху
    dPriceLeft   = High[ iNumBarLeft   ];
    dPriceMiddle = Low[  iNumBarMiddle ];
    dPriceRight  = High[ iNumBarRight  ];
  } // if ( опорная линия сверху
  
  if ( Low[ iNumBarLeft  ] < High[ iNumBarMiddle ] &&
       Low[ iNumBarRight ] < High[ iNumBarMiddle ] ) { // опорная линия снизу
    dPriceLeft   = Low[  iNumBarLeft   ];
    dPriceMiddle = High[ iNumBarMiddle ];
    dPriceRight  = Low[  iNumBarRight  ];
  } // if ( опорная линия снизу
  
  if ( ExtDrawPoints ) { // рисовать точки привязки
    if ( dPriceLeft > dPriceMiddle ) { // базовая линия сверху
      ExtMapBuffer1[ iNumBarLeft   ] = dPriceLeft   + 5 * Point;
      ExtMapBuffer1[ iNumBarMiddle ] = dPriceMiddle - 5 * Point;
      ExtMapBuffer1[ iNumBarRight  ] = dPriceRight  + 5 * Point;
    } // базовая линия сверху
    
    else { // базовая линия снизу
      ExtMapBuffer1[ iNumBarLeft   ] = dPriceLeft   - 5 * Point;
      ExtMapBuffer1[ iNumBarMiddle ] = dPriceMiddle + 5 * Point;
      ExtMapBuffer1[ iNumBarRight  ] = dPriceRight  - 5 * Point;
    } // базовая линия снизу
    
  } // if ( рисовать точки привязки
  
  //=== Вычисляем шаг (если он положительный, то канал нисходящий)
  dPriceDelta = ( dPriceLeft - dPriceRight ) / ( iNumBarLeft - iNumBarRight );
  
  //    Координаты по шкале цены для линии через 3-ю точку
  dDrawPriceRight = dPriceMiddle - dPriceDelta * ( iNumBarMiddle - iNumBarRight  );
  dDrawPriceLeft  = dPriceMiddle + dPriceDelta * ( iNumBarLeft   - iNumBarMiddle );
  
  //=== Рисуем линии канала
  //    Опорная линия
  sNameObject = "BaseLine" + ExtTimeLeft;
  ObjectCreate( sNameObject, OBJ_TREND, 0,
                ExtTimeLeft , dPriceLeft,
                ExtTimeRight, dPriceRight );
  ObjectSet(    sNameObject, OBJPROP_COLOR, ExtColor );
  ObjectSet(    sNameObject, OBJPROP_WIDTH, 0 );
  ObjectSet(    sNameObject, OBJPROP_STYLE, STYLE_DASH );
  
  //    Линия через 3-ю точку
  sNameObject = "Line3" + ExtTimeLeft;
  ObjectCreate( sNameObject, OBJ_TREND, 0,
                ExtTimeLeft , dDrawPriceLeft,
                ExtTimeRight, dDrawPriceRight );
  ObjectSet(    sNameObject, OBJPROP_COLOR, ExtColor );
  ObjectSet(    sNameObject, OBJPROP_WIDTH, 0 );
  ObjectSet(    sNameObject, OBJPROP_STYLE, STYLE_DASH );
  
  //    Средняя линия
  if ( ExtDrawMiddleLine ) {
    sNameObject = "MidLine" + ExtTimeLeft;
    ObjectCreate( sNameObject, OBJ_TREND, 0, 
                  ExtTimeLeft , ( dPriceLeft  + dDrawPriceLeft  )/2,
                  ExtTimeRight, ( dPriceRight + dDrawPriceRight )/2 );
    ObjectSet(    sNameObject, OBJPROP_COLOR, ExtColor );
    ObjectSet(    sNameObject, OBJPROP_WIDTH, 0 );
    ObjectSet(    sNameObject, OBJPROP_STYLE, STYLE_DASHDOTDOT );
  }
  
  return ( 0 );
} // int DrawLines()

//+------------------------------------------------------------------+
//| Удаление объектов.
//+------------------------------------------------------------------+
void DelObj()
{
  string sNameObject;
  int    iiObject;
  
  for ( iiObject = ObjectsTotal(); iiObject >= 0; iiObject-- ) {
    sNameObject = ObjectName( iiObject );
    if ( StringFind( sNameObject, "BaseLine" ) > -1 ) ObjectDelete ( sNameObject );
    if ( StringFind( sNameObject, "Line3"    ) > -1 ) ObjectDelete ( sNameObject );
    if ( StringFind( sNameObject, "MidLine"  ) > -1 ) ObjectDelete ( sNameObject );
  } // for
  
} // void DelObj()

//+------------------------------------------------------------------+
//| Цвета
//+------------------------------------------------------------------+
color StrToColor( string sColor )
{
  if      ( sColor == "Black"   ) return ( Black   );
  else if ( sColor == "Green"   ) return ( Green   );
  else if ( sColor == "Purple"  ) return ( Purple  );
  else if ( sColor == "Maroon"  ) return ( Maroon  );
  else if ( sColor == "Brown"   ) return ( Brown   );
  else if ( sColor == "Orange"  ) return ( Orange  );
  else if ( sColor == "Gold"    ) return ( Gold    );
  else if ( sColor == "Yellow"  ) return ( Yellow  );
  else if ( sColor == "Lime"    ) return ( Lime    );
  else if ( sColor == "Aqua"    ) return ( Aqua    );
  else if ( sColor == "Blue"    ) return ( Blue    );
  else if ( sColor == "Magenta" ) return ( Magenta );
  else if ( sColor == "Red"     ) return ( Red     );
  else if ( sColor == "Gray"    ) return ( Gray    );
  else if ( sColor == "Silver"  ) return ( Silver  );
  else if ( sColor == "Pink"    ) return ( Pink    );
  else if ( sColor == "Beige"   ) return ( Beige   );
  else if ( sColor == "White"   ) return ( White   );
  else 
    return ( Lime );
    
} // color StrToColor()

