Опять вопрос про быстродействие. - страница 2

 
Integer:

Какая у MQ задумана методика не знаю, скорее нет методики, просто дают средства программирования, а потом смотрят и диву даются, как этим пользуются.

Придерживаюсь таких принципов: вычисления делать в индикаторе, если постоянно нужны какие-то промежуточные значение, то выделять для них буферы и тянуть за собой, при переходе к вычислению очередного бара. Должен соблюдаться приницип обсчета только одного бара и использования значений других буферов только с тем же индексом, что у обсчитываемого бара, или с фиксированным отступом (главное не бегать в циклах по истории на каждом баре, а в буфере подтягивать за собой значение, как в индикаторе МА сделано - на каждом баре берется значение с предыдущего бара, старое отнимается, новое прибавляется...).  В советнике - через iCustom() копировать значение только с одного буфера. Если формирующийся бар не используется, то еще делать проверку времени бара, чтобы копировать значение только один раз на бар (но обязательно делать копирование на каждом баре, даже если значение не нужно). Еще можно тики пропускать, если цена не сильно изменилась  - выходим из OnTick() - это для пятизнака.

 

Да это все понятно про то как экономить вычесления. Но все же что быстрее? - иметь iCustom с копированием одного буфера, или делать такие расчеты в советнике копируя все через CopyRates? Что быстрее копировать 2000 баров или все, надеясь что компилятор поймет и комировать ничего не будет а просто даст буфера?



Да вот еще что - очень нужная вещь нужна - некий диспетчер задач. Ну например на графике есть некий индикатор с параметром (1) и в советнике вызывается такой же с такими же параметрами, и в другом индикаторе, вообщем было бы очень полезно, для того чтобы правильнее использовать ресурсы иметь такой некий диспечер ресурсов, чтобы там показывалось какие индикаторы и советрики загруженны сколько памяти они жрут, сколько времени занимают их вычесления. Кстати тайминги можно брать их интеловой библиотеки или сделать самим из счетчика встроенного в ядра, но у АМД по моему они работают несколько отлично от интела. Но тогда можно сиспользовать "счетчики производительности" от висты, а на XP можно их эмулировать.

 
Integer:
Четыре массива по 2000 баров на каждом тике... Вычисления, требующие исторических данных, надо в индикаторе делать.

:) Сделал, в советнике копируется только один бар из двух буферов iCustom , то есть код советника такой -

 int co;  
     double ib0[1];
     double ib1[1];
     
     co=CopyBuffer ( i4, 0,          0,1, ib0); 
     co=CopyBuffer ( i4, 1,          0,1, ib1); 
     
     
     if ( ib0[0] > 0 ){
      Buy(); 
     }
     
     if ( ib1[0] > 0 ){
      Sell(); 
     }


Результат стал еще хуже. Пока еще ни один раз прогон не закончен. :(


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



 
Academic:

:) Сделал, в советнике копируется только один бар из двух буферов iCustom , то есть код советника такой -

Результат стал еще хуже. Пока еще ни один раз прогон не закончен. :(

Попробуйте сделать как написано в справке к CopyBuffer():

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

 
Rosh:

Попробуйте сделать как написано в справке к CopyBuffer():


Сделал - время изминилось с 600 секунд до 500. :(

 
Renat:

Приведите полный исходный код, пожалуйста. Если не публично, то через сервисдеск.

Это поможет нам воспроизвести ситуацию и разобраться.


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

ОК, мне что называется не жалко - тем более что это все из области тестирования и понимания возможностей MT5


Вот код советника, Вы его уже видели, этот немного изменен :) Для быстрого сворачивания. Но суть совершенно та же.

#property copyright "1"
#property link      "1"
#property version   "1.00"
//--- input parameters

input int      Depth=3;
input int      Deviation=10;// размах по вертикали - по цене должно быть больше спреда
input int      Backstep=2;

input double   Dif=1.0;
input double   Dif2=2.0;

input double Speeder=10.0;


int is40x;

int OnInit()
  {
   
   is40x=iCustom ( _Symbol, _Period,"is40x",Depth,Deviation,Backstep,Dif,Dif2);
   
   return(0);
  }

void OnDeinit(const int reason)
  {
   
    IndicatorRelease(is40x);
       
  }

int Magic=12345;

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

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   
   if ( PositionSelect(_Symbol) ){
      long t=PositionGetInteger(POSITION_TYPE);
      if ( t == POSITION_TYPE_SELL ) {
         double v  = PositionGetDouble(POSITION_VOLUME);
         v = v/Speeder;
         v = (int) ( v/SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP)+0.5);
         if ( v <= 0 )
            v=1;
         Lot = v*SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
      }
   }

   
   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=10;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }

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

   SymbolInfoTick(_Symbol,Tick);
   
   double Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   
   if ( PositionSelect(_Symbol) ){
      long t=PositionGetInteger(POSITION_TYPE);
      if ( t == POSITION_TYPE_BUY ) {
         double v  = PositionGetDouble(POSITION_VOLUME);
         v = v/Speeder;
         v = (int) ( v/SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP)+0.5);
         if ( v <= 0 )
            v=1;
         Lot = v*SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
      }
   }
   
   
   
   
   

   
   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=10;                                           // проскальзывание от текущей цены

   OrderSend(mrequest,mresult);
  }

void OnTick()
  {
   
    
     int co;  
     double is40x_b0[1];
     double is40x_b1[1];
     
     co=CopyBuffer ( is40x, 0,          0,1, is40x_b0); 
     co=CopyBuffer ( is40x, 1,          0,1, is40x_b1); 
     
     
     if ( is40x_b0[0] > 0 ){
      Buy();//Signal ( _Bars-1, low[_Bars-1] ) ; // BUY SIGNAL
     }
     
     if ( is40x_b1[0] > 0 ){
      Sell();//Signal ( _Bars-1, high[_Bars-1] ) ; // SALE SIGNAL
     }
     
         
  }


Вот индикатор - :) Красавчег правда - рисует цифры и уровни -

 
#property copyright "1"
#property link      "1"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
 
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
 
#property indicator_label2  "Label2"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  Lime
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
 
input int      Depth=12;
input int      Deviation=5;
input int      Backstep=3;
input double   Dif =1.0;
input double   Dif2=2.0;


 
double         Label1Buffer[];
double         Label2Buffer[];

int iz;
 
int OnInit()
  {
   
   iz=iCustom(_Symbol,_Period,"examples\\ZigZag",Depth,Deviation,Backstep);
   
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,Label2Buffer,INDICATOR_DATA);
   
 
   return(0);
  }

void SaleSignal ( int i, double price )
{
   Label1Buffer[i] = price ;
}
void BuySignal  ( int i, double price )
{
    Label2Buffer[i]=price;
}

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[])
  {

 
 
     double zb0[]; 
    
     if ( prev_calculated == 0 ){
         ArrayInitialize(Label1Buffer,0);
         ArrayInitialize(Label2Buffer,0);
     }
    
 
     int ASize=2000;
      
     int co = CopyBuffer ( iz, 0, 0, ASize, zb0); // zigzag buffer
     
     int k=0;
     double p[4];
     datetime t[4];
     
     for ( int i=ASize-1,j=rates_total; i>=0;i--,j--){
      if ( zb0[i] != 0 ){
         p[k] = zb0[i];
         t[k] = time[j];
         k++;
      }
      if ( k > 3 )
         break;    
     }
     
     ObjectCreate(0,"p0",OBJ_TEXT,0,t[0],p[0]);ObjectSetString(0,"p0",OBJPROP_TEXT," 0 ");
     ObjectCreate(0,"p1",OBJ_TEXT,0,t[1],p[1]);ObjectSetString(0,"p1",OBJPROP_TEXT," 1 ");
     ObjectCreate(0,"p2",OBJ_TEXT,0,t[2],p[2]);ObjectSetString(0,"p2",OBJPROP_TEXT," 2 ");
     ObjectCreate(0,"p3",OBJ_TEXT,0,t[3],p[3]);ObjectSetString(0,"p3",OBJPROP_TEXT," 3 ");
     
     ObjectCreate(0,"a",OBJ_TREND,0,t[1],p[1],t[2],p[2]); ObjectSetInteger(0,"a",OBJPROP_RAY_LEFT,false); ObjectSetInteger(0,"a",OBJPROP_RAY_RIGHT,false);
     ObjectCreate(0,"b",OBJ_TREND,0,t[2],p[2],t[3],p[3]); ObjectSetInteger(0,"b",OBJPROP_RAY_LEFT,false); ObjectSetInteger(0,"b",OBJPROP_RAY_RIGHT,false);
     ObjectCreate(0,"c",OBJ_TREND,0,t[1],p[1],t[3],p[3]); ObjectSetInteger(0,"c",OBJPROP_RAY_LEFT,false); ObjectSetInteger(0,"c",OBJPROP_RAY_RIGHT,false);
     ObjectSetInteger(0,"c",OBJPROP_COLOR,Yellow);
     
     double a = MathAbs ( p[1] - p[2] ); // размахи
     double b = MathAbs ( p[2] - p[3] ); 
     double c = p[1] - p[3] ;
     
     int    ta= (int)(t[1]-t[2]); //  углы 
     int    tb= (int)(t[2]-t[3]);
     int    tc= (int)(t[1]-t[3]);
    
     double power  = MathMax ( a,b); // основное движение
     double reduce = MathMin ( a,b); // востановление
     double trand  = c; //     +/-   // тренд
     
     double Ka;
     double Kb;
     double Kc;
     
     
     if ( ta > 0 ) // проверка на дурака, такого на самом деле быть не может
      Ka = a/ta;
     else
      printf("ta=0");
      
     if ( tb > 0 )
      Kb = b/tb;
     else
      printf("tb=0");
     if ( tc > 0 )
      Kc = c/tc;
     else
      printf("tc=0");
     
    // имеем четыре варианта 
    // см рисунок, когда он будет

     if ( c > 0 ){
        if ( a > b ){// ( I )
         ChartSetString(0,CHART_COMMENT,"(I)");
         ObjectCreate(0,"Open",OBJ_HLINE,0,0,p[1] - Dif  * b);ObjectSetInteger(0,"Open",OBJPROP_COLOR,Yellow);
         ObjectCreate(0,"Stop",OBJ_HLINE,0,0,p[1] - Dif2 * b);ObjectSetInteger(0,"Stop",OBJPROP_COLOR,Red);
         if ( p[1] - Dif * b > low[rates_total-1] && p[1] - Dif2 * b < low[rates_total-1] )
            BuySignal ( rates_total-1, low[rates_total-1] ) ;  
        }
        else if ( a < b ){//  ( II )
         ChartSetString(0,CHART_COMMENT,"(II)");
         ObjectCreate(0,"Open",OBJ_HLINE,0,0,p[1] + Dif  * b);ObjectSetInteger(0,"Open",OBJPROP_COLOR,Yellow);
         ObjectCreate(0,"Stop",OBJ_HLINE,0,0,p[1] + Dif2 * b);ObjectSetInteger(0,"Stop",OBJPROP_COLOR,Red);
         if ( p[1] + Dif * b < high[rates_total-1] && p[1] + Dif2* b > high[rates_total-1])
            SaleSignal ( rates_total-1, high[rates_total-1] ) ;  
        }
        else
            printf(" c > 0 && a == b ");
     }
     else if ( c < 0 ){
        if ( a > b ){// ( III )
         ChartSetString(0,CHART_COMMENT,"(III)");
         ObjectCreate(0,"Open",OBJ_HLINE,0,0,p[1] + Dif  * b);ObjectSetInteger(0,"Open",OBJPROP_COLOR,Yellow);
         ObjectCreate(0,"Stop",OBJ_HLINE,0,0,p[1] + Dif2 * b);ObjectSetInteger(0,"Stop",OBJPROP_COLOR,Red);
         if ( p[1] + Dif * b < high[rates_total-1] && p[1] + Dif2 * b > high[rates_total-1])
             SaleSignal ( rates_total-1, high[rates_total-1] ) ;  
        }
        else if ( a < b ){ // IV
         ChartSetString(0,CHART_COMMENT,"(IV)");
         ObjectCreate(0,"Open",OBJ_HLINE,0,0,p[1] - Dif  * b);ObjectSetInteger(0,"Open",OBJPROP_COLOR,Yellow);
         ObjectCreate(0,"Stop",OBJ_HLINE,0,0,p[1] - Dif2 * b);ObjectSetInteger(0,"Stop",OBJPROP_COLOR,Red);
         if ( p[1] - Dif * b > low[rates_total-1] && p[1] - Dif2 * b < low[rates_total-1])
            BuySignal ( rates_total-1, low[rates_total-1] ) ;  
        }
        else
         printf("a < 0 && a == b ");
     }
     else
      printf("c == 0");
      

   return(rates_total);
  }




 
Опримизируются параметры ZigZag и два уровня - уровень "открытия" который определяется как процент от передидущего ZigZag и  уровень "стопа" ( когда уже поздно :) ) также как прцент от размера ZigZag.

 
Academic:

1. Результат стал еще хуже. Пока еще ни один раз прогон не закончен. :(

Academic:

2. Да это все понятно про то как экономить вычесления. Но все же что быстрее? - иметь iCustom с копированием одного буфера, или делать такие расчеты в советнике копируя все через CopyRates? Что быстрее копировать 2000 баров или все, надеясь что компилятор поймет и комировать ничего не будет а просто даст буфера?

 

1. Значит так индикатор написан. 

2. Все понятно, только не делаем, а когда делаем - не работает. 

Если делать те же самые вычисления в советнике и индикаторе. Будет ли ускорение от копирования оного бара или 2000... сделайте вывод. Индикатор обеспечивает динамическими буферами автоматически масштабируемыми при появлении нового бара, в индикаторе выполняется контроль поступления новых данных. Именно индикатор предназначен для каких-то вычислений с использованием истории цены, и если это делать правильно, все работает очень быстро. 

 

Обработчик события "новый бар"
Обработчик события "новый бар"
  • 2010.10.04
  • Konstantin Gruzdev
  • www.mql5.com
Язык программирования MQL5 позволяет решать задачи на совершенно новом уровне. Даже те задачи, которые уже вроде имеют решения, благодаря объектно-ориентированному программированию могут подняться на качественно новый уровень. В данной статье специально взят простой пример проверки появления нового бара на графике, который был преобразован в достаточно мощный и универсальный инструмент. Какой? Читайте в статье.
 
Academic:
Опримизируются параметры ZigZag и два уровня - уровень "открытия" который определяется как процент от передидущего ZigZag и  уровень "стопа" ( когда уже поздно :) ) также как прцент от размера ZigZag.

Копируем 2000 баров, на все эти 2000 баров считаем зигзаг? И так на каждом тике?

 
Integer:

Копируем 2000 баров, на все эти 2000 баров считаем зигзаг? И так на каждом тике?

 

 

Нет ZigZag просто iCustom. Это просто индикатор. И из его буфера данные копируеются, ну чтобы с небольшим запасом 2000 баров. А ZigZag сам по себе висит такой индикатор. :)
 
Integer:

 

1. Значит так индикатор написан. 

2. Все понятно, только не делаем, а когда делаем - не работает. 

Если делать те же самые вычисления в советнике и индикаторе. Будет ли ускорение от копирования оного бара или 2000... сделайте вывод. Индикатор обеспечивает динамическими буферами автоматически масштабируемыми при появлении нового бара, в индикаторе выполняется контроль поступления новых данных. Именно индикатор предназначен для каких-то вычислений с использованием истории цены, и если это делать правильно, все работает очень быстро. 

 

 

 

Мне всегда нравились самоуверенные люди :) Как так написан? :)

Вы уверенны что Вы подходите мне на роль учителя? Это я про то, что "Все понятно, только не делаем, а когда делаем - не работает. "


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