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

Індикатор для побудови графіка "Хрестики - нулики"

  1. Вступ Існує безліч типів графіків, які надають інформацію про поточну ситуацію на ринку. Багато...
  2. принцип побудови
  3. алгоритм індикатора
  4. стандартні сигнали
  5. Висновок

Вступ

Існує безліч типів графіків, які надають інформацію про поточну ситуацію на ринку. Багато з них прийшли до нас з далекого минулого, і як раз одним з таких є графік " Хрестики нолики "(Point and figure chart).

Цей тип графіка був відомий ще з кінця XIX століття. Його первісна назва "книжковий метод" вжив ще Чарльз Доу в редакційній статті номера "Уолл-Стріт Джорнал" від 20 липня 1901 року. Хоч Доу і стверджував, що "книжковий метод" вже існує п'ятнадцять років (тобто дата його народження 1886 рік), але саме він зафіксував його вживання і до цього дня.

Незважаючи на те, що Доу обмежився описом цього методу в редакційних статтях, зараз можна знайти безліч книг, в яких детально розкривається цей метод. Однією з таких книг, яку я б порадив прочитати початківцям трейдерам, є книга Томаса Дж. Дорсі "Метод графічного аналізу хрестики-нулики" (оригінал "Point and Figure Charting: The Essential Application for Forecasting and Tracking Market Prices").

опис

Графік "Хрестики-нулики" являє собою сукупність вертикальних стовпців: хрестиків "X" - символізують зростання цін, і налякав "O" - символізують падіння. Особливість цього графіка полягає в тому, що він будується на підставі цін, не враховуючи при цьому часу. Таким чином, прибравши одне значення з даних (час) для побудови цінових графіків, ми отримуємо графіки з каналами рівно в 45 градусів.

У побудові графіка "Хрестики-нулики" беруть участь дві заздалегідь обумовлені величини:

  • Коробка (box size) - кількість пунктів зміни ціни, які реєструються на графіку як хрестик або нулик (спочатку це значення передбачало вартість в доларах за акцію, але в подальшому переросло в пункти, що ми і будемо використовувати в нашому індикаторі).
  • Розворот (reversal) - величина протилежної руху ціни в одиницях величини коробки (box size), при якому відбувається зміна "Х" на "О" або навпаки (наприклад, розворот рівний 3 при величині коробки в 10 пунктів буде відповідати 30 пунктам).

Тобто ми вибираємо точку відліку, і від цієї точки, в разі зміни ціни на величину коробки помножену на параметр розвороту, ставимо хрестик "Х" при збільшенні ціни, і нулик "О" при зменшенні. Далі, в разі продовження руху в тому ж напрямку на розмір коробки, додаємо хрестик "Х" вгору стовпчика в разі збільшення і нулик "О" вниз стовпчика в разі зменшення. Якщо ж ціна пішла у зворотній бік від попереднього руху на величину коробки помноженої на параметр розвороту, то формується новий стовпчик і ставиться хрестик "Х" у разі збільшення і нулик "О" в разі зменшення.

Графік "Хрестики-нулики" зазвичай будується для зручності на картатій папері. Для більш детального уявлення розберемо невеликий приклад побудови графіка. Нехай є дані:

Дата Ціна High Ціна Low 07.03.2013 12:00 - 07.03.2013 20:00 1.3117 1.2989 07.03.2013 20:00 - 08.03.2013 04:00 1.3118 1.3093 08.03.2013 04:00 - 08.03.2013 12:00 1.3101 1.3080 08.03.2013 12:00 - 08.03.2013 20:00 1.3134 1.2955

З урахуванням того, що розмір коробки беремо рівним 10 і параметр розвороту рівним 3, побудуємо графік "Хрестики-нулики":

  • Спочатку ціна зростає на 128 пунктів, пройшовши від ціни 1.2989 до ціни 1.3117 - малюємо 12 хрестиків.
  • Далі ціна рухається вниз від 1.3118 до 1.3093 на 25 пунктів, чого недостатньо для розвороту, так що нічого не малюємо.
  • Після ми бачимо, що ціна падає ще до рівня 1.3080, і з огляду на верхнє значення 1.3118 ми отримуємо рух в 38 пунктів - значить можемо почати формувати новий стовпець двома нулями (хоч ціна і пройшла на три розміри коробки, малюємо два нулика, так як наступний стовпець малюється на один розмір коробки нижче).
  • Далі ціна зростає з 1.3080 до 1.3134 на 54 пункти і падає до 1.2955 - це 179 пунктів. Тобто ми отримуємо наступний стовпець в чотири хрестика вгору і далі ще один з 16 нулями вниз.

