Adwizard/Virtual/VirtualRiskManager.mqh

605 lines
53 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| VirtualRiskManager.mqh |
//| Copyright 2022-2025, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022-2025, Yuriy Bykov"
#property link "https://www.mql5.com/ru/users/antekov"
#property version "1.05"
#include "../Database/Storage.mqh"
// >7<>6=K5 A>AB>O=8O @8A:-<5=5465@0
enum ENUM_RM_STATE {
RM_STATE_OK, // 8<8BK =5 ?@52KH5=K
RM_STATE_DAILY_LOSS, // @52KH5= 4=52=>9 ;8<8B
RM_STATE_RESTORE, // >AAB0=>2;5=85 ?>A;5 4=52=>3> ;8<8B0
RM_STATE_OVERALL_LOSS, // @52KH5= >1I89 ;8<8B
RM_STATE_OVERALL_PROFIT // >AB83=CB0 >1I0O ?@81K;L
};
// >7<>6=K5 A?>A>1K @0AGQB0 4=52=KE ;8<8B>2
enum ENUM_RM_CALC_DAILY_LOSS {
RM_CALC_DAILY_LOSS_MONEY_BB, // [$] to Daily Level
RM_CALC_DAILY_LOSS_PERCENT_BB, // [%] from Base Balance to Daily Level
RM_CALC_DAILY_LOSS_PERCENT_DL // [%] from/to Daily Level
};
// >7<>6=K5 A?>A>1K @0AGQB0 >1I8E ;8<8B>2
enum ENUM_RM_CALC_OVERALL_LOSS {
RM_CALC_OVERALL_LOSS_MONEY_BB, // [$] to Base Balance
RM_CALC_OVERALL_LOSS_MONEY_HW_BAL, // [$] to HW Balance
RM_CALC_OVERALL_LOSS_MONEY_HW_EQ_BAL, // [$] to HW Equity or Balance
RM_CALC_OVERALL_LOSS_PERCENT_BB, // [%] from/to Base Balance
RM_CALC_OVERALL_LOSS_PERCENT_HW_BAL, // [%] from/to HW Balance
RM_CALC_OVERALL_LOSS_PERCENT_HW_EQ_BAL // [%] from/to HW Equity or Balance
};
// >7<>6=K5 A?>A>1K @0AGQB0 >1I59 ?@81K;8
enum ENUM_RM_CALC_OVERALL_PROFIT {
RM_CALC_OVERALL_PROFIT_MONEY_BB, // [$] to Base Balance
RM_CALC_OVERALL_PROFIT_PERCENT_BB, // [%] from/to Base Balance
};
//+------------------------------------------------------------------+
//| ;0AA C?@02;5=8O @8A:>< (@8A:-<5=5645@) |
//+------------------------------------------------------------------+
class CVirtualRiskManager : public CFactorable {
protected:
// A=>2=K5 ?0@0<5B@K :>=AB@C:B>@0
bool m_isActive; // 8A: <5=5465@ 0:B825=?
double m_baseBalance; // 07>2K9 10;0=A
ENUM_RM_CALC_DAILY_LOSS m_calcDailyLossLimit; // !?>A>1 @0AGQB0 <0:A8<0;L=>3> 4=52=>3> C1KB:0
double m_maxDailyLossLimit; // 0@0<5B@ @0AGQB0 <0:A8<0;L=>3> 4=52=>3> C1KB:0
double m_closeDailyPart; // =0G5=85 ?>@>3>2>9 G0AB8 4=52=>3> C1KB:0
ENUM_RM_CALC_OVERALL_LOSS m_calcOverallLossLimit; // !?>A>1 @0AGQB0 <0:A8<0;L=>3> >1I53> C1KB:0
double m_maxOverallLossLimit; // 0@0<5B@ @0AGQB0 <0:A8<0;L=>3> >1I53> C1KB:0
double m_closeOverallPart; // =0G5=85 ?>@>3>2>9 G0AB8 >1I53> C1KB:0
ENUM_RM_CALC_OVERALL_PROFIT m_calcOverallProfitLimit; // !?>A>1 @0AGQB0 <0:A8<0;L=>9 >1I59 ?@81K;8
double m_maxOverallProfitLimit; // 0@0<5B@ @0AGQB0 <0:A8<0;L=>9 >1I59 ?@81K;8
datetime m_maxOverallProfitDate; // @545;L=>5 2@5<O 4;O 4>AB865=8O >1I59 ?@81K;8
double m_maxRestoreTime; // @5<O >6840=8O ;CGH53> 2E>40 =0 ?@>A04:5
double m_lastVirtualProfitFactor; // =>68B5;L =0G0;L=>9 ;CGH59 ?@>A04:8
// "5:CI55 A>AB>O=85
ENUM_RM_STATE m_state; // !>AB>O=85
double m_lastVirtualProfit; // @81K;L >B:@KBKE 28@BC0;L=KE ?>78F89 =0 <><5=B ;8<8B0 C1KB:0
datetime m_startRestoreTime; // @5<O =0G0;0 2>AAB0=>2;5=8O @07<5@>2 >B:@KBKE ?>78F89
datetime m_startTime;
// 1=>2;O5<K5 7=0G5=8O
double m_balance; // "5:CI89 10;0=A
double m_equity; // "5:CI85 A@54AB20
double m_profit; // "5:CI0O ?@81K;L
double m_dailyProfit; // =52=0O ?@81K;L
double m_overallProfit; // 1I0O ?@81K;L
double m_baseDailyBalance; // =52=>9 107>2K9 10;0=A
double m_baseDailyEquity; // =52=K5 107>2K5 A@54AB20
double m_baseDailyLevel; // =52=>9 107>2K9 C@>25=L
double m_baseHWBalance; // High Watermark 10;0=A0
double m_baseHWEquityBalance; // High Watermark A@54AB2 8;8 10;0=A0
double m_virtualProfit; // @81K;L >B:@KBKE 28@BC0;L=KE ?>78F89
// #?@02;5=85 @07<5@>< >B:@KBKE ?>78F89
double m_baseDepoPart; // A?>;L7C5<0O G0ABL >1I53> 10;0=A0 (8AE>4=0O)
double m_dailyDepoPart; // =>68B5;L 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 ?> 4=52=><C C1KB:C
double m_overallDepoPart; // =>68B5;L 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 ?> >1I5<C C1KB:C
// 0I8IQ==K5 <5B>4K
double DailyLoss(); // 0:A8<0;L=K9 4=52=>9 C1KB>:
double OverallLoss(); // 0:A8<0;L=K9 >1I89 C1KB>:
double OverallProfit(); // 0:A8<0;L=0O ?@81K;L
void UpdateProfit(); // 1=>2;5=85 B5:CI8E 7=0G5=89 ?@81K;8
void UpdateBaseLevels(); // 1=>2;5=85 4=52=KE 107>2KE C@>2=59
void CheckLimits(); // @>25@:0 ?@52KH5=8O 4>?CAB8<KE C1KB:>2
bool CheckDailyLossLimit(); // @>25@:0 ?@52KH5=8O 4>?CAB8<>3> 4=52=>3> C1KB:0
bool CheckOverallLossLimit(); // @>25@:0 ?@52KH5=8O 4>?CAB8<>3> >1I53> C1KB:0
bool CheckOverallProfitLimit(); // @>25@:0 4>AB865=8O 7040==>9 ?@81K;8
void CheckRestore(); // @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O @07<5@>2 >B:@KBKE ?>78F89
bool CheckDailyRestore(); // @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O 4=52=>3> <=>68B5;O
bool CheckOverallRestore(); // @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O >1I53> <=>68B5;O
double VirtualProfit(); // ?@545;5=85 ?@81K;8 >B:@KBKE 28@BC0;L=KE ?>78F89
double RestoreVirtualProfit(); // ?@545;5=85 ?@81K;8 >B:@KBKE 28@BC0;L=KE ?>78F89 4;O 2>AAB0=>2;5=8O
void SetDepoPart(); // #AB0=>2:0 7=0G5=8O 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0
CVirtualRiskManager(string p_params); // >=AB@C:B>@
public:
STATIC_CONSTRUCTOR(CVirtualRiskManager);
virtual void Tick(); // 1@01>B:0 B8:0 2 @8A:-<5=5465@5
virtual bool Save(); // !>E@0=5=85 A>AB>O=8O
virtual bool Load(); // 03@C7:0 A>AB>O=8O
virtual string operator~() override; // @5>1@07>20=85 >1J5:B0 2 AB@>:C
};
REGISTER_FACTORABLE_CLASS(CVirtualRiskManager);
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CVirtualRiskManager::CVirtualRiskManager(string p_params) {
// 0?><8=05< AB@>:C 8=8F80;870F88
m_params = p_params;
// '8B05< AB@>:C 8=8F80;870F88 8 CAB0=02;8205< 7=0G5=8O A2>9AB2
m_isActive = (bool) ReadLong(p_params);
m_baseBalance = ReadDouble(p_params);
m_calcDailyLossLimit = (ENUM_RM_CALC_DAILY_LOSS) ReadLong(p_params);
m_maxDailyLossLimit = ReadDouble(p_params);
m_closeDailyPart = ReadDouble(p_params);
m_calcOverallLossLimit = (ENUM_RM_CALC_OVERALL_LOSS) ReadLong(p_params);
m_maxOverallLossLimit = ReadDouble(p_params);
m_closeOverallPart = ReadDouble(p_params);
m_calcOverallProfitLimit = (ENUM_RM_CALC_OVERALL_PROFIT) ReadLong(p_params);
m_maxOverallProfitLimit = ReadDouble(p_params);
m_maxOverallProfitDate = (datetime) ReadLong(p_params);
m_maxRestoreTime = ReadDouble(p_params);
m_lastVirtualProfitFactor = ReadDouble(p_params);
// #AB0=02;8205< A>AB>O=85: 8<8BK =5 ?@52KH5=K
m_state = RM_STATE_OK;
m_dailyDepoPart = 1;
m_overallDepoPart = 1;
m_lastVirtualProfit = 0;
m_startRestoreTime = 0;
// 0?><8=05< 4>;N 10;0=A0 AGQB0, 2K45;5==>3> =0 B>@3>2;N
m_baseDepoPart = CMoney::DepoPart();
// 1=>2;O5< 107>2K5 4=52=K5 C@>2=8
UpdateBaseLevels();
// >@@5:B8@C5< 107>2K9 10;0=A, 5A;8 >= =5 7040=
if(m_baseBalance == 0) {
m_baseBalance = m_balance;
}
}
//+------------------------------------------------------------------+
//| 1@01>B:0 B8:0 2 @8A:-<5=5465@5 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::Tick() {
// A;8 @8A:-<5=5465@ =50:B825=, B> 2KE>48<
if(!m_isActive) {
return;
}
// 1=>2;O5< B5:CI85 7=0G5=8O ?@81K;8
UpdateProfit();
// A;8 =0ABC?8; =>2K9 4=52=>9 ?5@8>4, B> >1=>2;O5< 107>2K5 4=52=K5 C@>2=8
if(IsNewBar(Symbol(), PERIOD_D1)) {
UpdateBaseLevels();
}
CheckRestore();
// @>25@O5< ?@52KH5=85 ?@545;>2 C1KB:0
CheckLimits();
}
//+------------------------------------------------------------------+
//| !>E@0=5=85 A>AB>O=8O |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::Save() {
CStorage::Set("CVirtualRiskManager::m_state", m_state);
CStorage::Set("CVirtualRiskManager::m_lastVirtualProfit", m_lastVirtualProfit);
CStorage::Set("CVirtualRiskManager::m_startRestoreTime", m_startRestoreTime);
CStorage::Set("CVirtualRiskManager::m_startTime", m_startTime);
CStorage::Set("CVirtualRiskManager::m_dailyDepoPart", m_dailyDepoPart);
CStorage::Set("CVirtualRiskManager::m_overallDepoPart", m_overallDepoPart);
return true;
}
//+------------------------------------------------------------------+
//| 03@C7:0 A>AB>O=8O |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::Load() {
CStorage::Get("CVirtualRiskManager::m_state", m_state);
CStorage::Get("CVirtualRiskManager::m_lastVirtualProfit", m_lastVirtualProfit);
CStorage::Get("CVirtualRiskManager::m_startRestoreTime", m_startRestoreTime);
CStorage::Get("CVirtualRiskManager::m_startTime", m_startTime);
CStorage::Get("CVirtualRiskManager::m_dailyDepoPart", m_dailyDepoPart);
CStorage::Get("CVirtualRiskManager::m_overallDepoPart", m_overallDepoPart);
//m_state = (ENUM_RM_STATE) FileReadNumber(f);
//m_lastVirtualProfit = FileReadNumber(f);
//m_startRestoreTime = FileReadDatetime(f);
//m_startTime = FileReadDatetime(f);
//m_dailyDepoPart = FileReadNumber(f);
//m_overallDepoPart = FileReadNumber(f);
return true;
}
//+------------------------------------------------------------------+
//| @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O @07<5@>2 >B:@KBKE ?>78F89 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::CheckRestore() {
// A;8 =C6=> 2>AAB0=02;820BL A>AB>O=85 4> =>@<0;L=>3>, B>
if(m_state == RM_STATE_RESTORE) {
// @>25@O5< 2>7<>6=>ABL 2>AAB0=>28BL 4> =>@<0;L=>3> <=>68B5;L 4=52=>3> C1KB:0
bool dailyRes = CheckDailyRestore();
// @>25@O5< 2>7<>6=>ABL 2>AAB0=>28BL 4> =>@<0;L=>3> <=>68B5;L >1I53> C1KB:0
bool overallRes = CheckOverallRestore();
// A;8 E>BO 1K >48= 87 =8E 2>AAB0=>28;AO, B>
if(dailyRes || overallRes) {
PrintFormat(__FUNCTION__" | VirtualProfit = %.2f | Profit = %.2f | Daily Profit = %.2f",
m_virtualProfit, m_profit, m_dailyProfit);
PrintFormat(__FUNCTION__" | RESTORE: depoPart = %.2f = %.2f * %.2f * %.2f",
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
// #AB0=02;8205< 7=0G5=85 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0
SetDepoPart();
// ?>25I05< ?>;CG0B5;L >1 87<5=5=8OE
CVirtualReceiver::Instance().Changed();
// A;8 >10 <=>68B5;O 2>AAB0=>2;5=K 4> =>@<0;L=KE, B>
if(dailyRes && overallRes) {
// #AB0=02;8205< =>@<0;L=>5 A>AB>O=85
m_state = RM_STATE_OK;
}
}
//else {
// if(IsNewBar(Symbol(), PERIOD_H1)) {
// PrintFormat(__FUNCTION__" | VirtualProfit = %.2f | Profit = %.2f | Daily Profit = %.2f",
// m_virtualProfit, m_profit, m_dailyProfit);
// PrintFormat(__FUNCTION__" | WAIT RESTORE: depoPart = %.2f = %.2f * %.2f * %.2f",
// m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
// m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
// }
//}
}
}
//+------------------------------------------------------------------+
//| @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O 4=52=>3> <=>68B5;O |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::CheckDailyRestore() {
// A;8 B5:CI0O 28@BC0;L=0O ?@81K;L <5=LH5 65;05<>9 4;O 2>AAB0=>2;5=8O, B>
if(m_virtualProfit <= RestoreVirtualProfit()) {
// >AAB0=02;8205< <=>68B5;L 4=52=>3> C1KB:0
m_dailyDepoPart = 1.0;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| @>25@:0 =5>1E>48<>AB8 2>AAB0=>2;5=8O >1I53> <=>68B5;O |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::CheckOverallRestore() {
// A;8 B5:CI0O 28@BC0;L=0O ?@81K;L <5=LH5 65;05<>9 4;O 2>AAB0=>2;5=8O, B>
if(m_virtualProfit <= RestoreVirtualProfit()) {
// >AAB0=02;8205< <=>68B5;L >1I53> C1KB:0
m_overallDepoPart = 1.0;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| 0:A8<0;L=K9 4=52=>9 C1KB>: |
//+------------------------------------------------------------------+
double CVirtualRiskManager::DailyLoss() {
if(m_calcDailyLossLimit == RM_CALC_DAILY_LOSS_PERCENT_BB) {
// ;O 7040==>3> ?@>F5=B0 >B 107>2>3> 10;0=A0 2KG8A;O5< 53>
return m_baseBalance * m_maxDailyLossLimit / 100;
} else if(m_calcDailyLossLimit == RM_CALC_DAILY_LOSS_PERCENT_DL) {
// ;O 7040==>3> ?@>F5=B0 >B 4=52=>3> C@>2=O 2KG8A;O5< 53>
return m_baseDailyLevel * m_maxDailyLossLimit / 100;
} else {
// ;O D8:A8@>20==>3> 7=0G5=8O ?@>AB> 2>72@0I05< 53>
return m_maxDailyLossLimit;
}
}
//+------------------------------------------------------------------+
//| 0:A8<0;L=K9 >1I89 C1KB>: |
//+------------------------------------------------------------------+
double CVirtualRiskManager::OverallLoss() {
if(m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_PERCENT_BB) {
// ;O 7040==>3> ?@>F5=B0 >B 107>2>3> 10;0=A0 2KG8A;O5< 53>
return m_baseBalance * m_maxOverallLossLimit / 100;
} else if(m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_PERCENT_HW_BAL) {
// ;O 7040==>3> ?@>F5=B0 >B 4=52=>3> C@>2=O 2KG8A;O5< 53>
return m_baseHWBalance * m_maxOverallLossLimit / 100;
} else if(m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_PERCENT_HW_EQ_BAL) {
// ;O 7040==>3> ?@>F5=B0 >B 4=52=>3> C@>2=O 2KG8A;O5< 53>
return m_baseHWEquityBalance * m_maxOverallLossLimit / 100;
} else {
// ;O D8:A8@>20==>3> 7=0G5=8O ?@>AB> 2>72@0I05< 53>
// RM_CALC_OVERALL_LOSS_MONEY_BB || RM_CALC_OVERALL_LOSS_MONEY_HW_BAL
return m_maxOverallLossLimit;
}
}
//+------------------------------------------------------------------+
//| 0:A8<0;L=K9 >1I0O ?@81K;L |
//+------------------------------------------------------------------+
double CVirtualRiskManager::OverallProfit() {
// "5:CI55 2@5<O
datetime tc = TimeCurrent();
// A;8 B5:CI55 2@5<O 1>;LH5 7040==>3> <0:A8<0;L=> 4>?CAB8<>3>, B>
if(m_maxOverallProfitDate && tc > m_maxOverallProfitDate) {
// >72@0I05< 7=0G5=85, 30@0=B8@CNI55 70:@KB85 ?>78F89
return m_overallProfit;
} else if(m_calcOverallProfitLimit == RM_CALC_OVERALL_PROFIT_PERCENT_BB) {
// ;O 7040==>3> ?@>F5=B0 >B 107>2>3> 10;0=A0 2KG8A;O5< 53>
return m_baseBalance * m_maxOverallProfitLimit / 100;
} else {
// ;O D8:A8@>20==>3> 7=0G5=8O ?@>AB> 2>72@0I05< 53>
// RM_CALC_OVERALL_PROFIT_MONEY_BB
return m_maxOverallProfitLimit;
}
}
//+------------------------------------------------------------------+
//| 1=>2;5=85 B5:CI8E 7=0G5=89 ?@81K;8 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::UpdateProfit() {
// "5:CI85 A@54AB20
m_equity = AccountInfoDouble(ACCOUNT_EQUITY);
// "5:CI89 10;0=A
m_balance = AccountInfoDouble(ACCOUNT_BALANCE);
// 082KAH89 10;0=A (High Watermark)
m_baseHWBalance = MathMax(m_balance, m_baseHWBalance);
// 082KAH89 10;0=A 8;8 A@54AB20 (High Watermark)
m_baseHWEquityBalance = MathMax(m_equity, MathMax(m_balance, m_baseHWEquityBalance));
// "5:CI0O ?@81K;L
m_profit = m_equity - m_balance;
// "5:CI0O 4=52=0O ?@81K;L >B=>A8B5;L=> 4=52=>3> C@>2=O
m_dailyProfit = m_equity - m_baseDailyLevel;
// "5:CI0O >1I0O ?@81K;L >B=>A8B5;L=> 107>2>3> 10;0=A0
m_overallProfit = m_equity - m_baseBalance;
// A;8 >1ICN ?@81K;L 15@Q< >B=>A8B5;L=> =082KAH53> 10;0=A0, B>
if(m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_MONEY_HW_BAL
|| m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_PERCENT_HW_BAL) {
// 5@5AG8B05< 5Q
m_overallProfit = m_equity - m_baseHWBalance;
}
// A;8 >1ICN ?@81K;L 15@Q< >B=>A8B5;L=> =082KAH53> 10;0=A0 8;8 A@54AB2, B>
if(m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_MONEY_HW_EQ_BAL
|| m_calcOverallLossLimit == RM_CALC_OVERALL_LOSS_PERCENT_HW_EQ_BAL) {
// 5@5AG8B05< 5Q
m_overallProfit = m_equity - m_baseHWEquityBalance;
}
// "5:CI0O ?@81K;L 28@BC0;L=KE >B:@KBKE ?>78F89
m_virtualProfit = VirtualProfit();
// 07 2 G0A 2K2>48< 7=0G5=8O 2 ;>3
if(IsNewBar(Symbol(), PERIOD_H1)) {
PrintFormat(__FUNCTION__" | Virtual = %.2f | Profit = %.2f | Daily = %.2f | Overall = %.2f"
" | depoPart = %.2f = %.2f * %.2f * %.2f",
m_virtualProfit, m_profit, m_dailyProfit, m_overallProfit,
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
}
}
//+------------------------------------------------------------------+
//| 1=>2;5=85 4=52=KE 107>2KE C@>2=59 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::UpdateBaseLevels() {
// 1=>2;O5< 10;0=A, A@54AB20 8 107>2K9 4=52=>9 C@>25=L
m_baseDailyBalance = m_balance;
m_baseDailyEquity = m_equity;
m_baseDailyLevel = MathMax(m_baseDailyBalance, m_baseDailyEquity);
m_dailyProfit = m_equity - m_baseDailyLevel;
PrintFormat(__FUNCTION__" | DAILY UPDATE: Balance = %.2f | Equity = %.2f | Level = %.2f"
" | depoPart = %.2f = %.2f * %.2f * %.2f",
m_baseDailyBalance, m_baseDailyEquity, m_baseDailyLevel,
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
// A;8 @0=55 1K; 4>AB83=CB 4=52=>9 C@>25=L C1KB:0, B>
if(m_state == RM_STATE_DAILY_LOSS) {
// 5@5E>48< 2 A>AB>O=85 2>AAB0=>2;5=8O @07<5@>2 >B:@KBKE ?>78F89
m_state = RM_STATE_RESTORE;
// 0?><8=05< 2@5<O =0G0;0 2>AAB0=>2;5=8O
m_startRestoreTime = TimeCurrent();
}
}
//+------------------------------------------------------------------+
//| @>25@:0 ;8<8B>2 C1KB:0 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::CheckLimits() {
if(false
|| CheckDailyLossLimit() // @>25@:0 4=52=>3> ;8<8B0
|| CheckOverallLossLimit() // @>25@:0 >1I53> ;8<8B0
|| CheckOverallProfitLimit() // @>25@:0 >1I59 ?@81K;8
) {
// 0?><8=05< B5:CI89 C@>25=L 28@BC0;L=>9 ?@81K;8
m_lastVirtualProfit = m_virtualProfit;
// ?>25I05< ?>;CG0B5;L >1 87<5=5=8OE
CVirtualReceiver::Instance().Changed();
}
}
//+------------------------------------------------------------------+
//| @>25@:0 4=52=>3> ;8<8B0 C1KB:0 |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::CheckDailyLossLimit() {
// A;8 4>AB83=CB 4=52=>9 C1KB>: 8 ?>78F88 5IQ >B:@KBK
if(m_dailyProfit < -DailyLoss() * (1 - m_dailyDepoPart * (1 - m_closeDailyPart))
&& CMoney::DepoPart() > 0) {
// #<5=LH05< <=>68B5;L 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 ?> 4=52=><C C1KB:C
m_dailyDepoPart *= (1 - m_closeDailyPart);
// A;8 <=>68B5;L C65 A;8H:>< <0;, B>
if(m_dailyDepoPart < 0.05) {
// #AB0=02;8205< 53> 2 0
m_dailyDepoPart = 0;
}
// #AB0=02;8205< 7=0G5=85 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0
SetDepoPart();
PrintFormat(__FUNCTION__" | VirtualProfit = %.2f | Profit = %.2f | Daily Profit = %.2f",
m_virtualProfit, m_profit, m_dailyProfit);
PrintFormat(__FUNCTION__" | RESET: depoPart = %.2f = %.2f * %.2f * %.2f",
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
// #AB0=02;8205< @8A:-<5=5465@ 2 A>AB>O=85 4>AB83=CB>3> 4=52=>3> C1KB:0
m_state = RM_STATE_DAILY_LOSS;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| @>25@:0 >1I53> ;8<8B0 C1KB:0 |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::CheckOverallLossLimit() {
// A;8 4>AB83=CB >1I89 C1KB>: 8 ?>78F88 5IQ >B:@KBK
if(m_overallProfit < -OverallLoss() * (1 - m_overallDepoPart * (1 - m_closeOverallPart))
&& CMoney::DepoPart() > 0) {
// #<5=LH05< <=>68B5;L 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 ?> >1I5<C C1KB:C
m_overallDepoPart *= (1 - m_closeOverallPart);
// A;8 <=>68B5;L C65 A;8H:>< <0;, B>
if(m_overallDepoPart < 0.05) {
// #AB0=02;8205< 53> 2 0
m_overallDepoPart = 0;
// #AB0=02;8205< @8A:-<5=5465@ 2 A>AB>O=85 4>AB83=CB>3> >1I53> C1KB:0
m_state = RM_STATE_OVERALL_LOSS;
}
// #AB0=02;8205< 7=0G5=85 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0
SetDepoPart();
PrintFormat(__FUNCTION__" | VirtualProfit = %.2f | Profit = %.2f | Daily Profit = %.2f",
m_virtualProfit, m_profit, m_dailyProfit);
PrintFormat(__FUNCTION__" | RESET: depoPart = %.2f = %.2f * %.2f * %.2f",
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| @>25@:0 4>AB865=8O 7040==>9 ?@81K;8 |
//+------------------------------------------------------------------+
bool CVirtualRiskManager::CheckOverallProfitLimit() {
// A;8 4>AB83=CB >1I89 C1KB>: 8 ?>78F88 5IQ >B:@KBK
if(m_overallProfit >= OverallProfit() && CMoney::DepoPart() > 0) {
// #<5=LH05< <=>68B5;L 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 ?> >1I5<C C1KB:C
m_overallDepoPart = 0;
// #AB0=02;8205< @8A:-<5=5465@ 2 A>AB>O=85 4>AB83=CB>9 >1I59 ?@81K;8
m_state = RM_STATE_OVERALL_PROFIT;
// #AB0=02;8205< 7=0G5=85 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0
SetDepoPart();
PrintFormat(__FUNCTION__" | VirtualProfit = %.2f | Profit = %.2f | Daily Profit = %.2f",
m_virtualProfit, m_profit, m_dailyProfit);
PrintFormat(__FUNCTION__" | RESET: depoPart = %.2f = %.2f * %.2f * %.2f",
m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart,
m_baseDepoPart, m_dailyDepoPart, m_overallDepoPart);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| ?@545;5=85 ?@81K;8 >B:@KBKE 28@BC0;L=KE ?>78F89 |
//+------------------------------------------------------------------+
double CVirtualRiskManager::VirtualProfit() {
// 1@0I05<AO : >1J5:BC ?>;CG0B5;O
CVirtualReceiver *m_receiver = CVirtualReceiver::Instance();
// #AB0=02;8205< 8AE>4=K9 <=>68B5;L 8A?>;L7>20=8O 10;0=A0
CMoney::DepoPart(m_baseDepoPart);
double profit = 0;
// ;O 2A5E 28@BC0;L=KE ?>78F89 =0E>48< AC<<C 8E ?@81K;8
FOR(m_receiver.OrdersTotal()) profit += CMoney::Profit(m_receiver.Order(i));
// >AAB0=02;8205< B5:CI89 <=>68B5;L 8A?>;L7>20=8O 10;0=A0
SetDepoPart();
return profit;
}
//+------------------------------------------------------------------+
//| ?@545;5=85 ?@81K;8 28@BC0;L=KE ?>78F89 4;O 2>AAB0=>2;5=8O |
//+------------------------------------------------------------------+
double CVirtualRiskManager::RestoreVirtualProfit() {
// A;8 <0:A8<0;L=>5 2@5<O 2>AAB0=>2;5=8O =5 7040=>, B>
if(m_maxRestoreTime == 0) {
// >72@0I05< B5:CI55 7=0G5=85 28@BC0;L=>9 ?@81K;8
return m_virtualProfit;
}
// 0E>48< ?@>H54H55 2@5<O A =0G0;0 2>AAB0=>2;5=8O 2 <8=CB0E
double t = (TimeCurrent() - m_startRestoreTime) / 60.0;
// >72@0I05< @0AGQB=>5 7=0G5=85 65;05<>9 28@BC0;L=>9 ?@81K;8
// 2 7028A8<>AB8 >B ?@>H54H53> 2@5<5=8 A =0G0;0 2>AAB0=>2;5=8O
return m_lastVirtualProfit * m_lastVirtualProfitFactor * (1 - t / m_maxRestoreTime);
}
//+------------------------------------------------------------------+
//| #AB0=>2:0 7=0G5=8O 8A?>;L7C5<>9 G0AB8 >1I53> 10;0=A0 |
//+------------------------------------------------------------------+
void CVirtualRiskManager::SetDepoPart() {
CMoney::DepoPart(m_baseDepoPart * m_dailyDepoPart * m_overallDepoPart);
}
//+------------------------------------------------------------------+
//| @5>1@07>20=85 >1J5:B0 2 AB@>:C |
//+------------------------------------------------------------------+
string CVirtualRiskManager::operator~() {
return StringFormat("%s(%s)", typename(this), m_params);
}
//+------------------------------------------------------------------+