Слоник, часть III

17 июля 2022, 15:49
Maxim Kuznetsov
0
22

обновление раздаваемой панельки и продолжение рассуждений про GUI и его устройство

панелька получила некоторые обновления, визуально - теперь умеет подписывать вертикальные линии. Чуть (почти незаметно) подправлены подписи. Отметки позиций теперь учитывают своп и комиссии, раньше были просто на средне-взвешенной цене. 


подобороты некоторые баги и конечно-же добавлены новые :-)

А теперь снова к GUI

В прошлый раз коснулись OnChartEvent (что в советниках ему лучше и не быть вовсе, чтобы не быть заспамленным) и отчасти синхронных функций (с которыми надо быть осторожным). Теперь посмотрим как советники взаимодействуют с ипостасью чарта  в лице индикаторов.

Простецкий индикатор, который при старте говорит в котором треде он запущен, а далее печатает события которые получает. В расчётной части - в единственном буфере суммирует "сколько баров было рассчитано"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_label1  "FAKE"
#property indicator_type1   DRAW_NONE
#property indicator_color1  clrNONE
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#include <WinAPI/processthreadsapi.mqh>

double         FAKE[];
long  counter;
int OnInit()
{
   counter=0;
   uint threadid=GetCurrentThreadId();
   PrintFormat("Indicator thread %d",threadid);
   SetIndexBuffer(0,FAKE,INDICATOR_DATA);
   return(INIT_SUCCEEDED);
}
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[])
{
   ArraySetAsSeries(FAKE,true);
   for(int bar=prev_calculated;bar<rates_total;bar++) {
      int i= rates_total - bar - 1;
      FAKE[i]=(double)(counter++);
   }
   return(rates_total);
}

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   PrintFormat("OnChartEvent id=%d (%s) lparam=%d dparam=%f sparam=%s",
      id,EnumToString((ENUM_CHART_EVENT)id),lparam,dparam,sparam);
}

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

#include <WinAPI/processthreadsapi.mqh>
int handle=INVALID_HANDLE;
double lastValue=0;
int OnInit()
{
   uint threadid=GetCurrentThreadId();
   PrintFormat("Expert thread %d",threadid);
   handle=iCustom(_Symbol,PERIOD_CURRENT,"/Indicators/PrintChartEvents");
   if (handle==INVALID_HANDLE) {
      Alert(StringFormat("Unable to create indicator,err=%d",GetLastError()));
      return INIT_FAILED;
   }
   lastValue=0;
   
   EventSetTimer(60);
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
   if (handle!=INVALID_HANDLE) IndicatorRelease(handle);
   EventKillTimer();
   
}
void OnTick()
{
}
void OnTimer()
{
   double data[2];
   CopyBuffer(handle,0,0,2,data);
   if (data[1]!=lastValue) {
      lastValue=data[1];
      PrintFormat("lastValue=%f",lastValue);
   }
}

Запускаем советник, смотрим в журнал:

про это в документации сказано, но не всеми воспринимается: ВСЕ ИНДИКАТОРЫ ЗАПУСКАЮТСЯ В ТРЕДЕ ЧАРТА. А советник в отдельном. ВСЕ индикаторы разделяют один ресурс - тред чарта. Их OnCalculate() будут вызываться последовательно. Буферы индикатора разделяются между индикатором и советником. 

Конечно разработчики терминала "костьми легли" на выстраивании приоритетов и разделении индикаторных буферов, но всё равно на CopyBuffer можно получить пенальти в виде непредвиденной задержки - если данные всё ещё не готовы в OnCalculate. Например вызван синхронный ObjectFind(), а в чарте много необработанных запросов. Или просто "долго рисуется". Это кстати веская причина по которой запрещён WebRequest в индикаторах.

Выход: минимизировать (а лучше вообще избегать) использование синхронных функций внутри OnCalculate индикаторов. Например не использовать их при открытии бара,ведь советники большую часть данных запрашивают именно в этот момент. 

С событиями и индикаторами вроде почти всё, надводную часть айсберга почти изучили ;-) Остаётся всего 9/10  

Прицеплена последняя версия панельки. Для демок без ограничений, для реала 2 месяца



Файлы:
ChartMan.ex5  219 kb