<
  • Главная
Статьи

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

  1. Вступ Гістограма - інструмент, що дозволяє візуально оцінити розподіл статистичних даних, згрупованих...
  2. Які властивості графічних об'єктів можна задіяти в графічній пам'яті
  3. Приклади побудови гістограм в головному вікні
  4. Гістограми в додаткових вікнах
  5. Приклади побудови гістограм в додаткових вікнах
  6. Чисельні характеристики статистичних розподілів
  7. клас CHistogram
  8. Приклад побудови гістограм з використанням класу CHistogram

Вступ

Гістограма - інструмент, що дозволяє візуально оцінити розподіл статистичних даних, згрупованих за частотою їх потрапляння в певний (заздалегідь заданий) інтервал.

Побудова гістограм і використання їх в аналізі статистичних даних - досить вивчена тема, якій присвячено безліч статей [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] І по якій створено чимало прикладів в CodeBase [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]. Однак використовувані алгоритми базуються на застосуванні індикаторних буферів або масивів. У даній статті розглянута можливість побудови статистичних розподілів різних характеристик ринку без складних розрахунків, угруповань, вибірок тощо Для цього скористаємося "графічної" пам'яттю - тим розділом, де зберігаються властивості графічних об'єктів. Справа в тому, що при побудові користувальницьких гістограм так чи інакше використовуються графічні об'єкти , Так чому б не задіяти їх "приховані" можливості на повну потужність і не скористатися наявними багатим функціоналом?

Мета даної статті - запропонувати прості рішення стандартних статистичних завдань. Основний упор буде зроблений на візуалізацію статистичних розподілів і їх основних характеристик. Відволікатися на інтерпретацію гістограм і їх доцільність не будемо.

Принцип побудови гістограм

Гістограма являє собою Столбикова діаграм частот. За однією з осей відкладають значення змінної, а по інший - частоту народження (виникнення, поява і т.п.) цих значень. Висота кожного стовпчика показує частоту (кількість) значень, що належать відповідному інтервалу, рівного ширині стовпчика. Найчастіше такі діаграми зображуються горизонтально, тобто, значення змінної розташовані на горизонтальній осі, а частоти - на вертикальній. Використання гістограм для подання досліджуваної інформації дозволяє надати статистичними даними наочність і виразність, полегшити сприйняття, а в багатьох випадках - і аналіз.

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

Вступники в термінал цінові дані розподіляються і групуються на поточному барі і можуть бути відображені щодо його осі зліва, справа або одночасно з обох сторін

Мал. 1. Вертикальна гістограма розподілу цін Bid і Ask.

Розглянемо конкретне завдання:

  • побудувати гістограму розподілу цін Bid і Ask;
  • цінові дані Ask розташуємо праворуч від поточного бару, а Bid - зліва;
  • при надходженні нового тика будемо обчислювати частоти для кожного, значення ціни, тобто інтервал гістограми дорівнює розміру пункту поточного інструменту.

Тепер усложним умова: не можна використовувати індикаторні буфери, масиви або структури.

Як вирішити цю проблему?

По-перше, потрібно придумати, де зберігати накопичені частоти для кожного стовпчика гістограми. Навіть на рис. 1. видно, що таких стовпців може бути скільки завгодно, і перше що приходить в голову - це використовувати масив. Причому динамічний, тому що заздалегідь невідомий можливий діапазон цін (кількість стовпців) на обраному часовому ділянці цінового графіка. Але за умовою завдання це заборонено.

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

Виявляється, що розробниками мови MQL5 вже давно створено необхідний для вирішення поставленого завдання функціонал, причому досить потужний. Так, шановний читачу, пропонується використовувати "приховані" (неочевидні) можливості групи функцій графічних об'єктів. У кожного об'єкта є властивості - це такі змінні, які створюються разом з об'єктом і служать для зберігання безлічі різних параметрів. Деякі властивості можна використовувати не зовсім за призначенням, і при цьому функціональність не буде втрачена. Назвемо такі властивості "графічної" пам'яттю. Іншими словами, якщо нам потрібно зберегти якусь змінну і при необхідності отримати її значення, то створюємо графічний об'єкт і присвоюємо певного властивості значення змінної.

Властивості графічних об'єктів - це свого роду аналог глобальних змінних терміналу, тільки краще. Глобальні змінні існують в клієнтському терміналі 4 тижні від часу останнього звернення до них, а потім автоматично знищуються. Графічна пам'ять існує до тих пір, поки графічний об'єкт не буде видалений. Уявляєте, які можливості нам це відкриває?

Які властивості графічних об'єктів можна задіяти в графічній пам'яті

При створенні будь-якого графічного об'єкта йому потрібно присвоїти унікальне ім'я, а це текстовий рядок. Рядок може складатися з подстрок, а подстрока може містити відформатовані основні типи даних: цілі, логічні, з плаваючою точкою, колір, дата і час. Отже, властивість OBJPROP_NAME підходить для зберігання змінних, правда, в основному для читання даних.

Наступне властивість, яке можна використовувати - це опис об'єкта OBJPROP_TEXT . Це теж текстовий рядок, можливості якої на порядок вище, ніж у попереднього властивості. У цьому полі властивості можливо і читання, і запис змінних.

У будь-якого графічного об'єкта є координати: ціна OBJPROP_PRICE і час OBJPROP_TIME . Їх також можна використовувати в графічної пам'яті.

Повернемося до нашого завдання. Частоти будемо зберігати в властивості OBJPROP_TEXT , А значення цін Bid і Ask - у властивості OBJPROP_NAME . Код функції, яка створює об'єкти і накопичує частоти, наведено нижче:

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); 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"); 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); }} 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. Тому коментарі є тільки в першому блоці.

У уважного читача напевно виникло резонне питання: а навіщо дублювати ціну в імені об'єкта, якщо вона і так доступна у властивості OBJPROP_PRICE ? У чому сенс цієї роботи?

На цьому моменті зупинимося детальніше. При надходженні нової ціни необхідно визначити, в який стовпець вона потрапить, і там, відповідно, збільшити значення частоти. Якби використовувалася координата ціни безпосередньо зі свого властивості, то довелося б перебрати всі графічні об'єкти, запросити значення цієї властивості, порівняти з надійшла ціною і тільки після цього записати нове значення частоти в потрібний стовпець. А порівнювати дійсні числа типу double - це та ще "засідка". Загалом, дуже неефективний алгоритм. Інша справа, коли під час вступу нового значення ціни ми відразу записуємо змінилася частоту туди, куди треба. Яким чином? Справа в тому, що при створенні нового графічного об'єкта з таким же ім'ям, з яким вже є існуючий, новий об'єкт не створюється і поля властивості не обнуляються. Іншими словами, ми створюємо об'єкти, не замислюючись про те, що вони будуть дублюватися. Не потрібно робити додаткових перевірок, тому що копії і клони створюватися не будуть. Про це подбає функціонал терміналу і графічних об'єктів. Залишається тільки визначити, вперше ця ціна потрапила у вибірку чи ні. Для цього в даній функції DrawHistogram () використовується префікс "зірочка" (*) у властивості об'єкта OBJPROP_TEXT . Якщо "зірочки" немає, то така ціна надійшла вперше. Дійсно, коли ми створюємо об'єкт даремно, це поле порожньо. При наступних зверненнях там буде зберігатися значення частоти з заданим префіксом.

Наступним кроком ми робимо зміщення гістограм вправо. При появі нового бару графік зсувається вліво, а треба, щоб гістограма завжди відображалася на поточному барі, тобто порушувався в протилежну сторону. Розглянемо, як це зробити:

