Скачать MetaTrader 5
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Узнай, как растет твой рейтинг
Forex Trader
114255
Forex Trader 2008.02.27 12:59 
Индикатор не рисуется, хотя, наверное, должен. Может, кто подскажет почему и как исправить? Голову сломал уже. Зигзаг можно любой вставить. Спасибо!

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red


//---- input parameters

//---- buffers
double Buffer1[];

//----
//+------------------------------------------------------------------+
//| Init                                                             |
//+------------------------------------------------------------------+
int init()
{
   IndicatorBuffers(1);

//---- indicators
    string short_name;
    IndicatorShortName(short_name);
    SetIndexStyle(0,DRAW_LINE,EMPTY,2);
    SetIndexBuffer(0,Buffer1);

//----
    return(0);
}

//+------------------------------------------------------------------+
//| Start Function                                                   |
//+------------------------------------------------------------------+
int start()
   {
   int counted_bars=IndicatorCounted();

//---- check for possible errors
   if(counted_bars<0) 
   {
      return(-1);
   }
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
//---- do it

   for (int j=0;j>=5000;j++){
       
        int Bar1=ZZBar("",0,j+1,3000,12);
        int Bar2=ZZBar("",0,j+2,3000,12);
           
        Buffer1[j]=Close[Bar2]-Close[Bar1];
       }
//----
   return(0);
  }

//+----------------------------------------------------------------------------+
//|  Возвращает номер бара экстремума ЗигЗага по его номеру.                   |
//|  Параметры:                                                                |
//|    sym - наименование инструмента  ("" - текущий символ)                   |
//|    tf  - таймфрейм                 ( 0 - текущий ТФ)                       |
//|    ne  - номер экстремума          ( 0 - текущий)                          |
//|    dp  - ExtDepth                                                          |
//|    dv  - ExtDeviation                                                      |
//|    bc  - ExtBackstep                                                       |
//+----------------------------------------------------------------------------+
int ZZBar(string sym="", int tf=0, int ne=1, int dp=600, int dv=12) {
  if (sym=="") sym=Symbol();
  double zz;
  int    i, k=iBars(NULL, 0), ke=0;
 
  for (i=1; i<k; i++) {
    zz=iCustom(sym, tf, "ZigZag_new_1", dp, dv, 0, i);
    if (zz!=0) {
      ke++;
      if (ke>ne) 
      return(i);
    }
    }
return(0);
}


Forex Trader
114255
Forex Trader 2008.02.27 18:58  
в таких случаях требуется
1. изложить требуюмую логику индикатора
2. приложить используемый сабиндикатор
3. желательно при обучении комментировать свой код
посмотрел твой код, внутри комментарии
//+------------------------------------------------------------------+
//|                                                       Idalgo.mq4 |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red

//---- input parameters
//---- buffers
double Buffer1[];          //при написании кода нужно стараться давать имена которые будут тебе говорить о функциональной нагрузке

//----
//+------------------------------------------------------------------+
//| Init                                                             |
//+------------------------------------------------------------------+
int init()
{
   IndicatorBuffers(1);

//---- indicators
    string short_name;
    IndicatorShortName(short_name);
    SetIndexStyle(0,DRAW_LINE,EMPTY,2);
    SetIndexBuffer(0,Buffer1);

//----
    return(0);
}

//+------------------------------------------------------------------+
//| Start Function                                                   |
//+------------------------------------------------------------------+
int start()
{
   int counted_bars=IndicatorCounted();

//---- check for possible errors
   if(counted_bars<0) 
   {
      return(-1);
   }
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
//---- do it

   for (int j=0;j>=5000;j++)
   {
      //int Bar1=ZZBar("",0,j+1,3000,12);
      //int Bar2=ZZBar("",0,j+2,3000,12);
      //изменились входные параметры функции, меняем код
      int Bar1=ZZBar(j+1,3000,12);
      int Bar2=ZZBar(j+2,3000,12);
      Buffer1[j]=Close[Bar2]-Close[Bar1];
   }
//----
   return(0);
}

