Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 795

 
Alexey Viktorov:
Задайте цвет отображения clrNONE.

То есть можно только буфер выводить, а отдельно переменную нельзя?

 
psyman:

То есть можно только буфер выводить, а отдельно переменную нельзя?

Да, только так. И ещё одна примочка, может пригодится, если задать SetIndexLabel(0, ""); то в окне данных эти значения не будут отображаться. И даже будут недоступны функции iCustom()
 
Igor Makanu:

Спасибо что ответили.

Так что как я понял надо создать буфер, потом заполнить

его значениями RSI и далее скормить этот буфер iMAOnArray().

Кто нибудь делал такое для советника и это будет отображаться при тестах советника в подокне?

Через iCustom обычно тесты советника подтормаживают.

 

Взял код из примера в справочнике https://www.mql5.com/ru/docs/strings/stringadd и вставил его в скрипт. Результат выполнения аналогичный в MQL4 и MQL5:


HE      0       22:42:49.015    Test Script (EURUSD,H1) time for 'c = a + b' = 235 milliseconds, i = 1000000
OH      0       22:42:50.187    Test Script (EURUSD,H1) time for 'StringAdd(a,b)' = 1156 milliseconds, i = 1000000
EP      0       22:42:50.781    Test Script (EURUSD,H1) time for 'StringConcatenate(c,a,b)' = 594 milliseconds, i = 1000000


Я думал, что StringAdd() и StringConcatenate() должны выполняться быстрее чем "+". Почему это не так?

 
Northwest:

Через iCustom обычно тесты советника подтормаживают.

не правда, обычно наоборот, т.к. распределением памяти для индикаторных буферов занимается терминал, а не скрипт MQL , обычно эти проблемы - это проблема не оптимального расчета  в индикаторе, многие новички на одном вызове индикатора - тик, рассчитывают всю длину исторических данных

ну если уже разобрались с основами MQL, читайте статьи, давно все написано

https://www.mql5.com/ru/articles/4602


Northwest:

Кто нибудь делал такое для советника и это будет отображаться при тестах советника в подокне?

никто не делал, прочитайте чем советник от индикатора отличается, у кого есть индикаторные буфера и у кого нет, у кого есть торговые функции у кого....

ЗЫ:подокно умеет создавать только индикатор, если Вы создадите подокно, тогда можете в это подокно добавлять графические объекты с помощью советника https://www.mql5.com/ru/docs/constants/objectconstants/enum_object

ЗЫЗЫ: подокно можно с помощью применения шаблона получить, была тема пару месяцев назад, но думаю у Вас задача в другом пока

Как перенести расчетную часть любого индикатора в код эксперта
Как перенести расчетную часть любого индикатора в код эксперта
  • www.mql5.com
Когда программист создает советник, который получает сигналы от индикаторов, он всякий раз сталкивается с вопросом: использовать обращение к индикатору или перенести код индикатора в советник? Причины этому могут быть различные: желание сохранить в тайне используемые индикаторы и стратегию в целом, необходимость распространения советника единым...
 
Igor Makanu:

не правда, обычно наоборот, т.к. распределением памяти для индикаторных буферов занимается терминал, а не скрипт MQL , обычно эти проблемы - это проблема не оптимального расчета  в индикаторе, многие новички на одном вызове индикатора - тик, рассчитывают всю длину исторических данных

ну если уже разобрались с основами MQL, читайте статьи, давно все написано

https://www.mql5.com/ru/articles/4602


никто не делал, прочитайте чем советник от индикатора отличается, у кого есть индикаторные буфера и у кого нет, у кого есть торговые функции у кого....

ЗЫ:подокно умеет создавать только индикатор, если Вы создадите подокно, тогда можете в это подокно добавлять графические объекты с помощью советника https://www.mql5.com/ru/docs/constants/objectconstants/enum_object

ЗЫЗЫ: подокно можно с помощью применения шаблона получить, была тема пару месяцев назад, но думаю у Вас задача в другом пока

Извиняюсь. Может я не правильно выразился но

насчёт подокна я имел ввиду только тестирование советника.А не его эксплуатацию.

