Код платформы многовалютного многотаймфреймового советника - страница 3

 
Vinin писал(а) >>
Что-то примерно так.

Спасибо, обязательно добавлю :)

 

попросили вот, чтоб многовалютный советник тики вылавливал. Попробую доработать свой, чтоб можно было к нему подключать и тиковые тактики.

У меня в связи с этим вот вопрос возник. Несет ли полезную информацию количество тиков, например на М1, на нескольких валютах. Можно ведь и счетчики тиков поставвить на каждой валюте и на каждом таймфрейе.

 

Мое мнение. он только и должен работать на тиках. Т.к. все остальное (бары) это производная от тикового потока. Причем бары это метод сжатия информации с потерями и нелинейными искажениями. Беря клоуз, мы из потока выбираем какойто тик, считая что он почему то важнее. С моей точки зрения это ошибка. Но к сожалению из-за формата хранения истории в МТ, вам скорее всего не удастся все корректно обработать (собрать)

 
Prival писал(а) >>

Мое мнение. он только и должен работать на тиках. Т.к. все остальное (бары) это производная от тикового потока. Причем бары это метод сжатия информации с потерями и нелинейными искажениями. Беря клоуз, мы из потока выбираем какойто тик, считая что он почему то важнее. С моей точки зрения это ошибка. Но к сожалению из-за формата хранения истории в МТ, вам скорее всего не удастся все корректно обработать (собрать)

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

 

Экспериментальный вариант:

//+------------------------------------------------------------------+
//|                                                          van.mq4 |
//|                                                 Copyright © 2009 |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
//
int TimeCycle  = 60;      //=== допустимое время обработки цикла в сек.
int TimeCycle2 = 5;      //=== время обработки цикла в сек, превышение которого должно сообщаться.
int countSymbol;       //=== количество торгуемых инструментов (массив Symbol_array[])
int countPeriod;       //=== количество анализируемых периодов (массив Period_array[])
//
string Symbol_array[] = {"EURUSD","GBPUSD","AUDUSD","USDJPY","USDCHF","USDCAD","EURJPY","EURGBP","EURCHF"};
double AskSymbol[9]; //=== текущие цены продажи инструментов(9шт) для регистрации тиков
int    Period_array[] = {1,5,15,60,240,1440};
int    prevtime         [9][6];  //=== 9-кол.вал.пар  6 таймфреймов
//#include "movelib2.mqh"        //=== функции движка
//#include "controllib.mqh"      //=== функции управления
//#include "analysislib.mqh"     //=== функции анализа
//
int init()   { return(0); }
int deinit() { return(0); }
//
//===== зацикленная функция start() ======================================================================================
int start()             {  
   startustanovki();         // начальные установки
   while(!IsStopped())  {    // До тех пор, пока пользователь не прекратит исполнение программы 
   
      int TC1   = TimeCurrent();   //=== время начала обработки цикла
      RefreshRates();              //=== Обновление данных   
      kontrol();                   //=== контрольные функции               
      //ProcSP();                  //=== процедуры, которые необходимо выполнять оперативно (в цикле обработки), не дожидаясь появления нового бара              
      SymbolPeriod();              //=== регистрация появления нового тика/бара по любому инструменту и на любом таймфрейме
      
      //====================== ежечасный профилактический перезапуск цикла ========  
      string text   = TimeToStr(TimeCurrent(),TIME_MINUTES);            
      int    index = StringFind(text, ":49", 0);   // разрешение на очередной ежечастный однократный перезапуск эксперта (цикла)
      if     (index==2) {bool perezapusk=true;}       
      index = StringFind(text, ":50", 0);          // профилактический перезапуск цикла делаю за 10 минут до начала нового часа 
      if     ((index==2)&&(perezapusk==true)){
         Print("======================================================");
         Print(" Профилактический, перезапуск цикла обработки ",TimeToStr(TimeCurrent(),TIME_MINUTES));
         Print("======================================================");   perezapusk=false;  break;
      }   
      //====================== ежечасный профилактический перезапуск цикла ========  
      
      Sleep(100);                  // притормози! (замедлитель цикла обработки)  
      
      int TC2 = TimeCurrent();     //=== время окончания обработки цикла               
      int analiz = TC2-TC1;  
      if (analiz>TimeCycle)   {
         Print("=================================================================");
         Print("Превышение допустимого (",TimeCycle,"сек) времени обработки !!!  ",analiz,"сек       Перезапуск цикла обработки.");
         Print("=================================================================");
         break;
      }   
   }      
   return(0);                      // Управление возвращается терминалу
}
//===== зацикленная функция start() ======================================================================================
//
//===== начальные установки ==============================================================================================   
void startustanovki()   {
   countSymbol  = ArraySize(Symbol_array);
   countPeriod  = ArraySize(Period_array);
   //countMA      = ArraySize(MA_array);
     
   //=== начальное обнуление массивов ===================================     
   for(int i=0; i<countSymbol; i++)      {      //=== перебор валютных пар
      AskSymbol[i] = 0;
      for(int j=0; j<countPeriod; j++)   {      //=== перебор периодов
         prevtime[i][j]       = 0;
         //f_UPPER_array[i][j]  = 0;
         //f_LOWER_array[i][j]  = 0;
         //f2_UPPER_array[i][j] = 0;
         //f2_LOWER_array[i][j] = 0;
         //accelerationBUY[i][j]  =false;     //=== зона BUY
         //accelerationSELL[i][j] =false;     //=== зона BUY
         //for(int k=0; k<countMA; k++)    {    //=== перебор периодов МА
         //   acceleration[i][j][k]  = 0; 
         //}     
      }          
   }
   //=== конец начального обнуления массивов ===================================
}
//===== начальные установки ==============================================================================================   
//
//===== периодический контроль ===========================================================================================   
void kontrol()     {
   if(!IsConnected())       { Print("----- Связь отсутствует!------------------------------------------------------------------"); return(0); }
   if(!IsExpertEnabled())   { Print("----- В клиентском терминале запуск экспертов запрещен! ----------------------------------"); return(0); }
   if(!IsTradeAllowed())    { Print("----- Поток для выполнения торговых операций занят! Эксперту не разрешено торговать! -----"); return(0); }
   if(IsTradeContextBusy()) { Print("----- Торговый поток занят. Подождите ----------------------------------------------------"); return(0); }
}
//===== периодический контроль ===========================================================================================   
//
 

В одном окне не поместилось. Продолжение:

//===== регистрация появления нового тика/бара по любому инструменту и на любом таймфрейме ===============================
void SymbolPeriod()     {
   int TT=0;
   int TC1   = TimeCurrent();              //=== время начала обработки 
   bool NewBarS=false;
   bool NewТicS=false;
   if (CheckHistory())         {  //=== контроль актуальности исторических данных (Vinin)
      for(int i=0; i<countSymbol; i++)     {  //=== перебор валютных пар
         if (isNewТic(i))     {          //=== появился новый тик по текущей валютной
            TT      = 1;               //=== появился новый тик, значит нужно замерить время последующей обработки
            NewТicS = true;
            //=== появился новый тик на i инструменте, можно принимать решения
            //=== основанные на анализе появления тиков i-го инструмента 
            ТicSymbol(i); //=== процедуры тактик ТicSymbol_01, ТicSymbol_02, ТicSymbol_03, ...
         }
         bool NewBar=false;
         for(int j=0; j<countPeriod; j++)  {  //=== перебор периодов
            if (isNewBar(i,j))     {          //=== появился новый бар по текущей валютной паре по текущему таймфрейму
            
               //Print("----- новый бар      i=",i," ",Symbol_array[i],"   j=",j," ",Period_array[j],"мин.            ");
               TT      = 1;               //=== появился новый бар, значит нужно замерить время последующей обработки
               NewBar  = true; NewBarS = true;
               //=== появился новый бар на i инструменте на j таймфрейме, можно принимать решения
               //=== основанные на анализе поведения i-го инструмента на j-ом таймфрейме 
               ProcSymbolPeriod(i,j);     //=== процедуры тактик 101, 102, 103, ...
               //Print("----- конец обработки нового бара         ");
            }                   
         }                   
      } 
      if (NewBar==true)   { 
         //=== был новый бар(бары) на i инструменте, можно принимать решения 
         //=== основанные на анализе поведения этого инструмента на всех таймфреймах 
         ProcSymbolPeriodS(i);            //=== процедуры тактик 201, 202, 203, ... 
      }   
   } 
   if (NewТicS==true)     { 
      //=== был новый тик(тики), можно принимать решения
      //=== основанные на анализе появления тиков на нескольких инструментах 
      ТicSymbolS(); //=== процедуры тактик ТicSymbolS_01, ТicSymbolS_02, ТicSymbolS_03, ...
   } 
   if (NewBarS==true)     { 
      //=== был новый бар(бары), можно принимать решения
      //=== основанные на анализе поведения всех инструментов на всех таймфреймах
      ProcSymbolSPeriodS();               //=== процедуры тактик 301, 302, 303, ...
   } 
        
   //====================== замер времени обработки процедур после появления нового бара(тика) или серии баров(тиков) ==============       
   int TC2 = TimeCurrent();                     
   int analiz = TC2-TC1;  
   if ((TT==1)&&(analiz>TimeCycle2)) {  //=== если нового бара или серии баров не было, то и процедур нет и время не замеряется 
      Print("            Время обработки  ",analiz,"сек.");
   }
   if (TT==1)                { 
   //  Print("--------------------- конец цикла обработки бара(баров) ----------------");
   }
   //====================== замер времени обработки процедур после появления нового бара или серии баров ==============       
}      
//===== регистрация появления нового тика/бара по любому инструменту и на любом таймфрейме ===============================
//
//===== контроль актуальности исторических данных (идея Vinin)  ошибка 4066 ==============================================  
bool CheckHistory(){  
   for(int i=0; i<countSymbol; i++)     {  //=== перебор валютных пар
      for(int j=0; j<countPeriod; j++)  {  //=== перебор периодов
         double tmp = iClose(Symbol_array[i],Period_array[j],0);
         int    err = GetLastError();  
         bool   rez = true;
         if (err==4066) {
            rez = false;
            Print("Запрошенные исторические данные в состоянии обновления"); 
            Sleep(1000);                 // подождем завершение обновления  
         }
      }
   }                  
  return(rez);
}
//===== контроль актуальности исторических данных (Vinin)  ошибка 4066 ===================================================  
//
//===== возвращает true если появлися новый бар, иначе false =============================================================  
bool  isNewBar(int i,int j)     {//=== i-индекс вал.пары, j-индекс таймфрейма
   bool res=false;    
   if ( prevtime[i][j] != iTime(Symbol_array[i],Period_array[j],0) )     {
      prevtime[i][j] = iTime(Symbol_array[i],Period_array[j],0);
      res=true;
   } 
   return(res);
}
//===== возвращает true если появлися новый бар, иначе false =============================================================  
//
//===== возвращает true если появлися новый тик, иначе false =============================================================  
bool  isNewТic(int i)  {           //=== i-индекс инструмента
   bool res=false;  
   RefreshRates();   
   int digits = MarketInfo(Symbol_array[i],MODE_DIGITS);
   double ask = NormalizeDouble(MarketInfo(Symbol_array[i],MODE_ASK),digits);
   if ( AskSymbol[i] != ask )   { AskSymbol[i] = ask;  res=true; } 
   return(res);
}
//===== возвращает true если появлися новый бар, иначе false =============================================================  
//
//===== процедуры тактик 101, 102, 103, ... ==============================================================================  
void ProcSymbolPeriod(int i,int j)     {      
}
//===== процедуры тактик 101, 102, 103, ... ==============================================================================  
//
//===== процедуры тактик 201, 202, 203, ... ==============================================================================  
void ProcSymbolPeriodS(int i)     {
}
//===== процедуры тактик 201, 202, 203, ... ==============================================================================  
//
//===== процедуры тактик 301, 302, 303, ... ==============================================================================  
void ProcSymbolSPeriodS()      {              
}
//===== процедуры тактик 301, 302, 303, ... ==============================================================================  
//
//===== процедуры тактик ТicSymbol_01, ТicSymbol_02, ТicSymbol_03, ... ===================================================  
void ТicSymbol(int i)      {              
}
//===== процедуры тактик ТicSymbol_01, ТicSymbol_02, ТicSymbol_03, ... ===================================================  
//
//===== процедуры тактик ТicSymbolS_01, ТicSymbolS_02, ТicSymbolS_03, ... ================================================  
void ТicSymbolS()      {              
}
//===== процедуры тактик ТicSymbolS_01, ТicSymbolS_02, ТicSymbolS_03, ... ================================================  
 
alexfx >>:

попросили вот, чтоб многовалютный советник тики вылавливал. Попробую доработать свой, чтоб можно было к нему подключать и тиковые тактики.

У меня в связи с этим вот вопрос возник. Несет ли полезную информацию количество тиков, например на М1, на нескольких валютах. Можно ведь и счетчики тиков поставвить на каждой валюте и на каждом таймфрейе.

тут отписал https://forum.mql4.com/ru/20351/page2

 
alexfx писал(а) >>

Экспериментальный вариант:

А как наиболее изящно отлавливать момент наличия нового бара на всех валютных парах на одном из таймфреймов?

 
Vinin писал(а) >>

RefreshRates() нужен при любом обращении к другим инструментам. А в твоем варианте эксперт зацикленный. И данные так просто обновляться не будут

Ошибка 4066

ERR_HISTORY_WILL_UPDATED 4066 Запрошенные исторические данные в состоянии обновления

означает что идет загрузка истории. Пока она не закончилась результаты нельзя принимать во внимание. Я обычно добавляю функцию контроля истории, которая просто запрашивает Клоуз всех инструментов. Если идет постоянное обращение, то ошибка 4066 не возникает. Только при первом запуске и после разрыва связи.

Vinin, дайте авторитетный совет. Мультивалютник кормится новыми барами. На каждой такой итерации происходят множественные обращения к другим "символо-периодам" (хм, удачно выразился). При такой схеме является ли достаточным использование RefreshRates() и контроля закачки истории при помощи приведенной Вами функции лишь единожды за итерацию (в функции Start с контролем открытия бара)? Торговые функции во внимание не принимаем, вопрос относится лишь к ковырянию котировок

 
Globe писал(а) >>

Vinin, дайте авторитетный совет. Мультивалютник кормится новыми барами. На каждой такой итерации происходят множественные обращения к другим "символо-периодам" (хм, удачно выразился). При такой схеме является ли достаточным использование RefreshRates() и контроля закачки истории при помощи приведенной Вами функции лишь единожды за итерацию (в функции Start с контролем открытия бара)? Торговые функции во внимание не принимаем, вопрос относится лишь к ковырянию котировок

Незнаю на счет авторитетности. для контроля новых тиков можно использовать MarketInfo(Symbol().MODE_TIME);

MODE_TIME 5 Время поступления последней котировки

Хотя такой контроль никогда не делал.

Как я понимаю - эксперт зацикленый, то RefreshRates() можно делать самой первой в теле цикла.

Все же зависит от потребностей. Для анализа достаточно. Но о тиковой истории лучше не думать.

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

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