Макрос подсчета «прибыльных» параметров
технического индикатора MACD
Суть: прогоняется прямым перебором параметры индикатора MACD и считается Профит/Лосс длинных и коротких позиций.
//+--------------------------------------------------------------------------
//+------------------------------------------------------------------+
//|
MACD_new.mq4 |
//|
Shumi
|
//| http://apsheronsk.bozo.ru // sneveld@yandex.ru
|
//+------------------------------------------------------------------+
#property copyright "Shumi"
#property link "http://apsheronsk.bozo.ru // sneveld@yandex.ru"
#include <stdlib.mqh>
double UP[],
DOWN[]; // массивы соответсвенно по количеству свечек MACD вниз и вверх
double UP_PROFIT[], DOWN_PROFIT[]; // счетчик, сколько было профитных
при MACD покупка и MACD продажа (если брать
четко Цена при открытии MACD-интервала
и закрытии MACD-интервала)
double UP_MONEY[], DOWN_MONEY[]; // количество денег (если брать четко при открытии и
закрытии)
double UP_HIGH[], DOWN_LOW[]; // позиции минимальных и максимальных точек в данных
интервалах
double UP_HIGH_PROFIT[], DOWN_LOW_PROFIT[];
// количество профитных позиций от начала MACD-интервала до наивысшей и
наименьшей точек
int array_size
= 50, Hist; //размер массивов UP DOWN
double spread;
double threshold = 0.98; // порог по Profit для вывода в csv
int min_gravity = 5; // начальная
точка для интервала центра тяжести
int max_gravity = 25; //конечная
точка для интервала центра тяжести
//+------------------------------------------------------------------+
int start()
{
Alert("Time start = ", TimeMinute(TimeLocal()), ":", TimeSeconds(TimeLocal()));
int file = FileOpen("macd1.csv",FILE_CSV|FILE_WRITE,
';');
int i,
j, sell, buy;
double tmp1, tmp2;
int SuccessUP,
SuccessDOWN;
int cur; // текущая позиция
индикатора -1 - продавать; 1 - покупать; 0 - закрывать
int prev; // предыдущая
позиция индикатора 0 - продавать, 1 - покупать; 0 - закрывать
double signal, main, sum5_up, sum5_down, pos_up, pos_down;
string str1, str2, str3, str4, str5, str6, str7, str8;
spread
= MarketInfo(Symbol(),MODE_SPREAD)*MathPow(10,(-1)*MarketInfo(Symbol(),MODE_DIGITS));
// спред
Hist = iBars(Symbol(),Period());
//Hist
= 500; // если тестово проверять, то на небольшой
истории
for(int k=23;k<40;k++) // цикл в iMACD по большой EMA
{
Alert("k=", k);
for(int h=7;h<k-2;h++) // цикл в iMACD по малой EMA
{
for(int u=5;u<h-2;u++) // цикл по сигнальной линии
{
//Alert("k=", k, " h= ", h, " u=
", u);
//k=26;h=12;u=9; // если тестово проверять -
правильно ли берутся интервалы, то здесь раскомментировать
и в конце всех главных циклов поставить break
InitUpDown();
prev = 0; cur = 0; sell = 0; buy =
0;
for(i=Hist-1;i>0;i--)
{
main = iMACD(Symbol(),Period(),h,k,u,PRICE_CLOSE,MODE_MAIN,i);
signal = iMACD(Symbol(),Period(),h,k,u,PRICE_CLOSE,MODE_SIGNAL,i);
tmp1=0; tmp2=0;
prev = cur; // смещение
//
main < signal - продавать
if(main < signal) {cur = -1;}
// покупать
else if (main > signal) {cur = 1;}
// ровно
else if (main == signal) {cur = 0;}
// тенденция вверх
if(cur == 1 && prev == 1)
{
buy++;
if(sell > 0) {/*CloseDOWN(sell,
i);*/} // не находит
sell=0;
}
// снизу вверх
else if(cur == 1 && prev
== -1)
{
buy++;
if(sell > 0) {CloseDOWN(sell, i);}
sell=0;
}
// тенденция вниз
else if(cur == -1 && prev
== -1)
{
sell++;
if(buy > 0) {CloseUP(buy, i);}
buy=0;
}
// сверху вниз
else if(cur == -1 && prev
== 1)
{
sell++;
if(buy > 0) {CloseUP(buy, i);}
buy=0;
}
// если ноль - закрываем позиции продаж и
покупки
else if(prev == 0 && cur == 1) // такая комбинация
не встречается
{
buy++;
if(sell > 0) {/*CloseDOWN(sell,
i);*/} // не находит
sell = 0;
}
else if (prev == 0 && cur
== -1)
{
sell++;
if(buy > 0) {CloseUP(buy, i);}
buy = 0;
}
else if (cur == 0) // такая комбинация вообще не встречается
{
if(sell > 0) {CloseDOWN(sell, i);} sell=0; // не находит
if(buy > 0) {CloseUP(buy, i);} buy=0;
}
}
str1=""; str2=""; str3="";str4="";str5="";str6="";str7="";str8="";
SuccessUP = 0; SuccessDOWN = 0;
tmp1 =
0; tmp2 = 0;
sum5_up=0; sum5_down=5; pos_up=0; pos_down=0;
for(int y=0;y<array_size;y++)
{
tmp1 = tmp1 + UP[y]; // общее количество mACD
вверх
tmp2 = tmp2 + DOWN[y];
if(y < 21)
{
if (UP[y] > threshold) {SuccessUP
= 1;}
if (DOWN[y] > threshold) {SuccessDOWN
= 1;}
}
}
if((SuccessUP
== 1) || (SuccessDOWN
== 1)) // если количество успешных комбинаций больше порога
{
for(y=0;y<array_size;y++)
{
if(y > min_gravity && y
< max_gravity) // считаем
точки тяжести
{
if(tmp1 != 0)
{
sum5_up = sum5_up + y*UP[y]/tmp1; // центр тяжести по общему
проценту
pos_up = pos_up + UP_HIGH[y]/tmp1;
// центр тяжести по позиции максимума macd - интервала
}
if(tmp2 != 0)
{
sum5_down = sum5_down + DOWN[y]/tmp2;
pos_down = pos_down
+ DOWN_LOW[y]/tmp2;
}
}
if(tmp1 != 0) { str1 = str1 + DoubleToStr(UP[y]/tmp1,3)
+ ";";}
else {str1 = str1 + ";";}
if(UP[y] != 0)
{
str3 = str3 + DoubleToStr(UP_PROFIT[y]/UP[y],3) + ";"; // процент прибыльных
str5 = str5 + DoubleToStr(UP_HIGH[y]/UP[y],3) + ";";
str7 = str7 + DoubleToStr(UP_HIGH_PROFIT[y]/UP[y],3) + ";";
}
else
{
str3 = str3 + "0;";
str5 = str5 + "0;";
str7 = str7 + "0;";
}
if(tmp2 != 0) {str2 = str2 + DoubleToStr(DOWN[y]/tmp2,3)
+ ";";}
else {str2 = str2 + ";";}
if(DOWN[y] != 0)
{
str4 = str4 + DoubleToStr(DOWN_PROFIT[y]/DOWN[y],3) + ";";
str6 = str6 + DoubleToStr(DOWN_LOW[y]/DOWN[y], 3) + ";";
str8 = str8 + DoubleToStr(DOWN_LOW_PROFIT[y]/DOWN[y],3)
+ ";";
}
else
{
str4 = str4 + "0;";
str6 = str6 + "0;";
str8 = str8 + "0;";
}
}
//int err = GetLastError();
//Alert(ErrorDescription(err),
" ", tmp1, " ", tmp2);
FileWrite(file,
k, h, u, tmp1, str1, DS(sum5_up,3)); // вывод столбиков MACD вверх
FileWrite(file, k, h, u,
"up", str3);
// вывод процентов прибыльных
FileWrite(file, k, h, u, "up_high", str5, DS(pos_up,3)); // вывод
процентов прибыльных
//FileWrite(file,
k, h, u, "up_prof", str7); // вывод процентов прибыльных
FileWrite(file,
k, h, u, tmp2, str2, DS(sum5_down,3)); // вывод столбиков MACD вниз
FileWrite(file,
k, h, u, "down", str4); // вывод столбиков MACD вверх
FileWrite(file,
k, h, u, "down_low", str6, DS(pos_down,3));
// вывод столбиков MACD вверх
//FileWrite(file,
k, h, u, "down_prof", str8); // вывод столбиков MACD вверх
}
}}}
FileClose(file);
Alert("Закончили
обработку данных");
Alert("Time end = ", TimeMinute(TimeLocal()),
":", TimeSeconds(TimeLocal()));
return(0);
}
//+------------------------------------------------------------------+
void CloseDOWN(int num, int pos)
{
// num - номер в
массиве DOWN, то есть сколько была длина интервала MACD. pos - номер i в основном счетчике цикла
// инкрментируем счетчики DOWN
//ObjectCreate(DoubleToStr(pos+num+1,1), OBJ_VLINE,0,Time[pos+num+1],Close[pos+num+1]);
// линия начала минусового MACD
//ObjectSet(DoubleToStr(pos+num+1,1),OBJPROP_COLOR, Red);
//ObjectCreate(DoubleToStr(pos+1,1), OBJ_VLINE,0,Time[pos+1],Close[pos+1]);
// линия окончания минусового MACD
//ObjectSet(DoubleToStr(pos+1,1),OBJPROP_COLOR, Blue);
if(num > array_size) {num = array_size - 2;}
DOWN[num]++;
double
delta = iOpen(Symbol(),Period(),pos+num+1) - iClose(Symbol(),Period(),pos+1) + spread;
if(delta < 0) {DOWN_PROFIT[num]++;}
DOWN_MONEY[num] = DOWN_MONEY[num] + delta;
//
ищем минимальное значение цены в данном промежутке
int
lowest = iLowest(Symbol(), Period(), MODE_LOW, num
,pos);
delta
= iOpen(Symbol(),Period(), pos+num+1) - iLow(Symbol(),Period(),lowest) + spread;
//ObjectCreate(DoubleToStr(pos + num + 1 - lowest,1),
OBJ_VLINE,0,Time[lowest],Close[lowest]); // линия минимального значения минусового MACD
//ObjectSet(DoubleToStr(pos + num + 1 - lowest,1),OBJPROP_COLOR,
Green);
//
Расстояние до минимума от первого бара меньше Macd, до минимального
бара в интервале включительно
DOWN_LOW[num] = DOWN_LOW[num]
+ (pos+num+1-lowest); // через сколько баров будет
минимум, потом вычисляем среднее
if(delta < 0) {DOWN_LOW_PROFIT[num]++;}
}
//+------------------------------------------------------------------+
void CloseUP(int num, int pos)
{
if(num > array_size) {num = array_size - 2;}
//ObjectCreate(DoubleToStr(pos+num+1,1),
OBJ_VLINE,0,Time[pos+num+1],Close[pos+num+1]); // линия
начала плюсового MACD
//ObjectSet(DoubleToStr(pos+num+1,1),OBJPROP_COLOR, Red);
//ObjectCreate(DoubleToStr(pos+1,1), OBJ_VLINE,0,Time[pos+1],Close[pos+1]);
// линия окончания плюсового MACD
//ObjectSet(DoubleToStr(pos+1,1),OBJPROP_COLOR, Blue);
UP[num]++;
double
delta = iClose(Symbol(),Period(),pos+1) - iOpen(Symbol(),Period(),pos+num+1) - spread;
if(delta > 0) {UP_PROFIT[num]++;}
UP_MONEY[num] = UP_MONEY[num] + delta;
//
ищем максимальное значение цены в данном промежутке
int
highest = iHighest(Symbol(), Period(), MODE_HIGH,
num, pos);
delta
= iHigh(Symbol(),Period(),highest) - iOpen(Symbol(),Period(),pos+num+1) - spread;
//ObjectCreate(DoubleToStr(pos + num + 1 - highest,1),
OBJ_VLINE,0,Time[highest],Close[highest]); // линия минимального значения минусового MACD
//ObjectSet(DoubleToStr(pos + num + 1 - highest,1),OBJPROP_COLOR,
Green);
UP_HIGH[num] = UP_HIGH[num] + (pos+num+1-highest); // через сколько баров
будут максимум, потом вычиляем среднее
if(delta > 0) {UP_HIGH_PROFIT[num]++;}
}
//+------------------------------------------------------------------+
void InitUpDown()
{
ArrayResize(UP,
array_size);
ArrayResize(DOWN,
array_size);
ArrayResize(UP_PROFIT,
array_size);
ArrayResize(DOWN_PROFIT,
array_size);
ArrayResize(UP_MONEY,
array_size);
ArrayResize(DOWN_MONEY,
array_size);
ArrayResize(UP_HIGH,
array_size);
ArrayResize(DOWN_LOW,
array_size);
ArrayResize(UP_HIGH_PROFIT,
array_size);
ArrayResize(DOWN_LOW_PROFIT,
array_size);
ArrayInitialize(UP,
0);
ArrayInitialize(DOWN,0);
ArrayInitialize(UP_PROFIT,
0);
ArrayInitialize(DOWN_PROFIT,
0);
ArrayInitialize(UP_MONEY,
0);
ArrayInitialize(DOWN_MONEY,
0);
ArrayInitialize(UP_HIGH,
0);
ArrayInitialize(DOWN_LOW,0);
ArrayInitialize(UP_HIGH_PROFIT,
0);
ArrayInitialize(DOWN_LOW_PROFIT,0);
}
//+------------------------------------------------------------------+
string DS(double s, int
digit)
{
return (DoubleToStr(s,digit));
}
//+------------------------------------------------------------------+