//+------------------------------------------------------------------+ //| Strategy.mqh | //| Copyright 2016, Vasiliy Sokolov, St-Petersburg, Russia | //| https://www.mql5.com/ru/users/c-4 | //+------------------------------------------------------------------+ #property copyright "Copyright 2016, Vasiliy Sokolov." #property link "https://www.mql5.com/ru/users/c-4" #property strict #define SOURCE ("ID " + (string)ExpertMagic() + " " + __FUNCTION__) #include #include "XML\XMLBase.mqh" // Работа с XML #include "Logs.mqh" // Логирование #ifdef __HT__ #include "Position.mqh" #else #include "PositionMT5.mqh" // Класс обыкновенных позиций #endif #include "TradeEnvironment.mqh" // Класс для детектирования изменений торгового окружения #include "NewBarDetector.mqh" // Определитель нового бара #include "NewTickDetector.mqh" // Определитель нового тика #include "Series.mqh" // Предоставляет удобный доступ к OHLCV серии данных #include "TradeControl.mqh" // Торговый модуль с дополнительными методами контроля за открытыми позициями #include "TradeState.mqh" // Торговый модуль с дополнительными методами контроля за открытыми позициями #include "MoneyManagment.mqh" #include "PendingOrders.mqh" #include "Symbol.mqh" //+------------------------------------------------------------------+ //| Определяет тип рыночного события. | //+------------------------------------------------------------------+ enum ENUM_MARKET_EVENT_TYPE { MARKET_EVENT_TICK, // Приход нового тика по текущему инструменту MARKET_EVENT_BAR_OPEN, // Открытие нового бара по текущему инструменту MARKET_EVENT_TIMER, // Срабатывание таймера MARKET_EVENT_BOOK_EVENT // Изменение стакана (в т.ч. приход тика). }; //+------------------------------------------------------------------+ //| Параметры события, которое повлекло вызов метода. | //+------------------------------------------------------------------+ struct MarketEvent { ENUM_MARKET_EVENT_TYPE type; // Тип события. ENUM_TIMEFRAMES period; // Период графика, к которому относится событие (только для MARKET_EVENT_BAR_OPEN). string symbol; // Название инструмента, по которому произошло событие. Для всех событий, кроме // MARKET_EVENT_BOOK_EVENT, название инструмента соответствует текущему инструменту. }; //+------------------------------------------------------------------+ //| Основная статистика по открытым позициям стратегии (экземпляра) | //+------------------------------------------------------------------+ struct PositionsStat { int open_buy; // Всего открытых позиций стратегии на покупку int open_sell; // Всего открытых позиций стратегии на продажу int open_total; // Общее количество открытых позиций стратегии int open_complex; // Всего комплексных позиций, которые принадлежат данной стратегии }; //+------------------------------------------------------------------+ //| Базовый класс стратегии-прослойки. | //+------------------------------------------------------------------+ class CStrategy : public CObject { private: MarketEvent m_event; // Последнее или текущее рыночное событие. ulong m_last_changed; // Последнее время изменения торгового окружения в микросекундах с момента запуска. uint m_expert_magic; // Уникальный идентификатор эксперта. string m_expert_name; // Имя эксперта. string m_expert_symbol; // Рабочий инструмент эксперта ENUM_TIMEFRAMES m_timeframe; // Таймфрейм стратегии ENUM_TRADE_STATE m_trade_state; // Торговое состояние эксперта. CTradeEnvironment m_environment; // Торговое окружение портфеля. CArrayObj m_bars_detectors; // Содержат определители новых баров. CArrayObj m_ticks_detectors; // Содержит определители новых тиков. void RebuildPositions(void); void CallInit(const MarketEvent &event); void CallSupport(const MarketEvent &event); void SpyEnvironment(void); virtual void ExitByStopRegim(CPosition *pos); void NewBarsDetect(void); void NewTickDetect(void); void RecalcStatistic(PositionsStat &positions); int LastWorkExpDay(MqlDateTime &dt); protected: bool m_multi_symbols; CTradeState m_state; // Возвращает торговое состояние. CArrayObj ActivePositions; // Список ОБЩИХ активных классических позиций. CArrayObj ComplexPositions; // Список ОБЩИХ комплексных позиций состоящий из множества классических позиций PositionsStat positions; // Статистика по позициям стратегии CTradeControl Trade; // Торговый класс (сам CStrategy не обладает торговой логикой). CArrayObj Modules; // Дополнительные модули сопровождения static CLog* Log; // Логирование эксперта string GetCurrentContract(string symbol); bool CheckCurrentSL(double sl,ENUM_POSITION_TYPE type); COrdersEnvironment PendingOrders; /* Подписка на события "открытие нового бара" и "образование нового тика" */ bool AddBarOpenEvent(string symbol,ENUM_TIMEFRAMES timeframe); bool AddTickEvent(string symbol); void CheckVolumes(void); /* Эксперт должен самостоятельно перестоить свои индикаторы при смене инструмента и таймфрейма, для чего он должен отслеживать соответствующие события */ virtual void OnSymbolChanged(string symbol); virtual void OnTimeframeChanged(ENUM_TIMEFRAMES tf); /* Торговые функции, которые необходимо переопределить */ virtual void InitBuy(const MarketEvent &event); virtual void InitSell(const MarketEvent &event); virtual void InitComplexPos(const MarketEvent &event); virtual void SupportBuy(const MarketEvent &event,CPosition *pos); virtual void SupportSell(const MarketEvent &event,CPosition *pos); virtual void SupportPendingBuy(const MarketEvent &event, CPendingOrder* order); virtual void SupportPendingSell(const MarketEvent &event, CPendingOrder* order); virtual void OnEvent(const MarketEvent& event); virtual bool IsTrackEvents(const MarketEvent &event); int PositionsTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0); int OrdersTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0); int OrdersTotal(ENUM_ORDER_TYPE order_type, string symbol="", int magic = 0); public: CMoneyManagment MM; // Модуль управления капиталом CTrailing* Trailing; // Модуль управления трейлинг-стопом для всех позиций CStrategy(void); CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf); ~CStrategy(void); /*Общие свойства*/ static CStrategy *GetStrategy(string name); CSymbol WS; virtual bool ParseXmlParams(CXmlElement *params); uint ExpertMagic(void); void ExpertMagic(uint ExpertMagic); string ExpertName(void); void ExpertName(string name); virtual string ExpertNameFull(void); string ExpertSymbol(); void ExpertSymbol(string symbol); void Timeframe(ENUM_TIMEFRAMES period); ENUM_TIMEFRAMES Timeframe(void); ENUM_TRADE_STATE TradeState(void); void TradeState(ENUM_TRADE_STATE state); /*Управление из вне*/ void Buy(double vol); void Sell(double vol); /*Передача событий*/ virtual bool OnInit(void); void OnTick(void); void OnTimer(void); void OnBookEvent(string symbol); virtual void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result){;} virtual int Compare(const CObject *node,const int mode=0) const; }; /*Размещение статических переменных*/ CLog *CStrategy::Log; //+------------------------------------------------------------------+ //| Базовый класс стратегии-прослойки. | //+------------------------------------------------------------------+ CStrategy::CStrategy(void) { m_multi_symbols = false; m_last_changed = 0; m_expert_magic = 0; m_timeframe=PERIOD_CURRENT; Log=CLog::GetLog(); WS.Name(Symbol()); WS.Period(Period()); } //+------------------------------------------------------------------+ //| Базовый класс с обязательными параметрами. | //+------------------------------------------------------------------+ CStrategy::CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf) : WS(symbol, tf) { m_multi_symbols = false; m_last_changed=0; Log=CLog::GetLog(); ExpertSymbol(symbol); ExpertName(exp_name); Timeframe(tf); ExpertMagic(magic); } //+------------------------------------------------------------------+ //| Диструктор. Удаляет модуль трейлинг-стопа в случае использования | //+------------------------------------------------------------------+ CStrategy::~CStrategy(void) { if(CheckPointer(Trailing)!=POINTER_INVALID) delete Trailing; } //+------------------------------------------------------------------+ //| Если рабочий символ изменился, эксперту необходимо самостоятельно| //| перестроить свои индикаторы и другие внутренние данные на работу | //| с этим символом, для чего переопределить данный обработчик | //| изменения символа | //+------------------------------------------------------------------+ void CStrategy::OnSymbolChanged(string symbol) { } //+------------------------------------------------------------------+ //| Если рабочий таймфрейм изменился, эксперту необходимо | //| самостоятельно перестроить свои индикаторы и другие внутренние | //| данные на работу с этим таймфреймом, для чего переопределить | //| данный обработчик изменения таймфрейма | //+------------------------------------------------------------------+ void CStrategy::OnTimeframeChanged(ENUM_TIMEFRAMES tf) { } //+------------------------------------------------------------------+ //| Переопределите метод правилами стратегии, при выполнении которых | //| необходимо открыть ДЛИННУЮ позицию. Само открытие позиции также | //| необходимо выполнить прямо в этом методе. | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //+------------------------------------------------------------------+ void CStrategy::InitBuy(const MarketEvent &event) { } //+------------------------------------------------------------------+ //| Переопределите метод правилами стратегии, при выполнении которых | //| необходимо открыть КОРОТКУЮ позицию. Само открытие позиции также | //| необходимо выполнить прямо в этом методе. | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //+------------------------------------------------------------------+ void CStrategy::InitSell(const MarketEvent &event) { } //+------------------------------------------------------------------+ //| Переопределите метод правилами стратегии, при выполнении которых | //| необходимо открыть КОМПЛЕКСНУЮ (или арбитражную) позицию. | //| Само открытие позиции также необходимо выполнить | //| прямо в этом методе. | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //+------------------------------------------------------------------+ void CStrategy::InitComplexPos(const MarketEvent &event) { } //+------------------------------------------------------------------+ //| Переопределите метод правилами стратегии, при выполнении которых | //| необходимо закрыть ДЛИННУЮ позицию, переданную в качестве второго| //| параметра. Само закрытие позиции также необходимо выполнить | //| прямо в этом методе. | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //| pos - позиция, управление которой требуется произвести. | //+------------------------------------------------------------------+ void CStrategy::SupportBuy(const MarketEvent &event,CPosition *pos) { } //+------------------------------------------------------------------+ //| Переопределите метод правилами стратегии, при выполнении которых | //| необходимо закрыть КОРОТКУЮ позицию,переданную в качестве второго| //| параметра. Само закрытие позиции также необходимо выполнить | //| прямо в этом методе. | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //| pos - позиция, управление которой требуется произвести. | //+------------------------------------------------------------------+ void CStrategy::SupportSell(const MarketEvent &event,CPosition *pos) { } //+------------------------------------------------------------------+ //| Переопределите данный метод для последовательного сопровождения | //| отложенного ордера на покупку | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //| order - позиция, управление которой требуется произвести. | //+------------------------------------------------------------------+ void CStrategy::SupportPendingBuy(const MarketEvent &event, CPendingOrder *order) { } //+------------------------------------------------------------------+ //| Переопределите данный метод для последовательного сопровождения | //| отложенного ордера на продажу | //| IN: | //| event - структура, описывающая событие, при получении | //| которого произошел вызов этого метода. | //| order - позиция, управление которой требуется произвести. | //+------------------------------------------------------------------+ void CStrategy::SupportPendingSell(const MarketEvent &event, CPendingOrder *order) { } //+------------------------------------------------------------------+ //| Общее событие OnEvent. Вызывается при получении любого события | //| независимо от торгового режима и настроек эксперта. | //+------------------------------------------------------------------+ void CStrategy::OnEvent(const MarketEvent &event) { } //+------------------------------------------------------------------+ //| Отфильтровывает поступающие события. Если переданное событие | //| не обрабатывается стратегией, возвращает ложь, если обрабатыва- | //| ется - возвращает истину. | //+------------------------------------------------------------------+ bool CStrategy::IsTrackEvents(const MarketEvent &event) { //Обрабатываем только открытие нового бара на рабочем инструменте и таймфрейме if(event.type != MARKET_EVENT_BAR_OPEN)return false; if(event.period != Timeframe())return false; if(event.symbol != ExpertSymbol())return false; return true; } //+------------------------------------------------------------------+ //| Делегирует дочерней стратегии парсинг ее специфических | //| параметров, обнаруженных в секции | //+------------------------------------------------------------------+ bool CStrategy::ParseXmlParams(CXmlElement *xmlParams) { string text="Found specific xml-settings, but "+ExpertName()+" strategy does not handle them. Override the method ParseXmlParams"; CMessage *msg=new CMessage(MESSAGE_WARNING,SOURCE,text); Log.AddMessage(msg); return false; } //+------------------------------------------------------------------+ //| Устанавливает уникальный идентфикатор эксперта. | //+------------------------------------------------------------------+ void CStrategy::ExpertMagic(uint ExpertMagic) { m_expert_magic=ExpertMagic; Trade.SetExpertMagicNumber(m_expert_magic); } //+------------------------------------------------------------------+ //| Возвращает уникальный идентификатор эксперта. | //+------------------------------------------------------------------+ uint CStrategy::ExpertMagic(void) { return m_expert_magic; } //+------------------------------------------------------------------+ //| Возвращает Имя эксперта (имя эксперта должно быть предварительно | //| установленно самим экспертом с помощью одноименного метода). | //+------------------------------------------------------------------+ string CStrategy::ExpertName(void) { return m_expert_name; } //+------------------------------------------------------------------+ //| С помощью этого метода эксперт устанавливает свое имя. | //+------------------------------------------------------------------+ void CStrategy::ExpertName(string name) { m_expert_name=name; } //+------------------------------------------------------------------+ //| Возвращает полное (уникальное имя эксперта). | //| (Этот метод необходимо переопределить в производном классе) | //+------------------------------------------------------------------+ string CStrategy::ExpertNameFull(void) { return ExpertName(); } //+------------------------------------------------------------------+ //| Возвращает рабочий инструмент эксперта. | //+------------------------------------------------------------------+ string CStrategy::ExpertSymbol(void) { if(m_expert_symbol==NULL || m_expert_symbol=="") return _Symbol; return m_expert_symbol; } //+------------------------------------------------------------------+ //| Устанавливает рабочий инструмент эксперта. | //+------------------------------------------------------------------+ void CStrategy::ExpertSymbol(string symbol) { m_expert_symbol=GetCurrentContract(symbol); OnSymbolChanged(m_expert_symbol); WS.Name(symbol); } //+------------------------------------------------------------------+ //| Вызывается менеджером стратегий при наступлении системного | //| события 'новый тик'. | //+------------------------------------------------------------------+ void CStrategy::OnTick(void) { NewTickDetect(); NewBarsDetect(); } //+------------------------------------------------------------------+ //| Это событие вызывается при добавлении стратегии в список | //| стратегий. Подразумевается, что в момент вызова этой функции, | //| все базовые параметры эксперта, такие как название симовола, | //| магический номер и тайфрем будут установлены. И эксперт сможет | //| сконфигурировать в этом методе свои внутренние данные. | //| В случае, если OnInit стратегии вернет false, стратегия не будет | //| добавлена в список. | //+------------------------------------------------------------------+ bool CStrategy::OnInit(void) { return true; } //+------------------------------------------------------------------+ //| Вызывается менеджером стратегий при наступлении системного | //| события 'OnTimer'. | //+------------------------------------------------------------------+ void CStrategy::OnTimer(void) { m_event.symbol=Symbol(); m_event.type=MARKET_EVENT_TIMER; m_event.period=(ENUM_TIMEFRAMES)Period(); OnEvent(m_event); CallSupport(m_event); CallInit(m_event); NewTickDetect(); NewBarsDetect(); } //+------------------------------------------------------------------+ //| Вызывается менеджером стратегий при наступлении системного | //| события 'OnBookEvent'. | //+------------------------------------------------------------------+ void CStrategy::OnBookEvent(string symbol) { m_event.symbol=symbol; m_event.type=MARKET_EVENT_BOOK_EVENT; m_event.period=PERIOD_CURRENT; OnEvent(m_event); CallSupport(m_event); CallInit(m_event); NewTickDetect(); NewBarsDetect(); } //+------------------------------------------------------------------+ //| Покупает от имени эксперта объем vol | //+------------------------------------------------------------------+ void CStrategy::Buy(double vol) { Trade.Buy(vol,ExpertSymbol(),"hand buy"); } //+------------------------------------------------------------------+ //| Продаем от имени эксперта объем vol | //+------------------------------------------------------------------+ void CStrategy::Sell(double vol) { Trade.Sell(vol,ExpertSymbol(),"hand sell"); } //+------------------------------------------------------------------+ //| Возвращает текущее торговое состояние эксперта. | //+------------------------------------------------------------------+ ENUM_TRADE_STATE CStrategy::TradeState(void) { return m_trade_state; } //+------------------------------------------------------------------+ //| Устанавливает текущее торговое состояние эксперта. | //+------------------------------------------------------------------+ void CStrategy::TradeState(ENUM_TRADE_STATE state) { if(state!=m_state.GetTradeState()) { m_state.SetTradeState(D'00:00', D'23:59', ALL_DAYS_OF_WEEK, state); string text="The mode of the current strategy has been changed to "+EnumToString(m_state.GetTradeState())+ ". The changes will come into force at receipt of new events"; CMessage *msg=new CMessage(MESSAGE_INFO,SOURCE,text); Log.AddMessage(msg); } } //+------------------------------------------------------------------+ //| Вызывает логику открытия позиции при условии, что торговое | //| состояние явно не запрещает этого делать. | //+------------------------------------------------------------------+ void CStrategy::CallInit(const MarketEvent &event) { m_trade_state=m_state.GetTradeState(); if(m_trade_state == TRADE_STOP)return; if(m_trade_state == TRADE_WAIT)return; if(m_trade_state == TRADE_NO_NEW_ENTRY)return; SpyEnvironment(); InitComplexPos(event); if(m_trade_state==TRADE_BUY_AND_SELL || m_trade_state==TRADE_BUY_ONLY) InitBuy(event); if(m_trade_state==TRADE_BUY_AND_SELL || m_trade_state==TRADE_SELL_ONLY) InitSell(event); } //+------------------------------------------------------------------+ //| Вызывает логику сопровождения позиций при условии, что торговое | //| состояние не равно TRADE_WAIT. | //+------------------------------------------------------------------+ void CStrategy::CallSupport(const MarketEvent &event) { m_trade_state=m_state.GetTradeState(); if(m_trade_state == TRADE_WAIT)return; SpyEnvironment(); // Управление активными позициями for(int i=ActivePositions.Total()-1; i>=0; i--) { CPosition *pos=ActivePositions.At(i); if(pos.ExpertMagic()!=m_expert_magic)continue; if(!m_multi_symbols && pos.Symbol()!=ExpertSymbol())continue; if(CheckPointer(Trailing)!=POINTER_INVALID) { if(CheckPointer(pos.Trailing)==POINTER_INVALID) { pos.Trailing = Trailing.Copy(); pos.Trailing.SetPosition(pos); } pos.Trailing.Modify(); if(!pos.IsActive()) continue; } if(pos.Direction()==POSITION_TYPE_BUY) SupportBuy(event,pos); else SupportSell(event,pos); if(m_trade_state==TRADE_STOP && pos.IsActive()) ExitByStopRegim(pos); } // Удаление отложенных ордеров при смене режима if(PendingOrders.Total() > 0 && (m_trade_state == TRADE_STOP || m_trade_state == TRADE_BUY_ONLY || m_trade_state == TRADE_SELL_ONLY)) { for(int p = PendingOrders.Total()-1; p >= 0; p--) { CPendingOrder* pend = PendingOrders.GetOrder(p); if(!pend.IsMain(ExpertSymbol(), ExpertMagic()))continue; bool needDelete = m_trade_state == TRADE_STOP; // SELL_ONLY - удаляем отложенные ордера на покупку if(!needDelete) { needDelete = m_trade_state == TRADE_SELL_ONLY && (pend.Type() == ORDER_TYPE_BUY_STOP || pend.Type() == ORDER_TYPE_BUY_LIMIT); } // BUY_ONLY - удаляем отложенные ордера на продажу if(!needDelete) { needDelete = m_trade_state == TRADE_BUY_ONLY && (pend.Type() == ORDER_TYPE_SELL_STOP || pend.Type() == ORDER_TYPE_SELL_LIMIT); } if(needDelete) pend.Delete(); } } for(int i = PendingOrders.Total()-1; i >= 0; i--) { CPendingOrder* order = PendingOrders.GetOrder(i); if(order.ExpertMagic()!=m_expert_magic)continue; if(order.Direction() == POSITION_TYPE_BUY) SupportPendingBuy(event, order); else SupportPendingSell(event, order); } } //+------------------------------------------------------------------+ //| Отслеживает изменение торгового окружения. | //+------------------------------------------------------------------+ void CStrategy::SpyEnvironment(void) { if(m_environment.ChangeEnvironment()) { //printf(ExpertNameFull()+". Trading environment has changed. Rebuild the environment"); RebuildPositions(); RecalcStatistic(positions); m_environment.RememberEnvironment(); } } //+------------------------------------------------------------------+ //| Пересчитывает статистику позиций и заполняет соответствующую | //| структуру. | //+------------------------------------------------------------------+ void CStrategy::RecalcStatistic(PositionsStat &pos) { pos.open_buy=0; pos.open_sell=0; pos.open_total=0; pos.open_complex=0; for(int i=0; i=14) || dt.mon==1 || dt.mon==2 || (dt.mon==3 && dt.day<14)) { mon=3; year=dt.year+1; } if((dt.mon==3 && dt.day>=14) || dt.mon==4 || dt.mon==5 || (dt.mon==6 && dt.day<14)) { mon=6; year=dt.year; } if((dt.mon==6 && dt.day>=14) || dt.mon==7 || dt.mon==8 || (dt.mon==9 && dt.day<14)) { mon=9; year=dt.year; } if((dt.mon==9 && dt.day>=14) || dt.mon==10 || dt.mon==11 || (dt.mon==12 && dt.day<14)) { mon=12; year=dt.year; } if(mon==0 || year==0) { string text="The current date is outside the execution of futures"; CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,text); return NULL; } //Пробуем сгенерировать инструмент и получить по нему данные string full_symbol=symbol+"-"+(string)mon+"."+StringSubstr((string)year,2); if(!SymbolInfoInteger(full_symbol,SYMBOL_SELECT)) { string text="Symbol "+symbol+" is not not selected in market watch. Check the name of the instrument"; CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,text); Log.AddMessage(msg); return NULL; } return full_symbol; } //+------------------------------------------------------------------+ //| Переопределяет сравнение по маджику | //+------------------------------------------------------------------+ int CStrategy::Compare(const CObject *obj,const int mode=0)const { const CStrategy *str=obj; if(m_expert_magic > str.m_expert_magic)return 1; if(m_expert_magic < str.m_expert_magic)return -1; return 0; } //+------------------------------------------------------------------+ //| Возвращает общее количество позиций по заданному критерию | //+------------------------------------------------------------------+ int CStrategy::PositionsTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0) { int total = 0; for(int i = 0; i < ActivePositions.Total(); i++) { CPosition* pos = ActivePositions.At(i); if(magic != 0 && magic != pos.ExpertMagic())continue; if(symbol != "" && symbol != pos.Symbol())continue; if(pos.Direction() != pos_type)continue; total++; } return total; } //+------------------------------------------------------------------+ //| Возвращает общее количество отложенных ордеров, чье направление | //| равно заданному | //+------------------------------------------------------------------+ int CStrategy::OrdersTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0) { int total = 0; for(int i = 0; i < PendingOrders.Total(); i++) { CPendingOrder* order = PendingOrders.GetOrder(i); if(magic != 0 && magic != order.ExpertMagic())continue; if(symbol != "" && symbol != order.Symbol())continue; if(order.Direction() != pos_type)continue; total++; } return total; } //+------------------------------------------------------------------+ //| Возвращает общее количество отложенных ордеров, чей тип | //| равен заданному | //+------------------------------------------------------------------+ int CStrategy::OrdersTotal(ENUM_ORDER_TYPE order_type, string symbol="", int magic = 0) { int total = 0; for(int i = 0; i < PendingOrders.Total(); i++) { CPendingOrder* order = PendingOrders.GetOrder(i); if(magic != 0 && magic != order.ExpertMagic())continue; if(symbol != "" && symbol != order.Symbol())continue; if(order.Type() != order_type)continue; total++; } return total; } #include "StrategiesList.mqh" //+------------------------------------------------------------------+