//+-------------------------------------------------------------------------------------+ //| NightBat.mq4 | //| Scriptong | //| scriptong@mail.ru | //+-------------------------------------------------------------------------------------+ #property copyright "Scriptong" #property link "scriptong@mail.ru" extern string A1 = "Период ATR и множитель"; extern int ATRPeriod = 5; extern double Factor = 4.0; extern string A2 = "================================================="; extern string A3 = "Цена применения (0-Close, 1-Open, 2-High, 3-Low и т. д.)"; extern int Price = 0; extern string A4 = "=================================="; extern string A5 = "Объем первой сделки и цель"; extern double Lots1 = 0.1; extern double FiboTarget1 = 161.8; extern string A6 = "==============================================================="; extern string A7 = "Ближайший ко входу уровень Фибо и объем сделки"; extern double Fibo2 = 61.8; extern double Lots2 = 0.1; extern double FiboTarget2 = 161.8; extern string A8 = "=================================="; extern string A9 = "Более дальний ко входу уровень Фибо и объем сделки"; extern double Fibo3 = 38.2; extern double Lots3 = 0.2; extern double FiboTarget3 = 161.8; extern string A10 = "=================================="; extern string OpenOrderSound = "ok.wav"; extern int MagicNumber = 875; // умножаем на 100. В младших разрядах храним номер // позиции в серии bool Activate, FreeMarginAlert, FatalError; double Tick, Spread, StopLevel, FreezeLevel, MinLot, MaxLot, LotStep, BuyLevel, SellLevel, HighBuy, LowSell, UpLevel, DnLevel, FirstBuyLevel, FirstSellLevel; datetime LastBar = 0, // Последний бар, на котором были произведены все расчеты LastSignal = 0, // Время последнего расчета сигнала LastCountTime = 0, // Время последнего рассчитанного бара LastPierce = 0, // Время последнего бробития уровня в ту или иную сторону SellTime[3], BuyTime[3]; // Время открытия последних сделок для каждого из типов int Buys, Sells, Dir, BuyTickets[3], SellTickets[3]; //+-------------------------------------------------------------------------------------+ //| 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 - ======================= Приведение значений обхема сделок к допустимым ========= Lots1 = LotRound(Lots1); Lots2 = LotRound(Lots2); Lots3 = LotRound(Lots3); // - 2 - ================================= Окончание блока ============================== // - 3 - ======================= Проверка корректности параметров Fibo ================== if (Fibo2 < 1 || Fibo2 > 99) { Comment("Значение параметра Fibo2 должно лежать в диапазоне 1 - 99."+ " Советник отключен!"); Print("Значение параметра Fibo2 должно лежать в диапазоне 1 - 99."+ " Советник отключен!"); return(0); } if (Fibo3 < 1 || Fibo3 > 99) { Comment("Значение параметра Fibo3 должно лежать в диапазоне 1 - 99."+ " Советник отключен!"); Print("Значение параметра Fibo3 должно лежать в диапазоне 1 - 99."+ " Советник отключен!"); return(0); } if (FiboTarget1 < 110) { Comment("Значение параметра FiboTarget1 должно быть больше 110."+ " Советник отключен!"); Print("Значение параметра FiboTarget1 должно быть больше 110."+ " Советник отключен!"); return(0); } if (FiboTarget2 < Fibo2) { Comment("Значение параметра FiboTarget2 должно быть больше Fibo2."+ " Советник отключен!"); Print("Значение параметра FiboTarget2 должно быть больше Fibo2."+ " Советник отключен!"); return(0); } if (FiboTarget3 < Fibo3) { Comment("Значение параметра FiboTarget3 должно быть больше Fibo3."+ " Советник отключен!"); Print("Значение параметра FiboTarget2 должно быть больше Fibo2."+ " Советник отключен!"); return(0); } // - 3 - ================================= Окончание блока ============================== // - 4 - ======================= Поиск в истории сделок последних открытых сделок ======= ArrayInitialize(BuyTime, 0); ArrayInitialize(SellTime, 0); for (int i = OrdersHistoryTotal()-1; i >= 0; i--) if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) if (OrderSymbol() == Symbol() && MathFloor(OrderMagicNumber()/100) == MagicNumber) { int ID = MathMod(OrderMagicNumber(), 100); if (MathMod(OrderType(), 2) == 0) BuyTime[ID] = MathMax(BuyTime[ID], OrderOpenTime()); else SellTime[ID] = MathMax(SellTime[ID], OrderOpenTime()); } // - 4 - ================================= Окончание блока ============================== LastCountTime = Time[1000]; UpLevel = 1000; // Текущий верхний уровень (для открытия BUY) DnLevel = 0; // Текущий нижний уровень (для открытия SELL) Dir = 0; // Текущее направление движения цены (1 - вверх, -1 - вниз) Activate = True; //---- return(0); } //+-------------------------------------------------------------------------------------+ //| expert deinitialization function | //+-------------------------------------------------------------------------------------+ int deinit() { //---- Comment(""); //---- return(0); } //+-------------------------------------------------------------------------------------+ //| Проверка объема на корректность и округление | //+-------------------------------------------------------------------------------------+ double LotRound(double L) { return(MathRound(MathMin(MathMax(L, MinLot), MaxLot)/LotStep)*LotStep); } //+-------------------------------------------------------------------------------------+ //| Приведение значений к точности одного тика | //+-------------------------------------------------------------------------------------+ 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 Lots, double Price, double SL, double TP, int MN, 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+Tick); else return(4); if (ND(Bid-SL) <= StopLevel) if (Redefinition) SL = ND(Bid-StopLevel-Tick); 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-Tick); else return(4); if (ND(SL-Ask) <= StopLevel && SL != 0) if (Redefinition) SL = ND(Ask+StopLevel+Tick); else return(3); break; case OP_BUYSTOP: S = "BUYSTOP"; if (ND(Price-Ask) <= StopLevel) if (Redefinition) Price = ND(Ask+StopLevel+Tick); else return(2); if (ND(TP-Price) <= StopLevel && TP != 0) if (Redefinition) TP = ND(Price+StopLevel+Tick); else return(4); if (ND(Price-SL) <= StopLevel) if (Redefinition) SL = ND(Price-StopLevel-Tick); else return(3); break; case OP_SELLSTOP: S = "SELLSTOP"; if (ND(Bid-Price) <= StopLevel) if (Redefinition) Price = ND(Bid-StopLevel-Tick); else return(2); if (ND(Price-TP) <= StopLevel) if (Redefinition) TP = ND(Price-StopLevel-Tick); else return(4); if (ND(SL-Price) <= StopLevel && SL != 0) if (Redefinition) SL = ND(Price+StopLevel+Tick); else return(3); break; case OP_BUYLIMIT: S = "BUYLIMIT"; if (ND(Ask-Price) <= StopLevel) if (Redefinition) Price = ND(Ask-StopLevel-Tick); else return(2); if (ND(TP-Price) <= StopLevel && TP != 0) if (Redefinition) TP = ND(Price+StopLevel+Tick); else return(4); if (ND(Price-SL) <= StopLevel) if (Redefinition) SL = ND(Price-StopLevel-Tick); else return(3); break; case OP_SELLLIMIT: S = "SELLLIMIT"; if (ND(Price - Bid) <= StopLevel) if (Redefinition) Price = ND(Bid+StopLevel+Tick); else return(2); if (ND(Price-TP) <= StopLevel) if (Redefinition) TP = ND(Price-StopLevel-Tick); else return(4); if (ND(SL-Price) <= StopLevel && SL != 0) if (Redefinition) SL = ND(Price+StopLevel+Tick); else return(3); break; } // - 2 - == Окончание блока ============================================================= // - 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 - == Окончание блока ============================================================= } //+-------------------------------------------------------------------------------------+ //| Расчет цены свечи по значению поля Price | //+-------------------------------------------------------------------------------------+ double GetPrice(int i) { switch (Price) { case 0: return(Close[i]); case 1: return(Open[i]); case 2: return(High[i]); case 3: return(Low[i]); case 4: return((High[i]+Low[i])/2); case 5: return((High[i]+Low[i]+Close[i])/3); case 6: return((High[i]+Low[i]+2*Close[i])/4); } } //+-------------------------------------------------------------------------------------+ //| Отображение уровня поддержки/сопротивления | //+-------------------------------------------------------------------------------------+ void ShowLevel(double Price, color Color) { if (ObjectFind("NB_Level") < 0) { ObjectCreate("NB_Level", OBJ_HLINE, 0, 1, Price); ObjectSet("NB_Level", OBJPROP_STYLE, STYLE_DOT); ObjectSet("NB_Level", OBJPROP_COLOR, Color); } else { ObjectMove("NB_Level", 0, 1, Price); ObjectSet("NB_Level", OBJPROP_COLOR, Color); } } //+-------------------------------------------------------------------------------------+ //| Расчет уровней для каждого направления торговли | //+-------------------------------------------------------------------------------------+ void GetSignal() { // - 1 - ============================= Инициализация переменных ========================= BuyLevel = 0; SellLevel = 0; // - 1 - ================================== Окончание блока ============================= // - 2 - =========== Поиск последнего пробитого уровня ATR ============================== int i = iBarShift(Symbol(), 0, LastCountTime);// Начинаем с последнего посчитанного бара while (i > 0) { double ApplyPrice = GetPrice(i); double ATRF = iATR(Symbol(), 0, ATRPeriod, i)*Factor; if (Dir == 0) // если направление не определено (первый подход к GetSignal), то { DnLevel = ApplyPrice - ATRF; // рассчитываем оба уровня - верхний и нижний UpLevel = ApplyPrice + ATRF; } if (Dir >= 0) // При наличии восходящего движения следим за пробитием поддержки if (Low[i] <= DnLevel) // пробита ли поддержка? { Dir = -1; // если пробита, то меняем текущее направление движения на нисходящее DnLevel = 0; LastPierce = Time[i]; // запоминаем время пробития } else DnLevel = MathMax(ApplyPrice - ATRF, DnLevel); // или высчитываем новый уровень if (Dir <= 0) // При наличии нисходящего движения следим за пробитием сопротивления if (High[i] >= UpLevel) // пробито ли сопротивление { Dir = 1; // если пробито, то меняем направление движения на восходящее UpLevel = 1000; LastPierce = Time[i]; // запоминаем время пробития i++; } else UpLevel = MathMin(ApplyPrice + ATRF, UpLevel); // или рассчитываем новый уровень i--; } // - 2 - ================================== Окончание блока ============================= LastCountTime = Time[i]; // Последний посчитанный бар запоминаем // - 3 - ================= Отображение верхнего уровня ATR выше цены ==================== if (Dir < 0) // текущее направление нисходящее { ShowLevel(UpLevel, Red); // отображаем уровень выше цены BuyLevel = UpLevel; // это и будет уровнем открытия Buy Stop } // - 3 - ================================== Окончание блока ============================= // - 4 - ================== Отображение нижнего уровня ATR ============================== if (Dir > 0) // текущее направление восходящее { ShowLevel(DnLevel, Blue); // отображаем уровень ниже цены SellLevel = DnLevel; // это и будет уровнем открытия Sell Stop } // - 4 - ================================== Окончание блока ============================= } //+-------------------------------------------------------------------------------------+ //| Нахождение всех своих ордеров и позиций. | //+-------------------------------------------------------------------------------------+ void FindOrders() { ArrayInitialize(BuyTickets, -1); // "обнуление" тикетов ArrayInitialize(SellTickets, -1); // "обнуление" тикетов Buys = 0; Sells = 0; // Счетчики кол-ва своих ордеров и позиций FirstBuyLevel = 0; FirstSellLevel = 0; // Уровни пробития // - 1 - ============================ Выбираем свои ордера и позиции ==================== for (int i = 0; i < OrdersTotal(); i++) if (OrderSelect(i, SELECT_BY_POS)) if (OrderSymbol() == Symbol() && MathFloor(OrderMagicNumber()/100) == MagicNumber) // - 1 - ================================ Окончание блока =============================== { // - 2 - =============== Сортировка ордеров и позиций по номерам тикетов ================ int ID = MathMod(OrderMagicNumber(), 100); if (MathMod(OrderType(), 2) == 0) // Найден BUY-ордер { BuyTickets[ID] = OrderTicket(); BuyTime[ID] = MathMax(BuyTime[ID], OrderOpenTime()); Buys++; if (ID == 0 && OrderType() == OP_BUY) FirstBuyLevel = OrderOpenPrice() - Spread; } else // найден Sell-ордер { SellTickets[ID] = OrderTicket(); SellTime[ID] = MathMax(SellTime[ID], OrderOpenTime()); Sells++; if (ID == 0 && OrderType() == OP_SELL) FirstSellLevel = OrderOpenPrice(); } // - 2 - ================================ Окончание блока =============================== } } //+-------------------------------------------------------------------------------------+ //| Вспомогательная функция для проверки дополнительных BUY-ордеров | //+-------------------------------------------------------------------------------------+ bool CheckAddingBuy(int Number, double Fibo, double Target, double volume) { if (BuyTickets[Number] > 0 && OrderSelect(BuyTickets[Number], SELECT_BY_TICKET) && OrderCloseTime() == 0) { // Ордер найден, проверяем уровень стопа if (MathAbs(OrderStopLoss()-SellLevel+Tick) >= Tick) // Стоп нужно изменить { if ((OrderType() == OP_BUY && Bid - SellLevel + Tick > StopLevel) || // расстояние (OrderType() == OP_BUYLIMIT && // от цены до нового стопа или от открытия до OrderOpenPrice() - SellLevel + Tick > StopLevel)) // нового стопа достаточное { if (WaitForTradeContext()) OrderModify(OrderTicket(), OrderOpenPrice(), NP(SellLevel - Tick), OrderTakeProfit(), 0); } else//Если расстояние недостаточное, то в случае присутствия BUYLIMIT удаляем его if (OrderType() == OP_BUYLIMIT) if (WaitForTradeContext()) OrderDelete(OrderTicket()); return(false); // Не все операции закончены } } else // Ордера/позиции нет if (BuyTime[Number] < LastPierce && // Последняя вторичная позиция открыта до пробития TimeCurrent() - LastPierce < 2*60*Period()) // и еще не поздно установить ордер { double Price = (FirstBuyLevel - SellLevel)*(Fibo/100.0) + SellLevel + Spread; double TP = (FirstBuyLevel - SellLevel)*(Target/100.0) + SellLevel; if (Price - SellLevel + Tick < StopLevel || // Цена открытия изначально ниже стопа SellLevel-Tick >= FirstBuyLevel)//или уровень стопа выше цены первичной позиции return(True); // поэтому больше сюда на этом сигнале не вернемся if (Ask - Price > StopLevel) OpenOrderCorrect(OP_BUYLIMIT, volume, NP(Price), NP(SellLevel - Tick), NP(TP), 100*MagicNumber+Number); return(False); // Не все операции закончены } return(True); } //+-------------------------------------------------------------------------------------+ //| Вспомогательная функция для проверки дополнительных SELL-ордеров | //+-------------------------------------------------------------------------------------+ bool CheckAddingSell(int Number, double Fibo, double Target, double volume) { if (SellTickets[Number] > 0 && OrderSelect(SellTickets[Number], SELECT_BY_TICKET) && OrderCloseTime() == 0) { // Ордер найден, проверяем уровень стопа if (MathAbs(OrderStopLoss()-BuyLevel-Spread-Tick) >= Tick) // Стоп нужно изменить { if ((OrderType() == OP_SELL && BuyLevel + Tick - Bid > StopLevel) || //расстояние (OrderType()== OP_SELLLIMIT &&//от цены до нового стопа или от открытия до но- BuyLevel + Spread + Tick - OrderOpenPrice() > StopLevel))//вого стопа в норме { if (WaitForTradeContext()) OrderModify(OrderTicket(), OrderOpenPrice(), NP(BuyLevel + Spread + Tick), OrderTakeProfit(), 0); } else//Если расстояние недостаточно, то в случае присутствия SELLLIMIT удаляем его if (OrderType() == OP_SELLLIMIT) if (WaitForTradeContext()) OrderDelete(OrderTicket()); return(false); // Не все операции закончены } } else // Ордера/позиции нет if (SellTime[Number] < LastPierce &&// Последняя вторичная позиция открыта до пробития TimeCurrent() - LastPierce < 2*60*Period()) // и еще не поздно установить ордер { double Price = BuyLevel - (BuyLevel - FirstSellLevel)*(Fibo/100.0); double TP = BuyLevel - (BuyLevel - FirstSellLevel)*(Target/100.0); if (BuyLevel + Spread + Tick - Price < StopLevel ||// Цена открытия изначально выше BuyLevel+Spread+Tick <= FirstSellLevel) // стопа или уровень стопа выше цены return(True);//первичной позиции, поэтому больше сюда на этом сигнале не вернемся if (Price - Bid > StopLevel) OpenOrderCorrect(OP_SELLLIMIT, volume, NP(Price), NP(BuyLevel + Spread + Tick), NP(TP), 100*MagicNumber+Number); return(False); // Не все операции закончены } return(True); } //+-------------------------------------------------------------------------------------+ //| Удаление ордера | //+-------------------------------------------------------------------------------------+ bool DeleteOrder(int Ticket) { if (Ticket > 0) if (OrderSelect(Ticket, SELECT_BY_TICKET) && OrderCloseTime() == 0) if (OrderType() > 1) { if (WaitForTradeContext()) OrderDelete(Ticket); return(False); } return(True); } //+-------------------------------------------------------------------------------------+ //| Анализ расположения ордеров и позиций (перемещение стопов, цен открытия) | //+-------------------------------------------------------------------------------------+ bool CheckOrders() { // - 1 - ==================== Активен сигнал открытия длинных позиций =================== if (SellLevel > 0) { // - 1.1 - ============== Проверка наличия основной позиции и ее стопа ============== if (BuyTickets[0] > 0 && OrderSelect(BuyTickets[0], SELECT_BY_TICKET) && OrderCloseTime() == 0) { if (OrderType() > 1) // Если это до сих пор ордер, то удаляем его { OrderDelete(OrderTicket()); return(false); // Не все операции закончены } if (MathAbs(OrderStopLoss()-SellLevel+Tick) >= Tick) // Стоп нужно изменить { if (Bid - SellLevel+Tick > StopLevel) if (WaitForTradeContext()) OrderModify(OrderTicket(), 0, NP(SellLevel-Tick), OrderTakeProfit(), 0); return(false); // Не все операции закончены } if (OrderTakeProfit() == 0) // Если профит еще не установлен, то установим { double TP = (FirstBuyLevel - SellLevel)*(FiboTarget1/100.0) + SellLevel; if (TP - Bid <= StopLevel) TP = Bid + StopLevel + Tick; if (WaitForTradeContext()) OrderModify(OrderTicket(), 0, OrderStopLoss(), NP(TP), 0); return(False); } } else if (BuyTime[0] 0 && OrderSelect(SellTickets[0], SELECT_BY_TICKET) && OrderCloseTime() == 0) { if (OrderType() > 1) if (MathAbs(OrderOpenPrice()-SellLevel+Tick)>=Tick) //Цену открытия нужно менять { if (Bid - SellLevel + Tick > StopLevel) if (WaitForTradeContext()) OrderModify(OrderTicket(), NP(SellLevel - Tick), 0, 0, 0); return(false); // Не все операции закончены } } else // Первичного SellStop нет - устанавливаем { OpenOrderCorrect(OP_SELLSTOP, Lots1, NP(SellLevel-Tick), 0, 0, 100*MagicNumber); // Открываем Sell Stop return(false); // Не все операции закончены } // - 1.4 - ============================= Окончание блока ============================ // - 1.5 - ================== Удаление оставшихся ордеров Sell Limit ================ if (!DeleteOrder(SellTickets[1]) || !DeleteOrder(SellTickets[2])) return(False); // - 1.5 - ============================= Окончание блока ============================ } // - 1 - ================================ Окончание блока =============================== // - 2 - =================== Активен сигнал открытия коротких позиций =================== if (BuyLevel > 0) { // - 2.1 - ============== Проверка наличия основной позиции и ее стопа ============== if (SellTickets[0] > 0 && OrderSelect(SellTickets[0], SELECT_BY_TICKET) && OrderCloseTime() == 0) { if (OrderType() > 1) // Если это до сих пор ордер, то удаляем его { if (WaitForTradeContext()) OrderDelete(OrderTicket()); return(false); // Не все операции закончены } if (MathAbs(OrderStopLoss()-BuyLevel-Spread-Tick) >= Tick) // Стоп нужно изменить { if (BuyLevel - Bid > StopLevel) if (WaitForTradeContext()) OrderModify(OrderTicket(), 0, NP(BuyLevel + Spread + Tick), OrderTakeProfit(), 0); return(false); // Не все операции закончены } if (OrderTakeProfit() == 0) // Если профит еще не установлен, то установим { TP = BuyLevel - (BuyLevel - FirstSellLevel)*(FiboTarget1/100.0); if (Ask - TP <= StopLevel) TP = Ask - StopLevel - Tick; if (WaitForTradeContext()) OrderModify(OrderTicket(), 0, OrderStopLoss(), NP(TP), 0); return(False); } } else if (SellTime[0] 0 && OrderSelect(BuyTickets[0], SELECT_BY_TICKET) && OrderCloseTime() == 0) { if (OrderType() > 1) if (MathAbs(OrderOpenPrice()-BuyLevel-Spread-Tick) >= Tick)//Цену открытия нужно { // изменить if (BuyLevel + Tick - Bid > StopLevel) if (WaitForTradeContext()) OrderModify(OrderTicket(), NP(BuyLevel + Spread + Tick), 0, 0, 0); return(false); // Не все операции закончены } } else // Первичного SellStop нет - устанавливаем { OpenOrderCorrect(OP_BUYSTOP, Lots1, NP(BuyLevel + Spread + Tick), 0, 0, 100*MagicNumber); // Открываем BuyStop return(false); // Не все операции закончены } // - 2.4 - ============================= Окончание блока ============================ // - 2.5 - ================== Удаление оставшихся ордеров Buy Limit ================= if (!DeleteOrder(BuyTickets[1]) || !DeleteOrder(BuyTickets[2])) return(False); // - 2.5 - ============================= Окончание блока ============================ } // - 2 - ================================ Окончание блока =============================== return(True); } //+-------------------------------------------------------------------------------------+ //| Функция 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); if (LastSignal != Time[0]) { GetSignal(); LastSignal = Time[0]; } // - 3 - ================================ Окончание блока ============================== // - 4 - =========== Изменение стопов позиций и цены открытия отложенных ордеров ======== FindOrders(); // Нахождение всех ордеров и позиций, сортировка по массивам тикетов if (!CheckOrders()) return(0); // - 4 - ========================== Окончание блока ===================================== LastBar = Time[0]; return(0); }