Зобразимо це на малюнку:

Рис 1. Зліва цінової графік у вигляді "Японських свічок", праворуч графік "Хрестики-нулики".

Даний приклад побудови графіка "Хрестики-нулики" дуже грубий і наведено для новачків, щоб полегшити розуміння.

принцип побудови

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

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

Сам принцип побудови досить простий:

  • Береться початкова точка - ціна відкриття першого хвилинного бару.
  • Далі, якщо ціна проходить відстань рівне розміру коробки помноженої на показник розвороту або більше, то малюються відповідні символи ( "О" - в разі спадного руху і "Х" - в разі висхідного). Запам'ятовуються дані для подальшої побудови про ціну останнього символу.
  • У разі продовження руху ціни в тому ж напрямку на розмір коробки, малюється відповідний символ.
  • Далі, в разі розвороту ціни, відлік проводиться не від найбільшої ціни валютної пари, а від ціни останнього символу, тобто якщо ціна не пройшла більше 50% розміру "Коробки", то вона просто ігнорується.

Давайте тепер визначимося зі стилем відтворення графіка "Хрестики-нулики". Мова MQL5 підтримує сім стилів побудови індикатора : Лінія, секція (відрізок), гістограма, стрілка (символ), зафарбовувана область (канал із заливкою), бари і японські свічки.

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

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

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

В підсумку виходить досить таки непогане візуальне уявлення:

Рис 2. Зовнішній вигляд побудови індикатора на парі EURUSD на денному таімфрейме.

алгоритм індикатора

Для початку нам слід визначитися з вхідними параметрами індикатора. Так як графік "Хрестики-нулики" не враховує дані часу, і ми використовуємо для побудови дані з хвилинних барів, то варто визначитися з кількістю оброблюваних даних, для того щоб не використовувати зайві ресурси системи. Та й будувати графік "Хрестики-нулики" на всій історії немає чого. Таким чином введемо перший параметр - "History". У ньому буде враховуватися кількість хвилинних барів для розрахунку.

Далі потрібно визначитися з розміром коробки і параметром розвороту. Для цього введемо змінні "Cell" (клітка) і "CellForChange" (клітини для зміни) відповідно. Також введемо параметр кольору хрестиків "ColorUp" і налякав "ColorDown". І нарешті, останній параметр - це колір меж поділу коробок "LineColor".

#property copyright "Aktiniy ICQ: 695710750" #property link "ICQ: 695710750" #property version "1.00" #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 #property indicator_label1 "APFD" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_style1 STYLE_SOLID #property indicator_color1 clrRed, clrGold #property indicator_width1 1 input int History = 10000; input int Cell = 5; input int CellForChange = 3; input color ColorUp = clrRed; input color ColorDown = clrGold; input color LineColor = clrAqua; double CandlesBufferOpen []; double CandlesBufferHigh []; double CandlesBufferLow []; double CandlesBufferClose []; double CandlesBufferColor []; double OpenPrice []; double PriceNow = 0; double PriceBefore = 0; char Trend = 0; double BeginPrice = 0; char FirstTrend = 0; int Columns = 0; double InterimOpenPrice = 0; double InterimClosePrice = 0; double NumberCell = 0; double Tick = 0; double OldPrice = 0; double InterimOpen []; double InterimClose [];

Тепер перейдемо до розгляду функції OnInit (). Тут буде вироблено зв'язування індикаторних буферів з одновимірними масивами. Також встановимо значення індикатора без відтворення для його коректного відображення.

Обчислимо значення допоміжної змінної "Tick" (розмір одного тика) для проведення розрахунків. Так само поставимо колірну схему і встановимо напрям індексації в індикаторних буферах як в таймсеріях. Це потрібно для зручності розрахунку значень індикатора.

int OnInit () {SetIndexBuffer (0, CandlesBufferOpen, INDICATOR_DATA); SetIndexBuffer (1, CandlesBufferHigh, INDICATOR_DATA); SetIndexBuffer (2, CandlesBufferLow, INDICATOR_DATA); SetIndexBuffer (3, CandlesBufferClose, INDICATOR_DATA); SetIndexBuffer (4, CandlesBufferColor, INDICATOR_COLOR_INDEX); PlotIndexSetDouble (0, PLOT_EMPTY_VALUE, 0); Tick ​​= SymbolInfoDouble (Symbol (), SYMBOL_TRADE_TICK_SIZE); PlotIndexSetInteger (0, PLOT_LINE_COLOR, 0, ColorUp); PlotIndexSetInteger (0, PLOT_LINE_COLOR, 1, ColorDown); ArraySetAsSeries (CandlesBufferClose, true); ArraySetAsSeries (CandlesBufferColor, true); ArraySetAsSeries (CandlesBufferHigh, true); ArraySetAsSeries (CandlesBufferLow, true); ArraySetAsSeries (CandlesBufferOpen, true); if (CellForChange <2) Alert ( "Параметр CellForChange повинен бути більше 1, з огляду на особливості побудови графіка"); return (0); }

У підсумку ми підійшли до самого "серця" індикатора - функції OnCalculate (), в якій буде проводитися його розрахунок. Розрахунки значень індикатора розбиті на шість базових функцій, які потрібно використовувати в OnCalculate (). Розглянемо їх:

1. Функція копіювання даних

Ця функція виконує копіювання даних з хвилинних барів в масив для розрахунків. Спочатку змінюємо розмірність приймає масиву, а потім, за допомогою функції CopyOpen (), копіюємо в нього ціни відкриття.

int FuncCopy (int HistoryInt) {ArrayResize (OpenPrice, (HistoryInt)); int Open = CopyOpen (Symbol (), PERIOD_M1, 0, (HistoryInt), OpenPrice); return (Open); }

2. Функція розрахунку числа стовпців

Ця функція обчислює кількість стовпців для побудови графіка "Хрестики-нулики".

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

  • 0 - невизначений тренд.
  • 1 - висхідний тренд.
  • -1 - спадний тренд.

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

Якщо таке пробиття відбувається вниз, то початковий тренд визначається як спадний і робиться відповідний запис в змінну "Trend". Визначення висхідного тренда відбувається аналогічним чином з точністю до навпаки. Також збільшується значення змінної числа стовпців "ColumnsInt".

Після визначення поточного тренда відбувається подальша координація, і встановлюються дві умови для кожного з напрямків. У разі продовження руху в бік поточного тренда на рівень "Коробки", змінна "ColumnsInt" залишається без змін. Якщо ж відбувається розворот ціни на величину 'Коробки "помноженої на значення" Розвороту ", то це означає появу нового стовпчика, і значення змінної" ColumnsInt "збільшується на один.

І так далі, поки не будуть визначені всі стовпці.

Для округлення кількості клітин в циклі використовується функція MathRound (), Яка дозволяє округляти отримані значення до найближчих цілих. При бажанні цю функцію можна замінити на MathFloor () (Округлення до нижнього цілого) або MathCeil () (Округлення до верхнього цілого), в залежності від того яке потрібно побудова.

int FuncCalculate (int HistoryInt) {int ColumnsInt = 0; Trend = 0; BeginPrice = OpenPrice [0]; FirstTrend = 0; Columns = 0; InterimOpenPrice = 0; InterimClosePrice = 0; NumberCell = 0; for (int x = 0; x <HistoryInt; x ++) {if (Trend == 0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {if (((BeginPrice-OpenPrice [ x]) / Tick)> 0) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpenPrice = BeginPrice; InterimClosePrice = BeginPrice- (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = - 1; } If (((BeginPrice-OpenPrice [x]) / Tick) <0) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpenPrice = BeginPrice; InterimClosePrice = BeginPrice + (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = 1; } BeginPrice = InterimClosePrice; ColumnsInt ++; FirstTrend = Trend; } If (Trend == - 1) {if (((BeginPrice-OpenPrice [x]) / Tick)> 0 && (Cell) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {NumberCell = fabs ( (BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimClosePrice = BeginPrice- (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = - 1; BeginPrice = InterimClosePrice; } If (((BeginPrice-OpenPrice [x]) / Tick) <0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {ColumnsInt ++; NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpenPrice = BeginPrice + (Cell * Tick); InterimClosePrice = BeginPrice + (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = 1; BeginPrice = InterimClosePrice; }} If (Trend == 1) {if (((BeginPrice-OpenPrice [x]) / Tick)> 0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {ColumnsInt ++; NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpenPrice = BeginPrice- (Cell * Tick); InterimClosePrice = BeginPrice- (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = - 1; BeginPrice = InterimClosePrice; } If (((BeginPrice-OpenPrice [x]) / Tick) <0 && (Cell) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimClosePrice = BeginPrice + (NumberCell * Cell * Tick); InterimClosePrice = NormalizeDouble (InterimClosePrice, Digits ()); Trend = 1; BeginPrice = InterimClosePrice; }}} Return (ColumnsInt); }

3. Функція розмальовки стовпців

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

int FuncColor (int ColumnsInt) {int x; for (x = 0; x <ColumnsInt; x ++) {if (FirstTrend == - 1) {if (x% 2 == 0) CandlesBufferColor [x] = 1; if (x% 2> 0) CandlesBufferColor [x] = 0; } If (FirstTrend == 1) {if (x% 2 == 0) CandlesBufferColor [x] = 0; if (x% 2> 0) CandlesBufferColor [x] = 1; }} Return (x); }

4. Функція визначення розмірів стовпців

Після того як ми визначили кількість використовуваних стовпців і встановили кольору розмальовки, потрібно подбати про їх вертикальному розмірі. Для цього створимо тимчасові масиви "InterimOpen []" і "InterimClose []", в яких ми будемо зберігати ціни відкриття і закриття для кожного стовпчика. Розмірність цих масивів встановимо рівною кількістю стовпців.

Далі слід цикл, який майже повністю повторює цикл з функції FuncCalculate (). Його відмінністю є те, що в ньому, крім усього вищевикладеного, запам'ятовуються ціни відкриття і закриття для кожного з стовпців. Такий поділ було зроблено для того, щоб заздалегідь знати кількість стовпців на графіку. Теоретично можна було спочатку задати свідомо більшу кількість стовпців для виділення пам'яті масивів і обійтися всього одним циклом, але тим самим ресурси пам'яті витрачалися б в більшому обсязі.

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

int FuncDraw (int HistoryInt) {ArrayResize (InterimOpen, Columns); ArrayResize (InterimClose, Columns); Trend = 0; BeginPrice = OpenPrice [0]; NumberCell = 0; int z = 0; for (int x = 0; x <HistoryInt; x ++) {if (Trend == 0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {if (((BeginPrice-OpenPrice [ x]) / Tick)> 0) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpen [z] = BeginPrice; InterimClose [z] = BeginPrice- (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = - 1; } If (((BeginPrice-OpenPrice [x]) / Tick) <0) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpen [z] = BeginPrice; InterimClose [z] = BeginPrice + (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = 1; } BeginPrice = InterimClose [z]; } If (Trend == - 1) {if (((BeginPrice-OpenPrice [x]) / Tick)> 0 && (Cell) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {NumberCell = fabs ( (BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimClose [z] = BeginPrice- (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = - 1; BeginPrice = InterimClose [z]; } If (((BeginPrice-OpenPrice [x]) / Tick) <0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {z ++; NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpen [z] = BeginPrice + (Cell * Tick); InterimClose [z] = BeginPrice + (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = 1; BeginPrice = InterimClose [z]; }} If (Trend == 1) {if (((BeginPrice-OpenPrice [x]) / Tick)> 0 && (Cell * CellForChange) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {z ++; NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimOpen [z] = BeginPrice- (Cell * Tick); InterimClose [z] = BeginPrice- (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = - 1; BeginPrice = InterimClose [z]; } If (((BeginPrice-OpenPrice [x]) / Tick) <0 && (Cell) <fabs ((BeginPrice-OpenPrice [x]) / Tick)) {NumberCell = fabs ((BeginPrice-OpenPrice [x]) / Tick) / Cell; NumberCell = MathRound (NumberCell); InterimClose [z] = BeginPrice + (NumberCell * Cell * Tick); InterimClose [z] = NormalizeDouble (InterimClose [z], Digits ()); Trend = 1; BeginPrice = InterimClose [z]; }}} Return (z); }

5. Функція розвороту масивів

Функція здійснює розворот отриманих даних масиву стовпців, щоб в подальшому призвести відображення графіка програмним шляхом справа наліво. У циклі здійснюється розворот масиву з привласненням значень "High" і "Low" для свічок. Це робиться, тому що індикатор відображається тільки для тих свічок, для яких значення всіх індикаторних буферів не рівні нулю.

int FuncTurnArray (int ColumnsInt) {int d = ColumnsInt; for (int x = 0; x <ColumnsInt; x ++) {d--; CandlesBufferOpen [x] = InterimOpen [d]; CandlesBufferClose [x] = InterimClose [d]; if (CandlesBufferClose [x]> CandlesBufferOpen [x]) {CandlesBufferHigh [x] = CandlesBufferClose [x]; CandlesBufferLow [x] = CandlesBufferOpen [x]; } If (CandlesBufferOpen [x]> CandlesBufferClose [x]) {CandlesBufferHigh [x] = CandlesBufferOpen [x]; CandlesBufferLow [x] = CandlesBufferClose [x]; }} Return (d); }

6. Функція для малювання горизонтальних ліній

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

int FuncDrawHorizontal (bool Draw) {int Horizontal = 0; if (Draw == true) {ObjectsDeleteAll (0, ChartWindowFind (), OBJ_HLINE); int MaxPriceElement = ArrayMaximum (OpenPrice); int MinPriceElement = ArrayMinimum (OpenPrice); for (double x = OpenPrice [0]; x <= OpenPrice [MaxPriceElement] + (Cell * Tick); x = x + (Cell * Tick)) {ObjectCreate (0, DoubleToString (x, Digits ()), OBJ_HLINE, ChartWindowFind (), 0, NormalizeDouble (x, Digits ())); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_COLOR, LineColor); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_SELECTED, false); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_WIDTH, 1); Horizontal ++; } For (double x = OpenPrice [0] - (Cell * Tick); x> = OpenPrice [MinPriceElement]; x = x- (Cell * Tick)) {ObjectCreate (0, DoubleToString (x, Digits ()), OBJ_HLINE , ChartWindowFind (), 0, NormalizeDouble (x, Digits ())); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_COLOR, LineColor); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_SELECTED, false); ObjectSetInteger (0, DoubleToString (x, Digits ()), OBJPROP_WIDTH, 1); Horizontal ++; } ChartRedraw (); } Return (Horizontal); }

Тепер, коли всі базові функції описані, розглянемо порядок їх виклику в OnCalculate ():

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

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 (close, true); if (prev_calculated == 0) {int ErrorCopy = FuncCopy (History); if (ErrorCopy == - 1) {Alert ( "Не вдалося провести копіювання. Дані ще завантажуються."); return (0); } Columns = FuncCalculate (History); int ColorCalculate = FuncColor (Columns); int z = FuncDraw (History); int Turn = FuncTurnArray (Columns); int Horizontal = FuncDrawHorizontal (true); OldPrice = close [0]; } If (fabs ((OldPrice-close [0]) / Tick)> Cell) return (0); return (rates_total); }

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

Для цього була застосована функція OnChartEvent () для обробки подій натискання на клавіші "С" - очищення і "R" - перерисовка. Очищення проводиться шляхом привласнення нульового значення одному з індикаторних буферів. Функція перемальовування графіка являє собою повторення попередніх розрахунків і присвоювання значень індикаторним буферам.

void OnChartEvent (const int id, const long & lparam, const double & dparam, const string & sparam) {if (id == CHARTEVENT_KEYDOWN) {if (lparam == 67) {for (int x = 0; x <Bars (Symbol () , PERIOD_CURRENT); x ++) CandlesBufferOpen [x] = 0; ChartRedraw (); } If (lparam == 82) {int ErrorCopy = FuncCopy (History); if (ErrorCopy == - 1) Alert ( "Не вдалося провести копіювання даних."); Columns = FuncCalculate (History); int ColorCalculate = FuncColor (Columns); int z = FuncDraw (History); int Turn = FuncTurnArray (Columns); int Horizontal = FuncDrawHorizontal (true); }}}

Тепер можна зітхнути з полегшенням, на цьому опис алгоритму та коду індикатора закінчилися, і далі ми приступимо до розгляду деяких патернів графіка "Хрестики-нулики", які формують сигнали для здійснення угод.

стандартні сигнали

Торгівля і аналіз графіків "Хрестики-нулики" здійснюється зазвичай двома способами: по паттернам (моделям) і лініях підтримки і опору. Характерною особливістю останніх є те, що їх побудова здійснюється під кутом 45 градусів (в проектованому індикаторі це не завжди так, з огляду на те що він використовує для побудови стиль японські свічки, які змінюють свій розмір в залежності від розміру основного графіка що може спотворювати кут).

Тепер поговоримо докладніше про самих патернах:

  1. Патерни "Подвійна вершина" і "Подвійне дно".

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

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

    Рис 3. Паттерни "Подвійна вершина" і "Подвійне дно".

  2. Патерни "Потрійна вершина" і "Потрійна підстава".

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

    "Потрійна вершина" утворюється, коли ціна досягає двічі одного цінового діапазону, а на третій раз прориває його вгору, що дає сигнал для здійснення покупки.

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

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

    Рис 4. Паттерни "Потрійна вершина" і "Потрійна підстава".

  3. Патерни "Прорив симетричного трикутника" вгору і вниз.

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

    Якщо прорив відбувається вгору (як показано на малюнку зліва) - це сигнал до покупки, а якщо навпаки вниз - то сигнал до продажу (на малюнку праворуч)

    Рис 5. Паттерни "Прорив симетричного трикутника" вгору і вниз.

  4. Патерни "Бича катапульта" і "Ведмежа катапульта".

    "Катапульти" також нагадують моделі технічного аналізу "Висхідний трикутник" і "Спадний трикутник". Суть їх сигналів схожа - як тільки ціна прориває трикутник в паралельній стороні, то дається сигнал до покупки або продажу. У разі "Бичачої катапульти" прорив відбувається вгору і це сигнал до покупки (рисунок ліворуч), а в разі "Ведмежої катапульти" прорив проходить вниз, і це сигнал до продажу (рисунок праворуч).

    У разі Бичачої катапульти прорив відбувається вгору і це сигнал до покупки (рисунок ліворуч), а в разі Ведмежої катапульти прорив проходить вниз, і це сигнал до продажу (рисунок праворуч)

    Рис 6. Паттерни "Бича катапульта" і "Ведмежа катапульта".

  5. Патерн "45-градусна трендова лінія".

    "45 градусна трендова лінія" створює лінію підтримки або опору, і в разі пробою цієї лінії ми отримуємо сигнал до продажу (як на малюнку справа) або до покупки (як на малюнку зліва).

    45 градусна трендова лінія створює лінію підтримки або опору, і в разі пробою цієї лінії ми отримуємо сигнал до продажу (як на малюнку справа) або до покупки (як на малюнку зліва)

    Рис 7. Паттерн "45-градусна трендова лінія".

Ми розглянули стандартні моделі і сигнали графіка "Хрестики-нулики". Тепер знайдемо деякі з них на графіку індикатора, який був розміщений на початку статті:

Рис 8. Визначення патернів на графіку "Хрестики-нулики".

Висновок

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

Розроблений індикатор хоч і має деякі недоліки, такі як блокове побудова у вигляді прямокутників за місце звичних хрестиків "Х" і налякав "О" і неможливість тестування в "тестер стратегій" (точніше некоректність роботи), але досить точно виробляє побудова графіка.

Хочу також відзначити, що використовуючи цей алгоритм, можна подумати про побудову графіків "Ренк" (Англ. Renko Charts) з невеликою його модифікацією, а також про спільну інтеграції обох графіків в один код з можливістю вибору з меню. Не виключаю і можливість побудови графіка безпосередньо в головному вікні, знову ж таки з незначною модифікацією коду.

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



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

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

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

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

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

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

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

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

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

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