if (time [0]> prevTimeBar) {prevTimeBar = time [0]; for (int obj = ObjectsTotal (0, - 1, - 1) - 1; obj> = 0; obj--) {string obj_name = ObjectName (0, obj, - 1, - 1); if (obj_name [0] == R) {ObjectSetInteger (0, obj_name, OBJPROP_TIME, 0, time [0]); string str = ObjectGetString (0, obj_name, OBJPROP_TEXT); string strint = StringSubstr (str, 1); long n = StringToInteger (strint); ObjectSetInteger (0, obj_name, OBJPROP_TIME, 1, time [0] + hsize * n); ObjectSetInteger (0, obj_name, OBJPROP_COLOR, color_R_passive); } If (obj_name [0] == L) {ObjectSetInteger (0, obj_name, OBJPROP_TIME, 0, time [0]); string str = ObjectGetString (0, obj_name, OBJPROP_TEXT); string strint = StringSubstr (str, 1); long n = StringToInteger (strint); ObjectSetInteger (0, obj_name, OBJPROP_TIME, 1, time [0] -hsize * n); ObjectSetInteger (0, obj_name, OBJPROP_COLOR, color_L_passive); }} ChartRedraw (); }

Ось, власне, і все. Гістограма цін Bid і Ask будується на графіку, і програма не використовує жодного масиву або індикаторного буфера. Повністю код цього рішення знаходиться в додатку до статті.

На відео показано готове рішення аналогічної задачі з використанням графічної пам'яті. Сам код можна знайти в CodeBase : індикатор "Histogram bid and ask prices" .

Приклади побудови гістограм в головному вікні

Технологія програмування функціоналу з використанням графічної пам'яті розглянута, тепер давайте побудуємо кілька гістограм для стандартних індикаторів. Принцип побудови аналогічний розглянутому, тільки замість цін Bid і Ask будемо використовувати значення індикаторів на поточному барі.

1. Індикатор iMA . Візьмемо два індикатора з різними періодами усереднення і побудуємо гістограми. Ось як виглядає код:

input int period_MA1 = 20; input int period_MA2 = 14; double MA1 []; double MA2 []; int iMA1_handle; int iMA2_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iMA1_handle = (_Symbol, _Period, period_MA1, 0, MODE_SMA, PRICE_CLOSE); iMA2_handle = (_Symbol, _Period, period_MA2, 0, MODE_SMA, PRICE_CLOSE); ArraySetAsSeries (MA1, true); ArraySetAsSeries (MA2, true); 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 (time, true); CopyBuffer (iMA1_handle, 0, 0, 1, MA1); CopyBuffer (iMA2_handle, 0, 0, 1, MA2); DrawHistogram (true, "iMA (" + (string) period_MA1 + ") =", MA1 [0], time [0], _Digits); DrawHistogram (false, "iMA (" + (string) period_MA2 + ") =", MA2 [0], time [0], _Digits); if (time [0]> prevTimeBar) {prevTimeBar = time [0]; for (int obj = ObjectsTotal (0, - 1, - 1) - 1; obj> = 0; obj--) {string obj_name = ObjectName (0, obj, - 1, - 1); if (obj_name [0] == R) {ObjectSetInteger (0, obj_name, OBJPROP_TIME, 0, time [0]); string str = ObjectGetString (0, obj_name, OBJPROP_TEXT); string strint = StringSubstr (str, 1); long n = StringToInteger (strint); ObjectSetInteger (0, obj_name, OBJPROP_TIME, 1, time [0] + hsize * n); ObjectSetInteger (0, obj_name, OBJPROP_COLOR, color_R_passive); } If (obj_name [0] == L) {ObjectSetInteger (0, obj_name, OBJPROP_TIME, 0, time [0]); string str = ObjectGetString (0, obj_name, OBJPROP_TEXT); string strint = StringSubstr (str, 1); long n = StringToInteger (strint); ObjectSetInteger (0, obj_name, OBJPROP_TIME, 1, time [0] -hsize * n); ObjectSetInteger (0, obj_name, OBJPROP_COLOR, color_L_passive); }} ChartRedraw (); } Return (rates_total); }

Мал. 2. Гістограма 2-х індикаторів iMA.

2. Індикатор iBands . Для цього індикатора побудуємо гістограми для верхньої (UPPER_BAND) і нижньої (LOWER_BAND) меж. Скорочений код показаний нижче.

