Add files via upload

This commit is contained in:
amirghadiri1987
2025-02-07 19:15:50 +03:30
committed by GitHub
parent e829dab822
commit 781d26ab5c
46 changed files with 12926 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+377
View File
@@ -0,0 +1,377 @@
//+------------------------------------------------------------------+
//| String.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CString. |
//| Appointment: Class-string. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CString : public CObject
{
protected:
string m_string;
public:
CString(void);
~CString(void);
//--- methods access
string Str(void) const { return(m_string); };
uint Len(void) const { return(StringLen(m_string)); };
void Copy(string &copy) const;
void Copy(CString *copy) const;
//--- methods fill
bool Fill(const short character) { return(StringFill(m_string,character)); };
void Assign(const string str) { m_string=str; };
void Assign(const CString *str) { m_string=str.Str(); };
void Append(const string str);
void Append(const CString *str);
uint Insert(const uint pos,const string substring);
uint Insert(const uint pos,const CString *substring);
//--- methods compare
int Compare(const string str) const;
int Compare(const CString *str) const;
int CompareNoCase(const string str) const;
int CompareNoCase(const CString *str) const;
//--- methods prepare
string Left(const uint count) const;
string Right(const uint count) const;
string Mid(const uint pos,const uint count) const;
//--- methods truncation/deletion
int Trim(const string targets);
int TrimLeft(const string targets);
int TrimRight(const string targets);
bool Clear(void) { return(StringInit(m_string)); };
//--- methods conversion
bool ToUpper(void) { return(StringToUpper(m_string)); };
bool ToLower(void) { return(StringToLower(m_string)); };
void Reverse(void);
//--- methods find
int Find(const uint start,const string substring) const;
int FindRev(const string substring) const;
uint Remove(const string substring);
uint Replace(const string substring,const string newstring);
protected:
virtual int Compare(const CObject *node,const int mode=0) const;
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CString::CString(void) : m_string("")
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CString::~CString(void)
{
}
//+------------------------------------------------------------------+
//| Copy the string value member to copy |
//+------------------------------------------------------------------+
void CString::Copy(string &copy) const
{
copy=m_string;
}
//+------------------------------------------------------------------+
//| Copy the string value member to copy |
//+------------------------------------------------------------------+
void CString::Copy(CString *copy) const
{
copy.Assign(m_string);
}
//+------------------------------------------------------------------+
//| Add a string to the end |
//+------------------------------------------------------------------+
void CString::Append(const string str)
{
m_string+=str;
}
//+------------------------------------------------------------------+
//| Add a string to the end |
//+------------------------------------------------------------------+
void CString::Append(const CString *str)
{
//--- check
if(!CheckPointer(str))
return;
//---
m_string+=str.Str();
}
//+------------------------------------------------------------------+
//| Insert a string in specified position |
//+------------------------------------------------------------------+
uint CString::Insert(const uint pos,const string substring)
{
string tmp=StringSubstr(m_string,0,pos);
//---
tmp+=substring;
m_string=tmp+StringSubstr(m_string,pos);
//--- result
return(StringLen(m_string));
}
//+------------------------------------------------------------------+
//| Insert a string in specified position |
//+------------------------------------------------------------------+
uint CString::Insert(const uint pos,const CString *substring)
{
//--- check
if(!CheckPointer(substring))
return(0);
//---
string tmp=StringSubstr(m_string,0,pos);
//---
tmp+=substring.Str();
m_string=tmp+StringSubstr(m_string,pos);
//--- result
return(StringLen(m_string));
}
//+------------------------------------------------------------------+
//| Comparison with the string |
//+------------------------------------------------------------------+
int CString::Compare(const string str) const
{
if(m_string<str)
return(-1);
if(m_string>str)
return(1);
//--- equal
return(0);
}
//+------------------------------------------------------------------+
//| Comparison with the string |
//+------------------------------------------------------------------+
int CString::Compare(const CString *str) const
{
//--- check
if(!CheckPointer(str))
return(0);
//---
if(m_string<str.Str())
return(-1);
if(m_string>str.Str())
return(1);
//--- equal
return(0);
}
//+------------------------------------------------------------------+
//| Comparison with the string without case |
//+------------------------------------------------------------------+
int CString::CompareNoCase(const string str) const
{
string tmp1,tmp2;
//---
tmp1=m_string;
tmp2=str;
StringToLower(tmp1);
StringToLower(tmp2);
//---
if(tmp1<tmp2)
return(-1);
if(tmp1>tmp2)
return(1);
//--- equal
return(0);
}
//+------------------------------------------------------------------+
//| Comparison with the string without case |
//+------------------------------------------------------------------+
int CString::CompareNoCase(const CString *str) const
{
string tmp1,tmp2;
//--- check
if(!CheckPointer(str))
return(0);
//---
tmp1=m_string;
tmp2=str.Str();
StringToLower(tmp1);
StringToLower(tmp2);
//---
if(tmp1<tmp2)
return(-1);
if(tmp1>tmp2)
return(1);
//--- equal
return(0);
}
//+------------------------------------------------------------------+
//| Find occurrences of substring from the specified position |
//+------------------------------------------------------------------+
int CString::Find(const uint start,const string substring) const
{
return(StringFind(m_string,substring,start));
}
//+------------------------------------------------------------------+
//| Find last occurrence of substring |
//+------------------------------------------------------------------+
int CString::FindRev(const string substring) const
{
int result,pos=-1;
//---
do
{
result=pos;
}
while((pos=StringFind(m_string,substring,pos+1))>=0);
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Get a substring consisting of count elements of the left string |
//+------------------------------------------------------------------+
string CString::Left(const uint count) const
{
return(StringSubstr(m_string,0,count));
}
//+------------------------------------------------------------------+
//| Get a substring consisting of count elements of the right string.|
//+------------------------------------------------------------------+
string CString::Right(const uint count) const
{
return(StringSubstr(m_string,StringLen(m_string)-count,count));
}
//+------------------------------------------------------------------+
//| Get a substring consisting of count elements of the pos string |
//+------------------------------------------------------------------+
string CString::Mid(const uint pos,const uint count) const
{
return(StringSubstr(m_string,pos,count));
}
//+------------------------------------------------------------------+
//| Remove from the string, all characters in the begin and |
//| in the end if they arein targets, or space, \t,\n or \r |
//+------------------------------------------------------------------+
int CString::Trim(const string targets)
{
return(TrimLeft(targets)+TrimRight(targets));
}
//+------------------------------------------------------------------+
//| Remove from the string, all characters in the begin if they are |
//| in targets, or space, \t,\n or \r |
//+------------------------------------------------------------------+
int CString::TrimLeft(const string targets)
{
ushort ch;
//---
for(int i=0;i<StringLen(m_string);i++)
{
ch=StringGetCharacter(m_string,i);
if(ch<=' ')
continue;
for(int j=0;j<StringLen(targets);j++)
{
if(ch==StringGetCharacter(targets,j))
{
StringSetCharacter(m_string,i,' ');
ch=' ';
}
}
if(ch!=' ')
break;
}
//--- result
return(StringTrimLeft(m_string));
}
//+------------------------------------------------------------------+
//| Remove from the string, all characters in the end if they are |
//| in targets, or space, \t,\n or \r |
//+------------------------------------------------------------------+
int CString::TrimRight(const string targets)
{
ushort ch;
//---
for(int i=StringLen(m_string)-1;i>=0;i--)
{
ch=StringGetCharacter(m_string,i);
if(ch<=' ')
continue;
for(int j=0;j<StringLen(targets);j++)
{
if(ch==StringGetCharacter(targets,j))
{
StringSetCharacter(m_string,i,' ');
ch=' ';
}
}
if(ch!=' ')
break;
}
//--- result
return(StringTrimRight(m_string));
}
//+------------------------------------------------------------------+
//| Deploy the sequence of characters in a string |
//+------------------------------------------------------------------+
void CString::Reverse(void)
{
ushort ch;
int i,j;
//---
for(i=StringLen(m_string)-1,j=0;i>j;i--,j++)
{
ch=StringGetCharacter(m_string,i);
StringSetCharacter(m_string,i,StringGetCharacter(m_string,j));
StringSetCharacter(m_string,j,ch);
}
}
//+------------------------------------------------------------------+
//| Remove all occurrences of the substring |
//+------------------------------------------------------------------+
uint CString::Remove(const string substring)
{
int result=0,len,pos=-1;
string tmp;
//---
len=StringLen(substring);
while((pos=StringFind(m_string,substring,pos))>=0)
{
tmp=StringSubstr(m_string,0,pos);
m_string=tmp+StringSubstr(m_string,pos+len);
result++;
}
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Replace all occurrences of a substring in the specified string |
//+------------------------------------------------------------------+
uint CString::Replace(const string substring,const string newstring)
{
int result=0,len,pos=-1;
string tmp;
//---
len=StringLen(substring);
while((pos=StringFind(m_string,substring,pos))>=0)
{
tmp=StringSubstr(m_string,0,pos)+newstring;
m_string=tmp+StringSubstr(m_string,pos+len);
// to eliminate possible loops
pos+=StringLen(newstring);
result++;
}
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Comparison with the string by algorithm |
//+------------------------------------------------------------------+
int CString::Compare(const CObject *node,const int mode=0) const
{
CString *str=(CString*)node;
//--- check
if(str==NULL)
return(0);
//---
switch(mode)
{
case 0: return(Compare(str));
case 1: return(CompareNoCase(str));
}
//--- equal
return(0);
}
//+------------------------------------------------------------------+
+581
View File
@@ -0,0 +1,581 @@
//+------------------------------------------------------------------+
//| DateTime.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Structure CDateTime. |
//| Purpose: Working with dates and time. |
//| Extends the MqlDateTime structure. |
//+------------------------------------------------------------------+
struct CDateTime : public MqlDateTime
{
//--- additional information
string MonthName(const int num) const;
string ShortMonthName(const int num) const;
string DayName(const int num) const;
string ShortDayName(const int num) const;
string MonthName(void) const { return(MonthName(mon)); }
string ShortMonthName(void) const { return(ShortMonthName(mon)); }
string DayName(void) const { return(DayName(day_of_week)); }
string ShortDayName(void) const { return(ShortDayName(day_of_week)); }
int DaysInMonth(void) const;
//--- data access
datetime DateTime(void) { return(StructToTime(this)); }
void DateTime(const datetime value) { TimeToStruct(value,this); }
void DateTime(const MqlDateTime& value) { this=value; }
void Date(const datetime value);
void Date(const MqlDateTime &value);
void Time(const datetime value);
void Time(const MqlDateTime &value);
//--- settings
void Sec(const int value);
void Min(const int value);
void Hour(const int value);
void Day(const int value);
void Mon(const int value);
void Year(const int value);
//--- increments
void SecDec(int delta=1);
void SecInc(int delta=1);
void MinDec(int delta=1);
void MinInc(int delta=1);
void HourDec(int delta=1);
void HourInc(int delta=1);
void DayDec(int delta=1);
void DayInc(int delta=1);
void MonDec(int delta=1);
void MonInc(int delta=1);
void YearDec(int delta=1);
void YearInc(int delta=1);
//--- check
void DayCheck(void);
};
//+------------------------------------------------------------------+
//| Gets month name |
//+------------------------------------------------------------------+
string CDateTime::MonthName(const int num) const
{
switch(num)
{
case 1: return("January");
case 2: return("February");
case 3: return("March");
case 4: return("April");
case 5: return("May");
case 6: return("June");
case 7: return("July");
case 8: return("August");
case 9: return("September");
case 10: return("October");
case 11: return("November");
case 12: return("December");
}
//---
return("Bad month");
}
//+------------------------------------------------------------------+
//| Gets short name of month |
//+------------------------------------------------------------------+
string CDateTime::ShortMonthName(const int num) const
{
switch(num)
{
case 1: return("jan");
case 2: return("feb");
case 3: return("mar");
case 4: return("apr");
case 5: return("may");
case 6: return("jun");
case 7: return("jul");
case 8: return("aug");
case 9: return("sep");
case 10: return("oct");
case 11: return("nov");
case 12: return("dec");
}
//---
return("Bad month");
}
//+------------------------------------------------------------------+
//| Gets name of week day |
//+------------------------------------------------------------------+
string CDateTime::DayName(const int num) const
{
switch(num)
{
case 0: return("Sunday");
case 1: return("Monday");
case 2: return("Tuesday");
case 3: return("Wednesday");
case 4: return("Thursday");
case 5: return("Friday");
case 6: return("Saturday");
}
//---
return("Bad day of week");
}
//+------------------------------------------------------------------+
//| Gets short name of week day |
//+------------------------------------------------------------------+
string CDateTime::ShortDayName(const int num) const
{
switch(num)
{
case 0: return("Su");
case 1: return("Mo");
case 2: return("Tu");
case 3: return("We");
case 4: return("Th");
case 5: return("Fr");
case 6: return("Sa");
}
//---
return("Bad day of week");
}
//+------------------------------------------------------------------+
//| Gets number of days in month |
//+------------------------------------------------------------------+
int CDateTime::DaysInMonth(void) const
{
int leap_year;
//---
switch(mon)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return(31);
case 2:
leap_year=year;
if(year%100==0)
leap_year/=100;
return((leap_year%4==0)? 29 : 28);
case 4:
case 6:
case 9:
case 11:
return(30);
}
//---
return(0);
}
//+------------------------------------------------------------------+
//| Sets date |
//+------------------------------------------------------------------+
void CDateTime::Date(const datetime value)
{
MqlDateTime dt;
//--- convert to structure
TimeToStruct(value,dt);
//--- set
Date(dt);
}
//+------------------------------------------------------------------+
//| Sets date |
//+------------------------------------------------------------------+
void CDateTime::Date(const MqlDateTime &value)
{
day =value.day;
mon =value.mon;
year=value.year;
//--- check if day is correct
DayCheck();
}
//+------------------------------------------------------------------+
//| Sets time |
//+------------------------------------------------------------------+
void CDateTime::Time(const datetime value)
{
MqlDateTime dt;
//--- convert to structure
TimeToStruct(value,dt);
//--- set
Time(dt);
}
//+------------------------------------------------------------------+
//| Sets time |
//+------------------------------------------------------------------+
void CDateTime::Time(const MqlDateTime &value)
{
hour=value.hour;
min =value.min;
sec =value.sec;
}
//+------------------------------------------------------------------+
//| Sets seconds |
//+------------------------------------------------------------------+
void CDateTime::Sec(const int value)
{
//--- check and set
if(value>=0 && value<60)
sec=value;
}
//+------------------------------------------------------------------+
//| Sets minutes |
//+------------------------------------------------------------------+
void CDateTime::Min(const int value)
{
//--- check and set
if(value>=0 && value<60)
min=value;
}
//+------------------------------------------------------------------+
//| Sets hours |
//+------------------------------------------------------------------+
void CDateTime::Hour(const int value)
{
//--- check and set
if(value>=0 && value<24)
hour=value;
}
//+------------------------------------------------------------------+
//| Sets day of month |
//+------------------------------------------------------------------+
void CDateTime::Day(const int value)
{
//--- check and set
if(value>0 && value<=DaysInMonth())
{
day=value;
//--- check if day is correct
DayCheck();
}
}
//+------------------------------------------------------------------+
//| Sets month |
//+------------------------------------------------------------------+
void CDateTime::Mon(const int value)
{
//--- check and set
if(value>0 && value<=12)
{
mon=value;
//--- check if day is correct
DayCheck();
}
}
//+------------------------------------------------------------------+
//| Sets year |
//+------------------------------------------------------------------+
void CDateTime::Year(const int value)
{
//--- check and set
if(value>=1970)
{
year=value;
//--- check if day is correct
DayCheck();
}
}
//+------------------------------------------------------------------+
//| Subtracts specified number of seconds |
//+------------------------------------------------------------------+
void CDateTime::SecDec(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
SecInc(-delta);
return;
}
//--- check if subtract from upper number positions
if(delta>60)
{
MinDec(delta/60);
delta%=60;
}
sec-=delta;
if(sec<0)
{
sec+=60;
MinDec();
}
}
//+------------------------------------------------------------------+
//| Adds specified number of seconds |
//+------------------------------------------------------------------+
void CDateTime::SecInc(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
SecDec(-delta);
return;
}
//--- check if add to upper number positions
if(delta>60)
{
MinInc(delta/60);
delta%=60;
}
sec+=delta;
if(sec>=60)
{
sec-=60;
MinInc();
}
}
//+------------------------------------------------------------------+
//| Subtracts specified number of minutes |
//+------------------------------------------------------------------+
void CDateTime::MinDec(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
MinInc(-delta);
return;
}
//--- check if subtract from upper number positions
if(delta>60)
{
HourDec(delta/60);
delta%=60;
}
min-=delta;
if(min<0)
{
min+=60;
HourDec();
}
}
//+------------------------------------------------------------------+
//| Adds specified number of minutes |
//+------------------------------------------------------------------+
void CDateTime::MinInc(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
MinDec(-delta);
return;
}
//--- check if add to upper number positions
if(delta>60)
{
HourInc(delta/60);
delta%=60;
}
min+=delta;
if(min>=60)
{
min-=60;
HourInc();
}
}
//+------------------------------------------------------------------+
//| Subtracts specified number of hours |
//+------------------------------------------------------------------+
void CDateTime::HourDec(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
HourInc(-delta);
return;
}
//--- check if subtract from upper number positions
if(delta>24)
{
DayDec(delta/24);
delta%=24;
}
hour-=delta;
if(hour<0)
{
hour+=24;
DayDec();
}
}
//+------------------------------------------------------------------+
//| Adds specified number of hours |
//+------------------------------------------------------------------+
void CDateTime::HourInc(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
HourDec(-delta);
return;
}
//--- check if add to upper number positions
if(delta>24)
{
DayInc(delta/24);
delta%=24;
}
hour+=delta;
if(hour>=24)
{
hour-=24;
DayInc();
}
}
//+------------------------------------------------------------------+
//| Subtracts specified number of days |
//+------------------------------------------------------------------+
void CDateTime::DayDec(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
DayInc(-delta);
return;
}
//--- uncertain condition, as the number of days in month can differ
while(day<=delta)
{
delta-=day;
MonDec();
day=DaysInMonth();
}
day-=delta;
//--- check if day is correct
DayCheck();
}
//+------------------------------------------------------------------+
//| Adds specified number of days |
//+------------------------------------------------------------------+
void CDateTime::DayInc(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
DayDec(-delta);
return;
}
//--- uncertain condition, as the number of days in month can differ
while(DaysInMonth()-day<delta)
{
delta-=DaysInMonth()-day+1;
MonInc();
day=1;
}
day+=delta;
//--- check if day is correct
DayCheck();
}
//+------------------------------------------------------------------+
//| Subtracts specified number of months |
//+------------------------------------------------------------------+
void CDateTime::MonDec(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
MonInc(-delta);
return;
}
//--- check if subtract from upper number positions
if(delta>12)
{
YearDec(delta/12);
delta%=12;
}
mon-=delta;
if(mon<=0)
{
mon+=12;
YearDec();
}
//--- check if day is correct
DayCheck();
}
//+------------------------------------------------------------------+
//| Adds specified number of months |
//+------------------------------------------------------------------+
void CDateTime::MonInc(int delta)
{
//--- if increment is 0 - exit
if(delta==0)
return;
//--- if increment is negative - inverse the operation
if(delta<0)
{
MonDec(-delta);
return;
}
//--- check if add to upper number positions
if(delta>12)
{
YearInc(delta/12);
delta%=12;
}
mon+=delta;
if(mon>12)
{
mon-=12;
YearInc();
}
//--- check if day is correct
DayCheck();
}
//+------------------------------------------------------------------+
//| Subtracts specified number of years |
//+------------------------------------------------------------------+
void CDateTime::YearDec(int delta)
{
//--- if increment is 0 - exit
if(delta!=0)
{
year-=delta;
//--- check if day is correct
DayCheck();
}
}
//+------------------------------------------------------------------+
//| Adds specified number of years |
//+------------------------------------------------------------------+
void CDateTime::YearInc(int delta)
{
//--- if increment is 0 - exit
if(delta!=0)
{
year+=delta;
//--- check if day is correct
DayCheck();
}
}
//+------------------------------------------------------------------+
//| Checks if day number is correct |
//+------------------------------------------------------------------+
void CDateTime::DayCheck(void)
{
if(day>DaysInMonth())
day=DaysInMonth();
//--- this is required to get day of week and day of year
TimeToStruct(StructToTime(this),this);
}
//+------------------------------------------------------------------+
+397
View File
@@ -0,0 +1,397 @@
//+------------------------------------------------------------------+
//| AccountInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CAccountInfo. |
//| Appointment: Class for access to account info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CAccountInfo : public CObject
{
public:
CAccountInfo(void);
~CAccountInfo(void);
//--- fast access methods to the integer account propertyes
long Login(void) const;
ENUM_ACCOUNT_TRADE_MODE TradeMode(void) const;
string TradeModeDescription(void) const;
long Leverage(void) const;
ENUM_ACCOUNT_STOPOUT_MODE StopoutMode(void) const;
string StopoutModeDescription(void) const;
ENUM_ACCOUNT_MARGIN_MODE MarginMode(void) const;
string MarginModeDescription(void) const;
bool TradeAllowed(void) const;
bool TradeExpert(void) const;
int LimitOrders(void) const;
//--- fast access methods to the double account propertyes
double Balance(void) const;
double Credit(void) const;
double Profit(void) const;
double Equity(void) const;
double Margin(void) const;
double FreeMargin(void) const;
double MarginLevel(void) const;
double MarginCall(void) const;
double MarginStopOut(void) const;
//--- fast access methods to the string account propertyes
string Name(void) const;
string Server(void) const;
string Currency(void) const;
string Company(void) const;
//--- access methods to the API MQL5 functions
long InfoInteger(const ENUM_ACCOUNT_INFO_INTEGER prop_id) const;
double InfoDouble(const ENUM_ACCOUNT_INFO_DOUBLE prop_id) const;
string InfoString(const ENUM_ACCOUNT_INFO_STRING prop_id) const;
//--- checks
double OrderProfitCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price_open,const double price_close) const;
double MarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price) const;
double FreeMarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price) const;
double MaxLotCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double price,const double percent=100) const;
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CAccountInfo::CAccountInfo(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CAccountInfo::~CAccountInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_LOGIN" |
//+------------------------------------------------------------------+
long CAccountInfo::Login(void) const
{
return(AccountInfoInteger(ACCOUNT_LOGIN));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_TRADE_MODE" |
//+------------------------------------------------------------------+
ENUM_ACCOUNT_TRADE_MODE CAccountInfo::TradeMode(void) const
{
return((ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_TRADE_MODE" as string |
//+------------------------------------------------------------------+
string CAccountInfo::TradeModeDescription(void) const
{
string str;
//---
switch(TradeMode())
{
case ACCOUNT_TRADE_MODE_DEMO:
str="Demo trading account";
break;
case ACCOUNT_TRADE_MODE_CONTEST:
str="Contest trading account";
break;
case ACCOUNT_TRADE_MODE_REAL:
str="Real trading account";
break;
default:
str="Unknown trade account";
}
//---
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_LEVERAGE" |
//+------------------------------------------------------------------+
long CAccountInfo::Leverage(void) const
{
return(AccountInfoInteger(ACCOUNT_LEVERAGE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_SO_MODE" |
//+------------------------------------------------------------------+
ENUM_ACCOUNT_STOPOUT_MODE CAccountInfo::StopoutMode(void) const
{
return((ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_SO_MODE" as string |
//+------------------------------------------------------------------+
string CAccountInfo::StopoutModeDescription(void) const
{
string str;
//---
switch(StopoutMode())
{
case ACCOUNT_STOPOUT_MODE_PERCENT:
str="Level is specified in percentage";
break;
case ACCOUNT_STOPOUT_MODE_MONEY:
str="Level is specified in money";
break;
default:
str="Unknown stopout mode";
}
//---
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_MODE" |
//+------------------------------------------------------------------+
ENUM_ACCOUNT_MARGIN_MODE CAccountInfo::MarginMode(void) const
{
return((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_MODE" as string |
//+------------------------------------------------------------------+
string CAccountInfo::MarginModeDescription(void) const
{
string str;
//---
switch(MarginMode())
{
case ACCOUNT_MARGIN_MODE_RETAIL_NETTING:
str="Netting";
break;
case ACCOUNT_MARGIN_MODE_EXCHANGE:
str="Exchange";
break;
case ACCOUNT_MARGIN_MODE_RETAIL_HEDGING:
str="Hedging";
break;
default:
str="Unknown margin mode";
}
//---
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_TRADE_ALLOWED" |
//+------------------------------------------------------------------+
bool CAccountInfo::TradeAllowed(void) const
{
return((bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_TRADE_EXPERT" |
//+------------------------------------------------------------------+
bool CAccountInfo::TradeExpert(void) const
{
return((bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_LIMIT_ORDERS" |
//+------------------------------------------------------------------+
int CAccountInfo::LimitOrders(void) const
{
return((int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_BALANCE" |
//+------------------------------------------------------------------+
double CAccountInfo::Balance(void) const
{
return(AccountInfoDouble(ACCOUNT_BALANCE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_CREDIT" |
//+------------------------------------------------------------------+
double CAccountInfo::Credit(void) const
{
return(AccountInfoDouble(ACCOUNT_CREDIT));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_PROFIT" |
//+------------------------------------------------------------------+
double CAccountInfo::Profit(void) const
{
return(AccountInfoDouble(ACCOUNT_PROFIT));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_EQUITY" |
//+------------------------------------------------------------------+
double CAccountInfo::Equity(void) const
{
return(AccountInfoDouble(ACCOUNT_EQUITY));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN" |
//+------------------------------------------------------------------+
double CAccountInfo::Margin(void) const
{
return(AccountInfoDouble(ACCOUNT_MARGIN));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_FREE" |
//+------------------------------------------------------------------+
double CAccountInfo::FreeMargin(void) const
{
return(AccountInfoDouble(ACCOUNT_MARGIN_FREE));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_LEVEL" |
//+------------------------------------------------------------------+
double CAccountInfo::MarginLevel(void) const
{
return(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_SO_CALL" |
//+------------------------------------------------------------------+
double CAccountInfo::MarginCall(void) const
{
return(AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_MARGIN_SO_SO" |
//+------------------------------------------------------------------+
double CAccountInfo::MarginStopOut(void) const
{
return(AccountInfoDouble(ACCOUNT_MARGIN_SO_SO));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_NAME" |
//+------------------------------------------------------------------+
string CAccountInfo::Name(void) const
{
return(AccountInfoString(ACCOUNT_NAME));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_SERVER" |
//+------------------------------------------------------------------+
string CAccountInfo::Server(void) const
{
return(AccountInfoString(ACCOUNT_SERVER));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_CURRENCY" |
//+------------------------------------------------------------------+
string CAccountInfo::Currency(void) const
{
return(AccountInfoString(ACCOUNT_CURRENCY));
}
//+------------------------------------------------------------------+
//| Get the property value "ACCOUNT_COMPANY" |
//+------------------------------------------------------------------+
string CAccountInfo::Company(void) const
{
return(AccountInfoString(ACCOUNT_COMPANY));
}
//+------------------------------------------------------------------+
//| Access functions AccountInfoInteger(...) |
//+------------------------------------------------------------------+
long CAccountInfo::InfoInteger(const ENUM_ACCOUNT_INFO_INTEGER prop_id) const
{
return(AccountInfoInteger(prop_id));
}
//+------------------------------------------------------------------+
//| Access functions AccountInfoDouble(...) |
//+------------------------------------------------------------------+
double CAccountInfo::InfoDouble(const ENUM_ACCOUNT_INFO_DOUBLE prop_id) const
{
return(AccountInfoDouble(prop_id));
}
//+------------------------------------------------------------------+
//| Access functions AccountInfoString(...) |
//+------------------------------------------------------------------+
string CAccountInfo::InfoString(const ENUM_ACCOUNT_INFO_STRING prop_id) const
{
return(AccountInfoString(prop_id));
}
//+------------------------------------------------------------------+
//| Access functions OrderCalcProfit(...). |
//| INPUT: name - symbol name, |
//| trade_operation - trade operation, |
//| volume - volume of the opening position, |
//| price_open - price of the opening position, |
//| price_close - price of the closing position. |
//+------------------------------------------------------------------+
double CAccountInfo::OrderProfitCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price_open,const double price_close) const
{
double profit=EMPTY_VALUE;
//---
if(!OrderCalcProfit(trade_operation,symbol,volume,price_open,price_close,profit))
return(EMPTY_VALUE);
//---
return(profit);
}
//+------------------------------------------------------------------+
//| Access functions OrderCalcMargin(...). |
//| INPUT: name - symbol name, |
//| trade_operation - trade operation, |
//| volume - volume of the opening position, |
//| price - price of the opening position. |
//+------------------------------------------------------------------+
double CAccountInfo::MarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price) const
{
double margin=EMPTY_VALUE;
//---
if(!OrderCalcMargin(trade_operation,symbol,volume,price,margin))
return(EMPTY_VALUE);
//---
return(margin);
}
//+------------------------------------------------------------------+
//| Access functions OrderCalcMargin(...). |
//| INPUT: name - symbol name, |
//| trade_operation - trade operation, |
//| volume - volume of the opening position, |
//| price - price of the opening position. |
//+------------------------------------------------------------------+
double CAccountInfo::FreeMarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double volume,const double price) const
{
return(FreeMargin()-MarginCheck(symbol,trade_operation,volume,price));
}
//+------------------------------------------------------------------+
//| Access functions OrderCalcMargin(...). |
//| INPUT: name - symbol name, |
//| trade_operation - trade operation, |
//| price - price of the opening position, |
//| percent - percent of available margin [1-100%]. |
//+------------------------------------------------------------------+
double CAccountInfo::MaxLotCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation,
const double price,const double percent) const
{
double margin=0.0;
//--- checks
if(symbol=="" || price<=0.0 || percent<1 || percent>100)
{
Print("CAccountInfo::MaxLotCheck invalid parameters");
return(0.0);
}
//--- calculate margin requirements for 1 lot
if(!OrderCalcMargin(trade_operation,symbol,1.0,price,margin) || margin<0.0)
{
Print("CAccountInfo::MaxLotCheck margin calculation failed");
return(0.0);
}
//---
if(margin==0.0) // for pending orders
return(SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX));
//--- calculate maximum volume
double volume=NormalizeDouble(FreeMargin()*percent/100.0/margin,2);
//--- normalize and check limits
double stepvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
if(stepvol>0.0)
volume=stepvol*MathFloor(volume/stepvol);
//---
double minvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
if(volume<minvol)
volume=0.0;
//---
double maxvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
if(volume>maxvol)
volume=maxvol;
//--- return volume
return(volume);
}
//+------------------------------------------------------------------+
+430
View File
@@ -0,0 +1,430 @@
//+------------------------------------------------------------------+
//| DealInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CDealInfo. |
//| Appointment: Class for access to history deal info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CDealInfo : public CObject
{
protected:
ulong m_ticket; // ticket of history order
public:
CDealInfo(void);
~CDealInfo(void);
//--- methods of access to protected data
void Ticket(const ulong ticket) { m_ticket=ticket; }
ulong Ticket(void) const { return(m_ticket); }
//--- fast access methods to the integer position propertyes
long Order(void) const;
datetime Time(void) const;
ulong TimeMsc(void) const;
ENUM_DEAL_TYPE DealType(void) const;
string TypeDescription(void) const;
ENUM_DEAL_ENTRY Entry(void) const;
string EntryDescription(void) const;
long Magic(void) const;
long PositionId(void) const;
//--- fast access methods to the double position propertyes
double Volume(void) const;
double Price(void) const;
double Commission(void) const;
double Swap(void) const;
double Profit(void) const;
//--- fast access methods to the string position propertyes
string Symbol(void) const;
string Comment(void) const;
string ExternalId(void) const;
//--- access methods to the API MQL5 functions
bool InfoInteger(ENUM_DEAL_PROPERTY_INTEGER prop_id,long &var) const;
bool InfoDouble(ENUM_DEAL_PROPERTY_DOUBLE prop_id,double &var) const;
bool InfoString(ENUM_DEAL_PROPERTY_STRING prop_id,string &var) const;
//--- info methods
string FormatAction(string &str,const uint action) const;
string FormatEntry(string &str,const uint entry) const;
string FormatDeal(string &str) const;
//--- method for select deal
bool SelectByIndex(const int index);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CDealInfo::CDealInfo(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CDealInfo::~CDealInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_ORDER" |
//+------------------------------------------------------------------+
long CDealInfo::Order(void) const
{
return(HistoryDealGetInteger(m_ticket,DEAL_ORDER));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_TIME" |
//+------------------------------------------------------------------+
datetime CDealInfo::Time(void) const
{
return((datetime)HistoryDealGetInteger(m_ticket,DEAL_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_TIME_MSC" |
//+------------------------------------------------------------------+
ulong CDealInfo::TimeMsc(void) const
{
return(HistoryDealGetInteger(m_ticket,DEAL_TIME_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_TYPE" |
//+------------------------------------------------------------------+
ENUM_DEAL_TYPE CDealInfo::DealType(void) const
{
return((ENUM_DEAL_TYPE)HistoryDealGetInteger(m_ticket,DEAL_TYPE));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_TYPE" as string |
//+------------------------------------------------------------------+
string CDealInfo::TypeDescription(void) const
{
string str;
//---
switch(DealType())
{
case DEAL_TYPE_BUY:
str="Buy type";
break;
case DEAL_TYPE_SELL:
str="Sell type";
break;
case DEAL_TYPE_BALANCE:
str="Balance type";
break;
case DEAL_TYPE_CREDIT:
str="Credit type";
break;
case DEAL_TYPE_CHARGE:
str="Charge type";
break;
case DEAL_TYPE_CORRECTION:
str="Correction type";
break;
case DEAL_TYPE_BONUS:
str="Bonus type";
break;
case DEAL_TYPE_COMMISSION:
str="Commission type";
break;
case DEAL_TYPE_COMMISSION_DAILY:
str="Daily Commission type";
break;
case DEAL_TYPE_COMMISSION_MONTHLY:
str="Monthly Commission type";
break;
case DEAL_TYPE_COMMISSION_AGENT_DAILY:
str="Daily Agent Commission type";
break;
case DEAL_TYPE_COMMISSION_AGENT_MONTHLY:
str="Monthly Agent Commission type";
break;
case DEAL_TYPE_INTEREST:
str="Interest Rate type";
break;
case DEAL_TYPE_BUY_CANCELED:
str="Canceled Buy type";
break;
case DEAL_TYPE_SELL_CANCELED:
str="Canceled Sell type";
break;
default:
str="Unknown type";
}
//---
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_ENTRY" |
//+------------------------------------------------------------------+
ENUM_DEAL_ENTRY CDealInfo::Entry(void) const
{
return((ENUM_DEAL_ENTRY)HistoryDealGetInteger(m_ticket,DEAL_ENTRY));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_ENTRY" as string |
//+------------------------------------------------------------------+
string CDealInfo::EntryDescription(void) const
{
string str;
//---
switch(CDealInfo::Entry())
{
case DEAL_ENTRY_IN:
str="In entry";
break;
case DEAL_ENTRY_OUT:
str="Out entry";
break;
case DEAL_ENTRY_INOUT:
str="InOut entry";
break;
case DEAL_ENTRY_STATE:
str="Status record";
break;
case DEAL_ENTRY_OUT_BY:
str="Out By entry";
break;
default:
str="Unknown entry";
}
//---
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_MAGIC" |
//+------------------------------------------------------------------+
long CDealInfo::Magic(void) const
{
return(HistoryDealGetInteger(m_ticket,DEAL_MAGIC));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_POSITION_ID" |
//+------------------------------------------------------------------+
long CDealInfo::PositionId(void) const
{
return(HistoryDealGetInteger(m_ticket,DEAL_POSITION_ID));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_VOLUME" |
//+------------------------------------------------------------------+
double CDealInfo::Volume(void) const
{
return(HistoryDealGetDouble(m_ticket,DEAL_VOLUME));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_PRICE_OPEN" |
//+------------------------------------------------------------------+
double CDealInfo::Price(void) const
{
return(HistoryDealGetDouble(m_ticket,DEAL_PRICE));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_COMMISSION" |
//+------------------------------------------------------------------+
double CDealInfo::Commission(void) const
{
return(HistoryDealGetDouble(m_ticket,DEAL_COMMISSION));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_SWAP" |
//+------------------------------------------------------------------+
double CDealInfo::Swap(void) const
{
return(HistoryDealGetDouble(m_ticket,DEAL_SWAP));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_PROFIT" |
//+------------------------------------------------------------------+
double CDealInfo::Profit(void) const
{
return(HistoryDealGetDouble(m_ticket,DEAL_PROFIT));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_SYMBOL" |
//+------------------------------------------------------------------+
string CDealInfo::Symbol(void) const
{
return(HistoryDealGetString(m_ticket,DEAL_SYMBOL));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_COMMENT" |
//+------------------------------------------------------------------+
string CDealInfo::Comment(void) const
{
return(HistoryDealGetString(m_ticket,DEAL_COMMENT));
}
//+------------------------------------------------------------------+
//| Get the property value "DEAL_EXTERNAL_ID" |
//+------------------------------------------------------------------+
string CDealInfo::ExternalId(void) const
{
return(HistoryDealGetString(m_ticket,DEAL_EXTERNAL_ID));
}
//+------------------------------------------------------------------+
//| Access functions HistoryDealGetInteger(...) |
//+------------------------------------------------------------------+
bool CDealInfo::InfoInteger(ENUM_DEAL_PROPERTY_INTEGER prop_id,long &var) const
{
return(HistoryDealGetInteger(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions HistoryDealGetDouble(...) |
//+------------------------------------------------------------------+
bool CDealInfo::InfoDouble(ENUM_DEAL_PROPERTY_DOUBLE prop_id,double &var) const
{
return(HistoryDealGetDouble(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions HistoryDealGetString(...) |
//+------------------------------------------------------------------+
bool CDealInfo::InfoString(ENUM_DEAL_PROPERTY_STRING prop_id,string &var) const
{
return(HistoryDealGetString(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Converths the type of a deal to text |
//+------------------------------------------------------------------+
string CDealInfo::FormatAction(string &str,const uint action) const
{
//--- see the type
switch(action)
{
case DEAL_TYPE_BUY:
str="buy";
break;
case DEAL_TYPE_SELL:
str="sell";
break;
case DEAL_TYPE_BALANCE:
str="balance";
break;
case DEAL_TYPE_CREDIT:
str="credit";
break;
case DEAL_TYPE_CHARGE:
str="charge";
break;
case DEAL_TYPE_CORRECTION:
str="correction";
break;
case DEAL_TYPE_BONUS:
str="bonus";
break;
case DEAL_TYPE_COMMISSION:
str="commission";
break;
case DEAL_TYPE_COMMISSION_DAILY:
str="daily commission";
break;
case DEAL_TYPE_COMMISSION_MONTHLY:
str="monthly commission";
break;
case DEAL_TYPE_COMMISSION_AGENT_DAILY:
str="daily agent commission";
break;
case DEAL_TYPE_COMMISSION_AGENT_MONTHLY:
str="monthly agent commission";
break;
case DEAL_TYPE_INTEREST:
str="interest rate";
break;
case DEAL_TYPE_BUY_CANCELED:
str="canceled buy";
break;
case DEAL_TYPE_SELL_CANCELED:
str="canceled sell";
break;
default:
str="unknown deal type "+(string)action;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the deal direction to text |
//+------------------------------------------------------------------+
string CDealInfo::FormatEntry(string &str,const uint entry) const
{
//--- see the type
switch(entry)
{
case DEAL_ENTRY_IN:
str="in";
break;
case DEAL_ENTRY_OUT:
str="out";
break;
case DEAL_ENTRY_INOUT:
str="in/out";
break;
case DEAL_ENTRY_OUT_BY:
str="out by";
break;
default:
str="unknown deal entry "+(string)entry;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the deal parameters to text |
//+------------------------------------------------------------------+
string CDealInfo::FormatDeal(string &str) const
{
string type;
long tmp_long;
//--- set up
string symbol_name=this.Symbol();
int digits=_Digits;
if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long))
digits=(int)tmp_long;
//--- form the description of the deal
switch(DealType())
{
//--- Buy-Sell
case DEAL_TYPE_BUY:
case DEAL_TYPE_SELL:
str=StringFormat("#%I64u %s %s %s at %s",
Ticket(),
FormatAction(type,DealType()),
DoubleToString(Volume(),2),
symbol_name,
DoubleToString(Price(),digits));
break;
//--- balance operations
case DEAL_TYPE_BALANCE:
case DEAL_TYPE_CREDIT:
case DEAL_TYPE_CHARGE:
case DEAL_TYPE_CORRECTION:
case DEAL_TYPE_BONUS:
case DEAL_TYPE_COMMISSION:
case DEAL_TYPE_COMMISSION_DAILY:
case DEAL_TYPE_COMMISSION_MONTHLY:
case DEAL_TYPE_COMMISSION_AGENT_DAILY:
case DEAL_TYPE_COMMISSION_AGENT_MONTHLY:
case DEAL_TYPE_INTEREST:
str=StringFormat("#%I64u %s %s [%s]",
Ticket(),
FormatAction(type,DealType()),
DoubleToString(Profit(),2),
this.Comment());
break;
default:
str="unknown deal type "+(string)DealType();
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Select a deal on the index |
//+------------------------------------------------------------------+
bool CDealInfo::SelectByIndex(const int index)
{
ulong ticket=HistoryDealGetTicket(index);
if(ticket==0)
return(false);
Ticket(ticket);
//---
return(true);
}
//+------------------------------------------------------------------+
+472
View File
@@ -0,0 +1,472 @@
//+------------------------------------------------------------------+
//| HistoryOrderInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CHistoryOrderInfo. |
//| Appointment: Class for access to history order info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CHistoryOrderInfo : public CObject
{
protected:
ulong m_ticket; // ticket of history order
public:
CHistoryOrderInfo(void);
~CHistoryOrderInfo(void);
//--- methods of access to protected data
void Ticket(const ulong ticket) { m_ticket=ticket; }
ulong Ticket(void) const { return(m_ticket); }
//--- fast access methods to the integer order propertyes
datetime TimeSetup(void) const;
ulong TimeSetupMsc(void) const;
datetime TimeDone(void) const;
ulong TimeDoneMsc(void) const;
ENUM_ORDER_TYPE OrderType(void) const;
string TypeDescription(void) const;
ENUM_ORDER_STATE State(void) const;
string StateDescription(void) const;
datetime TimeExpiration(void) const;
ENUM_ORDER_TYPE_FILLING TypeFilling(void) const;
string TypeFillingDescription(void) const;
ENUM_ORDER_TYPE_TIME TypeTime(void) const;
string TypeTimeDescription(void) const;
long Magic(void) const;
long PositionId(void) const;
long PositionById(void) const;
//--- fast access methods to the double order propertyes
double VolumeInitial(void) const;
double VolumeCurrent(void) const;
double PriceOpen(void) const;
double StopLoss(void) const;
double TakeProfit(void) const;
double PriceCurrent(void) const;
double PriceStopLimit(void) const;
//--- fast access methods to the string order propertyes
string Symbol(void) const;
string Comment(void) const;
string ExternalId(void) const;
//--- access methods to the API MQL5 functions
bool InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const;
bool InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const;
bool InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const;
//--- info methods
string FormatType(string &str,const uint type) const;
string FormatStatus(string &str,const uint status) const;
string FormatTypeFilling(string &str,const uint type) const;
string FormatTypeTime(string &str,const uint type) const;
string FormatOrder(string &str) const;
string FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const;
//--- method for select history order
bool SelectByIndex(const int index);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CHistoryOrderInfo::CHistoryOrderInfo(void) : m_ticket(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CHistoryOrderInfo::~CHistoryOrderInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_SETUP" |
//+------------------------------------------------------------------+
datetime CHistoryOrderInfo::TimeSetup(void) const
{
return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_SETUP));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_SETUP_MSC" |
//+------------------------------------------------------------------+
ulong CHistoryOrderInfo::TimeSetupMsc(void) const
{
return(HistoryOrderGetInteger(m_ticket,ORDER_TIME_SETUP_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_DONE" |
//+------------------------------------------------------------------+
datetime CHistoryOrderInfo::TimeDone(void) const
{
return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_DONE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_DONE_MSC" |
//+------------------------------------------------------------------+
ulong CHistoryOrderInfo::TimeDoneMsc(void) const
{
return(HistoryOrderGetInteger(m_ticket,ORDER_TIME_DONE_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE CHistoryOrderInfo::OrderType(void) const
{
return((ENUM_ORDER_TYPE)HistoryOrderGetInteger(m_ticket,ORDER_TYPE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE" as string |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::TypeDescription(void) const
{
string str;
//---
return(FormatType(str,OrderType()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_STATE" |
//+------------------------------------------------------------------+
ENUM_ORDER_STATE CHistoryOrderInfo::State(void) const
{
return((ENUM_ORDER_STATE)HistoryOrderGetInteger(m_ticket,ORDER_STATE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_STATE" as string |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::StateDescription(void) const
{
string str;
//---
return(FormatStatus(str,State()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_EXPIRATION" |
//+------------------------------------------------------------------+
datetime CHistoryOrderInfo::TimeExpiration(void) const
{
return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_EXPIRATION));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_FILLING" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_FILLING CHistoryOrderInfo::TypeFilling(void) const
{
return((ENUM_ORDER_TYPE_FILLING)HistoryOrderGetInteger(m_ticket,ORDER_TYPE_FILLING));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_FILLING" as string |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::TypeFillingDescription(void) const
{
string str;
//---
return(FormatTypeFilling(str,TypeFilling()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_TIME" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_TIME CHistoryOrderInfo::TypeTime(void) const
{
return((ENUM_ORDER_TYPE_TIME)HistoryOrderGetInteger(m_ticket,ORDER_TYPE_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_TIME" as string |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::TypeTimeDescription(void) const
{
string str;
//---
return(FormatTypeTime(str,TypeTime()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_EXPERT" |
//+------------------------------------------------------------------+
long CHistoryOrderInfo::Magic(void) const
{
return(HistoryOrderGetInteger(m_ticket,ORDER_MAGIC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_POSITION_ID" |
//+------------------------------------------------------------------+
long CHistoryOrderInfo::PositionId(void) const
{
return(HistoryOrderGetInteger(m_ticket,ORDER_POSITION_ID));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_POSITION_BY_ID" |
//+------------------------------------------------------------------+
long CHistoryOrderInfo::PositionById(void) const
{
return(HistoryOrderGetInteger(m_ticket,ORDER_POSITION_BY_ID));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_VOLUME_INITIAL" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::VolumeInitial(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_VOLUME_INITIAL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_VOLUME_CURRENT" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::VolumeCurrent(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_VOLUME_CURRENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_OPEN" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::PriceOpen(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_OPEN));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_SL" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::StopLoss(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_SL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TP" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::TakeProfit(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_TP));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_CURRENT" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::PriceCurrent(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_CURRENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_STOPLIMIT" |
//+------------------------------------------------------------------+
double CHistoryOrderInfo::PriceStopLimit(void) const
{
return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_STOPLIMIT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_SYMBOL" |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::Symbol(void) const
{
return(HistoryOrderGetString(m_ticket,ORDER_SYMBOL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_COMMENT" |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::Comment(void) const
{
return(HistoryOrderGetString(m_ticket,ORDER_COMMENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_EXTERNAL_ID" |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::ExternalId(void) const
{
return(HistoryOrderGetString(m_ticket,ORDER_EXTERNAL_ID));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetInteger(...) |
//+------------------------------------------------------------------+
bool CHistoryOrderInfo::InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const
{
return(HistoryOrderGetInteger(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetDouble(...) |
//+------------------------------------------------------------------+
bool CHistoryOrderInfo::InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const
{
return(HistoryOrderGetDouble(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetString(...) |
//+------------------------------------------------------------------+
bool CHistoryOrderInfo::InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const
{
return(HistoryOrderGetString(m_ticket,prop_id,var));
}
//+------------------------------------------------------------------+
//| Converts the order type to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatType(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_TYPE_BUY:
str="buy";
break;
case ORDER_TYPE_SELL:
str="sell";
break;
case ORDER_TYPE_BUY_LIMIT:
str="buy limit";
break;
case ORDER_TYPE_SELL_LIMIT:
str="sell limit";
break;
case ORDER_TYPE_BUY_STOP:
str="buy stop";
break;
case ORDER_TYPE_SELL_STOP:
str="sell stop";
break;
case ORDER_TYPE_BUY_STOP_LIMIT:
str="buy stop limit";
break;
case ORDER_TYPE_SELL_STOP_LIMIT:
str="sell stop limit";
break;
case ORDER_TYPE_CLOSE_BY:
str="close by";
break;
default:
str="unknown order type "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order status to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatStatus(string &str,const uint status) const
{
//--- see the type
switch(status)
{
case ORDER_STATE_STARTED:
str="started";
break;
case ORDER_STATE_PLACED:
str="placed";
break;
case ORDER_STATE_CANCELED:
str="canceled";
break;
case ORDER_STATE_PARTIAL:
str="partial";
break;
case ORDER_STATE_FILLED:
str="filled";
break;
case ORDER_STATE_REJECTED:
str="rejected";
break;
case ORDER_STATE_EXPIRED:
str="expired";
break;
default:
str="unknown order status "+(string)status;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order filling type to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatTypeFilling(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_FILLING_RETURN:
str="return remainder";
break;
case ORDER_FILLING_IOC:
str="cancel remainder";
break;
case ORDER_FILLING_FOK:
str="fill or kill";
break;
default:
str="unknown type filling "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the type of order by expiration to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatTypeTime(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_TIME_GTC:
str="gtc";
break;
case ORDER_TIME_DAY:
str="day";
break;
case ORDER_TIME_SPECIFIED:
str="specified";
break;
case ORDER_TIME_SPECIFIED_DAY:
str="specified day";
break;
default:
str="unknown type time "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order parameters to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatOrder(string &str) const
{
string type,price;
long tmp_long;
//--- set up
string symbol_name=this.Symbol();
int digits=_Digits;
if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long))
digits=(int)tmp_long;
//--- form the order description
str=StringFormat("#%I64u %s %s %s",
Ticket(),
FormatType(type,OrderType()),
DoubleToString(VolumeInitial(),2),
symbol_name);
//--- receive the price of the order
FormatPrice(price,PriceOpen(),PriceStopLimit(),digits);
//--- if there is price, write it
if(price!="")
{
str+=" at ";
str+=price;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order prices to text |
//+------------------------------------------------------------------+
string CHistoryOrderInfo::FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const
{
string price,trigger;
//--- Is there its trigger price?
if(price_trigger)
{
price =DoubleToString(price_order,digits);
trigger=DoubleToString(price_trigger,digits);
str =StringFormat("%s (%s)",price,trigger);
}
else
str=DoubleToString(price_order,digits);
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Select a history order on the index |
//+------------------------------------------------------------------+
bool CHistoryOrderInfo::SelectByIndex(const int index)
{
ulong ticket=HistoryOrderGetTicket(index);
if(ticket==0)
return(false);
Ticket(ticket);
//---
return(true);
}
//+------------------------------------------------------------------+
Binary file not shown.
+553
View File
@@ -0,0 +1,553 @@
//+------------------------------------------------------------------+
//| OrderInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class COrderInfo. |
//| Appointment: Class for access to order info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class COrderInfo : public CObject
{
protected:
ulong m_ticket;
ENUM_ORDER_TYPE m_type;
ENUM_ORDER_STATE m_state;
datetime m_expiration;
double m_volume_curr;
double m_price_open;
double m_stop_loss;
double m_take_profit;
public:
COrderInfo(void);
~COrderInfo(void);
//--- methods of access to protected data
ulong Ticket(void) const { return(m_ticket); }
//--- fast access methods to the integer order propertyes
datetime TimeSetup(void) const;
ulong TimeSetupMsc(void) const;
datetime TimeDone(void) const;
ulong TimeDoneMsc(void) const;
ENUM_ORDER_TYPE OrderType(void) const;
string TypeDescription(void) const;
ENUM_ORDER_STATE State(void) const;
string StateDescription(void) const;
datetime TimeExpiration(void) const;
ENUM_ORDER_TYPE_FILLING TypeFilling(void) const;
string TypeFillingDescription(void) const;
ENUM_ORDER_TYPE_TIME TypeTime(void) const;
string TypeTimeDescription(void) const;
long Magic(void) const;
long PositionId(void) const;
long PositionById(void) const;
//--- fast access methods to the double order propertyes
double VolumeInitial(void) const;
double VolumeCurrent(void) const;
double PriceOpen(void) const;
double StopLoss(void) const;
double TakeProfit(void) const;
double PriceCurrent(void) const;
double PriceStopLimit(void) const;
//--- fast access methods to the string order propertyes
string Symbol(void) const;
string Comment(void) const;
string ExternalId(void) const;
//--- access methods to the API MQL5 functions
bool InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const;
bool InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const;
bool InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const;
//--- info methods
string FormatType(string &str,const uint type) const;
string FormatStatus(string &str,const uint status) const;
string FormatTypeFilling(string &str,const uint type) const;
string FormatTypeTime(string &str,const uint type) const;
string FormatOrder(string &str) const;
string FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const;
//--- method for select order
bool Select(void);
bool Select(const ulong ticket);
bool SelectByIndex(const int index);
//--- additional methods
void StoreState(void);
bool CheckState(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
COrderInfo::COrderInfo(void) : m_ticket(ULONG_MAX),
m_type(WRONG_VALUE),
m_state(WRONG_VALUE),
m_expiration(0),
m_volume_curr(0.0),
m_price_open(0.0),
m_stop_loss(0.0),
m_take_profit(0.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
COrderInfo::~COrderInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_SETUP" |
//+------------------------------------------------------------------+
datetime COrderInfo::TimeSetup(void) const
{
return((datetime)OrderGetInteger(ORDER_TIME_SETUP));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_SETUP_MSC" |
//+------------------------------------------------------------------+
ulong COrderInfo::TimeSetupMsc(void) const
{
return(OrderGetInteger(ORDER_TIME_SETUP_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_DONE" |
//+------------------------------------------------------------------+
datetime COrderInfo::TimeDone(void) const
{
return((datetime)OrderGetInteger(ORDER_TIME_DONE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_DONE_MSC" |
//+------------------------------------------------------------------+
ulong COrderInfo::TimeDoneMsc(void) const
{
return(OrderGetInteger(ORDER_TIME_DONE_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE COrderInfo::OrderType(void) const
{
return((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE" as string |
//+------------------------------------------------------------------+
string COrderInfo::TypeDescription(void) const
{
string str;
//---
return(FormatType(str,OrderType()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_STATE" |
//+------------------------------------------------------------------+
ENUM_ORDER_STATE COrderInfo::State(void) const
{
return((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_STATE" as string |
//+------------------------------------------------------------------+
string COrderInfo::StateDescription(void) const
{
string str;
//---
return(FormatStatus(str,State()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TIME_EXPIRATION" |
//+------------------------------------------------------------------+
datetime COrderInfo::TimeExpiration(void) const
{
return((datetime)OrderGetInteger(ORDER_TIME_EXPIRATION));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_FILLING" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_FILLING COrderInfo::TypeFilling(void) const
{
return((ENUM_ORDER_TYPE_FILLING)OrderGetInteger(ORDER_TYPE_FILLING));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_FILLING" as string |
//+------------------------------------------------------------------+
string COrderInfo::TypeFillingDescription(void) const
{
string str;
//---
return(FormatTypeFilling(str,TypeFilling()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_TIME" |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_TIME COrderInfo::TypeTime(void) const
{
return((ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TYPE_TIME" as string |
//+------------------------------------------------------------------+
string COrderInfo::TypeTimeDescription(void) const
{
string str;
//---
return(FormatTypeTime(str,TypeFilling()));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_MAGIC" |
//+------------------------------------------------------------------+
long COrderInfo::Magic(void) const
{
return(OrderGetInteger(ORDER_MAGIC));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_POSITION_ID" |
//+------------------------------------------------------------------+
long COrderInfo::PositionId(void) const
{
return(OrderGetInteger(ORDER_POSITION_ID));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_POSITION_BY_ID" |
//+------------------------------------------------------------------+
long COrderInfo::PositionById(void) const
{
return(OrderGetInteger(ORDER_POSITION_BY_ID));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_VOLUME_INITIAL" |
//+------------------------------------------------------------------+
double COrderInfo::VolumeInitial(void) const
{
return(OrderGetDouble(ORDER_VOLUME_INITIAL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_VOLUME_CURRENT" |
//+------------------------------------------------------------------+
double COrderInfo::VolumeCurrent(void) const
{
return(OrderGetDouble(ORDER_VOLUME_CURRENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_OPEN" |
//+------------------------------------------------------------------+
double COrderInfo::PriceOpen(void) const
{
return(OrderGetDouble(ORDER_PRICE_OPEN));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_SL" |
//+------------------------------------------------------------------+
double COrderInfo::StopLoss(void) const
{
return(OrderGetDouble(ORDER_SL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TP" |
//+------------------------------------------------------------------+
double COrderInfo::TakeProfit(void) const
{
return(OrderGetDouble(ORDER_TP));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_CURRENT" |
//+------------------------------------------------------------------+
double COrderInfo::PriceCurrent(void) const
{
return(OrderGetDouble(ORDER_PRICE_CURRENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_PRICE_STOPLIMIT" |
//+------------------------------------------------------------------+
double COrderInfo::PriceStopLimit(void) const
{
return(OrderGetDouble(ORDER_PRICE_STOPLIMIT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_SYMBOL" |
//+------------------------------------------------------------------+
string COrderInfo::Symbol(void) const
{
return(OrderGetString(ORDER_SYMBOL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_COMMENT" |
//+------------------------------------------------------------------+
string COrderInfo::Comment(void) const
{
return(OrderGetString(ORDER_COMMENT));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_EXTERNAL_ID" |
//+------------------------------------------------------------------+
string COrderInfo::ExternalId(void) const
{
return(OrderGetString(ORDER_EXTERNAL_ID));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetInteger(...) |
//+------------------------------------------------------------------+
bool COrderInfo::InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const
{
return(OrderGetInteger(prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetDouble(...) |
//+------------------------------------------------------------------+
bool COrderInfo::InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const
{
return(OrderGetDouble(prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions OrderGetString(...) |
//+------------------------------------------------------------------+
bool COrderInfo::InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const
{
return(OrderGetString(prop_id,var));
}
//+------------------------------------------------------------------+
//| Converts the order type to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatType(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_TYPE_BUY:
str="buy";
break;
case ORDER_TYPE_SELL:
str="sell";
break;
case ORDER_TYPE_BUY_LIMIT:
str="buy limit";
break;
case ORDER_TYPE_SELL_LIMIT:
str="sell limit";
break;
case ORDER_TYPE_BUY_STOP:
str="buy stop";
break;
case ORDER_TYPE_SELL_STOP:
str="sell stop";
break;
case ORDER_TYPE_BUY_STOP_LIMIT:
str="buy stop limit";
break;
case ORDER_TYPE_SELL_STOP_LIMIT:
str="sell stop limit";
break;
case ORDER_TYPE_CLOSE_BY:
str="close by";
break;
default :
str="unknown order type "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order status to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatStatus(string &str,const uint status) const
{
//--- see the type
switch(status)
{
case ORDER_STATE_STARTED:
str="started";
break;
case ORDER_STATE_PLACED:
str="placed";
break;
case ORDER_STATE_CANCELED:
str="canceled";
break;
case ORDER_STATE_PARTIAL:
str="partial";
break;
case ORDER_STATE_FILLED:
str="filled";
break;
case ORDER_STATE_REJECTED:
str="rejected";
break;
case ORDER_STATE_EXPIRED:
str="expired";
break;
case ORDER_STATE_REQUEST_ADD:
str="request adding";
break;
case ORDER_STATE_REQUEST_MODIFY:
str="request modifying";
break;
case ORDER_STATE_REQUEST_CANCEL:
str="request cancelling";
break;
default :
str="unknown order status "+(string)status;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order filling type to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatTypeFilling(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_FILLING_RETURN:
str="return remainder";
break;
case ORDER_FILLING_IOC:
str="cancel remainder";
break;
case ORDER_FILLING_FOK:
str="fill or kill";
break;
default:
str="unknown type filling "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the type of order by expiration to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatTypeTime(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case ORDER_TIME_GTC:
str="gtc";
break;
case ORDER_TIME_DAY:
str="day";
break;
case ORDER_TIME_SPECIFIED:
str="specified";
break;
case ORDER_TIME_SPECIFIED_DAY:
str="specified day";
break;
default:
str="unknown type time "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order parameters to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatOrder(string &str) const
{
string type,price;
long tmp_long;
//--- set up
string symbol_name=this.Symbol();
int digits=_Digits;
if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long))
digits=(int)tmp_long;
//--- form the order description
str=StringFormat("#%I64u %s %s %s",
Ticket(),
FormatType(type,OrderType()),
DoubleToString(VolumeInitial(),2),
symbol_name);
//--- receive the price of the order
FormatPrice(price,PriceOpen(),PriceStopLimit(),digits);
//--- if there is price, write it
if(price!="")
{
str+=" at ";
str+=price;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the order prices to text |
//+------------------------------------------------------------------+
string COrderInfo::FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const
{
string price,trigger;
//--- Is there its trigger price?
if(price_trigger)
{
price =DoubleToString(price_order,digits);
trigger=DoubleToString(price_trigger,digits);
str =StringFormat("%s (%s)",price,trigger);
}
else
str=DoubleToString(price_order,digits);
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Selecting an order to access |
//+------------------------------------------------------------------+
bool COrderInfo::Select(void)
{
return(OrderSelect(m_ticket));
}
//+------------------------------------------------------------------+
//| Selecting an order to access |
//+------------------------------------------------------------------+
bool COrderInfo::Select(const ulong ticket)
{
if(OrderSelect(ticket))
{
m_ticket=ticket;
return(true);
}
m_ticket=ULONG_MAX;
//---
return(false);
}
//+------------------------------------------------------------------+
//| Select an order by the index |
//+------------------------------------------------------------------+
bool COrderInfo::SelectByIndex(const int index)
{
ulong ticket=OrderGetTicket(index);
if(ticket==0)
{
m_ticket=ULONG_MAX;
return(false);
}
m_ticket=ticket;
//---
return(true);
}
//+------------------------------------------------------------------+
//| Stored order's current state |
//+------------------------------------------------------------------+
void COrderInfo::StoreState(void)
{
m_type =OrderType();
m_state =State();
m_expiration =TimeExpiration();
m_volume_curr=VolumeCurrent();
m_price_open =PriceOpen();
m_stop_loss =StopLoss();
m_take_profit=TakeProfit();
}
//+------------------------------------------------------------------+
//| Check order change |
//+------------------------------------------------------------------+
bool COrderInfo::CheckState(void)
{
if(m_type==OrderType() &&
m_state==State() &&
m_expiration==TimeExpiration() &&
m_volume_curr==VolumeCurrent() &&
m_price_open==PriceOpen() &&
m_stop_loss==StopLoss() &&
m_take_profit==TakeProfit())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
+364
View File
@@ -0,0 +1,364 @@
//+------------------------------------------------------------------+
//| PositionInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CPositionInfo. |
//| Appointment: Class for access to position info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CPositionInfo : public CObject
{
protected:
ENUM_POSITION_TYPE m_type;
double m_volume;
double m_price;
double m_stop_loss;
double m_take_profit;
public:
CPositionInfo(void);
~CPositionInfo(void);
//--- fast access methods to the integer position propertyes
ulong Ticket(void) const;
datetime Time(void) const;
ulong TimeMsc(void) const;
datetime TimeUpdate(void) const;
ulong TimeUpdateMsc(void) const;
ENUM_POSITION_TYPE PositionType(void) const;
string TypeDescription(void) const;
long Magic(void) const;
long Identifier(void) const;
//--- fast access methods to the double position propertyes
double Volume(void) const;
double PriceOpen(void) const;
double StopLoss(void) const;
double TakeProfit(void) const;
double PriceCurrent(void) const;
double Commission(void) const;
double Swap(void) const;
double Profit(void) const;
//--- fast access methods to the string position propertyes
string Symbol(void) const;
string Comment(void) const;
//--- access methods to the API MQL5 functions
bool InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const;
bool InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const;
bool InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const;
//--- info methods
string FormatType(string &str,const uint type) const;
string FormatPosition(string &str) const;
//--- methods for select position
bool Select(const string symbol);
bool SelectByMagic(const string symbol,const ulong magic);
bool SelectByTicket(const ulong ticket);
bool SelectByIndex(const int index);
//---
void StoreState(void);
bool CheckState(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CPositionInfo::CPositionInfo(void) : m_type(WRONG_VALUE),
m_volume(0.0),
m_price(0.0),
m_stop_loss(0.0),
m_take_profit(0.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CPositionInfo::~CPositionInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TICKET" |
//+------------------------------------------------------------------+
ulong CPositionInfo::Ticket(void) const
{
return((ulong)PositionGetInteger(POSITION_TICKET));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TIME" |
//+------------------------------------------------------------------+
datetime CPositionInfo::Time(void) const
{
return((datetime)PositionGetInteger(POSITION_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TIME_MSC" |
//+------------------------------------------------------------------+
ulong CPositionInfo::TimeMsc(void) const
{
return((ulong)PositionGetInteger(POSITION_TIME_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TIME_UPDATE" |
//+------------------------------------------------------------------+
datetime CPositionInfo::TimeUpdate(void) const
{
return((datetime)PositionGetInteger(POSITION_TIME_UPDATE));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TIME_UPDATE_MSC" |
//+------------------------------------------------------------------+
ulong CPositionInfo::TimeUpdateMsc(void) const
{
return((ulong)PositionGetInteger(POSITION_TIME_UPDATE_MSC));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TYPE" |
//+------------------------------------------------------------------+
ENUM_POSITION_TYPE CPositionInfo::PositionType(void) const
{
return((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TYPE" as string |
//+------------------------------------------------------------------+
string CPositionInfo::TypeDescription(void) const
{
string str;
//---
return(FormatType(str,PositionType()));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_MAGIC" |
//+------------------------------------------------------------------+
long CPositionInfo::Magic(void) const
{
return(PositionGetInteger(POSITION_MAGIC));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_IDENTIFIER" |
//+------------------------------------------------------------------+
long CPositionInfo::Identifier(void) const
{
return(PositionGetInteger(POSITION_IDENTIFIER));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_VOLUME" |
//+------------------------------------------------------------------+
double CPositionInfo::Volume(void) const
{
return(PositionGetDouble(POSITION_VOLUME));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_PRICE_OPEN" |
//+------------------------------------------------------------------+
double CPositionInfo::PriceOpen(void) const
{
return(PositionGetDouble(POSITION_PRICE_OPEN));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_SL" |
//+------------------------------------------------------------------+
double CPositionInfo::StopLoss(void) const
{
return(PositionGetDouble(POSITION_SL));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_TP" |
//+------------------------------------------------------------------+
double CPositionInfo::TakeProfit(void) const
{
return(PositionGetDouble(POSITION_TP));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_PRICE_CURRENT" |
//+------------------------------------------------------------------+
double CPositionInfo::PriceCurrent(void) const
{
return(PositionGetDouble(POSITION_PRICE_CURRENT));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_COMMISSION" |
//+------------------------------------------------------------------+
double CPositionInfo::Commission(void) const
{
return(PositionGetDouble(POSITION_COMMISSION));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_SWAP" |
//+------------------------------------------------------------------+
double CPositionInfo::Swap(void) const
{
return(PositionGetDouble(POSITION_SWAP));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_PROFIT" |
//+------------------------------------------------------------------+
double CPositionInfo::Profit(void) const
{
return(PositionGetDouble(POSITION_PROFIT));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_SYMBOL" |
//+------------------------------------------------------------------+
string CPositionInfo::Symbol(void) const
{
return(PositionGetString(POSITION_SYMBOL));
}
//+------------------------------------------------------------------+
//| Get the property value "POSITION_COMMENT" |
//+------------------------------------------------------------------+
string CPositionInfo::Comment(void) const
{
return(PositionGetString(POSITION_COMMENT));
}
//+------------------------------------------------------------------+
//| Access functions PositionGetInteger(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const
{
return(PositionGetInteger(prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions PositionGetDouble(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const
{
return(PositionGetDouble(prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions PositionGetString(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const
{
return(PositionGetString(prop_id,var));
}
//+------------------------------------------------------------------+
//| Converts the position type to text |
//+------------------------------------------------------------------+
string CPositionInfo::FormatType(string &str,const uint type) const
{
//--- see the type
switch(type)
{
case POSITION_TYPE_BUY:
str="buy";
break;
case POSITION_TYPE_SELL:
str="sell";
break;
default:
str="unknown position type "+(string)type;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Converts the position parameters to text |
//+------------------------------------------------------------------+
string CPositionInfo::FormatPosition(string &str) const
{
string tmp,type;
long tmp_long;
ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
//--- set up
string symbol_name=this.Symbol();
int digits=_Digits;
if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long))
digits=(int)tmp_long;
//--- form the position description
if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
str=StringFormat("#%I64u %s %s %s %s",
Ticket(),
FormatType(type,PositionType()),
DoubleToString(Volume(),2),
symbol_name,
DoubleToString(PriceOpen(),digits+3));
else
str=StringFormat("%s %s %s %s",
FormatType(type,PositionType()),
DoubleToString(Volume(),2),
symbol_name,
DoubleToString(PriceOpen(),digits+3));
//--- add stops if there are any
double sl=StopLoss();
double tp=TakeProfit();
if(sl!=0.0)
{
tmp=StringFormat(" sl: %s",DoubleToString(sl,digits));
str+=tmp;
}
if(tp!=0.0)
{
tmp=StringFormat(" tp: %s",DoubleToString(tp,digits));
str+=tmp;
}
//--- return the result
return(str);
}
//+------------------------------------------------------------------+
//| Access functions PositionSelect(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::Select(const string symbol)
{
return(PositionSelect(symbol));
}
//+------------------------------------------------------------------+
//| Access functions PositionSelect(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::SelectByMagic(const string symbol,const ulong magic)
{
bool res=false;
uint total=PositionsTotal();
//---
for(uint i=0; i<total; i++)
{
string position_symbol=PositionGetSymbol(i);
if(position_symbol==symbol && magic==PositionGetInteger(POSITION_MAGIC))
{
res=true;
break;
}
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Access functions PositionSelectByTicket(...) |
//+------------------------------------------------------------------+
bool CPositionInfo::SelectByTicket(const ulong ticket)
{
return(PositionSelectByTicket(ticket));
}
//+------------------------------------------------------------------+
//| Select a position on the index |
//+------------------------------------------------------------------+
bool CPositionInfo::SelectByIndex(const int index)
{
ulong ticket=PositionGetTicket(index);
return(ticket>0);
}
//+------------------------------------------------------------------+
//| Stored position's current state |
//+------------------------------------------------------------------+
void CPositionInfo::StoreState(void)
{
m_type =PositionType();
m_volume =Volume();
m_price =PriceOpen();
m_stop_loss =StopLoss();
m_take_profit=TakeProfit();
}
//+------------------------------------------------------------------+
//| Check position change |
//+------------------------------------------------------------------+
bool CPositionInfo::CheckState(void)
{
if(m_type==PositionType() &&
m_volume==Volume() &&
m_price==PriceOpen() &&
m_stop_loss==StopLoss() &&
m_take_profit==TakeProfit())
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
+789
View File
@@ -0,0 +1,789 @@
//+------------------------------------------------------------------+
//| SymbolInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CSymbolInfo. |
//| Appointment: Class for access to symbol info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CSymbolInfo : public CObject
{
protected:
string m_name; // symbol name
MqlTick m_tick; // structure of tick;
double m_point; // symbol point
double m_tick_value; // symbol tick value
double m_tick_value_profit; // symbol tick value profit
double m_tick_value_loss; // symbol tick value loss
double m_tick_size; // symbol tick size
double m_contract_size; // symbol contract size
double m_lots_min; // symbol lots min
double m_lots_max; // symbol lots max
double m_lots_step; // symbol lots step
double m_lots_limit; // symbol lots limit
double m_swap_long; // symbol swap long
double m_swap_short; // symbol swap short
int m_digits; // symbol digits
int m_order_mode; // symbol valid orders
ENUM_SYMBOL_TRADE_EXECUTION m_trade_execution; // symbol trade execution
ENUM_SYMBOL_CALC_MODE m_trade_calcmode; // symbol trade calcmode
ENUM_SYMBOL_TRADE_MODE m_trade_mode; // symbol trade mode
ENUM_SYMBOL_SWAP_MODE m_swap_mode; // symbol swap mode
ENUM_DAY_OF_WEEK m_swap3; // symbol swap3
double m_margin_initial; // symbol margin initial
double m_margin_maintenance; // symbol margin maintenance
bool m_margin_hedged_use_leg; // calculate hedged margin using larger leg
double m_margin_hedged; // symbol margin hedged
int m_trade_time_flags; // symbol trade time flags
int m_trade_fill_flags; // symbol trade fill flags
public:
CSymbolInfo(void);
~CSymbolInfo(void);
//--- methods of access to protected data
string Name(void) const { return(m_name); }
bool Name(const string name);
bool Refresh(void);
bool RefreshRates(void);
//--- fast access methods to the integer symbol propertyes
bool Select(void) const;
bool Select(const bool select);
bool IsSynchronized(void) const;
//--- volumes
ulong Volume(void) const { return(m_tick.volume); }
ulong VolumeHigh(void) const;
ulong VolumeLow(void) const;
//--- miscellaneous
datetime Time(void) const { return(m_tick.time); }
int Spread(void) const;
bool SpreadFloat(void) const;
int TicksBookDepth(void) const;
//--- trade levels
int StopsLevel(void) const;
int FreezeLevel(void) const;
//--- fast access methods to the double symbol propertyes
//--- bid parameters
double Bid(void) const { return(m_tick.bid); }
double BidHigh(void) const;
double BidLow(void) const;
//--- ask parameters
double Ask(void) const { return(m_tick.ask); }
double AskHigh(void) const;
double AskLow(void) const;
//--- last parameters
double Last(void) const { return(m_tick.last); }
double LastHigh(void) const;
double LastLow(void) const;
//--- fast access methods to the mix symbol propertyes
int OrderMode(void) const { return(m_order_mode); }
//--- terms of trade
ENUM_SYMBOL_CALC_MODE TradeCalcMode(void) const { return(m_trade_calcmode); }
string TradeCalcModeDescription(void) const;
ENUM_SYMBOL_TRADE_MODE TradeMode(void) const { return(m_trade_mode); }
string TradeModeDescription(void) const;
//--- execution terms of trade
ENUM_SYMBOL_TRADE_EXECUTION TradeExecution(void) const { return(m_trade_execution); }
string TradeExecutionDescription(void) const;
//--- swap terms of trade
ENUM_SYMBOL_SWAP_MODE SwapMode(void) const { return(m_swap_mode); }
string SwapModeDescription(void) const;
ENUM_DAY_OF_WEEK SwapRollover3days(void) const { return(m_swap3); }
string SwapRollover3daysDescription(void) const;
//--- dates for futures
datetime StartTime(void) const;
datetime ExpirationTime(void) const;
//--- margin parameters
double MarginInitial(void) const { return(m_margin_initial); }
double MarginMaintenance(void) const { return(m_margin_maintenance); }
bool MarginHedgedUseLeg(void) const { return(m_margin_hedged_use_leg); }
double MarginHedged(void) const { return(m_margin_hedged); }
//--- left for backward compatibility
double MarginLong(void) const { return(0.0); }
double MarginShort(void) const { return(0.0); }
double MarginLimit(void) const { return(0.0); }
double MarginStop(void) const { return(0.0); }
double MarginStopLimit(void) const { return(0.0); }
//--- trade flags parameters
int TradeTimeFlags(void) const { return(m_trade_time_flags); }
int TradeFillFlags(void) const { return(m_trade_fill_flags); }
//--- tick parameters
int Digits(void) const { return(m_digits); }
double Point(void) const { return(m_point); }
double TickValue(void) const { return(m_tick_value); }
double TickValueProfit(void) const { return(m_tick_value_profit); }
double TickValueLoss(void) const { return(m_tick_value_loss); }
double TickSize(void) const { return(m_tick_size); }
//--- lots parameters
double ContractSize(void) const { return(m_contract_size); }
double LotsMin(void) const { return(m_lots_min); }
double LotsMax(void) const { return(m_lots_max); }
double LotsStep(void) const { return(m_lots_step); }
double LotsLimit(void) const { return(m_lots_limit); }
//--- swaps
double SwapLong(void) const { return(m_swap_long); }
double SwapShort(void) const { return(m_swap_short); }
//--- fast access methods to the string symbol propertyes
string CurrencyBase(void) const;
string CurrencyProfit(void) const;
string CurrencyMargin(void) const;
string Bank(void) const;
string Description(void) const;
string Path(void) const;
//--- session information
long SessionDeals(void) const;
long SessionBuyOrders(void) const;
long SessionSellOrders(void) const;
double SessionTurnover(void) const;
double SessionInterest(void) const;
double SessionBuyOrdersVolume(void) const;
double SessionSellOrdersVolume(void) const;
double SessionOpen(void) const;
double SessionClose(void) const;
double SessionAW(void) const;
double SessionPriceSettlement(void) const;
double SessionPriceLimitMin(void) const;
double SessionPriceLimitMax(void) const;
//--- access methods to the API MQL5 functions
bool InfoInteger(const ENUM_SYMBOL_INFO_INTEGER prop_id,long& var) const;
bool InfoDouble(const ENUM_SYMBOL_INFO_DOUBLE prop_id,double& var) const;
bool InfoString(const ENUM_SYMBOL_INFO_STRING prop_id,string& var) const;
bool InfoMarginRate(const ENUM_ORDER_TYPE order_type,double& initial_margin_rate,double& maintenance_margin_rate) const;
//--- service methods
double NormalizePrice(const double price) const;
bool CheckMarketWatch(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSymbolInfo::CSymbolInfo(void) : m_name(NULL),
m_point(0.0),
m_tick_value(0.0),
m_tick_value_profit(0.0),
m_tick_value_loss(0.0),
m_tick_size(0.0),
m_contract_size(0.0),
m_lots_min(0.0),
m_lots_max(0.0),
m_lots_step(0.0),
m_swap_long(0.0),
m_swap_short(0.0),
m_digits(0),
m_order_mode(0),
m_trade_execution(0),
m_trade_calcmode(0),
m_trade_mode(0),
m_swap_mode(0),
m_swap3(0),
m_margin_initial(0.0),
m_margin_maintenance(0.0),
m_margin_hedged_use_leg(false),
m_margin_hedged(0.0),
m_trade_time_flags(0),
m_trade_fill_flags(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSymbolInfo::~CSymbolInfo(void)
{
}
//+------------------------------------------------------------------+
//| Set name |
//+------------------------------------------------------------------+
bool CSymbolInfo::Name(const string name)
{
string symbol_name=StringLen(name)>0 ? name : _Symbol;
//--- check previous set name
if(m_name!=symbol_name)
{
m_name=symbol_name;
//---
if(!CheckMarketWatch())
return(false);
//---
if(!Refresh())
{
m_name="";
Print(__FUNCTION__+": invalid data of symbol '"+symbol_name+"'");
return(false);
}
}
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Refresh cached data |
//+------------------------------------------------------------------+
bool CSymbolInfo::Refresh(void)
{
long tmp_long=0;
//---
if(!SymbolInfoDouble(m_name,SYMBOL_POINT,m_point))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE,m_tick_value))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT,m_tick_value_profit))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_LOSS,m_tick_value_loss))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_SIZE,m_tick_size))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE,m_contract_size))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MIN,m_lots_min))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MAX,m_lots_max))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP,m_lots_step))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_LIMIT,m_lots_limit))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_LONG,m_swap_long))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_SHORT,m_swap_short))
return(false);
if(!SymbolInfoInteger(m_name,SYMBOL_DIGITS,tmp_long))
return(false);
m_digits=(int)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_ORDER_MODE,tmp_long))
return(false);
m_order_mode=(int)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_EXEMODE,tmp_long))
return(false);
m_trade_execution=(ENUM_SYMBOL_TRADE_EXECUTION)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE,tmp_long))
return(false);
m_trade_calcmode=(ENUM_SYMBOL_CALC_MODE)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_MODE,tmp_long))
return(false);
m_trade_mode=(ENUM_SYMBOL_TRADE_MODE)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_MODE,tmp_long))
return(false);
m_swap_mode=(ENUM_SYMBOL_SWAP_MODE)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_ROLLOVER3DAYS,tmp_long))
return(false);
m_swap3=(ENUM_DAY_OF_WEEK)tmp_long;
if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL,m_margin_initial))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_MAINTENANCE,m_margin_maintenance))
return(false);
if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_HEDGED,m_margin_hedged))
return(false);
if(!SymbolInfoInteger(m_name,SYMBOL_MARGIN_HEDGED_USE_LEG,tmp_long))
return(false);
m_margin_hedged_use_leg=(bool)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_EXPIRATION_MODE,tmp_long))
return(false);
m_trade_time_flags=(int)tmp_long;
if(!SymbolInfoInteger(m_name,SYMBOL_FILLING_MODE,tmp_long))
return(false);
m_trade_fill_flags=(int)tmp_long;
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Refresh cached data |
//+------------------------------------------------------------------+
bool CSymbolInfo::RefreshRates(void)
{
return(SymbolInfoTick(m_name,m_tick));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SELECT" |
//+------------------------------------------------------------------+
bool CSymbolInfo::Select(void) const
{
return((bool)SymbolInfoInteger(m_name,SYMBOL_SELECT));
}
//+------------------------------------------------------------------+
//| Set the property value "SYMBOL_SELECT" |
//+------------------------------------------------------------------+
bool CSymbolInfo::Select(const bool select)
{
return(SymbolSelect(m_name,select));
}
//+------------------------------------------------------------------+
//| Check synchronize symbol |
//+------------------------------------------------------------------+
bool CSymbolInfo::IsSynchronized(void) const
{
return(SymbolIsSynchronized(m_name));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_VOLUMEHIGH" |
//+------------------------------------------------------------------+
ulong CSymbolInfo::VolumeHigh(void) const
{
return(SymbolInfoInteger(m_name,SYMBOL_VOLUMEHIGH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_VOLUMELOW" |
//+------------------------------------------------------------------+
ulong CSymbolInfo::VolumeLow(void) const
{
return(SymbolInfoInteger(m_name,SYMBOL_VOLUMELOW));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SPREAD" |
//+------------------------------------------------------------------+
int CSymbolInfo::Spread(void) const
{
return((int)SymbolInfoInteger(m_name,SYMBOL_SPREAD));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SPREAD_FLOAT" |
//+------------------------------------------------------------------+
bool CSymbolInfo::SpreadFloat(void) const
{
return((bool)SymbolInfoInteger(m_name,SYMBOL_SPREAD_FLOAT));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TICKS_BOOKDEPTH" |
//+------------------------------------------------------------------+
int CSymbolInfo::TicksBookDepth(void) const
{
return((int)SymbolInfoInteger(m_name,SYMBOL_TICKS_BOOKDEPTH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TRADE_STOPS_LEVEL" |
//+------------------------------------------------------------------+
int CSymbolInfo::StopsLevel(void) const
{
return((int)SymbolInfoInteger(m_name,SYMBOL_TRADE_STOPS_LEVEL));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TRADE_FREEZE_LEVEL" |
//+------------------------------------------------------------------+
int CSymbolInfo::FreezeLevel(void) const
{
return((int)SymbolInfoInteger(m_name,SYMBOL_TRADE_FREEZE_LEVEL));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_BIDHIGH" |
//+------------------------------------------------------------------+
double CSymbolInfo::BidHigh(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_BIDHIGH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_BIDLOW" |
//+------------------------------------------------------------------+
double CSymbolInfo::BidLow(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_BIDLOW));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_ASKHIGH" |
//+------------------------------------------------------------------+
double CSymbolInfo::AskHigh(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_ASKHIGH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_ASKLOW" |
//+------------------------------------------------------------------+
double CSymbolInfo::AskLow(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_ASKLOW));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_LASTHIGH" |
//+------------------------------------------------------------------+
double CSymbolInfo::LastHigh(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_LASTHIGH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_LASTLOW" |
//+------------------------------------------------------------------+
double CSymbolInfo::LastLow(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_LASTLOW));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TRADE_CALC_MODE" as string |
//+------------------------------------------------------------------+
string CSymbolInfo::TradeCalcModeDescription(void) const
{
string str;
//---
switch(m_trade_calcmode)
{
case SYMBOL_CALC_MODE_FOREX:
str="Calculation of profit and margin for Forex";
break;
case SYMBOL_CALC_MODE_CFD:
str="Calculation of collateral and earnings for CFD";
break;
case SYMBOL_CALC_MODE_FUTURES:
str="Calculation of collateral and profits for futures";
break;
case SYMBOL_CALC_MODE_CFDINDEX:
str="Calculation of collateral and earnings for CFD on indices";
break;
case SYMBOL_CALC_MODE_CFDLEVERAGE:
str="Calculation of collateral and earnings for the CFD when trading with leverage";
break;
case SYMBOL_CALC_MODE_EXCH_STOCKS:
str="Calculation for exchange stocks";
break;
case SYMBOL_CALC_MODE_EXCH_FUTURES:
str="Calculation for exchange futures";
break;
case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
str="Calculation for FORTS futures";
break;
default:
str="Unknown calculation mode";
}
//--- result
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TRADE_MODE" as string |
//+------------------------------------------------------------------+
string CSymbolInfo::TradeModeDescription(void) const
{
string str;
//---
switch(m_trade_mode)
{
case SYMBOL_TRADE_MODE_DISABLED:
str="Disabled";
break;
case SYMBOL_TRADE_MODE_LONGONLY:
str="Long only";
break;
case SYMBOL_TRADE_MODE_SHORTONLY:
str="Short only";
break;
case SYMBOL_TRADE_MODE_CLOSEONLY:
str="Close only";
break;
case SYMBOL_TRADE_MODE_FULL:
str="Full access";
break;
default:
str="Unknown trade mode";
}
//--- result
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_TRADE_EXEMODE" as string |
//+------------------------------------------------------------------+
string CSymbolInfo::TradeExecutionDescription(void) const
{
string str;
//---
switch(m_trade_execution)
{
case SYMBOL_TRADE_EXECUTION_REQUEST:
str="Trading on request";
break;
case SYMBOL_TRADE_EXECUTION_INSTANT:
str="Trading on live streaming prices";
break;
case SYMBOL_TRADE_EXECUTION_MARKET:
str="Execution of orders on the market";
break;
case SYMBOL_TRADE_EXECUTION_EXCHANGE:
str="Exchange execution";
break;
default:
str="Unknown trade execution";
}
//--- result
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SWAP_MODE" as string |
//+------------------------------------------------------------------+
string CSymbolInfo::SwapModeDescription(void) const
{
string str;
//---
switch(m_swap_mode)
{
case SYMBOL_SWAP_MODE_DISABLED:
str="No swaps";
break;
case SYMBOL_SWAP_MODE_POINTS:
str="Swaps are calculated in points";
break;
case SYMBOL_SWAP_MODE_CURRENCY_SYMBOL:
str="Swaps are calculated in base currency";
break;
case SYMBOL_SWAP_MODE_CURRENCY_MARGIN:
str="Swaps are calculated in margin currency";
break;
case SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT:
str="Swaps are calculated in deposit currency";
break;
case SYMBOL_SWAP_MODE_INTEREST_CURRENT:
str="Swaps are calculated as annual interest using the current price";
break;
case SYMBOL_SWAP_MODE_INTEREST_OPEN:
str="Swaps are calculated as annual interest using the open price";
break;
case SYMBOL_SWAP_MODE_REOPEN_CURRENT:
str="Swaps are charged by reopening positions at the close price";
break;
case SYMBOL_SWAP_MODE_REOPEN_BID:
str="Swaps are charged by reopening positions at the Bid price";
break;
default:
str="Unknown swap mode";
}
//--- result
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SWAP_ROLLOVER3DAYS" as string |
//+------------------------------------------------------------------+
string CSymbolInfo::SwapRollover3daysDescription(void) const
{
string str;
//---
switch(m_swap3)
{
case SUNDAY:
str="Sunday";
break;
case MONDAY:
str="Monday";
break;
case TUESDAY:
str="Tuesday";
break;
case WEDNESDAY:
str="Wednesday";
break;
case THURSDAY:
str="Thursday";
break;
case FRIDAY:
str="Friday";
break;
case SATURDAY:
str="Saturday";
break;
default:
str="Unknown";
}
//--- result
return(str);
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_START_TIME" |
//+------------------------------------------------------------------+
datetime CSymbolInfo::StartTime(void) const
{
return((datetime)SymbolInfoInteger(m_name,SYMBOL_START_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_EXPIRATION_TIME" |
//+------------------------------------------------------------------+
datetime CSymbolInfo::ExpirationTime(void) const
{
return((datetime)SymbolInfoInteger(m_name,SYMBOL_EXPIRATION_TIME));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_CURRENCY_BASE" |
//+------------------------------------------------------------------+
string CSymbolInfo::CurrencyBase(void) const
{
return(SymbolInfoString(m_name,SYMBOL_CURRENCY_BASE));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_CURRENCY_PROFIT" |
//+------------------------------------------------------------------+
string CSymbolInfo::CurrencyProfit(void) const
{
return(SymbolInfoString(m_name,SYMBOL_CURRENCY_PROFIT));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_CURRENCY_MARGIN" |
//+------------------------------------------------------------------+
string CSymbolInfo::CurrencyMargin(void) const
{
return(SymbolInfoString(m_name,SYMBOL_CURRENCY_MARGIN));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_BANK" |
//+------------------------------------------------------------------+
string CSymbolInfo::Bank(void) const
{
return(SymbolInfoString(m_name,SYMBOL_BANK));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_DESCRIPTION" |
//+------------------------------------------------------------------+
string CSymbolInfo::Description(void) const
{
return(SymbolInfoString(m_name,SYMBOL_DESCRIPTION));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_PATH" |
//+------------------------------------------------------------------+
string CSymbolInfo::Path(void) const
{
return(SymbolInfoString(m_name,SYMBOL_PATH));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_DEALS" |
//+------------------------------------------------------------------+
long CSymbolInfo::SessionDeals(void) const
{
return(SymbolInfoInteger(m_name,SYMBOL_SESSION_DEALS));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_BUY_ORDERS" |
//+------------------------------------------------------------------+
long CSymbolInfo::SessionBuyOrders(void) const
{
return(SymbolInfoInteger(m_name,SYMBOL_SESSION_BUY_ORDERS));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_SELL_ORDERS" |
//+------------------------------------------------------------------+
long CSymbolInfo::SessionSellOrders(void) const
{
return(SymbolInfoInteger(m_name,SYMBOL_SESSION_SELL_ORDERS));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_TURNOVER" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionTurnover(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_TURNOVER));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_INTEREST" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionInterest(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_INTEREST));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_BUY_ORDERS_VOLUME" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionBuyOrdersVolume(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_SELL_ORDERS_VOLUME" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionSellOrdersVolume(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_OPEN" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionOpen(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_OPEN));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_CLOSE" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionClose(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_CLOSE));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_AW" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionAW(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_AW));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_PRICE_SETTLEMENT" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionPriceSettlement(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_SETTLEMENT));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_PRICE_LIMIT_MIN" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionPriceLimitMin(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN));
}
//+------------------------------------------------------------------+
//| Get the property value "SYMBOL_SESSION_PRICE_LIMIT_MAX" |
//+------------------------------------------------------------------+
double CSymbolInfo::SessionPriceLimitMax(void) const
{
return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX));
}
//+------------------------------------------------------------------+
//| Access functions SymbolInfoInteger(...) |
//+------------------------------------------------------------------+
bool CSymbolInfo::InfoInteger(const ENUM_SYMBOL_INFO_INTEGER prop_id,long &var) const
{
return(SymbolInfoInteger(m_name,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions SymbolInfoDouble(...) |
//+------------------------------------------------------------------+
bool CSymbolInfo::InfoDouble(const ENUM_SYMBOL_INFO_DOUBLE prop_id,double &var) const
{
return(SymbolInfoDouble(m_name,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions SymbolInfoString(...) |
//+------------------------------------------------------------------+
bool CSymbolInfo::InfoString(const ENUM_SYMBOL_INFO_STRING prop_id,string &var) const
{
return(SymbolInfoString(m_name,prop_id,var));
}
//+------------------------------------------------------------------+
//| Access functions SymbolInfoMarginRate(...) |
//+------------------------------------------------------------------+
bool CSymbolInfo::InfoMarginRate(const ENUM_ORDER_TYPE order_type,double& initial_margin_rate,double& maintenance_margin_rate) const
{
return(SymbolInfoMarginRate(m_name,order_type,initial_margin_rate,maintenance_margin_rate));
}
//+------------------------------------------------------------------+
//| Normalize price |
//+------------------------------------------------------------------+
double CSymbolInfo::NormalizePrice(const double price) const
{
if(m_tick_size!=0)
return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,m_digits));
//---
return(NormalizeDouble(price,m_digits));
}
//+------------------------------------------------------------------+
//| Checks if symbol is selected in the MarketWatch |
//| and adds symbol to the MarketWatch, if necessary |
//+------------------------------------------------------------------+
bool CSymbolInfo::CheckMarketWatch(void)
{
//--- check if symbol is selected in the MarketWatch
if(!Select())
{
if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL)
{
printf(__FUNCTION__+": Unknown symbol '%s'",m_name);
return(false);
}
if(!Select(true))
{
printf(__FUNCTION__+": Error adding symbol %d",GetLastError());
return(false);
}
}
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
+225
View File
@@ -0,0 +1,225 @@
//+------------------------------------------------------------------+
//| TerminalInfo.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CTerminalInfo. |
//| Appointment: Class for access to terminal info. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CTerminalInfo : public CObject
{
public:
CTerminalInfo(void);
~CTerminalInfo(void);
//--- fast access methods to the integer terminal propertyes
int Build(void) const;
bool IsConnected(void) const;
bool IsDLLsAllowed(void) const;
bool IsTradeAllowed(void) const;
bool IsEmailEnabled(void) const;
bool IsFtpEnabled(void) const;
int MaxBars(void) const;
int CodePage(void) const;
int CPUCores(void) const;
int MemoryPhysical(void) const;
int MemoryTotal(void) const;
int MemoryAvailable(void) const;
int MemoryUsed(void) const;
bool IsX64(void) const;
int OpenCLSupport(void) const;
int DiskSpace(void) const;
//--- fast access methods to the string terminal propertyes
string Language(void) const;
string Name(void) const;
string Company(void) const;
string Path(void) const;
string DataPath(void) const;
string CommonDataPath(void) const;
//--- access methods to the API MQL5 functions
long InfoInteger(const ENUM_TERMINAL_INFO_INTEGER prop_id) const;
string InfoString(const ENUM_TERMINAL_INFO_STRING prop_id) const;
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CTerminalInfo::CTerminalInfo(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTerminalInfo::~CTerminalInfo(void)
{
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_BUILD" |
//+------------------------------------------------------------------+
int CTerminalInfo::Build(void) const
{
return((int)TerminalInfoInteger(TERMINAL_BUILD));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_CONNECTED" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsConnected(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_CONNECTED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_DLLS_ALLOWED" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsDLLsAllowed(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_DLLS_ALLOWED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_TRADE_ALLOWED" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsTradeAllowed(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_TRADE_ALLOWED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_EMAIL_ENABLED" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsEmailEnabled(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_EMAIL_ENABLED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_FTP_ENABLED" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsFtpEnabled(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_FTP_ENABLED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_MAXBARS" |
//+------------------------------------------------------------------+
int CTerminalInfo::MaxBars(void) const
{
return((int)TerminalInfoInteger(TERMINAL_MAXBARS));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_CODEPAGE" |
//+------------------------------------------------------------------+
int CTerminalInfo::CodePage(void) const
{
return((int)TerminalInfoInteger(TERMINAL_CODEPAGE));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_CPU_CORES" |
//+------------------------------------------------------------------+
int CTerminalInfo::CPUCores(void) const
{
return((int)TerminalInfoInteger(TERMINAL_CPU_CORES));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_MEMORY_PHYSICAL" |
//+------------------------------------------------------------------+
int CTerminalInfo::MemoryPhysical(void) const
{
return((int)TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_MEMORY_TOTAL" |
//+------------------------------------------------------------------+
int CTerminalInfo::MemoryTotal(void) const
{
return((int)TerminalInfoInteger(TERMINAL_MEMORY_TOTAL));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_MEMORY_AVAILABLE" |
//+------------------------------------------------------------------+
int CTerminalInfo::MemoryAvailable(void) const
{
return((int)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_MEMORY_USED" |
//+------------------------------------------------------------------+
int CTerminalInfo::MemoryUsed(void) const
{
return((int)TerminalInfoInteger(TERMINAL_MEMORY_USED));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_X64" |
//+------------------------------------------------------------------+
bool CTerminalInfo::IsX64(void) const
{
return((bool)TerminalInfoInteger(TERMINAL_X64));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_OPENCL_SUPPORT" |
//+------------------------------------------------------------------+
int CTerminalInfo::OpenCLSupport(void) const
{
return((int)TerminalInfoInteger(TERMINAL_OPENCL_SUPPORT));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_DISK_SPACE" |
//+------------------------------------------------------------------+
int CTerminalInfo::DiskSpace(void) const
{
return((int)TerminalInfoInteger(TERMINAL_DISK_SPACE));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_LANGUAGE" |
//+------------------------------------------------------------------+
string CTerminalInfo::Language(void) const
{
return(TerminalInfoString(TERMINAL_LANGUAGE));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_NAME" |
//+------------------------------------------------------------------+
string CTerminalInfo::Name(void) const
{
return(TerminalInfoString(TERMINAL_NAME));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_COMPANY" |
//+------------------------------------------------------------------+
string CTerminalInfo::Company(void) const
{
return(TerminalInfoString(TERMINAL_COMPANY));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_PATH" |
//+------------------------------------------------------------------+
string CTerminalInfo::Path(void) const
{
return(TerminalInfoString(TERMINAL_PATH));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_DATA_PATH" |
//+------------------------------------------------------------------+
string CTerminalInfo::DataPath(void) const
{
return(TerminalInfoString(TERMINAL_DATA_PATH));
}
//+------------------------------------------------------------------+
//| Get the property value "TERMINAL_COMMONDATA_PATH" |
//+------------------------------------------------------------------+
string CTerminalInfo::CommonDataPath(void) const
{
return(TerminalInfoString(TERMINAL_COMMONDATA_PATH));
}
//+------------------------------------------------------------------+
//| Access functions AccountInfoInteger(...) |
//+------------------------------------------------------------------+
long CTerminalInfo::InfoInteger(const ENUM_TERMINAL_INFO_INTEGER prop_id) const
{
return(TerminalInfoInteger(prop_id));
}
//+------------------------------------------------------------------+
//| Access functions AccountInfoString(...) |
//+------------------------------------------------------------------+
string CTerminalInfo::InfoString(const ENUM_TERMINAL_INFO_STRING prop_id) const
{
return(TerminalInfoString(prop_id));
}
//+------------------------------------------------------------------+
+1708
View File
File diff suppressed because it is too large Load Diff
+385
View File
@@ -0,0 +1,385 @@
//+------------------------------------------------------------------+
//| Box.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "www.mql5.com/en/users/iceron"
#include <Controls\WndClient.mqh>
#define CLASS_LAYOUT 999
#ifdef LAYOUT_BOX_DEBUG
#define COLOR_BOX_BORDER clrRed
#else
#define COLOR_BOX_BORDER clrNONE
#endif
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum LAYOUT_STYLE
{
LAYOUT_STYLE_VERTICAL,
LAYOUT_STYLE_HORIZONTAL
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum VERTICAL_ALIGN
{
VERTICAL_ALIGN_CENTER,
VERTICAL_ALIGN_CENTER_NOSIDES,
VERTICAL_ALIGN_TOP,
VERTICAL_ALIGN_BOTTOM
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum HORIZONTAL_ALIGN
{
HORIZONTAL_ALIGN_CENTER,
HORIZONTAL_ALIGN_CENTER_NOSIDES,
HORIZONTAL_ALIGN_LEFT,
HORIZONTAL_ALIGN_RIGHT
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CBox: public CWndClient
{
protected:
LAYOUT_STYLE m_layout_style;
VERTICAL_ALIGN m_vertical_align;
HORIZONTAL_ALIGN m_horizontal_align;
CSize m_min_size;
int m_controls_total;
int m_padding_top;
int m_padding_bottom;
int m_padding_left;
int m_padding_right;
int m_total_x;
int m_total_y;
public:
CBox();
~CBox();
virtual int Type() const
{
return CLASS_LAYOUT;
}
virtual bool Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2);
virtual bool Pack();
void LayoutStyle(LAYOUT_STYLE style)
{
m_layout_style = style;
}
LAYOUT_STYLE LayoutStyle() const
{
return (m_layout_style);
}
void HorizontalAlign(const HORIZONTAL_ALIGN align)
{
m_horizontal_align = align;
}
HORIZONTAL_ALIGN HorizontalAlign() const
{
return (m_horizontal_align);
}
void VerticalAlign(const VERTICAL_ALIGN align)
{
m_vertical_align = align;
}
VERTICAL_ALIGN VerticalAlign() const
{
return (m_vertical_align);
}
void Padding(const int top, const int bottom, const int left, const int right);
void Padding(const int padding);
void PaddingTop(const int padding)
{
m_padding_top = padding;
}
int PaddingTop() const
{
return (m_padding_top);
}
void PaddingRight(const int padding)
{
m_padding_right = padding;
}
int PaddingRight() const
{
return (m_padding_right);
}
void PaddingBottom(const int padding)
{
m_padding_bottom = padding;
}
int PaddingBottom() const
{
return (m_padding_bottom);
}
void PaddingLeft(const int padding)
{
m_padding_left = padding;
}
int PaddingLeft() const
{
return (m_padding_left);
}
CSize GetMinSize() const
{
CSize sz;
sz.cx = m_min_size.cx + m_padding_left + m_padding_right;
sz.cy = m_min_size.cy + m_padding_top + m_padding_bottom;
return sz;
}
protected:
virtual void CheckControlSize(CWnd *control);
virtual void GetTotalControlsSize(void);
virtual bool GetSpace(int &x_space, int &y_space);
virtual bool Render(void);
virtual void Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::CBox():
m_layout_style(LAYOUT_STYLE_HORIZONTAL),
m_vertical_align(VERTICAL_ALIGN_CENTER),
m_horizontal_align(HORIZONTAL_ALIGN_CENTER),
m_controls_total(0),
m_padding_top(2),
m_padding_bottom(2),
m_padding_left(2),
m_padding_right(2),
m_total_x(0),
m_total_y(0)
{
m_min_size.cx = 0;
m_min_size.cy = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::~CBox()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2)
{
if(!CWndContainer::Create(chart, name, subwin, x1, y1, x2, y2))
return (false);
if(!CreateBack())
return (false);
if(!ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG))
return (false);
if(!ColorBorder(COLOR_BOX_BORDER))
return (false);
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Pack(void)
{
GetTotalControlsSize();
return (Render());
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::CheckControlSize(CWnd *control)
{
bool adjust = false;
CSize size = Size();
CSize control_size = control.Size();
if(control_size.cx > size.cx - (m_padding_left + m_padding_right))
{
control_size.cx = size.cx - (m_padding_left + m_padding_right);
adjust = true;
}
if(control_size.cy > size.cy - (m_padding_top + m_padding_bottom))
{
control_size.cy = size.cy - (m_padding_top + m_padding_bottom);
adjust = true;
}
if(adjust)
control.Size(control_size.cx, control_size.cy);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::GetTotalControlsSize(void)
{
m_total_x = 0;
m_total_y = 0;
m_controls_total = 0;
m_min_size.cx = 0;
m_min_size.cy = 0;
int total = ControlsTotal();
for(int i = 0; i < total; i++)
{
CWnd *control = Control(i);
if(control == NULL) continue;
if(control == &m_background) continue;
CheckControlSize(control);
if(control.Type() == CLASS_LAYOUT)
{
((CBox *)control).GetTotalControlsSize();
}
CSize control_size = control.Size();
if(m_min_size.cx < control_size.cx)
m_min_size.cx = control_size.cx;
if(m_min_size.cy < control_size.cy)
m_min_size.cy = control_size.cy;
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL) m_total_x += control_size.cx;
else m_total_x = MathMax(m_min_size.cx, m_total_x);
if(m_layout_style == LAYOUT_STYLE_VERTICAL) m_total_y += control_size.cy;
else m_total_y = MathMax(m_min_size.cy, m_total_y);
m_controls_total++;
}
CSize size = Size();
if(m_total_x > size.cx && m_layout_style == LAYOUT_STYLE_HORIZONTAL)
{
size.cx = m_total_x;
}
if(m_total_y > size.cy && m_layout_style == LAYOUT_STYLE_VERTICAL) // shrink
{
size.cy = m_total_y;
}
Size(size);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::GetSpace(int &x_space, int &y_space)
{
if(m_controls_total == 0)
return (true);
if(m_controls_total == 1)
{
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
m_horizontal_align = HORIZONTAL_ALIGN_CENTER;
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
m_vertical_align = VERTICAL_ALIGN_CENTER;
}
CSize size = Size();
int x_space_total = 0;
int y_space_total = 0;
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
{
x_space_total = size.cx - (m_total_x + m_padding_left + m_padding_right);
y_space_total = size.cy - (m_min_size.cy + m_padding_top + m_padding_bottom);
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space = x_space_total / (m_controls_total - 1);
else if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER)
x_space = x_space_total / (m_controls_total + 1);
else
x_space = x_space_total / m_controls_total;
if(m_vertical_align == VERTICAL_ALIGN_CENTER || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
y_space = y_space_total / 2;
else
y_space = y_space_total;
}
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
{
x_space_total = size.cx - (m_min_size.cx + m_padding_left + m_padding_right);
y_space_total = size.cy - (m_total_y + m_padding_top + m_padding_bottom);
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space = x_space_total / 2;
else
x_space = x_space_total;
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
y_space = y_space_total / (m_controls_total - 1);
else if(m_vertical_align == VERTICAL_ALIGN_CENTER)
y_space = y_space_total / (m_controls_total + 1);
else
y_space = y_space_total / m_controls_total;
}
else
return (false);
if(x_space < 0) x_space = 0;
if(y_space < 0) y_space = 0;
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space)
{
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
x += x_space + control.Width();
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
y += y_space + control.Height();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Render(void)
{
int x_space = 0, y_space = 0;
if(!GetSpace(x_space, y_space))
return (false);
int x = Left() + m_padding_left +
((m_horizontal_align == HORIZONTAL_ALIGN_LEFT || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES) ? 0 : x_space);
int y = Top() + m_padding_top +
((m_vertical_align == VERTICAL_ALIGN_TOP || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES) ? 0 : y_space);
for(int j = 0; j < ControlsTotal(); j++)
{
CWnd *control = Control(j);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
if(j < ControlsTotal() - 1)
Shift(GetPointer(control), x, y, x_space, y_space);
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::Padding(const int top, const int right, const int bottom, const int left)
{
m_padding_top = top;
m_padding_right = right;
m_padding_bottom = bottom;
m_padding_left = left;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::Padding(const int padding)
{
m_padding_top = padding;
m_padding_right = padding;
m_padding_bottom = padding;
m_padding_left = padding;
}
//+------------------------------------------------------------------+
+66
View File
@@ -0,0 +1,66 @@
//+------------------------------------------------------------------+
//| ComboBoxResizable.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls/ComboBox.mqh>
class ComboBoxResizable: public CComboBox
{
public:
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
virtual bool OnResize(void) override
{
m_edit.Width(Width());
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_COMBO_BUTTON_X_OFF);
int y1 = (Height() - CONTROLS_BUTTON_SIZE) / 2;
m_drop.Move(Left() + x1, Top() + y1);
m_list.Width(Width());
return CWndContainer::OnResize();
}
virtual bool OnClickButton(void) override
{
// this is a hack to trigger resizing of elements in the list
// we need it because standard ListView is incorrectly coded in such a way
// that elements are resized only if vscroll is present
bool vs = m_list.VScrolled();
if(m_drop.Pressed())
{
m_list.VScrolled(true);
}
bool b = CComboBox::OnClickButton();
m_list.VScrolled(vs);
return b;
}
virtual bool Enable(void) override
{
m_edit.Show();
m_drop.Show();
return CComboBox::Enable();
}
virtual bool Disable(void) override
{
m_edit.Hide();
m_drop.Hide();
return CComboBox::Disable();
}
};
#define EXIT_ON_DISABLED \
if(!IsEnabled()) \
{ \
return false; \
}
EVENT_MAP_BEGIN(ComboBoxResizable)
EXIT_ON_DISABLED
ON_EVENT(ON_CLICK, m_drop, OnClickButton)
EVENT_MAP_END(CComboBox)
+153
View File
@@ -0,0 +1,153 @@
//+------------------------------------------------------------------+
//| Grid.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "http://www.mql5.com"
#property strict
#include "Box.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGrid: public CBox
{
protected:
int m_cols;
int m_rows;
int m_hgap;
int m_vgap;
CSize m_cell_size;
public:
CGrid();
CGrid(int rows, int cols, int hgap = 0, int vgap = 0);
~CGrid();
virtual int Type() const
{
return CLASS_LAYOUT;
}
virtual bool Init(int rows, int cols, int hgap = 0, int vgap = 0);
virtual bool Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2);
virtual int Columns()
{
return (m_cols);
}
virtual void Columns(int cols)
{
m_cols = cols;
}
virtual int Rows()
{
return (m_rows);
}
virtual void Rows(int rows)
{
m_rows = rows;
}
virtual int HGap()
{
return (m_hgap);
}
virtual void HGap(int gap)
{
m_hgap = gap;
}
virtual int VGap()
{
return (m_vgap);
}
virtual void VGap(int gap)
{
m_vgap = gap;
}
virtual bool Pack();
protected:
virtual void CheckControlSize(CWnd *control);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CGrid()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CGrid(int rows, int cols, int hgap = 0, int vgap = 0)
{
Init(rows, cols, hgap, vgap);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::~CGrid()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Init(int rows, int cols, int hgap = 0, int vgap = 0)
{
Columns(cols);
Rows(rows);
HGap(hgap);
VGap(vgap);
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Create(const long chart, const string name, const int subwin,
const int x1, const int y1, const int x2, const int y2)
{
return (CBox::Create(chart, name, subwin, x1, y1, x2, y2));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGrid::Pack()
{
CSize size = Size();
m_cell_size.cx = (size.cx - ((m_cols + 1) * m_hgap)) / m_cols;
m_cell_size.cy = (size.cy - ((m_rows + 1) * m_vgap)) / m_rows;
int x = Left(), y = Top();
int cnt = 0;
for(int i = 0; i < ControlsTotal(); i++)
{
CWnd *control = Control(i);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
if(cnt == 0 || Right() - (x + m_cell_size.cx) < m_cell_size.cx + m_hgap)
{
if(cnt == 0)
y += m_vgap;
else
y += m_vgap + m_cell_size.cy;
x = Left() + m_hgap;
}
else
x += m_cell_size.cx + m_hgap;
CheckControlSize(control);
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
cnt++;
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGrid::CheckControlSize(CWnd *control)
{
control.Size(m_cell_size.cx, m_cell_size.cy);
}
//+------------------------------------------------------------------+
+154
View File
@@ -0,0 +1,154 @@
//+------------------------------------------------------------------+
//| GridTk.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "http://www.mql5.com"
#property strict
#include "Grid.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGridConstraints: public CObject
{
protected:
CWnd *m_control;
int m_row;
int m_col;
int m_rowspan;
int m_colspan;
public:
CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1);
~CGridConstraints();
CWnd *Control()
{
return (m_control);
}
int Row()
{
return (m_row);
}
int Column()
{
return (m_col);
}
int RowSpan()
{
return (m_rowspan);
}
int ColSpan()
{
return (m_colspan);
}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints::CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
{
m_control = control;
m_row = MathMax(0, row);
m_col = MathMax(0, column);
m_rowspan = MathMax(1, rowspan);
m_colspan = MathMax(1, colspan);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints::~CGridConstraints()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CGridTk: public CGrid
{
protected:
CArrayObj m_constraints;
public:
CGridTk();
~CGridTk();
bool Grid(CWnd *control, int row, int column, int rowspan, int colspan);
bool Pack();
CGridConstraints *GetGridConstraints(CWnd *control);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridTk::CGridTk(void)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridTk::~CGridTk(void)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGridTk::Grid(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
{
CGridConstraints *constraints = new CGridConstraints(control, row, column, rowspan, colspan);
if(!CheckPointer(constraints))
return (false);
if(!m_constraints.Add(constraints))
return (false);
return (Add(control));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGridTk::Pack()
{
CGrid::Pack();
CSize size = Size();
m_cell_size.cx = (size.cx - (m_cols + 1) * m_hgap) / m_cols;
m_cell_size.cy = (size.cy - (m_rows + 1) * m_vgap) / m_rows;
for(int i = 0; i < ControlsTotal(); i++)
{
int x = Left(), y = Top();
CWnd *control = Control(i);
if(control == NULL)
continue;
if(control == GetPointer(m_background))
continue;
CGridConstraints *constraints = GetGridConstraints(control);
if(constraints == NULL)
continue;
int column = constraints.Column();
int row = constraints.Row();
x += (column * m_cell_size.cx) + ((column + 1) * m_hgap);
y += (row * m_cell_size.cy) + ((row + 1) * m_vgap);
int colspan = constraints.ColSpan();
int rowspan = constraints.RowSpan();
control.Size(colspan * m_cell_size.cx + ((colspan - 1) * m_hgap), rowspan * m_cell_size.cy + ((rowspan - 1) * m_vgap));
control.Move(x, y);
if(control.Type() == CLASS_LAYOUT)
{
CBox *container = control;
container.Pack();
}
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGridConstraints *CGridTk::GetGridConstraints(CWnd *control)
{
for(int i = 0; i < m_constraints.Total(); i++)
{
CGridConstraints *constraints = m_constraints.At(i);
CWnd *ctrl = constraints.Control();
if(ctrl == NULL)
continue;
if(ctrl == control)
return (constraints);
}
return (NULL);
}
//+------------------------------------------------------------------+
+337
View File
@@ -0,0 +1,337 @@
//+------------------------------------------------------------------+
//| MaximizableAppDialog.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#resource "res\\Expand2.bmp"
#resource "res\\size6.bmp"
#resource "res\\size10.bmp"
class MaximizableAppDialog: public CAppDialog
{
protected:
CBmpButton m_button_truemax;
CBmpButton m_button_size;
bool m_maximized;
CRect m_max_rect;
CSize m_size_limit;
bool m_sizing;
// window maximization
virtual bool CreateButtonMinMax(void) override;
virtual void OnClickButtonMinMax(void) override;
virtual void OnClickButtonTrueMax(void);
virtual void OnClickButtonSizeFixMe(void);
virtual void Expand(void);
virtual void Restore(void);
virtual void Minimize(void) override;
// window resizing
bool CreateButtonSize(void);
bool OnDialogSizeStart(void);
virtual bool OnDialogDragStart(void) override;
virtual bool OnDialogDragProcess(void) override;
virtual bool OnDialogDragEnd(void) override;
virtual void SelfAdjustment(const bool minimized = false) = 0;
public:
MaximizableAppDialog(): m_maximized(false), m_sizing(false) {}
virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) override;
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
virtual bool OnChartChange(const long &lparam, const double &dparam, const string &sparam);
void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
void SetSizeLimit(const CSize &limit) { m_size_limit = limit; }
CSize GetSizeLimit() { return m_size_limit; }
};
void MaximizableAppDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_CHART_CHANGE)
{
if(OnChartChange(lparam, dparam, sparam)) return;
}
CAppDialog::ChartEvent(id, lparam, dparam, sparam);
}
EVENT_MAP_BEGIN(MaximizableAppDialog)
ON_EVENT(ON_CLICK, m_button_truemax, OnClickButtonTrueMax)
ON_EVENT(ON_CLICK, m_button_size, OnClickButtonSizeFixMe)
ON_EVENT(ON_DRAG_START, m_button_size, OnDialogSizeStart)
ON_EVENT_PTR(ON_DRAG_PROCESS, m_drag_object, OnDialogDragProcess)
ON_EVENT_PTR(ON_DRAG_END, m_drag_object, OnDialogDragEnd)
EVENT_MAP_END(CAppDialog)
bool MaximizableAppDialog::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
{
// 1 * CONTROLS_BORDER_WIDTH - stays here, because the standard control library minimizes window
// when it's height is 1 pixel smaller than the entire chart height
m_max_rect.SetBound(0,
0,
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
if(!CreateButtonSize()) return false;
m_size_limit.cx = x2 - x1;
m_size_limit.cy = y2 - y1;
if(m_size_limit.cx >= m_max_rect.Width() || m_size_limit.cy >= m_max_rect.Height())
{
m_size_limit.cx = m_min_rect.Width() * 3;
m_size_limit.cy = m_min_rect.Height() * 7;
}
return true;
}
bool MaximizableAppDialog::CreateButtonMinMax(void) override
{
if(!CAppDialog::CreateButtonMinMax()) return false;
// add maximization button
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
int x1 = Width() - off - 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF);
int y1 = off + CONTROLS_DIALOG_BUTTON_OFF;
int x2 = x1 + CONTROLS_BUTTON_SIZE;
int y2 = y1 + CONTROLS_BUTTON_SIZE;
if(!m_button_truemax.Create(m_chart_id, m_name + "TrueMax", m_subwin, x1, y1, x2, y2)) return false;
if(!m_button_truemax.BmpNames("::res\\Expand2.bmp", "::res\\Restore.bmp")) return false;
if(!CWndContainer::Add(m_button_truemax)) return false;
m_button_truemax.Locking(true);
m_button_truemax.Alignment(WND_ALIGN_RIGHT, 0, 0, off + 2 * CONTROLS_BUTTON_SIZE + 2 * CONTROLS_DIALOG_BUTTON_OFF, 0);
CaptionAlignment(WND_ALIGN_WIDTH, off, 0, off + 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF), 0);
return true;
}
bool MaximizableAppDialog::CreateButtonSize(void)
{
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
int x1 = Width() - CONTROLS_BUTTON_SIZE + 1;
int y1 = Height() - CONTROLS_BUTTON_SIZE + 1;
int x2 = x1 + CONTROLS_BUTTON_SIZE - 1;
int y2 = y1 + CONTROLS_BUTTON_SIZE - 1;
if(!m_button_size.Create(m_chart_id, m_name + "Size", m_subwin, x1, y1, x2, y2)) return false;
if(!m_button_size.BmpNames("::res\\size6.bmp", "::res\\size10.bmp")) return false;
if(!CWndContainer::Add(m_button_size)) return false;
m_button_size.Alignment(WND_ALIGN_RIGHT|WND_ALIGN_BOTTOM, 0, 0, 0, 0);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
return true;
}
void MaximizableAppDialog::OnClickButtonTrueMax(void)
{
if(m_button_truemax.Pressed())
Expand();
else
Restore();
SubwinOff();
}
// This is a hack. It's required because in minimized state sizing button somehow "overlaps"
// the close button and intercepts clicks on it (which prevents exit from minimized app).
// This happens despite the fact that the sizing button is hidden, disabled and assigned
// with minimal Z-order (checked out, then removed).
// Looks like a bug in the standard control library, specifically:
// In CWnd::OnMouseEvent there must be a line:
//
// if(!IS_ENABLED || !IS_VISIBLE) return false;
//
// but it's not there, so invisible, disabled and even background objects are processed
// in the same manner as all other objects. Specifically in CWndContainer::OnMouseEvent
// there is a reverse loop through all objects (it does _not_ respect Z-order anyhow).
void MaximizableAppDialog::OnClickButtonSizeFixMe(void)
{
if(m_minimized)
{
Destroy();
}
}
void MaximizableAppDialog::Expand(void)
{
m_maximized = true;
m_minimized = false;
m_button_minmax.Pressed(false);
Rebound(m_max_rect);
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
if(!m_panel_flag)
{
m_caption.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
ClientAreaVisible(true);
SelfAdjustment();
}
//+------------------------------------------------------------------+
//| Restore dialog window |
//+------------------------------------------------------------------+
void MaximizableAppDialog::Restore(void)
{
m_maximized = false;
m_minimized = false;
m_button_minmax.Pressed(false);
m_button_size.Show();
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
CAppDialog::Maximize();
if(!m_panel_flag)
{
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
SelfAdjustment();
}
void MaximizableAppDialog::Minimize()
{
CAppDialog::Minimize();
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
bool MaximizableAppDialog::OnChartChange(const long &lparam, const double &dparam, const string &sparam)
{
m_max_rect.SetBound(0, 0,
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
if(m_maximized)
{
if(m_rect.Width() != m_max_rect.Width() || m_rect.Height() != m_max_rect.Height())
{
Rebound(m_max_rect);
SelfAdjustment();
m_chart.Redraw();
}
return true;
}
return false;
}
void MaximizableAppDialog::OnClickButtonMinMax(void)
{
CAppDialog::OnClickButtonMinMax();
m_button_truemax.Pressed(false);
m_maximized = false;
if(m_minimized)
{
m_button_size.Hide();
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
}
else
{
m_button_size.Show();
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
if(!m_panel_flag)
{
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
}
SelfAdjustment(m_minimized);
}
bool MaximizableAppDialog::OnDialogSizeStart(void)
{
if(m_drag_object == NULL)
{
m_drag_object = new CDragWnd;
if(m_drag_object == NULL) return false;
}
int x1 = m_button_size.Left() - CONTROLS_DRAG_SPACING;
int y1 = m_button_size.Top() - CONTROLS_DRAG_SPACING;
int x2 = m_button_size.Right() + CONTROLS_DRAG_SPACING;
int y2 = m_button_size.Bottom() + CONTROLS_DRAG_SPACING;
m_drag_object.Create(m_chart_id, "", m_subwin, x1, y1, x2, y2);
m_drag_object.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
CChart chart;
chart.Attach(m_chart_id);
m_drag_object.Limits(-CONTROLS_DRAG_SPACING, -CONTROLS_DRAG_SPACING,
chart.WidthInPixels() + CONTROLS_DRAG_SPACING,
chart.HeightInPixels(m_subwin) + CONTROLS_DRAG_SPACING);
chart.Detach();
m_drag_object.MouseX(m_button_size.MouseX());
m_drag_object.MouseY(m_button_size.MouseY());
m_drag_object.MouseFlags(m_button_size.MouseFlags());
m_sizing = true;
return true;
}
bool MaximizableAppDialog::OnDialogDragStart(void)
{
if(m_maximized) return false;
return CAppDialog::OnDialogDragStart();
}
//+------------------------------------------------------------------+
//| Continue dragging the dialog box |
//+------------------------------------------------------------------+
bool MaximizableAppDialog::OnDialogDragProcess(void)
{
if(!m_sizing) return CDialog::OnDialogDragProcess();
if(m_drag_object == NULL) return false;
int x = m_drag_object.Right() - Right() - CONTROLS_DRAG_SPACING;
int y = m_drag_object.Bottom() - Bottom() - CONTROLS_DRAG_SPACING;
// resize dialog
CRect r = Rect();
r.right += x;
r.bottom += y;
if(r.Width() < m_size_limit.cx) r.right = r.left + m_size_limit.cx;
if(r.Height() < m_size_limit.cy) r.bottom = r.top + m_size_limit.cy;
Rebound(r);
SelfAdjustment();
return true;
}
//+------------------------------------------------------------------+
//| End dragging the dialog box |
//+------------------------------------------------------------------+
bool MaximizableAppDialog::OnDialogDragEnd(void)
{
if(!m_sizing) return CDialog::OnDialogDragEnd();
if(m_drag_object != NULL)
{
m_button_size.MouseFlags(m_drag_object.MouseFlags());
delete m_drag_object;
m_drag_object = NULL;
}
m_norm_rect.SetBound(m_rect);
m_sizing = false;
SelfAdjustment();
return true;
}
+27
View File
@@ -0,0 +1,27 @@
//+------------------------------------------------------------------+
//| SpinEditResizable.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#include <Controls/SpinEdit.mqh>
class SpinEditResizable: public CSpinEdit
{
public:
virtual bool OnResize(void) override
{
m_edit.Width(Width());
m_edit.Height(Height());
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
int y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2;
m_inc.Move(Left() + x1, Top() + y1);
x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2 + CONTROLS_SPIN_BUTTON_SIZE;
m_dec.Move(Left() + x1, Top() + y1);
return CWndContainer::OnResize();
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long
+112
View File
@@ -0,0 +1,112 @@
//+------------------------------------------------------------------+
//| CSVReader.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/ru/articles/5913 |
//+------------------------------------------------------------------+
#include <Marketeer/IndexMap.mqh>
#include <Marketeer/GroupSettings.mqh>
input GroupSettings SCV_Settings; // C S V S E T T I N G S
input string CSVDelimiter = ";" /*mql5 signals use ';' instead of ','*/; // · Delimiter
class CSVConverter
{
private:
class File
{
int file;
public:
File(const string name, const int flags, const short delimiter)
{
file = FileOpen(name, flags, delimiter, CP_UTF8);
}
File(const string name, const int flags)
{
file = FileOpen(name, flags);
}
bool isOpened()
{
return (file != INVALID_HANDLE);
}
int handle()
{
return file;
}
~File()
{
if(file != INVALID_HANDLE) FileClose(file);
}
};
public:
static IndexMap *ReadCSV(const string inputFileName)
{
// history.csv - 13 columns, positions.csv - 10 columns
int columns = StringFind(inputFileName, ".history.csv") > 0 ? 13 : (StringFind(inputFileName, ".positions.csv") > 0 ? 10 : 0);
if(columns == 0)
{
Print("Supported files: *.history.csv and .positions.csv");
return NULL;
}
Print("Reading csv-file ", inputFileName);
uchar delimiter = (uchar)CSVDelimiter[0];
File f(inputFileName, FILE_READ|FILE_TXT|FILE_ANSI|FILE_SHARE_READ|FILE_SHARE_WRITE, delimiter);
if(!f.isOpened())
{
Alert("Can't read file " + inputFileName);
return NULL;
}
int file = f.handle();
bool headerLine = true;
IndexMap *data = new IndexMap();
string headers[];
uint count = 0;
while(!FileIsEnding(file))
{
string stLine = "";
string stParts[];
stLine = FileReadString(file);
int nParts = StringSplit(stLine, delimiter, stParts);
if(nParts != columns)
{
Print("File " + inputFileName + " contains " + (string)nParts + " columns (" + (string)(columns) + "+ required)");
Print("Line: ", stLine);
return NULL;
}
if(headerLine)
{
headerLine = false;
ArrayCopy(headers, stParts);
continue;
}
IndexMap *row = new IndexMap();
for(int i = 0; i < nParts; i++)
{
row.setValue((string)i + "." + headers[i], stParts[i]);
}
data.add((string)count, row);
++count;
}
return data;
}
};
+11
View File
@@ -0,0 +1,11 @@
#define CSV_COLUMN_TIME1 0
#define CSV_COLUMN_TYPE 1
#define CSV_COLUMN_VOLUME 2
#define CSV_COLUMN_SYMBOL 3
#define CSV_COLUMN_PRICE1 4
#define CSV_COLUMN_TIME2 5 // 7
#define CSV_COLUMN_PRICE2 6 // 8
#define CSV_COLUMN_COMMISSION 7 // 9
#define CSV_COLUMN_SWAP 8 // 10
#define CSV_COLUMN_PROFIT 9 // 11
#define CSV_COLUMN_COMMENT 12
+24
View File
@@ -0,0 +1,24 @@
template<typename T1,typename T2>
class Converter
{
private:
union _L2D
{
T1 L;
T2 D;
}
L2D;
public:
T2 operator[](const T1 L)
{
L2D.L = L;
return L2D.D;
}
T1 operator[](const T2 D)
{
L2D.D = D;
return L2D.L;
}
};
+1
View File
@@ -0,0 +1 @@
enum GroupSettings {};
+15
View File
@@ -0,0 +1,15 @@
#define COLUMNS_COUNT 13
#define COLUMN_TIME 0
#define COLUMN_DEAL 1
#define COLUMN_SYMBOL 2
#define COLUMN_TYPE 3
#define COLUMN_DIRECTION 4
#define COLUMN_VOLUME 5
#define COLUMN_PRICE 6
#define COLUMN_ORDER 7
#define COLUMN_COMISSION 8
#define COLUMN_SWAP 9
#define COLUMN_PROFIT 10
#define COLUMN_BALANCE 11
#define COLUMN_COMMENT 12
+401
View File
@@ -0,0 +1,401 @@
//+------------------------------------------------------------------+
//| IndexMapT.mqh |
//| https://www.mql5.com/ru/articles/5706/ |
//+------------------------------------------------------------------+
#define EMPTY ((int)EMPTY_VALUE)
#ifdef HASHMAP_WARNING
#define NULL_PLACEHOLDER "n/a"
#else
#define NULL_PLACEHOLDER ""
#endif
class Object
{
public:
virtual string asString() const
{
return(__FUNCSIG__);
}
virtual string asCSVString() const
{
return(__FUNCSIG__);
}
virtual string getTypeName() const = 0;
};
/**
* Base container for indexed map. Can contain plain types and pointers.
*/
class Container: public Object
{
protected:
enum datatype
{
null,
s,
d,
t,
i,
o,
u
};
datatype type;
public:
datatype getType() const
{
return type;
}
// helper method to access plain type values from the base class
template<typename R>
R get() const;
// helper method to access object pointers from the base class
template<typename R>
Object *getObject() const;
};
/**
* Variable type data for indexed map; plain types only.
*/
template<typename T>
class TypeContainer: public Container
{
private:
int digits;
int flags;
protected:
T v;
TypeContainer()
{
digits = _Digits;
flags = TIME_DATE | TIME_MINUTES;
}
public:
TypeContainer(T _v, int precision = INT_MIN, int timeflags = TIME_DATE | TIME_MINUTES)
{
v = _v;
digits = precision == INT_MIN ? _Digits : precision;
flags = timeflags;
if(typename(T) == "string")
{
type = datatype::s;
}
else
if(typename(T) == "double" || typename(T) == "float")
{
type = datatype::d;
}
else
if(typename(T) == "datetime")
{
type = datatype::t;
}
else
if(typename(T) == "char" || typename(T) == "short" || typename(T) == "int" || typename(T) == "long")
{
type = datatype::i;
}
else
{
type = datatype::u;
}
}
virtual T getValue() const
{
return v;
}
// represent data as a string, convert if necessary
virtual string asString() const
{
switch(type)
{
case datatype::s: return (string)v;
case datatype::d: return DoubleToString((double)v, digits);
case datatype::t: return TimeToString((datetime)v, flags);
case datatype::i: return IntegerToString((long)v);
default: return (string)v;
}
}
virtual string asCSVString() const
{
return asString();
}
virtual string getTypeName() const override
{
return typename(this);
}
};
/**
* Object pointer types for indexed map.
* Pointer will be deleted automatically.
*/
template<typename T>
class ObjectContainer: public Container
{
protected:
Object *o;
public:
ObjectContainer(T _v)
{
o = _v;
type = datatype::o;
}
~ObjectContainer()
{
if(CheckPointer(o) == POINTER_DYNAMIC)
{
delete(o);
}
}
T getObject() const
{
return o;
}
virtual string asString() const override
{
return o.asString();
}
virtual string asCSVString() const
{
return o.asCSVString();
}
virtual string getTypeName() const override
{
return typename(this);
}
};
template<typename R>
R Container::get() const
{
const TypeContainer<R> *ptr = dynamic_cast<const TypeContainer<R> *>(&this);
if(ptr != NULL) return (R)ptr.getValue();
return (R)NULL;
}
template<typename R> // R is supposed to be an object pointer
Object *Container::getObject() const
{
const ObjectContainer<R> *obj = dynamic_cast<const ObjectContainer<R> *>(&this);
if(obj != NULL) return obj.getObject();
return NULL;
}
/**
* Indexed map with random access by key and index.
*/
template<typename T>
class IndexMapT: public Container // Object
{
private:
T keys[];
Container *values[];
int count;
string id;
uchar delimiter;
public:
IndexMapT(): count(0), delimiter(',') {}
IndexMapT(string obj): id (obj), count(0), delimiter(',') {}
IndexMapT(uchar d): count(0), delimiter(d) {}
~IndexMapT()
{
reset();
}
virtual string getTypeName() const override
{
return typename(this);
}
void add(const T key, Container *value)
{
ArrayResize(keys, count + 1);
ArrayResize(values, count + 1);
keys[count] = key;
values[count] = value;
count++;
}
void reset()
{
for(int i = 0; i < count; i++)
{
if(CheckPointer(values[i]) == POINTER_DYNAMIC)
{
delete(values[i]);
}
}
ArrayResize(keys, 0);
ArrayResize(values, 0);
count = 0;
}
bool isKeyExisting(const T key) const
{
return (getIndex(key) != EMPTY);
}
int getIndex(const T key) const
{
for(int i = 0; i < count; i++)
{
if(keys[i] == key) return(i);
}
#ifdef HASHMAP_VERBOSE
Print(__FUNCSIG__, ": no key=", key);
#endif
return EMPTY;
}
Container *operator[](const int index) const
{
if(index < 0 || index >= count)
{
#ifdef HASHMAP_VERBOSE
Print(__FUNCSIG__, ": index=", index);
#endif
return(NULL);
}
return(GetPointer(values[index]));
}
Container *operator[](const T key) const
{
for(int i = 0; i < count; i++)
{
if(keys[i] == key) return(GetPointer(values[i]));
}
#ifdef HASHMAP_VERBOSE
Print(__FUNCSIG__, ": no key=", key);
#endif
return(NULL);
}
T getKey(const int index) const
{
if(index < 0 || index >= count)
{
Print(__FUNCSIG__, ": index=", index);
}
return(keys[index]);
}
template<typename R>
void setValue(const T key, R value)
{
// NB: implementation specific
// in HTML every attribute can occur only once in a tag,
// all successive assignments are ignored
if(!isKeyExisting(key))
{
set(key, new TypeContainer<R>(value));
}
}
void set(const T key, Container *value)
{
int index = getIndex(key);
if(index != EMPTY)
{
#ifdef HASHMAP_WARNING
Print(__FUNCSIG__, ": overwritten key=", key, ", old value=", (values[index] != NULL ? values[index].asString() : "null"), ", new value=", (value != NULL ? value.asString() : "null"));
#endif
values[index] = value;
}
else
{
add(key, value);
}
}
void set(const T key)
{
int index = getIndex(key);
if(index == EMPTY)
{
add(key, NULL);
}
}
int getSize() const
{
return(count);
}
virtual string asString() const
{
string result = "";
for(int i = 0; i < count; i++)
{
result += (string)keys[i] + "=" + (CheckPointer(values[i]) == POINTER_INVALID ? NULL_PLACEHOLDER : values[i].asString()) + ";";
}
return result;
}
virtual string asCSVString() const
{
string result = "";
string d = CharToString(delimiter);
for(int i = 0; i < count; i++)
{
string v = NULL_PLACEHOLDER;
if(CheckPointer(values[i]) != POINTER_INVALID)
{
v = values[i].asCSVString();
StringReplace(v, d, "");
}
if(i < count - 1)
{
result += v + d;
}
else
{
result += v;
}
}
return result;
}
};
class IndexMap: public IndexMapT<string>
{
public:
IndexMap(): IndexMapT() {}
IndexMap(string obj): IndexMapT(obj) {}
IndexMap(uchar d): IndexMapT(d) {}
string get(const string key)
{
Container *c = this[key];
if(c == NULL) return NULL;
return c.get<string>();
}
};
+195
View File
@@ -0,0 +1,195 @@
//+------------------------------------------------------------------+
//| RubbArray.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//| https://www.mql5.com/ru/articles/5638 |
//+------------------------------------------------------------------+
template <typename T>
interface Clonable
{
T clone();
};
template <typename T>
class BaseArray
{
protected:
T data[];
public:
virtual ~BaseArray()
{
clear();
}
virtual void clear()
{
ArrayResize(data, 0);
}
T operator[](int i) const
{
return get(i);
}
T get(int i) const
{
if(i < 0 || i >= ArraySize(data))
{
Print("Array size=", ArraySize(data), ", index=", i);
return NULL;
}
return data[i];
}
T top() const
{
if(ArraySize(data) == 0)
{
Print("Array size=0");
return NULL;
}
return data[ArraySize(data) - 1];
}
T peek() const
{
return top();
}
BaseArray *add(T d)
{
int n = ArraySize(data);
ArrayResize(data, n + 1);
data[n] = d;
return &this;
}
BaseArray *operator<<(T d)
{
return add(d);
}
BaseArray *operator<<(const BaseArray<T> *x)
{
for(int i = 0; i < x.size(); i++)
{
Clonable<T> *clone = dynamic_cast<Clonable<T> *>(x[i]);
if(clone != NULL)
{
add(clone.clone());
}
else
{
add(x[i]);
}
}
return &this;
}
BaseArray *push(T d)
{
return add(d);
}
void operator=(const BaseArray &d)
{
int i, n = d.size();
ArrayResize(data, n);
for(i = 0; i < n; i++)
{
data[i] = d[i];
}
}
T operator>>(int i)
{
T d = this[i];
if(d == NULL) return NULL;
int n = ArraySize(data) - 1;
if(i < n)
{
ArrayCopy(data, data, i, i + 1);
}
ArrayResize(data, n);
return d;
}
T pop()
{
int _size = ArraySize(data) - 1;
T d = this[_size];
ArrayResize(data, _size);
return d;
}
int size() const
{
return ArraySize(data);
}
string toString() const
{
static string formats[4][2] = {{"double", "%f"}, {"long", "%i"}, {"string", "%s"}, {"int", "%i"}};
string fmt = "%x";
for(int k = 0; k < ArrayRange(formats, 0); k++)
{
if(typename(T) == formats[k][0])
{
fmt = formats[k][1];
break;
}
}
int i, n = ArraySize(data);
string s;
for(i = 0; i < n; i++)
{
s += StringFormat(fmt, data[i]) + ",";
}
return (s);
}
};
template <typename T>
class RubbArray: public BaseArray<T>
{
public:
RubbArray()
{
}
~RubbArray()
{
clear();
}
virtual void clear() override
{
int i, n = ArraySize(data);
for(i = 0; i < n; i++)
{
if(CheckPointer(data[i]) == POINTER_DYNAMIC) delete data[i];
}
ArrayResize(data, 0);
}
T replace(const int i, T v)
{
int n = ArraySize(data);
if(i < n)
{
if(CheckPointer(data[i]) == POINTER_DYNAMIC) delete data[i];
data[i] = v;
}
return v;
}
};
#define List RubbArray
#define Stack RubbArray
+43
View File
@@ -0,0 +1,43 @@
//#define DATETIME_PLACEHOLDER ((datetime)0xFFFFFFFFFFFFFFFF)
class DateTime
{
private:
MqlDateTime mdtstruct;
public:
DateTime(){TimeToStruct(0, mdtstruct);}
DateTime *assign(datetime dt) {TimeToStruct(dt, mdtstruct); return &this;}
int __TimeDayOfWeek() {return mdtstruct.day_of_week;}
int __TimeDayOfYear() {return mdtstruct.day_of_year;}
int __TimeYear() {return mdtstruct.year;}
int __TimeMonth() {return mdtstruct.mon;}
int __TimeDay() {return mdtstruct.day;}
int __TimeHour() {return mdtstruct.hour;}
int __TimeMinute() {return mdtstruct.min;}
int __TimeSeconds() {return mdtstruct.sec;}
};
DateTime _DateTime;
#define TimeDayOfWeek(T) _DateTime.assign(T).__TimeDayOfWeek()
#define TimeYear(T) _DateTime.assign(T).__TimeYear()
#define TimeMonth(T) _DateTime.assign(T).__TimeMonth()
#define TimeDay(T) _DateTime.assign(T).__TimeDay()
#define TimeHour(T) _DateTime.assign(T).__TimeHour()
#define TimeMinute(T) _DateTime.assign(T).__TimeMinute()
#define TimeSeconds(T) _DateTime.assign(T).__TimeSeconds()
#define _TimeYear _DateTime.__TimeYear
#define _TimeMonth _DateTime.__TimeMonth
#define _TimeDay _DateTime.__TimeDay
#define _TimeHour _DateTime.__TimeHour
#define _TimeMinute _DateTime.__TimeMinute
#define _TimeSeconds _DateTime.__TimeSeconds
#define Year _DateTime.assign(TimeCurrent()).__TimeYear
#define Month _DateTime.assign(TimeCurrent()).__TimeMonth
#define Day _DateTime.assign(TimeCurrent()).__TimeDay
#define Hour _DateTime.assign(TimeCurrent()).__TimeHour
#define Minute _DateTime.assign(TimeCurrent()).__TimeMinute
#define Seconds _DateTime.assign(TimeCurrent()).__TimeSeconds
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
// header
"isindex",
"base",
"meta",
"link",
"nextid",
"range",
// elsewhere
"img",
"br",
"hr",
"frame",
"wbr",
"basefont",
"spacer",
"area",
"param",
"keygen",
"col",
"limittext"
+151
View File
@@ -0,0 +1,151 @@
//+------------------------------------------------------------------+
//| CSVcube.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//| Online Analytical Processing of trading hypercubes |
//| https://www.mql5.com/ru/articles/6602 |
//| https://www.mql5.com/ru/articles/6603 |
//+------------------------------------------------------------------+
#include <Marketeer/CSVReader.mqh>
#include <Marketeer/CSVcolumns.mqh>
template<typename T>
class CSVTradeRecord: public T // TradeRecord
{
public:
CSVTradeRecord(const double balance, const string symbol, const IndexMap *row)
{
const int add = row.getSize() == 13 ? 2 : 0;
set(FIELD_NUMBER, counter);
set(FIELD_TICKET, counter++);
set(FIELD_SYMBOL, symbols.add(symbol));
string t = row[CSV_COLUMN_TYPE].get<string>();
StringToLower(t);
const int _type = t == "buy" ? +1 : (t == "sell" ? -1 : 0);
set(FIELD_TYPE, _type == +1 ? OP_BUY : (_type == -1 ? OP_SELL : OP_BALANCE));
datetime time1 = StringToTime(row[CSV_COLUMN_TIME1].get<string>()) + TimeShift;
datetime time2 = StringToTime(row[CSV_COLUMN_TIME2 + add].get<string>()) + TimeShift;
set(FIELD_DATETIME1, time1);
set(FIELD_DATETIME2, time2);
set(FIELD_DURATION, time2 - time1);
double price1 = StringToDouble(row[CSV_COLUMN_PRICE1].get<string>());
double price2 = StringToDouble(row[CSV_COLUMN_PRICE2 + add].get<string>());
set(FIELD_PRICE1, price1);
set(FIELD_PRICE2, price2);
set(FIELD_MAGIC, 0);
magics.add(0);
set(FIELD_LOT, StringToDouble(row[CSV_COLUMN_VOLUME].get<string>()));
t = row[CSV_COLUMN_PROFIT + add].get<string>();
StringReplace(t, " ", "");
const double profit = StringToDouble(t);
set(FIELD_PROFIT_AMOUNT, profit);
set(FIELD_PROFIT_PERCENT, (profit / balance));
set(FIELD_PROFIT_POINT, (_type * (price2 - price1) / SymbolInfoDouble(symbol, SYMBOL_POINT)));
set(FIELD_COMMISSION, StringToDouble(row[CSV_COLUMN_COMMISSION + add].get<string>()));
set(FIELD_SWAP, StringToDouble(row[CSV_COLUMN_SWAP + add].get<string>()));
fillCustomFields();
}
};
template<typename T>
class CSVReportAdapter: public DataAdapter
{
private:
RubbArray<CSVTradeRecord<T> *> trades;
int cursor;
int size;
double balance;
IndexMap *data;
void reset()
{
size = 0;
cursor = 0;
balance = 0;
if(CheckPointer(data) == POINTER_DYNAMIC) delete data;
}
public:
CSVReportAdapter()
{
reset();
TradeRecord::reset();
}
~CSVReportAdapter()
{
if(CheckPointer(data) == POINTER_DYNAMIC) delete data;
}
bool load(const string file)
{
reset();
data = CSVConverter::ReadCSV(file);
if(data != NULL)
{
size = generate();
Print(data.getSize(), " records transferred to ", size, " trades");
}
return data != NULL;
}
virtual int reservedSize() override
{
return size;
}
virtual Record *getNext() override
{
if(cursor < size)
{
return trades[cursor++];
}
return NULL;
}
protected:
int generate()
{
int count = 0;
balance = 0;
for(int i = data.getSize() - 1; i >= 0; --i) // csv-files have reverse chronological order
{
IndexMap *row = data[i];
const int add = row.getSize() == 13 ? 2 : 0;
string s = row[CSV_COLUMN_SYMBOL].get<string>();
StringTrimLeft(s);
if(StringLen(s) > 0)
{
if(balance == 0)
{
Print("Zero balance, 10000 emulated");
balance = 10000;
}
string real = TradeRecord::realsymbol(s);
if(real == NULL) continue;
trades << new CSVTradeRecord<T>(balance, real, row);
++count;
}
else
{
string type = row[CSV_COLUMN_TYPE].get<string>();
StringToLower(type);
if(type == "balance")
{
string t = row[CSV_COLUMN_PROFIT + add].get<string>();
StringReplace(t, " ", "");
balance += StringToDouble(t);
}
}
}
return count;
}
};
+350
View File
@@ -0,0 +1,350 @@
//+------------------------------------------------------------------+
//| HTMLcube.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//| Online Analytical Processing of trading hypercubes |
//| https://www.mql5.com/ru/articles/6602 |
//| https://www.mql5.com/ru/articles/6603 |
//+------------------------------------------------------------------+
#include <Marketeer/GroupSettings.mqh>
input GroupSettings Common_Settings; // G E N E R A L S E T T I N G S
input string ReportFile = ""; // · ReportFile
input string Prefix = ""; // · Prefix
input string Suffix = ""; // · Suffix
input int TimeShift = 0; // · TimeShift
#include <Marketeer/WebDataExtractor.mqh>
#include <Marketeer/RubbArray.mqh>
#include <Marketeer/HTMLcolumns.mqh>
template<typename T>
class HTMLTradeRecord: public T // TradeRecord
{
public:
HTMLTradeRecord(
const double balance,
const long ticket,
const string symbol,
const int type,
const datetime time1,
const datetime time2,
const double price1,
const double price2,
const double lot,
const double profit,
const double commission,
const double swap)
{
set(FIELD_NUMBER, counter++);
set(FIELD_TICKET, ticket);
set(FIELD_SYMBOL, symbols.add(symbol));
set(FIELD_TYPE, type);
set(FIELD_DATETIME1, time1);
set(FIELD_DATETIME2, time2);
set(FIELD_DURATION, time2 - time1);
set(FIELD_PRICE1, (float)price1);
set(FIELD_PRICE2, (float)price2);
set(FIELD_MAGIC, 0);
magics.add(0);
set(FIELD_LOT, (float)lot);
set(FIELD_PROFIT_AMOUNT, (float)profit);
set(FIELD_PROFIT_PERCENT, (float)(profit / balance));
set(FIELD_PROFIT_POINT, (float)((type == OP_BUY ? +1 : -1) * (price2 - price1) / SymbolInfoDouble(symbol, SYMBOL_POINT)));
set(FIELD_COMMISSION, (float)commission);
set(FIELD_SWAP, (float)swap);
fillCustomFields(); // calls implementation from T
}
};
template<typename T>
class HTMLReportAdapter: public DataAdapter
{
private:
class Deal // if MQL5 could respect private access specifier for classes,
{ // Trades will be unreachable from outer world, so it would be fine to have
public: // fields made public for direct access from Processor only
datetime time;
double price;
int type; // +1 - buy, -1 - sell
int direction; // +1 - in, -1 - out, 0 - in/out
double volume;
double profit;
long deal;
long order;
string comment;
string symbol;
double commission;
double swap;
public:
Deal(const IndexMap *row) // this is MT5 deal
{
time = StringToTime(row[COLUMN_TIME].get<string>()) + TimeShift;
price = StringToDouble(row[COLUMN_PRICE].get<string>());
string t = row[COLUMN_TYPE].get<string>();
type = t == "buy" ? +1 : (t == "sell" ? -1 : 0);
t = row[COLUMN_DIRECTION].get<string>();
direction = 0;
if(StringFind(t, "in") > -1) ++direction;
if(StringFind(t, "out") > -1) --direction;
volume = StringToDouble(row[COLUMN_VOLUME].get<string>());
t = row[COLUMN_PROFIT].get<string>();
StringReplace(t, " ", "");
profit = StringToDouble(t);
deal = StringToInteger(row[COLUMN_DEAL].get<string>());
order = StringToInteger(row[COLUMN_ORDER].get<string>());
comment = row[COLUMN_COMMENT].get<string>();
symbol = row[COLUMN_SYMBOL].get<string>();
commission = StringToDouble(row[COLUMN_COMISSION].get<string>());
swap = StringToDouble(row[COLUMN_SWAP].get<string>());
}
bool isIn() const
{
return direction >= 0;
}
bool isOut() const
{
return direction <= 0;
}
bool isOpposite(const Deal *t) const
{
return type * t.type < 0;
}
bool isActive() const
{
return volume > 0;
}
int op_type() const
{
if(type == +1) return OP_BUY;
else if(type == -1) return OP_SELL;
return OP_BALANCE;
}
};
RubbArray<Deal *> array;
RubbArray<Deal *> queue;
int size;
int cursor;
double balance;
IndexMap *data;
RubbArray<HTMLTradeRecord<T> *> trades;
protected:
int generate()
{
array.clear();
balance = 0;
for(int i = 0; i < data.getSize(); ++i)
{
IndexMap *row = data[i];
if(CheckPointer(row) == POINTER_INVALID || row.getSize() != COLUMNS_COUNT) return 0; // something is broken
string s = row[COLUMN_SYMBOL].get<string>();
StringTrimLeft(s);
if(StringLen(s) > 0)
{
array << new Deal(row);
}
else if(row[COLUMN_TYPE].get<string>() == "balance")
{
string t = row[COLUMN_PROFIT].get<string>();
StringReplace(t, " ", "");
balance += StringToDouble(t);
}
}
if(balance == 0) balance = 10000; // default, if missing
int count = 0;
// abstract:
// if direction <= 0
// collect all Trades from the queue which have direction >= 0 and opposite type
// if this volume is greater than collected volumes
// reduce volume in this Deal by the total volume of collected Trades
// else if collected volumes are greater than this volume
// reduce volume in matched Trades in a loop until all volume of this Deal is exhausted
// create object-lines from all affected Trades to this Deal
// 'delete' all affected Trades with zero volume from queue
// if volume == 0, 'delete' this Deal (disactivate)
// if direction >= 0 push the new Deal object to the queue
for(int i = 0; i < array.size(); ++i)
{
Deal *current = array[i];
if(!current.isActive()) continue;
string real = TradeRecord::realsymbol(current.symbol);
if(real == NULL) continue;
if(current.isOut())
{
// first try to find exact match
for(int j = 0; j < queue.size(); ++j)
{
if(queue[j].isIn() && queue[j].isOpposite(current) && queue[j].volume == current.volume && queue[j].symbol == current.symbol)
{
trades << new HTMLTradeRecord<T>(
balance,
queue[j].deal,
real, // current.symbol,
queue[j].op_type(),
queue[j].time,
current.time,
queue[j].price,
current.price,
current.volume,
current.profit,
queue[j].commission + current.commission,
current.swap);
balance += current.profit;
current.volume = 0;
queue >> j; // remove from queue
++count;
break;
}
}
if(!current.isActive()) continue;
// second try to perform partial close
for(int j = 0; j < queue.size(); ++j)
{
if(queue[j].isIn() && queue[j].isOpposite(current) && queue[j].symbol == current.symbol)
{
if(current.volume >= queue[j].volume)
{
double fraction = queue[j].volume / current.volume;
trades << new HTMLTradeRecord<T>(
balance,
queue[j].deal,
real, // current.symbol,
queue[j].op_type(),
queue[j].time,
current.time,
queue[j].price,
current.price,
queue[j].volume,
current.profit * fraction,
queue[j].commission + current.commission * fraction,
current.swap * fraction);
balance += current.profit * fraction;
current.volume -= queue[j].volume;
queue[j].volume = 0;
++count;
}
else
{
double fraction = current.volume / queue[j].volume;
trades << new HTMLTradeRecord<T>(
balance,
queue[j].deal,
real, // current.symbol,
queue[j].op_type(),
queue[j].time,
current.time,
queue[j].price,
current.price,
current.volume,
queue[j].profit * fraction, // should be 0
queue[j].commission * fraction + current.commission,
current.swap);
balance += queue[j].profit * fraction;
queue[j].volume -= current.volume;
current.volume = 0;
++count;
break;
}
}
}
// purge all inactive from queue
for(int j = queue.size() - 1; j >= 0; --j)
{
if(!queue[j].isActive())
{
queue >> j;
}
}
}
if(current.isActive()) // is _still_ active
{
if(current.isIn())
{
queue << current;
}
}
}
return count;
}
void reset()
{
cursor = 0;
balance = 0;
if(CheckPointer(data) == POINTER_DYNAMIC) delete data;
}
public:
HTMLReportAdapter()
{
reset();
TradeRecord::reset();
}
~HTMLReportAdapter()
{
if(CheckPointer(data) == POINTER_DYNAMIC) delete data;
((BaseArray<Deal *> *)&queue).clear();
}
bool load(const string file)
{
reset();
data = HTMLConverter::convertReport2Map(file, true);
if(data != NULL)
{
size = generate();
Print(data.getSize(), " deals transferred to ", size, " trades");
}
return data != NULL;
}
virtual int reservedSize() override
{
return size;
}
virtual Record *getNext() override
{
if(cursor < size)
{
return trades[cursor++];
}
return NULL;
}
};
+241
View File
@@ -0,0 +1,241 @@
//+------------------------------------------------------------------+
//| OLAPcore.mqh |
//| Copyright © 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//| Online Analytical Processing of trading hypercubes |
//| https://www.mql5.com/ru/articles/6602 |
//| https://www.mql5.com/ru/articles/6603 |
//+------------------------------------------------------------------+
#include <OLAP/OLAPcube.mqh>
#include <OLAP/HTMLcube.mqh>
#include <OLAP/CSVcube.mqh>
class DaysRangeSelector: public DateTimeSelector<TRADE_RECORD_FIELDS>
{
protected:
int granulatity;
public:
DaysRangeSelector(const int n): DateTimeSelector<TRADE_RECORD_FIELDS>(FIELD_DURATION, 7), granulatity(n)
{
_typename = typename(this);
}
virtual int getRange() const
{
return granulatity;
}
virtual bool select(const Record *r, int &index) const
{
double d = r.get(selector);
int days = (int)(d / (60 * 60 * 24));
index = MathMin(days, granulatity - 1);
return true;
}
virtual string getLabel(const int index) const
{
return index < granulatity - 1 ? ((index < 10 ? " ": "") + (string)index + "D") : ((string)index + "D+");
}
};
class OLAPWrapper
{
protected:
Selector<TRADE_RECORD_FIELDS> *createSelector(const SELECTORS selector, const TRADE_RECORD_FIELDS field)
{
switch(selector)
{
case SELECTOR_TYPE:
return new TypeSelector();
case SELECTOR_SYMBOL:
return new SymbolSelector();
case SELECTOR_SERIAL:
return new SerialNumberSelector();
case SELECTOR_MAGIC:
return new MagicSelector();
case SELECTOR_PROFITABLE:
return new ProfitableSelector();
case SELECTOR_DURATION:
return new DaysRangeSelector(15); // up to 14 days
case SELECTOR_WEEKDAY:
return field != FIELD_NONE ? new WeekDaySelector(field) : NULL;
case SELECTOR_DAYHOUR:
return field != FIELD_NONE ? new DayHourSelector(field) : NULL;
case SELECTOR_HOURMINUTE:
return field != FIELD_NONE ? new DayHourSelector(field) : NULL;
case SELECTOR_SCALAR:
return field != FIELD_NONE ? new TradeSelector(field) : NULL;
case SELECTOR_QUANTS:
return field != FIELD_NONE ? new QuantizationSelector(field) : NULL;
}
return NULL;
}
public:
void process(
const SELECTORS &selectorArray[], const TRADE_RECORD_FIELDS &selectorField[],
const AGGREGATORS AggregatorType, const TRADE_RECORD_FIELDS AggregatorField, Display &display,
const SORT_BY SortBy = SORT_BY_NONE,
const double Filter1value1 = 0, const double Filter1value2 = 0)
{
int selectorCount = 0;
for(int i = 0; i < MathMin(ArraySize(selectorArray), 3); i++)
{
selectorCount += selectorArray[i] != SELECTOR_NONE;
}
if(selectorCount == 0)
{
Alert("No selectors. Setup at least one of them.");
return;
}
// filter section not used yet >>>
SELECTORS Filter1 = SELECTOR_NONE;
TRADE_RECORD_FIELDS Filter1Field = FIELD_NONE;
if(ArraySize(selectorArray) > 3)
{
Filter1 = selectorArray[3];
}
if(ArraySize(selectorField) > 3)
{
Filter1Field = selectorField[3];
}
// <<< filter section not used
HistoryDataAdapter<CustomTradeRecord> history;
HTMLReportAdapter<CustomTradeRecord> report;
CSVReportAdapter<CustomTradeRecord> external;
DataAdapter *adapter = &history;
if(ReportFile != "")
{
if(StringFind(ReportFile, ".htm") > 0 && report.load(ReportFile))
{
adapter = &report;
}
else
if(StringFind(ReportFile, ".csv") > 0 && external.load(ReportFile))
{
adapter = &external;
}
else
{
Alert("Unknown file format: ", ReportFile);
return;
}
}
else
{
Print("Analyzing account history");
}
Analyst<TRADE_RECORD_FIELDS> *analyst;
Selector<TRADE_RECORD_FIELDS> *selectors[];
ArrayResize(selectors, selectorCount);
for(int i = 0; i < selectorCount; i++)
{
selectors[i] = createSelector(selectorArray[i], selectorField[i]);
if(selectors[i] == NULL)
{
Print("Selector ", i, " is empty. Setup selectors successively (don't leave a hole in-between), specify a field when required");
return;
}
}
// filter section not used yet >>>
Filter<TRADE_RECORD_FIELDS> *filters[];
if(Filter1 != SELECTOR_NONE)
{
ArrayResize(filters, 1);
Selector<TRADE_RECORD_FIELDS> *filterSelector = createSelector(Filter1, Filter1Field);
if(Filter1value1 != Filter1value2)
{
filters[0] = new FilterRange<TRADE_RECORD_FIELDS>(filterSelector, Filter1value1, Filter1value2);
}
else
{
filters[0] = new Filter<TRADE_RECORD_FIELDS>(filterSelector, Filter1value1);
}
}
// <<< filter section not used
Aggregator<TRADE_RECORD_FIELDS> *aggregator;
// MQL does not support a 'class info' metaclass.
// Otherwise we could use an array of classes instead of the switch
switch(AggregatorType)
{
case AGGREGATOR_SUM:
aggregator = new SumAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_AVERAGE:
aggregator = new AverageAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_MAX:
aggregator = new MaxAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_MIN:
aggregator = new MinAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_COUNT:
aggregator = new CountAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_PROFITFACTOR:
aggregator = new ProfitFactorAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_PROGRESSIVE:
aggregator = new ProgressiveTotalAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
case AGGREGATOR_IDENTITY:
aggregator = new IdentityAggregator<TRADE_RECORD_FIELDS>(AggregatorField, selectors, filters);
break;
}
analyst = new Analyst<TRADE_RECORD_FIELDS>(adapter, aggregator, display);
analyst.acquireData();
Print("Symbol number: ", TradeRecord::getSymbolCount());
for(int i = 0; i < TradeRecord::getSymbolCount(); i++)
{
Print(i, "] ", TradeRecord::getSymbol(i));
}
Print("Magic number: ", TradeRecord::getMagicCount());
for(int i = 0; i < TradeRecord::getMagicCount(); i++)
{
Print(i, "] ", TradeRecord::getMagic(i));
}
Print("Filters: ", aggregator.getFilterTitles());
Print("Selectors: ", selectorCount);
analyst.build();
analyst.display(SortBy, AggregatorType == AGGREGATOR_IDENTITY);
delete analyst;
delete aggregator;
for(int i = 0; i < selectorCount; i++)
{
delete selectors[i];
}
for(int i = 0; i < ArraySize(filters); i++)
{
delete filters[i].getSelector();
delete filters[i];
}
}
};
File diff suppressed because it is too large Load Diff
+148
View File
@@ -0,0 +1,148 @@
//+------------------------------------------------------------------+
//| PairArray.mqh |
//| Copyright © 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
class PairArray
{
public:
// aux struct to populate temp array when sorting is enabled
struct Pair
{
double value;
string title;
Pair(): value(DBL_MAX), title(NULL) {}
Pair(const double v, const string s): value(v), title(s) {}
Pair(const string s, const double v): value(v), title(s) {}
bool operator>(const double v) const
{
return value > v;
}
bool operator>(const string s) const
{
return title > s;
}
};
// this is a common parent, so it can not be templatized
class Comparator
{
public:
// templatized method can not be virtual,
// so we do artificial dynamic dispatching manually
// (see below after declaration of descendant classes)
template<typename T>
bool compare(const Pair &v1, const T v2);
};
class Greater: public Comparator
{
public:
template<typename T>
bool compare(const Pair &v1, const T v2)
{
return v1 > v2;
}
};
class Lesser: public Comparator
{
public:
template<typename T>
bool compare(const Pair &v1, const T v2)
{
return !(v1 > v2);
}
};
private:
Comparator *comparator;
public:
// temp array for sorting (if enabled)
Pair array[];
PairArray(): comparator(NULL)
{
}
PairArray(const int reserved, Comparator *c = NULL)
{
comparator = c;
ArrayResize(array, reserved);
}
~PairArray()
{
ArrayResize(array, 0);
if(CheckPointer(comparator) == POINTER_DYNAMIC) delete comparator;
}
void allocate(const int reserved)
{
ArrayResize(array, reserved);
}
void compareBy(Comparator *c)
{
if(CheckPointer(comparator) == POINTER_DYNAMIC) delete comparator;
comparator = c;
}
void move(const int index, const int count)
{
for(int i = count - 1; i >= index; --i)
{
array[i + 1] = array[i];
}
}
template<typename T1, typename T2>
void insert(const int count, const T1 v, const T2 s)
{
Pair p(v, s);
for(int i = 0; i < count; i++)
{
if(comparator != NULL && comparator.compare(array[i], v))
{
move(i, count);
array[i] = p;
return;
}
}
array[count] = p;
}
void convert(double &x[], string &s[]) const
{
int n = ArraySize(array);
ArrayResize(x, n);
ArrayResize(s, n);
for(int i = 0; i < n; i++)
{
x[i] = array[i].value;
s[i] = array[i].title;
}
}
void convert(double &x[]) const
{
int n = ArraySize(array);
ArrayResize(x, n);
for(int i = 0; i < n; i++)
{
x[i] = array[i].value;
}
}
void convert(string &s[]) const
{
int n = ArraySize(array);
ArrayResize(s, n);
for(int i = 0; i < n; i++)
{
s[i] = array[i].title;
}
}
};
+525
View File
@@ -0,0 +1,525 @@
//+------------------------------------------------------------------+
//| Plot.mqh |
//| Copyright (c) 2019, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2019, Marketeer"
#property link "https://www.mql5.com/en/users/marketeer"
#property version "1.0"
#include <Controls\WndClient.mqh>
#include <Graphics\Graphic.mqh>
#include <OLAP/PairArray.mqh>
class CurveSubtitles
{
public:
CCurve *curve;
PairArray *data;
void assign(const CCurve *c, const PairArray *d)
{
curve = (CCurve *)c;
data = (PairArray *)d;
}
};
class CGraphicInPlot: public CGraphic
{
protected:
long m_chart_id; // chart ID
CurveSubtitles curvecache[];
void CGraphicInPlot::Customize(CCurve *c, const int points);
CCurve *CGraphicInPlot::CacheIt(const CCurve *c, const PairArray *data = NULL);
public:
CGraphicInPlot();
~CGraphicInPlot();
virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2);
CCurve *CurveAdd(const PairArray *data, ENUM_CURVE_TYPE type, const string name = NULL); // overload
CCurve *CurveAdd(const double &x[], const double &y[], ENUM_CURVE_TYPE type, const string name = NULL); // overload
void CurvesRemoveAll(void);
virtual bool Shift(const int dx, const int dy);
virtual bool Show(void);
virtual bool Hide(void);
void Destroy(void);
void ResetColors(void);
CCurve *CurveDetach(const int index);
bool CurveAttach(CCurve *curve);
int getIndexInCache(CCurve *c);
void replaceInCache(const int index, CCurve *c);
int cacheSize() const
{
return ArraySize(curvecache);
}
const CurveSubtitles *cacheItem(const int index) const
{
return &curvecache[index];
}
void InitXAxis(const bool custom);
void InitYAxis(const bool custom);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string CustomDoubleToStringFunction(double value, void *ptr)
{
CGraphicInPlot *self = dynamic_cast<CGraphicInPlot *>(ptr);
if(self != NULL)
{
if(self.cacheSize() > 0)
{
const int index = (int)value;
if(MathAbs(((double)index) - value) <= DBL_EPSILON)
{
const CurveSubtitles *s = self.cacheItem(0);
if(index < 0 || index >= ArraySize(s.data.array)) return NULL; // (string)(float)value; // debug
return s.data.array[index].title;
}
}
}
return NULL;
}
CGraphicInPlot::CGraphicInPlot()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CGraphicInPlot::~CGraphicInPlot()
{
CurvesRemoveAll();
}
void CGraphicInPlot::Destroy(void)
{
m_generator.Reset();
m_canvas.Destroy();
}
void CGraphicInPlot::ResetColors(void)
{
m_generator.Reset();
}
/* TODO: enable this to support Y marks customization
class AxisCustomizer
{
public:
const bool Y; // true for Y, false for X (default)
const CGraphicInPlot *parent;
AxisCustomizer(const bool axisY, CGraphicInPlot *p): Y(axisY), parent(p) {}
};
*/
void CGraphicInPlot::InitXAxis(const bool custom)
{
if(custom)
{
m_x.Type(AXIS_TYPE_CUSTOM);
m_x.ValuesFunctionFormat(CustomDoubleToStringFunction);
m_x.ValuesFunctionFormatCBData(&this);
}
else
{
m_x.Type(AXIS_TYPE_DOUBLE);
}
}
void CGraphicInPlot::InitYAxis(const bool custom)
{
if(custom)
{
m_y.Type(AXIS_TYPE_CUSTOM);
m_y.ValuesFunctionFormat(CustomDoubleToStringFunction);
m_y.ValuesFunctionFormatCBData(&this);
}
else
{
m_y.Type(AXIS_TYPE_DOUBLE);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGraphicInPlot::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
{
if(!CGraphic::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
m_chart_id = chart;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGraphicInPlot::Show(void)
{
string obj_name = ChartObjectName();
if(obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) return false;
if(!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS)) return false;
Update(false);
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGraphicInPlot::Hide(void)
{
string obj_name = ChartObjectName();
if(obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) return false;
return ObjectSetInteger(m_chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CGraphicInPlot::Shift(const int dx, const int dy)
{
string obj_name = ChartObjectName();
if(obj_name == NULL || ObjectFind(m_chart_id, obj_name) < 0) return false;
int x = (int)ObjectGetInteger(m_chart_id, obj_name, OBJPROP_XDISTANCE) + dx;
int y = (int)ObjectGetInteger(m_chart_id, obj_name, OBJPROP_YDISTANCE) + dy;
if(!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_XDISTANCE, x)) return false;
if(!ObjectSetInteger(m_chart_id, obj_name, OBJPROP_YDISTANCE, y)) return false;
return true;
}
CCurve *CGraphicInPlot::CurveDetach(const int index)
{
return m_arr_curves.Detach(index);
}
bool CGraphicInPlot::CurveAttach(CCurve *curve)
{
return m_arr_curves.Add(curve);
}
void CGraphicInPlot::Customize(CCurve *c, const int points)
{
int w = MathMax(Width() / points / 4, 1);
c.HistogramWidth(w);
c.LinesWidth(3);
c.PointsFill(true);
}
CCurve *CGraphicInPlot::CacheIt(const CCurve *c, const PairArray *data = NULL)
{
int n = ArraySize(curvecache);
ArrayResize(curvecache, n + 1);
curvecache[n].assign(c, data);
return (CCurve *)c;
}
CCurve *CGraphicInPlot::CurveAdd(const PairArray *data, ENUM_CURVE_TYPE type, const string name = NULL)
{
double y[];
string s[];
data.convert(y, s);
CCurve *c = CGraphic::CurveAdd(y, type, name);
Customize(c, ArraySize(y));
return CacheIt(c, data);
}
CCurve *CGraphicInPlot::CurveAdd(const double &x[], const double &y[], ENUM_CURVE_TYPE type, const string name = NULL)
{
CCurve *c = CGraphic::CurveAdd(x, y, type, name);
Customize(c, ArraySize(x));
return CacheIt(c);
}
int CGraphicInPlot::getIndexInCache(CCurve *c)
{
int n = ArraySize(curvecache);
for(int i = 0; i < n; i++)
{
if(curvecache[i].curve == c) return i;
}
return -1;
}
void CGraphicInPlot::replaceInCache(const int index, CCurve *c)
{
curvecache[index].curve = c;
}
void CGraphicInPlot::CurvesRemoveAll(void)
{
int n = m_arr_curves.Total();
for(int i = n - 1; i >= 0; i--)
{
CurveRemoveByIndex(i);
}
n = ArraySize(curvecache);
for(int i = n - 1; i >= 0; i--)
{
if(CheckPointer(curvecache[i].data) == POINTER_DYNAMIC) delete curvecache[i].data;
}
ArrayResize(curvecache, 0);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CPlot: public CWndClient
{
private:
CGraphicInPlot *m_graphic;
ENUM_CURVE_TYPE type;
uint i_text_color;
CCurve *temp[];
public:
CPlot();
~CPlot();
bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2, const ENUM_CURVE_TYPE t = CURVE_HISTOGRAM);
virtual void Destroy(const int reason = 0) override;
bool Refresh(const bool enforce = false);
bool SetTextColor(color value);
virtual bool Shift(const int dx, const int dy) override;
virtual bool Show(void);
virtual bool Hide(void);
bool Resize(const int x1, const int y1, const int x2, const int y2);
CCurve *CurveAdd(const PairArray *data, const string name = NULL);
CCurve *CurveAdd(const double &x[], const double &y[], const string name = NULL);
void CurvesRemoveAll(void);
void SetDefaultCurveType(ENUM_CURVE_TYPE t)
{
type = t;
}
void InitXAxis(const bool custom)
{
if(CheckPointer(m_graphic) != POINTER_INVALID)
{
m_graphic.InitXAxis(custom);
}
}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CPlot::CPlot():
type(CURVE_HISTOGRAM), i_text_color(ColorToARGB(clrBlack, 255))
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CPlot::~CPlot()
{
if(CheckPointer(m_graphic) != POINTER_INVALID)
{
m_graphic.Destroy();
delete m_graphic;
}
}
void CPlot::Destroy(const int reason = 0)
{
if(CheckPointer(m_graphic) != POINTER_INVALID)
{
m_graphic.Destroy();
delete m_graphic;
m_graphic = NULL;
}
CWndClient::Destroy(reason);
}
CCurve *CPlot::CurveAdd(const PairArray *data, const string name = NULL)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return NULL;
return m_graphic.CurveAdd(data, type, name);
}
CCurve *CPlot::CurveAdd(const double &x[], const double &y[], const string name = NULL)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return NULL;
return m_graphic.CurveAdd(x, y, type, name);
}
void CPlot::CurvesRemoveAll(void)
{
m_graphic.CurvesRemoveAll();
m_graphic.ResetColors();
}
bool CPlot::Resize(const int x1, const int y1, const int x2, const int y2)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
int width = Width();
int height = Height();
Size(x2 - x1, y2 - y1);
string obj_name = m_name + "_0_0";
int obj_x1 = m_rect.left;
int obj_x2 = obj_x1 + width;
int obj_y1 = m_rect.top;
int obj_y2 = obj_y1 + height;
m_graphic.Destroy();
if(!m_graphic.Create(m_chart_id, obj_name, m_subwin, obj_x1, obj_y1, obj_x2, obj_y2))
{
Print(GetLastError());
return false;
}
for(int i = 0; i < ArraySize(temp); ++i)
{
if(CheckPointer(temp[i]) == POINTER_DYNAMIC) delete temp[i];
}
ArrayResize(temp, m_graphic.CurvesTotal());
// Graphic library does not provide a method to update curve without array copying
for(int i = m_graphic.CurvesTotal() - 1; i >= 0; --i)
{
temp[i] = m_graphic.CurveDetach(i);
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CPlot::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2, const ENUM_CURVE_TYPE t = CURVE_HISTOGRAM)
{
if(!CWndClient::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
type = t;
int width = Width();
int height = Height();
string obj_name = m_name + "_0_0";
int obj_x1 = m_rect.left;
int obj_x2 = obj_x1 + width;
int obj_y1 = m_rect.top;
int obj_y2 = obj_y1 + height;
m_graphic = new CGraphicInPlot();
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
if(!m_graphic.Create(m_chart_id, obj_name, m_subwin, obj_x1, obj_y1, obj_x2, obj_y2)) return false;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CPlot::Hide(void)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
if(!m_graphic.Hide()) return false;
return CWndClient::Hide();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CPlot::Show(void)
{
if(!CWndClient::Show()) return false;
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
if(m_graphic.Show()) return false;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CPlot::Shift(const int dx, const int dy)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
if(!m_graphic.Shift(dx, dy)) return false;
return CWndClient::Shift(dx, dy);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CPlot::Refresh(const bool enforce = false)
{
if(CheckPointer(m_graphic) == POINTER_INVALID) return false;
if(ArraySize(temp) == 0 && enforce)
{
m_graphic.ResetColors();
ArrayResize(temp, m_graphic.CurvesTotal());
for(int i = m_graphic.CurvesTotal() - 1; i >= 0; --i)
{
temp[i] = m_graphic.CurveDetach(i);
}
}
for(int i = 0; i < ArraySize(temp); ++i)
{
if(CheckPointer(temp[i]) == POINTER_DYNAMIC)
{
double x[], y[];
temp[i].GetX(x);
temp[i].GetY(y);
string name = temp[i].Name();
int index = m_graphic.getIndexInCache(temp[i]);
delete temp[i];
CCurve *curve = NULL;
if(ArraySize(x) > 0)
{
if(ArraySize(y) > 0)
{
curve = m_graphic.CurveAdd(x, y, type, name);
}
else
{
curve = m_graphic.CurveAdd(x, type, name);
}
}
m_graphic.replaceInCache(index, curve);
// axis does not yet calculated, it's done only during CurvePlotAll
// so we can't automatically adjust histogram width
// double range = (m_graphic.XAxis().Max() - m_graphic.XAxis().Min());
// double data = (x[ArrayMaximum(x)] - x[ArrayMinimum(x)]);
// int downsize = (int)(range / data);
curve.HistogramWidth(Width() / ArraySize(x) / 4);
curve.LinesWidth(3);
}
}
ArrayResize(temp, 0);
if(!m_graphic.CurvePlotAll()) return false;
m_graphic.Update(false);
ChartRedraw(m_chart_id);
return true;
}
+344
View File
@@ -0,0 +1,344 @@
//+------------------------------------------------------------------+
//| MovingAverages.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Simple Moving Average |
//+------------------------------------------------------------------+
double SimpleMA(const int position,const int period,const double &price[])
{
double result=0.0;
//--- check period
if(period>0 && period<=(position+1))
{
for(int i=0; i<period; i++)
result+=price[position-i];
result/=period;
}
return(result);
}
//+------------------------------------------------------------------+
//| Exponential Moving Average |
//+------------------------------------------------------------------+
double ExponentialMA(const int position,const int period,const double prev_value,const double &price[], const bool distance, const double distpip,
const int buysell)
{
double result=0.0;
//--- check period
if(period>0)
{
if (!distance)
{
double pr=2.0/(period+1.0);
result=price[position]*pr+prev_value*(1-pr);
}
if (distance)
{
if (buysell == 1)
{
double pr=2.0/(period+1.0);
double _dis_point = distpip * Point();
double val_dist = (price[position] / _dis_point) - 1.0;
double sum_val_dist = price[position] - _dis_point; //val_dist * _dis_point;
result = sum_val_dist*pr+prev_value*(1-pr);
}
else if (buysell == -1)
{
double pr=2.0/(period+1.0);
double _dis_point = distpip * Point();
double val_dist = (price[position] / _dis_point) - 1.0;
double sum_val_dist = price[position] + _dis_point; //val_dist * _dis_point;
result = sum_val_dist*pr+prev_value*(1-pr);
}
}
}
return(result);
}
//+------------------------------------------------------------------+
//| Smoothed Moving Average |
//+------------------------------------------------------------------+
double SmoothedMA(const int position,const int period,const double prev_value,const double &price[])
{
double result=0.0;
//--- check period
if(period>0 && period<=(position+1))
{
if(position==period-1)
{
for(int i=0; i<period; i++)
result+=price[position-i];
result/=period;
}
result=(prev_value*(period-1)+price[position])/period;
}
return(result);
}
//+------------------------------------------------------------------+
//| Linear Weighted Moving Average |
//+------------------------------------------------------------------+
double LinearWeightedMA(const int position,const int period,const double &price[])
{
double result=0.0;
//--- check period
if(period>0 && period<=(position+1))
{
double sum =0.0;
int wsum=0;
for(int i=period; i>0; i--)
{
wsum+=i;
sum +=price[position-i+1]*(period-i+1);
}
result=sum/wsum;
}
return(result);
}
//+------------------------------------------------------------------+
//| Simple moving average on price array |
//+------------------------------------------------------------------+
int SimpleMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
{
//--- check period
if(period<=1 || period>(rates_total-begin))
return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
ArraySetAsSeries(price,false);
ArraySetAsSeries(buffer,false);
//--- calculate start position
int start_position;
if(prev_calculated==0) // first calculation or number of bars was changed
{
//--- set empty value for first bars
start_position=period+begin;
for(int i=0; i<start_position-1; i++)
buffer[i]=0.0;
//--- calculate first visible value
double first_value=0;
for(int i=begin; i<start_position; i++)
first_value+=price[i];
buffer[start_position-1]=first_value/period;
}
else
start_position=prev_calculated-1;
//--- main loop
for(int i=start_position; i<rates_total; i++)
buffer[i]=buffer[i-1]+(price[i]-price[i-period])/period;
//--- restore as_series flags
ArraySetAsSeries(price,as_series_price);
ArraySetAsSeries(buffer,as_series_buffer);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//| Exponential moving average on price array |
//+------------------------------------------------------------------+
int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
{
//--- check period
if(period<=1 || period>(rates_total-begin))
return(0);
//--- save and clear 'as_series' flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
ArraySetAsSeries(price,false);
ArraySetAsSeries(buffer,false);
//--- calculate start position
int start_position;
double smooth_factor=2.0/(1.0+period);
if(prev_calculated==0) // first calculation or number of bars was changed
{
//--- set empty value for first bars
for(int i=0; i<begin; i++)
buffer[i]=0.0;
//--- calculate first visible value
start_position=period+begin;
buffer[begin] =price[begin];
for(int i=begin+1; i<start_position; i++)
buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor);
}
else
start_position=prev_calculated-1;
//--- main loop
for(int i=start_position; i<rates_total; i++)
buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor);
//--- restore as_series flags
ArraySetAsSeries(price,as_series_price);
ArraySetAsSeries(buffer,as_series_buffer);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on price array classic |
//+------------------------------------------------------------------+
int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
{
//--- check period
if(period<=1 || period>(rates_total-begin))
return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
ArraySetAsSeries(price,false);
ArraySetAsSeries(buffer,false);
//--- calculate start position
int i,start_position;
if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed
{
//--- set empty value for first bars
start_position=period+begin;
for(i=0; i<start_position; i++)
buffer[i]=0.0;
}
else
start_position=prev_calculated-2;
//--- calculate first visible value
double sum=0.0,lsum=0.0;
int l,weight=0;
for(i=start_position-period,l=1; i<start_position; i++,l++)
{
sum +=price[i]*l;
lsum +=price[i];
weight+=l;
}
buffer[start_position-1]=sum/weight;
//--- main loop
for(i=start_position; i<rates_total; i++)
{
sum =sum-lsum+price[i]*period;
lsum =lsum-price[i-period]+price[i];
buffer[i]=sum/weight;
}
//--- restore as_series flags
ArraySetAsSeries(price,as_series_price);
ArraySetAsSeries(buffer,as_series_buffer);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on price array fast |
//+------------------------------------------------------------------+
int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[],int &weight_sum)
{
//--- check period
if(period<=1 || period>(rates_total-begin))
return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
ArraySetAsSeries(price,false);
ArraySetAsSeries(buffer,false);
//--- calculate start position
int start_position;
if(prev_calculated==0) // first calculation or number of bars was changed
{
//--- set empty value for first bars
start_position=period+begin;
for(int i=0; i<start_position; i++)
buffer[i]=0.0;
//--- calculate first visible value
double first_value=0;
int wsum =0;
for(int i=begin,k=1; i<start_position; i++,k++)
{
first_value+=k*price[i];
wsum +=k;
}
buffer[start_position-1]=first_value/wsum;
weight_sum=wsum;
}
else
start_position=prev_calculated-1;
//--- main loop
for(int i=start_position; i<rates_total; i++)
{
double sum=0;
for(int j=0; j<period; j++)
sum+=(period-j)*price[i-j];
buffer[i]=sum/weight_sum;
}
//--- restore as_series flags
ArraySetAsSeries(price,as_series_price);
ArraySetAsSeries(buffer,as_series_buffer);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//| Smoothed moving average on price array |
//+------------------------------------------------------------------+
int SmoothedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
{
//--- check period
if(period<=1 || period>(rates_total-begin))
return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
ArraySetAsSeries(price,false);
ArraySetAsSeries(buffer,false);
//--- calculate start position
int start_position;
if(prev_calculated==0) // first calculation or number of bars was changed
{
//--- set empty value for first bars
start_position=period+begin;
for(int i=0; i<start_position-1; i++)
buffer[i]=0.0;
//--- calculate first visible value
double first_value=0;
for(int i=begin; i<start_position; i++)
first_value+=price[i];
buffer[start_position-1]=first_value/period;
}
else
start_position=prev_calculated-1;
//--- main loop
for(int i=start_position; i<rates_total; i++)
buffer[i]=(buffer[i-1]*(period-1)+price[i])/period;
//--- restore as_series flags
ArraySetAsSeries(price,as_series_price);
ArraySetAsSeries(buffer,as_series_buffer);
//---
return(rates_total);
}
//+------------------------------------------------------------------+