//+------------------------------------------------------------------+ //| ZiCoSandwich_v.1.2.mq4 | //| AriusKis | //| AriusKis@gmail.com | //| Добавлен еще фильтр для входа - вход по фракталу с нижнего ТФ и | //|перевод в безубыток + немного прибыли | //+------------------------------------------------------------------+ #property copyright "AriusKis" #property link "AriusKis@gmail.com" #property version "1.2" #property strict enum howstop { lastcorrection=0, //по коррекции main_swing=1 //по основному свингу }; enum howtotakeprofit { multipliersl=0, //по множителю от размера стопа target=1 //по цели - размер свинга }; //Если по размеру свинга, то проверяем соотношение тейка к стопу. enum howtoclose { take_profit=0, //выставлять тейк-профит tralaggr=1 //агрессивный трал по меньшему ТФ }; //Ниже опция по фиксации небольшой прибыли при переводе в безубыток. Если в процентах, то измеряется расстояние до текущей цены и берется интервал в %, который прибавляется к цене открытия enum bemode { noadd=0, //ничего не добавлять percent=1, //добавить в % от разницы pips=2 //добавить в пунктах }; struct ZigZagData { double point_1; //первая точка с конца double point_2; //вторая точка с конца double point_3; //третья точка с конца double point_4; //четвертая точка с конца double point_5; //пятая точка с конца double mainsize; //размер последнего свинга double maincorrec; //размер последней коррекции datetime time_1; //время открытия свечи на первой точке int shift_12; //кол-во свечей между точкой 1 и 2 int shift_23; //кол-во свечей между точкой 2 и 3 bool upward; //последний свинг: false - нисходящий, true - восходящий bool swingOK; //подходит свинг или нет }; struct orderdata { double BEprice; //цена для перевода в безубыток double SLvalue; //размер стоп-лосса int ticket; //тикет ордера bool alreadyBE; //переведен ли в безубыток }; enum yesorno { no=0, //нет yes=1 //да }; enum Colorstyle { styleGray=0, //серая градация styleRed=1, //красная градация styleBlue=2, //синяя градация styleGreen=3 //зеленая градация }; input string Head = " AriusKis@gmail.com |----- "; // -----| Created by AriusKis, email - input string ZigZagSettings = " индикатора ZigZag |----- "; // -----| Входные настройки input int InpDepth = 16; input int InpDeviation = 8; input int InpBackstep = 2; input string Levelssettings = " уровней |----- "; // -----| Настройки input bool Uselevels = true; //Использовать в торговле уровни? extern int Segment = 80; //Количество рассматриваемых баров input int Bar4Fract = 3; //Мин. кол-во баров для стороны фрактала extern double K_fading = 0.4; //Нижняя граница коэф. затухания (если = 1, то не учитывается) //Коэффициент затухания 1 соответствует 0му бару, нижняя граница коэффициента - последнему бару Segment. extern double K_speeddev = 0.5; //Девиация коэф-та скорости отскока(если=0, то не учитывается) //Коэффициент скорости отскока фрактала будет в пределах от 1-K_speeddev до 1+K_speeddev extern double K_distdev = 0.5; //Девиация коэф-та дальности отскока(если=0, то не учитывается) //Коэффициент дальности отскока фрактала будет в пределах от 1-K_distdev до 1+K_distdev input double K_round5 = 1.1; //Коэф. круглого уровня 5 (если=1, то не учитывается) input double K_round4 = 1.05; //Коэф. круглого уровня 4 (если=1, то не учитывается) input double K_round3 = 1.025; //Коэф. круглого уровня 3 (если=1, то не учитывается) input string VolText = "уровней |---------"; //---------| Параметры для расчета ширины extern int VolatBars = 120; //Кол-во баров для расчета волат-ти на текущем ТФ extern double K_volFloor = 0.1; //Нижняя граница коэффициента волатильности extern double K_volRoof = 4; //Верхняя граница коэффициента волатильности input bool LevsDraw = true; //Рисовать уровни? //Чем темнее уровень, тем он сильнее input Colorstyle Stylecolor = 0; //Цвет отрисовки уровней input bool Drawforward = true; //Рисовать уровни вперед по времени? input bool Textlabel = true; //Добавить надпись с силой уровня? input color Textcolor = clrBlack; //Цвет текстовой метки input string Settings4Entry = " для входа |----- "; // -----| Настройки input int VolatDays = 10; //Количество дней для расчета волатильности на D1 input double K_volat = 0.8; //Коэффициент вол-ти для миним. свинга input double Minswing = 300; //Минимальный свинг в пунктах input double Correctionmin = 10; //% коррекции для разворота минимальный input double Correctionmax = 100; //% коррекции для разворота максимальный input double EntryCorrmin = 50; //% коррекции для входа минимальный input double EntryCorrmax = 70; //% коррекции для входа максимальный input double K_Momentum = 1.2; //Миним. соотношение моментумов свингов основного/коррекции, если 0, то не используется input int TriggerLevel = 5; //Миним. уровень Sandwich для входа input double TriggerProc = 50; //% от осн. свинга для опр. касания уровня input double K_rotation = 1; //Коэф-т вращения цены на входе, если 0, то не используется input bool FollowTrend = true; //Использовать ли проверку на тренд input bool BreakOut = false; //Входить после прорыва фрактала на тек. или меньшем ТФ? input ENUM_TIMEFRAMES BOutTF = PERIOD_M1; //ТФ для проверки прорыва фрактала input string Formonitor = " сделкой |----- "; // -----| Настройки управления input howstop SLmode = 0; //Где выставлять стоп-лосс input double SLmin = 50; //Минимальный стоп-лосс в пунктах input int Indent = 20; //Отступ от экстр. для SL в пунктах input howtotakeprofit TPmode = 0; //Где ставить тейк-профит input double K_TP = 2; //Множитель от стопа для тейка при использовании т/п input double TakeStop = 1; //Минимальное отношение прибыль/убыток при исп-ии свингов для т/п input howtoclose CloseMode = 0; //Как выходим из сделки? input ENUM_TIMEFRAMES Tralperiod = PERIOD_M5; //Таймфрейм для агрессивного трала input int MinPipstral = 50; //Минимальный размер трейлинг-стопа в пунктах input yesorno SwitchBE = 0; //Использовать перевод в безубыток? input double K_BE = 1; //Коэффициент от стоп-лосса для перевода в б/у input bemode Whatplus = 0; //Ставить С/Л чуть выше цены б/у? input double PipsOrProc = 70; input string AdditionalSet = " настройки |----- "; // -----| Дополнительные input double Risk = 1; //Риск на сделку, % от депо input int SpreadMax = 30; //Допустимый спред в пунктах input int SleepSec = 20; //Время ожидания в секундах при неудовл. спреде input int Slippage = 30; input int Magic = 222; datetime opentime=0; ZigZagData ZZD = {0,0,0,0,0,0,0,0,0,0,false, false}; bool first_condition=false; int orderdir = -1; orderdata sellOD = {0,0,0,false}; orderdata buyOD = {0,0,0,false}; double memoryprice; double tpvirtuaLbuy = 10000, tpvirtuaLsell = 0; int Fractals[][7]; //0 - номер бара фрактала, 1 - вид фрактала (1 - нижний, 2 - верхний), 2 - сила фрактала, 3 - цена фрактала, 4 - учтен или нет при подсчете силы уровней, 5 - нижняя граница по цене, 6 - верхняя граница по цене int FrMembers=0; //string labels = "sandwich"; //для отладки силы фракталов double Maxlevel, Maxfractal, Minfractal; int Levelsmain[][2]; //Массив с силой уровней 0 - сила уровня по десятибальной, 1 - верхняя граница дискреции цены int LEVELS[][2]; //Главный массив, содержащий силы уровней, 0 - сила по 10 бальной, 1 - верхняя граница цены bool allowtrading=true; color Color1, Color2, Color3, Color4, Color5, Color6, Color7, Color8, Color9, Color10; int lastfractal; bool wait4BOut=false; double BOutlevel=0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if(InpDepth<=0 || InpBackstep<=0 || InpDeviation<=0) { Alert("Входные параметры для ZigZag должны быть больше нуля!"); return(INIT_FAILED); } if(VolatDays<2) { Alert("Количество дней для расчета волатильности должно быть больше одного!"); return(INIT_FAILED); } if(K_volat<0 || Minswing<0 || Correctionmin<0 || Correctionmax<0 || EntryCorrmin<0 || EntryCorrmax<0) { Alert("Все настройки для входа не могут быть ниже нуля!"); return(INIT_FAILED); } if(Correctionmin>=Correctionmax || EntryCorrmin>=EntryCorrmax) { Alert("Неверно выставлены % коррекций! Минимальные должны быть больше максимальных!"); return(INIT_FAILED); } if(K_TP<=0 || Slippage<=0 || Magic<=0) { Alert("Дополнительные настройки - отношение тейка к стопу, Slippage и Magic должны быть больше нуля!"); return(INIT_FAILED); } if(CloseMode==tralaggr && Tralperiod>_Period) { Alert("Агрессивный трал не может быть по таймфрейму больше текущего!"); return(INIT_FAILED); } if(K_Momentum<0) { Alert("Соотношение моментумов не может быть ниже нуля!"); return(INIT_FAILED); } if(K_rotation<0) { Alert("Коэффициент вращения не может быть ниже нуля!"); return(INIT_FAILED); } if(Whatplus==1 && PipsOrProc<0 && PipsOrProc>90) { Alert("Прибавка % к безубытку не может быть ниже нуля либо выше 90%!"); return(INIT_FAILED); } if(Whatplus==2 && PipsOrProc<0) { Alert("Прибавка в пунктах к безубытку не может быть ниже нуля!"); return(INIT_FAILED); } if(BreakOut && BOutTF>_Period) { Alert("Таймфрейм для проверки прорыва по фракталам должен быть не больше текущего таймфрейма!"); return(INIT_FAILED); } if(Uselevels) { if(K_round3>K_round4 || K_round4>K_round5) { Alert("Неверны входные данные для коэффициентов круглого уровня, К5 должен быть больше К4, а К4 больше К3!"); return(INIT_FAILED); } if(K_fading<0 || K_fading>1) { Alert("Неверное значение нижней границы коэффициента затухания! Должен быть в пределах от 0 до 1!"); return(INIT_FAILED); } if(Bar4Fract<2 || Bar4Fract>Segment/2) { Alert("Неверное значение количества баров для стороны фрактала! Значение должно быть от 2 до половины количества рассматриваемых баров!"); return(INIT_FAILED); } if(K_speeddev<0 || K_speeddev>1) { Alert("Неверное значение девиации коэффициента скорости отскока! Девиация должна быть в пределах от 0 до 1!"); return(INIT_FAILED); } if(K_distdev<0 || K_distdev>1) { Alert("Неверное значение девиации коэффициента дальности отскока! Девиация должна быть в пределах от 0 до 1!"); return(INIT_FAILED); } if(Segment<10) { Alert("Слишком малое значение количества рассматриваемых баров! Должно быть более 10!"); return(INIT_FAILED); } if(K_volFloor<=0 || K_volFloor>K_volRoof) { Alert("Неверные значения границ коэффициента волатильности! Должны быть больше нуля и нижняя граница меньше или равна верхней границе!"); return(INIT_FAILED); } FrMembers = Segment/2; ArrayResize(Fractals,FrMembers,0); FillExtremePowers(); FractalsAndLevels(); if(LevsDraw) { switch(Stylecolor) { case 0: Color1=C'235,235,235'; Color2=C'215,215,215'; Color3=C'195,195,195'; Color4=C'175,175,175'; Color5=C'155,155,155'; Color6=C'135,135,135'; Color7=C'115,115,115'; Color8=C'95,95,95'; Color9=C'75,75,75'; Color10=C'55,55,55'; break; case 1: Color1=C'255,235,235'; Color2=C'255,185,185'; Color3=C'255,135,135'; Color4=C'255,85,85'; Color5=C'255,35,35'; Color6=C'230,0,0'; Color7=C'180,0,0'; Color8=C'130,0,0'; Color9=C'80,0,0'; Color10=C'30,0,0'; break; case 2: Color1=C'235,235,255'; Color2=C'185,185,255'; Color3=C'135,135,255'; Color4=C'85,85,255'; Color5=C'35,35,255'; Color6=C'0,0,230'; Color7=C'0,0,180'; Color8=C'0,0,130'; Color9=C'0,0,80'; Color10=C'0,0,30'; break; case 3: Color1=C'235,255,235'; Color2=C'185,255,185'; Color3=C'135,255,135'; Color4=C'85,255,85'; Color5=C'35,255,35'; Color6=C'0,230,0'; Color7=C'0,180,0'; Color8=C'0,130,0'; Color9=C'0,80,0'; Color10=C'0,30,0'; break; } Drawlevels(); } lastfractal = Fractals[0,0]; } opentime = Time[0]; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(Uselevels && LevsDraw) Deletelevels(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(Time[0]!=opentime) { FillZigZagData(); if(Uselevels) { lastfractal++; if(Findnewfractal()) { FractalsAndLevels(); lastfractal=Fractals[0,0]; if(LevsDraw) { Deletelevels(); Drawlevels(); } } } if(ZZD.swingOK) first_condition = CheckSignal(); else first_condition = false; if(ZZD.point_1==memoryprice) first_condition = false; //Ждем обновления экстремума зиг-зага if(CloseMode==tralaggr) //агрессивный трал - один раз за свечу проверяем Monitortral(); wait4BOut = false; //флаг обнулили - возможно, другие условия на вход перестали соответствовать opentime=Time[0]; } if(first_condition) { if(!wait4BOut) Monitor4entry(false); else CompareBOLev(); } if(SwitchBE==1) MonitorBE(); } //+------------------------------------------------------------------+ //| Функция-индикатор появления нового фрактала | //+------------------------------------------------------------------+ int Findnewfractal() { int a, n; int aimlow, aimhigh; for(a=1; a<=Segment-Bar4Fract; a++) { aimlow = iLowest(_Symbol, 0, MODE_LOW, Bar4Fract*2+1, a); aimhigh = iHighest(_Symbol, 0, MODE_HIGH, Bar4Fract*2+1, a); n = a+Bar4Fract; if(aimlow==n || aimhigh==n) //Есть фрактал { if(npricemax) pricemax=highnow; } if(Fractals[f,0]==0) break; } length = (int)((pricemax-pricemin)/Point()); if(length<=1000) { levmembers = length; step = 1; } else { if(length<=10000) { levmembers = length/10; step = 10; } else { if(length<=100000) { levmembers = length/100; step = 100; } else { if(length<=1000000) { levmembers = length/1000; step = 1000; } else { Alert("Слишком большой ценовой разброс для отрисовки уровней - ", DoubleToString(length), "! Поменяйте параметры, либо валютную пару!"); allowtrading = false; } } } } ArrayResize(Levelsmain,levmembers,0); ArrayInitialize(Levelsmain,0); pricemin = pricemin/Point(); for(x=0; x0) //Фрактал еще не учтен { if(Fractals[u,4]!=1 && Fractals[u,2]>frpower) //Находим максимальной силы фрактал из оставшихся { frnumber=u; frpower=Fractals[u,2]; } } else break; } if(frnumber>=0) { Fractals[frnumber,4]=1; highlevel = Fractals[frnumber,6]; lowlevel = Fractals[frnumber,5]; } else break; do { frnextflag=false; for(u=0; u0) { if(Fractals[u,4]!=1 && Fractals[u,6]>lowlevel && Fractals[u,5]highlevel) highlevel = Fractals[u,6]; } } else break; } } while(frnextflag); //Надо сразу учесть круглые уровни bool Round5=false, Round4=false, Round3=false; if(K_round5>1) { for(z=lowlevel+1; z<=highlevel; z++) { if((z/1000)*1000==z) Round3=true; if((z/10000)*10000==z) Round4=true; if((z/100000)*10000==z) Round5=true; } if(Round5) frpower = (int)round(frpower*K_round5); else { if(Round4) frpower = (int)round(frpower*K_round4); else { if(Round3) frpower = (int)round(frpower*K_round3); } } } //Тут посчитаем силу по 10бальной шкале и запишем в массив for(z=0; z<=lastmember; z++) { if(Levelsmain[z,1]>lowlevel && Levelsmain[z,1]<=highlevel) { Levelsmain[z,0]=(int)(((9*frpower)/Maxlevel)+1); //Записали силу по 10-бальной if(Levelsmain[z,0]>10) Levelsmain[z,0]=10; } } if(lowlevel10) lowpower=10; } if(highlevel>levelend) //Если выходим свехру за рамки массива { endnew = highlevel; highpower = (int)(((9*frpower)/Maxlevel)+1); if(highpower>10) highpower=10; } } while(frpower>0); //Теперь надо объединить основной массив и расширение снизу и сверху, если есть int addmemberslow=0, addmembershigh=0, members; if(startnew!=0) //если снизу надо добавить addmemberslow = (int)MathCeil((levelstart-startnew)/step); if(endnew!=0) //если сверху надо добавить addmembershigh = (int)MathCeil((endnew-levelend)/step); members = lastmember + 1 + addmembershigh + addmemberslow; ArrayResize(LEVELS,members,0); ArrayInitialize(LEVELS,0); if(addmemberslow!=0) //Добавляем снизу { for(z=addmemberslow-1; z>=0; z--) { LEVELS[z,0]=lowpower; LEVELS[z,1]=levelstart-step*(addmemberslow-1-z); } } for(z=0; z<=lastmember; z++) //Основное тело массива { LEVELS[z+addmemberslow,0]=Levelsmain[z,0]; LEVELS[z+addmemberslow,1]=Levelsmain[z,1]; } if(addmembershigh!=0) //Добавляем сверху { for(z=lastmember+addmemberslow+1; z0) { Maxfractal *= (1+K_speeddev); Minfractal *= (1-K_speeddev); Maxlevel *= (1+K_speeddev); } if(K_distdev>0) { Maxfractal *= (1+K_distdev); Minfractal *= (1-K_distdev); Maxlevel *= (1+K_distdev); } if(K_round5>1) Maxlevel *= K_round5; } //+------------------------------------------------------------------+ //| Находим силу фракталов и дополняем массив | //+------------------------------------------------------------------+ void FractalsPower() { int j,s,p; int maxright, maxleft, addbar; double extremeprice, rightpricedif=0, leftpricedif=0; double frprice, levelwidth; int fractal; int basicpower; double currentpower, volatility; int leftspeed=0, rightspeed=0; int lefthigh, righthigh, leftlow, rightlow; double K_curFading; //Текущий коэффициент затухания double K_curSpeed=1, K_realSpeed=1; //Текущий коэффициент скорости и реальный без перевода double K_curDist=1, K_realDist=1; //Текущий коэффициент дальности и реальный без перевода double price4speed; //Значение цены для нахождения скорости ее движения до и после фрактала double K_volCur=0; //Текущий коэффициент волатильности для фрактала volatility = Volatility(VolatBars,_Period)/_Point; //получили в волатильность в пунктах for(j=0; j0; s--) //Идем от фрактала до нулевого бара (Bar4Fract баров уже учли по бокам, когда искали фракталы) { if(frprice0; s--) //Идем от фрактала до нулевого бара (два бара уже учли по бокам, когда искали фракталы) { if(frprice>High[s]) maxright++; else break; } for(s=fractal+Bar4Fract+1; sHigh[s]) maxleft++; else break; } } basicpower=MathMin(maxleft,maxright); //Базовая сила фрактала //Теперь считаем с учетом затухания K_curFading = 1 - ((double)fractal/Segment)*(1-K_fading); //Текущий коэффициент затухания (будет = 1, если K_fading=1) currentpower=basicpower*K_curFading; //Нашли силу фрактала с учетом затухания, либо без, если K_curFading=1 //при учете коэффициента скорости отскока if(K_speeddev>0) //Если учитываем коэффициент скорости отскока { if(Fractals[j,1]==1) //Если нижний фрактал { if(Open[fractal]>=Close[fractal]) //Фрактальная свеча медвежья или доджи addbar=0; else //Фрактальная свеча бычья addbar=1; lefthigh = iHighest(Symbol(),0,MODE_HIGH,basicpower+1,fractal+addbar); righthigh = iHighest(Symbol(),0,MODE_HIGH,basicpower+addbar,fractal-basicpower); leftspeed = lefthigh - fractal + 1 - addbar; rightspeed = fractal - righthigh + addbar; if(High[lefthigh]=fractal-basicpower; p--) //считаем количество баров справа до достижения заданной цены { rightspeed++; if(High[p]>=price4speed) break; } } if(High[lefthigh]>High[righthigh]) { price4speed = High[righthigh]; leftspeed=0; for(p=fractal+addbar; p<=fractal+basicpower; p++) { leftspeed++; if(High[p]>=price4speed) break; } } } if(Fractals[j,1]==2) //Если верхний фрактал { if(Open[fractal]>=Close[fractal]) //Фрактальная свеча медвежья или доджи addbar=1; else //Фрактальная свеча бычья addbar=0; leftlow = iLowest(Symbol(),0,MODE_LOW,basicpower+1,fractal+addbar); rightlow = iLowest(Symbol(),0,MODE_LOW,basicpower+addbar,fractal-basicpower); leftspeed = leftlow - fractal + 1 - addbar; rightspeed = fractal - rightlow + addbar; if(Low[leftlow]>Low[rightlow]) //за сравниваемое значение берем более высокий лоу, при равенстве ничего не меняем { price4speed = Low[leftlow]; rightspeed=0; for(p=fractal-1+addbar; p>=fractal-basicpower; p--) //считаем количество баров справа до достижения заданной цены { rightspeed++; if(Low[p]<=price4speed) break; } } if(Low[leftlow]1) K_curSpeed = ((K_speeddev*(K_realSpeed-1)*(Segment-1))/(K_realSpeed*(Segment-2)))+1; //Для правильности должно колебаться от 1 до 2 else { if(K_realSpeed<1) K_curSpeed = 1 - ((K_speeddev*(1-K_realSpeed)*(Segment-1))/(Segment-2)); else K_curSpeed = K_realSpeed; } currentpower *= K_curSpeed; //Находим итоговую силу фрактала } //При учете коэффициента дальности отскока if(K_distdev>0) { if(Fractals[j,1]==1) //Если нижний фрактал { if(Open[fractal]>=Close[fractal]) //Фрактальная свеча медвежья или доджи addbar=0; else //Фрактальная свеча бычья addbar=1; lefthigh = iHighest(Symbol(),0,MODE_HIGH,basicpower+1,fractal+addbar); righthigh = iHighest(Symbol(),0,MODE_HIGH,basicpower+addbar,fractal-basicpower); extremeprice = Low[fractal]; leftpricedif = High[lefthigh]-extremeprice; rightpricedif = High[righthigh]-extremeprice; } if(Fractals[j,1]==2) //Если верхний фрактал { if(Open[fractal]>=Close[fractal]) //Фрактальная свеча медвежья или доджи addbar=1; else //Фрактальная свеча бычья addbar=0; leftlow = iLowest(Symbol(),0,MODE_LOW,basicpower+1,fractal+addbar); rightlow = iLowest(Symbol(),0,MODE_LOW,basicpower+addbar,fractal-basicpower); extremeprice = High[fractal]; leftpricedif = extremeprice-Low[leftlow]; rightpricedif = extremeprice-Low[rightlow]; } if(leftpricedif!=0) K_realDist = rightpricedif/leftpricedif; else K_realDist = 1000; if(K_realDist<1) //Справа расстояние меньше, чем слева K_curDist = 1 - K_distdev*(1-K_realDist); else { if(K_realDist>1) K_curDist = ((K_distdev*(K_realDist-1))/K_realDist)+1; else K_curDist = K_realDist; } currentpower *= K_curDist; } Fractals[j,2]=(int)round(currentpower); //Итоговая сила фрактала с учетом всех коэффициентов //Теперь сразу находим границы сверху и снизу в зависимости от волатильности K_volCur = K_volRoof - (((K_volRoof-K_volFloor)*(Maxfractal-currentpower))/(Maxfractal-Minfractal)); levelwidth = (volatility*K_volCur)/2; Fractals[j,5]=(int)round(Fractals[j,3]-levelwidth); //Нижняя граница Fractals[j,6]=(int)round(Fractals[j,3]+levelwidth); //Верхняя граница влияния } } //+--------------------------------------------------------------------+ //| Функция по трейлинг-стопу с таймфрейма меньше или равному текущему | //+--------------------------------------------------------------------+ void Monitortral() { double stop_new=0; int j; bool resultat; if(CountOrders(0)>0 && Bid>=tpvirtuaLbuy) { for(j=1; j0) { if((Bid-stop_new)/_Point < MinPipstral) Print("Стоп по тралу слишком близко к текущей цене! Ищу дальше!"); else break; } } if(stop_new0 && Ask<=tpvirtuaLsell) { for(j=1; j0) { if((stop_new-Ask)/_Point < MinPipstral) Print("Стоп по тралу слишком близко к текущей цене! Ищу дальше!"); else break; } } if(stop_new>Ask) { if(OrderSelect(sellOD.ticket,SELECT_BY_TICKET,MODE_TRADES)) { if(OrderStopLoss()>stop_new) { if(IsTesting()) resultat = OrderModify(OrderTicket(),OrderOpenPrice(),stop_new,OrderTakeProfit(),0,clrNONE); else resultat = OrderModifyx(OrderTicket(),OrderOpenPrice(),stop_new,OrderTakeProfit(),0,clrNONE); } } } } } //+------------------------------------------------------------------+ //| Проверяем триггер для перевода в безубыток и переводим | //+------------------------------------------------------------------+ void MonitorBE() { bool modanswer = false; double price4BE=0; if(!buyOD.alreadyBE && CountOrders(0)>0) //Проверка ордера на покупку { if(Bid>=buyOD.BEprice && OrderSelect(buyOD.ticket,SELECT_BY_TICKET,MODE_TRADES)) { if(Whatplus==0) price4BE = OrderOpenPrice(); else price4BE = AddtoBE(0,OrderOpenPrice()); if(IsTesting()) modanswer = OrderModify(OrderTicket(),OrderOpenPrice(),price4BE,OrderTakeProfit(),0,clrNONE); else modanswer = OrderModifyx(OrderTicket(),OrderOpenPrice(),price4BE,OrderTakeProfit(),0,clrNONE); } if(modanswer) buyOD.alreadyBE = true; } modanswer = false; if(!sellOD.alreadyBE && CountOrders(1)>0) //Проверка ордера на продажу { if(Ask<=sellOD.BEprice && OrderSelect(sellOD.ticket,SELECT_BY_TICKET,MODE_TRADES)) { if(Whatplus==0) price4BE = OrderOpenPrice(); else price4BE = AddtoBE(1,OrderOpenPrice()); if(IsTesting()) modanswer = OrderModify(OrderTicket(),OrderOpenPrice(),price4BE,OrderTakeProfit(),0,clrNONE); else modanswer = OrderModifyx(OrderTicket(),OrderOpenPrice(),price4BE,OrderTakeProfit(),0,clrNONE); } if(modanswer) sellOD.alreadyBE = true; } } //+------------------------------------------------------------------+ //| Вычисление цены с добавлением прибыли к безубытку | //+------------------------------------------------------------------+ double AddtoBE(int typeord, double ordopenprice) { double SPread = MarketInfo(_Symbol,MODE_SPREAD); double SLnew = ordopenprice; double sizeadd=0, allowlevel=0; if(Whatplus==1) //если нужно высчитывать процент { if(typeord==0) sizeadd = (Bid-ordopenprice)*PipsOrProc/100; if(typeord==1) sizeadd = (ordopenprice-Ask)*PipsOrProc/100; } if(Whatplus==2) //если просто прибавляем пункты sizeadd = PipsOrProc*_Point; //Находим и проверяем близость нового стопа к текущей цене - условие такое, что не ближе, чем еще один размер спреда //Если будет ближе - корректируем на максимально близкое значение if(typeord==0) //Если ордер на покупку { SLnew = ordopenprice + sizeadd; allowlevel = Bid - SPread*_Point; SLnew = MathMin(SLnew,allowlevel); } if(typeord==1) //Ордер на продажу { SLnew = ordopenprice - sizeadd; allowlevel = Ask + SPread*_Point; SLnew = MathMax(SLnew,allowlevel); } SLnew = NormalizeDouble(SLnew,_Digits); return(SLnew); } //+------------------------------------------------------------------+ //| Проверяем наличие второго сигнала и входим | //+------------------------------------------------------------------+ void Monitor4entry(bool secondtime) //Secondtime = true, если функция вызывается не из OnTick { bool action_1 = false, action_2 = false, action_3 = false, action_4 = false, action_5 = false, action_6 = false; double mom_swing, mom_cor; double corrnow = (MathAbs(ZZD.point_1-Bid))/ZZD.maincorrec; //первая проверка и основная - наличие уже открытых ордеров, коррекция if(orderdir==0) { if(CountOrders(0)>0) //сразу стопорим, если уже есть ордера return; if(corrnow >= EntryCorrmin/100 && corrnow <= EntryCorrmax/100) //Второе условие для входа - нужное движение по коррекции в сторону основного свинга action_1 = true; } else { if(CountOrders(1)>0) return; if(corrnow >= EntryCorrmin/100 && corrnow <= EntryCorrmax/100) action_1 = true; } //вторая проверка - проверяем уровень if(action_1) { if(Uselevels) { if(CheckLevTrig()) action_2=true; else first_condition = false; //на следующей свече опять проверяем - уровень может приблизиться } else action_2=true; } //Третья проверка на вход - проверяем вращение цены на развороте коррекции if(action_2) { if(K_rotation>0) { if(Rotation()) action_3=true; else { Print("Вращение цены неудовлетворительно! Пропускаю вход!"); //в следующий раз проверяем только тогда, когда первая точка зиг-зага обновится first_condition=false; memoryprice=ZZD.point_1; } } else action_3=true; } //Четвертая проверка на вход - есть ли тренд (по предыдущему за основным свингу) if(action_3) { if(FollowTrend) { if(Trend()) action_4=true; else { Print("Нет тренда по ZigZag!"); //в следующий раз проверка - только после обновления первой точки зиг-зага memoryprice = ZZD.point_1; first_condition = false; } } else action_4=true; } //Пятая проверка на вход - проверяем моментум основного свинга и коррекции if(action_4) { if(K_Momentum==0) action_5 = true; else { mom_swing = ZZD.mainsize/ZZD.shift_23; mom_cor = ZZD.maincorrec/ZZD.shift_12; if(mom_swing/mom_cor>=K_Momentum) //Если моментум основного свинга больше моментума коррекции в х раз action_5 = true; else { Print("Моментум коррекции неудовлетворительный для входа в сделку!"); //следующая проверка - после обновления первой точки зиг-зага memoryprice = ZZD.point_1; first_condition = false; } } } //Шестая проверка - пробит или нет фрактал с меньшего таймфрейма if(action_5) { if(BreakOut && !secondtime) { if(CheckBreakOut()) action_6 = true; else wait4BOut = true; //установили флаг, что ждем прорыва фрактала } else action_6 = true; } if(action_6) DealOpen(orderdir); } //+------------------------------------------------------------------+ //| Проверяем прорыв по фракталам с нижнего таймффрейма | //+------------------------------------------------------------------+ bool CheckBreakOut() { int modeFract, f; bool responce=false; BOutlevel = 0; if(orderdir==0) modeFract = MODE_UPPER; else modeFract = MODE_LOWER; for(f=1; f0) break; } if(orderdir==0) { if(Bid>BOutlevel) return(true); } else { if(Bid=ZZD.point_2 && ZZD.point_5>ZZD.point_3) return(true); } return(false); } //+-----------------------------------------------------------------------------------------+ //| Проверка вращения цены перед входом, для лучшей точности проверяем на меньшем таймфрейме| //+-----------------------------------------------------------------------------------------+ bool Rotation() { int barsbefore=1, barsafter=1, realextr=0; int g; int periodlook = PERIOD_M1; int checkbars = 0; //количество баров для проверки реального экстремума int countbars = 0; //стартовая точка switch (_Period) { case PERIOD_MN1: periodlook = PERIOD_W1; checkbars = 5; break; case PERIOD_W1: periodlook = PERIOD_D1; checkbars = 7; break; case PERIOD_D1: periodlook = PERIOD_H4; checkbars = 6; break; case PERIOD_H4: periodlook = PERIOD_H1; checkbars = 4; break; case PERIOD_H1: periodlook = PERIOD_M30; checkbars = 2; break; case PERIOD_M30: periodlook = PERIOD_M15; checkbars = 2; break; case PERIOD_M15: periodlook = PERIOD_M5; checkbars = 3; break; default: periodlook = PERIOD_M1; checkbars = 5; } for(g=1; g=ZZD.time_1) countbars++; else //прошли точку экстремума break; } //теперь находим реальный экстремум if(ZZD.upward) realextr = iLowest(_Symbol,periodlook,MODE_LOW,checkbars,countbars-checkbars+1); else realextr = iHighest(_Symbol,periodlook,MODE_HIGH,checkbars,countbars-checkbars+1); barsafter = realextr+1; for(g=realextr; g=Bid) { barsbefore = g-realextr+1; break; } } else { if(iLow(_Symbol,periodlook,g)<=Bid) { barsbefore = g-realextr+1; break; } } } //А теперь проверяем соотношение количества свеч после к количеству свеч до if((double)barsbefore/barsafter >= K_rotation) return(true); return(false); } //+-------------------------------------------------------------------------------------------+ //| Проверка касания ценой коррекции уровня с учетом области касания по % от основного свинга | //+-------------------------------------------------------------------------------------------+ bool CheckLevTrig() { bool signal = false; bool wearein = false; //Флаг того, что мы зацепили наш интервал int LEVCUR=0, g; int Members = ArrayRange(LEVELS,0); int Step = LEVELS[1,1]-LEVELS[0,1]; double tr_bottom, tr_roof, half; half = (ZZD.mainsize*TriggerProc/100)/2; tr_bottom = ZZD.point_1 - half; //нашли нижнюю границу интервала цены tr_roof = ZZD.point_1 + half; //нашли верхнюю границу интервала цены //Ниже, или выше, чем свинг, не нужно проверять if(ZZD.upward) //если восходящий { tr_bottom = MathMax(tr_bottom,ZZD.point_3); tr_roof = MathMin(tr_roof,ZZD.point_2); } else { tr_bottom = MathMax(tr_bottom,ZZD.point_2); tr_roof = MathMin(tr_roof,ZZD.point_3); } tr_bottom = tr_bottom/_Point; tr_roof = tr_roof/_Point; for(g=0; gLEVELS[g,1]-Step) wearein=true; } else { if(!wearein) { if(tr_bottom>LEVELS[g-1,1] && tr_bottom<=LEVELS[g,1]) //зацепили нижнюю часть интервала wearein = true; } else { if(LEVELS[g,0]>=TriggerLevel) //Есть касание сильного уровня { signal=true; break; } if(tr_roof>LEVELS[g-1,1] && tr_roof<=LEVELS[g,1]) //зацепили верхнюю часть интервала break; } } } return(signal); } //+------------------------------------------------------------------+ //| Мониторим прорыв фрактала для входа | //+------------------------------------------------------------------+ void CompareBOLev() { if(orderdir==0) { if(Bid>BOutlevel) { wait4BOut = false; Monitor4entry(true); //Пробили уровень - проверяем опять все условия для входа } } else { if(Bid SpreadMax) { Print("Неудовлетворительны спред = ", NormalizeDouble(spread,0), " пунктов. Жду восстановления."); Sleep(SleepSec*1000); return; } if(typeorder==0) { price=Ask; if(SLmode==0) SL = ZZD.point_1-Indent*_Point; else SL = ZZD.point_3-Indent*_Point; slvalue = Ask - SL; if(TPmode == multipliersl) TP = Ask + K_TP*slvalue; else { TP = FindSwingTP(0); if(!ProfitToLoss(slvalue,(TP - Ask))) { Print("Плохое соотношение риск/прибыль! Пропускаю сделку!"); memoryprice = ZZD.point_1; first_condition = false; return; } } col = clrBlue; } else { price = Bid; if(SLmode==0) SL = ZZD.point_1+Indent*_Point; else SL = ZZD.point_3+Indent*_Point; slvalue = SL - Bid; if(TPmode == multipliersl) TP = Bid - K_TP*slvalue; else { TP = FindSwingTP(1); if(!ProfitToLoss(slvalue,(Bid - TP))) { Print("Плохое соотношение риск/прибыль! Пропускаю сделку!"); memoryprice = ZZD.point_1; first_condition = false; return; } } col = clrRed; } if(slvalue/_Point0) { if(typeorder==0) { buyOD.ticket = Ticket; buyOD.alreadyBE = false; buyOD.SLvalue = slvalue; buyOD.BEprice = price + K_BE*slvalue; } if(typeorder==1) { sellOD.ticket = Ticket; sellOD.alreadyBE = false; sellOD.SLvalue = slvalue; sellOD.BEprice = price - K_BE*slvalue; } } } //+---------------------------------------------------------------------+ //| Находим тейк-профит в зависимости от размера основного свинга | //+---------------------------------------------------------------------+ double FindSwingTP(int ordtype) { double tpnew; if(ordtype==0) //если покупка tpnew = ZZD.point_1 + ZZD.mainsize; else //если продажа tpnew = ZZD.point_1 - ZZD.mainsize; tpnew = NormalizeDouble(tpnew,_Digits); return(tpnew); } //+---------------------------------------------------------------------+ //| Проверяем соотношение профит/убыток | //+---------------------------------------------------------------------+ bool ProfitToLoss(double SLvalue, double TPvalue) { if(TPvalue/SLvalue >= TakeStop) return(true); else return(false); } //+---------------------------------------------------------------------+ //| Функция вычисления объема сделки - здесь от еквити и проверяется шаг| //+---------------------------------------------------------------------+ double DealVolume(double riskcount,double sl) { double lot_min, lot_max, lot_step, lotcost; lot_min = MarketInfo(_Symbol, MODE_MINLOT); lot_max = MarketInfo(_Symbol, MODE_MAXLOT); lot_step = MarketInfo(_Symbol, MODE_LOTSTEP); lotcost = MarketInfo(_Symbol, MODE_TICKVALUE); double lot=0; double UsdPerPip=0; lot = MathMin(AccountBalance(), AccountEquity())*riskcount/100; UsdPerPip=lot/sl; lot=UsdPerPip/lotcost; lot = MathFloor(lot/lot_step)*lot_step; if(lotlot_max) lot = lot_max; return(lot); } //+------------------------------------------------------------------+ //| Находим открытые ордера советника и их число | //+------------------------------------------------------------------+ int CountOrders(int ord_type) { int i; int ordcount=0; for(i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { if(OrderSymbol()==_Symbol && OrderMagicNumber()==Magic) { if(OrderType()==ord_type) ordcount++; } } } return(ordcount); } //+------------------------------------------------------------------+ //| Проверяем наличие сигнала для старта мониторинга | //+------------------------------------------------------------------+ bool CheckSignal() { double correctionnow; if(ZZD.upward) //если свинг 3-2 направлен вверх { if(ZZD.point_1>ZZD.point_3) { correctionnow = ZZD.maincorrec/ZZD.mainsize; if(correctionnow >= Correctionmin/100 && correctionnow <= Correctionmax/100) //Основное условие - коррекция стала больше требуемой { first_condition = true; orderdir = 0; //будем искать точку для входа на покупки return(true); } } } else { if(ZZD.point_1= Correctionmin/100 && correctionnow <= Correctionmax/100) { first_condition = true; orderdir = 1; //ищем продажи return(true); } } } return(false); } //+------------------------------------------------------------------+ //| Заполняем последние данные по ZigZag | //+------------------------------------------------------------------+ void FillZigZagData() { int i, p_1=0, p_2=0, p_3=0; double ZZvalue; int step = 0; double minpips=0; for(i=1; i<=10000; i++) { ZZvalue = iCustom(_Symbol,0,"ZigZag",InpDepth,InpDeviation,InpBackstep,0,i); if(ZZvalue!=0) { if(step==4) { ZZD.point_5 = ZZvalue; break; } if(step==3) { ZZD.point_4 = ZZvalue; step = 4; } if(step==2) { ZZD.point_3 = ZZvalue; p_3 = i; step = 3; } if(step==1) { p_2 = i; if(ZZvalue!=ZZD.point_2) { ZZD.point_2 = ZZvalue; step=2; } else break; } if(step==0) { p_1 = i; if(ZZvalue!=ZZD.point_1) { ZZD.point_1 = ZZvalue; ZZD.time_1 = Time[i]; step=1; } else break; } } } if(ZZD.point_2>ZZD.point_3) { ZZD.upward=true; ZZD.mainsize = ZZD.point_2-ZZD.point_3; } else { ZZD.upward=false; ZZD.mainsize = ZZD.point_3-ZZD.point_2; } //Сразу проверим величину свинга на соответствие минимальному значению minpips = K_volat*Volatility(VolatDays,PERIOD_D1); if(Minswing>minpips/_Point) minpips = Minswing*_Point; if(ZZD.mainsize>=minpips) ZZD.swingOK = true; else ZZD.swingOK = false; ZZD.maincorrec = MathAbs(ZZD.point_2-ZZD.point_1); if(p_2!=0) ZZD.shift_12 = p_2 - p_1; if(p_3!=0) ZZD.shift_23 = p_3 - p_2; } //+--------------------------------------------------------------------------+ //| Функция расчета волатильности по заданному количеству дневных баров | //+--------------------------------------------------------------------------+ double Volatility(int period, int timeframe) { double Differ[]; ArrayResize(Differ,period+1,1); double diff1, diff=0; int i, count=0; for(i=1; i<=period; i++) //Заполнение массива { if(timeframe != _Period) Differ[i]=iHigh(_Symbol,timeframe,i)-iLow(_Symbol,timeframe,i); //Рассчитываем величину свечей на нужном таймфрейме else Differ[i]=High[i]-Low[i]; } for(i=1; i<=period; i++) { diff+=Differ[i]; count++; } diff1=diff/count; //Показатель волатильности без учета текущего бара return(diff1); } //+------------------------------------------------------------------+ //| Функция-обработчик ошибок при открытии ордеров | //+------------------------------------------------------------------+ int OrderSendx(string symbolx, int cmdx, double volumex, double pricex, int slippagex, double stoplossx, double takeprofitx, string commentx, int magicx, datetime expirationx, color arrow_colorx) { int err = 0; bool exit_loop = false; int ticketx = -1; int Retry = 10; int cnt = 0; while (!exit_loop) { ticketx = OrderSend(symbolx, cmdx, volumex, pricex, slippagex, stoplossx, takeprofitx, commentx, magicx, expirationx, arrow_colorx); err = GetLastError(); switch(err) { case ERR_NO_ERROR: exit_loop = true; return(ticketx); case ERR_SERVER_BUSY: case ERR_NO_CONNECTION: case ERR_INVALID_PRICE: case ERR_TRADE_TIMEOUT: case ERR_OFF_QUOTES: case ERR_BROKER_BUSY: case ERR_TRADE_CONTEXT_BUSY: cnt++; break; case ERR_PRICE_CHANGED: case ERR_REQUOTE: RefreshRates(); cnt++; continue; default: exit_loop = true; break; } if (cnt>Retry) { exit_loop = true; Print("Ошибка открытия ордера после ", cnt, " попыток"); } if (err != ERR_NO_ERROR) Print("Ошибка открытия ордера - ", ErrorDescription(err)); //Вместо err добавить функцию из включаемого файла ErrorDescription(err) if (!exit_loop) { Sleep(3000); RefreshRates(); if (cmdx==OP_SELL) pricex=Bid; if (cmdx==OP_BUY) pricex=Ask; } } return(ticketx); } //+------------------------------------------------------------------+ //| Описание ошибок на русском | //+------------------------------------------------------------------+ string ErrorDescription(int error) { string ErrorNumber; switch(error) { case 0: case 1: ErrorNumber = "Нет ошибки, но результат неизвестен"; break; case 2: ErrorNumber = "Общая ошибка"; break; case 3: ErrorNumber = "Неправильные параметры"; break; case 4: ErrorNumber = "Торговый сервер занят"; break; case 5: ErrorNumber = "Старая версия клиентского терминала"; break; case 6: ErrorNumber = "Нет связи с торговым сервером"; break; case 7: ErrorNumber = "Недостаточно прав"; break; case 8: ErrorNumber = "Слишком частые запросы"; break; case 9: ErrorNumber = "Недопустимая операция нарушающая функционирование сервера"; break; case 64: ErrorNumber = "Счет заблокирован"; break; case 65: ErrorNumber = "Неправильный номер счета"; break; case 128: ErrorNumber = "Истек срок ожидания совершения сделки"; break; case 129: ErrorNumber = "Неправильная цена"; break; case 130: ErrorNumber = "Неправильные стопы"; break; case 131: ErrorNumber = "Неправильный объем"; break; case 132: ErrorNumber = "Рынок закрыт"; break; case 133: ErrorNumber = "Торговля запрещена"; break; case 134: ErrorNumber = "Недостаточно денег для совершения операции"; break; case 135: ErrorNumber = "Цена изменилась"; break; case 136: ErrorNumber = "Нет цен"; break; case 137: ErrorNumber = "Брокер занят"; break; case 138: ErrorNumber = "Новые цены - Реквот"; break; case 139: ErrorNumber = "Ордер заблокирован и уже обрабатывается"; break; case 140: ErrorNumber = "Разрешена только покупка"; break; case 141: ErrorNumber = "Слишком много запросов"; break; case 145: ErrorNumber = "Модификация запрещена, так как ордер слишком близок к рынку";break; case 146: ErrorNumber = "Подсистема торговли занята"; break; case 147: ErrorNumber = "Использование даты истечения ордера запрещено брокером"; break; case 148: ErrorNumber = "Количество открытых и отложенных ордеров достигло предела "; break; case 149: ErrorNumber = "Запрещено хэджирование"; break; case 150: ErrorNumber = "Запрещено правилами FIFO"; break; case 4000: ErrorNumber = "Нет ошибки"; break; case 4001: ErrorNumber = "Неправильный указатель функции"; break; case 4002: ErrorNumber = "Индекс массива - вне диапазона"; break; case 4003: ErrorNumber = "Нет памяти для стека функций"; break; case 4004: ErrorNumber = "Переполнение стека после рекурсивного вызова"; break; case 4005: ErrorNumber = "На стеке нет памяти для передачи параметров"; break; case 4006: ErrorNumber = "Нет памяти для строкового параметра"; break; case 4007: ErrorNumber = "Нет памяти для временной строки"; break; case 4008: ErrorNumber = "Неинициализированная строка"; break; case 4009: ErrorNumber = "Неинициализированная строка в массиве"; break; case 4010: ErrorNumber = "Нет памяти для строкового массива"; break; case 4011: ErrorNumber = "Слишком длинная строка"; break; case 4012: ErrorNumber = "Остаток от деления на ноль"; break; case 4013: ErrorNumber = "Деление на ноль"; break; case 4014: ErrorNumber = "Неизвестная команда"; break; case 4015: ErrorNumber = "Неправильный переход"; break; case 4016: ErrorNumber = "Неинициализированный массив"; break; case 4017: ErrorNumber = "Вызовы DLL не разрешены"; break; case 4018: ErrorNumber = "Невозможно загрузить библиотеку"; break; case 4019: ErrorNumber = "Невозможно вызвать функцию"; break; case 4020: ErrorNumber = "Вызовы внешних библиотечных функций не разрешены"; break; case 4021: ErrorNumber = "Недостаточно памяти для строки, возвращаемой из функции"; break; case 4022: ErrorNumber = "Система занята"; break; case 4050: ErrorNumber = "Неправильное количество параметров функции"; break; case 4051: ErrorNumber = "Недопустимое значение параметра функции"; break; case 4052: ErrorNumber = "Внутренняя ошибка строковой функции"; break; case 4053: ErrorNumber = "Ошибка массива"; break; case 4054: ErrorNumber = "Неправильное использование массива-таймсерии"; break; case 4055: ErrorNumber = "Ошибка пользовательского индикатора"; break; case 4056: ErrorNumber = "Массивы несовместимы"; break; case 4057: ErrorNumber = "Ошибка обработки глобальныех переменных"; break; case 4058: ErrorNumber = "Глобальная переменная не обнаружена"; break; case 4059: ErrorNumber = "Функция не разрешена в тестовом режиме"; break; case 4060: ErrorNumber = "Функция не подтверждена"; break; case 4061: ErrorNumber = "Ошибка отправки почты"; break; case 4062: ErrorNumber = "Ожидается параметр типа string"; break; case 4063: ErrorNumber = "Ожидается параметр типа integer"; break; case 4064: ErrorNumber = "Ожидается параметр типа double"; break; case 4065: ErrorNumber = "В качестве параметра ожидается массив"; break; case 4066: ErrorNumber = "Запрошенные исторические данные в состоянии обновления"; break; case 4067: ErrorNumber = "Ошибка при выполнении торговой операции"; break; case 4099: ErrorNumber = "Конец файла"; break; case 4100: ErrorNumber = "Ошибка при работе с файлом"; break; case 4101: ErrorNumber = "Неправильное имя файла"; break; case 4102: ErrorNumber = "Слишком много открытых файлов"; break; case 4103: ErrorNumber = "Невозможно открыть файл"; break; case 4104: ErrorNumber = "Несовместимый режим доступа к файлу"; break; case 4105: ErrorNumber = "Ни один ордер не выбран"; break; case 4106: ErrorNumber = "Неизвестный символ"; break; case 4107: ErrorNumber = "Неправильный параметр цены для торговой функции"; break; case 4108: ErrorNumber = "Неверный номер тикета"; break; case 4109: ErrorNumber = "Торговля не разрешена"; break; case 4110: ErrorNumber = "Длинные позиции не разрешены"; break; case 4111: ErrorNumber = "Короткие позиции не разрешены"; break; case 4200: ErrorNumber = "Объект уже существует"; break; case 4201: ErrorNumber = "Запрошено неизвестное свойство объекта"; break; case 4202: ErrorNumber = "Объект не существует"; break; case 4203: ErrorNumber = "Неизвестный тип объекта"; break; case 4204: ErrorNumber = "Нет имени объекта"; break; case 4205: ErrorNumber = "Ошибка координат объекта"; break; case 4206: ErrorNumber = "Не найдено указанное подокно"; break; case 4207: ErrorNumber = "Ошибка при работе с объектом"; break; case 4210: ErrorNumber = "Неверные свойства графика"; break; case 4211: ErrorNumber = "График не найдено"; break; case 4212: ErrorNumber = "Подокно не найдено"; break; case 4213: ErrorNumber = "Индикатор на графике не найден"; break; case 4220: ErrorNumber = "Ошибка выбора валютной пары"; break; case 4250: ErrorNumber = "Ошибка отправки Push-уведомления"; break; case 4251: ErrorNumber = "Ошибка параметров Push-уведомления"; break; case 4252: ErrorNumber = "Push-уведомления отключены"; break; case 4253: ErrorNumber = "Слишком частые отправки Push-уведомлений"; break; case 4260: ErrorNumber = "ftp-сервер неверный"; break; case 4261: ErrorNumber = "ftp-логин нуверный"; break; case 4262: ErrorNumber = "ftp соединение не удалось"; break; case 4263: ErrorNumber = "ftp соединение закрыто"; break; case 4264: ErrorNumber = "Ошибка смены ftp-пути"; break; case 4265: ErrorNumber = "Ошибка ftp-файла"; break; case 4266: ErrorNumber = "Общая ошибка ftp"; break; case 5001: ErrorNumber = "Слишком много открытых файлов"; break; case 5002: ErrorNumber = "Неверное имя файла"; break; case 5003: ErrorNumber = "Слишком длинное имя файла"; break; case 5004: ErrorNumber = "Невозможно открыть файл"; break; case 5005: ErrorNumber = "Ошибка распределения текста в буфере файла"; break; case 5006: ErrorNumber = "Невозможно удалить файл"; break; case 5007: ErrorNumber = "Неверный индекс файла (закрыт или не был открыт)"; break; case 5008: ErrorNumber = "Неверный индекс файла (индекс вне списка системы)"; break; case 5009: ErrorNumber = "Файл должен быть открыт с флагом FILE_WRITE"; break; case 5010: ErrorNumber = "Файл должен быть открыт с флагом FILE_READ"; break; case 5011: ErrorNumber = "Файл должен быть открыт с флагом FILE_BIN"; break; case 5012: ErrorNumber = "Файл должен быть открыт с флагом FILE_TXT"; break; case 5013: ErrorNumber = "Файл должен быть открыт с флагом FILE_TXT или FILE_CSV"; break; case 5014: ErrorNumber = "Файл должен быть открыт с флагом FILE_CSV"; break; case 5015: ErrorNumber = "Ошибка чтения файла"; break; case 5016: ErrorNumber = "Ошибка записи файла"; break; case 5017: ErrorNumber = "Размер строки должен быть адаптирован для бинарных файлов"; break; case 5018: ErrorNumber = "Несовместимый файл (для строковых мас-TXT, для других-BIN)"; break; case 5019: ErrorNumber = "Файл является каталогом, а не файлом"; break; case 5020: ErrorNumber = "Файл не существует"; break; case 5021: ErrorNumber = "Файл не может быть перезаписан"; break; case 5022: ErrorNumber = "Неверное имя каталога"; break; case 5023: ErrorNumber = "Каталог не существует"; break; case 5024: ErrorNumber = "Определенный файл не каталог"; break; case 5025: ErrorNumber = "Невозможно удалить каталог"; break; case 5026: ErrorNumber = "Невозможно очистить каталог"; break; case 5027: ErrorNumber = "Ошибка изменения размера массива"; break; case 5028: ErrorNumber = "Ошибка изменения размера строки"; break; case 5029: ErrorNumber = "Структура содержит строки или динамические массивы"; break; default: ErrorNumber = "Неизвестная ошибка"; } return (ErrorNumber); } //+------------------------------------------------------------------+ //| Функция-обработчик ошибок при модификации ордеров | //+------------------------------------------------------------------+ bool OrderModifyx(int ticketx, double pricex, double stoplossx, double takeprofitx, datetime expirationx, color arrow_colorx) { int err = 0; bool exit_loop = false; bool answer = false; int Retry = 10; int cnt = 0; while (!exit_loop) { answer = OrderModify(ticketx, pricex, stoplossx, takeprofitx, expirationx, arrow_colorx); err = GetLastError(); switch(err) { case ERR_NO_ERROR: exit_loop = true; return(answer); case ERR_SERVER_BUSY: case ERR_NO_CONNECTION: case ERR_INVALID_PRICE: case ERR_TRADE_TIMEOUT: case ERR_OFF_QUOTES: case ERR_BROKER_BUSY: case ERR_TRADE_CONTEXT_BUSY: cnt++; break; default: exit_loop = true; break; } if (cnt>Retry) { exit_loop = true; Print("Ошибка модификации ордера после ", cnt, " попыток"); } if (err != ERR_NO_ERROR) Print("Ошибка модификации ордера - ", err); //Вместо err добавить функцию из включаемого файла ErrorDescription(err) if (!exit_loop) { Sleep(5000); RefreshRates(); } } return(answer); } //+------------------------------------------------------------------+