Впервые на форуме, если что-то делаю на форуме криво - заранее прошу извинить.
Давно смотрю на графики с индикаторами. Недавно слил 2 депозита. Перед открытием нового счета хочу проверить на истории прибыльность стратегии. На демо счету в МТ4.
Я вообще не программер. Умею только устанавливать сторонние индикаторы в МТ4 и, может быть, поменять толщину линии индикатора в MetaEditor (цвет в коде индикатора поменять уже скорее всего не смогу - только в терминале).
Скажите пож-та, есть где-то доходчиво изложенная инф. для человека с моими познаниями, с чего пошагово начать тестирование (в просторечье "инструкция для негров как пользоваться унитазом")? Индикаторов в стратегии 3 шт: МА (3 шт простые), Стохастик со стандартными уровнями, и CCI с 5-тью уровнями. Открытие коротких сделок после пересечения уровней индикаторов сверху вниз, длинных - наоборот (наверно понятно..). Установка тэйков и лосей.
Хотелось бы иметь возможность как визуального отслеживания работы стратегии в авто-режиме, так и без визуализации для подбора параметров индикаторов и ордеров.
Впервые на форуме, если что-то делаю на форуме криво - заранее прошу извинить.
Давно смотрю на графики с индикаторами. Недавно слил 2 депозита. Перед открытием нового счета хочу проверить на истории прибыльность стратегии. На демо счету в МТ4.
Я вообще не программер. Умею только устанавливать сторонние индикаторы в МТ4 и, может быть, поменять толщину линии индикатора в MetaEditor (цвет в коде индикатора поменять уже скорее всего не смогу - только в терминале).
Скажите пож-та, есть где-то доходчиво изложенная инф. для человека с моими познаниями, с чего пошагово начать тестирование (в просторечье "инструкция для негров как пользоваться унитазом")? Индикаторов в стратегии 3 шт: МА (3 шт простые), Стохастик со стандартными уровнями, и CCI с 5-тью уровнями. Открытие коротких сделок после пересечения уровней индикаторов сверху вниз, длинных - наоборот (наверно понятно..). Установка тэйков и лосей.
Хотелось бы иметь возможность как визуального отслеживания работы стратегии в авто-режиме, так и без визуализации для подбора параметров индикаторов и ордеров.
при создании графического объекта (ГО), например ТрендЛине, выбираете цвет. При повторном создании ТрендЛине создается этим же цветом. Для Hline - выбрали цвет - и следующая такая. Берите желтый, голубой, ...
Если ГО создает советник, индикатор, скрипт - то как в программе напишете. Иногда выбор параметрами
Если Вы думаете, что кто-то, глядя на Ваш код, может быстро найти ошибка - заблуждаетесь. Ошибки ищет компилятор. Текст программы должен быть отформатирован - для этого в MetaEditor есть стилизатор. Если Вам нравится другой стиль - используйте, например, программу AStyle.exe. После стилизации вы быстро увидите, что в программе 1) лишняя закрывающая скобка. 2) Объявлена переменная: datetime date_Buf_1; // массив дат индикатора - чтоб это был массив, надо [размер] или [] для динамического массива и потом размер задать ArrayResize кажется. И это нужно делать до использования массива - смотрите про это посты выше. 3) FileOpen(InpDirectoryName+"//"+InpFileName - кажется, палки надо наклонить в другую сторону. А лучше обойтись без InpDirectoryName+"//" - в папке Files и так файл найдете.
на строку: int copied=CopyTime(NULL,0,0,0,date_Buf_1); Компилятор злится, начало=конец=0 количество=0
Спасибо. Что-то получилось исправить, но больше интуитивно, чем пониманием. Но, все равно 3 ошибки лезут, касательно массива:
'Buf_1' - array required111.mq49321
'date_Buf_1' - array required111.mq49421
'Buf_1' - array required111.mq410016
//+------------------------------------------------------------------+//| Custom indicator initialization function |//+------------------------------------------------------------------+inputstring InpFileName="111.csv"; // Имя файла inputstring InpDirectoryName="Data"; // Имя каталога datetime Время=0; // Время прошлого бараdouble Bid1;
double Buf_1[];
// double ExtBuffer;long V1; // объем для текущего тика вверхlong V2; // накопленный объем для всех тиков вверх текущего бараlong V3; // объем текущего тика внизlong V4; // накопленный объем для всех тиков вниз для текущего бараlong V5; // отрицательные и положительные iVolume нарастающим итогом//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnInit()
{
IndicatorDigits(0);
SetIndexBuffer(0,Buf_1);
//SetIndexBuffer(1,Buf_2);
Bid1=Bid;
V5=0;
}
//+------------------------------------------------------------------+//| Custom indicator iteration function |//+------------------------------------------------------------------+intOnCalculate(constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &spread[])
{
datetime Вр=Time[0]; // Время текущего бараif(Вр>Время) // Если новый бар
{
Время=Вр; // Запомнить// Buf_1[0]=0; // и обнулить последний элемент буфера
}
datetime date_Buf_1[]; // массив дат индикатора datetime time_Buf_1[]; // массив времени // --- считаю объем для положительных и отрицательных тиков if(Bid>=Bid1)
{
if(Bid>Bid1) // если тик положительный..
{
V1=iVolume(NULL,0,0); // если повышающий цену тик, то находим его объем
V2= V1 + V2;
}
else
{
V1=0; // если Bid1 = Bid2, т.е. изменение цены = 0, то iVolume этого тика присваиваем 0;
V2= V1 + V2;
}
}
else
{
V3 = iVolume(NULL, 0, 0); // если понижающий цену тик
V4 = V3 + V4; // то находим его объем
}
V5=V2-V4; // определяем разницу (дельту) между объемами положительных и отрицательных тиков
Bid1=Bid;
Buf_1[0]=V5; // в буфер сгружаем дельту// ExtBuffer = Buf_1 [0];// double macurrent=iMAOnArray(ExtBuffer,0,5,0,MODE_LWMA,0); // запись в файл данных буфера//--- установим для массивов признак таймсерии ArraySetAsSeries(Buf_1[0],true);
ArraySetAsSeries(date_Buf_1[0],true);
//--- скопируем таймсерию int copied=CopyTime(NULL,0,10000,0,date_Buf_1);
//--- подготовим массив Buf_1 ArrayResize(Buf_1[0],copied);
//--- скопируем значения линии индикатора for(int i=0;i<copied;i++)
{
Buf_1[i]=V5;
}
//--- откроем файл для записи значений индикатора ResetLastError();
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_WRITE|FILE_CSV);
if(file_handle!=INVALID_HANDLE)
{
PrintFormat("Файл %s открыт для записи",InpFileName);
PrintFormat("Путь к файлу: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
//--- сначала запишем значения индикатора FileWrite(file_handle,Buf_1[0]);
//--- запишем время и значения в файл for(int i=0;i<Buf_1[0];i++)
FileWrite(file_handle,time_Buf_1[0],Buf_1[0]);
//--- закрываем файл FileClose(file_handle);
PrintFormat("Данные записаны, файл %s закрыт",InpFileName);
}
elsePrintFormat("Не удалось открыть файл %s, Код ошибки = %d",InpFileName,GetLastError());
return(rates_total);
}
//+------------------------------------------------------------------+
Не понял я, как Ваши замечания претворить в жизнь. Но, лишнюю скобу нашел :)
Образовался ряд вопросов, очень надеюсь на помощь. Обнаружил очень грустную вещь, что работа советника во время тестирования и в режиме реального времени сильно отличается, поэтому хотелось бы разобрать самые ходовые и типовые ошибки. Сначала напишу с какими я столкнулся, было бы классно если бы знающие тоже поделились опытом - о чем нельзя забывать и что должно присутсвовать в коде.
1. В режиме реальной торговли вылезала ошибка деления на ноль, хотя разумеется в коде деления на ноль не было и во время бектестов такого не появлялось. Решил проблему тем, что каждый делитель записывал как NormalizeDouble(x,Digits);
2. Не открылась сделка. Пятничный день прогнав на бектесте сделка открылась, а во время реальной торговли нет. При чем в журнале советника никаких ошибок не выдал. Вот тут я не знаю в чем может быть дело, но грешу на пару вещей. Во первых у меня висят предупреждения вида "return value of 'ordersend' should be checked", но если я правильно понимаю на выполнение кода это влиять не должно? Или же все дело в проскальзывании? У меня стоит 1, что вроде не особо и мало. Да и бар на котором должен был выполнять вход открылся без гэпа.
3. Из стандартного примера со скользяшками я взял строчку "if(Volume[0]>1) return;" и вставил в начало кода. То есть мой код выполняется только во время первого тика при появлении нового бара. Может ли такое быть, что бар открывается сразу с объемом и мой код не выполняется?
4. Посоветуйте моменты на которые надо обратить внимание или типичные ошибки, при работе советника с историей и реальным временем, пожалуйста
Образовался ряд вопросов, очень надеюсь на помощь. Обнаружил очень грустную вещь, что работа советника во время тестирования и в режиме реального времени сильно отличается, поэтому хотелось бы разобрать самые ходовые и типовые ошибки. Сначала напишу с какими я столкнулся, было бы классно если бы знающие тоже поделились опытом - о чем нельзя забывать и что должно присутсвовать в коде.
1. В режиме реальной торговли вылезала ошибка деления на ноль, хотя разумеется в коде деления на ноль не было и во время бектестов такого не появлялось. Решил проблему тем, что каждый делитель записывал как NormalizeDouble(x,Digits);
2. Не открылась сделка. Пятничный день прогнав на бектесте сделка открылась, а во время реальной торговли нет. При чем в журнале советника никаких ошибок не выдал. Вот тут я не знаю в чем может быть дело, но грешу на пару вещей. Во первых у меня висят предупреждения вида "return value of 'ordersend' should be checked", но если я правильно понимаю на выполнение кода это влиять не должно? Или же все дело в проскальзывании? У меня стоит 1, что вроде не особо и мало. Да и бар на котором должен был выполнять вход открылся без гэпа.
3. Из стандартного примера со скользяшками я взял строчку "if(Volume[0]>1) return;" и вставил в начало кода. То есть мой код выполняется только во время первого тика при появлении нового бара. Может ли такое быть, что бар открывается сразу с объемом и мой код не выполняется?
4. Посоветуйте моменты на которые надо обратить внимание или типичные ошибки, при работе советника с историей и реальным временем, пожалуйста
Замените такие дикие конструкции "if(Volume[0]>1) return;" на нормальную проверку "Нового бара", здесь на форуме их полно.
Предупреждения вида "return value of 'ordersend' should be checked" - это пока не ошибка, это потенциальная ошибка на будущее. В коде не должно быть никаких предупреждений, а тем более при работе онлайн.
"У меня стоит 1, что вроде не особо и мало" - этого может быть очень мало на открытии нового бара, а тем более получасового, и часового, в это время сильно расширяется спред.
Что нужно: Делать проверку на новый бар, и если он новый, то смотреть условия на вход, если совпали - совершить сделку. После этого уже записать что бар отработан, и ждём новый.
Что есть сейчас: if(Volume[0]>1) return; = если новый бар, то смотрим условия, условие не подошло == большой спред = выход снова в OnTick(), на следующем тике if(Volume[0]>1) return; уже не пропустит дальше, поэтому сделка пропущена, даже если спред будет 0.0001
Здравствуйте. Подскажите пожалуйста, как мне с помощью кода описать следующее: Есть флет, ограниченный верхней и нижней горизонтальными линиями. Их советник определяет и устанавливает сам.
Нужно, чтобы советник определил выход цены из зоны флета, а затем возвращение в эту зону. И только после этого открывал позицию.
Для фильтрации шума использую мувинг с параметром 2 или3
Замените такие дикие конструкции "if(Volume[0]>1) return;" на нормальную проверку "Нового бара", здесь на форуме их полно.
Предупреждения вида "return value of 'ordersend' should be checked" - это пока не ошибка, это потенциальная ошибка на будущее. В коде не должно быть никаких предупреждений, а тем более при работе онлайн.
"У меня стоит 1, что вроде не особо и мало" - этого может быть очень мало на открытии нового бара, а тем более получасового, и часового, в это время сильно расширяется спред.
Что нужно: Делать проверку на новый бар, и если он новый, то смотреть условия на вход, если совпали - совершить сделку. После этого уже записать что бар отработан, и ждём новый.
Что есть сейчас: if(Volume[0]>1) return; = если новый бар, то смотрим условия, условие не подошло == большой спред = выход снова в OnTick(), на следующем тике if(Volume[0]>1) return; уже не пропустит дальше, поэтому сделка пропущена, даже если спред будет 0.0001
Насчет открытия нового бара. Будет ли хорошим такой вариант? :
datetime counted_bar = 0;
intOnInit()
{
counted_bar = 0; // если нужно, чтоб при перезапуске последний бар был проанализирован
...
voidOnTick()
{
// Если появился новый барif ( iTime( _Symbol, _Period, 0 ) > counted_bar )
{
counted_bar = iTime( _Symbol, _Period, 0 );
// Анализируем индикаторы
...
}
Суть такая, что если спред больше нормы, значит выходим снова в OnTick, и на новом тике проверяем спред, если он нормальный - отправляем ордер и запоминаем, что на этом баре была сделка.
Можно ещё второй способ:
voidOnTick()
{
// Если появился новый барif ( iTime( _Symbol, _Period, 0 ) > counted_bar )
{
if(SpreadMax > текущий спред) return;
// Анализируем индикаторы
...
result = OrderSend(...);
// если открылась позиция, то result будет тикет позицииif(result>0) counted_bar = iTime( _Symbol, _Period, 0 );
}
В общем, вам нужно определиться с логикой, когда должно записаться, и больше не проверятся до образования "Нового бара"
при создании графического объекта (ГО), например ТрендЛине, выбираете цвет. При повторном создании ТрендЛине создается этим же цветом. Для Hline - выбрали цвет - и следующая такая. Берите желтый, голубой, ...
Если ГО создает советник, индикатор, скрипт - то как в программе напишете. Иногда выбор параметрами
Если Вы думаете, что кто-то, глядя на Ваш код, может быстро найти ошибка - заблуждаетесь. Ошибки ищет компилятор. Текст программы должен быть отформатирован - для этого в MetaEditor есть стилизатор. Если Вам нравится другой стиль - используйте, например, программу AStyle.exe. После стилизации вы быстро увидите, что в программе 1) лишняя закрывающая скобка. 2) Объявлена переменная: datetime date_Buf_1; // массив дат индикатора - чтоб это был массив, надо [размер] или [] для динамического массива и потом размер задать ArrayResize кажется. И это нужно делать до использования массива - смотрите про это посты выше. 3) FileOpen(InpDirectoryName+"//"+InpFileName - кажется, палки надо наклонить в другую сторону. А лучше обойтись без InpDirectoryName+"//" - в папке Files и так файл найдете.
на строку: int copied=CopyTime(NULL,0,0,0,date_Buf_1); Компилятор злится, начало=конец=0 количество=0
Спасибо. Что-то получилось исправить, но больше интуитивно, чем пониманием. Но, все равно 3 ошибки лезут, касательно массива:
'Buf_1' - array required 111.mq4 93 21
'date_Buf_1' - array required 111.mq4 94 21
Спасибо. Что-то получилось исправить, но больше интуитивно, чем пониманием. Но, все равно 3 ошибки лезут, касательно массива:
'Buf_1' - array required 111.mq4 93 21
'date_Buf_1' - array required 111.mq4 94 21
Оставьте только названия переменных-массивов. Уберите "[]" в тех строках кода, на которые указывает вам компилятор.
Спасибо. Посмотрю что получилось в жизни. Что-то у меня большие сомнения что что-то запишется в файл :)
Образовался ряд вопросов, очень надеюсь на помощь. Обнаружил очень грустную вещь, что работа советника во время тестирования и в режиме реального времени сильно отличается, поэтому хотелось бы разобрать самые ходовые и типовые ошибки. Сначала напишу с какими я столкнулся, было бы классно если бы знающие тоже поделились опытом - о чем нельзя забывать и что должно присутсвовать в коде.
1. В режиме реальной торговли вылезала ошибка деления на ноль, хотя разумеется в коде деления на ноль не было и во время бектестов такого не появлялось. Решил проблему тем, что каждый делитель записывал как NormalizeDouble(x,Digits);
2. Не открылась сделка. Пятничный день прогнав на бектесте сделка открылась, а во время реальной торговли нет. При чем в журнале советника никаких ошибок не выдал. Вот тут я не знаю в чем может быть дело, но грешу на пару вещей. Во первых у меня висят предупреждения вида "return value of 'ordersend' should be checked", но если я правильно понимаю на выполнение кода это влиять не должно? Или же все дело в проскальзывании? У меня стоит 1, что вроде не особо и мало. Да и бар на котором должен был выполнять вход открылся без гэпа.
3. Из стандартного примера со скользяшками я взял строчку "if(Volume[0]>1) return;" и вставил в начало кода. То есть мой код выполняется только во время первого тика при появлении нового бара. Может ли такое быть, что бар открывается сразу с объемом и мой код не выполняется?
4. Посоветуйте моменты на которые надо обратить внимание или типичные ошибки, при работе советника с историей и реальным временем, пожалуйста
Образовался ряд вопросов, очень надеюсь на помощь. Обнаружил очень грустную вещь, что работа советника во время тестирования и в режиме реального времени сильно отличается, поэтому хотелось бы разобрать самые ходовые и типовые ошибки. Сначала напишу с какими я столкнулся, было бы классно если бы знающие тоже поделились опытом - о чем нельзя забывать и что должно присутсвовать в коде.
1. В режиме реальной торговли вылезала ошибка деления на ноль, хотя разумеется в коде деления на ноль не было и во время бектестов такого не появлялось. Решил проблему тем, что каждый делитель записывал как NormalizeDouble(x,Digits);
2. Не открылась сделка. Пятничный день прогнав на бектесте сделка открылась, а во время реальной торговли нет. При чем в журнале советника никаких ошибок не выдал. Вот тут я не знаю в чем может быть дело, но грешу на пару вещей. Во первых у меня висят предупреждения вида "return value of 'ordersend' should be checked", но если я правильно понимаю на выполнение кода это влиять не должно? Или же все дело в проскальзывании? У меня стоит 1, что вроде не особо и мало. Да и бар на котором должен был выполнять вход открылся без гэпа.
3. Из стандартного примера со скользяшками я взял строчку "if(Volume[0]>1) return;" и вставил в начало кода. То есть мой код выполняется только во время первого тика при появлении нового бара. Может ли такое быть, что бар открывается сразу с объемом и мой код не выполняется?
4. Посоветуйте моменты на которые надо обратить внимание или типичные ошибки, при работе советника с историей и реальным временем, пожалуйста
Замените такие дикие конструкции "if(Volume[0]>1) return;" на нормальную проверку "Нового бара", здесь на форуме их полно.
Предупреждения вида "return value of 'ordersend' should be checked" - это пока не ошибка, это потенциальная ошибка на будущее. В коде не должно быть никаких предупреждений, а тем более при работе онлайн.
"У меня стоит 1, что вроде не особо и мало" - этого может быть очень мало на открытии нового бара, а тем более получасового, и часового, в это время сильно расширяется спред.
Что нужно: Делать проверку на новый бар, и если он новый, то смотреть условия на вход, если совпали - совершить сделку. После этого уже записать что бар отработан, и ждём новый.
Что есть сейчас: if(Volume[0]>1) return; = если новый бар, то смотрим условия, условие не подошло == большой спред = выход снова в OnTick(), на следующем тике if(Volume[0]>1) return; уже не пропустит дальше, поэтому сделка пропущена, даже если спред будет 0.0001
Здравствуйте. Подскажите пожалуйста, как мне с помощью кода описать следующее: Есть флет, ограниченный верхней и нижней горизонтальными линиями. Их советник определяет и устанавливает сам.
Нужно, чтобы советник определил выход цены из зоны флета, а затем возвращение в эту зону. И только после этого открывал позицию.
Для фильтрации шума использую мувинг с параметром 2 или3
Замените такие дикие конструкции "if(Volume[0]>1) return;" на нормальную проверку "Нового бара", здесь на форуме их полно.
Предупреждения вида "return value of 'ordersend' should be checked" - это пока не ошибка, это потенциальная ошибка на будущее. В коде не должно быть никаких предупреждений, а тем более при работе онлайн.
"У меня стоит 1, что вроде не особо и мало" - этого может быть очень мало на открытии нового бара, а тем более получасового, и часового, в это время сильно расширяется спред.
Что нужно: Делать проверку на новый бар, и если он новый, то смотреть условия на вход, если совпали - совершить сделку. После этого уже записать что бар отработан, и ждём новый.
Что есть сейчас: if(Volume[0]>1) return; = если новый бар, то смотрим условия, условие не подошло == большой спред = выход снова в OnTick(), на следующем тике if(Volume[0]>1) return; уже не пропустит дальше, поэтому сделка пропущена, даже если спред будет 0.0001
Насчет открытия нового бара. Будет ли хорошим такой вариант? :
Насчет открытия нового бара. Будет ли хорошим такой вариант? :
Пусть будет изначально такая.
Далее, нужно сделать правильное фиксирование что бар отработан, но здесь нужно просчитать весь подход к ТЗ.
Пока то, что Я вижу с вашего поста, то нужно сделать так:
Суть такая, что если спред больше нормы, значит выходим снова в OnTick, и на новом тике проверяем спред, если он нормальный - отправляем ордер и запоминаем, что на этом баре была сделка.
Можно ещё второй способ:
В общем, вам нужно определиться с логикой, когда должно записаться, и больше не проверятся до образования "Нового бара"