Price Data Components
Miscellaneous
0
Views
0
Downloads
0
Favorites
EquityChartModeller
#property copyright "EquityChartModeller - by transcendreamer - origins from Xupypr"
// The indicator plots virtual equity charts representing a portfolios (synthethic instruments)
// Portfolios may consist of any number of positions, long and short, currencies and CFDs, with any lots
// Example of portfolio formula syntax: EURGBP+2.5 AUDCAD-1.1 NZDJPY+1.2 #MSFT+5 #GE-3
// PLUS = long position, MINUS = short position, SPACE = separator
// Spreads, commisssions and swaps are not counted
///////////////////////////////////////////////////////////////////////////
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_level1 0
///////////////////////////////////////////////////////////////////////////
extern datetime Time_Start_Chart=D'2012.01.01 00:00';
extern datetime Time_Stop_Chart=D'2019.12.31 00:00';
extern datetime Time_Zero_Level=D'2012.01.01 00:00';
extern string Portfolio_Formula_A="";
extern string Portfolio_Formula_B="";
extern double Lot_Divider=100;
extern int Period_Zero_Level=1440;
extern bool Plot_Difference=false;
extern bool Plot_Inversion=false;
extern bool Show_Grid=false;
extern int Grid_Interval=1000;
extern color Color_Portfolio_1=DarkViolet;
extern color Color_Portfolio_2=Green;
extern color Color_Difference=Red;
extern int Update_Seconds=5;
///////////////////////////////////////////////////////////////////////////
int Total,BlocksTotal,BlocksLastN,inv,num_A,num_B;
bool Error;
int OpenBar,CloseBar,ZeroBar;
int Index[2];
string Block[],Instrument[];
double Lots[],OpenPrice[],ClosePrice[];
double Portfolio1[],Portfolio2[],Difference[];
string Missing;
int Window;
string currency;
datetime tick;
///////////////////////////////////////////////////////////////////////////
int init()
{
IndicatorDigits(2);
IndicatorShortName("Equity Chart");
Window=WindowFind("Equity Chart");
ObjectsDeleteAll(Window,EMPTY);
SetIndexBuffer(0,Portfolio1);
SetIndexBuffer(1,Portfolio2);
SetIndexBuffer(2,Difference);
SetIndexStyle(0,DRAW_LINE,DRAW_LINE,1,Color_Portfolio_1); SetIndexLabel(0,"Portfolio A");
SetIndexStyle(1,DRAW_LINE,DRAW_LINE,1,Color_Portfolio_2); SetIndexLabel(1,"Portfolio B");
SetIndexStyle(2,DRAW_LINE,DRAW_LINE,1,Color_Difference); SetIndexLabel(2,"Difference");
Error=false; Missing=""; Total=0; BlocksTotal=0; BlocksLastN=0;
currency=AccountCurrency();
if(Plot_Difference && Plot_Inversion) inv=-1; else inv=1;
ArrayInitialize(Portfolio1,EMPTY_VALUE);
ArrayInitialize(Portfolio2,EMPTY_VALUE);
ArrayInitialize(Difference,EMPTY_VALUE);
if(Portfolio_Formula_A!="") SetPositions(Portfolio_Formula_A,1); num_A=Total;
if(Portfolio_Formula_B!="") SetPositions(Portfolio_Formula_B,2); num_B=Total-num_A;
if(Total==0) { Alert("No data for charting!"); return(0); }
if(Error) { Alert("Missing symbols in Market Watch: "+Missing); return(0); }
int y_offset=25;
for(int j=0;j<Total;j++)
{
if(Plot_Difference && Plot_Inversion) int sign_inv=-1; else sign_inv=1;
if(Lots[j]<0) int sign_lot=-1; else sign_lot=1;
if(Index[j]==2 && Plot_Difference) int sign_2nd=-1; else sign_2nd=1;
if(sign_inv*sign_2nd*sign_lot==1) string sign="+";
if(sign_inv*sign_2nd*sign_lot==-1) sign="-";
string text=StringConcatenate(Instrument[j],sign,MathAbs(Lots[j]));
if(Index[j]==1) {int colour=Color_Portfolio_1; string prefix="A_";}
if(Index[j]==2) {colour=Color_Portfolio_2; prefix="B_";}
if(Plot_Difference) {colour=Color_Difference; prefix="X_";}
PlaceLabel(prefix+j,5,y_offset,0,text,colour);
if(!Plot_Difference && j==num_A-1) y_offset+=11;
y_offset+=11;
}
return(0);
}
///////////////////////////////////////////////////////////////////////////
int start()
{
if(Total==0) return(0);
if(TimeCurrent()-tick<Update_Seconds) return(0);
else tick=TimeCurrent();
if(Period()>Period_Zero_Level) int Period_Work=Period();
else Period_Work=Period_Zero_Level;
bool seek_history=true;
datetime Current_Time=Time_Zero_Level;
while(seek_history && Current_Time<=Time[0] && Current_Time<=Time_Stop_Chart)
{
seek_history=false;
for(int i=0;i<Total;i++)
{
int shift=iBarShift(Instrument[i],Period_Work,Current_Time,true);
if(shift!=-1) OpenPrice[i]=iClose(Instrument[i],Period_Work,shift);
else seek_history=true;
}
if(seek_history) Current_Time+=Period()*60;
}
if(Time_Zero_Level<Current_Time) Time_Zero_Level=Current_Time;
OpenBar=iBarShift(NULL,0,Time_Start_Chart);
CloseBar=iBarShift(NULL,0,Time_Stop_Chart);
for(i=OpenBar;i>=CloseBar;i--)
{
double PL1=0; double PL2=0;
for(int j=0;j<Total;j++)
{
ClosePrice[j]=iClose(Instrument[j],0,iBarShift(Instrument[j],0,Time[i]));
double result=(ClosePrice[j]-OpenPrice[j])*LotSize(Instrument[j],Time[i])*Lots[j]/Lot_Divider;
if(Index[j]==1) PL1+=result;
if(Index[j]==2) PL2+=result;
}
if(!Plot_Difference)
{if(Portfolio_Formula_A!="") Portfolio1[i]=NormalizeDouble(PL1,2);
if(Portfolio_Formula_B!="") Portfolio2[i]=NormalizeDouble(PL2,2);}
else Difference[i]=NormalizeDouble(PL1-PL2,2)*inv;
}
if(Show_Grid) Grid();
return(0);
}
///////////////////////////////////////////////////////////////////////////
void Grid()
{
if(Portfolio_Formula_A!=""&&!Plot_Difference)
PlaceLine("Equity_A",Portfolio1[CloseBar],Color_Portfolio_1,STYLE_DOT);
if(Portfolio_Formula_B!=""&&!Plot_Difference)
PlaceLine("Equity_B",Portfolio2[CloseBar],Color_Portfolio_2,STYLE_DOT);
if(Plot_Difference)
PlaceLine("Equity",Difference[CloseBar],Color_Difference,STYLE_DOT);
PlaceMark("Zero_point",Time_Zero_Level,Gray,STYLE_DOT);
double max=-2147483647; double min=2147483647;
for(int i=OpenBar;i>=CloseBar;i--)
{
if(Plot_Difference)
{if(Difference[i]>max) max=Difference[i];
if(Difference[i]<min) min=Difference[i];}
else
{if(Portfolio1[i]>max && Portfolio_Formula_A!="") max=Portfolio1[i];
if(Portfolio1[i]<min && Portfolio_Formula_A!="") min=Portfolio1[i];
if(Portfolio2[i]>max && Portfolio_Formula_B!="") max=Portfolio2[i];
if(Portfolio2[i]<min && Portfolio_Formula_B!="") min=Portfolio2[i];}
}
double y=0;
while(y<max) {y+=Grid_Interval;PlaceLine("Level_P"+y,y,Gray,STYLE_DOT);}
y=0;
while(y>min) {y-=Grid_Interval;PlaceLine("Level_N"+y,y,Gray,STYLE_DOT);}
}
///////////////////////////////////////////////////////////////////////////
double LotSize(string symbol, datetime tbar)
{
double size,close1,close2;
string BQ;
if(currency=="") currency="USD";
int type=MarketInfo(symbol,MODE_PROFITCALCMODE);
switch (type)
{
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")
{
close1=iClose(symbol,0,sbar);
if(close1>0) size=size/close1;
}
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);
close1=iClose(symbol,0,sbar);
close2=iClose(BQ,0,BQbar);
if(close1>0 && close2>0)
{
if(StringSubstr(BQ,0,3)=="USD") size=size/close2/close1;
else size=size*close2/close1;
}
}
} 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;
close1=iClose(BQ,0,iBarShift(BQ,0,tbar));
if(close1>0) size*=close1;
}
else
{
close1=iClose(BQ,0,iBarShift(BQ,0,tbar));
if(close1>0) size/=close1;
}
}
return(size);
}
///////////////////////////////////////////////////////////////////////////
void SetPositions(string name, int number)
{
BlocksLastN=BlocksTotal;
SeparateBlocks(name);
for(int i=BlocksLastN;i<BlocksTotal;i++)
{
Total++;
ArrayResize(Lots,Total);
ArrayResize(Instrument,Total);
ArrayResize(OpenPrice,Total);
ArrayResize(ClosePrice,Total);
ArrayResize(Index,Total);
int length=StringLen(Block[i]);
int p=length-1;
while(p>=0)
{
string X=StringSubstr(Block[i],p,1);
if(X=="+"||X=="-") break;
if(p==0) break;
else p--;
}
Index[Total-1]=number;
Instrument[Total-1]=StringSubstr(Block[i],0,p);
if(p==0) Lots[Total-1]=1;
else Lots[Total-1]=StrToDouble(StringSubstr(Block[i],p,length-p));
if(MarketInfo(Instrument[Total-1],MODE_POINT)==0)
{Missing=StringConcatenate(Missing," ",Instrument[Total-1]);Error=true;}
}
}
///////////////////////////////////////////////////////////////////////////
void SeparateBlocks(string text)
{
string fragment="";
int length=StringLen(text);
for(int position=0;position<length;position++)
{
int sym=StringGetChar(text,position);
if(sym!=32&&sym!=9&&sym!=10&&sym!=13) fragment=fragment+StringSubstr(text,position,1);
if(sym==32||sym==9||sym==10||sym==13||position==length-1)
if(StringLen(fragment)>0)
{BlocksTotal++;ArrayResize(Block,BlocksTotal);
Block[BlocksTotal-1]=fragment;fragment="";}
}
}
///////////////////////////////////////////////////////////////////////////
void PlaceLabel(string name, int x, int y, int corner, string text, int colour)
{
ObjectCreate(name,OBJ_LABEL,Window,0,0);
ObjectSet(name,OBJPROP_CORNER,corner);
ObjectSet(name,OBJPROP_XDISTANCE,x);
ObjectSet(name,OBJPROP_YDISTANCE,y);
ObjectSetText(name,text,8,"Tahoma",colour);
}
///////////////////////////////////////////////////////////////////////////
void PlaceLine(string name, int price, int colour, int style)
{
ObjectCreate(name,OBJ_HLINE,Window,0,price);
ObjectSet(name,OBJPROP_COLOR,colour);
ObjectSet(name,OBJPROP_STYLE,style);
}
///////////////////////////////////////////////////////////////////////////
void PlaceMark(string name, datetime mark, int colour, int style)
{
ObjectCreate(name,OBJ_VLINE,Window,mark,0);
ObjectSet(name,OBJPROP_COLOR,colour);
ObjectSet(name,OBJPROP_STYLE,style);
}
///////////////////////////////////////////////////////////////////////////
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---