#property copyright "EquityHedgeGraph - by transcendreamer - origins from Xupypr"
// building two equity graphs, one vs another, to seek hedge opportunities visually
// each graph may represent a single instrument or a lot-adusted basket
// spreads and swaps are not counted
// Total = Side_A - Side_B

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Green
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_level1 0

extern datetime Time_Open=D'2012.01.01 00:00';  // Время одновременного открытия позиций
extern datetime Time_Close=D'2019.12.31 00:00'; // Время одновременного закрытия позиций
extern bool     General_Line=false; // Использовать граф.объекты - линии для установки времени открытия/закрытия
extern double   Default_Lot=0.01;    // Размер лота по умолчанию, если он не указан дополнительно в перечне символов
//--- Перечни символов, которые условно открываются в buy или в sell
//--- "На хвост" символу может дописываться размер лота
//--- Если размер лота не дописан, применяется лот по умолчанию
//--- Количество символов в пакете произвольное
extern string   Symbols_Side_A="GBPUSD+1 GBPJPY+1";
extern string   Symbols_Side_B="EURUSD+1 EURJPY+1";
extern bool     Show_Side_A=true;   // Отображать эквити позиций группы А
extern bool     Show_Side_B=true;  // Отображать эквити позиций группы Б
extern bool     Show_Total=false;  // Отображать суммарное эквити

int      Total;
bool     First;
double   TotalEquity[],Equity_A[],Equity_B[];
string   ShortName;

int      OpenBar;      // номер бара открытия
int      CloseBar;     // Номер бара закрытия
int      Type[];       // тип операции
string   Instrument[]; // инструмент
double   Lots[];       // количество лотов
double   OpenPrice[];  // цена открытия

