English 中文 Español Deutsch 日本語 Português
Построение фрактальных линий

Построение фрактальных линий

MetaTrader 4Примеры | 17 октября 2006, 09:19
5 875 7
Shashev Sergei
Shashev Sergei

Введение

Фракталами пользуется практически каждый трейдер, но спросите его, что такое фрактал, и в лучшем случае он ответит, что это индикатор из системы Билла Вильямса. Более продвинутые скажут, что это последовательность из 5 баров, в которых если High среднего бара выше остальных в последовательности, то это Up фрактал, а если Low среднего бара ниже остальных, то это Down фрактал. Как говорится – “Вот и все, что я могу сказать о войне”.

Коротко о фракталах, в частности, об их природе и использовании говорится в книге Билла Вильямса “Новые измерения биржевой торговли”, кое-что есть в статье Чекулаева «Фракталы». Математически фракталы неплохо описаны в книге Ширяева – «Основы стохастической математики».

Использование фракталов

Можно выделить два вида пробития фракталов – простое, когда цена поднимается выше Up фрактала (ниже Down фрактала), причем лучше дождаться цены закрытия и открывать позицию на открытии следующего бара.


Соответствующие Buy и Sell фракталы отмечены стрелками на рисунке. Мы рассмотрели простое пробитие фрактала. В сложном пробитии используются 2 фрактала – последний и предпоследний. Через них проводится прямая, которая должна быть пробита ценой закрытия.



Места входа при пробитии фрактальной линии обозначены голубой и красненькой стрелочками. Лучше разобраться во фрактальной идеологии нам поможет язык MQL4.


Сформулируем задачу для тестирования фракталов.

  • нарисовать фракталы buy/sell;
  • нарисовать горизонтальные уровни пробития;
  • нарисовать фрактальные линии;
  • предполагаемые места входа пометить стрелочками.

Нарисовать фракталы buy/sell

Самая элементарная часть. Учитывая еще и наличие индикатора iFractal на MQL4 (в Omege этот индикатор сам писал и из-за ее особенностей очень запарился). Примеры написания этого индикатора можно посмотреть в Code Base.

Горизонтальные уровни пробития

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

ObjectCreate("SimpleUp"+Up,OBJ_TREND,0,bufUpDate[Up],
             bufUpPrice[Up],Time[i-1],bufUpPrice[Up]);
ObjectSet("SimpleUp"+Up,OBJPROP_COLOR,Aqua);
ObjectSet("SimpleUp"+Up,OBJPROP_RAY,True);

Фрактальные линии

Казалось бы простой выход – прорисовка трендовых линий через 2 точки. Делаем линию лучом и ждем пробития. Но на деле сравнить цену закрытия и значение цены на фрактальной линии не представилось возможным, так как функция ObjectGet может вернуть только значения точек, которые образовали фрактальную линию. Что же делать?

Вспомнить аналитическую геометрию. У нас есть 2 точки, значит имеем уравнение прямой, а по уравнению прямой, зная координату времени, элементарно получаем значение цены. Каноническое уравнение прямой выглядит так:


Вместо х и у подставляем цены и время. Реализация представлена в функции LevelCalculate, которая рассчитывает уровень пробоя, а заодно и определяет новые координаты фрактальной линии, которые устанавливаются с помощью функции ObjectSet.

ObjectCreate("LineUp"+Up,OBJ_TREND,0,bufUpDate[Up],
             bufUpPrice[Up],bufUpDate[Up-1],bufUpPrice[Up-1]); 
ObjectSet("LineUp"+Up,OBJPROP_COLOR,Blue);
ObjectSet("LineUp"+Up,OBJPROP_RAY,False);

Расстановка стрелок

В цикле строим все необходимые линии и сравниваем с текущими ценами. Если пробой уровня простой , то ставим желтую стрелочку. Если пробой фрактальной линии, то на Buy – синюю, а на Sell – красную.

Все это реализовано в качестве индикатора FractalLines.mq4.

//+------------------------------------------------------------------+
//|                                                 FractalLines.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
 
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
//---- input parameters
extern int       lines=5;  //Количество видимых фрактальных линий
extern int       MaxFractals=10000; // :)
extern bool       ShowHorisontalLines=true;
extern bool       ShowFractalLines=true; 
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//--- my variables
double bufUpPrice[10000];  //массив цен Up фракталов
double bufUpDate[10000];   //массив дат Up фракталов
double bufDownPrice[10000];   //массив цен Down фракталов
double bufDownDate[10000]; //массив дат Down фракталов
int Up = 0; //счетчик Up фракталов
int Down = 0;  //счетчик Down фракталов
 
//Функция считает значение цены пробития фрактальной линии по простейшим
//уравниниям аналитической геометрии
double LevelCalculate(double Price1, double Time1, double Price2, 
                     double Time2, double NewTime)
{
   double level;
   if (Time2!=Time1)// На всякий случай, чтобы не было деления на 0.
   {
      level=(NewTime-Time1)*(Price2-Price1)/(Time2-Time1)+Price1;
   }
   else
   { 
      return(Price2);
   }
   return(level);
}
 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,217);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,218);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexEmptyValue(1,0.0);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//---- последний посчитанный бар будет пересчитан   
   if(counted_bars > 0) 
       counted_bars--;
   int limit = Bars - counted_bars;
// Пожалуй, расставим стрелки в момент пробития фрактальных линий, 
// оценим эффективность
 // Идея позаимствована у Rosha, надеюсь, не обидится :)    
  string arrowName; // здесь будут назначаться уникальное имя объекта-стрелки
  
  //Номер пробитого фрактала
  //Пробитие фрактальной линии
  int FractalUp = 0;
  int FractalDown = 0;
  //Простое пробитие фрактала
  int SimpleFractalUp = 0;
  int SimpleFractalDown = 0;
  
  double BuyFractalLevel = 0;  //уровень пробития фрактальной линии Up
  double SellFractalLevel = 0; //уровень пробития фрактальной линии Down
  double buf = 0; // буферной значение наличие фрактала, если 0, то фрактала нет
 
//---- основной цикл       
   for(int i = limit; i>0; i--)
   {   
   
       //Рисуем простые фрактальные уровни
       
       //Определим текущие фрактальные уровни 
 
         BuyFractalLevel=LevelCalculate(bufUpPrice[Up],bufUpDate[Up],
                   bufUpPrice[Up-1],bufUpDate[Up-1],Time[i]);
         //Двигаем вторую координату фрактальной прямой Up                              
         ObjectSet("LineUp"+Up,OBJPROP_TIME1,Time[i]);
         ObjectSet("LineUp"+Up,OBJPROP_PRICE1,BuyFractalLevel); 
         SellFractalLevel=LevelCalculate(bufDownPrice[Down],
                          bufDownDate[Down],bufDownPrice[Down-1],
                          bufDownDate[Down-1],Time[i]);
         //Двигаем вторую координату фрактальной прямой Down                                
         ObjectSet("LineDown"+Down,OBJPROP_TIME1,Time[i]);
         ObjectSet("LineDown"+Down,OBJPROP_PRICE1,SellFractalLevel);
         
      //Ищем простое пробитие
         if (Close[i]>ObjectGet("SimpleUp"+Up,OBJPROP_PRICE1)&&
                          (Up>SimpleFractalUp))
         {
            arrowName="SimleUpArrow"+Up;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         Low[i-1]-Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,241);
            ObjectSet(arrowName,OBJPROP_COLOR,Yellow);
            SimpleFractalUp=Up;             
         }
         
         if (Close[i]<ObjectGet("SimpleDown"+Down,OBJPROP_PRICE1)&&
                          (Down>SimpleFractalDown))
         {
            arrowName="SimleUpArrow"+Down;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         High[i-1]+Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,242);
            ObjectSet(arrowName,OBJPROP_COLOR,Yellow);
            SimpleFractalDown=Down;             
         }                                                                                                                          
 
      //Ищем сложное пробитие
        if ((Close[i]>BuyFractalLevel)&&(Up>FractalUp)) 
         {
            //Ставим стрелочку вверх
            arrowName="UpArrow"+Up;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         Low[i-1]-Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,241);
            ObjectSet(arrowName,OBJPROP_COLOR,Blue);
            FractalUp=Up;        
         }
                                          
        if ((Close[i]<SellFractalLevel)&&(Down>FractalDown))
         {
            //Ставим стрелочку вверх
            arrowName="DownArrow"+Down;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         High[i-1]+Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,242);
            ObjectSet(arrowName,OBJPROP_COLOR,Red); 
            FractalDown=Down;       
         }
        //Рисуем сам фрактал  Up
        ExtMapBuffer1[i] = iFractals(NULL, 0, MODE_UPPER, i);
        
        //Если он есть, то заносим его в массив фракталов
        buf = iFractals(NULL, 0, MODE_UPPER, i);
        if (buf!=0)
        {
            Up++;
            bufUpPrice[Up]=iFractals(NULL, 0, MODE_UPPER, i);
            bufUpDate[Up]=Time[i];
            //Текущий уровень пробития фрактала - сам фрактал
            BuyFractalLevel=bufUpPrice[Up];
            
            if (Up>1)
            
            {
               //Простой фрактал
               ObjectCreate("SimpleUp"+Up,OBJ_TREND,0,bufUpDate[Up],
                   bufUpPrice[Up],Time[i-1],bufUpPrice[Up]);
      ObjectSet("SimpleUp"+Up,OBJPROP_COLOR,Aqua);
      ObjectSet("SimpleUp"+Up,OBJPROP_RAY,True);   
               //Чертим фрактальные линии по 2 координатам
               ObjectCreate("LineUp"+Up,OBJ_TREND,0,bufUpDate[Up],
                  bufUpPrice[Up],bufUpDate[Up-1],bufUpPrice[Up-1]); 
      ObjectSet("LineUp"+Up,OBJPROP_COLOR,Blue);
      ObjectSet("LineUp"+Up,OBJPROP_RAY,False);
               //Удаляем устаревшии линии
               if (Up>lines+1)
               {
                  ObjectDelete("LineUp"+(Up-lines));
                  ObjectDelete("SimpleUp"+(Up-lines));                  
               }
            }     
        }
         //Аналогичный блок, но на Down фракталы
        ExtMapBuffer2[i] = iFractals(NULL, 0, MODE_LOWER, i);
        buf = iFractals(NULL, 0, MODE_LOWER, i);    
        if (buf!=0)
        {
            Down++;
            bufDownPrice[Down]=iFractals(NULL, 0, MODE_LOWER, i);
            bufDownDate[Down]=Time[i];
            SellFractalLevel=bufDownPrice[Down];
                                         
            if (Down>1)
            
            {
               ObjectCreate("SimpleDown"+Down,OBJ_TREND,0,bufDownDate[Down],
                   bufDownPrice[Down],Time[i-1],bufDownPrice[Down]);        
               ObjectSet("SimpleDown"+Down,OBJPROP_COLOR,LightCoral);
               ObjectSet("SimpleDown"+Down,OBJPROP_RAY,True);
                                  
               ObjectCreate("LineDown"+Down,OBJ_TREND,0,
                            bufDownDate[Down],bufDownPrice[Down],
                            bufDownDate[Down-1],bufDownPrice[Down-1]);        
               ObjectSet("LineDown"+Down,OBJPROP_COLOR,Red);
               ObjectSet("LineDown"+Down,OBJPROP_RAY,False);
               if (Down>lines+1)
               {
                  ObjectDelete("LineDown"+(Down-lines));
                  ObjectDelete("SimpleDown"+(Down-lines));
               }            
            }
     
        }           
        if (!ShowHorisontalLines)
        {   
            ObjectDelete("SimpleDown"+Down);              
            ObjectDelete("SimpleUp"+Up);                
        }
        if (!ShowFractalLines)
        {
            ObjectDelete("LineDown"+Down);        
            ObjectDelete("LineUp"+Up);
        }          
     }   
//----
   return(0);
  }
//+----------------------------------------------------------------- 

Старые линии необходимо удалять, а то чарт станет палитрой. В индикаторе предусмотрена еще пара дополнительных настроек, таких как видимость различных линий и количество линий. Результат работы индикатора приведен ниже.





Незаменимая вещь для любителей фракталов!

Прикрепленные файлы |
FractalLines.mq4 (9.4 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (7)
eugenk1
eugenk1 | 21 окт. 2006 в 00:37
Народ, если честно, мне само название "фракталы" кажется исключительно неудачным. Просто рынок на самом деле фрактален(в математическом смысле), а этот термин Вильямса вносит дикую путаницу. О математических фракталах я думал в связи с некоторой фрактальной(в математическом смысле) торговой стратегией. Суть такова. Есть таймфреймы от 15 минут до суток - М15, М30, Н1, Н2, Н4, Н12, D1. Фреймов Н2 и Н12 нет в МТ4, но их легко получить склейкой Н1 и Н4. И вообще весь ряд получается склейкой единственного фрейма М15. Идея в том, чтобы торговать одновременно на всех этих фреймах, быть может по разным правилам. Преимущество мыслилось в том, что высокий риск малых фреймов будет компенсироваться бОльшей надежностью на больших. А низкая прибыльность больших фреймов скомпенсируется более высокой прибыльностью на малых. Идея еще не проработана. Просто к слову выкладываю. В порядке "а что если ?"
Mykola Revych
Mykola Revych | 25 апр. 2007 в 13:16
Такой вид представления трудно назвать индикатором - его практически нельзя использовать в советниках.
У меня похожий индикатор - пришлось линии заменить на точки, а фракталы - на горизонтальные линии.
Да и линии : по верхним фракталам только те, что смотрят вниз; по нижним фракталам - только те, что смоьтрят вверх.
Вот как выглядит у меня :
DrShumiloff
DrShumiloff | 22 мая 2008 в 12:54
ArtemRG:
Терминологический вопрос. Почему локальные экстремумы на Форекс называют фракталами? С легкой руки Билла Вильямса?

Фрактал, по одной из геометических трактовок, есть статистически самоподобная фигура. Для рынка такой самоподобной фигурой, обнаруживаемой при любом масштабе, является волна Элиота.

Волна Элиота содержит 4 или 5 локальных максимумов, третий, как правило, выше всех других. Сводя ее к предельно простому графическому примитиву, получаем фрактал Вильямса.

DeveloperMQL
DeveloperMQL | 11 авг. 2009 в 20:33
[Удален] | 24 апр. 2010 в 21:17

как доработать индикатор? логично рисовать по вeрхним фракталам только направлeнныe вниз, а по нижним - только ввeрх. И eщe: как у вас получилось рисовать нe лучи, а отрeзки?
Визуализация тестирования. Ручная торговля. Визуализация тестирования. Ручная торговля.
Тестирование "ручных" стратегий на истории. Проверьте свой алгоритм торговли, не вникая в тонкости программирования!
Разработка торговых тактик для FOREX Разработка торговых тактик для FOREX
Данная статья поможет начинающему трейдеру при выработке торговых тактик для работы на FOREX.
Секреты клиентского терминала MetaTrader 4: Библиотека файлов в MetaEditor Секреты клиентского терминала MetaTrader 4: Библиотека файлов в MetaEditor
При создании собственных программ важное значение имеет редактор кода. Чем больше функций предлагает редактор, тем удобнее и быстрее создаётся программа. Многие программы создаются на основе уже существующего кода. Вы используете индикатор или скрипт, но Вас не всё в нём устраивает? Скачайте код этой программы с нашего сайта и переделайте его под себя.
Десять "ошибок" начинающего трейдера? Десять "ошибок" начинающего трейдера?
В статье обосновывается подход к построению торговой системы как последовательности открытия и закрытия взаимосвязанных ордеров в зависимости от складывающейся обстановки - цены и текущего значения прибыли/убытка каждого ордера, а не только и не столько от традиционных "сигналов". Приведен пример конкретной реализации такой простейшей торговой системы.