Обсуждение статьи "Статистические распределения в виде гистограмм без индикаторных буферов и массивов"

 

Опубликована статья Статистические распределения в виде гистограмм без индикаторных буферов и массивов:

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

В данной статье остановимся на вертикальных гистограммах вариационных рядов: ценовые значения исследуемых характеристик будут находиться на вертикальной оси в порядке возрастания, а частоты — на горизонтальной (Рис. 1). Поступающие в терминал ценовые данные распределяются и группируются на текущем баре и могут быть отображены относительно его оси слева, справа или одновременно с обеих сторон.

Рис. 1. Вертикальная гистограмма распределения цен Bid и Ask. 

Рис. 1. Вертикальная гистограмма распределения цен Bid и Ask.

Автор: Sergey Pavlov

 
Привязка не мешает?
 

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

(примером может служить индикатор  #Xaser-info

[Удален]  
Запомнился такой способ отображения в индикаторах по VSA. Наглядно и эффективно
 

Сергей, это очень интересно, и я хотел бы поговорить об этом.

Во-первых, я не знаю, как получить код из новости. В итоге я сохранил код и скопировал его из сохраненного файла. Я не знаю, что такое файл .mht.

В любом случае, я вставил функцию DrawHistogram(), но когда я попытался скомпилировать ее, появились неопределенные переменные, например, color_R_active. Не могли бы вы помочь мне определить их.

Спасибо.

Чак Стенгор

 
cstangor:

Сергей, это очень интересно, и я хотел бы поговорить об этом.

Во-первых, я не знаю, как получить код из новости. В итоге я сохранил код и скопировал его из сохраненного файла. Я не знаю, что такое файл .mht.

В любом случае, я вставил функцию DrawHistogram(), но когда я попытался скомпилировать ее, появились неопределенные переменные, например, color_R_active. Не могли бы вы помочь мне определить их.

Спасибо.

Чак Стенгор

Показать полный код.

 
Sergey Pavlov:

Показать полный код.

//+------------------------------------------------------------------+
//|draw_histogram.mqh |
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Определяет|
//+------------------------------------------------------------------+
// #define MacrosHello "Hello, world!"
// #define MacrosYear 2010
//+------------------------------------------------------------------+
//| Импорт DLL|
//+------------------------------------------------------------------+
// #import "user32.dll"
// int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
// int ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| Импорт EX5|
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
// string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

void DrawHistogram(bool draw,     // нарисуйте гистограмму влево или вправо
                   string h_name, // уникальный префикс для имени объекта
                   double price,  // цена (анализируемый параметр)
                   datetime time, // привязываем гистограмму к текущему бару
                   int span,      // анализируемый параметр разрядности
                   int swin=0)    // окно гистограммы
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// если draw=true, перерисуйте гистограмму вправо
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // название объекта: префикс+цена
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // создайте объект
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // установите цвет объекта
      ObjSet;                                                // макрос для сокращения кода
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// если полученная цена впервые попала в выборку
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // частота колебаний цены равна 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // определите координату времени
        }
      else
        {// если полученная цена попала в выборку не в первый раз
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // получить значение свойства
         string strint=StringSubstr(str,1);                  // выделите подстроку
         long n=StringToInteger(strint);                     // получить частоту для дальнейших расчетов
         n++;                                                // увеличьте значение на 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // запишите новое значение в свойство
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//определите временную координату
        }
     }
// если draw=false, перепишите гистограмму влево
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
 
//+------------------------------------------------------------------+
//|draw_histogram.mqh |
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//--- Макросы
#define   R        43    // значения префикса (+) для гистограмм справа
#define   L        45    // значения префикса (-) для гистограмм слева
#define   WIDTH    2     // толщина линий
#define   ObjSet1  ObjectSetInteger(0,name,OBJPROP_WIDTH,WIDTH)
#define   ObjSet2  ObjectSetDouble(0,name,OBJPROP_PRICE,0,y)
#define   ObjSet3  ObjectSetInteger(0,name,OBJPROP_TIME,0,time)
#define   ObjSet4  ObjectSetDouble(0,name,OBJPROP_PRICE,1,y)
#define   ObjSet5  ObjectSetInteger(0,name,OBJPROP_BACK,true)
#define   ObjSet   ObjSet1;ObjSet2;ObjSet3;ObjSet4;ObjSet5
//---
int      hsize=10;                     // масштаб гистограммы
color    color_R_active=clrRed;        // цвет активных линий справа
color    color_R_passive=clrLightCoral;// цвет пассивных линий справа
color    color_L_active=clrBlue;       // цвет активных линий слева
color    color_L_passive=clrSkyBlue;   // цвет пассивных линий слева

void DrawHistogram(bool draw,     // нарисуйте гистограмму влево или вправо
                   string h_name, // уникальный префикс для имени объекта
                   double price,  // цена (анализируемый параметр)
                   datetime time, // привязываем гистограмму к текущему бару
                   int span,      // анализируемый параметр разрядности
                   int swin=0)    // окно гистограммы
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// если draw=true, перерисуйте гистограмму вправо
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // название объекта: префикс+цена
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // создайте объект
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // установите цвет объекта
      ObjSet;                                                // макрос для сокращения кода
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// если полученная цена впервые попала в выборку
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // частота колебаний цены равна 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // определите координату времени
        }
      else
        {// если полученная цена попала в выборку не в первый раз
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // получить значение свойства
         string strint=StringSubstr(str,1);                  // выделите подстроку
         long n=StringToInteger(strint);                     // получить частоту для дальнейших расчетов
         n++;                                                // увеличьте значение на 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // запишите новое значение в свойство
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//определите временную координату
        }
     }
// если draw=false, перепишите гистограмму влево
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
 
Sergey Pavlov:
//+------------------------------------------------------------------+
//|draw_histogram.mqh |
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//--- Макросы
#define   R        43    // значения префикса (+) для гистограмм справа
#define   L        45    // значения префикса (-) для гистограмм слева
#define   WIDTH    2     // толщина линий
#define   ObjSet1  ObjectSetInteger(0,name,OBJPROP_WIDTH,WIDTH)
#define   ObjSet2  ObjectSetDouble(0,name,OBJPROP_PRICE,0,y)
#define   ObjSet3  ObjectSetInteger(0,name,OBJPROP_TIME,0,time)
#define   ObjSet4  ObjectSetDouble(0,name,OBJPROP_PRICE,1,y)
#define   ObjSet5  ObjectSetInteger(0,name,OBJPROP_BACK,true)
#define   ObjSet   ObjSet1;ObjSet2;ObjSet3;ObjSet4;ObjSet5
//---
int      hsize=10;                     // масштаб гистограммы
color    color_R_active=clrRed;        // цвет активных линий справа
color    color_R_passive=clrLightCoral;// цвет пассивных линий справа
color    color_L_active=clrBlue;       // цвет активных линий слева
color    color_L_passive=clrSkyBlue;   // цвет пассивных линий слева

void DrawHistogram(bool draw,     // нарисуйте гистограмму влево или вправо
                   string h_name, // уникальный префикс для имени объекта
                   double price,  // цена (анализируемый параметр)
                   datetime time, // привязываем гистограмму к текущему бару
                   int span,      // анализируемый параметр разрядности
                   int swin=0)    // окно гистограммы
  {
   double y=NormalizeDouble(price,span);
   string pfx=DoubleToString(y,span);
// если draw=true, перерисуйте гистограмму вправо
   if(draw)
     {
      string name="+ "+h_name+pfx;                   // название объекта: префикс+цена
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);    // создайте объект
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // установите цвет объекта
      ObjSet;                                                // макрос для сокращения кода
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {// если полученная цена впервые попала в выборку
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");          // частота колебаний цены равна 1
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // определите координату времени
        }
      else
        {// если полученная цена попала в выборку не в первый раз
         string str=ObjectGetString(0,name,OBJPROP_TEXT);    // получить значение свойства
         string strint=StringSubstr(str,1);                  // выделите подстроку
         long n=StringToInteger(strint);                     // получить частоту для дальнейших расчетов
         n++;                                                // увеличьте значение на 1
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // запишите новое значение в свойство
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//определите временную координату
        }
     }
// если draw=false, перепишите гистограмму влево
   if(!draw)
     {
      string name="- "+h_name+pfx;
      ObjectCreate(0,name,OBJ_TREND,swin,time,y);
      ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active);
      ObjSet;
      if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0)
        {
         ObjectSetString(0,name,OBJPROP_TEXT,"*1");
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize);
        }
      else
        {
         string str=ObjectGetString(0,name,OBJPROP_TEXT);
         string strint=StringSubstr(str,1);
         long n=StringToInteger(strint);
         n++;
         ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n);
         ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n);
        }
     }
  ChartRedraw();
}
Спасибо!
 

Сергей,

Я пытаюсь построить тиковый объем покупки и продажи вместо bid и ask, чтобы иметь объем по цене, как индикатор, возможно ли это? Есть ли у вас какой-нибудь код с тиковым объемом покупки/продажи, который вы можете опубликовать?

Большое спасибо!


Пример данных, которые я хочу построить, он строит горизонтальную гистограмму тикового объема покупки/продажи в отдельном окне, я хочу построить вертикальную гистограмму в основном окне графика:

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//
#property indicator_label1  "SELL Tick"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrTomato
#property indicator_style1  STYLE_SOLID
//
#property indicator_label2  "BUY Tick"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrSpringGreen
#property indicator_style2  STYLE_SOLID
#property indicator_width2  5

//--- индикаторные буферы
double         ExtBuyBuffer[];
double         ExtSellBuffer[];

int OnInit()
  {
//--- отображение индикаторных буферов
   SetIndexBuffer(0,ExtBuyBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtSellBuffer,INDICATOR_DATA);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0);
//---
   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[])
  {

static int ticks=0;
//---
   if(ticks==0)
     {
      ArrayInitialize(ExtSellBuffer,0);
      ArrayInitialize(ExtBuyBuffer,0);
     }
//---
   MqlTick last_tick;
   if(SymbolInfoTick(Symbol(),last_tick) && last_tick.flags == 56)
     {
         ExtBuyBuffer[ticks]+=NormalizeDouble(last_tick.volume,2); 
         int shift=rates_total-1-ticks;
         ticks++;
         ExtBuyBuffer[rates_total-1]=last_tick.volume;
         PlotIndexSetInteger(0,PLOT_SHIFT,shift);
     }
   if(SymbolInfoTick(Symbol(),last_tick) && last_tick.flags == 88)
     {
         ExtSellBuffer[ticks]+=NormalizeDouble(last_tick.volume,2); 
         int shift=rates_total-1-ticks;
         ticks++;
         ExtSellBuffer[rates_total-1]=last_tick.volume;
         PlotIndexSetInteger(1,PLOT_SHIFT,shift);
     }

//
//--- возвращаем значение prev_calculated для следующего вызова

   return(rates_total);
 }