input int period_Bands = 14; double UPPER []; double LOWER []; int iBands_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iBands_handle = (_Symbol, _Period, period_Bands, 0, 5.00, PRICE_CLOSE); ArraySetAsSeries (UPPER, true); ArraySetAsSeries (LOWER, true); 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 (time, true); CopyBuffer (iBands_handle, 1, 0, 1, UPPER); CopyBuffer (iBands_handle, 2, 0, 1, LOWER); DrawHistogram (true, "iBands (UPPER) =", UPPER [0], time [0], _Digits); DrawHistogram (false, "iBands (LOWER) =", LOWER [0], time [0], _Digits); if (time [0]> prevTimeBar) {...} return (rates_total); }

Мал. 3. Гістограма смуг Боллинджера індикатора iBands.

Цікаві гістограми вийдуть для індикатора Боллинджера, якщо використовувати всі 3 індикаторних буфера (0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND). Гістограму верхньої і нижньої смуг розташуємо праворуч від поточного бару, а гистограмму базової лінії - зліва від нульового бару. Результат показаний на наступному малюнку:

Результат показаний на наступному малюнку:

Мал. 4. Гістограма смуг Боллинджера на 3 індикаторних буферах.

Код для цього варіанту гістограм наведено нижче. Зверніть увагу, що справа відображаються фактично дві гістограми: для верхньої і нижньої меж індикатора. При цьому візуально вони сприймаються як одна єдина діаграма.

input int period_Bands = 20; double BASE []; double UPPER []; double LOWER []; int iBands_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iBands_handle = (_Symbol, _Period, period_Bands, 0, 10.00, PRICE_CLOSE); ArraySetAsSeries (BASE, true); ArraySetAsSeries (UPPER, true); ArraySetAsSeries (LOWER, true); 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 (time, true); CopyBuffer (iBands_handle, 0, 0, 1, BASE); CopyBuffer (iBands_handle, 1, 0, 1, UPPER); CopyBuffer (iBands_handle, 2, 0, 1, LOWER); DrawHistogram (true, "iBands (UPPER) =", UPPER [0], time [0], _Digits); DrawHistogram (true, "iBands (LOWER) =", LOWER [0], time [0], _Digits); DrawHistogram (false, "iBands (LOWER) =", BASE [0], time [0], _Digits); if (time [0]> prevTimeBar) {...} return (rates_total); }

До сих пір були розглянуті приклади варіаційних рядів, в яких інтервал значень досліджуваної величини (варіанти) дорівнював розміру пункту поточного інструменту _Point . Інакше кажучи, все значення ціни малювалися окремим стовпчиком гістограми.

Слід підкреслити, як витончено і непомітно для читача варіаційні ряди були розсортовані (ранжовані) вбудованим функціоналом терміналу. Для цього не довелося написати жодного рядка коду.

А тепер подивимося, як змінити інтервал розподілу, в якому буде кілька значень варіанти, використовуючи всього одну змінну і міць функціоналу графічних об'єктів. У розглянутій вище функції DrawHistogram () є вхідний параметр span - розрядність досліджуваного параметра. Так ось, варіюючи розрядність, ми можемо змінювати інтервал для розрахунку частот гістограми. Оскільки в ім'я графічного об'кта влючая ціна, то відбір відбувається автоматично на етапі створення і коригування властивостей об'єктів. Подивіться, як легко вирішуються завдання сортування і угрупування з використанням графічної пам'яті без програмування.

Мал. 5. Гістограма цін Bid і Ask зі збільшеним інтервалом стовпчиків.

Отже, побудувати гістограми в головному вікні графіка виявилося дуже просто. Тепер розберемося з тим, як зробити подібні діаграми в додаткових вікнах графіка.

Гістограми в додаткових вікнах

Принцип створення статистичних розподілів в додаткових вікнах такий же, як і в головному. Різниця в тому, що значення досліджуваних величин можуть мати негативні величини і довільну розрядність. Так, в головному вікні цінова шкала має заздалегідь відому розрядність, яку можна отримати за допомогою змінної _Digits . У додаткових вікнах змінні можуть приймати як позитивні, так і негативні значення. Крім того, кількість значущих цифр після коми може бути яким завгодно. Тому цю особливість потрібно врахувати при завданні вхідних параметрів функції DrawHistogram () для побудови гістограм, а також вказати номер додаткового вікна. За замовчуванням, в функції використовується головне вікно, яке дорівнює нулю.

Приклади побудови гістограм в додаткових вікнах

Найкраще інформація засвоюється на прикладах. Ними і займемося. Розглянемо кілька прикладів побудови гістограм в додаткових вікнах для стандартних технічних індикаторів.

1. Індикатор iChaikin .

Індикатор   iChaikin

Мал. 6. Гістограма індикатора Chaikin Oscillator.

Скорочений код для цього індикатора:

input int period_fast = 3; input int period_slow = 10; double CHO []; int iChaikin_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iChaikin_handle = (_Symbol, _Period, period_fast, period_slow, MODE_SMA, VOLUME_TICK); ArraySetAsSeries (CHO, true); 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 (time, true); CopyBuffer (iChaikin_handle, 0, 0, 2, CHO); DrawHistogram (true, "iChaikin =", CHO [0], time [0], 0, 1); if (time [0]> prevTimeBar) {...} return (rates_total); }

2. Індикатор iCCI .

Мал. 7. Гістограма індикатора Commodity Channel Index.

Скорочений код:

input int period_CCI = 14; double CCI []; int iCCI_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iCCI_handle = (_Symbol, _Period, period_CCI, PRICE_CLOSE); ArraySetAsSeries (CCI, true); 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 (time, true); CopyBuffer (iCCI_handle, 0, 0, 2, CCI); DrawHistogram (true, "iCCI =", CCI [0], time [0], 0, 1); if (time [0]> prevTimeBar) {...} return (rates_total); }

3. Індикатори: iEnvelopes , iATR , iMACD . Комбінація гістограм для трьох індикаторів, кожен з яких буде відображатися в своєму вікні.

Комбінація гістограм для трьох індикаторів, кожен з яких буде відображатися в своєму вікні

Мал. 8. Гістограми 3-х індикаторів: iEnvelopes, iATR and iMACD.

Скорочений код, який реалізує набір гістограм, зображений на рис. 8.

input int period_Envelopes = 14; input int period_ATR = 14; input int period_fast = 12; input int period_slow = 26; double UPPER []; double LOWER []; double ATR []; double MAIN []; double SIGNAL []; int iEnvelopes_handle; int iATR_handle; int iMACD_handle; int OnInit () {ObjectsDeleteAll (0, - 1, - 1); ChartRedraw (); iEnvelopes_handle = (_Symbol, _Period, period_Envelopes, 0, MODE_SMA, PRICE_CLOSE, 0.1); iATR_handle = (_Symbol, _Period, period_ATR); iMACD_handle = (_Symbol, _Period, period_fast, period_slow, 9, PRICE_CLOSE); ArraySetAsSeries (UPPER, true); ArraySetAsSeries (LOWER, true); ArraySetAsSeries (ATR, true); ArraySetAsSeries (MAIN, true); ArraySetAsSeries (SIGNAL, true); 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 (time, true); CopyBuffer (iEnvelopes_handle, 0, 0, 1, UPPER); CopyBuffer (iEnvelopes_handle, 1, 0, 1, LOWER); CopyBuffer (iATR_handle, 0, 0, 1, ATR); CopyBuffer (iMACD_handle, 0, 0, 1, MAIN); CopyBuffer (iMACD_handle, 1, 0, 1, SIGNAL); DrawHistogram (true, "iEnvelopes.UPPER =", UPPER [0], time [0], _Digits); DrawHistogram (false, "iEnvelopes.LOWER =", LOWER [0], time [0], _Digits); DrawHistogram (true, "iATR =", ATR [0], time [0], _Digits +1, 1); DrawHistogram (true, "iMACD.SIGNAL =", SIGNAL [0], time [0], _Digits +1, 2); DrawHistogram (false, "iMACD.MAIN =", MAIN [0], time [0], _Digits +1, 2); if (time [0]> prevTimeBar) {...} return (rates_total); }

