456 lines
8.9 KiB
MQL4
456 lines
8.9 KiB
MQL4
|
|
#property indicator_separate_window
|
||
|
|
#property indicator_buffers 1
|
||
|
|
#property indicator_color1 Red
|
||
|
|
#property indicator_width1 1
|
||
|
|
|
||
|
|
#define MAX_AMOUNTSYMBOLS 15
|
||
|
|
#define MAX_POINTS 100000
|
||
|
|
|
||
|
|
extern int Margin = 1000;
|
||
|
|
extern color ColorText = Gray;
|
||
|
|
|
||
|
|
string FontName = "Arial";
|
||
|
|
|
||
|
|
string SymbolsStr;
|
||
|
|
int Depth;
|
||
|
|
|
||
|
|
double Buffer[];
|
||
|
|
|
||
|
|
string Symbols[MAX_AMOUNTSYMBOLS];
|
||
|
|
double BaseMatrix[][MAX_POINTS];
|
||
|
|
double Means[], Vars[], SVector[];
|
||
|
|
int Times[MAX_POINTS];
|
||
|
|
double Recycles[];
|
||
|
|
int AmountSymbols, MatrixRows;
|
||
|
|
double Vectors[][MAX_POINTS];
|
||
|
|
int StartTime;
|
||
|
|
double Data[];
|
||
|
|
double Lots[], Spreads[], TickValues[];
|
||
|
|
|
||
|
|
string IndName = "RecycleProfit";
|
||
|
|
string UName;
|
||
|
|
|
||
|
|
void GetConfig( string FileName )
|
||
|
|
{
|
||
|
|
int handle = FileOpen(FileName, FILE_CSV|FILE_READ);
|
||
|
|
|
||
|
|
SymbolsStr = FileReadString(handle);
|
||
|
|
FileReadNumber(handle); // Correlation
|
||
|
|
Depth = FileReadNumber(handle);
|
||
|
|
|
||
|
|
FileClose(handle);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
string StrDelSpaces( string Str )
|
||
|
|
{
|
||
|
|
int Pos, Length;
|
||
|
|
|
||
|
|
Str = StringTrimLeft(Str);
|
||
|
|
Str = StringTrimRight(Str);
|
||
|
|
|
||
|
|
Length = StringLen(Str) - 1;
|
||
|
|
Pos = 1;
|
||
|
|
|
||
|
|
while (Pos < Length)
|
||
|
|
if (StringGetChar(Str, Pos) == ' ')
|
||
|
|
{
|
||
|
|
Str = StringSubstr(Str, 0, Pos) + StringSubstr(Str, Pos + 1, 0);
|
||
|
|
Length--;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
Pos++;
|
||
|
|
|
||
|
|
return(Str);
|
||
|
|
}
|
||
|
|
|
||
|
|
int StrToStringS( string Str, string Razdelitel, string &Output[] )
|
||
|
|
{
|
||
|
|
int Pos, LengthSh;
|
||
|
|
int Count = 0;
|
||
|
|
|
||
|
|
Str = StrDelSpaces(Str);
|
||
|
|
Razdelitel = StrDelSpaces(Razdelitel);
|
||
|
|
|
||
|
|
LengthSh = StringLen(Razdelitel);
|
||
|
|
|
||
|
|
while (TRUE)
|
||
|
|
{
|
||
|
|
Pos = StringFind(Str, Razdelitel);
|
||
|
|
Output[Count] = StringSubstr(Str, 0, Pos);
|
||
|
|
Count++;
|
||
|
|
|
||
|
|
if (Pos == -1)
|
||
|
|
break;
|
||
|
|
|
||
|
|
Pos += LengthSh;
|
||
|
|
Str = StringSubstr(Str, Pos);
|
||
|
|
}
|
||
|
|
|
||
|
|
return(Count);
|
||
|
|
}
|
||
|
|
|
||
|
|
datetime GetStartTime( string FileName )
|
||
|
|
{
|
||
|
|
int handle = FileOpen(FileName, FILE_BIN|FILE_READ);
|
||
|
|
int T[], Time0, CurrTime, Pos = 0;
|
||
|
|
|
||
|
|
if (FileSize(handle) == 0)
|
||
|
|
return(0);
|
||
|
|
Time0 = FileReadInteger(handle);
|
||
|
|
FileClose(handle);
|
||
|
|
|
||
|
|
ArrayResize(T, Depth);
|
||
|
|
|
||
|
|
CurrTime = iTime(Symbols[0], Period(), iBarShift(Symbols[0], Period(), Time0) + Depth);
|
||
|
|
|
||
|
|
while (CurrTime < Time0)
|
||
|
|
{
|
||
|
|
T[Pos] = CurrTime;
|
||
|
|
|
||
|
|
if (Pos < Depth - 1)
|
||
|
|
Pos++;
|
||
|
|
else
|
||
|
|
Pos = 0;
|
||
|
|
|
||
|
|
CurrTime = GetNextTime(CurrTime);
|
||
|
|
}
|
||
|
|
|
||
|
|
return(T[Pos]);
|
||
|
|
}
|
||
|
|
|
||
|
|
double GetPrice( string Symb, int time )
|
||
|
|
{
|
||
|
|
double Price;
|
||
|
|
|
||
|
|
Price = iClose(Symb, Period(), iBarShift(Symb, Period(), time));
|
||
|
|
|
||
|
|
return(Price);
|
||
|
|
}
|
||
|
|
|
||
|
|
int GetNextTime( int CurrTime )
|
||
|
|
{
|
||
|
|
static int Pos[MAX_AMOUNTSYMBOLS];
|
||
|
|
int i, MinTime, Tmp = -1;
|
||
|
|
|
||
|
|
for (i = 0; i < AmountSymbols; i++)
|
||
|
|
{
|
||
|
|
Pos[i] = iBarShift(Symbols[i], Period(), CurrTime) - 1;
|
||
|
|
|
||
|
|
if (Pos[i] >= 0)
|
||
|
|
Tmp = i;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Tmp < 0)
|
||
|
|
return(Time[0]);
|
||
|
|
|
||
|
|
MinTime = iTime(Symbols[Tmp], Period(), Pos[Tmp]);
|
||
|
|
|
||
|
|
i = Tmp - 1;
|
||
|
|
|
||
|
|
while (i >= 0)
|
||
|
|
{
|
||
|
|
if (Pos[i] >= 0)
|
||
|
|
{
|
||
|
|
Tmp = iTime(Symbols[i], Period(), Pos[i]);
|
||
|
|
|
||
|
|
if (Tmp < MinTime)
|
||
|
|
MinTime = Tmp;
|
||
|
|
}
|
||
|
|
|
||
|
|
i--;
|
||
|
|
}
|
||
|
|
|
||
|
|
return(MinTime);
|
||
|
|
}
|
||
|
|
|
||
|
|
void GetBaseMatrix()
|
||
|
|
{
|
||
|
|
int i, CurrTime = StartTime;
|
||
|
|
|
||
|
|
MatrixRows = 0;
|
||
|
|
|
||
|
|
while (CurrTime < Time[0])
|
||
|
|
{
|
||
|
|
for (i = 0; i < AmountSymbols; i++)
|
||
|
|
BaseMatrix[i][MatrixRows] = GetPrice(Symbols[i], CurrTime);
|
||
|
|
|
||
|
|
Times[MatrixRows] = CurrTime;
|
||
|
|
|
||
|
|
MatrixRows++;
|
||
|
|
|
||
|
|
CurrTime = GetNextTime(CurrTime);
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
double TrueTickValue( string Symb )
|
||
|
|
{
|
||
|
|
double TickValue = MarketInfo(Symb, MODE_TICKVALUE);
|
||
|
|
double Tmp = MarketInfo(Symb, MODE_MARGININIT);
|
||
|
|
|
||
|
|
if ((MarketInfo(Symb, MODE_MARGINCALCMODE) > 0) && (Tmp > 0))
|
||
|
|
TickValue *= MarketInfo(Symb, MODE_MARGINREQUIRED) / Tmp;
|
||
|
|
|
||
|
|
return(TickValue);
|
||
|
|
}
|
||
|
|
|
||
|
|
void GetMarket( int Pos )
|
||
|
|
{
|
||
|
|
double Tmp = 0;
|
||
|
|
|
||
|
|
RefreshRates();
|
||
|
|
|
||
|
|
for (int i = 0; i < AmountSymbols; i++)
|
||
|
|
{
|
||
|
|
Spreads[i] = MarketInfo(Symbols[i], MODE_SPREAD) * MarketInfo(Symbols[i], MODE_POINT);
|
||
|
|
TickValues[i] = TrueTickValue(Symbols[i]) / MarketInfo(Symbols[i], MODE_TICKSIZE);
|
||
|
|
|
||
|
|
if (Recycles[Pos] < 0)
|
||
|
|
Lots[i] = Vectors[i][Pos] / (MarketInfo(Symbols[i], MODE_ASK) * TickValues[i]);
|
||
|
|
else
|
||
|
|
Lots[i] = -Vectors[i][Pos] / (MarketInfo(Symbols[i], MODE_ASK) * TickValues[i]);
|
||
|
|
|
||
|
|
Tmp += MathAbs(Lots[i]) * MarketInfo(Symbols[i], MODE_MARGINREQUIRED);
|
||
|
|
|
||
|
|
if (MarketInfo(Symbols[i], MODE_MARGINREQUIRED) == 0)
|
||
|
|
Alert("Warning: MODE_MARGINREQUIRED(" + Symbols[i] + ") = 0.");
|
||
|
|
}
|
||
|
|
|
||
|
|
Tmp /= Margin;
|
||
|
|
|
||
|
|
for (i = 0; i < AmountSymbols; i++)
|
||
|
|
Lots[i] /= Tmp;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void GetData( string FileName )
|
||
|
|
{
|
||
|
|
int i = Depth, j;
|
||
|
|
double V[];
|
||
|
|
int handle = FileOpen(FileName, FILE_BIN|FILE_READ);
|
||
|
|
|
||
|
|
ArrayResize(V, AmountSymbols);
|
||
|
|
|
||
|
|
while (FileTell(handle) < FileSize(handle))
|
||
|
|
{
|
||
|
|
Times[i] = FileReadInteger(handle);
|
||
|
|
Recycles[i] = FileReadDouble(handle);
|
||
|
|
FileReadDouble(handle); // Divs[i]
|
||
|
|
|
||
|
|
FileReadArray(handle, V, 0, AmountSymbols);
|
||
|
|
|
||
|
|
for (j = 0; j < AmountSymbols; j++)
|
||
|
|
Vectors[j][i] = V[j];
|
||
|
|
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
|
||
|
|
FileClose(handle);
|
||
|
|
|
||
|
|
MatrixRows = i;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void init()
|
||
|
|
{
|
||
|
|
UName = "hwnd" + WindowHandle(Symbol(), Period());
|
||
|
|
|
||
|
|
if (!GlobalVariableCheck(UName))
|
||
|
|
return;
|
||
|
|
|
||
|
|
IndicatorDigits(8);
|
||
|
|
SetIndexStyle(0, DRAW_LINE, DRAW_LINE);
|
||
|
|
SetIndexBuffer(0, Buffer);
|
||
|
|
|
||
|
|
GetConfig(UName + ".ini");
|
||
|
|
|
||
|
|
AmountSymbols = StrToStringS(SymbolsStr, ",", Symbols);
|
||
|
|
|
||
|
|
ArrayResize(Symbols, AmountSymbols);
|
||
|
|
ArrayResize(BaseMatrix, AmountSymbols);
|
||
|
|
ArrayResize(Means, AmountSymbols);
|
||
|
|
ArrayResize(Vectors, AmountSymbols);
|
||
|
|
|
||
|
|
ArrayResize(Lots, AmountSymbols);
|
||
|
|
ArrayResize(Spreads, AmountSymbols);
|
||
|
|
ArrayResize(TickValues, AmountSymbols);
|
||
|
|
|
||
|
|
StartTime = GetStartTime(UName + ".dat");
|
||
|
|
|
||
|
|
GetBaseMatrix();
|
||
|
|
|
||
|
|
ArrayResize(Recycles, MatrixRows);
|
||
|
|
ArrayResize(Times, MatrixRows);
|
||
|
|
|
||
|
|
ArrayResize(Data, MatrixRows);
|
||
|
|
|
||
|
|
GetData(UName + ".dat");
|
||
|
|
|
||
|
|
return(TRUE);
|
||
|
|
}
|
||
|
|
|
||
|
|
int GetTimePos( int SearchTime )
|
||
|
|
{
|
||
|
|
int LeftTime, RightTime, PosTime;
|
||
|
|
int Left, Right, Pos = 0;
|
||
|
|
|
||
|
|
Left = 0;
|
||
|
|
Right = MatrixRows - 1;
|
||
|
|
|
||
|
|
LeftTime = Times[Left];
|
||
|
|
RightTime = Times[Right];
|
||
|
|
|
||
|
|
if (SearchTime >= RightTime)
|
||
|
|
Pos = Right;
|
||
|
|
|
||
|
|
while ((LeftTime < SearchTime) && (SearchTime < RightTime))
|
||
|
|
{
|
||
|
|
Pos = (Left + Right) >> 1;
|
||
|
|
PosTime = Times[Pos];
|
||
|
|
|
||
|
|
if (Pos == Left)
|
||
|
|
break;
|
||
|
|
|
||
|
|
if (SearchTime >= PosTime)
|
||
|
|
{
|
||
|
|
Left = Pos;
|
||
|
|
LeftTime = PosTime;
|
||
|
|
}
|
||
|
|
else // if (SearchTime < PosTime)
|
||
|
|
{
|
||
|
|
Right = Pos;
|
||
|
|
RightTime = PosTime;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return(Pos);
|
||
|
|
}
|
||
|
|
|
||
|
|
void DrawData( int Pos )
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
string Str = ")";
|
||
|
|
double Tmp = Data[Pos];
|
||
|
|
double Max = MathAbs(Tmp);
|
||
|
|
int NullTime, NullBar, MaxBar = Pos;
|
||
|
|
|
||
|
|
for (i = 0; i < MatrixRows; i++)
|
||
|
|
Buffer[iBarShift(Symbol(), Period(), Times[i])] = Data[i];
|
||
|
|
|
||
|
|
for (i = 0; i < AmountSymbols; i++)
|
||
|
|
ModifyTextObject(Symbols[i] + "_lots", Symbols[i] + " = " + Lots[i] + " lots");
|
||
|
|
|
||
|
|
WindowRedraw();
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Check()
|
||
|
|
{
|
||
|
|
static int PrevEndInterval = 0;
|
||
|
|
int EndInterval, Pos;
|
||
|
|
int i, j;
|
||
|
|
double Profit = 0, InitProfit = 0;
|
||
|
|
|
||
|
|
EndInterval = ObjectGet("EndInterval", OBJPROP_TIME1);
|
||
|
|
|
||
|
|
if (EndInterval != PrevEndInterval)
|
||
|
|
{
|
||
|
|
PrevEndInterval = EndInterval;
|
||
|
|
|
||
|
|
Pos = GetTimePos(EndInterval);
|
||
|
|
|
||
|
|
GetMarket(Pos);
|
||
|
|
|
||
|
|
for (i = 0; i < AmountSymbols; i++)
|
||
|
|
{
|
||
|
|
TickValues[i] *= MathAbs(Lots[i]);
|
||
|
|
InitProfit -= Spreads[i] * TickValues[i];
|
||
|
|
Spreads[i] = BaseMatrix[i][Pos];
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < MatrixRows; i++)
|
||
|
|
{
|
||
|
|
Profit = InitProfit;
|
||
|
|
|
||
|
|
for (j = 0; j < AmountSymbols; j++)
|
||
|
|
if (Lots[j] > 0)
|
||
|
|
Profit += (BaseMatrix[j][i] - Spreads[j]) * TickValues[j];
|
||
|
|
else
|
||
|
|
Profit -= (BaseMatrix[j][i] - Spreads[j]) * TickValues[j];
|
||
|
|
|
||
|
|
Data[i] = Profit;
|
||
|
|
}
|
||
|
|
|
||
|
|
DrawData(Pos);
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CreateObject( string Name, string Value, int FontSize, int Xcoord, int Ycoord, int Angle, bool Hide, bool Back, int Color )
|
||
|
|
{
|
||
|
|
ObjectCreate(Name, OBJ_LABEL, WindowFind(IndName), 0, 0);
|
||
|
|
// HideObject(Name, Hide);
|
||
|
|
ObjectSet(Name, OBJPROP_ANGLE, Angle);
|
||
|
|
ObjectSet(Name, OBJPROP_XDISTANCE, Xcoord);
|
||
|
|
ObjectSet(Name, OBJPROP_YDISTANCE, Ycoord);
|
||
|
|
ObjectSet(Name, OBJPROP_BACK, Back);
|
||
|
|
ObjectSetText(Name, Value, FontSize, FontName, Color);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ModifyTextObject( string Name, string Text )
|
||
|
|
{
|
||
|
|
int Color = ObjectGet(Name, OBJPROP_COLOR);
|
||
|
|
int FontSize = ObjectGet(Name, OBJPROP_FONTSIZE);
|
||
|
|
|
||
|
|
ObjectSetText(Name, Text, FontSize, FontName, Color);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CreateObjects( int Xcoord, int Ycoord )
|
||
|
|
{
|
||
|
|
for (int i = 0; i < AmountSymbols; i++)
|
||
|
|
{
|
||
|
|
CreateObject(Symbols[i] + "_lots", Symbols[i], 12, Xcoord, Ycoord, 0, FALSE, FALSE, ColorText);
|
||
|
|
|
||
|
|
Ycoord += 20;
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Init()
|
||
|
|
{
|
||
|
|
static bool FirstRun = TRUE;
|
||
|
|
|
||
|
|
if (!FirstRun)
|
||
|
|
return;
|
||
|
|
|
||
|
|
IndName = IndName + ": Margin = " + Margin;
|
||
|
|
|
||
|
|
IndicatorShortName(IndName);
|
||
|
|
|
||
|
|
CreateObjects(5, 15);
|
||
|
|
|
||
|
|
FirstRun = FALSE;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void start()
|
||
|
|
{
|
||
|
|
Init();
|
||
|
|
|
||
|
|
Check();
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|