Что касаемо визуализации на графике индикатора в процессе тестирования советника то если пользоваться

встроенными функциями индикаторами они без проблем отрисовываются на графике в процессе тестирования

советника.Вот именно это я и имел ввиду.

А если пользоваться какимто своим кодом расчёта индикатора встроенным в код советника то этот индикатор

не будет отображён в процессе тестирования советника.

Что касаемо iCustom то при  её использовании в процессе тестирования советника будут отображены на графике

любые индикаторы и код индикатора при том можно скомпилировать с советником в один ex4 но мне это не нужно.

Просто я хотел узнать может как то можно обойти в этом вопросе iCustom.Но если нет то тоже не проблема.

Большое спасибо за развёрнутый ответ.

 

Здесь Артем выкладывал шаблон индикатора, вот часть из  OnCalculate

//--- Проверка количества доступных баров (1 - минимально, 4 - оптимально для большинства расчётов. Но всё "по месту"...)
   if(rates_total<4) return 0;
//--- Проверка и расчёт количества просчитываемых баров
   int limit=rates_total-prev_calculated; // 0 - пришел новый тик, новый бар формироваться не начал. 1 - пришел новый тик и начал формироваться новый бар.
   if(limit>1) 
               // если вписать "limit>0", то на нулевом баре будет расчёт только нулевого бара, на каждом новом баре будет полный перерасчёт всей истории
               // если вписать "limit>1", то на нулевом баре будет расчёт только нулевого бара, на открытии нового бара - пересчёт первого и нулевого,
               // при подгрузке истории и на первом запуске - перерасчёт всей истории
     {
      limit=rates_total-1;
      // здесь должна быть инициализация всех используемых буферов индикатора необходимыми значениями (обычно EMPTY_VALUE и 0)
     }

Я его использую, но один вопрос не дает мне покоя ))

Почему для полного расчета истории используется limit=rates_total-1 , а не limit=rates_total?

 
psyman:

Почему для полного расчета истории используется limit=rates_total-1 , а не limit=rates_total?

попробуйте проверить, будет сразу "вылет" за пределы массива - нумерация баров от нуля до ... общее кол-во -1 , обычная ситуация в программировании - нумерация начинается с 0 . Как очевидный пример объявите массив double x[5] и попробуйте записать что-нить в последний элемент x[5] = 100;

ЗЫ: отвечаю на не заданный еще вопрос.... OrderTotal() тоже нумерация с нуля до OrderTotal()-1 ;)

 
Igor Makanu:

ЗЫ: отвечаю на не заданный еще вопрос.... OrderTotal() тоже нумерация с нуля до OrderTotal()-1 ;)

Вопрос возник попутно, сейчас пока не могу победить усреднение по массиву, правда делаю в пятерке, но в какую тему написать не знаю, пусть будет здесь.

Индикатор вычисляет разницу open-close и строит по ней МА. Для отладки выбрал МА=2, однако при использовании SimpleMAOnBuffer и iMAOnArray получаются необъяснимые смещения линии, iMAOnArray на последнем баре выдает нулевое значение.


//+------------------------------------------------------------------+
//|                                                        _null.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#include <MovingAverages.mqh>

#property indicator_buffers 4
#property indicator_plots   2
//--- plot OC
#property indicator_label1  "OC"
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrSteelBlue, clrRed,clrGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "MA1"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBrown
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1


//--- indicator buffers
double   OC[], OC_color[], MA1_buf[];
input int MA1=2;

int OnInit()
  {
  
   IndicatorSetString(INDICATOR_SHORTNAME,"t1");
   
   SetIndexBuffer(0,OC,INDICATOR_DATA);
   SetIndexBuffer(1,OC_color,INDICATOR_COLOR_INDEX);
   
   SetIndexBuffer(2, MA1_buf,INDICATOR_DATA); 
   //PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,50);

     
//--- indicator buffers mapping

   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{

//--- Проверка количества доступных баров (1 - минимально, 4 - оптимально для большинства расчётов. Но всё "по месту"...)
   if(rates_total<4) return 0;
//--- Проверка и расчёт количества просчитываемых баров
   int limit=rates_total-prev_calculated; // 0 - пришел новый тик, новый бар формироваться не начал. 1 - пришел новый тик и начал формироваться новый бар.
   //if(limit>1) 
   
               // если вписать "limit>0", то на нулевом баре будет расчёт только нулевого бара, на каждом новом баре будет полный перерасчёт всей истории
               // если вписать "limit>1", то на нулевом баре будет расчёт только нулевого бара, на открытии нового бара - пересчёт первого и нулевого,
               // при подгрузке истории и на первом запуске - перерасчёт всей истории
     {
     limit=rates_total-1;
           // здесь должна быть инициализация всех используемых буферов индикатора необходимыми значениями (обычно EMPTY_VALUE и 0)
     }
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      // необходимые действия по расчёту индикатора
     
     OC[i]=fmax(open[i],close[i])-fmin(open[i],close[i]);
     if(OC[i]>0.001)
      {   OC_color[i]=1;
      }
      }  
   
 /*  for(int k=limit; k>=0 && !IsStopped(); k--)
     {
   
     MA1_buf[k]=iMAOnArray(OC,0,MA1,k,MODE_SMA,0);
     }
*/
      SimpleMAOnBuffer(rates_total,prev_calculated,0,MA1,OC,MA1_buf);

//--- return value of prev_calculated for next call
   return(rates_total);
  }




double iMAOnArray(double &array[],
                      int total,
                      int period,
                      int ma_shift,
                      int ma_method,
                      int shift)
  {
   double buf[],arr[];
   if(total==0) total=ArraySize(array);
   if(total>0 && total<=period) return(0);
   if(shift>total-period-ma_shift) return(0);
   switch(ma_method)
     {
      case MODE_SMA :
        {
         total=ArrayCopy(arr,array,0,shift+ma_shift,period);
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,pos=total-1;
         for(i=1;i<period;i++,pos--)
            sum+=arr[pos];
         while(pos>=0)
           {
            sum+=arr[pos];
            buf[pos]=sum/period;
            sum-=arr[pos+period-1];
            pos--;
           }
         return(buf[0]);
        }
      case MODE_EMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double pr=2.0/(period+1);
         int    pos=total-2;
         while(pos>=0)
           {
            if(pos==total-2) buf[pos+1]=array[pos+1];
            buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_SMMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0;
         int    i,k,pos;
         pos=total-period;
         while(pos>=0)
           {
            if(pos==total-period)
              {
               for(i=0,k=pos;i<period;i++,k++)
                 {
                  sum+=array[k];
                  buf[k]=0;
                 }
              }
            else sum=buf[pos+1]*(period-1)+array[pos];
            buf[pos]=sum/period;
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      case MODE_LWMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double sum=0.0,lsum=0.0;
         double price;
         int    i,weight=0,pos=total-1;
         for(i=1;i<=period;i++,pos--)
           {
            price=array[pos];
            sum+=price*i;
            lsum+=price;
            weight+=i;
           }
         pos++;
         i=pos+period;
         while(pos>=0)
           {
            buf[pos]=sum/weight;
            if(pos==0) break;
            pos--;
            i--;
            price=array[pos];
            sum=sum-lsum+price*period;
            lsum-=array[i];
            lsum+=price;
           }
         return(buf[shift+ma_shift]);
        }
      default: return(0);
     }
   return(0);
  }
 
psyman:

Вопрос возник попутно, сейчас пока не могу победить усреднение по массиву, правда делаю в пятерке, но в какую тему написать не знаю, пусть будет здесь.

в MQL5 индикаторные буффера и таймсерии "развернуты" наоборот, по умолчанию самый левый бар в МТ5 это бар №0, а в МТ4 самый правый бар это бар №0 и индикаторные буффера такую же имеют нумерацию

ЗЫ: увы, с МТ5 не хочу возиться, мне для проверки идей МТ4 хватает, в МТ5 только готовою смотрю, если что и пишу под МТ5, то никому не показываю )))