Отже, розглянувши технологію побудови різних гістограм статистичних розподілів характеристик ринку, можна стверджувати, що:

  • функціонал торгового терміналу МТ5;
  • можливості графічних об'єктів MQL5;
  • графічна пам'ять (маловідомі можливості графічних об'єктів);
  • найпростіша функція DrawHistogram ()

дозволяють розрахувати і візуалізувати накопичувальні гістограми безлічі індикаторів - від стандартних до призначених для користувача. Втім, для більш детального аналізу ринкових характеристик цього недостатньо.

Чисельні характеристики статистичних розподілів

У першій частині статті був показаний спосіб побудови гістограм для початківців програмістів. Наведені приклади легко проектуються на великий клас завдань, пов'язаних з дослідженням статистичних розподілів і їх візуалізацією. Але для більш глибокого аналізу гістограм необхідні найбільш універсальні і прогресивні методи програмування, а саме - ООП . Отже, рассмотрімкакіе параметри статистичних розподілів будуть цікаві читачам.

В першу чергу, нас цікавлять кількісні показники варіаційних рядів:

  • середнє арифметичне (середня частота);
  • зважене середнє арифметичне;
  • дисперсія;
  • середньоквадратичне відхилення.

У другу чергу, необхідна візуалізація зазначених характеристик. Звичайно, все це можна реалізувати і в процедурному стилі, але в даній статті вирішимо поставлені завдання із застосуванням об'єктно-орієнтованого програмування.

клас CHistogram

Функціонал даного класу дозволяє відображати на графіку гістограми і основні характеристики статистичних розподілів. Розглянемо основні методи.

Метод: конструктор класу CHistogram.

Ініціалізує екземпляр класу.

void CHistogram (
string name,
int hsize,
int width,
color active,
color passive,
bool Left_Right = true,
bool relative_frequency = false,
int sub_win = 0
);

Параметри:

name

[In] Унікальний префікс імені для всіх стовпців гістограми.

hsize

[In] Масштаб відображення гістограми.

width

[In] Товщина ліній стовпців гістограми.

active

[In] Колір стовпців гістограми, оновлених на поточному барі.

passive

[In] Колір стовпців гістограми, які на поточному барі не оновлюється.

Left_Right = true

[In] Напрямок відображення гістограми. false - гістограма розташована зліва від поточного бару, true - справа.

relative_frequency = false

[In] Метод обліку значень частот. false - абсолютні значення частот, true - відносні значення частот.

sub_win = 0

[In] Індекс вікна для побудови гістограми. 0 - головне вікно графіка.

Значення, що повертається:

Немає значення, що повертається. У разі успіху створюється екземпляр класу з заданими параметрами.

Метод: відображення гістограми DrawHistogram.

Відображає стовпці гістограми: створює нові, редагує наявні, зберігає значення частот в графічній пам'яті. відображає гістограму на поточному барі.

void DrawHistogram (
double price,
datetime time
);

Параметри:

price

[In] Значення варіанти досліджуваної характеристики ринку.

time

[In] Час поточного бару. На цьому барі буде вісь гістограми.

Значення, що повертається:

Немає значення, що повертається. У разі успіху буде створений новий або скоректований наявний стовпець гістограми. Якщо з'явиться новий бар, гістограма зсувається таким чином, щоб вісь перебувала на поточному барі.

Метод: розрахунок характеристик гістограми HistogramCharacteristics.

Повертає розраховані характеристики варіаційного ряду в змінної типу sVseries.

sVseries HistogramCharacteristics ();

Параметри:

Немає вхідних параметрів.

Значення, що повертається:

У разі успіху повертає значення змінної типу sVseries.

Структура для отримання поточних значень характеристик гістограми (sVseries).

Структура для зберігання останніх значень характеристик статистичного розподілу. Призначена для отримання найбільш затребуваною інформації про вариационном ряді.

struct sVseries
{
long N;
double Na;
double Vmax;
double Vmin;
double A;
double Mean;
double D;
double SD;
};

Змінна типу sVseries дозволяє за один виклик функції HistogramCharacteristics () отримати значення всіх основних характеристик варіаційного ряду, відображений у вигляді гістограми.

Метод: візуалізація значення середньої DrawMean.

Відображає значення зваженої середньої арифметичної варіаційного ряду на графіку.

void DrawMean (
double coord,
datetime time,
bool marker = false,
bool save = false
);

Параметри:

coord

[In] Значення зваженої середньої арифметичної.

time

[In] Час поточного бару. На цьому барі буде фіксуватися значення зваженої середньої арифметичної.

marker = false

[In] Відображати маркер на графіку чи ні. false - маркер не відображається, true - маркер відображається на графіку.

save = false

[In] Зберігати значення зваженої середньої арифметичної в історії. false - не відображати, true - відображати значення на графіку.

Значення, що повертається:

У разі успіху на графіку відображається горизонтальна лінія, відповідна значенню зваженої середньої арифметичної.

Метод: візуалізація середнє відхилення DrawSD.

Відображає значення середньоквадратичного відхилення у вигляді прямокутника, ширина якого збігається із середньою частотою, а висота дорівнює стандартному відхиленню, відкладеному вгору і вниз від значення зваженої середньої арифметичної.

void DrawSD (
sVseries & coord,
datetime time,
double deviation = 1.0,
color clr = clrYellow
);

Параметри:

coord

[In] Значення змінної типу sVseries.

time

[In] Час поточного бару.

deviation = 1.0

[In] Коефіцієнт, на який буде збільшено значення середньоквадратичного відхилення.

clr = clrYellow

[In] Колір прямокутника візуалізуються середнє відхилення.

Значення, що повертається:

У разі успіху на графіку відображається прямокутник, що характеризує середньоквадратичне відхилення від значення зваженої середньої арифметичної.

Приклад побудови гістограм з використанням класу CHistogram

Як приклад побудуємо гістограми статистичних розподілів цін Bid і Ask, а також двох індикаторів ATR и MACD (Рис. 9). На відміну від попередніх прикладів, за допомогою розглянутого класу можна створювати відносні діаграми. Для цін, крім самої гістограми, створимо графічне відображення зваженої середньої арифметичної і середнє відхилення. При цьому середню будемо зберігати за допомогою індикаторних буферів. На малюнку среднеквадратические відхилення зображені у вигляді прямокутників, ширина яких відповідає середній частоті, а висота дорівнює двом відхилень, збільшеним для наочності в кілька разів.

Мал. 9. Гістограми 2-х індикаторів: iATR, iMACD і цін Bid і Ask.

Код цього прикладу знаходиться в додатку до статті. Використання індикаторних буферів в даній програмі викликано бажанням продемонструвати зв'язок розглянутого класу і функціоналу індикатора.

Висновок

  • Статистичні розподілу варіаційних рядів у вигляді гістограм, без використання масивів і індикаторних буферів, абсолютно спокійно можна реалізувати з застосуванням "графічної" пам'яті.
  • У тих завданнях, де використовуються графічні побудови (об'єкти), в більшості випадків виправдано використання властивостей графічних об'єктів як економною пам'яті. При цьому ми отримуємо доступ до великим можливостям функціоналу терміналу і мови MQL5: таким, як сортування, угруповання, пошук, вибірка, прямий доступ до елементів і іншим.
  • Розглянуто базові, примітивні способи використання "графічної" пам'яті. Насправді можна зберігати невеликі масиви і структури в властивості графічних об'єктів.
Як вирішити цю проблему?
Уявляєте, які можливості нам це відкриває?
У чому сенс цієї роботи?
Яким чином?


Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью