Новый клиентский терминал MetaTrader 4 build 199 - страница 11

 

Теперь я понял в чем проблема. Если это можно исправить на текущем этапе - думаю, исправят. Нужно узнать есть ли возможность получения точных пиксельных координат середины отрезка 2-3 с последующим нахождением правильной точкой привязки.
Rosh, спасибо.

Надеюсь на дальнейшее плодотворное сотрудничество.

Возможность расчета точной координаты в метатрейдере есть. Это не сложно.

Теперь придется в индикаторе корректировать код. Он у меня сейчас сделан с учетом этой ошибки. Если ошибка будет исправлена, также придется исправлять некоторые линии из "полного комплекта" вил Эндрюса.

Если ошибка будет исправлена, возможно, подкину еще... что хотелось бы исправить. Например, каналы Фибоначчи в некоторых случаях нельзя построить правильно. Это, правда, пограничные случаи.

С уважением, Евгений.
 
Проверьте пока этот алгоритм. В нем не реализована полная "защита от дурака", но идея та, что требовалась.



//+------------------------------------------------------------------+
//|                                             AndrewsPitchfork.mq4 |
//|                                                             Rosh |
//|                    http://www.alpari-idc.ru/ru/experts/articles/ |
//+------------------------------------------------------------------+
#property copyright "Rosh"
#property link      "http://www.alpari-idc.ru/ru/experts/articles/"


extern color mainLineColor=Blue;
extern color bandsLineColor=Blue;

int range=20;// initial index bar of first reper;
// coordinates of repers
double price1,price2,price3;
datetime time1,time2,time3;
double A; // coeff for Y=A*X+B
string medianLine="mainAP";
string upLine="upAP";
string downLine="downAP";
double PriceMediana;
datetime TimeMediana; 
double t2,t3,bar1,bar2,bar3;
int intBar1,intBar2,intBar3,barMediana;
//+------------------------------------------------------------------+
//| checking shift of  Number reper                                  |
//+------------------------------------------------------------------+
int Delta(int Number)
  {
//----
   int res=0; 
   if (Number<0||Number>3) return(0);
   switch (Number)
      {
      case 1:if (MathAbs(price1-ReperPrice(1))>Point || MathAbs(time1-ReperTime(1))>0)
         {
         res=1;
         break;
         }
      case 2:if (MathAbs(price2-ReperPrice(2))>Point || MathAbs(time2-ReperTime(2))>0)
         {
         res=2;
         break;
         }
      case 3:if (MathAbs(price3-ReperPrice(3))>Point || MathAbs(time3-ReperTime(3))>0)
         {
         res=3;
         break;
         }
      default: res=0;break;
      }
   return(res);
  }

//+------------------------------------------------------------------+
//| checking repers                                                  |
//+------------------------------------------------------------------+
bool isChanged()
  {
//----
   bool res=false; 
   if (Delta(1)!=0) return(true);   
   if (Delta(2)!=0) return(true);   
   if (Delta(3)!=0) return(true);   
   return(res);
  }

//+------------------------------------------------------------------+
//| redraw pitchforks                                                |
//+------------------------------------------------------------------+
void Redraw()
  {
//----
   if (ObjectFind(medianLine)==-1) ObjectCreate(medianLine,OBJ_TREND,0,time1,price1,TimeMediana,PriceMediana);
   else 
      {
      ObjectSet(medianLine,OBJPROP_PRICE1,price1);
      ObjectSet(medianLine,OBJPROP_PRICE2,PriceMediana);
      ObjectSet(medianLine,OBJPROP_TIME1,time1);
      ObjectSet(medianLine,OBJPROP_TIME2,TimeMediana);
      }
   ObjectSet(medianLine,OBJPROP_COLOR,mainLineColor);

   if (ObjectFind(upLine)==-1) ObjectCreate(upLine,OBJ_TREND,0,time2,price2,Time[0],price2+A*iBarShift(Symbol(),0,time2));
   else 
      {
      ObjectSet(upLine,OBJPROP_PRICE1,price2);
      ObjectSet(upLine,OBJPROP_PRICE2,price2+A*iBarShift(Symbol(),0,time2));
      ObjectSet(upLine,OBJPROP_TIME1,time2);
      ObjectSet(upLine,OBJPROP_TIME2,Time[0]);
      }
   ObjectSet(upLine,OBJPROP_COLOR,bandsLineColor);

   if (ObjectFind(downLine)==-1) ObjectCreate(downLine,OBJ_TREND,0,time3,price3,Time[0],price3+A*iBarShift(Symbol(),0,time3));
   else 
      {
      ObjectSet(downLine,OBJPROP_PRICE1,price3);
      ObjectSet(downLine,OBJPROP_PRICE2,price3+A*iBarShift(Symbol(),0,time3));
      ObjectSet(downLine,OBJPROP_TIME1,time3);
      ObjectSet(downLine,OBJPROP_TIME2,Time[0]);
      }
   ObjectSet(downLine,OBJPROP_COLOR,bandsLineColor);

   //Print("Перерисовываем");
   WindowRedraw();
   return;
  }

//+------------------------------------------------------------------+
//| return time of reper                                             |
//+------------------------------------------------------------------+
datetime ReperTime(int Number)
  {
//----
   datetime res=0;
   //Print("Возвращаем время репера №",Number);
   if (Number==1)
      {
      if (ObjectFind(medianLine)==-1) return(res);
      else res=ObjectGet(medianLine,OBJPROP_TIME1); 
      }
   if (Number==2)
      {
      if (ObjectFind(upLine)==-1) return(res);
      else res=ObjectGet(upLine,OBJPROP_TIME1); 
      }
   if (Number==3)
      {
      if (ObjectFind(downLine)==-1) return(res);
      else res=ObjectGet(downLine,OBJPROP_TIME1); 
      }

   return(res);
  }

//+------------------------------------------------------------------+
//| return price of reper                                            |
//+------------------------------------------------------------------+
double ReperPrice(int Number)
  {
//----
   double res=0;
   //Print("Возвращаем цену репера #",Number);
   if (Number==1)
      {
      if (ObjectFind(medianLine)==-1) return(res);
      else res=ObjectGet(medianLine,OBJPROP_PRICE1); 
      }
   if (Number==2)
      {
      if (ObjectFind(upLine)==-1) return(res);
      else res=ObjectGet(upLine,OBJPROP_PRICE1); 
      }
   if (Number==3)
      {
      if (ObjectFind(downLine)==-1) return(res);
      else res=ObjectGet(downLine,OBJPROP_PRICE1); 
      }

   return(res);
  }


//+------------------------------------------------------------------+
//| scrypt initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   double drop_price=WindowPriceOnDropped();
   datetime drop_time=WindowTimeOnDropped();
   if (drop_time>0)
      {
      price1=drop_price;
      time1=drop_time;
      Redraw();
      }
   else 
      {
      time1=ReperTime(1);
      //Print("Время первого репера ",TimeToStr(time1));
      if (time1==0) 
         {
         time1=Time[range];
         price1=(High[iHighest(Symbol(),0,MODE_HIGH,range,0)]+Low[iLowest(Symbol(),0,MODE_LOW,range,0)])/2;
         bar1=range;
         }
      else 
         {
         price1=ReperPrice(1);
         bar1=iBarShift(Symbol(),0,time1);
         }
      //Print("Выполняем блок без броска скрипта");
      
      time2=ReperTime(2);
      if (time2==0)
         {         
         intBar2=iHighest(Symbol(),0,MODE_HIGH,range/2.0,0);
         bar2=intBar2;
         time2=Time[intBar2];
         price2=High[intBar2];
         }
      else price2=ReperPrice(2);   
      
      time3=ReperTime(3);
      if (time3==0)
         {
         intBar3=iLowest(Symbol(),0,MODE_LOW,range/2.0,0);
         bar3=intBar3;
         time3=Time[intBar3];
         price3=Low[intBar3];
         }
      else price3=ReperPrice(3);   

      bar2=iBarShift(Symbol(),0,time2);
      bar3=iBarShift(Symbol(),0,time3);
      if (MathMod(MathAbs(bar3-bar2),2)==0) // четное число промежутков между барами
         {
         PriceMediana=(price2+price3)/2.0;
         t2=time2;
         t3=time3;
         TimeMediana=(t2+t3)/2.0;
         A=(PriceMediana-price1)/(bar1-(bar3+bar2)/2.0);
         //Print("Первый вариант, barMediana=",(bar3+bar2)/2,"  bar2=",bar2,"   bar3=",bar3,"   bar1=",bar1);
         }
      else  // нечетное число промежутков между барами
         {
         barMediana=(bar3+bar2+1.0)/2.0;
         TimeMediana=Time[barMediana];
         PriceMediana=(price2+price3)/2.0;
         A=(PriceMediana-price1)/(bar1-(bar3+bar2)/2.0);
         PriceMediana=price1+A*(bar1-barMediana);
         //Print("Второй вариант, barMediana=",barMediana,"  bar2=",bar2,"   bar3=",bar3,"   bar1=",bar1);
         }            
      Redraw();   
      }   
   return(0);
  }

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   while (!IsStopped())
      {
      if (isChanged())
         {
         time1=ReperTime(1);
         time2=ReperTime(2);
         time3=ReperTime(3);
         price1=ReperPrice(1);
         price2=ReperPrice(2);
         price3=ReperPrice(3);
         bar1=iBarShift(Symbol(),0,time1);
         bar2=iBarShift(Symbol(),0,time2);
         bar3=iBarShift(Symbol(),0,time3);
         if (MathMod(MathAbs(bar3-bar2),2)==0) // четное число промежутков между барами
            {
            PriceMediana=(price2+price3)/2.0;
            t2=time2;
            t3=time3;
            TimeMediana=(t2+t3)/2.0;
            A=(PriceMediana-price1)/(bar1-(bar3+bar2)/2.0);
            //Print("Первый вариант, barMediana=",(bar3+bar2)/2,"  bar2=",bar2,"   bar3=",bar3,"   bar1=",bar1);
            }
         else  // нечетное число промежутков между барами
            {
            barMediana=(bar3+bar2+1.0)/2.0;
            TimeMediana=Time[barMediana];
            PriceMediana=(price2+price3)/2.0;
            A=(PriceMediana-price1)/(bar1-(bar3+bar2)/2.0);
            PriceMediana=price1+A*(bar1-barMediana);
            //Print("Второй вариант, barMediana=",barMediana,"  bar2=",bar2,"   bar3=",bar3,"   bar1=",bar1);
            }            

         Redraw();
         }
      Sleep(100);
      }
//----
   return(0);
  }
//+------------------------------------------------------------------+


 
Rosh, спасибо.
У меня проще. Хотелось бы, чтобы в Метатрейдере встроенные вилы работали корректно.
Многие используют встроенные вилы. Без программирования.

Наиболее оптимально будет, если будем совместными усилиями устранять ошибки метатрейдера.

Точнее, не проще, а по другому.

Если точка 3 находится на нулевом баре, то трендовую от нее программно не построишь. Поэтому линию, проходящую от точки 3, строю от точки 2. Берется время точки 2. Этот момент исключает правильное построение вил Эндрюса с помощью трендовых линий. И поэтому было бы правильнее исправить вывод линий Эндрюса в Метатрейдере.

extern color mainLineColor=Blue;
double price1,price2,price3;
datetime time1,time2,time3;
string medianLine="mainAP";
string upLine="upAP";
string downLine="downAP";
double PriceMediana;

double Level_05=0.5;
int c_bar1, c_bar2;
double mediana, tangens, delta;

c_bar1=iBarShift(Symbol(),Period(),time1)-iBarShift(Symbol(),Period(),time2); // количество бар в отрезке 1-2
c_bar2=iBarShift(Symbol(),Period(),time2)-iBarShift(Symbol(),Period(),time3); // количество бар в отрезке 2-3
mediana=Level_05*(price2+price3);

ObjectDelete(medianLine);
ObjectDelete(upLine);
ObjectDelete(downLine);
if (price2>price1)
  {
   tangens=(mediana-price1)/(c_bar1+Level_05*c_bar2);
   PriceMediana=mediana+c_bar2*Level_05*tangens;
   delta=Level_05*(price2-price3);

   ObjectCreate(upLine,OBJ_TREND,0,time2,price2,time3,PriceMediana+delta);
   ObjectSet(upLine,OBJPROP_COLOR,mainLineColor);

   ObjectCreate(downLine,OBJ_TREND,0,time2,price2-2*delta,time3,price3);
   ObjectSet(downLine,OBJPROP_COLOR,mainLineColor);
  }
else
  {
   tangens=(price1-mediana)/(c_bar1+Level_05*c_bar2);
   PriceMediana=mediana-c_bar2*Level_05*tangens;
   delta=Level_05*(price3-price2);

   ObjectCreate(upLine,OBJ_TREND,0,time2,price2+2*delta,time3,PriceMediana+delta);
   ObjectSet(upLine,OBJPROP_COLOR,mainLineColor);

   ObjectCreate(downLine,OBJ_TREND,0,time2,price2,time3,price3-2*delta);
   ObjectSet(downLine,OBJPROP_COLOR,mainLineColor);
  }

ObjectCreate(medianLine,OBJ_TREND,0,time1,price1,time3,PriceMediana);
ObjectSet(medianLine,OBJPROP_COLOR,mainLineColor);



Подредактировал применительно к Вашему коду.
Это только кусочек кода - вывод вил на график. Здесь используются значения для точек 1-2-3 полученные от скрипта или еще каким-то способом.






 
Rosh, спасибо.
У меня проще. Хотелось бы, чтобы в Метатрейдере встроенные вилы работали корректно.
Многие используют встроенные вилы. Без программирования.

Наиболее оптимально будет, если будем совместными усилиями устранять ошибки метатрейдера.

Точнее, не проще, а по другому.

Если точка 3 находится на нулевом баре, то трендовую от нее программно не построишь. Поэтому линию, проходящую от точки 3, строю от точки 2. Берется время точки 2. Этот момент исключает правильное построение вил Эндрюса с помощью трендовых линий. И поэтому было бы правильнее исправить вывод линий Эндрюса в Метатрейдере.




Вот это я и имел ввиду про "защиту от дурака". Но на самом деле это 1) не имеет значения 2) имеет решение на программном уровне. Трендовыми линиями это тоже решается, просто точка 2 или 3, находящяяся на нулевом баре автоматом съезжает с нужными поправками на первый бар (решение на уровне скрипта). Решение на уровне встроенного элемента вообще не затронет реперные точки (смещение не потребуется).
Просто я показал пример скрипта, который реализует аналог встроенного инструмента Andrews Pitchfork. Он также будет перерисовываться при изменении положений реперов (точки 1-2-3).

 
В принципе, программно можно все решить.
Но тут получаются два пути:
1) делаем свою разработку и прощаемся с метатрейдером
2) все-таки устраняем ошибки в метатрейдере.
 
Евгений, скоро будет новый билд с исправленным построением вил Эндрюса.
 
Евгений, скоро будет новый билд с исправленным построением вил Эндрюса.


Ex, kto-bi ese ZigZag vstroenniy popravil, kotoriy to rabotaet, to net..;/
 
Zigzag budet zavtra.
 
Евгений, скоро будет новый билд с исправленным построением вил Эндрюса.
Отлично!!!!!
 
Zigzag budet zavtra.
Неплохой ZigZag сделал Николай Косицын. Его ZigZag впролне можено использовать в работе.
Причина обращения: