//+------------------------------------------------------------------+ //| EquityDrawdown.mqh – max drawdown z equity, uzavření při překročení| //+------------------------------------------------------------------+ #property copyright "TestRefactor" #property strict #ifndef __EQUITY_DRAWDOWN_MQH__ #define __EQUITY_DRAWDOWN_MQH__ #include "Context.mqh" #include "Positions.mqh" #include "Logger.mqh" #include //+------------------------------------------------------------------+ //| CEquityDrawdown – sleduje vrchol equity, uzavře vše při X % DD | //+------------------------------------------------------------------+ class CEquityDrawdown { private: SContext m_ctx; CPositions *m_positions; CLogger *m_log; CTrade *m_trade; double m_peakEquity; string m_symbol; public: CEquityDrawdown() : m_positions(NULL), m_log(NULL), m_trade(NULL), m_peakEquity(0), m_symbol("") {} void SetContext(const SContext &ctx) { m_ctx = ctx; } void SetPositions(CPositions *pos) { m_positions = pos; } void SetLogger(CLogger *log) { m_log = log; } void SetTrade(CTrade *trade) { m_trade = trade; } void SetSymbol(string symbol) { m_symbol = symbol; } void CheckAndClose() { if(m_ctx.tradeMode == TRADE_GRID) return; // Grid má vlastní logiku (profit target), DD by ničil akumulaci if(m_ctx.maxEquityDrawdownPct <= 0 || !m_trade || !m_positions) return; double equity = AccountInfoDouble(ACCOUNT_EQUITY); if(equity > m_peakEquity) m_peakEquity = equity; if(m_peakEquity <= 0) return; double drawdownPct = (m_peakEquity - equity) / m_peakEquity * 100.0; if(drawdownPct < m_ctx.maxEquityDrawdownPct) return; m_positions.Refresh(); ulong tickets[]; m_positions.GetTickets(tickets); int n = ArraySize(tickets); if(n == 0) return; for(int j = 0; j < n; j++) m_trade.PositionClose(tickets[j]); m_peakEquity = AccountInfoDouble(ACCOUNT_EQUITY); if(m_log) m_log.Info("Max drawdown " + DoubleToString(m_ctx.maxEquityDrawdownPct, 1) + "% – uzavřeny všechny pozice. Equity drawdown byl " + DoubleToString(drawdownPct, 2) + "%."); } }; #endif