//+----------------------------------------------------------------------------+
//|  Возвращает номер бара экстремума ЗигЗага по его номеру.                   |
//|  Параметры:                                                                |
//|    sym - наименование инструмента  ("" - текущий символ)                   |
//|    tf  - таймфрейм                 ( 0 - текущий ТФ)                       |
//|    ne  - номер экстремума          ( 0 - текущий)                          |
//|    dp  - ExtDepth                                                          |
//|    dv  - ExtDeviation                                                      |
//|    bc  - ExtBackstep                                                       |
//+----------------------------------------------------------------------------+
//при написании собственных функций в объявлении лучше просто перечислить 
//входные переменные и их типы, а присвоение делать уже внутри функции
//потому заменил твою строчку
//int ZZBar(string sym="", int tf=0, int ne=1, int dp=600, int dv=12)
//для чего объявлять входную переменную sym, если она никак и нигде не меняется?
//то же самое по т.ф.
int ZZBar(int ne, int dp, int dv)
{
  //if (sym=="") sym=Symbol();
  double zz;
  //зачем грузить код лишними вызовами "тяжелых" функций? k нигде не меняется,
  //поэтому заменил твой код
  //int    i, k=iBars(NULL, 0), ke=0;
  int    i,ke=0;
  //здесь присваиваю значения переменным (хотя они у тебя статичные, и можно было указать 
  //их значение непосредственно при вызове iCustom
  dp=600;
  dv=12;
  ne=1;
 
  //обязательно комментируй свой код, потому что
  //1. будешь видеть четкий пошаговый алгоритм кода
  //2. легко даже по прошествии времени сможешь разобраться, чего же делает твой код
  //3. это признак профессионального подхода, т.к. и другим людям позволит понять логику твоего кода
  //в цикле ты задаешь начало просчета с бара с индексом 1, т.е. на каком бы участке ты бы не хотел
  //посчитать какие-либо данные всегда будешь просчитывать с бара имеющего индекс 1 (из всего множества 
  //что есть на графике, т.е. непонятно зачем тебе нужно пробегать в функции старт по всем 5000 барам
  //если тебя интересуют только крайне правые две вершины от индекса 1 до индекса Bars-1
  for (i=1; i<Bars; i++)
  {
      //будем надеяться что твой ZigZag_new_1, это аналог стандартного и использует именно 0 буфер, 
      //и количество входных данных (внешних) у него равно 2, и заданы они корректно
      zz=iCustom(NULL,0,"ZigZag_new_1",dp,dv,0,i);
      //т.к. в буферах содержится информация типа double, то твое сравнение некорректно
      //на форуме это обсуждалось мягко говоря "туева хуча" раз, я вписал свою функцию, которую пользую, 
      //с точностью до Digits знаков, видимо твой зигзаг может иметь значение и меньше нуля
      //а сравнение только на неравенство, но можно посмотреть и стандартную библиотеку там тоже есть 
      //функция на равенство вещественных чисел
      //if (zz!=0 )
      if( !CompareDoubles_m(zz,0,Digits) )
      {
         //если есть отрисовка ЗЗ на графике ты увеличиваешь счетчик
         ke++;
         //когда счетчик больше 1, т.е. 2 отрисовки происходит выход из цикла
         if (ke>ne)
         //здесь ты просто фиксируешь и возвращаешь индекс бара от 1 до того места где у тебя обнаружена второй
         //экстримум на зигзаге, как я уже и говорил это будет всегда одна и та же точка
         return(i);
      }
  }
  //видимо ты хотел чтобы ne у тебя была переменной?, тогда не нужно присваивать значение 1
  //и тогда не понятно какая логика в увязке количества баров и количества вершин
  //хотя вроде ты хотел вычислить разницу в ценах закрытия на двух последних вершинах? или я ошибаюсь?
return(0);
}

