//+------------------------------------------------------------------+ //| Impulse 2.0.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" #include "Strategy\Strategy.mqh" #include "Strategy\Indicators.mqh" input int PeriodMA = 12; input double StopPercent = 0.05; //+------------------------------------------------------------------+ //| Стратегия CImpulse | //+------------------------------------------------------------------+ class CImpulse : public CStrategy { private: double m_percent; // Процент уровня отложенного ордера protected: virtual void InitBuy(const MarketEvent &event); virtual void InitSell(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 bool OnInit(void); public: double GetPercent(void); void SetPercent(double percent); CUnIndicator UnMA; }; //+------------------------------------------------------------------+ //| Инициализируем скользящую среднюю | //+------------------------------------------------------------------+ bool CImpulse::OnInit(void) { UnMA.SetParameter(12); UnMA.SetParameter(0); UnMA.SetParameter(MODE_SMA); UnMA.SetParameter(PRICE_CLOSE); m_percent = StopPercent; if(UnMA.Create(Symbol(), Period(), IND_MA) != INVALID_HANDLE) return true; return false; } //+------------------------------------------------------------------+ //| Установка отложенных ордеров BuyStop | //+------------------------------------------------------------------+ void CImpulse::InitBuy(const MarketEvent &event) { if(!IsTrackEvents(event))return; // Создаем отложенные ордера только на открытии нового бара if(PositionsTotal(POSITION_TYPE_BUY, ExpertSymbol(), ExpertMagic()) > 0) // Не должно быть открыто ни одной длинной позиции return; if(OrdersTotal(POSITION_TYPE_BUY, ExpertSymbol(), ExpertMagic()) > 0) // Не должно быть ни одного отложенного ордера на покупку return; double target = WS.Ask() + WS.Ask()*(m_percent/100.0); // Рассчитываем уровень нового отложенного ордера if(target < UnMA[0]) // Цена срабатывания ордера должна быть выше скользящей средней return; Trade.BuyStop(MM.GetLotFixed(), target, ExpertSymbol(), 0, 0, NULL); // Устанавливаем новый BuyStop ордер } //+------------------------------------------------------------------+ //| Работа с отложенными ордерами BuyStop для открытия длинной | //| позиции | //+------------------------------------------------------------------+ void CImpulse::SupportPendingBuy(const MarketEvent &event,CPendingOrder *order) { if(!IsTrackEvents(event))return; double target = WS.Ask() + WS.Ask()*(m_percent/100.0); // Рассчитываем новый уровень отложенного ордера if(UnMA[0] > target) // Если новый уровень ниже текущей средней order.Delete(); // - удаляем его else // В противном случае модифицируем на новую цену order.Modify(target); } //+------------------------------------------------------------------+ //| Работа с отложенными ордерами SellStop для открытия короткой | //| позиции | //+------------------------------------------------------------------+ void CImpulse::SupportPendingSell(const MarketEvent &event,CPendingOrder* order) { if(!IsTrackEvents(event))return; double target = WS.Ask() - WS.Ask()*(m_percent/100.0); // Рассчитываем новый уровень отложенного ордера if(UnMA[0] < target) // Если новый уровень выше текущей средней order.Delete(); // - удаляем его else // В противном случае модифицируем на новую цену order.Modify(target); } //+------------------------------------------------------------------+ //| Установка отложенных ордеров SellStop | //+------------------------------------------------------------------+ void CImpulse::InitSell(const MarketEvent &event) { if(!IsTrackEvents(event))return; // Создаем отложенные ордера только на открытии нового бара if(PositionsTotal(POSITION_TYPE_SELL, ExpertSymbol(), ExpertMagic()) > 0) // Не должно быть открыто ни одной короткой позиции return; if(OrdersTotal(POSITION_TYPE_SELL, ExpertSymbol(), ExpertMagic()) > 0) // Не должно быть ни одного отложенного ордера на продажу return; double target = WS.Bid() - WS.Bid()*(m_percent/100.0); // Рассчитываем уровень нового отложенного ордера if(target > UnMA[0]) // Цена срабатывания ордера должна быть ниже скользящей средней return; Trade.SellStop(MM.GetLotFixed(), target, ExpertSymbol(), 0, 0, NULL); // Устанавливаем новый BuyStop ордер } //+------------------------------------------------------------------+ //| Сопровождение длинной позиции по скользящей средней Moving | //+------------------------------------------------------------------+ void CImpulse::SupportBuy(const MarketEvent &event,CPosition *pos) { int bar_open = WS.IndexByTime(pos.TimeOpen()); if(!IsTrackEvents(event))return; ENUM_ACCOUNT_MARGIN_MODE mode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); if(mode != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) { double target = WS.Bid() - WS.Bid()*(m_percent/100.0); if(target < UnMA[0]) pos.StopLossValue(target); else pos.StopLossValue(0.0); } if(WS.Bid() < UnMA[0]) pos.CloseAtMarket(); } //+------------------------------------------------------------------+ //| Сопровождение короткой позиции по скользящей средней Moving | //+------------------------------------------------------------------+ void CImpulse::SupportSell(const MarketEvent &event,CPosition *pos) { if(!IsTrackEvents(event))return; ENUM_ACCOUNT_MARGIN_MODE mode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); if(mode != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) { double target = WS.Ask() + WS.Ask()*(m_percent/100.0); if(target > UnMA[0]) pos.StopLossValue(target); else pos.StopLossValue(0.0); } if(WS.Ask() > UnMA[0]) pos.CloseAtMarket(); } //+------------------------------------------------------------------+ //| Возвращает процент пробойного уровня | //+------------------------------------------------------------------+ double CImpulse::GetPercent(void) { return m_percent; } //+------------------------------------------------------------------+ //| Устанавливает процент пробойного уровня | //+------------------------------------------------------------------+ void CImpulse::SetPercent(double percent) { m_percent = percent; } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { CImpulse* impulse = new CImpulse(); impulse.ExpertMagic(140578); impulse.ExpertName("Impulse 2.0"); impulse.Timeframe(Period()); impulse.ExpertSymbol(Symbol()); Manager.AddStrategy(impulse); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { Manager.OnTick(); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { Manager.OnChartEvent(id, lparam, dparam, sparam); ChartRedraw(0); }