Скачать MetaTrader 5

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

17 октября 2006, 09:19
Shashev Sergei
7
2 428

Введение

Фракталами пользуется практически каждый трейдер, но спросите его, что такое фрактал, и в лучшем случае он ответит, что это индикатор из системы Билла Вильямса. Более продвинутые скажут, что это последовательность из 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. |
//|                                        http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "http://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)
eugenk1
eugenk1 | 21 окт 2006 в 00:37
Народ, если честно, мне само название "фракталы" кажется исключительно неудачным. Просто рынок на самом деле фрактален(в математическом смысле), а этот термин Вильямса вносит дикую путаницу. О математических фракталах я думал в связи с некоторой фрактальной(в математическом смысле) торговой стратегией. Суть такова. Есть таймфреймы от 15 минут до суток - М15, М30, Н1, Н2, Н4, Н12, D1. Фреймов Н2 и Н12 нет в МТ4, но их легко получить склейкой Н1 и Н4. И вообще весь ряд получается склейкой единственного фрейма М15. Идея в том, чтобы торговать одновременно на всех этих фреймах, быть может по разным правилам. Преимущество мыслилось в том, что высокий риск малых фреймов будет компенсироваться бОльшей надежностью на больших. А низкая прибыльность больших фреймов скомпенсируется более высокой прибыльностью на малых. Идея еще не проработана. Просто к слову выкладываю. В порядке "а что если ?"
Nick Revych
Nick Revych | 25 апр 2007 в 13:16
Такой вид представления трудно назвать индикатором - его практически нельзя использовать в советниках.
У меня похожий индикатор - пришлось линии заменить на точки, а фракталы - на горизонтальные линии.
Да и линии : по верхним фракталам только те, что смотрят вниз; по нижним фракталам - только те, что смоьтрят вверх.
Вот как выглядит у меня :
DrShumiloff
DrShumiloff | 22 май 2008 в 12:54
ArtemRG:
Терминологический вопрос. Почему локальные экстремумы на Форекс называют фракталами? С легкой руки Билла Вильямса?

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

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

MQL4 Comments
MQL4 Comments | 24 апр 2010 в 21:17

как доработать индикатор? логично рисовать по вeрхним фракталам только направлeнныe вниз, а по нижним - только ввeрх. И eщe: как у вас получилось рисовать нe лучи, а отрeзки?
Разработка торговых тактик для FOREX Разработка торговых тактик для FOREX

Данная статья поможет начинающему трейдеру при выработке торговых тактик для работы на FOREX.

Десять "ошибок" начинающего трейдера? Десять "ошибок" начинающего трейдера?

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

Визуализация тестирования. Ручная торговля. Визуализация тестирования. Ручная торговля.

Тестирование "ручных" стратегий на истории. Проверьте свой алгоритм торговли, не вникая в тонкости программирования!

Секреты клиентского терминала MetaTrader 4: Библиотека файлов в MetaEditor'е Секреты клиентского терминала MetaTrader 4: Библиотека файлов в MetaEditor'е

При создании собственных программ важное значение имеет редактор кода. Чем больше функций предлагает редактор, тем удобнее и быстрее создаётся программа. Многие программы создаются на основе уже существующего кода. Вы используете индикатор или скрипт, но Вас не всё в нём устраивает? Скачайте код этой программы с нашего сайта и переделайте его под себя.