//+----------------------------------------------------------------------------+
//|  Custom indicator initialization function                                  |
//+----------------------------------------------------------------------------+
int init()
{
 SetIndexBuffer(0,TotalEquity);
 SetIndexLabel(0,"Total");
 SetIndexStyle(0,DRAW_LINE);
 SetIndexBuffer(1,Equity_A);
 SetIndexLabel(1,"Side A");
 SetIndexStyle(1,DRAW_LINE);
 SetIndexBuffer(2,Equity_B);
 SetIndexLabel(2,"Side B");
 SetIndexStyle(2,DRAW_LINE);
 ShortName="Equity Hedge Graph";
 //if (Show_Total) ShortName=StringConcatenate(ShortName," Total");
 //if (Show_Side_A)   ShortName=StringConcatenate(ShortName," Side A");
 //if (Show_Side_B)  ShortName=StringConcatenate(ShortName," Side B");
 IndicatorShortName(ShortName);
 //
 int Window=WindowFind(ShortName);
 ObjectCreate("EquityA",OBJ_LABEL,Window,0,0);
 ObjectSet("EquityA",OBJPROP_XDISTANCE,5);
 ObjectSet("EquityA",OBJPROP_YDISTANCE,15);
 ObjectSet("EquityA",OBJPROP_CORNER,0);
 ObjectSetText("EquityA",Symbols_Side_A,7,"Tahoma",indicator_color2);
 //
 ObjectCreate("EquityB",OBJ_LABEL,Window,0,0);
 ObjectSet("EquityB",OBJPROP_XDISTANCE,5);
 ObjectSet("EquityB",OBJPROP_YDISTANCE,25);
 ObjectSet("EquityB",OBJPROP_CORNER,0);
 ObjectSetText("EquityB",Symbols_Side_B,7,"Tahoma",indicator_color3);
 //
 IndicatorDigits(2);
 First=true;
 return(0);
}
//+----------------------------------------------------------------------------+
//|  Custom indicator iteration function                                       |
//+----------------------------------------------------------------------------+
int start()
{
 static string minfosymbols="";
 double A_profitloss,B_profitloss,spread,lotsize;
 int bar,i,j;
/*
 if (!IsConnected())
 {
  Print("Связь с сервером отсутствует или прервана");
  return(0);
 }
*/
 if (General_Line)
 {
  if (ObjectFind("openall")==-1) ObjectCreate("openall",OBJ_VLINE,0,Time_Open,0);
  if (ObjectFind("closeall")==-1) ObjectCreate("closeall",OBJ_VLINE,0,Time_Close,0);
  if (ObjectGet("openall",OBJPROP_TIME1)!=Time_Open || ObjectGet("closeall",OBJPROP_TIME1)!=Time_Close)
  {
   First=true;
   Time_Open=ObjectGet("openall",OBJPROP_TIME1);
   Time_Close=ObjectGet("closeall",OBJPROP_TIME1);
   ArrayInitialize(TotalEquity,EMPTY_VALUE);
   ArrayInitialize(Equity_A,EMPTY_VALUE);
   ArrayInitialize(Equity_B,EMPTY_VALUE);
  }
 }
 OpenBar=iBarShift(NULL,0,Time_Open);
 CloseBar=iBarShift(NULL,0,Time_Close,true);
 if (First)
 {
  First=false;
  Total=0;
  SetOrder(Symbols_Side_A,OP_BUY);
  SetOrder(Symbols_Side_B,OP_SELL);
  if (Total==0)
  {
   Alert("Ни одного символа не задано!");
   return(0);
  }
 }
 else
 {
  if (Total==0) return(0);
  if (CloseBar>=0) return(0);
  else
  {
   OpenBar=1;
   CloseBar=0;
  }
 }
 for (i=OpenBar;i>=CloseBar;i--)
 {
  A_profitloss=0.0;
  B_profitloss=0.0;
  for (j=0;j<Total;j++)
  {
   if (MarketInfo(Instrument[j],MODE_POINT)==0)
   {
    if (StringFind(minfosymbols,Instrument[j])==-1)
    {
     Alert("В обзоре рынка не хватает "+Instrument[j]);
     minfosymbols=StringConcatenate(minfosymbols," ",Instrument[j]);
    }
    continue;
   }
   bar=iBarShift(Instrument[j],0,Time[i]);
   lotsize=LotSize(Instrument[j],Time[i]);
   if (Type[j]==OP_BUY) A_profitloss+=(iClose(Instrument[j],0,bar)-OpenPrice[j])*Lots[j]*lotsize;
   else
   {
    //spread=MarketInfo(Instrument[j],MODE_POINT)*MarketInfo(Instrument[j],MODE_SPREAD);
    //B_profitloss+=(OpenPrice[j]-iClose(Instrument[j],0,bar)-spread)*Lots[j]*lotsize;
    B_profitloss+=(iClose(Instrument[j],0,bar)-OpenPrice[j])*Lots[j]*lotsize;
   }
  }
  if (Show_Total) TotalEquity[i]=NormalizeDouble(A_profitloss-B_profitloss,2);
  if (Show_Side_A) Equity_A[i]=NormalizeDouble(A_profitloss,2);
  if (Show_Side_B) Equity_B[i]=NormalizeDouble(B_profitloss,2);
 }
  return(0);
}
//+----------------------------------------------------------------------------+
//|  Определение размера контракта                                             |
//+----------------------------------------------------------------------------+
double LotSize(string symbol, datetime tbar)
{
 double size;
 string BQ,currency=AccountCurrency();
 switch (MarketInfo(symbol,MODE_PROFITCALCMODE))
 {
  case 0:
  {
   int sbar=iBarShift(symbol,0,tbar);
   size=MarketInfo(symbol,MODE_LOTSIZE);
   if (StringSubstr(symbol,3,3)=="USD") break;
   if (StringSubstr(symbol,0,3)=="USD") size=size/iClose(symbol,0,sbar);
   else
   {
    BQ=StringSubstr(symbol,0,3)+"USD";
    if (iClose(BQ,0,0)==0) BQ="USD"+StringSubstr(symbol,0,3);
    if (iClose(BQ,0,0)==0) break;
    int BQbar=iBarShift(BQ,0,tbar);
    if (StringSubstr(BQ,0,3)=="USD") size=size/iClose(BQ,0,BQbar)/iClose(symbol,0,sbar);
    else size=size*iClose(BQ,0,BQbar)/iClose(symbol,0,sbar);
   }
  } break;
  case 1: size=MarketInfo(symbol,MODE_LOTSIZE); break;
  case 2: size=MarketInfo(symbol,MODE_TICKVALUE)/MarketInfo(symbol,MODE_TICKSIZE);
 }
 if (currency!="USD")
 {
  BQ=currency+"USD";
  if (iClose(BQ,0,0)==0)
  {
   BQ="USD"+currency;
   size*=iClose(BQ,0,iBarShift(BQ,0,tbar));
  }
  else size/=iClose(BQ,0,iBarShift(BQ,0,tbar));
 }
 return(size);
}
//+----------------------------------------------------------------------------+
//|  Установка параметров ордера                                               |
//+----------------------------------------------------------------------------+
void SetOrder(string name, int cmd)
{
 int length,pos,end;
 
 length=StringLen(name);
 pos=0;
 while (pos<length)
 {
  Total++;
  ArrayResize(Type,Total);
  ArrayResize(Instrument,Total);
  ArrayResize(Lots,Total);
  ArrayResize(OpenPrice,Total);
  Type[Total-1]=cmd;
  Instrument[Total-1]=StringSubstr(name,pos,6);
  pos+=6;
  if (StringGetChar(name,pos)==32 || (length-1)<pos) Lots[Total-1]=Default_Lot;
  else
  {
   end=0;
   while(StringGetChar(name,pos+end)!=32)
   {
    if ((length-1)<pos+end) break;
    end++;
   }
   Lots[Total-1]=StrToDouble(StringSubstr(name,pos,pos+end));
   pos+=end;
  }
  pos++;
  OpenPrice[Total-1]=iOpen(Instrument[Total-1],0,iBarShift(Instrument[Total-1],0,Time_Open));
  //if (cmd==OP_BUY) OpenPrice[Total-1]+=MarketInfo(Instrument[Total-1],MODE_POINT)*MarketInfo(Instrument[Total-1],MODE_SPREAD);
 }
}
//+----------------------------------------------------------------------------+