//+--------------------------------------------------------------------------------------------------------------------------------------------------+
//| right comparison of 2 doubles                                                                                                                    |
//+--------------------------------------------------------------------------------------------------------------------------------------------------+
bool CompareDoubles_m(double number1,double number2,int dig)
{
   if(NormalizeDouble(number1-number2,dig)==0) return(true);
   else return(false);
}
Forex Trader
114255
Forex Trader 2008.02.27 21:03  
Уважаемый Profi_R! Огромное спасибо за столь подробный разбор моего кода и ценные советы, которые я обязательно приму к сведению.

Вообще, я хотел создать индикатор, который позволял бы сравнивать определенный набор вершин зигзага, причем не просто несколько последних вершин, а позволял бы выявлять определенные паттерны (в рамках волнового анализа, к примеру) на истории. Например, если принять за экстремум зигзага Ext[n], где n - номер экстремума, то пятиволновая модель у нас будет (образно) выглядеть как Ext[5]<Ext[4] && Ext[5]<Ext[3]<Ext[4] && Ext[2]>Ext[3] и т.д. до нулевого или первого экстремума. При наличии такой конфигурации можно говорить о том, что мы находимся, к примеру, на вершине пятиволновой модели и ожидаем коррекцию (и, скажем, ставим соответствующую стрелку вниз).

С помощью функции ZZBar, которую, не стану скрывать, написал не я, можно сравнивать экстремумы зигзага, но это работает "только вперед", при прогонке индикатора на тестере. А хотелось бы, чтобы все эти конфигурации считались назад, на истории, и все было видно сразу.

Соответственно, если рассматривать предложенный мной вначале (неработающий) код, я хотел в функции Start спроецировать расчитанные экстремумы ZZBar на историю - в шаблонном, разумеется варианте и там должно быть не

Close[Bar2]-Close[Bar1], а, скажем,

if (Close[Bar2]-Close[Bar1]) {рисуем стрелку вверх или вниз} - это уже просто.

Если осуществление этой затеи не является чем-то очень сложным, буду признателен за содействие - наверное, это многим было бы интересно!

Ниже код зигзага, который я использовал, его единственное достоинство - он не перерисовывает лучи:

 //+------------------------------------------------------------------+
//|                                         High_Low v2 (ZigZag).mq4 |
//|                                          rewritten by CrazyChart |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "rewritten by CrazyChart"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Blue
//---- input parameters
extern int       barn=300;
extern int       Length=6;
//---- buffers
double ExtMapBuffer1[];
//double ExtMapBuffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexEmptyValue(0,0.0);
  //SetIndexDrawBegin(0, barn);
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexBuffer(0,ExtMapBuffer1);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
   int shift,Swing,Swing_n,uzl,i,zu,zd,mv;
   double LL,HH,BH,BL,NH,NL; 
   double Uzel[10000][3]; 
   string text;
// loop from first bar to current bar (with shift=0) 
      Swing_n=0;Swing=0;uzl=0; 
      BH =High[barn];BL=Low[barn];zu=barn;zd=barn; 

for (shift=barn;shift>=0;shift--) { 
      LL=10000000;HH=-100000000; 
   for (i=shift+Length;i>=shift+1;i--) { 
         if (Low[i]< LL) {LL=Low[i];} 
         if (High[i]>HH) {HH=High[i];} 
   } 


   if (Low[shift]<LL && High[shift]>HH){ 
      Swing=2; 
      if (Swing_n==1) {zu=shift+1;} 
      if (Swing_n==-1) {zd=shift+1;} 
   } else { 
      if (Low[shift]<LL) {Swing=-1;} 
      if (High[shift]>HH) {Swing=1;} 
   } 

   if (Swing!=Swing_n && Swing_n!=0) { 
   if (Swing==2) {
      Swing=-Swing_n;BH = High[shift];BL = Low[shift]; 
   } 
      uzl=uzl+1; 
   if (Swing==1) {
      Uzel[uzl][1]=zd;
      Uzel[uzl][2]=BL;
   } 
   if (Swing==-1) {
      Uzel[uzl][1]=zu;
      Uzel[uzl][2]=BH; 
   } 
      BH = High[shift];
      BL = Low[shift]; 
   } 

   if (Swing==1) { 
      if (High[shift]>=BH) {BH=High[shift];zu=shift;}}
      if (Swing==-1) {
          if (Low[shift]<=BL) {BL=Low[shift]; zd=shift;}} 
      Swing_n=Swing; 
   } 
   for (i=1;i<=uzl;i++) { 
      //text=DoubleToStr(Uzel[i][1],0);
      //text=;
         mv=StrToInteger(DoubleToStr(Uzel[i][1],0));
      ExtMapBuffer1[mv]=Uzel[i][2];
   } 





   return(0);
  }
