//+-------------------------------------------------------------------------------------+ //| Phoenix_Reverse.mq4 | //| Scriptong | //| scriptong@mail.ru | //+-------------------------------------------------------------------------------------+ #property copyright "Scriptong" #property link "scriptong@mail.ru" //---- input parameters extern double Lots = 0.1; extern string A1 = "Параметры быстрой МА"; extern int FastMAPeriod = 8; extern int FastMAShift = 0; extern int FastMAMethod = 0; extern int FastMAPrice = 0; extern string A2 = "=================================="; extern string A3 = "Параметры медленной МА"; extern int SlowMAPeriod = 13; extern int SlowMAShift = 0; extern int SlowMAMethod = 0; extern int SlowMAPrice = 0; extern string A4 = "=================================="; extern string OpenOrderSound = "ok.wav"; extern int MagicNumber = 10012; bool Activate, FreeMarginAlert, FatalError, IsClose; double Tick, Spread, StopLevel, FreezeLevel, MinLot, MaxLot, LotStep; int Signal; datetime LastBar = 0; //+-------------------------------------------------------------------------------------+ //| expert initialization function | //+-------------------------------------------------------------------------------------+ int init() { FatalError = False; Activate = False; IsClose = False; // - 1 - == Сбор информации об условиях торговли ======================================== Tick = MarketInfo(Symbol(), MODE_TICKSIZE); // минимальный тик Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point); // текущий спрэд StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point); // текущий уровень стопов FreezeLevel = ND(MarketInfo(Symbol(), MODE_FREEZELEVEL)*Point); // уровень заморозки MinLot = MarketInfo(Symbol(), MODE_MINLOT); // минимальный разрешенный объем сделки MaxLot = MarketInfo(Symbol(), MODE_MAXLOT); // максимальный разрешенный объем сделки LotStep = MarketInfo(Symbol(), MODE_LOTSTEP); // шаг приращения объема сделки // - 1 - == Окончание блока ============================================================= // - 2 - == Приведение объема сделки к допустимому и проверка корректности объема ======= Lots = LotRound(Lots); // округление объема до ближайшего допустимого // - 2 - == Окончание блока ============================================================= if ((FastMAPeriod == SlowMAPeriod && FastMAShift == SlowMAShift && FastMAMethod == SlowMAMethod && FastMAPrice == SlowMAPrice) || SlowMAPeriod < FastMAPeriod) { Comment("FastМАPeriod должен быть меньше SlowМАPeriod. Советник отключен!"); Print("FastМАPeriod должен быть меньше SlowМАPeriod. Советник отключен!"); return(0); } Activate = True; //---- return(0); } //+-------------------------------------------------------------------------------------+ //| expert deinitialization function | //+-------------------------------------------------------------------------------------+ int deinit() { //---- Comment(""); //---- return(0); } //+-------------------------------------------------------------------------------------+ //| Приведение значений к точности одного тика | //+-------------------------------------------------------------------------------------+ double NP(double A) { return(MathRound(A/Tick)*Tick); } //+-------------------------------------------------------------------------------------+ //| Приведение значений к точности одного тика | //+-------------------------------------------------------------------------------------+ double ND(double A) { return(NormalizeDouble(A, Digits)); } //+-------------------------------------------------------------------------------------+ //| Расшифровка сообщения об ошибке | //+-------------------------------------------------------------------------------------+ string ErrorToString(int Error) { switch(Error) { case 2: return("зафиксирована общая ошибка, обратитесь в техподдержку."); case 5: return("у вас старая версия терминала, обновите ее."); case 6: return("нет связи с сервером, попробуйте перезагрузить терминал."); case 64: return("счет заблокирован, обратитесь в техподдержку."); case 132: return("рынок закрыт."); case 133: return("торговля запрещена."); case 149: return("запрещено локирование."); } } //+-------------------------------------------------------------------------------------+ //| Ожидание торгового потока. Если поток свободен, то результат True, иначе - False | //+-------------------------------------------------------------------------------------+ bool WaitForTradeContext() { int P = 0; // цикл "пока" while(IsTradeContextBusy() && P < 5) { P++; Sleep(1000); } // ------------- if(P == 5) return(False); return(True); } //+-------------------------------------------------------------------------------------+ //| "Правильное" открытие позиции | //| В отличие от OpenOrder проверяет соотношение текущих уровней и устанавливаемых | //| Возвращает: | //| 0 - нет ошибок | //| 1 - Ошибка открытия | //| 2 - Ошибка значения Price | //| 3 - Ошибка значения SL | //| 4 - Ошибка значения TP | //| 5 - Ошибка значения Lot | //+-------------------------------------------------------------------------------------+ int OpenOrderCorrect(int Type, double Price, double SL, double TP, bool Redefinition = True) // Redefinition - при True доопределять параметры до минимально допустимых // при False - возвращать ошибку { // - 1 - == Проверка достаточности свободных средств ==================================== if(AccountFreeMarginCheck(Symbol(), OP_BUY, Lots) <= 0 || GetLastError() == 134) { if(!FreeMarginAlert) { Print("Недостаточно средств для открытия позиции. Free Margin = ", AccountFreeMargin()); FreeMarginAlert = True; } return(5); } FreeMarginAlert = False; // - 1 - == Окончание блока ============================================================= // - 2 - == Корректировка значений Price, SL и TP или возврат ошибки ==================== RefreshRates(); switch (Type) { case OP_BUY: string S = "BUY"; if (MathAbs(Price-Ask)/Point > 3) if (Redefinition) Price = ND(Ask); else return(2); if (ND(TP-Bid) < StopLevel && TP != 0) if (Redefinition) TP = ND(Bid+StopLevel); else return(4); if (ND(Bid-SL) < StopLevel) if (Redefinition) SL = ND(Bid-StopLevel); else return(3); break; case OP_SELL: S = "SELL"; if (MathAbs(Price-Bid)/Point > 3) if (Redefinition) Price = ND(Bid); else return(2); if (ND(Ask-TP) < StopLevel) if (Redefinition) TP = ND(Ask-StopLevel); else return(4); if (ND(SL-Ask) < StopLevel && SL != 0) if (Redefinition) SL = ND(Ask+StopLevel); else return(3); break; case OP_BUYSTOP: S = "BUYSTOP"; if (ND(Price-Ask) < StopLevel) if (Redefinition) Price = ND(Ask+StopLevel); else return(2); if (ND(TP-Price) < StopLevel && TP != 0) if (Redefinition) TP = ND(Price+StopLevel); else return(4); if (ND(Price-SL) < StopLevel) if (Redefinition) SL = ND(Price-StopLevel); else return(3); break; case OP_SELLSTOP: S = "SELLSTOP"; if (ND(Bid-Price) < StopLevel) if (Redefinition) Price = ND(Bid-StopLevel); else return(2); if (ND(Price-TP) < StopLevel) if (Redefinition) TP = ND(Price-StopLevel); else return(4); if (ND(SL-Price) < StopLevel && SL != 0) if (Redefinition) SL = ND(Price+StopLevel); else return(3); break; case OP_BUYLIMIT: S = "BUYLIMIT"; if (ND(Ask-Price) < StopLevel) if (Redefinition) Price = ND(Ask-StopLevel); else return(2); if (ND(TP-Price) < StopLevel && TP != 0) if (Redefinition) TP = ND(Price+StopLevel); else return(4); if (ND(Price-SL) < StopLevel) if (Redefinition) SL = ND(Price-StopLevel); else return(3); break; case OP_SELLLIMIT: S = "SELLLIMIT"; if (ND(Price - Bid) < StopLevel) if (Redefinition) Price = ND(Bid+StopLevel); else return(2); if (ND(Price-TP) < StopLevel) if (Redefinition) TP = ND(Price-StopLevel); else return(4); if (ND(SL-Price) < StopLevel && SL != 0) if (Redefinition) SL = ND(Price+StopLevel); else return(3); break; } // - 2 - == Окончание блока ============================================================= // - 3 - == Открытие ордера с ожидание торгового потока ================================= if(WaitForTradeContext()) // ожидание освобождения торгового потока { Comment("Отправлен запрос на открытие ордера ", S, " ..."); int ticket=OrderSend(Symbol(), Type, Lots, Price, 3, SL, TP, NULL, MagicNumber, 0);// открытие позиции // Попытка открытия позиции завершилась неудачей if(ticket<0) { int Error = GetLastError(); if(Error == 2 || Error == 5 || Error == 6 || Error == 64 || Error == 132 || Error == 133 || Error == 149) // список фатальных ошибок { Comment("Фатальная ошибка при открытии позиции т. к. "+ ErrorToString(Error)+" Советник отключен!"); FatalError = True; } else Comment("Ошибка открытия позиции ", S, ": ", Error); // нефатальная ошибка return(1); } // --------------------------------------------- // Удачное открытие позиции Comment("Позиция ", S, " открыта успешно!"); PlaySound(OpenOrderSound); return(0); // ------------------------ } else { Comment("Время ожидания освобождения торгового потока истекло!"); return(1); } // - 3 - == Окончание блока ============================================================= } //+-------------------------------------------------------------------------------------+ //| Расчет значений средних с формированием сигналов открытия позиций | //+-------------------------------------------------------------------------------------+ void GetSignal() { Signal = 0; // - 1 - ====================== Расчет сигнала №1 ======================================= bool PierceUp = False; bool PierceDown = False; for (int i = 1; i < iBars(Symbol(), PERIOD_D1); i++) { if (iClose(Symbol(), PERIOD_D1, i) > iHigh(Symbol(), PERIOD_D1, i+1)) { PierceUp = True; break; } if (iClose(Symbol(), PERIOD_D1, i) < iLow(Symbol(), PERIOD_D1, i+1)) { PierceDown = True; break; } } if (!PierceUp && !PierceDown) return; // - 1 - ======================= Окончание блока ======================================== // - 2 - ====================== Расчет сигнала №2 ======================================= double Div1 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 1)- iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 1); double Div2 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 2)- iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 2); double Div3 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 3)- iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 3); // - 2 - ======================= Окончание блока ======================================== // - 3 - == Генерация сигнала =========================================================== if (PierceUp) if (Div3 >= Div2 && Div1 > Div2 && Div1 < 0) Signal = -1; // Открытие SELL if (PierceDown) if (Div3 <= Div2 && Div1 < Div2 && Div1 > 0) Signal = 1; // Открытие BUY // - 3 - == Окончание блока ============================================================= } //+-------------------------------------------------------------------------------------+ //| Проверка объема на корректность и округление | //+-------------------------------------------------------------------------------------+ double LotRound(double L) { return(MathRound(MathMin(MathMax(L, MinLot), MaxLot)/LotStep)*LotStep); } //+-------------------------------------------------------------------------------------+ //| Закрывает все позиции типа Type. Если закрыть не удалось, то 1. | //| Если присутствует противоположная, то возвращает 2. В случае успеха 0. | //+-------------------------------------------------------------------------------------+ int CheckOrdersReal(int Type) { for (int i = OrdersTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS)) if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() < 2) // поиск "своей" сделки if(OrderType() == Type) // Если позиция типа Type { if (WaitForTradeContext()) { if(Type == OP_BUY) double Pr = ND(MarketInfo(Symbol(), MODE_BID)); else Pr = ND(MarketInfo(Symbol(), MODE_ASK)); if (!OrderClose(OrderTicket(), OrderLots(), Pr, 3))// то пытаемся закрыть ее return(1); // не удалось закрыть - вернем 1 } else return(1);//вернем 1, если не удалось дождаться освобождения торгового потока } else return(2); // вернем 2, если открыта позиция, противоположная указанной return(0); // если все ОК, то вернем 0 } //+-------------------------------------------------------------------------------------+ //| Функция START эксперта | //+-------------------------------------------------------------------------------------+ int start() { // - 1 - == Разрешено ли советнику работать? =========================================== if (!Activate || FatalError) // Отключается работа советника, если функция return(0); // init завершилась с ошибкой или имела место фатальная ошибка // - 1 - == Окончание блока ============================================================ // - 2 - == Сбор информации об условиях торговли ======================================== Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point); // текщий спрэд StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point); // текущий уровень стопов FreezeLevel = ND(MarketInfo(Symbol(), MODE_FREEZELEVEL)*Point); // уровень заморозки // - 2 - == Окончание блока ============================================================ // - 3 - ======== Обработка существующей позиции и контроль открытия нового бара ======== if (LastBar == Time[0]) return(0); // - 3 - == Окончание блока ============================================================ // - 4 - ======================== Расчет сигнала ======================================== GetSignal(); // - 4 - == Окончание блока ============================================================ // - 5 - == Открытие позиций ============================================================ if (Signal == 1) // Открытие BUY { int Res = CheckOrdersReal(OP_SELL); if (Res == 0) { double SL = NP(MathMin(MathMin(iLow(Symbol(), PERIOD_D1, 1), iLow(Symbol(), PERIOD_D1, 0)), iLow(Symbol(), PERIOD_D1, 2)) - Tick + Spread); double TP = NP(Ask + 4*iATR(Symbol(), 0, 24, 1)); RefreshRates(); if (OpenOrderCorrect(OP_BUY, ND(Ask), SL, TP) != 0) // открытие позиции return(0); // если не удалось открыть, то попытка переносится на следующий тик } if (Res == 1) return(0); } if (Signal == -1) // Открытие SELL { Res = CheckOrdersReal(OP_BUY); if (Res == 0) { SL = NP(MathMax(MathMax(iHigh(Symbol(), PERIOD_D1, 0), iHigh(Symbol(), PERIOD_D1, 1)), iHigh(Symbol(), PERIOD_D1, 2)) + Tick); TP = NP(Bid - 4*iATR(Symbol(), 0, 24, 1)); RefreshRates(); if (OpenOrderCorrect(OP_SELL, ND(Bid), SL, TP) != 0) // открытие позиции return(0); // если не удалось открыть, то попытка переносится на следующий тик } if (Res == 1) return(0); } // - 5 - == Окончание блока ============================================================ LastBar = Time[0]; return(0); }