Трёхмерные графики - профессиональный инструмент анализа рынка

Antoniuk Oleg | 6 декабря, 2006

Введение

Все трейдеры работают с постоянно меняющимися ценами и котировками. Все ищут зависимости и закономерности. Мы исследуем объемы, значения различных индикаторов и еще очень много чего. Не думаю, что нужно вас убеждать, насколько хорош язык MQL 4 для анализа рынка. Вы просто пишете скрипт и делаете вывод по результатам. Обычно анализ проводится по графикам самих котировок или по графикам, которые показывают определенную зависимость двух переменных. Это все, конечно, очень хорошо, но иногда нужно найти связь между тремя переменными и наглядно увидеть, что их связывает. Для этого во всем мире используются трехмерные графики и их анализ. Такой подход экономит ваше время и деньги.

В это статье мы напишем простую библиотеку для создания трехмерных графиков и последующего их просмотра в Microsoft Excel. Мы воспользуемся стандартными возможностями языка MQL 4 для подготовки и экспорта данных в файл формата *.csv.


Что такое формат *.csv ?

Это текстовый файл, в котором размещается последовательность значений разделенных заданным разделителем, в нашем случае точкой с запятой - "; ". Чтобы сформировать таблицу, достаточно записать несколько строк кода. Прелесть этого формата в том, что он легко распознается и интерпретируется в виде таблицы программой Microsoft Excel. А уже в ней мы можем на основе полученных данных легко создать трехмерный график и заняться его анализом.


Библиотека generateCsv.

Для того, чтобы просто и быстро выводить данные, мы создадим библиотеку. Итак, создайте новую библиотеку и вставьте приведенный код, сохраните под названием generateCsv.mq4 в папке "...MetaTrader\experts\libraries". После этого скомпилируйте библиотеку.

//+------------------------------------------------------------------+
//|                                                  generateCsv.mq4 |
//|         Copyright © 2006, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
#property library
 
//+------------------------------------------------------------------+
//| PrepareString                                                    |
//+------------------------------------------------------------------+
 
string PrepareString(string s)
  {
   bool exit = false;
   int index = 0;
   string str = s;
   
   while(!exit)
     {
       index = StringFind(str, ".", index);
      
       if(index > -1)
           str = StringSetChar(str, index, ',');
       else
           exit = true;
     }
   return(str);
  }
 
 
//+------------------------------------------------------------------+
//| GenerateCsv                                                      |
//+------------------------------------------------------------------+
int GenerateCsv(string fileName, int arraySizeX, int arraySizeY,
                double arrayIndexX[], double arrayIndexY[], double arrayZ[][])
  {
   int handle = FileOpen(fileName, FILE_CSV|FILE_WRITE, ' '), x, y;
   string str;
   
   if(handle1)
     {
       Print("Error:", GetLastError());
       return(handle);
     }
   else
     {
       str = ";";
       for(x = 0; x < arraySizeX; x++)
         {
           str = str + arrayIndexX[x];
           str = str + ";";         
         }
       FileWrite(handle,PrepareString(str));
      
       for(y = 0; y < arraySizeY; y++)
         {
           str = "";   
           str = str + arrayIndexY[y] + ";";
         
           for(x = 0; x < arraySizeX; x++)
             {
               str = str + arrayZ[x,y];
               str = str + ";";         
             }
           FileWrite(handle, PrepareString(str));
         }
     }
      
   FileClose(handle);   
   return(handle);
  }

Теперь создайте новый заголовочный файл для доступа к функциям библиотеки под названием generateCsv.mqh, вставте туда приведённый код и сохраните в папке "...MetaTrader\experts\include".

//+------------------------------------------------------------------+
//|                                                  generateCsv.mqh |
//|         Copyright © 2006, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Antonio Banderass. All rights reserved"
#property link "banderassa@ukr.net"
 
#import "generateCsv.ex4"
 
string PrepareString(string s);
int GenerateCsv(string fileName, int arraySizeX, int arraySizeY,
double arrayIndexX[], double arrayIndexY[],double arrayZ[][]);

Эта простая библиотека состоит из двух функций. Рассмотрим назначение каждой из них. Первая функция PrepareString предназначена для замены в строке точек на запятые. Дело в том, что при записи данных в файл с помощью стандартной функции FileWrite используется точка при разделении целой и дробной части числа. Это является недопустимым в нашем случае, так как Microsoft Excel распознаёт дробные числа только в том случае, если они разделены запятой. Поэтому при выводе данных в файл *.csv производится вызов этой функции в теле функции GenerateCsv. Единственный параметр функции является строка, в которой следует заменить точки на нули. Возвращаемое значение - новая строка, которая уже без точек. Помните, что эту функцию не нужно нигде вызывать, это делает вторая функция автоматически, когда нужно.

Функция GenerateCsv служит для вывода данных в формате *.csv в файл. Рассмотрим ее параметры:

int GenerateCsv(string fileName, int arraySizeX, int arraySizeY,
                double arrayIndexX[], double arrayIndexY[], double arrayZ[][]);             

Чтобы понять предназначение каждого параметра, взгляните на рисунок:

Итак, все что вам нужно иметь, чтобы вывести данные, это три массива значений для каждой переменной. Теперь давайте посмотрим, как все это работает.


Использование библиотеки generateCsv.

Создайте новый скрипт с именем 3dGraphicOut и вставьте туда приведенный код.

//+------------------------------------------------------------------+
//|                                                 3dGraphicOut.mq4 |
//|         Copyright © 2006, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
 
#include <generateCsv.mqh>
 
#define ARRAY_SIZE_X 16
#define ARRAY_SIZE_Y 16
 
//+------------------------------------------------------------------+
//| start                                                            |
//+------------------------------------------------------------------+
int start()
  {
  
   int x,y;
   
   double arrayIndexX[ARRAY_SIZE_X];
   double arrayIndexY[ARRAY_SIZE_Y];
   double arrayZ[ARRAY_SIZE_X,ARRAY_SIZE_Y];
   
   
   for(x=0;x<ARRAY_SIZE_X;x++)
      arrayIndexX[x]=x/10.0; 
      
   for(y=0;y<ARRAY_SIZE_Y;y++)
      arrayIndexY[y]=y/10.0;
   
   for(x=0;x<ARRAY_SIZE_X;x++)
      for(y=0;y<ARRAY_SIZE_Y;y++)
         arrayZ[x,y]=MathSin(arrayIndexX[x]+arrayIndexY[y]);
 
   GenerateCsv("test.csv",ARRAY_SIZE_X,ARRAY_SIZE_Y,arrayIndexX,arrayIndexY,arrayZ); 
   return(0);
  }

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

#include <generateCsv.mqh>

Подключаем библиотеку generateCsv.

#define ARRAY_SIZE_X 16
#define ARRAY_SIZE_Y 16

Здесь мы определяем размерность таблицы для вывода: ARRAY_SIZE_X - ширина таблицы, ARRAY_SIZE_Y - высота.

int x,y;

Это два индекса массивов. Так как они используются неоднократно, то я их вынес из тела циклов.

double arrayIndexX[ARRAY_SIZE_X];

Это массив значений первой переменной. Допустим, вы исследуете влияние двух индикаторов на прибыль. Тогда значения первого индикатора будут размещены в этом массиве. Помните, что нужно начинать с какого-то начального значения, например, с нуля и постепенно увеличивать его с определенным шагом, например, 0,5.

double arrayIndexY[ARRAY_SIZE_Y];

Значения второго индикатора должны быть размещены в этом массиве. Также выберите подходящее начальное значение и шаг.

double arrayZ[ARRAY_SIZE_X,ARRAY_SIZE_Y];

А здесь уже должны быть значения прибыли в зависимости от значений индикаторов. Еще раз посмотрите на приведенный выше рисунок, что бы понять, что это за массивы.

Обратите внимание, что тип массивов - double. Это сделано для универсальности. Если вы используете в качестве значений элементов массива целые числа (int), то ничего страшного в этом нет, ведь в MQL 4 есть неявное преобразование типов.

for(x = 0; xARRAY_SIZE_X; x++)
  {
    // arrayIndexX[x]= ... ;
  }

В этом блоке заполняем массив первой переменной значениями, помните, что они должны увеличиваться с определенным шагом.

for(y = 0; y < ARRAY_SIZE_Y; y++)
   {
      // arrayIndexY[y]= ... ;
   }

Тоже самое для второй переменной.

for(x = 0; x < ARRAY_SIZE_X; x++)
   {
     for(y = 0; y < ARRAY_SIZE_Y; y++)
       {
         // arrayZ[x,y]= ... ;
       }
   }

А это самое интересное место во всем шаблоне: заполняем двухмерный массив значениями в зависимости от двух других переменных.

GenerateCsv("test.csv",ARRAY_SIZE_X,ARRAY_SIZE_Y,arrayIndexX,arrayIndexY,arrayZ); 

И наконец выводим данные в файл для дальнейшего анализа в Microsoft Exсel. Теперь сохраните этот шаблон для дальнейшего использования.


Простейший пример.

Рассмотрим простейший пример использования библиотеки. Я специально не писал пример связаный с торговлей, чтобы сделать код максимально простым и доступным.

//+------------------------------------------------------------------+
//|                                                 3dGraphicOut.mq4 |
//|         Copyright © 2006, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
 
#include <generateCsv.mqh>
 
#define ARRAY_SIZE_X 16
#define ARRAY_SIZE_Y 16
 
//+------------------------------------------------------------------+
//| start                                                            |
//+------------------------------------------------------------------+
int start()
  {
   int x,y;
 
   double arrayIndexX[ARRAY_SIZE_X];
   double arrayIndexY[ARRAY_SIZE_Y];
   double arrayZ[ARRAY_SIZE_X,ARRAY_SIZE_Y];
 
 
   for(x=0;x<ARRAY_SIZE_X;x++)
      arrayIndexX[x]=x/10.0;
 
   for(y=0;y<ARRAY_SIZE_Y;y++)
      arrayIndexY[y]=y/10.0;
 
   for(x=0;x<ARRAY_SIZE_X;x++)
      for(y=0;y<ARRAY_SIZE_Y;y++)
         arrayZ[x,y]=MathSin(arrayIndexX[x]+arrayIndexY[y]);
 
   GenerateCsv("test.csv",ARRAY_SIZE_X,ARRAY_SIZE_Y,arrayIndexX,arrayIndexY,arrayZ);
 
   return(0);
  }

Сохраните тестовый скрипт, откомпилируйте и запустите в терминале. Теперь загляните в папку "...MetaTraider\experts\files\", там появится файл "test.csv", откройте его с помощью Microsoft Excel. Файл будет преобразован в двухмерную таблицу, как показано ниже:

Теперь выделите все ячейки (CTRL+A) и зайдите в Insert -> Chart (ALT+I,H):

После этого выберите Chart Type -> Surface, Chart sub-type -> 3D-Surface и нажмите Finish:

После этих действий появится трёхмерный график:


Заключение.

Вам стал доступен удобный инструмент для быстрого экспортирования данных из торгового терминала MetaTrader в программу Microsoft Excel для быстрого построения трёхмерных графиков и их дальнейшего анализа. Теперь вы имеете возможность анализировать зависимости и закономерности валютного рынка Forex между тремя переменными одновременно. Попробуйте проанализировать трёхмерные гистограммы зависимости прибыли от таких параметров как TakeProfit и StopLoss или посмотрите как выглядит график зависимости объёмов от текущего дня недели и часа. Думаю вы найдёте много интересных и полезных закономерностей.