//+-------------------------------------------------------------------------------------+ //| PhoenixDouble.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 = 127; extern int FastMAShift = 0; extern int FastMAMethod = 0; extern int FastMAPrice = 0; extern string A2 = "=================================="; extern string A3 = "Параметры медленной МА для прямой системы"; extern int SlowMAPeriod = 150; extern int SlowMAShift = 0; extern int SlowMAMethod = 0; extern int SlowMAPrice = 0; extern string A4 = "=================================="; extern string A5 = "Параметры быстрой МА для реверсной системы"; extern int FastMAPeriod_Rev = 265; extern int FastMAShift_Rev = 0; extern int FastMAMethod_Rev = 0; extern int FastMAPrice_Rev = 0; extern string A6 = "=================================="; extern string A7 = "Параметры медленной МА для реверсной системы"; extern int SlowMAPeriod_Rev = 275; extern int SlowMAShift_Rev = 0; extern int SlowMAMethod_Rev = 0; extern int SlowMAPrice_Rev = 0; extern string A8 = "=================================="; extern string OpenOrderSound = "ok.wav"; extern int MagicNumber = 10002; // Сам магик умножаем на 10, в младшем разряде - // идентификатор системы. Для прямой системы ID - 0, для обратной - 1. bool Activate, FreeMarginAlert, FatalError, IsPendings; double Tick, Spread, StopLevel, FreezeLevel, MinLot, MaxLot, LotStep, BuySL[2], BuyTP[2], SellSL[2], SellTP[2], OpPrice[2], // цена открытия отложенных ордеров SLPrice[2], // уровень стопа отложенных ордеров TPPrice[2]; // Уровень профита отложенных ордеров int Signal; datetime LastBar = 0; int BuyTicket[2], // Тикеты BUY по прямой (элемент 0) и обратной (элемент 1) системам SellTicket[2], // Тикеты SELL по прямой (элемент 0) и обратной (элемент 1) системам BSTicket[2], // Тикеты BUYSTOP по прямой (элемент 0) и обратной (элемент 1) системам SSTicket[2], // Тикеты SELLSTOP по прямой (элемент 0) и обратной (элемент 1) системам BLTicket[2], // Тикеты BUYLIMIT по прямой (элемент 0) и обратной (элемент 1) системам SLTicket[2],// Тикеты SELLLIMIT по прямой (элемент 0) и обратной (элемент 1) системам PenType[2], // Типы двух отложенных ордеров, которые необходимо установить OrdID[2]; // Идентификаторы для установки ордеров //+-------------------------------------------------------------------------------------+ //| expert initialization function | //+-------------------------------------------------------------------------------------+ int init() { FatalError = False; Activate = 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) return(0); ArrayInitialize(PenType, 0); Activate = True; //---- return(0); } //+-------------------------------------------------------------------------------------+ //| expert deinitialization function | //+-------------------------------------------------------------------------------------+ int deinit() { //---- Comment(""); //---- return(0); } //+-------------------------------------------------------------------------------------+ //| Приведение значений к точности одного пункта | //+-------------------------------------------------------------------------------------+ double ND(double A) { return(NormalizeDouble(A, Digits)); } //+-------------------------------------------------------------------------------------+ //| Приведение значений к точности одного тика | //+-------------------------------------------------------------------------------------+ double NP(double A) { return(MathRound(A/Tick)*Tick); } //+-------------------------------------------------------------------------------------+ //| Расшифровка сообщения об ошибке | //+-------------------------------------------------------------------------------------+ 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, int Num, 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 - == Окончание блока ============================================================= int MN = MagicNumber*10 + Num; // - 3 - == Открытие ордера с ожидание торгового потока ================================= if(WaitForTradeContext()) // ожидание освобождения торгового потока { Comment("Отправлен запрос на открытие ордера ", S, " ..."); int ticket=OrderSend(Symbol(), Type, Lots, Price, 3, SL, TP, NULL, MN, 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 - == Окончание блока ============================================================= } //+-------------------------------------------------------------------------------------+ //| Расчет значений Bollinger с формированием сигналов для открытия позиций | //+-------------------------------------------------------------------------------------+ 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 DD1 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 1) - iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 1); double DD2 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 2) - iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 2); double DD3 = iMA(Symbol(), 0, FastMAPeriod, FastMAShift, FastMAMethod, FastMAPrice, 3) - iMA(Symbol(), 0, SlowMAPeriod, SlowMAShift, SlowMAMethod, SlowMAPrice, 3); double DR1 = iMA(Symbol(), 0, FastMAPeriod_Rev, FastMAShift_Rev, FastMAMethod_Rev, FastMAPrice_Rev, 1) - iMA(Symbol(), 0, SlowMAPeriod_Rev, SlowMAShift_Rev, SlowMAMethod_Rev, SlowMAPrice_Rev, 1); double DR2 = iMA(Symbol(), 0, FastMAPeriod_Rev, FastMAShift_Rev, FastMAMethod_Rev, FastMAPrice_Rev, 2) - iMA(Symbol(), 0, SlowMAPeriod_Rev, SlowMAShift_Rev, SlowMAMethod_Rev, SlowMAPrice_Rev, 2); double DR3 = iMA(Symbol(), 0, FastMAPeriod_Rev, FastMAShift_Rev, FastMAMethod_Rev, FastMAPrice_Rev, 3) - iMA(Symbol(), 0, SlowMAPeriod_Rev, SlowMAShift_Rev, SlowMAMethod_Rev, SlowMAPrice_Rev, 3); // - 2 - ======================= Окончание блока ======================================== // - 3 - == Генерация сигнала для прямой системы ======================================== if (PierceUp) if (DD3 >= DD2 && DD1 > DD2 && DD1 < 0) Signal = 1; // Открытие BUY if (PierceDown) if (DD3 <= DD2 && DD1 < DD2 && DD1 > 0) Signal = -1; // Открытие SELL // - 3 - == Окончание блока ============================================================= // - 4 - == Генерация сигнала для обратной системы ====================================== if (PierceDown) if (DR3 <= DR2 && DR1 < DR2 && DR1 > 0) Signal = Signal + 2; // Открытие BUY if (PierceUp) if (DR3 >= DR2 && DR1 > DR2 && DR1 < 0) Signal = Signal - 2; // Открытие SELL // - 4 - == Окончание блока ============================================================= } //+-------------------------------------------------------------------------------------+ //| Проверка объема на корректность и округление | //+-------------------------------------------------------------------------------------+ double LotRound(double L) { return(MathRound(MathMin(MathMax(L, MinLot), MaxLot)/LotStep)*LotStep); } //+-------------------------------------------------------------------------------------+ //| Закрывает выбранную позицию. Если закрыть не удалось, то False, иначе True. | //+-------------------------------------------------------------------------------------+ bool ClosePos(int Ticket) { if (OrderSelect(Ticket, SELECT_BY_TICKET) && OrderCloseTime() == 0) if (WaitForTradeContext()) { if (OrderType() == OP_BUY) double Pr = ND(MarketInfo(Symbol(), MODE_BID)); else Pr = ND(MarketInfo(Symbol(), MODE_ASK)); if (OrderClose(OrderTicket(), OrderLots(), Pr, 3)) return(True); } return(False); } //+-------------------------------------------------------------------------------------+ //| Удаление всех отложенных ордеров | //+-------------------------------------------------------------------------------------+ bool DeletePendings() { for (int i = 0; i < 2; i++) { int Ticket = 0; if (BSTicket[i] > 0) Ticket = BSTicket[i]; if (BLTicket[i] > 0) Ticket = BLTicket[i]; if (SSTicket[i] > 0) Ticket = SSTicket[i]; if (SLTicket[i] > 0) Ticket = SLTicket[i]; if (Ticket > 0) { if (WaitForTradeContext()) if (OrderDelete(Ticket)) continue; return(False); } } return(True); } //+-------------------------------------------------------------------------------------+ //| Поиск позиций с заполнением массивов тикетов BuyTicket и SellTicket | //+-------------------------------------------------------------------------------------+ bool OrdersFind() { // - 1 - ======================== Инициализация массивов тикетов ======================== ArrayInitialize(BuyTicket, -1); ArrayInitialize(SellTicket, -1); ArrayInitialize(BSTicket, -1); ArrayInitialize(SSTicket, -1); ArrayInitialize(BLTicket, -1); ArrayInitialize(SLTicket, -1); int Pendings = 0; IsPendings = False; // - 1 - ========================= Окончание блока ====================================== // - 2 - ========================= Подсчет своих позиций ================================ for (int i = OrdersTotal()-1; i >= 0; i--) if (OrderSelect(i, SELECT_BY_POS)) if (OrderSymbol() == Symbol() && MathFloor(OrderMagicNumber()/10) == MagicNumber) { int ID = MathMod(OrderMagicNumber(), 10); switch (OrderType()) { case OP_BUY: BuyTicket[ID] = OrderTicket(); BuySL[ID] = OrderStopLoss(); BuyTP[ID] = OrderTakeProfit(); break; case OP_SELL: SellTicket[ID] = OrderTicket(); SellSL[ID] = OrderStopLoss(); SellTP[ID] = OrderTakeProfit(); break; case OP_BUYSTOP: BSTicket[ID] = OrderTicket(); Pendings++; break; case OP_SELLSTOP: SSTicket[ID] = OrderTicket(); Pendings++; break; case OP_BUYLIMIT: BLTicket[ID] = OrderTicket(); Pendings++; break; case OP_SELLLIMIT: SLTicket[ID] = OrderTicket(); Pendings++; break; } } // - 2 - ========================= Окончание блока ====================================== // - 3 - ============== Ликвидация лишнего ордера из пары связанных ордеров ============= if (Pendings == 1) // Существует только один отложенный ордер, необходимо удалить его if (!DeletePendings()) return(False); // - 3 - ========================= Окончание блока ====================================== if (Pendings == 2) IsPendings = True; return(True); } //+-------------------------------------------------------------------------------------+ //| Поиск закрытия позиции нужного типа на текущей свече. Если найдено закрытие, то True| //| В противном случае результат False | //+-------------------------------------------------------------------------------------+ bool IsCloseOnThisCandle(int Type, int ID) { // - 1 - ============== Блок проверки для режима тестирования =========================== if (IsTesting()) { if (OrderSelect(OrdersHistoryTotal()-1, SELECT_BY_POS, MODE_HISTORY)) if (OrderCloseTime() >= Time[0]) if (OrderType() == Type) if (MathMod(OrderMagicNumber(), 10) == ID) return(True); } // - 1 - =========================== Окончание блока ==================================== else // - 2 - ==================== Блок проверки для режима онлайн =========================== { for (int i = 0; i < OrdersHistoryTotal(); i++) if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) if (OrderSymbol() == Symbol()) if (OrderCloseTime() >= Time[0]) if (OrderType() == Type && MathFloor(OrderMagicNumber()/10) == MagicNumber) if (MathMod(OrderMagicNumber(), 10) == ID) return(True); } // - 2 - =========================== Окончание блока ==================================== return(False); } //+-------------------------------------------------------------------------------------+ //| Подготовка данных для установки отложенных ордеров | //+-------------------------------------------------------------------------------------+ void SetPendings(int ID, int Rev, int Type, double SLD, double TPD, double SLR, double TPR) { // - 1 - ==================== Если по текущей системе необходимо открыть длинную ======== if (Type == OP_BUY) { if (SLR - Spread < TPD) {// Установить BuyStop на уровне SLR с ИД = ID PenType[0] = OP_BUYSTOP; OpPrice[0] = SLR; SLPrice[0] = SLD; // Уровни стопа и профита берем от текущей системы TPPrice[0] = TPD; OrdID[0] = ID; } else {// Установить SellLimit на уровне TPD с ИД = Rev PenType[0] = OP_SELLLIMIT; OpPrice[0] = TPD; SLPrice[0] = SLR; // Уровни стопа и профита берем от противоположной системы TPPrice[0] = TPR; OrdID[0] = Rev; } if (TPR - Spread < SLD) {// Установить SellStop на уровне SLD с ИД = Rev PenType[1] = OP_SELLSTOP; OpPrice[1] = SLD; SLPrice[1] = SLR; // Уровни стопа и профита берем от противоположной системы TPPrice[1] = TPR; OrdID[1] = Rev; } else {// Установить BuyLimit на уровне TPR с ИД = ID PenType[1] = OP_BUYLIMIT; OpPrice[1] = TPR; SLPrice[1] = SLD; // Уровни стопа и профита берем от текущей системы TPPrice[1] = TPD; OrdID[1] = ID; } } // - 1 - ===================================== Окончание блока ========================== else // - 2 - ==================== Если по текущей системе необходимо открыть короткую ======= { if (SLR + Spread > TPD) {// Установить SellStop на уровне SLR с ИД = ID PenType[0] = OP_SELLSTOP; OpPrice[0] = SLR; SLPrice[0] = SLD; // Уровни стопа и профита берем от текущей системы TPPrice[0] = TPD; OrdID[0] = ID; } else {// Установить BuyLimit на уровне TPD с ИД = Rev PenType[0] = OP_BUYLIMIT; OpPrice[0] = TPD; SLPrice[0] = SLR; // Уровни стопа и профита берем от противоположной системы TPPrice[0] = TPR; OrdID[0] = Rev; } if (TPR + Spread > SLD) {// Установить BuyStop на уровне SLD с ИД = Rev PenType[1] = OP_BUYSTOP; OpPrice[1] = SLD; SLPrice[1] = SLR; // Уровни стопа и профита берем от противоположной системы TPPrice[1] = TPR; OrdID[1] = Rev; } else {// Установить SellLimit на уровне TPR с ИД = ID PenType[1] = OP_SELLLIMIT; OpPrice[1] = TPR; SLPrice[1] = SLD; // Уровни стопа и профита берем от текущей системы TPPrice[1] = TPD; OrdID[1] = ID; } } // - 2 - ===================================== Окончание блока ========================== } //+-------------------------------------------------------------------------------------+ //| Открытие и закрытие позиций | //+-------------------------------------------------------------------------------------+ bool Trades() { // - 1 - ============================ Инициализация "рабочих" переменных ================ int i = MathAbs(Signal); // Количество итераций цикла 0, 1 или 2 while (i > 0) { int ID = MathFloor(i/2); // Идентификатор системы 0 - прямая, 1 - обратная int Rev = MathAbs(ID-1); // Идентификатор противоположной системы // - 1 - ===================================== Окончание блока ========================== // - 2 - ==================== Действия при сигнале открытия длинных позиций ============= if (Signal > 0) { double SL = NP(MathMin(MathMin(iLow(Symbol(), PERIOD_D1, 1), iLow(Symbol(), PERIOD_D1, 0)), iLow(Symbol(), PERIOD_D1, 2)) - Tick); double TP = NP(Ask + 4*iATR(Symbol(), 0, 24, 1)); if (SellTicket[ID] > 0) // найден SELL текущей системы { // нужно закрыть его и открыть BUY if (!ClosePos(SellTicket[ID])) // Попытка закрытия SELL return(False); if (SellTicket[Rev] > 0) // найден SELL противоположной системы { // закрываем его, и ставим два отложенных ордера if (!ClosePos(SellTicket[Rev])) return(False); // Команда установки отложенных ордеров SetPendings(ID, Rev, OP_BUY, SL, TP, SellSL[Rev], SellTP[Rev]); } else // не найден SELL противоположной системы, открываем BUY if (OpenOrderCorrect(OP_BUY, NP(Ask), SL, TP, ID) != 0) return(False); } else if (BuyTicket[ID] < 0)// не найден BUY текущей системы, т. е. вообще нет позиций // текущей системы. // Проверяем существование SELL противоположной системы if (SellTicket[Rev] > 0) // Если найден SELL, то закрываем его, но не { // открываем BUY if (!ClosePos(SellTicket[Rev])) return(False); // Команда установки отложенных ордеров SetPendings(ID, Rev, OP_BUY, SL, TP, SellSL[Rev], SellTP[Rev]); } else // Если не было закрытия SELL на текущей свече или существует BUY // противоположной системы, то открываем новый BUY if (BuyTicket[Rev] > 0 || !IsCloseOnThisCandle(OP_SELL, Rev)) if (OpenOrderCorrect(OP_BUY, NP(Ask), SL, TP, ID) != 0) return(False); } // - 2 - ===================================== Окончание блока ========================== // - 3 - ==================== Действия при сигнале открытия коротких позиций ============ if (Signal < 0) { SL = NP(MathMax(MathMax(iHigh(Symbol(), PERIOD_D1, 0), iHigh(Symbol(), PERIOD_D1, 1)), iHigh(Symbol(), PERIOD_D1, 2)) + Spread + Tick); TP = NP(Bid - 4*iATR(Symbol(), 0, 24, 1)); if (BuyTicket[ID] > 0) // найден BUY текущей системы { // нужно закрыть его и открыть SELL if (!ClosePos(BuyTicket[ID])) // Попытка закрытия BUY текущей системы return(False); if (BuyTicket[Rev] > 0) // найден BUY противоположной системы { // закрываем его, но новый SELL не открываем if (!ClosePos(BuyTicket[Rev]))//Попытка закрытия BUY противоположной системы return(False); // Команда установки отложенных ордеров SetPendings(ID, Rev, OP_SELL, SL, TP, BuySL[Rev], BuyTP[Rev]); } else // Нет позиции BUY противоположной системы, можно открывать SELL if (OpenOrderCorrect(OP_SELL, NP(Bid), SL, TP, ID) != 0) return(False); } else // Нет позиции BUY текущей системы if (SellTicket[ID] < 0) // не найден SELL текущей системы, т. е. вообще нет // текущей системы. Проверяем существование SELL противоположной системы if (BuyTicket[Rev] > 0) // Если найден BUY противоположной системы, { // то закрываем его, но SELL не открываем if (!ClosePos(BuyTicket[Rev])) return(False); // Команда установки отложенных ордеров SetPendings(ID, Rev, OP_SELL, SL, TP, BuySL[Rev], BuyTP[Rev]); } else // Если не было закрытия BUY на текущей свече или существует SELL // противоположной системы, то открываем новый SELL if (SellTicket[Rev] > 0 || !IsCloseOnThisCandle(OP_BUY, Rev)) if (OpenOrderCorrect(OP_SELL, NP(Bid), SL, TP, ID) != 0) return(False); } // - 3 - ===================================== Окончание блока ========================== i = i - 2; // Учитываем, что сигнал мог быть по обратной системе с весом 2 } return(True); } //+-------------------------------------------------------------------------------------+ //| Установка отложенных ордеров | //+-------------------------------------------------------------------------------------+ void SetOrders() { for (int i = 1; i >= 0; i--) if (PenType[i] > 0) if (OpenOrderCorrect(PenType[i], OpPrice[i], SLPrice[i], TPPrice[i], OrdID[i]) == 0) PenType[i] = 0; else return; } //+-------------------------------------------------------------------------------------+ //| Функция 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 (PenType[0] > 0) // Если необходимо установить отложенные ордера, то больше { // ничего на этом тике не делаем SetOrders(); return(0); } if (!OrdersFind()) return(0); // Подсчет своих позиций // - 3 - == Окончание блока ============================================================ // - 4 - ======== Обработка существующей позиции и контроль открытия нового бара ======== if (LastBar == Time[0]) return(0); // - 4 - == Окончание блока ============================================================ // - 5 - ======================== Расчет сигнала ======================================== GetSignal(); // - 5 - == Окончание блока ============================================================ // - 6 - == Открытие позиций ============================================================ if (Signal != 0) { if (IsPendings) // Если присутствуют отложенные ордера, то if (!DeletePendings()) // пытаемся удалить их return(0); if (!Trades()) // Открытие/закрытие сделок return(0); } // - 6 - == Окончание блока ============================================================ LastBar = Time[0]; return(0); }