К разработчикам. Реал-тайм индикатор

 

Добрый день!

Сейчас в индикаторе значения буфера отображаются только из функции OnCalculate()

и размер буфера индикатора нельзя изменить (он всегда равен rates_total) 

Ниже, приведён код индикатора, отображающий Ask и Bid символа:

//+------------------------------------------------------------------+
//|                                                 Test_ask_bid.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015"
#property link      "http://www.mql5.com"
#property version   "1.00"
//
#property indicator_separate_window

#property indicator_buffers 2
#property indicator_plots   2

//--- plot Label1
#property indicator_label1  "Ask"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//---
//--- plot Label1
#property indicator_label2  "Bid"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//
//--- indicator buffers
double AskBuffer[];
double BidBuffer[];
//--- temp buffers
double AskTemp[];
double BidTemp[];
//
int event_cnt;
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
  event_cnt = 0;
//--- Add book
  if ( !MarketBookAdd( _Symbol ) )
  {
    MessageBox( "Стакан символа " + _Symbol + " не добавден!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//---  
  IndicatorSetInteger( INDICATOR_DIGITS, _Digits );
  IndicatorSetString( INDICATOR_SHORTNAME, "Ask_Bid" );
//---  
  SetIndexBuffer( 0, AskBuffer, INDICATOR_DATA );
  PlotIndexSetDouble( 0, PLOT_EMPTY_VALUE, EMPTY_VALUE );
  ArraySetAsSeries( AskBuffer, true );
//---
  SetIndexBuffer( 1, BidBuffer, INDICATOR_DATA );
  PlotIndexSetDouble( 1, PLOT_EMPTY_VALUE, EMPTY_VALUE );
  ArraySetAsSeries( BidBuffer, true );
//---  
  ArraySetAsSeries( AskTemp, true );
  ArraySetAsSeries( BidTemp, true );
//---
  return( INIT_SUCCEEDED );
}
//+------------------------------------------------------------------+
// Custom indicator DeInit function                                  |
//+------------------------------------------------------------------+
void OnDeinit( const int reason )
{
//  EventKillTimer();
  MarketBookRelease( _Symbol );
//---  
  if ( reason == REASON_INITFAILED )
  {
    Print( "Индикатор удалён! Причина - ошибка инициализации." );
    string short_name = ChartIndicatorName( 0, 1, 0 );
    ChartIndicatorDelete( 0, 1, short_name ); 
  }
}
//+------------------------------------------------------------------+
//| Custom indicator Get Stakan values function                      |
//+------------------------------------------------------------------+ 
void GetStakanValues( const string aSymbol, double &s_price, double &b_price )
{
  MqlBookInfo book_price[];
  b_price = 0;
  s_price = DBL_MAX;
  
//--- Get stakan
  if ( MarketBookGet( aSymbol, book_price ) )
  {
    int size = ArraySize( book_price );
//---    
    if ( size > 0 )
    { 
      for( int i = 0; i < size; i++ )
      {
        if ( book_price[i].type == BOOK_TYPE_SELL )
        {
          if ( book_price[i].price < s_price )
          {
            s_price = book_price[i].price;
          }
        }
        else
        if ( book_price[i].type == BOOK_TYPE_BUY )
        {
          b_price = book_price[i].price;
          break;
        }
      }
    }
  }
//---
  if ( s_price == DBL_MAX ) s_price = 0;
}
//+------------------------------------------------------------------+
// Custom indicator On book event function                           |
//+------------------------------------------------------------------+
void OnBookEvent( const string& a_symbol )
{
  double sell_price, buy_price;
//---  
  if ( a_symbol == _Symbol )
  {
    GetStakanValues( _Symbol, sell_price, buy_price );
    ArrayResize( AskTemp, event_cnt + 1 );
    ArrayResize( BidTemp, event_cnt + 1 );
    AskTemp[0] = sell_price;
    BidTemp[0] = buy_price; 
//---     
    event_cnt++;
  }
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate( const int rates_total,
                 const int prev_calculated,
                 const int begin,
                 const double &price[] )

{
  if ( prev_calculated == 0 )
  {
    for( int i = rates_total - 1; i >= 0; i-- )
    {
      AskBuffer[i] = EMPTY_VALUE;
      BidBuffer[i] = EMPTY_VALUE;
    }
  }
  else
  {
    if ( event_cnt >= rates_total - 1 )
    {
      event_cnt = 0;
      return( rates_total );
    }
    for( int i = event_cnt - 1; i >= 0; i-- )
    {
      AskBuffer[i] = AskTemp[i];
      BidBuffer[i] = BidTemp[i];
    }
  }
//---  
  return( rates_total );
}

 Событие Calculate() приходит не при каждом изменении стакана цен,

поэтому значения в индикаторе отображаются "пачками" и с достаточно большими

задержками. При этом, на каждой итерации необходимо переписывать буферы индикатора.

И есть большая вероятность утери изменения Ask и Bid (пока работает OnCalculate() ). 

Если бы Вы дали нам возможность произвольно изменять размеры буферов из любой функции

в индикаторе и отображать их значения, то можно было бы создавать точные реал-тайм индикаторы.

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

 

Михаил:

...то можно было бы создавать реал-тйам индикаторы...

Михаил, а позвольте уточнить, что такое "реал-тайм индикаторы" в Вашем понимании?
 
Dennis Kirichenko:
Михаил, а позвольте уточнить, что такое "реал-тайм индикаторы" в Вашем понимании?
Без задержек вывода информации.
 
Михаил:
Без задержек вывода информации.
Т.е. сейчас есть задержки, при текущей архитектуре?
 
Dennis Kirichenko:
Т.е. сейчас есть задержки, при текущей архитектуре?

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

Плюс мы ограничены размером буфера (rates-total) 

 
Михаил:

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

Плюс мы ограничены размером буфера (rates-total) 

Тут возникает 2 вопроса:

1) как Вы думаете, почему разработчик не даёт контролировать буфер индикатора?

2) почти всегда буфер достаточно велик для решения разнообразных задач. Вам не кажется, что мы нисколько не ограничены размером буфера? :-)

 
Dennis Kirichenko:

Тут возникает 2 вопроса:

1) как Вы думаете, почему разработчик не даёт контролировать буфер индикатора?

2) почти всегда буфер достаточно велик для решения разнообразных задач. Вам не кажется, что мы нисколько не ограничены размером буфера? :-)

1. Не знаю (думаю, что из-за привязки ко времени).

2. На минутках размер буфера ~25000, на часовках ~800

И в том и другом случае ОЧЕНЬ мало для вывода всех Ask и Bid за торговую сессию

 
Михаил:

1. Не знаю (lдумаю, что из-за привязки ко времени).

2. На минутках размер буфера ~25000, на часовках ~800

И в том и другом случае ОЧЕНЬ мало для вывода всех Ask и Bid за торговую сессию

1. Я тоже не знаю, но догадываюсь... наверное потому, что для программы выделяется ресурс. И этот ресурс не может ходить туда-сюда. Иначе сама программа может быть повреждена. Короче, это "защита от дурака". Если я не прав, то меня поправят специалисты...

2. А скажите, какой смысл всю торговую сессию пихать в буфер? Можно порционно данных сохранять в файл. И Вам польза - инфу потом можно обрабатывать, и программе - нет перерасхода топлива...

Поищите статью про тиковый индикатор на сайте. Там есть описание и код...

 
Dennis Kirichenko:

1. Я тоже не знаю, но догадываюсь... наверное потому, что для программы выделяется ресурс. И этот ресурс не может ходить туда-сюда. Иначе сама программа может быть повреждена. Короче, это "защита от дурака". Если я не прав, то меня поправят специалисты...

2. А скажите, какой смысл всю торговую сессию пихать в буфер? Можно порционно данных сохранять в файл. Поищите статью про тиковый индикатор на сайте. Там есть описание и код...

1. Пусть выделяется ресурс (размер буфера всё-равно ограничен INT_MAX, "далеко не уедешь")

2. А скажите, для чего тогда индикаторы? Ведь всё можно сохранять в файл.. :)

 
Михаил:

1. Пусть выделяется ресурс (размер буфера всё-равно ограничен INT_MAX, "далеко не уедешь")

2. А скажите, для чего тогда индикаторы? Ведь всё можно сохранять в файл...

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

2. Имхо, индикатор нужен для визуализации и локального среза рыночной ситуации...

 
Dennis Kirichenko:

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

2. Имхо, индикатор нужен для визуализации и локального среза рыночной ситуации...

1. Это не ограничение, а кол-во баров, которое ВСЕГДА меньше кол-ва Ask и Bid (не на каждом же Ask и Bid совершается сделка)

2. Вот и я про то же - хочу видеть...