//------------------------------------------------------------------------------------
//   TradeHistory_V3.mq4
//   by ST2050
//   Индикатор выводит информацию о последних N сделках из истории
//
//   История версий:
//   v1 - базовый функционал 
//   v2 - добавлена фильтрация по дате StartFromDate
//   v3 - добавлена фильтрация по Magic
//   v4 - добавлена индикация о перекрытии убытка
//
//------------------------------------------------------------------------------------
#property indicator_chart_window
#property copyright "ST2050 from tradelikeapro.ru forum"

//---------------------------------------------------------------------------------------------
//  Внешние ресурсы
//---------------------------------------------------------------------------------------------
#import "user32.dll"
int GetWindowRect(int hwnd, int& lpRect[]);

//---------------------------------------------------------------------------------------------
//  Внешние переменные
//---------------------------------------------------------------------------------------------
extern int     HistOrdersCount  = 8;      // Количество ордеров из истории, макс. 100
extern bool    CompensationAll = false;   // Выводить галочки компенсации убытков для всех ордеров
                                          //   false - только последнее перекрытие убытков и последующие неперекрытые
extern int     GUI_WindowNumber = 0;      // Номер окна, где выводить данные
                                          //   0 - график, >1 номер подвала
extern bool    GUI_Left         = false;  // true - слева, false = справа
extern int     GUI_Right_Offset = 213;    // При расположении справа - расстояние от правого края
extern int     GUI_X            = 10;
extern int     GUI_Y            = 10;
extern int     GUI_LabelsYDist  = 14;
extern string  GUI_FontName     = "Arial";
extern int     GUI_FontSize     = 9;
extern color   GUI_FontColor    = C'80,80,80';
extern color   GUI_FontNagative = Maroon;
extern datetime StartFromDate   = D'2015.01.01 00:00';
extern bool    FilterMagic      = false;  // Фильтровать по магику, false - все ордера
extern int     Magic            = 0;      // true+0=только ручная торговля
//---------------------------------------------------------------------------------------------
//  Внутренние переменные
//---------------------------------------------------------------------------------------------

string IndName = "TradeHistoty";
string LabelsPrefix = "TradeHistoty_lbl_";

int _GUI_WindowNumber = 0;
int _GUI_X;
int _GUI_Y;
int    _GUI_Window_Width = 0;                                     // ширина окна, вычисляется в CalculateWindowRect
int    _GUI_Window_Height = 0;                                    // высота окна, вычисляется в CalculateWindowRect
bool   _FlagWindowWidthChanged = false;                          // флаг, что ширина окна изменилась

//---------------------------------------------------------------------------------------------
int OnInit()
 {
  RemoveObjects(IndName);

  IndicatorShortName(IndName);
  
  // Вычисляем номер окна
  if (GUI_WindowNumber <0) _GUI_WindowNumber = 0;
  else _GUI_WindowNumber=GUI_WindowNumber;
  
  //Вычисляем размер окна
  CalculateWindowRect();
  
  if (HistOrdersCount>100) HistOrdersCount=100;

  return(INIT_SUCCEEDED);
 }

//---------------------------------------------------------------------------------------------
int deinit()
{
   RemoveObjects(IndName);
   return(0);
}  
  
//---------------------------------------------------------------------------------------------
int start() {
 
  CreateObjectsOnPanel();
  _FlagWindowWidthChanged = false;

  return(0);
}

//---------------------------------------------------------------------------------------------
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
  if(CHARTEVENT_CHART_CHANGE)
  {
    // Вычисляем размер окна
    CalculateWindowRect();
    // Если ширина окна изменилась, пересоздаем объекты
    if (_FlagWindowWidthChanged)
    {
      CreateObjectsOnPanel();
    }
  }
}

//---------------------------------------------------------------------------------------------
void CreateObjectsOnPanel()
{
  RemoveObjects(IndName);

  int _aGUI_Y = _GUI_Y;
  string _Caption;
  _Caption = "Last  "+HistOrdersCount+"  trades";
  if (FilterMagic) _Caption=_Caption+" (Magic="+Magic+") ";
  _Caption=_Caption+":";
  
  CreateLabel(LabelsPrefix+"Caption1", _Caption, _GUI_X, _aGUI_Y, GUI_FontColor);
  _aGUI_Y = _aGUI_Y + GUI_LabelsYDist;
  CreateLabel(LabelsPrefix+"Caption2", "------------------------------------------------", _GUI_X, _aGUI_Y, GUI_FontColor);

  int _OrdCount = OrdersHistoryTotal();
  int i, j;
  int iSymbol = 0;
  MqlDateTime _structOCT;
  string _string;
  int _aGUI_X;
  bool _Buy;
  bool _Sell;
  double _OrderProfit, _TotalProfit, _CompensationProfit = 0;
  color _Color;
  double _ArrayProfitsZA[100];
  double _ArrayProfitsAZ[100];
  double _ArrayCompProfits[100];
  
   for (i=OrdersHistoryTotal(); i>=0; i--)
   {
     if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true)
     {
       if (OrderSymbol()==Symbol())
       {
         if(OrderCloseTime()<StartFromDate) continue;
         if ((FilterMagic) && (OrderMagicNumber()!=Magic)) continue;
         
         _Buy = OrderType() == OP_BUY;
         _Sell = OrderType() == OP_SELL;
         if (_Buy || _Sell)
         {
            iSymbol = iSymbol+1;
            _aGUI_Y = _aGUI_Y + GUI_LabelsYDist;
            TimeToStruct(OrderCloseTime(),_structOCT);

            //day_of_week
            _string = GetDayOfWeekNameFromInt(_structOCT.day_of_week);
            _aGUI_X = _GUI_X;
             CreateLabel(LabelsPrefix+"OrderCloseDW"+iSymbol, _string, _aGUI_X, _aGUI_Y, GUI_FontColor);
            
            //close date
            _string = LeadZeroDate(_structOCT.day)+"."+LeadZeroDate(_structOCT.mon);
            _aGUI_X = _GUI_X + GUI_FontSize*2;
             CreateLabel(LabelsPrefix+"OrderCloseTime"+iSymbol, _string, _aGUI_X, _aGUI_Y, GUI_FontColor);
            _aGUI_X = _GUI_X + GUI_FontSize*2+ GUI_FontSize*5+2;
            if (_Buy) _string = "Buy";
              else _string = "Sell";
            CreateLabel(LabelsPrefix+"OrderType"+iSymbol, _string, _aGUI_X, _aGUI_Y, GUI_FontColor);

            _aGUI_X = _GUI_X + GUI_FontSize*2+ GUI_FontSize*5 + GUI_FontSize*3;
            CreateLabel(LabelsPrefix+"OrderLot"+iSymbol, OrderLots(), _aGUI_X, _aGUI_Y, GUI_FontColor);
            _aGUI_X = _GUI_X + GUI_FontSize*2+ GUI_FontSize*5 + GUI_FontSize*3 + GUI_FontSize*4+1;
            _OrderProfit = OrderProfit();
            _Color=GetColorForProfit(_OrderProfit);
            _string = LeadPlusPositive(_OrderProfit);
            CreateLabel(LabelsPrefix+"OrderProfit"+iSymbol, _string, _aGUI_X, _aGUI_Y, _Color);
            
            //CompensationProfit profit
            _ArrayProfitsZA[iSymbol] = _OrderProfit;
            //Total profit
            _TotalProfit = _TotalProfit + _OrderProfit;

             if (iSymbol==HistOrdersCount) break;
        }
        
        } // if (OrderSymbol()==Symbol())
      } //if (OrderSelect
   } // for i
   
   //CompensationProfit
   //Заполняем профиты в нормальном порядке ордеров
   j=0;
   for (i=iSymbol; i>=1; i--)
   {
      j=j+1;
      _ArrayProfitsAZ[j] = _ArrayProfitsZA[i];
   }
   //Вычисляем компенсацию профитов в нормальном порядке ордеров
   for (i=1; i<=iSymbol; i++)
   {
     _CompensationProfit=_CompensationProfit+_ArrayProfitsAZ[i];
     _ArrayCompProfits[i]=_CompensationProfit;
     if (_CompensationProfit>0) _CompensationProfit=0;
   }
   //Выводим компенсацию профитов в обратном порядке ордеров
   int _aGUI_Yc;
   _aGUI_Yc = _GUI_Y + GUI_LabelsYDist;
   for (i=iSymbol; i>=1; i--)
   {
     _aGUI_Yc = _aGUI_Yc + GUI_LabelsYDist;
     _aGUI_X = _GUI_X + GUI_FontSize*2+ GUI_FontSize*5 + GUI_FontSize*3 + GUI_FontSize*4+3 + GUI_FontSize*6-1;
     _Color=GetColorForProfit(_ArrayCompProfits[i]);
     if (_ArrayCompProfits[i]<0)
       _string=CharToStr(251);
     else _string=CharToStr(252);
     CreateLabel(LabelsPrefix+"CompensationProfit"+i,  _string, CORNER_LEFT_UPPER, _aGUI_X, _aGUI_Yc, "Wingdings", GUI_FontSize+2, _Color);
     if ((!CompensationAll)&&(_ArrayCompProfits[i]>0)) break;
   }
  
  //Итого
  _aGUI_Y = _aGUI_Y + GUI_LabelsYDist;
  CreateLabel(LabelsPrefix+"Caption3", "------------------------------------------------", _GUI_X, _aGUI_Y, GUI_FontColor);
  _aGUI_Y = _aGUI_Y + GUI_LabelsYDist;
  CreateLabel(LabelsPrefix+"Caption4", "Total", _GUI_X, _aGUI_Y, GUI_FontColor);
  _aGUI_X = _GUI_X + GUI_FontSize*2+GUI_FontSize*5 + GUI_FontSize*3 + GUI_FontSize*4+1;
  _string = LeadPlusPositive(_TotalProfit);
  _Color=GetColorForProfit(_TotalProfit);
  CreateLabel(LabelsPrefix+"TotalProfit", _string, _aGUI_X, _aGUI_Y, _Color);
 
}

string GetDayOfWeekNameFromInt(int aDayOfWeek)
{
  string _Result;
  switch(aDayOfWeek)
  {
    case 1: _Result="пн"; break;
    case 2: _Result="вт"; break;
    case 3: _Result="ср"; break;
    case 4: _Result="чт"; break;
    case 5: _Result="пт"; break;
    case 6: _Result="сб"; break;
    case 7: _Result="вс"; break;
    default: _Result="?"+aDayOfWeek;
  }
  return(_Result);
}


string LeadZeroDate(int aNumber)
{
  string _Result;
  if (aNumber<10) _Result="0"+aNumber;
  else _Result=aNumber;
  return(_Result);
}

string LeadPlusPositive(double aNumber)
{
  string _Result;
  if (aNumber>0) _Result="+ "+aNumber;
  if (aNumber==0) _Result="   "+aNumber;
  if (aNumber<0) _Result="-  "+(-1*aNumber);
  return(_Result);
}

color GetColorForProfit(double aProfit)
{
  color _Result;
  if (aProfit<0) _Result=GUI_FontNagative;
    else _Result=GUI_FontColor;
  return(_Result);
}

//---------------------------------------------------------------------------------------------
//
//  Работа с объектами на графике
//
//---------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------------
//  Удаляет свои объекты с графика
//  Процедура не моя, где взял не помню
//---------------------------------------------------------------------------------------------
void RemoveObjects(string Prefix)
{
   for(int k=ObjectsTotal()-1; k>=0; k--) 
     {
      string Obj_Name=ObjectName(k);                           // Запpашиваeм имя объeкта
      string Head=StringSubstr(Obj_Name,0,StringLen(Prefix)); // Извлeкаeм первыe симолы
      if (Head==Prefix)// Найдeн объeкт, ..
         {
         ObjectDelete(Obj_Name);
         }                  
     }
}

//---------------------------------------------------------------------------------------------
//  Создает Label (упрощенный вызов)
//---------------------------------------------------------------------------------------------

void CreateLabel(string aLabelName, string aLabelText, int aXDISTANCE, int aYDISTANCE, color aColor)
{
  CreateLabel(aLabelName, aLabelText, CORNER_LEFT_UPPER, aXDISTANCE, aYDISTANCE, GUI_FontName, GUI_FontSize, aColor);
}

//---------------------------------------------------------------------------------------------
//  Создает Label
//---------------------------------------------------------------------------------------------
void CreateLabel(string aLabelName, string aLabelText, int aCorner, int aXDISTANCE, int aYDISTANCE, string aFontName, int aFontSize, color aColor)
{
   ObjectDelete(aLabelName);
   ObjectCreate(aLabelName, OBJ_LABEL, _GUI_WindowNumber, 0, 1.0);
   ObjectSet(aLabelName, OBJPROP_CORNER, aCorner);
   ObjectSet(aLabelName, OBJPROP_XDISTANCE, aXDISTANCE);
   ObjectSet(aLabelName, OBJPROP_YDISTANCE, aYDISTANCE);
   ObjectSetText(aLabelName, aLabelText, aFontSize, aFontName, aColor);
}

//---------------------------------------------------------------------------------------------
//  Вычисляет ширину и высоту окна в переменные GUI_Window_Width, GUI_Window_Height
//  Устанавливает флаг GUI_Window_FlagWidthChanged
//---------------------------------------------------------------------------------------------
void CalculateWindowRect()
{
  int _Window_rect[4];     // Массив координат окна
  int _aGUI_Window_Width;   // Ширина окна (локальная)

  // Вычисляем Rect окна и определяем ширину
  GetWindowRect(WindowHandle(Symbol(), Period()), _Window_rect);
  _aGUI_Window_Width = _Window_rect[2]-_Window_rect[0];

  // Если ширина изменилась и панель справа, то выставляем флаг изменения ширины окна
  // используется в OnChartEvent для перерисовки контролов
  if (_aGUI_Window_Width!=_GUI_Window_Width)
  {
    _GUI_Window_Width=_aGUI_Window_Width;
    _FlagWindowWidthChanged=true;
  }
    
  // Оперативный сдвиг по X
  if (GUI_Left)
  {
    _GUI_X = GUI_X;
  }
  else
  {
    _GUI_X = (_Window_rect[2]-_Window_rect[0]-48)-GUI_Right_Offset+GUI_X;
  }

  // Высота окна
  _GUI_Window_Height = _Window_rect[3]-_Window_rect[1];
  
  _GUI_Y=GUI_Y;
}
