Предложение как ускорить оптимизацию.

 
На самом деле оптимизация идет очень медленно. Вот пример советника
int i1;
int i2;
double         i1Buffer[1];
double         i2Buffer[1];

input int Par=15;

int OnInit()
  {
   i1=iCustom(_Symbol,_Period,"i1",Par);
   i2=iCustom(_Symbol,_Period,"i2",Par);
   return(0);
  }
void OnDeinit(const int reason)
  {
   IndicatorRelease(i1);
   IndicatorRelease(i2);
  }

int Magic=12345;

void Buy(void)
  {
  
   MqlTradeRequest mrequest;
   MqlTradeResult mresult;
   MqlTick Tick;

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   
   mrequest.action=TRADE_ACTION_DEAL;                                 // немедленное исполнение
   mrequest.price=NormalizeDouble(Tick.ask,_Digits);          // последняя цена ask
   mrequest.sl = 0;// NormalizeDouble(Tick.ask - StopLoss  * _Point,_Digits); // Stop Loss
   mrequest.tp = 0;//NormalizeDouble(Tick.ask + TakeProfit* _Point,_Digits); // Take Profit
   mrequest.symbol= _Symbol;                                         // символ
   mrequest.volume = Lot;                                            // количество лотов для торговли
   mrequest.magic = Magic;                                        // Magic Number
   mrequest.type = ORDER_TYPE_BUY;                                     // ордер на покупку
   mrequest.type_filling = ORDER_FILLING_AON;                          // тип исполнения ордера - все или ничего
   mrequest.deviation=3;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }

void Sell(void)
  {
  
   MqlTradeRequest mrequest;
   MqlTradeResult mresult;
   MqlTick Tick;

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);

   
   mrequest.action=TRADE_ACTION_DEAL;                                 // немедленное исполнение
   mrequest.price=NormalizeDouble(Tick.bid,_Digits);          // последняя цена ask
   mrequest.sl = 0;//NormalizeDouble(Tick.bid + StopLoss  * _Point,_Digits); // Stop Loss
   mrequest.tp =0;// NormalizeDouble(Tick.bid - TakeProfit* _Point,_Digits); // Take Profit
   mrequest.symbol= _Symbol;                                         // символ
   mrequest.volume = Lot;                                            // количество лотов для торговли
   mrequest.magic = Magic;                                        // Magic Number
   mrequest.type = ORDER_TYPE_SELL;                                     // ордер на продажу
   mrequest.type_filling = ORDER_FILLING_AON;                          // тип исполнения ордера - все или ничего
   mrequest.deviation=3;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }
void OnTick()
  {
   
//   int copy;
   /*copy = */CopyBuffer ( i1,0,0,1,i1Buffer);
   /*copy = */CopyBuffer ( i2,0,0,1,i2Buffer);
   
   if ( i1Buffer[0] != 0 )
      Sell();
   if ( i2Buffer[0] != 0 )
      Buy();

  }
//+------------------------------------------------------------------+
Знакомство с MQL5: написание простого советника и индикатора
Знакомство с MQL5: написание простого советника и индикатора
  • 2010.03.16
  • Denis Zyatkevich
  • www.mql5.com
В этой статье проведен краткий обзор языка MQL5, приведен пример написания советника и индикатора. Данная статья ориентирована как на читателей, знакомых с программированием на языке MQL4, так и на тех, кто только начинает знакомство с программированием торговых систем и индикаторов.
 

Так вот видимо следует не пересчитывать индикаторы рассчитанные на предыдущих прогонах.

Если тормозит не тут , то укажите где. Вот только не надо советовать поменять стратегию - да пусть она "такая" специально, но настоящую не покажу. Но тестирует МЕДЛЕННО !!!! Надо срочно улучшать тестер. !

 

Если без торговых операций тоже тормозит, то нужно смотреть код индикатора

void OnTick()
  {
   
//   int copy;
   /*copy = */CopyBuffer ( i1,0,0,1,i1Buffer);
   /*copy = */CopyBuffer ( i2,0,0,1,i2Buffer);
уберем все торговые операции   
//   if ( i1Buffer[0] != 0 )
//      Sell();
//   if ( i2Buffer[0] != 0 )
//      Buy();

  }

 
Academic:

Так вот видимо следует не пересчитывать индикаторы рассчитанные на предыдущих прогонах.

Если тормозит не тут , то укажите где. Вот только не надо советовать поменять стратегию - да пусть она "такая" специально, но настоящую не покажу. Но тестирует МЕДЛЕННО !!!! Надо срочно улучшать тестер. !

Я это реалузую в самом индикаторе - беру массив цен, и беру этот массив не каждый тик, а по "is new bar", и тольк минимально сколько надо для текущего расчета, например - 10 последних, и индикатор сам рассчитывается и строится не на весь буфер, а только для последних, скажем, десяти свечек, и расчет не кажный тик, а по "is new bar". Еще есть такая возможность - попробуйте написать собственный тестер прямо в режиме индикатора, и зависимости от тестера не будет, и эквити он-лайн. Последнее средство - все расчеты(включая собственный тестер) на с++ dll в машинный код. В МТ не особо пока разбираюсь, т.ч. может чего не так понял...
 
Academic:
Если тормозит не тут , то укажите где. Вот только не надо советовать поменять стратегию - да пусть она "такая" специально, но настоящую не покажу. Но тестирует МЕДЛЕННО !!!! Надо срочно улучшать тестер. !

Указываем - индикаторы неэкономные.

Но Вы не предоставили их кода.

 
Возможность такой оптимизации в тестере, это частный случай торговой стратегии в целом. Поэтому навряд ли появится эта оптимизация.

 
mql5:
Возможность такой оптимизации в тестере, это частный случай торговой стратегии в целом. Поэтому навряд ли появится эта оптимизация.

Представьте себе 2000 прогонов от начальной даты и до конечной - параметры не меняются => можно один раз индикатор просчитать и потом только выдавать расчетные. :) То есть если код експерта из трех строк, то тут уж по любому надо расчитывать индикатор один раз. Правда есть проблемы с нулевым баром. Так как там бар по которому расчитывается индикатор еще не сформирован. Но заниматься одинаковыми расчетами - глупо.
 
Renat:

Указываем - индикаторы неэкономные.

Но Вы не предоставили их кода.

ОК - я потрачу время, все равно надо вас убедить :))  И покажу что  все-таки, господа надо  "оптимизировать" работу тестера, а иначе результата не будет.


Вот тот же "эксперт" :fff.mq5

int i1;
int i2;
double         i1Buffer[1];
double         i2Buffer[1];

input int Par=15;

int OnInit()
  {
   i1=iCustom(_Symbol,_Period,"i1",Par);
   if ( i1 == INVALID_HANDLE )
      printf("ssss-> i1");
      
   i2=iCustom(_Symbol,_Period,"i2",Par);
   return(0);
  }
void OnDeinit(const int reason)
  {
   IndicatorRelease(i1);
   IndicatorRelease(i2);
  }

int Magic=12345;

void Buy(void)
  {
  
   MqlTradeRequest mrequest;
   MqlTradeResult mresult;
   MqlTick Tick;

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   
   mrequest.action=TRADE_ACTION_DEAL;                                 // немедленное исполнение
   mrequest.price=NormalizeDouble(Tick.ask,_Digits);          // последняя цена ask
   mrequest.sl = 0;// NormalizeDouble(Tick.ask - StopLoss  * _Point,_Digits); // Stop Loss
   mrequest.tp = 0;//NormalizeDouble(Tick.ask + TakeProfit* _Point,_Digits); // Take Profit
   mrequest.symbol= _Symbol;                                         // символ
   mrequest.volume = Lot;                                            // количество лотов для торговли
   mrequest.magic = Magic;                                        // Magic Number
   mrequest.type = ORDER_TYPE_BUY;                                     // ордер на покупку
   mrequest.type_filling = ORDER_FILLING_AON;                          // тип исполнения ордера - все или ничего
   mrequest.deviation=3;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }

void Sell(void)
  {
  
   MqlTradeRequest mrequest;
   MqlTradeResult mresult;
   MqlTick Tick;

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);

   
   mrequest.action=TRADE_ACTION_DEAL;                                 // немедленное исполнение
   mrequest.price=NormalizeDouble(Tick.bid,_Digits);          // последняя цена ask
   mrequest.sl = 0;//NormalizeDouble(Tick.bid + StopLoss  * _Point,_Digits); // Stop Loss
   mrequest.tp =0;// NormalizeDouble(Tick.bid - TakeProfit* _Point,_Digits); // Take Profit
   mrequest.symbol= _Symbol;                                         // символ
   mrequest.volume = Lot;                                            // количество лотов для торговли
   mrequest.magic = Magic;                                        // Magic Number
   mrequest.type = ORDER_TYPE_SELL;                                     // ордер на продажу
   mrequest.type_filling = ORDER_FILLING_AON;                          // тип исполнения ордера - все или ничего
   mrequest.deviation=3;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }
void OnTick()
  {
   
//   int copy;
   /*copy = */CopyBuffer ( i1,0,0,1,i1Buffer);
   /*copy = */CopyBuffer ( i2,0,0,1,i2Buffer);
   
   if ( i1Buffer[0] != 0 )
      Sell();
   if ( i2Buffer[0] != 0 )
      Buy();

  }
//+------------------------------------------------------------------+


Вот индикаторы :

i1.mq5 ->


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_label1  "i1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

input int      Par=15;

double         Label1Buffer[];

int OnInit()
  {
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
   
   return(0);
  }
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[])
  {
   
   for ( int i=prev_calculated; i<rates_total; i++){
      
      int sum=0;
      
      int e=i+Par;
      if ( e > rates_total )
         e=rates_total;
         
      if ( (e-i)/3 != 0 ){   
         for ( int j=i; j<e; j++ )
            sum += (int)(open[j]/_Point);
            
         sum = sum / ( (e-i)/3 );
            
         if ( (sum % Par) == 0 ) 
            Label1Buffer[i]=open[i];
      }
   }
   return(rates_total);
  }


Вот i2.mq5->


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_label1  "i2"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

input int      Par=15;

double         Label1Buffer[];

int OnInit()
  {
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
   
   return(0);
  }
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[])
  {
   
   for ( int i=prev_calculated; i<rates_total; i++){
      
      int sum=0;
      
      int e=i+Par;
      if ( e > rates_total )
         e=rates_total;
            
      if ( (e-i)/3 != 0 ){  
         for ( int j=i; j<e; j++ )
            sum += (int)(open[j]/_Point);
            
         sum = sum / ( (e-i)/3 );
            
         if ( (sum % (Par+Par/2)) == 0 ) 
            Label1Buffer[i]=open[i];
            
      }   
   }
   return(rates_total);
  }

 

Не сказать что какой-то выдающийся код у индикаторов. Не сказать что перегруженный. Но зачем его вычислять сто-тыщь раз при оптимизации на одних и тех же данных не понятно.
 

Academic:
Представьте себе 2000 прогонов от начальной даты и до конечной - параметры не меняются => можно один раз индикатор просчитать и потом только выдавать расчетные. :) То есть если код експерта из трех строк, то тут уж по любому надо расчитывать индикатор один раз. Правда есть проблемы с нулевым баром. Так как там бар по которому расчитывается индикатор еще не сформирован. Но заниматься одинаковыми расчетами - глупо.

Такой подход годится только при режиме "по ценам открытия".

Как быть со значениями индикатора в процессе развития бара? 

Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы - Документация по MQL5
 
stringo:

Такой подход годится только при режиме "по ценам открытия".

Как быть со значениями индикатора в процессе развития бара? 

Все просто - надо хранить результаты один раз просчитать и все - сохранить на диске и выдавать. Число тиков одинаково на каждый тик сохранил значение индикатора и потом только выдаешь - не считаешь. Иначе нафиг-нафиг такой оптимизатор. Вы же сами нагрузили тестер мультивалетностью, и хотите со старым подходом как в четверке? Вот поэтому и получается что медленно. И надо отработать компенсацию ( соптимизировать) по мультивалютной нагрузке.



Причина обращения: