АвторСообщение



Сообщение: 1
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.03.13 08:23. Заголовок: помогите с кодом


Пишу индикатор, который рисует линии типа зиг заг на основе анализа уже имеющихся экстремумов зиг зага.
Сначала экстремумы собираю в буфера.
А вот далее нужно сравнивать пики и впадины и если, например, пики понижаются, то линия зиг зага должна рисоваться вниз, а если впадины повышаются, линия зиг зага идет вверх.
Написал вот так:
for(int i=0; i<100; i++)
{
double up = iCustom(NULL,0,"ZZ", 0, i);
double dw = iCustom(NULL,0,"ZZ", 1, i);
if(up!=2147483647) UP = High;
if(dw!=2147483647) DW = Low;

int countUP = ArraySize(UP);
int countDW = ArraySize(DW);

for(int u=0; u<countUP; u++)
{
if(UP<UP[u+1])
{
bufDn=UP;
bufUp=EMPTY_VALUE;
}
}
for(int d=0; d<countDW; d++)
{
if(DW[d]>DW[d+1])
{
bufUp=DW[d];
bufDn=EMPTY_VALUE;
}
}
}
Результат - нулевой. Подскажите, где я ошибаюсь.
Заранее - большое спасибо!

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 49 , стр: 1 2 3 4 All [только новые]







Сообщение: 8
Зарегистрирован: 03.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.03.13 11:25. Заголовок: А можете привести ко..


А можете привести код индикатора ZZ?
Если имеется в виду стандартный ZigZag, то для поиска максимумов используйте буфер с индексом 1, а для поиска минимумов - буфер с индексом 2. Буфер 0 состоит из экстремумов обоих типов: и максимумов и минимумов.

P. S. Для прикрепления файлов используйте какой-нибудь бесплатный файловый сервер (например, zalil.ru). А сюда просто вставляйте ссылку на него. Для размещения изображений удобно использовать сервер http://www.imageup.ru/.

Спасибо: 0 
ПрофильЦитата Ответить



Сообщение: 2
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.03.13 11:57. Заголовок: Scriptong, спасибо з..


Scriptong, спасибо за быстрый ответ.
Использовался индикатор rvmGann_sv8, но для личного удобства я его переименовал в ZZ.
Сам код индикатора по ссылке http://zalil.ru/34318988

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 11
Зарегистрирован: 03.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.03.13 14:30. Заголовок: Ага, понятно. Теперь..


Ага, понятно. Теперь можно приступить к разбору кода.

1. Вы организовываете цикл, обрабатывающий бары справа налево. Такой подход оправдан, когда необходимо определить последние актуальные данные. Если же нужны все экстремумы, то следует организовывать цикл слева направо по графику, т. е. от большего индекса к меньшему:

 цитата:
for(int i = 100; i > 0; i--)



2. В этой части все правильно:

 цитата:
double up = iCustom(NULL,0,"ZZ", 0, i);
double dw = iCustom(NULL,0,"ZZ", 1, i);



3. Далее следует определить наличие экстремума. По сути, верно. Но, все же, лучше использовать именованные константы, а не их значения. Так код читается легче:

 цитата:
if (up != EMPTY_VALUE)
{
// запомнить максимум
}
if (dw != EMPTY_VALUE)
{
// запомнить минимум
}



4. Назначение этой конструкции мне непонятно:

 цитата:
int countUP = ArraySize(UP);
int countDW = ArraySize(DW);


Если UP и DW - индикаторные буфера, то их размер всегда равен количеству баров на графике (Bars), т. е. countUP всегда будет равно countDW. Кстати, обходить далее все бары графика не имеет смысла, т. к. Вы изначально обходите только 100 из них.

5. Конструкции типа:

 цитата:
if(UP<UP[u+1])
{
bufDn=UP;
bufUp=EMPTY_VALUE;
}


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

