- Implemented sqx_audit.py to audit StrategyQuant X trade lists, focusing on performance metrics and cost analysis. - Created sqx_portfolio.py to evaluate portfolio performance based on uncorrelated components and their impact on risk and return. - Developed swing.py to analyze cost ratios across different holding periods and assess swing trading structures. - Introduced test_management.py to investigate the effectiveness of exit rules on random entries and their impact on expectancy.
56 lines
3.3 KiB
MQL5
56 lines
3.3 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| SignalRiskGuard.mqh |
|
|
//| AnimateDread |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "AnimateDread"
|
|
#property link "https://www.mql5.com"
|
|
#include "..\Expert\ExpertSignalCustom.mqh"
|
|
#include "..\Variables\RiskBudget.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| Class CSignalRiskGuard. |
|
|
//| Vetoes new entries (the EMPTY_VALUE convention every other filter |
|
|
//| here uses, via the composite Direction()) whenever the account's |
|
|
//| loss budget is exhausted. |
|
|
//| |
|
|
//| This class USED TO OWN the whole mechanism - thresholds, day-start|
|
|
//| balance, peak equity, its own state file. It no longer does, and |
|
|
//| the reason is that a CExpertSignal filter is the wrong place for |
|
|
//| an account-level hard limit: |
|
|
//| |
|
|
//| * Direction() is called by the signal pipeline, and with the |
|
|
//| shipped Expert_EveryTick=false that is ONCE PER BAR at the bar|
|
|
//| open. A 4% daily limit checked once an hour on H1 is not a |
|
|
//| limit. The budget is now evaluated from OnTick()/OnTimer() |
|
|
//| (Variables\RiskBudget.mqh), at quote frequency, whatever |
|
|
//| timeframe the signals run on. |
|
|
//| * A veto can only decline to OPEN. It cannot size a trade to |
|
|
//| fit the remaining allowance, and it cannot act on a position |
|
|
//| that is already running toward the limit. Both of those now |
|
|
//| live in CRiskBudget, which the money manager consults before |
|
|
//| every lot-size calculation. |
|
|
//| |
|
|
//| What remains here is the entry veto alone - kept because the |
|
|
//| composite-Direction convention is how every other filter blocks a |
|
|
//| trade, so the journal, the panel and the vote arithmetic all |
|
|
//| behave consistently when the budget halts trading. |
|
|
//+------------------------------------------------------------------+
|
|
class CSignalRiskGuard : public CExpertSignalCustom
|
|
{
|
|
public:
|
|
virtual double Direction(void);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| CRiskBudget::Update() has already run this tick (OnTick calls it |
|
|
//| before Expert.OnTick()), so this is a pure read - no account |
|
|
//| queries, no file I/O, nothing that costs anything per bar. |
|
|
//+------------------------------------------------------------------+
|
|
double CSignalRiskGuard::Direction(void)
|
|
{
|
|
if(!g_riskBudget.Enabled())
|
|
return 0.0; // permanent no-op, same convention as the other disabled filters
|
|
if(g_riskBudget.Halted())
|
|
return EMPTY_VALUE; // veto: the composite Direction() turns this into "no new entries"
|
|
return 0.0;
|
|
}
|
|
//+------------------------------------------------------------------+
|