• Главная
  • Карта сайта
Не найдено

Обробник події "новий бар"

  1. Вступ Для творців індикаторів і експертів завжди було актуальним питання написання економічного коду...
  2. Аналіз функції-прототипу
  3. Створення нової функції isNewBar ()
  4. Приклади використання класу CisNewBar
  5. Обробник події "новий бар"
  6. Висновок

Вступ

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

  • про способи виявлення нового бару;
  • про недоліки вже існуючих алгоритмів визначення нового бару;
  • про створення універсального методу виявлення нового бару;
  • про тонкощі і способах застосування цього методу;
  • про подію NewBar і обробнику цієї події OnNewBar ().

Способи виявлення нового бару

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

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

Наприклад, в призначених для користувача індикаторах можна використовувати для цієї мети пару вхідних параметрів функції OnCalculate () : Rates_total і prev_calculated. Обмеженість цього методу в основному полягає в тому, що його можна використовувати тільки для визначення нового бару поточного графіка і тільки в індикаторах. Якщо ви хочете виявити новий бар на іншому періоді або символі, то необхідно використовувати додаткові прийоми.

Або, наприклад, можна спробувати зловити новий бар на його першому тику, коли тиковий обсяг Tick Volume = 1, або коли всі ціни бару рівні Open = High = Low = Close. Ці способи цілком можуть використовуватися при тестуванні, але в реальній торгівлі вони часто дають збої. Це пов'язано з тим, що миті між першим і другим тиком буває недостатньо, щоб зловити що утворився бар. Особливо це стає помітно при сильному русі ринку або при поганій якості каналу зв'язку.

Є спосіб виявлення нового бару на основі функції TimeCurrent () . До речі, хороший спосіб, якщо вам потрібно визначити поява нового бару на поточному графіку. Ми його використовуємо в кінці статті.

Ну, можна ще запитати у сусіда: "Слухай, а не з'явився новий бар?". Цікаво, що він відповість? Ну да ладно, давайте зупинимо свій вибір на принципі відстеження часу відкриття поточного незавершеного бару для виявлення нового. За ступенем простоти і надійності він вселяє довіру і вже зарекомендував себе.

Відправний пункт

У вище перерахованих матеріалах з відстеженням появи нового бару справи йдуть непогано. Але ...

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

bool isNewBar () {static datetime last_time = 0; datetime lastbar_time = SeriesInfoInteger (Symbol (), Period (), SERIES_LASTBAR_DATE); if (last_time == 0) {last_time = lastbar_time; return (false); } If (last_time! = Lastbar_time) {last_time = lastbar_time; return (true); } Return (false); }

Ця наша функція-прототип насправді працездатна і має повне право на життя. Але ...

Аналіз функції-прототипу

Я скопіював цю функцію в код свого, природно, геніального і найкращого радника. Чи не запрацювало. Став розбиратися. Нижче мої роздуми щодо цієї функції.

Заголовок функції. Давайте розглянемо все по порядку. Почнемо з заголовка функції:

bool isNewBar ()

Заголовок функції мені подобається, дуже простий, інтуїтивно зрозумілий, і не треба розбиратися з переданими параметрами. Було б добре зберегти його в майбутньому в такому вигляді.

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

static datetime last_time = 0;

Начебто все красиво. Але ...

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

Якщо виклик цієї функції-прототипу відбувається з одного місця, то ми отримаємо що потрібно. Але якщо ми захочемо скористатися цією функцією, наприклад, ще раз в іншому місці в цьому ж циклі розрахунку, то вона завжди буде повертати false, що означає "бару немає". А це не завжди буде правдою. Статична змінна в нашому випадку накладає штучне обмеження на кількість викликів функції-прототипу.

Питання універсальності. Наступна інструкція до функцій-прототип виглядає так:

datetime lastbar_time = SeriesInfoInteger (Symbol (), Period (), SERIES_LASTBAR_DATE);

Логічно, що для отримання часу відкриття останнього незавершеного бару використовується функція SeriesInfoInteger () з модифікатором SERIES_LASTBAR_DATE.

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

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

Обробка помилок. Давайте ще раз глянемо на функцію SeriesInfoInteger () . Як ви думаєте, що вона поверне, якщо її змусили виконуватися, коли графік ще не сформувався? Така ситуація може виникнути, наприклад, якщо ви приєднали до графіка свій експерт або індикатор і вирішили змінити період або символ графіка, а також при перезапуску терміналу. А що буде під час поновлення таймсеріі? До речі, в довідці є таке попередження:

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

Можливість ініціалізації. Рухаємося далі. Розглянемо наступні інструкції нашої функції-прототипу:

if (last_time == 0) {last_time = lastbar_time; return (false); }

Вже тут-то точно все добре. Є, правда, один нюанс. Звернули увагу на вищенаведену фразу з довідки: "Статичні змінні існують з моменту виконання програми і не започатковано одноразово перед викликом спеціалізованої функції OnInit () "? А як бути, якщо нам необхідно ще раз ініціалізувати змінну last_time. Точніше, що робити, якщо необхідно штучно створити ситуацію першого виклику? Або яку іншу ситуацію? Легко задавати питання, коли знаєш відповіді. Але про це пізніше.

Кількість барів. Далі в нашій функції-прототипі йде наступний код:

if (last_time! = lastbar_time) {last_time = lastbar_time; return (true); }

Розумієте, такий програміст як я, може зробити так, що цей оператор if буде дивувати клієнтський термінал і тестер стратегій. Справа в тому, що, за логікою речей, минулий час завжди менше сьогодення. Тобто last_time <lastbar_time. У мене через випадкову програмної помилки вийшла машина часу, точніше, вийшло навпаки lastbar_time <last_time. Як тут не здивуєшся? В общем-то, такий часовий парадокс легко виявити і видати повідомлення про помилку.

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

Закінчується наша функція-прототип так:

return (false);

Так, якщо дійшли до цього місця - значить бар не новий.

Створення нової функції isNewBar ()

Починається цікаве. Будемо усувати виявлені мінуси. Відразу скажу, що був скромним, назвавши розділ "Створення нової функції isNewBar ()". Будемо робити щось більш солідне.

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

З ходу приходить на розум, що можна використовувати відповідні однойменні функції isNewBar () зі статті " Принципи економного перерахунку індикаторів "Або звідси isNewBar , Тобто в тіло функції включити масиви для зберігання кількох значень last_time, поставити лічильники викликів функції isNewBar () з різних місць і так далі. Безумовно, все це робочі варіанти і вони можуть бути втілені в життя. Але уявімо, що ми пишемо мультивалютний радник для роботи на 12 валютних парах. Це ж скільки всяких нюансів треба врахувати і не заплутатися?

Що робити? відповідь тут !

Краса об'єктно-орієнтованого програмування полягає в тому, що об'єкт або екземпляр якогось класу може жити власним життям незалежно від інших екземплярів цього ж класу. Тому давайте почнемо створювати клас СisNewBar, щоб у нас була можливість "плодити" екземпляри цього класу в будь-якому місці нашого радника або індикатора будь-яку кількість разів. І нехай кожен екземпляр "живе своїм життям".

Ось що для початку ми маємо:

class CisNewBar {protected: datetime m_lastbar_time; public: void CisNewBar (); bool isNewBar (); }; bool CisNewBar :: isNewBar () {... return (false); }

Те, що було функцією isNewBar (), тепер є методом. Зверніть увагу, що у нас немає тепер статичної змінної last_time - замість неї з'явилася захищена змінна класу m_lastbar_time. Якби ми залишили статичну змінну в методі isNewBar (), то всі наші зусилля пішли б нанівець, так як залишилися б все ті ж проблеми, що і раніше з функцією isNewBar () - такі особливості статичних змінних.

А зараз час останнього бару буде зберігатися в захищеній змінної класу m_lastbar_time, і для кожного екземпляра класу для неї буде визначено окреме місце в пам'яті комп'ютера. Таким чином нам вдалося зняти обмеження на кількість викликів, яке було у функції-прототипу. Ми можемо викликати метод isNewBar () в різних місцях нашої MQL-програми як угодне кількість разів, створюючи для кожного місця свій екземпляр класу.

Вже щось нам вдалося. Тепер займемося питанням універсальності. Перш ніж щось додавати в наш новий клас, хотів вас підвести до однієї забавної ідеї.

Давайте міркувати. Що ми хочемо? Хочемо отримати сигнал про появу нового бару. Як ми хочемо це зробити? Так, якщо час відкриття поточного незавершеного бару на останньому тику (або в останній момент часу) більше часу відкриття поточного незавершеного бару на попередньому тику (або в попередній момент часу), то утворився новий бар. Не понял що написав, але зате правильно написав. Суть в тому, що нам потрібно порівнювати час. Тому вирішив, що якщо в якості параметра передавати в метод isNewBar () час відкриття поточного незавершеного бару newbar_time - буде логічно. Тоді заголовок методу буде таким:

bool isNewBar (datetime newbar_time)

Поки не питайте, звідки ми візьмемо newbar_time, припустимо, що воно відоме. Пізніше розберемося.

До речі, передаючи час в метод isNewBar (), ми отримаємо досить гнучкий інструмент для відстеження появи нового бару. Ми зможемо охопити всі стандартні періоди графіків зі всілякими торговими інструментами. Вийшло так, що ми не залежимо зараз від назви інструмента і розміру періоду.

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

Що ж, з універсальністю у нас тепер теж може бути все в порядку. Давайте доповнимо наш клас CisNewBar відповідно до нашою ідеєю:

class CisNewBar {protected: datetime m_lastbar_time; uint m_retcode; int m_new_bars; string m_comment; public: void CisNewBar (); bool isNewBar (datetime new_Time); }; bool CisNewBar :: isNewBar (datetime newbar_time) {m_new_bars = 0; m_retcode = 0; m_comment = __ FUNCTION __ + "Перевірка появи нового бару завершилася успішно"; if (m_lastbar_time> newbar_time) {m_comment = __ FUNCTION __ + "Помилка синхронізації: час попереднього бару" + TimeToString (m_lastbar_time) + ", час запиту нового бару" + TimeToString (newbar_time); m_retcode = - 1; return (false); } If (m_lastbar_time == 0) {m_lastbar_time = newbar_time; m_comment = __FUNCTION__ + "Ініціалізація lastbar_time =" + TimeToString (m_lastbar_time); return (false); } If (m_lastbar_time <newbar_time) {m_new_bars = 1; m_lastbar_time = newbar_time; return (true); } Return (false); }

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

Все б добре, але наш універсальний метод isNewBar (datetime newbar_time) містить в собі одне істотне незручність. Це незручність полягає в тому, що нам в коді свого експерта або індикатора завжди потрібно піклуватися про обчислення часу передбачуваного нового бару newbar_time.

На щастя, в деяких випадках ми можемо спростити собі життя, доручивши цю функцію новому додатковому методу нашого класу. Це можна зробити для стандартних періодів і торгових інструментів як в нашій функції-прототипі, використовуючи другий варіант знайомої функції SeriesInfoInteger з модифікатором SERIES_LASTBAR_DATE, а у всіх інших випадках - користуватися універсальним методом. Отже, ось що у мене вийшло:

int CisNewBar :: isNewBar () {datetime newbar_time; datetime lastbar_time = m_lastbar_time; ResetLastError (); if (! SeriesInfoInteger (m_symbol, m_period, SERIES_LASTBAR_DATE, newbar_time)) {m_retcode = GetLastError (); m_comment = __ FUNCTION __ + "Помилка при отриманні часу відкриття останнього бару:" + IntegerToString (m_retcode); return (0); } If (! IsNewBar (newbar_time)) return (0); m_new_bars = Bars (m_symbol, m_period, lastbar_time, newbar_time) -1; return (m_new_bars); }

Що ми маємо на даний момент? Тепер нам не потрібно для стандартних періодів піклуватися про визначення часу відкриття останнього незавершеного бару. Ми прийшли практично до нашої функції-прототипу з її простим викликом і без тих недоліків, які у неї були. І навіть отримали додаткові плюси, включаючи номери помилок, коментарі виконання і кількість нових барів.

Чи залишилося у нас ще щось? Так. Залишився останній момент - ініціалізація. Для цього ми скористаємося конструктором класу і декількома Set-методами. Наш конструктор класу виглядає так:

void CisNewBar :: CisNewBar () {m_retcode = 0; m_lastbar_time = 0; m_new_bars = 0; m_comment = ""; m_symbol = Symbol (); m_period = Period (); }

А Set-методи так:

void SetLastBarTime (datetime lastbar_time) {m_lastbar_time = lastbar_time; } Void SetSymbol (string symbol) {m_symbol = (symbol == NULL || symbol == "")? Symbol (): symbol; } Void SetPeriod (ENUM_TIMEFRAMES period) {m_period = (period == PERIOD_CURRENT)? Period (): period; }

Завдяки конструктору класу, нам не потрібно приділяти увагу ініціалізації торгового інструменту і періоду для поточного графіка. Як і в функції-прототипі, вони будуть використовуватися за замовчуванням. Але якщо нам потрібно використовувати інший торговий інструмент або період графіка, то можемо для цього застосувати створені нами Set-методи. Крім цього, використовуючи SetLastBarTime (datetime lastbar_time), при необхідності можна повторно створювати ситуацію "перший виклик".

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

uint GetRetCode () const {return (m_retcode); } Datetime GetLastBarTime () const {return (m_lastbar_time);} int GetNewBars () const {return (m_new_bars); } String GetComment () const {return (m_comment); } String GetSymbol () const {return (m_symbol); } ENUM_TIMEFRAMES GetPeriod () const {return (m_period); }

Тепер ми можемо в своїх mql5-програмах отримувати всю необхідну інформацію. На цьому в створенні класу СisNewBar можна поставити крапку.

Повний код нашого класу в доданому файлі Lib СisNewBar.mqh.

Приклади використання класу CisNewBar

Пропоную розглянути приклади використання нашого класу з метою розібратися з усіма тонкощами того, що ми створили. Бути може, є не тільки плюси, а й мінуси.

Приклад 1. Для початку створимо абсолютно ідентичний радник, що й для функції isNewBar () зі статті " Обмеження і перевірки в експертів ":

#property copyright "Copyright 2010 Lizar" #property link "[email protected]" #property version "1.00" #include <Lib CisNewBar.mqh> CisNewBar current_chart; void OnTick () {if (current_chart.isNewBar ()> 0) {PrintFormat ( "Новий бар:% s", TimeToString (TimeCurrent (), TIME_SECONDS)); }}

Запустимо обидва радника на графіках з однаковою парою і однаковим періодом. Подивимося, що у нас вийшло:

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

Далі, я змінив період графіка на двохвилинний. Радники по різному відреагували на це. Радник CheckLastBar став повідомляти про появу нового бару раз в 2 хвилини, а Example1NewBar показує поява нових барів кожну хвилину, як ніби зміни періоду не відбулося (відзначено цифрою 2).

Справа в тому, що ініціалізація нашого екземпляра класу current_chart сталася при приєднанні радника до графіка конструктором класу. При зміні періоду, при вже приєднаному до графіка експерта, конструктор класу не запускається, і наш радник продовжує працювати з хвилинним періодом. Це говорить про те, що створений нами екземпляр класу живе власним життям і на нього навіть не впливають зміни зовнішнього середовища. Це може бути як плюсом так і мінусом - все залежить про вирішуваних завдань.

Для того, щоб наш експерт все ж діяв такоже як и радник CheckLastBar, та патенти, в Функції OnInit () провести ініціалізацію захищених змінних класу m_symbol і m_period. Давайте зробимо це.

Приклад 2. Введемо деякі доповнення в наш радник і знову порівняємо його роботу з CheckLastBar. Код радника прикладений в файлі Example2NewBar.mq5. Запустимо радники на графіках з однаковою парою і однаковим періодом. Створимо для них ті ж перешкоди, що і минулого разу. Подивимося, що у нас вийшло:

Як і минулого разу, радники спочатку синхронно повідомляють про появу нового бару. Потім на кілька хвилин відключаю інтернет ... Включаю. Наш новий радник не просто повідомив про появу нового бару, але і підказав нам скільки їх з'явилося (відзначено цифрою 1). Для більшості індикаторів і експертів це число буде означати кількість Непосчітанние барів. Таким чином, ми отримали хорошу основу для створення економічних алгоритмів перерахунку.

Далі, я змінив період графіків на 2-х хвилинний. На відміну від прикладу 1, радники працюють синхронно (відзначено цифрою 2). Ініціалізація в функції OnInit () захищених змінних класу m_symbol і m_period допомогла. При зміні робочого інструменту (відзначено цифрою 3), експерти теж працюють однаково.

Приклад 3. У наш клас CisNewBar ми заклали можливість відстеження появи помилок. Буває, що радник побудований так, що необхідність відстежувати помилки відсутня. Що ж, тоді просто не використовуйте таку можливість. Ми ж спробуємо штучно створити таку ситуацію, коли помилка можлива, і спробуємо зловити її. Для цього трохи доповнимо код експерта (файл Example3NewBar.mq5).

Що я буду робити? Як завжди запущу радник Example3NewBar на хвилинних графіках. Потім почну міняти, наприклад, інструменти графіка в надії, що виникне ситуація, що термінал не встигне побудувати таймсерію до запиту радника. Загалом, від душі познущалися над клієнтським терміналом і подивлюся, що вийде ... Ну, це нормальний спосіб досліджень для Росії.

Після декількох спроб наш радник зловив помилку:

Тепер можна з упевненістю сказати, що ми вміємо ловити помилки виконання. Як їх обробляти - справа смаку. Зауважте, що помилку ми відстежили чотири рази. Коли завантаження і формування графіка завершилися, радник підказав, що ми пропустили всього 1 бар.

До речі, ті, хто подивився код радника, могли звернути увагу, що помилки є сенс перевіряти, тільки коли метод isNewBar () повертає значення менше або рівне нулю.

Попередження: якщо під час цього експерименту ви почнете міняти період графіка, то при зміні графіка з маленького періоду на великий отримаєте помилку синхронізації, тому що час відкриття бару, наприклад, у періоду Н1 більш раннє, ніж, наприклад, у M1 в 59 випадках. Щоб уникнути появи цієї помилки при перемиканні періоду графіка, потрібно правильно форматувати змінну m_lastbar_time в функції OnInit () методом SetLastBarTime (datetime lastbar_time).

Приклад 4. У цьому прикладі ускладнити завдання експерта. Візьмемо три валютні пари: EURUSD на M1, GBPUSD на M1 і USDJPY на M2. Графік з першою парою буде поточним, і на ньому ми будемо просто відстежувати появу нового бару. За другою парі ми будемо вважати кількість утворилися барів після старту радника. Рахунок будемо вести коли перша пара просигналізує, що з'явився новий бар. А по третин будемо постійно (при появі бару на EURUSD) проводити ініціалізацію захищеної змінної класу m_lastbar_time. Код радника прикладений в файлі Example4NewBar.mq5.

Створивши цей приклад, хочу з'ясувати, як наш клас функцій CisNewBar буде працювати в мультивалютний режимі. Що ж, запускаю ... Ось що вийшло:

Ось що вийшло:

Результати викликають питання. Поділлю масла в вогонь і вижену цю ж ділянку в тестері. Результати тестера:

Результати тестера:

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

Приклад 5. Поки ми ще жодного разу в прикладах явно не використовували самий універсальний метод визначення нового бару isNewBar (datetime newbar_time). Для цього я візьму індикатор тикових свічок зі статті " Створення тикових індикаторів "І додам в нього буфер для зберігання часу відкриття бару (файл TickColorCandles v2.00.mq5). Напишу коротенький радник, який буде повідомляти про час появи нової тикової свічки (файл Example5NewBar.mq5):

#property copyright "Copyright 2010 Lizar" #property link "[email protected]" #property version "1.00" #include <Lib CisNewBar.mqh> CisNewBar newbar_ind; int HandleIndicator; int OnInit () {HandleIndicator = iCustom (_Symbol, _Period, "TickColorCandles v2.00", 16, 0, ""); if (HandleIndicator == INVALID_HANDLE) {Alert ( "Помилка при створенні хендлом індикатора, номер помилки:", GetLastError ()); Print ( "Ініціалізація радника завершена некоректно. Торгівля заборонена."); return (1); } If (! ChartIndicatorAdd (ChartID (), 1, HandleIndicator)) {Alert ( "Помилка приєднання індикатора до графіка, номер помилки:", GetLastError ()); return (1); } Print ( "Ініціалізація радника завершена успішно. Торгівля дозволена."); return (0); } Void OnTick () {double iTime [1]; if (CopyBuffer (HandleIndicator, 5, 0, 1, iTime) <= 0) {Print ( "Невдала спроба отримати значення часу індикатора." + "\ nСледующая спроба отримати значення індикатора буде зроблена на наступному тику.", GetLastError ()) ; return; } If (newbar_ind.isNewBar ((datetime) iTime [0])) {PrintFormat ( "Новий бар. Час відкриття:% s Час останнього тика:% s", TimeToString ((datetime) iTime [0], TIME_SECONDS), TimeToString (TimeCurrent (), TIME_SECONDS)); }}

Напевно ви звернули увагу, яким чином ми отримуємо час відкриття тикової свічки. Дуже просто, правда? Розміщую індикатор і радник в свої папки, компілює і запускаю експерт. Запрацювало, ось результати:

Обробник події "новий бар"


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

Коль є бажання мати обробник події "новий бар" (або NewBar) - так давайте його створимо! Тим більше, що зараз ми з легкістю, використовуючи наш клас, можемо це подія ловити. Ось так буде виглядати наш експерт, в який ми вставили обробник OnNewBar () події NewBar:

#property copyright "Copyright 2010 Lizar" #property link "[email protected]" #property version "1.00" #include "OnNewBar.mqh" void OnNewBar () {PrintFormat ( "Новий бар:% s", TimeToString (TimeCurrent (), TIME_SECONDS)); }

Вийшло красиво. Зовні наш експерт виглядає дуже просто. Все, що наш обробник робить, так це друкує рядок про появу нового бару. Щоб зрозуміти, як відстежуємо подія NewBar і як запускається обробник, потрібно заглянути в файл OnNewBar.mqh:

#property copyright "Copyright 2010 Lizar" #property link "[email protected]" #include <Lib CisNewBar.mqh> CisNewBar current_chart; void OnTick () {int period_seconds = PeriodSeconds (_Period); datetime new_time = TimeCurrent () / period_seconds * period_seconds; if (current_chart.isNewBar (new_time)) OnNewBar (); }

Як бачите, тут теж немає нічого складного. Але є пара моментів, на які хотів звернути вашу увагу:

Перше. Як ви помітили, я використовую функцію TimeCurrent () для обчислення часу відкриття бару і застосовую перший метод перевірки появи події NewBar з нашого класу. В цьому є хороший плюс. Він полягає в тому, що такий прийом не вимагає обробки помилок, як при використанні функції SeriesInfoInteger з модифікатором SERIES_LASTBAR_DATE. Для нас це важливо, тому що наш обробник OnNewBar () повинен бути якомога більш надійним.

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

Результат роботи нашого обробника:

Висновок

Під час викладу матеріалу ми виконали хороший аналіз способів виявлення нового бару. Виявили недоліки і плюси існуючих прийомів відстеження моменту появи нового бару. Спираючись на те, що було, створили клас CisNewBar, що дозволяє без особливих витрат на програмування, ловити подія "новий бар" практично в будь-яких завданнях. При цьому ми позбулися більшості незручностей, присутніх в колишніх рішеннях.

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

Створений нами обробник події "новий бар" підходить тільки для одновалютних радників. Але ми навчилися використовувати для цієї мети найбільш надійний і швидкий спосіб. Тепер можна піти далі і зробити мультивалютний обробник подій NewBar. Але це тема цілої статті.

Ну, можна ще запитати у сусіда: "Слухай, а не з'явився новий бар?
Цікаво, що він відповість?
Але що робити, якщо я використовую період і інструмент не тільки поточного графіка?
Крім того, а що якщо у мене взагалі який-небудь хитрий графік?
Як ви думаєте, що вона поверне, якщо її змусили виконуватися, коли графік ще не сформувався?
А що буде під час поновлення таймсеріі?
Точніше, що робити, якщо необхідно штучно створити ситуацію першого виклику?
Або яку іншу ситуацію?
Як тут не здивуєшся?
Це ж скільки всяких нюансів треба врахувати і не заплутатися?
Провайдеры:
  • 08.09.2015

    Batyevka.NET предоставляет услуги доступа к сети Интернет на территории Соломенского района г. Киева.Наша миссия —... 
    Читать полностью

  • 08.09.2015
    IPNET

    Компания IPNET — это крупнейший оператор и технологический лидер на рынке телекоммуникаций Киева. Мы предоставляем... 
    Читать полностью

  • 08.09.2015
    Boryspil.Net

    Интернет-провайдер «Boryspil.net» начал свою работу в 2008 году и на данный момент является одним из крупнейших поставщиков... 
    Читать полностью

  • 08.09.2015
    4OKNET

    Наша компания работает в сфере телекоммуникационных услуг, а именно — предоставлении доступа в сеть интернет.Уже... 
    Читать полностью

  • 08.09.2015
    Телегруп

    ДП «Телегруп-Украина» – IT-компания с 15-летним опытом работы на рынке телекоммуникационных услуг, а также официальный... 
    Читать полностью

  • 08.09.2015
    Софтлинк

    Высокая скоростьМы являемся участником Украинского центра обмена трафиком (UA — IX) с включением 10 Гбит / сек... 
    Читать полностью