//+------------------------------------------------------------------+
Forex Trader
114255
Forex Trader 2008.02.28 00:27  
вот посмотри, я не понял твоего задания, но и тебе лучше начинать с простого
//+------------------------------------------------------------------+
//|                                             Education_Idalgo.mq4 |
//|                                      rvm_fam  @  fromru  .  com |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property link      "http://www.metaquotes.net"

//индикатор будем отрисовывать в основном окне
#property indicator_chart_window

/*
Не пытайся сразу объять не объятное, пользуйся уже проверенными народными мудростями
и ранее полученным опытом, а именно, начни с простого, поняв механизмы ты затем сможешь
реализовывать более сложные задачи. Этот подход можно реализовать не только упрощением задачи,
но и путем разбития задачи на подзадачи. 
Давай реализуем более простую задачу, т.к. из того что ты изложил я мало что понял, а
дальше я думаю ты сам сможешь воплотить то, что ты хотел.
итак на входе имее индикатор High_Low v2 с двумя внешними переменными - типа целочисленные,
кроме того известно входной индикатор пишет все свои значения в один буфер с индексом - 0 и
еще что он имеет тип отрисовки - зигзаг, т.е. вершины в нем чередуются с впадинами.
Задача - найти на графике все наборы из двух последовательных а) повышающихся вершин
б) понижающихся впадит, и отметить их соответствующими значками
*/

//потребуется два буфера для отрисовки, в одном будем ставить значки означающие повышение вершин,
//в другом - понижающиеся впадины
#property indicator_buffers 2

//назначим цвета для наших значков
#property indicator_color1 Black
#property indicator_color2 Yellow

//---- input parameters

//т.к. мы будем экспеременитровать с входящими значениями исходного индикатора, то
//вынесем его внешние переменные на вход нашего индикатора, при этом желательно чтобы имена
//совпадали, это даст лего понять в любом месте кода что за переменные мы используем
//и даже больше можно добавить в начало аббревиатуру исходного индикатора
extern int HL_v2_barn=3000;
extern int HL_v2_Length=12;

//---- buffers здесь объявление использования буферов
double increasing_tops[];     //в этом буфере (массиве) будем отображать значки повышающихся вершин
double lowerring_troughs[];   //в этом буфере (массиве) будем отображать значки понижающихся впадин


//----- var здесь будем описывать глобальные для индикатора переменные, которые будут доступны
datetime time_0;           //последнее известное время 0 бара
double High_0,Low_0;       //последние известные максимум и минимум 0 бара
//----- из любого места нашего кода индикатора

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   //функция init предназначена для начальной инициализации буферов, переменных
   //т.к. нас интересуют значки то соответственно выбераем этот тип отрисовки
   //о специфике и различиях можно почитать в справке, и посмотреть на примере
   //стандартных индикаторов
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexStyle(1,DRAW_ARROW);
   //назначаем код значка которым будет отображаться наш индикатор
   SetIndexArrow(0,217);
   SetIndexArrow(1,218);
   //привязываем наши массивы к буферам индикаторов
   SetIndexBuffer(0,increasing_tops);
   SetIndexBuffer(1,lowerring_troughs);
   //назначаем инициализационное значение для буфера, я например практикую значение "-1"
   //это дает возможность использование сравнения с 0, в данном случае это делать не
   //обязательно, но бывает очень удобно в некоторых случаях, а означает то, что до тех пор
   //пока мы явно не назначим конкретное значение, в буфере содержится значение "-1" и
   //при отрисовке если такое значение встречается, то на этом месте индикатор ничего не
   //отрисует
   SetIndexEmptyValue(0,-1.0);
   SetIndexEmptyValue(1,-1.0);
   //можно задать некоторые имена для буферов, которые будут подсвечиваться, при наведении
   //на них курсора (хинты)
   SetIndexLabel(0,"есть повышающиеся максимумы");
   SetIndexLabel(1,"есть понижающиеся минимумы");
   //инициализируем также нижеописанную глобальную для индикатора переменную
   time_0=0;
//----
   return(0);
  }
//---- из опыта знаю что мало какие расчеты обходятся без сравнения чисел с плавающей точкой
//---- и специфики этого сравнения в MQL4 сразу вставляю функции на сравнении двух чисел
//---- их две - на равенство, и на то что первое число, больше второго. Они нам пригодятся.
//+--------------------------------------------------------------------------------------------------------------------------------------------------+
//| right comparison of 2 doubles                                                                                                                    |
//+--------------------------------------------------------------------------------------------------------------------------------------------------+
bool GreaterDoubles(double number1,double number2,int dig)
{
   if(NormalizeDouble(number1-number2,dig)>0) return(true);
   else return(false);
}
//+--------------------------------------------------------------------------------------------------------------------------------------------------+
//| right comparison of 2 doubles                                                                                                                    |
//+--------------------------------------------------------------------------------------------------------------------------------------------------+
bool CompareDoubles_m(double number1,double number2,int dig)
{
   if(NormalizeDouble(number1-number2,dig)==0) return(true);
   else return(false);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   //теперь нам нужно определиться, как мы будем просчитывать индикатор
   //слева направо, или наоборот и как часто мы будем это делать
   //думаю классический расчет слева направо можно использовать
   //в дальнейшем нужно подходить к каждому случаю индивидуально
   //и выбирать оптимальный вариант, чтобы производить как можно
   //меньше операций
   //следующим шагом будет определение области баров (подсвечников)
   //на которых необходимо произвести расчет, при ее определении
   //также необходимо учитывать специфику исходных данных
   //например мы знаем что исходный индикатор модифицируется
   //изменяет свои показания при условии что на последнем баре
   //установлен новый минимум или максимум, также начальную фиксацию
   //минимума и максимума нужно начинать с момента появления этого бара
   //т.е. определение состояния мы будем производить в двух случаях
   //1. если появился новый бар
   //2. если установлен новый минимум или максимум
   //для определения появления нового бара можно воспользоваться
   //следующими приемами
   //1. сравнение количества баров текущего и ранее записанного
   //2. сравнение времени начала отрисовки 0 бара текущего и ранее записанного
   //мы будем использовать второй вариант
   //также нас интересует первый просчет всей области индексов, на момент
   //прикрепления индикатора, т.к. в это время может и не появляться новых баров,
   //а мы должны просчитать всю область, этот момент мы будем определять по количеству
   //просчитанных баров определяемых функцией IndicatorCounted(), т.к. при первоначальном
   //просчете количество этих баров равно 0
   //для фиксации времени нулевого бара, а также его минимума и максимума
   //заведем глобальные для индикатора переменные, там где у нас раздел
   //"//----- var "
   //итак если у нас появился новый бар или это первый расчет, т.е. время последнего известного
   //времени 0 бара меньше чем время 0 бара на графике
   if( time_0<Time[0] )
   {
      //здесь идет объявление и сразу расчет переменной counted_bars, но я лично
      //предпочитаю выносить все объявления переменных в начало функции
      //на мой взгляд так удобнее
      int counted_bars=IndicatorCounted();
      //цикл мы будем делать по барам поэтому индекс бара рассчитываемого в текущий момент
      //мы так и обзовем current_bar, а количество баров требующих расчет (вернее область индексов)
      //обзавем limit_calculated_bar, обе эти переменные будут иметь целочисленный тип
      int current_bar,limit_calculated_bar;
      //если по какой-то причине произошел сбой, то переменная counted_bars, будет содержать значение
      //меньше 0, в этом случае не производим никаких расчетов и выходим из функции с возвратом кода "-1"
      //это на всякий, чтобы можно было обработать эту ситуацию
      if( counted_bars<0 )
      {
         return(-1);
      }
      //фиксируем последнее известное время 0 бара
      time_0=Time[0];
      //фиксируем максимум и минимум нового 0 бара
      High_0=High[0];
      Low_0=Low[0];
      //т.к. при появлении нового бара появлется один непросчитанный бар+для гарантированного
      //просчета в MQL4 значение IndicatorCounted() возвращается на 1 меньше чем реальное значение
      //то получается что при появлении нового бара нужно посчитать два последних бара, но
      //мы во избежание лишней головомороки и оптимизации увеличиваем это значение на 1
      //и таким образом будем просчитыать только последний "0" бар
      counted_bars++;
      //таким образом при первом расчете у нас будет просчитано Bars-1-counted_bars(эта вся область индексов минус 1,
      //самый левый бар на графике просчитываться не будет, а оно нам и не надо)
      //при последующих эта область будет состоять из области 0 индекса, т.е. самый последний бар
      limit_calculated_bar=Bars-1-counted_bars;
   }
   else
   {
      //иначе если нет нового бара и не первый расчет
      //область индексов требующих расчет равна 0, т.е. требуется просчитать только последний бар
      limit_calculated_bar=0;
   }
   
   //как уже раньше упомянал что нам не надо ничего считать если не изменились максимумы и минимумы
   //за исключением когда максимум=минимум, а такое бывает на первом тике бара
   //здесь понадобятся наши предсказанные функции на сравнение
   //формируем условие - если максимум 0 бара не равен минимуму 0 бара (не первый тик) и при этом
   //значение максимума 0 бара не больше последнего известного максимума 0 бара и последний известный
   //минимум 0 бара больше минимума 0 бара и это не первый просчет, пропускаем расчеты и выходим
   //
   if( !CompareDoubles_m(High[0],Low[0],Digits) && !GreaterDoubles(High[0],High_0,Digits) && !GreaterDoubles(Low_0,Low[0],Digits) && counted_bars>1 )
   {
      return(0);
   }
   //иначе сохраняем новые значения максимума и минимума
   High_0=High[0];
   Low_0=Low[0];
   //а здесь будем проводить обсчет всех требуемых индексов
   //для начала напишем шаблон цикла, затем перейдем к доп функциям
   //которые напишем для облегчения читаемости кода
   for( current_bar=limit_calculated_bar;current_bar>=0;current_bar-- )
   {
      //после того как мы описали функцию получения значений 
      //вспомогательного индикатора, можем продолжить дальше
      //понятно, что если на текущем баре индикатор не отрисовывался
      //то значит ничего пока не изменилось и считать его не надо,
      //но если это не последний индекс (крайне правый - 0),
      //то есть еще бары на которых возможно необходимо будет
      //произвести расчет поэтому мы воспользуемся командой continue
      //а не return
      //заведем временную переменную в которой будем хранить значение полученное
      //функцией Get_mInd_value
      double tmp_value=Get_mInd_value(current_bar);
      if( !GreaterDoubles(tmp_value,0,Digits) )
      {
         continue;
      }
      else
      {
         //первая точка у нас есть, теперь нужно найти вторую точку
         //с которой будет идти сравнение, для этого напишем еще
         //одну функцию - search_second_point
         double first_point=tmp_value;
         double second_point=search_second_point(current_bar);
         //теперь если первая точка построена по максимуму и она выше второй
         //записываем значение в буфер increasing_tops
         //если же построена по минимуму и ниже ниже
         //записываем значение в буфер lowerring_troughs
         if( CompareDoubles_m(first_point,High[current_bar],Digits) && GreaterDoubles(first_point,second_point,Digits) )
         {
            //наверно целесообразно поставить значок чуть выше на 10 пипсов
            increasing_tops[current_bar]=High[current_bar]+10*Point;
         }
         else
         {
            if( CompareDoubles_m(first_point,Low[current_bar],Digits) && GreaterDoubles(second_point,first_point,Digits) )
            {
               lowerring_troughs[current_bar]=Low[current_bar]-10*Point;
            }
         }
      }
      
   }
//----
   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
   return(0);
}
//+------------------------------------------------------------------+
//| Функция возвращает значение вспомогательного индикатора на       |
//| полученном в качестве параметра индексе                          |
//+------------------------------------------------------------------+
double Get_mInd_value( int cur_bar )
{
//----
   double result;          //переменная в которой будет храниться результат работы функции
   //будь внимателен большинство людей обращавшихся ко мне за помощью в поиске ошибок
   //просто неверно писали наименование индикатора в результате чего получали
   //неправильный результат работы кода
   result=iCustom(NULL,0,"High_Low_v2",HL_v2_barn,HL_v2_Length,0,cur_bar); 
   //в данном случае cur_bar - это полученный индекс, на котором необходимо определить факт 
   //отрисовки вспомогательного индикатора
//----
   return(result);
}
//+------------------------------------------------------------------+
//| Функция возвращает значение вспомогательного индикатора на       |
//| втором искомом индексе                                           |
//+------------------------------------------------------------------+
double search_second_point( int cur_bar )
{
//----
   double result;          //переменная в которой будет храниться результат работы функции
   //здесь потребуется свой миницикл с индекса следующего за 1 найденной точкой
   //фактически нам нужно найти третье значение индикатора больше значения инициализации
   //объявим переменную
   int cb;                 //current_bar сократили до cur_bar, а здесь еще короче :)
   //также нам потребуется булева переменная, которая по умолчанию фальсе
   //а нагрузка будет состоять в том, что прошли мы уже вторую точку или нет
   bool intermediate_point=0;
   //почему мы ищем третью наверно понятно, потому что вершины чередуются
   //если последняя вершина, предпоследняя впадина, а предшествующая ей опять вершина
   //нам же нужно будем сравнивать две вершины или две впадины
   //здесь цикл идет справа налево
   for( cb=cur_bar+1;cb<Bars;cb++ )
   {
      //здесь нам понадобится уже написанная функция Get_mInd_value
      //опять таки если значений нет пропустим бар
      double tmp_value=Get_mInd_value(cb);
      if( !GreaterDoubles(tmp_value,0,Digits) )
      {
         continue;
      }
      else
      {
         //смотрим если вторая точка еще не пропущена
         if( !intermediate_point )
         {
            intermediate_point=1;   //выставляем флаг что вторая точка, ту что нужно пропустить найдена
         }
         else
         {
            //нашли искомую точку, прерываем цикл, далее в нем нет необходимости
            result=tmp_value;
            break;
         }
      }
   }
//----
   return(result);
}



Forex Trader
114255
Forex Trader 2008.02.28 14:44  
Спасибо тебе огромное, дружище! На самом деле, заложенная тобой в твой индикатор логика соответствует тому, что я говорил, просто надо кое-что добавить. Но я уже вижу, что справлюсь с этим самостоятельно с учетом твоих подробнейших комментариев.

Я читал что-то по mql (начинал с нуля, безо всякого опыта программирования чего-либо), но, конечно, парочка твоих постов с разбором конкретных задач помогли мне куда больше, чем изучение абстрактных примеров. Думаю, если бы ты написал учебник по mql, он бы пользовался спросом (по крайней мере, я бы купил) :)

Спасибо!
Forex Trader
114255
Forex Trader 2008.02.29 07:50  
/
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий