extern string rem2 = "=== Количество лотов ==="; extern double _Lots0_1 = 0.1; // Базовый уровень (для 1-го ордера) extern double _Lots0_2 = 0.1; // Базовый уровень (для 2-го ордера) // extern string rem3 = "=== Дополнительные параметры ==="; extern int _TakeProfit1_Proc = 50; // Процент риска для тейк-профита 1-го ордера extern int _SpaseFromMaxMin = 1; // Отступ от Вершины/Дна // extern string rem4 = "=== Параметры безубытка ==="; extern bool _IsStopLoss_0 = false; // Включение использования уровня безубытка extern int _StopLoss_0_From = 0; // Отступ от уровеня безубытка (в пунктах) extern int _StopLoss_0_Level = 15; // Уровень безубытка // extern string rem5 = "=== Параметры трейлинг стопа ==="; extern bool _IsTrailingStop = false; // Включение трейлинг стопа bool _IsTrailingStopProfit = true; // Включение трейлинг стопа с позиции безубытка //extern int _TrailingStopProfit_From = 0; // Отступ от уровеня безубытка (в пунктах) extern int _TrailingStopLevel = 15; // Уровень трейлинг стопа extern int _TrailingStopStep = 5; // Шаг перемещения трейлинг стопа // extern string rem6 = "=== Настройки инструмента ==="; extern string _Symboll = ""; // Символьное имя инструмента: "" - текущий символ extern int _Timeframe = 0; // Период: 0 - период текущего графика int _Digitss; // Количество цифр после десятичной точки в цене double _Points; // Размер пункта в валюте котировки extern int _Slippage = 2; // Проскальзывание extern int _Magic1 = 1281; // Уникальный номер ордеров советника (1-й ордер) extern int _Magic2 = 1282; // Уникальный номер ордеров советника (2-й ордер) // extern string rem7 = "=== Параметры индикатора MA1 ==="; extern int _MA1_Timeframe = PERIOD_D1; // Период: 0 - период текущего графика extern int _MA1_Period = 20; // Период усреднения для вычисления скользящего среднего extern int _MA1_Shift = 0; // Сдвиг индикатора относительно ценового графика extern int _MA1_Method = 0; // Метод усреднения: 0 - SMA, 1 - EMA, 2 - SMMA, 3 - LWMA extern int _MA1_Applied_Price = 0; // Используемая цена: 0 - close, 1 - open, 2 - high, 3 - low // extern string rem8 = "=== Параметры индикатора MA2 ==="; extern int _MA2_Timeframe = PERIOD_H4; // Период: 0 - период текущего графика extern int _MA2_Period = 20; // Период усреднения для вычисления скользящего среднего extern int _MA2_Shift = 0; // Сдвиг индикатора относительно ценового графика extern int _MA2_Method = 0; // Метод усреднения: 0 - SMA, 1 - EMA, 2 - SMMA, 3 - LWMA extern int _MA2_Applied_Price = 0; // Используемая цена: 0 - close, 1 - open, 2 - high, 3 - low // extern string rem9 = "=== Параметры индикатора Bollinger Bands ==="; //extern int _BB_Timeframe = 0; // Период: 0 - период текущего графика extern int _BB_Period = 20; // Период усреднения основной линии индикатора extern int _BB_Deviation = 2; // Отклонение от основной линии extern int _BB_Bands_Shift = 0; // Сдвиг индикатора относительно ценового графика extern int _BB_Applied_Price = 0; // Используемая цена: 0 - close // extern string rem10 = "=== Параметры индикатора ZigZag ==="; //extern int _ZZ_Timeframe = 0; // Период: 0 - период текущего графика extern int _ZZ_ExtDepth = 12; extern int _ZZ_ExtDeviation = 5; extern int _ZZ_ExtBackstep = 3; // datetime _TimePrevious; datetime _TimeCurrent; // string _fstr; int _tp; // void MaxOrders(int max_orders=5); //=++==============================================================++= int init() { if(_Symbol == "") _Symboll = Symbol(); // _Digitss = MarketInfo(_Symbol, MODE_DIGITS); _Points = MarketInfo(_Symbol, MODE_POINT); // if(_Timeframe == 0) _Timeframe = Period(); Print("v128-2 > init() >> _Timeframe=", _Timeframe, " rem4=",_IsStopLoss_0, " rem5=",_IsTrailingStop,_IsTrailingStopProfit); // _fstr = "v128_"; _tp = _FileReadWriteDouble(_fstr+"_tp.dat", 0); // убедиться в наличии файла, если его нет - создать Print("v128-2 > init() >> _Timeframe=", _Timeframe, " _tp=",_tp); // _TimePrevious=iTime(_Symbol, _Timeframe, 0); // Print("v128-2 > Завершено: init() >> _TimePrevious=", _TimePrevious, " (", TimeToStr(_TimePrevious,TIME_DATE|TIME_MINUTES), ")"); return(0); } //=++==============================================================++= int start() { double P_Close1, P_Close2; double BB_1_upper, BB_1_lower; double MA1_0, MA2_0; double P_ask, P_bid; bool is_signal_2_buy, is_signal_2_sell; double P1_buy, P2_buy, P3_buy; double P1_sell, P2_sell, P3_sell; bool is_b1 = false, is_s1 = false; bool is_b2 = false, is_s2 = false; int ticket; // _TimeCurrent = iTime(_Symbol, _Timeframe, 0); if(_TimeCurrent != _TimePrevious) { MA1_0 = iMA(_Symbol, _MA1_Timeframe, _MA1_Period, _MA1_Shift, _MA1_Method, _MA1_Applied_Price, 0); MA2_0 = iMA(_Symbol, _MA2_Timeframe, _MA2_Period, _MA2_Shift, _MA2_Method, _MA2_Applied_Price, 0); BB_1_upper = iBands(_Symbol, _Timeframe, _BB_Period,_BB_Deviation,_BB_Bands_Shift,_BB_Applied_Price, MODE_UPPER, 1); BB_1_lower = iBands(_Symbol, _Timeframe, _BB_Period,_BB_Deviation,_BB_Bands_Shift,_BB_Applied_Price, MODE_LOWER, 1); P_Close1 = iClose(_Symbol, _Timeframe, 1); P_Close2 = iClose(_Symbol, _Timeframe, 2); P_ask = MarketInfo(_Symbol, MODE_ASK); P_bid = MarketInfo(_Symbol, MODE_BID); Print("v120-4 > ", _Symbol, " | ", _Timeframe, " -> MA1_0=", MA1_0, " | MA2_0=", MA2_0, " -> BB_1_upper=", BB_1_upper, " | BB_1_lower=", BB_1_lower, " -> P_Close1=", P_Close1, " | P_Close2=", P_Close2, " -> ask=", P_ask, " | bid=", P_bid); // is_signal_2_buy = P_bid >= MA1_0 && P_bid >= MA2_0 && P_Close1 >= BB_1_lower && P_Close2 <= BB_1_lower && P_bid >= BB_1_lower; is_signal_2_sell = P_bid <= MA1_0 && P_bid <= MA2_0 && P_Close1 <= BB_1_upper && P_Close2 >= BB_1_upper && P_bid <= BB_1_upper; Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> is_signal2 -> buy=", is_signal_2_buy, " | sell=", is_signal_2_sell); // ========== по рынку // ========== открытие ордера BUY if( is_signal_2_buy ) { Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> сигнал на открытие ордера BUY"); OrdersDeleteAll(OP_SELL); // if(!is_b1 || !is_b2) { P1_buy = P_ask; P3_buy = FindPriceMinMax(false) - (_SpaseFromMaxMin) * _Point; _tp = (P1_buy - P3_buy) / _Point * (_TakeProfit1_Proc / 100.0); P2_buy = DoubleTestZero(_tp, P1_buy + (_tp) * _Point); // _FileWriteDouble(_fstr+"_tp.dat", _tp); // Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> BUY -> P1_buy=", P1_buy, " | P2_buy=", P2_buy, " | P3_buy=", P3_buy, "_tp=", _tp); // ticket = OrderSend(_Symbol, OP_BUY, _Lots0_1, ND(P1_buy), _Slippage, ND(P3_buy), ND(P2_buy), NULL, _Magic1, 0, CLR_NONE); if(ticket == -1) Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> BUY (1) > Ошибка (открытие) #", GetLastError()); else is_b1 = true; // ticket = OrderSend(_Symbol, OP_BUY, _Lots0_2, ND(P1_buy), _Slippage, ND(P3_buy), 0, NULL, _Magic2, 0, CLR_NONE); if(ticket == -1) Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> BUY (2) > Ошибка (открытие) #", GetLastError()); else is_b2 = true; // } else { is_b1 = true; is_b2 = true; } } else { is_b1 = true; is_b2 = true; } //Print("= buy +++",is_b1,is_b2,"==",is_s1,is_s2); // ========== открытие ордера SELL if( is_signal_2_sell ) { Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> сигнал на открытие ордера SELL"); OrdersDeleteAll(OP_BUY); // if(!is_s1 || !is_s2) { P1_sell = P_bid; P3_sell = FindPriceMinMax(true) + (_SpaseFromMaxMin) * _Point; _tp = (P3_sell - P1_sell) / _Point * (_TakeProfit1_Proc / 100.0); P2_sell = DoubleTestZero(_tp, P1_sell - (_tp) * _Point); // _FileWriteDouble(_fstr+"_tp.dat", _tp); // Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> BUY -> P1_sell=", P1_sell, " | P2_sell=", P2_sell, " | P3_sell=", P3_sell); // ticket = OrderSend(_Symbol, OP_SELL, _Lots0_1, ND(P1_sell), _Slippage, ND(P3_sell), ND(P2_sell), NULL, _Magic1, 0, CLR_NONE); if(ticket == -1) Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> SELL (1) > Ошибка (открытие) #", GetLastError()); else is_s1 = true; // ticket = OrderSend(_Symbol, OP_SELL, _Lots0_2, ND(P1_sell), _Slippage, ND(P3_sell), 0, NULL, _Magic2, 0, CLR_NONE); if(ticket == -1) Print("v128-2 > ", _Symbol, " | ", _Timeframe, " -> SELL (2) > Ошибка (открытие) #", GetLastError()); else is_s2 = true; // } else { is_s1 = true; is_s2 = true; } } else { is_s1 = true; is_s2 = true; } //Print("= sell +++",is_b1,is_b2,"==",is_s1,is_s2); // ========== if(is_b1 && is_s1 && is_b2 && is_s2) _TimePrevious=_TimeCurrent; } // if(_IsTrailingStop) { if( !FindOrders(_Magic1) ) TrailingStop(_tp); } // if(_IsStopLoss_0) StopLoss_0(_StopLoss_0_From); // return(0); } //=++==============================================================++= double DoubleTestZero(double value, double new_value) { if(value==0) return(value); else return(new_value); } //=++==============================================================++= double ND(double value) { return( NormalizeDouble(value, _Digits) ); } //=++==============================================================++= // закрытие ордеров. Завершение при закрытии всех void OrdersDeleteAll(int cmd) { while(CountOrders(cmd) > 0) { for(int i = OrdersTotal() - 1; i >= 0 ; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if( (OrderSymbol() == _Symbol) && (OrderMagicNumber() == _Magic1 || OrderMagicNumber() == _Magic2) && (OrderType() == cmd) ) { if(OrderType() == OP_BUY) if(!OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), _Slippage, CLR_NONE)) Print("v128-2 > ", _Symbol, " > BUY -> ticket=", OrderTicket(), " -> Ошибка (закрытие) #", GetLastError()); if(OrderType() == OP_SELL) if(!OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), _Slippage, CLR_NONE)) Print("v128-2 > ", _Symbol, " > SELL -> ticket=", OrderTicket(), " -> Ошибка (закрытие) #", GetLastError()); } } } } // количество ордеров } //=++==============================================================++= // подсчёт количества ордеров по направлению int CountOrders(int cmd) { int n = 0; for(int i = OrdersTotal() - 1; i >= 0 ; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if( (OrderSymbol() == _Symbol) && (OrderMagicNumber() == _Magic1 || OrderMagicNumber() == _Magic2) && (OrderType() == cmd) ) n++; } } return(n); } //=++==============================================================++= // поиск ордера по магику bool FindOrders(int magic) { for(int i = OrdersTotal() - 1; i >= 0 ; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if( (OrderSymbol() == _Symbol) && (OrderMagicNumber() == magic) ) return(true); } } return(false); } //=++==============================================================++= // отработка уровня безубытка по магику void StopLoss_0(int from) { double profitpoint, bid, ask; bool is; double P3_buy, P3_sell; // for(int i = OrdersTotal() - 1; i >= 0 ; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(!( (OrderSymbol() == _Symbol) && (OrderMagicNumber() == _Magic1 || OrderMagicNumber() == _Magic2) )) continue; // if(OrderType() == OP_BUY) { bid = MarketInfo(_Symbol, MODE_BID); profitpoint = (bid - OrderOpenPrice()) / _Point; is = profitpoint >= _StopLoss_0_Level + from; P3_buy = ND( OrderOpenPrice() + from * _Point ); // if( is && ( OrderStopLoss() == 0 || OrderStopLoss() < P3_buy ) ) { Print("v128-2 б4 >", _Symbol, " | ", _Timeframe, " -> Bid=", MarketInfo(_Symbol, MODE_BID), " | p/o=", OrderOpenPrice(), " | s/l=", OrderStopLoss(), " | P3_buy=", P3_buy, " | d=", _StopLoss_0_Level, " | profitpoint=", profitpoint); if(!OrderModify(OrderTicket(), OrderOpenPrice(), P3_buy, OrderTakeProfit(), 0, CLR_NONE)) Print("v128-2 б4 > ", _Symbol, " | ", _Timeframe, " -> BUY > ticket=", OrderTicket(), " > Ошибка (безубыток) #", GetLastError()); } } // else if(OrderType() == OP_SELL) { ask = MarketInfo(_Symbol, MODE_ASK); profitpoint = (OrderOpenPrice() - ask) / _Point; is = profitpoint >= _StopLoss_0_Level + from; P3_sell = ND( OrderOpenPrice() - from * _Point ); // if( is && ( OrderStopLoss() == 0 || OrderStopLoss() > P3_sell ) ) { Print("v128-2 б4 >", _Symbol, " | ", _Timeframe, " -> Ask =", MarketInfo(_Symbol, MODE_ASK), " | p/o=", OrderOpenPrice(), " | s/l=", OrderStopLoss(), " | P3_sell=", P3_sell, " | d=", _StopLoss_0_Level, " | profitpoint=", profitpoint); if(!OrderModify(OrderTicket(), OrderOpenPrice(), P3_sell, OrderTakeProfit(), 0, CLR_NONE)) Print("v128-2 б4 > ", _Symbol, " | ", _Timeframe, " -> SELL -> ticket=", OrderTicket(), " > Ошибка (безубыток) #", GetLastError()); } } } } } //=++==============================================================++= // отработка трейлинг стопа по магику void TrailingStop(int from) { double profitpoint, bid, ask; double fromprice; // for(int i = OrdersTotal() - 1; i >= 0 ; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(!( (OrderSymbol() == _Symbol) && (OrderMagicNumber() == _Magic1 || OrderMagicNumber() == _Magic2) )) continue; // if(OrderType() == OP_BUY) { if(_IsTrailingStopProfit) fromprice = OrderOpenPrice() + from * _Point; else fromprice = OrderStopLoss(); // bid = MarketInfo(_Symbol, MODE_BID); profitpoint = (bid - ND(fromprice)) / _Point; // if( profitpoint >= _TrailingStopLevel && bid > (OrderStopLoss() + (_TrailingStopLevel + _TrailingStopStep) * _Point) ) { Print("v128-2 т4 >", _Symbol, " | ", _Timeframe, " -> Bid=", MarketInfo(_Symbol, MODE_BID), " | p/o=", OrderOpenPrice(), " | s/l=", OrderStopLoss(), " | d=", _TrailingStopLevel, " | profitpoint=", profitpoint); if(!OrderModify(OrderTicket(), OrderOpenPrice(), ND(bid - (_TrailingStopLevel) * _Point), OrderTakeProfit(), 0, CLR_NONE)) { Print("v128-2 т4 >", _Symbol, " | ", _Timeframe, " -> BUY > ticket=", OrderTicket(), " > Ошибка (трейлинг стоп) #", GetLastError()); } } } // else if(OrderType() == OP_SELL) { if(_IsTrailingStopProfit) fromprice = OrderOpenPrice() - from * _Point; else fromprice = OrderStopLoss(); // ask = MarketInfo(_Symbol, MODE_ASK); profitpoint = (ND(fromprice) - ask) / _Point; // if( profitpoint >= _TrailingStopLevel && ask < (OrderStopLoss() - (_TrailingStopLevel + _TrailingStopStep) * _Point) ) { Print("v128-2 т4 >", _Symbol, " | ", _Timeframe, " -> Ask=", MarketInfo(_Symbol, MODE_ASK), " | p/o=", OrderOpenPrice(), " | s/l=", OrderStopLoss(), " | d=", _TrailingStopLevel, " | profitpoint=", profitpoint); if(!OrderModify(OrderTicket(), OrderOpenPrice(), ND(ask + (_TrailingStopLevel) * _Point), OrderTakeProfit(), 0, CLR_NONE)) { Print("v128-2 т4 >", _Symbol, " | ", _Timeframe, " -> SELL > ticket=", OrderTicket(), " > Ошибка (трейлинг стоп) #", GetLastError()); } } } } } } //=++==============================================================++= // Поиск локального дна. Возвращает цену double FindPriceMinMax(bool isUp) { int shift = 1; double price = 0, p0,p1,p2; while(price == 0) { p0 = iCustom(_Symbol, _Timeframe, "ZigZag", _ZZ_ExtDepth, _ZZ_ExtDeviation, _ZZ_ExtBackstep, 0, shift); p1 = iCustom(_Symbol, _Timeframe, "ZigZag", _ZZ_ExtDepth, _ZZ_ExtDeviation, _ZZ_ExtBackstep, 1, shift); p2 = iCustom(_Symbol, _Timeframe, "ZigZag", _ZZ_ExtDepth, _ZZ_ExtDeviation, _ZZ_ExtBackstep, 2, shift); //Print("v128-2 >", _Symbol, " | ", _Timeframe, // " > sift=", shift, " | p0=", p0, " | p1=", p1, " | p2=", p2); if(isUp) { if(p0 !=0 && p0 == p1) // найдена вершина price = p0; } else { if(p0 != 0 && p0 == p2) // найдено дно price = p0; } shift++; } //Print("v128-2 >", _Symbol, " | ", _Timeframe, // " -> return(price)=", price); return(price); } //==================================================================== // Cчитать переменную из файла. // В случае отсутствия файла - создать файл и записать переменную в файл double _FileReadWriteDouble(string filename, double value) { int h1 = FileOpen(filename, FILE_BIN); if(h1 > 0) { value = FileReadDouble(h1, DOUBLE_VALUE); FileClose(h1); } else { h1 = FileOpen(filename, FILE_BIN|FILE_WRITE); FileWriteDouble(h1, value, DOUBLE_VALUE); FileClose(h1); } return(value); } //==================================================================== // Записать переменную в файл void _FileWriteDouble(string filename, double value) { int h1 = FileOpen(filename, FILE_BIN|FILE_WRITE); FileWriteDouble(h1, value, DOUBLE_VALUE); FileClose(h1); }