Вывод: Для достижения Вашей цели программа должна быть устроена как-то иначе. К примеру, на каждом новом баре, необходимо заново определять пару последних экстремумов, записывая индексы их баров и значения экстремумов. По крайней мере, при работе с фракталами это делается именно так. Аналогичная функция была разработана в одном из последних советников PercentageZigZag_Expert_v7:

 цитата:
//+-------------------------------------------------------------------------------------+
//| Сохранение данных по экстремуму в одну или другую пар переменных |
//+-------------------------------------------------------------------------------------+
void SaveExtremum(int index, double extValue,
int& ext1Index, int& ext2Index,
double& ext1Value, double& ext2Value)
{
if (ext1Index < 0)
{
ext1Index = index;
ext1Value = extValue;
return;
}

ext2Index = index;
ext2Value = extValue;
}
//+-------------------------------------------------------------------------------------+
//| Поиск четырех последних экстремумов PercentageZigZag |
//+-------------------------------------------------------------------------------------+
bool FindLastExtremums(int& max1Index, int& max2Index,
int& min1Index, int& min2Index,
double& max1Val, double& max2Val,
double& min1Val, double& min2Val)
{
int i = 1;
while (i < Bars && (min2Index < 0 || max2Index < 0))
{
double high = iCustom(NULL, 0, "PercentageZigZag_v5", i_percentageChange,
i_changeOfPrevLeg, false, 0, i);
double low = iCustom(NULL, 0, "PercentageZigZag_v5", i_percentageChange,
i_changeOfPrevLeg, false, 1, i);

if (high != EMPTY_VALUE && max2Index < 0) // Найден максимум. Запись экстремума
SaveExtremum(i, High, max1Index,
max2Index, max1Val, max2Val);

if (low != EMPTY_VALUE && min2Index < 0) // Найден минимум. Запись экстремума
SaveExtremum(i, Low, min1Index,
min2Index, min1Val, min2Val);

i++;
}

if (i >= Bars) // До конца истории четыре экстремума
return (false); // ..найти не удалось

return (true);
}



Переменные, передаваемые функции FindLastExtremums по указателю - это четыре пары переменных, каждая из которых описывает свой экстремум. К примеру, переменной max1Index соответствует переменная max1Value. Первая переменная хранит индекс бара ближайшего максимума, а вторая - цену максимума. Соответственно, max2Index - индекс бара дальнего максимума (второго от текущего бара), а max2Value - цену этого максимума.

Спасибо: 1 
ПрофильЦитата Ответить



Сообщение: 3
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.03.13 15:01. Заголовок: Scriptong, большое с..


Scriptong, большое спасибо за подробный разбор полетов!
Пока ждал ответа, пересмотрел ваши коды и пришел вот к какому решению:
Пики и впадины я ищу теперь вот такой модифицированной из вашей функцией:

 цитата:
void CreateArray(int limit)
{
for (int i = limit; i >= 0; i--) // Прохождение по обновленной истории
{
Ext1 = 0;
Ext2 = 0;
// - 1 - =========================== Нахождение максимумов ==============================
bool found = false; // Флаг нахождения экстремума (false - нет)
double cur = iCustom(NULL,0,"ZZ", 0, i);

if(cur!=EMPTY_VALUE) //
found=true;
else
found=false;

if (found) // Если максимум найден, то..
Ext1 = cur; // ..отмечаем его
// - 1 - ============================== Окончание блока ================================

// - 2 - ============================ Нахождение минимумов ==============================
found = false; // Флаг нахождения экстремума (false - нет)
cur = iCustom(NULL,0,"ZZ", 1, i);

if (cur!=EMPTY_VALUE)
found = true;
else
found = false;

if (found) // Если минимум найден, то..
Ext2 = cur; // ..отмечаем его
// - 2 - ============================= Окончание блока =================================
}
}



Далее в следующем модифицированном из вашего блоке нахожу последние пары экстремумов:

 цитата:
void ExtremumsFind(int limit)
{
// - 1 - ========= Инициализация переменных, хранящих данные об экстремумах ============
NUp1 = 0; NUp2 = 0; NDn1 = 0; NDn2 = 0;
UpV1 = 0; UpV2 = 0; DnV1 = 0; DnV2 = 0;
// - 1 - ============================= Окончание блока ==================================

for (int i = limit; i < Bars && (NUp2 == 0 || NDn2 == 0); i++)
{
// - 2 - ================================ Поиск максимумов =============================
if (Ext1 > 0) // Найден максимум
if (NUp1 == 0) // Первый максимум еще не найден
{
NUp1 = i; // Сохраняем номер бара
UpV1 = Ext1; // Сохраняем значение экстремума
}
else // Если первый максимум найден
if (NUp2 == 0) // Второй максимум не найден
{
NUp2 = i; // Сохраняем номер бара
UpV2 = Ext1; // Сохраняем значение экстремума
}
// - 2 - ================================ Окончание блока ===============================

// - 3 - ================================ Поиск минимумов ==============================
if (Ext2 > 0) // Найден минимум
if (NDn1 == 0) // Первый минимум еще не найден
{
NDn1 = i; // Сохраняем номер бара
DnV1 = Ext2; // Сохраняем значение экстремума
}
else // Если первый минимум найден
if (NDn2 == 0) // Второй минимум не найден
{
NDn2 = i; // Сохраняем номер бара
DnV2 = Ext2; // Сохраняем значение экстремума
}
// - 3 - ================================ Окончание блока ===============================
}
}



И следующем блоке сравниваю экстремумы и вывожу данные в буфера для отрисовки:

 цитата:
void Results(int limit)
{
for (int i = limit; i >=0; i--)
{
// - 1 - ================= Отслеживание формирования нового максимума ===================
if (Ext1 > 0) // Если есть новый максимум
{
NUp2 = NUp1; //Первый максимум становится вторым
UpV2 = UpV1;
NUp1 = i; // А первый максимум обновляется
UpV1 = Ext1;
}
// - 1 - ============================ Окончание блока ===================================

// - 2 - ================= Отслеживание формирования нового минимума ====================
if (Ext2 > 0) // Если есть новый минимум
{
NDn2 = NDn1; // Первый минимум становится вторым
DnV2 = DnV1;
NDn1 = i; // А первый минимум обновляется
DnV1 = Ext2;
}
// - 2 - ============================ Окончание блока ===================================


// - 4 - ====================== Проверка наличия восходящего канала =====================
if (UpV1 > UpV2 && DnV1 > DnV2) // Первый максимум выше второго и..
{ // ..первый минимум выше второго
UP = UpV1;
}
// - 4 - ============================== Окончание блока =================================

// - 5 - ====================== Проверка наличия нисходящего канала =====================
else
if (UpV1 < UpV2 && DnV1 < DnV2) // Первый минимум ниже второго и..
{ // ..первый максимум ниже второго
DW = DnV1;
}
// - 5 - ============================== Окончание блока =================================


// - 6 - ============================== Окончание блока =================================
}
}


Рисовать индикатор начал, но только как-то кривова-то...
вот картинка click here
И не могу въехать, в чем тут может быть дело :(

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 3
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 17.03.13 16:02. Заголовок: Кто знает как это програмируется?


При создании идикаторов частенько необходимо выставление значков типа DRAW_ARROW чуть выше High или ниже Low. Простое добавление растояния в pip не подходит, так как не корректируется при изменении фрейма и масштаба. Однако встроенный в терминал индикатор фракталов рисуется как надо. Кто знает как это програмируется?
С уважением.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 38
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 1
ссылка на сообщение  Отправлено: 18.03.13 19:09. Заголовок: Sergey пишет: При с..


Sergey пишет:

 цитата:
При создании идикаторов частенько необходимо выставление значков типа DRAW_ARROW чуть выше High или ниже Low. Простое добавление растояния в pip не подходит, так как не корректируется при изменении фрейма и масштаба. Однако встроенный в терминал индикатор фракталов рисуется как надо. Кто знает как это програмируется?


Да, такая проблема существует и она неоднократно обсуждалась на форуме MQL4. Штатной возможности решения проблемы (возможностями языка MQL4) не существует.
Максимум, что можно сделать, это задавать отступ не в пунктах, а в средних волатильностях, т. е.:

 цитата:
up = High + iATR(NULL, 0, 14, i);
dn = Low - iATR(NULL, 0, 14, i);


Достаточно удобное решение.

Стандартный индикатор фракталов оперирует внутренними данными терминала о графике, которые нам недоступны. Для сравнения возьмите этот же индикатор с открытым кодом. Там такой красоты уже нет.

Чтобы отобразить отступы идеально, потребуется наряду с индикатором запустить зацикленный скрипт, который бы постоянно опрашивал график на предмет максимальной и минимальной цен в окне и в соответствии с ними устанавливал отступы от экстремумов. Но такое решение - из пушки по воробьям.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 4
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 18.03.13 20:35. Заголовок: Спасибо за разъяснен..


Спасибо за разъяснение и подсказку.
С уважением!

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 5
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 21.04.13 11:14. Заголовок: Уважаемый Scriptong как это програмируется?


В учебнике по MQL есть пример реализации функции учета ордеров int Terminal() и функции int Events() слежения за их изменениями. Проблема в том, что их результаты обнуляются при перезагрузке или вынужденной остановке советника, т.к. данные массива хранятся внутри советника. Возможна ли организовать сохранность данных при выключении советника в функции int deinit() в формате TXT. DBF или XL и загрузку их в функции int init() при повторном старте? Если да, то как это сделать?
С уважением!

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 85
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.13 17:19. Заголовок: Добрый день. Эта пр..


Добрый день.

Эта проблема решается, как минимум, тремя способами:
1. Использовать запись в файл, как Вы и указали. Для этого необходимо использовать Файловые операции. Если будете реализовывать, то рассмотрим подробнее. На мой взгляд, второй способ проще.
2. Записывать данные в глобальные переменные терминала. Это та же самая работа с файлами, но проводит ее сам терминал. Вы будете использовать простые функции.
3. Вместо локальных переменных эксперта использовать глобальные переменные. Но поможет этот способ только в случае, если эксперт не был отключен от графика полностью (смена таймфрейма, символа, настроечных параметров).

Также хочу еще обратить внимание на один нюанс. В перерыве между отключениями эксперта состав ордеров вполне может измениться. В итоге информация, которую Вы собираетесь запоминать, становится неактуальной. Поэтому информация об ордерах начинает собираться только в тот момент, когда в ней возникает необходимость. Хранить ее просто так, на всякий случай, никакого смысла нет.
И даже больше. К примеру, когда реализуются функции, в которых производятся операции с массой ордеров, нужно учитывать факт изменения состава ордеров за то время, которое тратится на обработку одного ордера.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 8
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 23.04.13 07:05. Заголовок: Большое спасибо!!!


Игорь, идея в создании функции учета суммы убытков по закрытым ордерам Buy и Sell в раздельности при работе эксперта для последующего анализа. При этом любые действия с терминалом или даже перезагрузка ПК не должна удалять эти данные. Думаю, что работа с файловыми операциями то, что нужно. Хотя попробую "вникнуть и в Глобальные переменные". Вычитал, что они хранятся 2 недели. Смею предположить, что перезапись файлов может сильно повлиять на быстодействие эксперта. Учет ордеров с помощью функций int Terminal() и int Events() мной уже реализован. Как получиться реализовать задуманное отпишусь.
С уважением!

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 89
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 1
ссылка на сообщение  Отправлено: 29.04.13 20:28. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, идея в создании функции учета суммы убытков по закрытым ордерам Buy и Sell в раздельности при работе эксперта для последующего анализа.



Для этого случая есть три подхода:

1. Работа с историей счета. В итоге уходим от использования файлов, но для этого потребуется точная идентификация ордеров, открытых экспертом. Обычно для этого достаточно уникального Magic Number при открытии ордеров. Недостаток этого способа - история счета не всегда может быть доступной: либо пользователь изменил ее отображение на "Сегодня", либо брокер заархивировал сделки за некоторый период.

2. Работа с файлами (или глобальными переменными). В этом случае достаточно вести всю бухгалтерию во время работы советника, а при деинициализации сбрасывать необходимые сведения в файл. При очередной инициализации вновь считывать из файла. Недостаток способа - привязка к определенному терминалу в определенной папке одного и того же компьютера.

3. Универсальный и несколько оригинальный способ, который не привязан к терминалу, позволяя запускать советник на разных компьютерах при условии доступа к одному и тому же счету. Информацию о текущих расчетах можно представлять в виде отложенных ордеров. Например, чтобы записать текущую прибыль/убыток по ордерам типа Sell советник устанавливает отложенный ордер Sell Stop по некоторой очень далекой цене (чтобы ордер гарантированно не сработал), например, Point. При этом полезная информация может храниться сразу в двух параметрах отложенного ордера: Magic Number и объеме ордера. Например, в объем можно записать совокупный объем закрытых ордеров, в Magic Number - значение прибыли/убытка в пунктах. Аналогично для ордеров Buy - устанавливать отложенный ордер Buy Limit по цене Point. При этом советник в момент изменения данных просто удаляет имеющиеся ордера, а потом заново их устанавливает. В итоге вся полезная информация хранится на сервере брокера.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 13
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 05.05.13 21:07. Заголовок: Универсальный и несколько оригинальный способ


Идея супер! Спасибо!

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 15
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 19.05.13 20:31. Заголовок: Нужно ограничить вре..


Нужно ограничить время существования отложенного ордера при его выставлении
int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)
параметр datetime expiration. Не могу понять как правильно его расчитать. Я сделал так: Time[0]+Period()*60*k, гда k-количестово баров после которых должен удалиться отложенный ордер. При тесте то выдается ошибка 3-неправильный параметр, то все проходит нормально. В чем дело не могу понять?



Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 16
Зарегистрирован: 05.03.13
Репутация: 0
ссылка на сообщение  Отправлено: 20.05.13 07:30. Заголовок: Решил проблему испо..



Решил проблему используя функцию OrderSelect(), написал так

if ((OrderOpenTime()+Period()*60*k)<Time[0])
if (!OrderDelete(OrderTicket())) return(False);

Уважаемый Scriptong, если не затруднит, подскажите на будущее в чем ошибка в первом варианте?

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 100
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 1
ссылка на сообщение  Отправлено: 20.05.13 09:00. Заголовок: Sergey пишет: подск..


Sergey пишет:

 цитата:
подскажите на будущее в чем ошибка в первом варианте?


По большому счету, ошибки нет. Время истечения ордера указывается в формате времени, т. е. ставится любое будущее время сервера.
Есть лишь один нюанс, который, почему-то, не документирован. Касается он минимальной дельты времени между текущим временем и временем истечения. Эта дельта равна 10 минутам. В итоге, если устанавливается ордер в 10:30:00, а время его истечения 10:39:59, то получим ошибку установки ордера. Бороться с этим просто:

 цитата:

#define MIN_EXPIRATION_SECONDS 600
...
int barsCnt = 10;
datetime expTime = TimeCurrent() + Period() * 60 * barsCnt;
expTime = MathMax(expTime, TimeCurrent() + MIN_EXPIRATION_SECONDS);
int ticket = OrderSend(Symbol(), OP_SELLSTOP, 0.1, Bid - 50 * Point, 0, 0, NULL, 0, expTime);



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

Ну и не забудем упомянуть еще один момент - далеко не все брокеры поддерживают использование времени истечения ордера.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 49 , стр: 1 2 3 4 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  2 час. Хитов сегодня: 1
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет