Мультисоветник. Лучший способ получения данных

 
  • 27% (16)
  • 32% (19)
  • 25% (15)
  • 17% (10)
Всего проголосовало: 60
 
  • На каждом символе индикатор-агент - генерация пользовательского события
    На каждый символ вешается индикатор-агент. Задача агента: при поступлении нового тика генерировать пользовательское событие с именем символа и ценами. В этом случае в главной программе будут собираться и анализироваться эти пользовательские события.
  • Использование последних доступных данных
    Просто обход всех символов - если по каждому символу УДАЛОСЬ получить данные, то считаем, что эти данные самые свежие
  • Таймер
    Таймер в главной программе, который опрашивает все символы. Если по каждому символу УДАЛОСЬ получить данные, то считаем, что эти данные самые свежие
 

Хороший вопрос. Выбрал "Свой вариант", т.к. перечисленные варианты скорее всего определяются целями самой стратегии. Где-то хорош таймер, где-то агенты...

Вариант "Использование последних доступных данных", хмм... Можно поподробнее?

 
Dennis Kirichenko:

Хороший вопрос. Выбрал "Свой вариант", т.к. перечисленные варианты скорее всего определяются целями самой стратегии. Где-то хорош таймер, где-то агенты...

Вариант "Использование последних доступных данных", хмм... Можно поподробнее?

Я так понял - то же самое, что и в таймере, но не в таймере...

Вы правы - всё зависит от поставленной задачи.

 
Dennis Kirichenko:

Хороший вопрос. Выбрал "Свой вариант", т.к. перечисленные варианты скорее всего определяются целями самой стратегии. Где-то хорош таймер, где-то агенты...

Вариант "Использование последних доступных данных", хмм... Можно поподробнее?

Тоже, что и в таймере. Различие с таймеров в том, что здесь обработчик в OnTick() главной программы, а не OnTImer().
 
Ещё бы добавил вариант "Новый бар".
 
Vladimir Karputov:
Тоже, что и в таймере. Различие с таймеров в том, что здесь обработчик в OnTick() главной программы, а не OnTImer().
Это совсем не вариант, OnTick может не приходить по символу, где сидит советник и будут пропущены данные по другим символам. Я таймер использую, пока хватает 1 сек. Для биржи надо явно быстрее.
 
Dennis Kirichenko:
Ещё бы добавил вариант "Новый бар".
Это для тормозов из прошлого века ))
 
Вопрос. "Лучший способ" - тот, который дает минимальную задержку во времени между моментом появления новых котировок в памяти терминала и моментом, когда программа(ы) MQL узнают об этом? Или другая цель?
 
Vladimir:
Вопрос. "Лучший способ" - тот, который дает минимальную задержку во времени между моментом появления новых котировок в памяти терминала и моментом, когда программа(ы) MQL узнают об этом? Или другая цель?
Это не способ, это расширенное описание цели ) О чем вы и написали в последнем предложении.
 

О методах получения данных - вот простой пример, когда советник висит на одной символе и данные с других символов получает внутри своего OnTick()

//+------------------------------------------------------------------+
//|                                                MultiCurrency.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
#include <Trade\SymbolInfo.mqh>  
CSymbolInfo    m_arr_symbol[];               // symbol info object
//--- input parameters
input int      InpNumberOfSymbols=3;         // symbols from the MarketWatch
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ResetLastError();
   int resize=ArrayResize(m_arr_symbol,InpNumberOfSymbols);
   if(resize==-1)
     {
      Print("ArrayResize, error# ",GetLastError());
      return(INIT_FAILED);
     }
   else if(resize!=InpNumberOfSymbols)
     {
      PrintFormat("ArrayResize, новый размер: %d не соответствует заказанному: %d",resize,InpNumberOfSymbols);
      return(INIT_FAILED);
     }
//---
   int symbbols_total=SymbolsTotal(true);
   if(symbbols_total<InpNumberOfSymbols)
     {
      PrintFormat("В окне MarketWatch: %d символов и это меньше заказанного: %d",symbbols_total,InpNumberOfSymbols);
      return(INIT_FAILED);
     }
   for(int i=0;i<symbbols_total;i++)
     {
      m_arr_symbol[i].Name(SymbolName(i,true));
      RefreshRates(i);
      m_arr_symbol[i].Refresh();
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- почему не используем метод bool CSymbolInfo::Refresh(void):
////+------------------------------------------------------------------+
////| Refresh cached data                                              |
////+------------------------------------------------------------------+
//   bool CSymbolInfo::Refresh(void)
//     {
//      long tmp=0;
//      //---
//      if(!SymbolInfoDouble(m_name,SYMBOL_POINT,m_point))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE,m_tick_value))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT,m_tick_value_profit))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_LOSS,m_tick_value_loss))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_SIZE,m_tick_size))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE,m_contract_size))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MIN,m_lots_min))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MAX,m_lots_max))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP,m_lots_step))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_LIMIT,m_lots_limit))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_LONG,m_swap_long))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_SHORT,m_swap_short))
//         return(false);
//      if(!SymbolInfoInteger(m_name,SYMBOL_DIGITS,tmp))
//         return(false);
//      m_digits=(int)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_ORDER_MODE,tmp))
//         return(false);
//      m_order_mode=(int)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_EXEMODE,tmp))
//         return(false);
//      m_trade_execution=(ENUM_SYMBOL_TRADE_EXECUTION)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE,tmp))
//         return(false);
//      m_trade_calcmode=(ENUM_SYMBOL_CALC_MODE)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_MODE,tmp))
//         return(false);
//      m_trade_mode=(ENUM_SYMBOL_TRADE_MODE)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_MODE,tmp))
//         return(false);
//      m_swap_mode=(ENUM_SYMBOL_SWAP_MODE)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_ROLLOVER3DAYS,tmp))
//         return(false);
//      m_swap3=(ENUM_DAY_OF_WEEK)tmp;
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL,m_margin_initial))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_MAINTENANCE,m_margin_maintenance))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_LONG,m_margin_long))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_SHORT,m_margin_short))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_LIMIT,m_margin_limit))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_STOP,m_margin_stop))
//         return(false);
//      if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_STOPLIMIT,m_margin_stoplimit))
//         return(false);
//      if(!SymbolInfoInteger(m_name,SYMBOL_EXPIRATION_MODE,tmp))
//         return(false);
//      m_trade_time_flags=(int)tmp;
//      if(!SymbolInfoInteger(m_name,SYMBOL_FILLING_MODE,tmp))
//         return(false);
//      m_trade_fill_flags=(int)tmp;
//      //--- succeed
//      return(true);
//     }
//--- так как метод bool CSymbolInfo::Refresh(void) не обнолвляет текущие цены и время последней котировки

   string text="Символ        Bid        Ask        Время\n";
   for(int i=0;i<InpNumberOfSymbols;i++)
     {
      RefreshRates(i);
      text+=m_arr_symbol[i].Name()+"  "+
            DoubleToString(m_arr_symbol[i].Bid(),m_arr_symbol[i].Digits())+"  "+
            DoubleToString(m_arr_symbol[i].Ask(),m_arr_symbol[i].Digits())+"  "+
            TimeToString(m_arr_symbol[i].Time(),TIME_MINUTES|TIME_SECONDS)+"\n";

     }
   Comment(text);

  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates(const int index)
  {
//--- refresh rates
   if(!m_arr_symbol[index].RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_arr_symbol[index].Ask()==0 || m_arr_symbol[index].Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+

В настройках задаётся количество символов из окна MarketWatch - перед этим нужно самостоятельно добавить эти символы в окно "MarketWatch" - так как это простой пример.

И уже видно, что если на основном символе (EURUSD) тиков нет, то естественно данные по другим символам будут пропущены:

EURUSD не обновляет данные по другим символам, так как тики по EURUSD поступают реже 

 EURUSD не обновляет данные по другим символам, так как тики по EURUSD поступают реже

Файлы: