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





Сообщение: 122
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 14.04.14 09:56. Заголовок: Я в шоке! Подскажите.


Всем привет!
Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Игорь подскажи, где можно ознакомиться с изменениями в MQL4?
Хотел перенести все данные на новый комп, но некоторые индикаторы после компиляции перестают работать. Вот один из них.
http://gfile.ru/a8cCP
Хотя не перекомпилированные файлы работают.
Компиляция ошибок в коде не выявляет. Но при отладке выдается ошибка формирования массива стр.67. Но в чем ошибка не пойму.
Буду благодарен, если найдешь время исправить.



Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 203 , стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 All [только новые]


постоянный участник




Сообщение: 494
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 1
ссылка на сообщение  Отправлено: 14.04.14 10:41. Заголовок: Sergey пишет: Всем ..


Sergey пишет:

 цитата:
Всем привет!
Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены.



Привет, Сергей! С возвращением !

У Игоря была статья про возможности обновленного MQL, но видимо надо его попросить обновить две базовые статьи:
"Как создать советник, не обладая навыками программирования",
"Как создать индикатор, не обладая навыками программирования", и шаблоны к ним.


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 123
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 14.04.14 13:16. Заголовок: Genry пишет: Приве..


Genry пишет:


 цитата:
Привет, Сергей! С возвращением



Спасибо Genry!
Неотложных дел еще на месяц. Затем буду включаться в работу.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 508
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 1
ссылка на сообщение  Отправлено: 17.04.14 05:41. Заголовок: Sergey пишет: Всем ..


Sergey пишет:

 цитата:
Всем привет!
Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Игорь подскажи, где можно ознакомиться с изменениями в MQL4?
Хотел перенести все данные на новый комп, но некоторые индикаторы после компиляции перестают работать. ...
Хотя не перекомпилированные файлы работают.
Компиляция ошибок в коде не выявляет. Но при отладке выдается ошибка формирования массива стр.67. Но в чем ошибка не пойму.
Буду благодарен, если найдешь время исправить.



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

1.Ошибки компиляции
◾1.1. Идентификатор совпадает с зарезервированным словом
◾1.2. Специальные символы в наименованиях переменных и функций
◾1.3. Ошибки использования оператора switch
◾1.4. Возвращаемые значения у функций

◾1.5. Массивы в аргументах функций


2.Ошибки времени выполнения
◾2.1. Выход за пределы массива (Array out of range)
◾2.2. Деление на ноль (Zero divide)
◾2.3. Использование 0 вместо NULL для текущего символа
◾2.4. Строки в формате Unicodе и их использование в DLL
◾2.5. Совместное использование файлов
◾2.6. Особенность преобразования datetime

3.Предупреждения компилятора
◾3.1. Пересечения имен глобальных и локальных переменных
◾3.2. Несоответствие типов
◾3.3. Неиспользуемые переменные


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 404
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 18.04.14 17:31. Заголовок: Исправленный индикат..


Исправленный индикатор - здесь.

Ошибки:
1. Выход за пределы массивов при расчете начального бара (переменная limit). В момент начала работы индикатора выражение

 цитата:
limit = Bars - counted_bars;


указывает на бар с индексом Bars, которого не существует. Bars - это общее количество баров на графике, которое индексируется с нуля. Поэтому последний бар графика будет иметь индекс Bars - 1.
Чтобы подобное не происходило, нужно начинать обработку баров с того бара, для которого будет произведен корректный расчет всех значений индиктаора. В общем случае можно поступить так:

 цитата:
limit = (int)MathMin(Bars - counted_bars, Bars - 1);


Но в данном случае это тоже неправильно, т. к. необходимо обеспечить расчет средней скользящей с периодом Periods. То есть от конца графика нужно отодвинуться еще на Periods баров:

 цитата:
limit = (int)MathMin(Bars - counted_bars, Bars - Periods - 1);



2. Связывание индикаторных буферов с индексами произведено неправильно:

 цитата:
if(
!SetIndexBuffer(0,e7) &&
!SetIndexBuffer(1,e2) &&
!SetIndexBuffer(2,e3) &&
!SetIndexBuffer(3,e4) &&
!SetIndexBuffer(4,e5) &&
!SetIndexBuffer(5,e6) &&
!SetIndexBuffer(6,e1)
)


В новом MQL4 логические выражения обрабатываются по укороченному сценарию. Это означает, что если после вычисления первой части выражения результат всего выражения уже не изменится, то вторая и последующая части не вычисляются. В данном случае при успешном связывании первого буфера становится ясно, что выражение будет иметь результат false. Потому последующие буфера не связываются.
Правильно делать так:

 цитата:
if(
!SetIndexBuffer(0,e7) ||
!SetIndexBuffer(1,e2) ||
!SetIndexBuffer(2,e3) ||
!SetIndexBuffer(3,e4) ||
!SetIndexBuffer(4,e5) ||
!SetIndexBuffer(5,e6) ||
!SetIndexBuffer(6,e1)
)


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

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





Сообщение: 127
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 19.04.14 08:01. Заголовок: Scriptong пишет: И..


Scriptong пишет:


 цитата:
Исправленный индикатор



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

Удачи!

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





Сообщение: 144
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 14.08.14 09:46. Заголовок: В папке Includ файл ..


В папке Include файл MovingAverages.mqh
Функция
double ExponentialMA(const int position,const int period,const double prev_value,const double &price[])

Что обозначает параметр prev_value?

И каково предназначение символа & ( &price[])?

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





Сообщение: 707
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 15.08.14 16:32. Заголовок: Sergey пишет: Что о..


Sergey пишет:

 цитата:
Что обозначает параметр prev_value?


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

Sergey пишет:

 цитата:
И каково предназначение символа & ( &price[])?


В MQL4/5 символ "&", поставленный в объявлении переменной перед ее именем, означает ссылку на переменную. Ссылка в большинстве случаев дает возможность изменять значение переменной внутри локальной функции так, что измененное значение будет доступно после окончания выполнения этой локальной функции. Вот простой пример. В одной функции объявляются переменные a и b, но их значения меняются в другой функции, в которой они не объявлены, а переданы по ссылке:

 цитата:
void SwapVars(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
void OnTick()
{
int a = 5;
int b = 10;
Print("До изменения: a = ", a, ", b = ", b);

SwapVars(a, b);
Print("После изменения: a = ", a, ", b = ", b);
}




В случае с функцией ExponentialMA ссылка имеет другое назначение. Перед типом данных установлен спецификатор const, который указывает на тот факт, что переменная, передаваемая по ссылке, не может быть изменена. Возникает логичный вопрос - а зачем тогда ссылка? Здесь она нужна по той причине, что в функцию требуется передать не одно значение, а целый массив. Если передавать массив по значению, то чем большее количество элементов в массиве, тем дольше он будет передаваться в функцию. Ссылка же дает возможность не передавать все значения массива, а просто указать место в памяти, где все эти значения лежат. При этом передающая функция "может быть спокойна за целостность данных", т. к. функция ExponentialMA не имеет право изменять данные массива price.

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





Сообщение: 146
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 16.09.14 11:50. Заголовок: Всегда имел проблемы..


Всегда имел проблемы с графикой.
Вот код:

ShowTypeBars(g_typebar, Volume|i|, Time|i|, clrText);
//+-------------------------------------------------------------------------------------+
//| Отображение надписи типа сигнала |
//+-------------------------------------------------------------------------------------+
void ShowTypeBars(string j_typebar, int j_volume, datetime j_time, color clr)
{
string name = PREFIX + j_time;
ObjectDelete("name");
ObjectCreate(name, OBJ_TEXT, WindowFind(short_name), j_time, j_volume);
ObjectSetText(name, j_typebar, 8, "Arial Black", clr);
}
//=================================================



Не могу понять, почему после установки индикатора на нулевом баре не обновляется координата j_volume, хотя текущая гистограмма объема отображается верно.

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





Сообщение: 803
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 16.09.14 12:45. Заголовок: Sergey пишет: Не мо..


Sergey пишет:

 цитата:
Не могу понять, почему после установки индикатора на нулевом баре не обновляется координата j_volume, хотя текущая гистограмма объема отображается верно.


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

 цитата:
ObjectDelete("name");


нужно написать:

 цитата:
ObjectDelete(name);


Ведь name - это имя переменной, а в коде оно используется как имя объекта. То есть удаляется объект с названием name, а создается потом совершенно другой объект с названием, которое находится в переменной name.

При обновлении данных графических объектов лучше использовать не удаление/создание, а создание/модификацию:

 цитата:
string name = PREFIX + ...;
if (ObjectFind(name) < 0) // объекта нет - можно создавать
{
ObjectCreate(..);
// назначение свойств объекта
}
else
{
// модификация объекта - те свойства, которые нужно изменить
}



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





Сообщение: 147
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 16.09.14 16:12. Заголовок: Огромное спасибо! Пе..


Огромное спасибо!
Первоначальный вариант бал такой, однако он так же не работал из-за ошибки в названии.

void ShowTypeBars(string j_typebar, int j_volume, datetime j_time, color clr)
{
string name = PREFIX + j_time;
ObjectDelete("name");
if (ObjectFind(name) < 0)
{
ObjectCreate(name, OBJ_TEXT, WindowFind(short_name), j_time, j_volume);
ObjectSetText(name, j_typebar, 8, "Arial Black", clr); // текст объекта
return;
}

ObjectMove(name, WindowFind(short_name), j_time, j_volume);
ObjectSet(name, OBJ_TEXT, j_typebar);
ObjectSet(name, OBJPROP_COLOR, clr);
}

Вернулся к нему, так как он работает более корректно при смене ТФ.

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





Сообщение: 804
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 16.09.14 21:11. Заголовок: Да, именно о таком в..


Да, именно о таком варианте я и говорил... Только не забудьте в нем убрать кавычки вокруг name.

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



Сообщение: 2
Зарегистрирован: 20.02.14
Репутация: 0
ссылка на сообщение  Отправлено: 18.09.14 08:52. Заголовок: Scriptong пишет: ..


Scriptong пишет:
[quote]`
Добрый день уважаемый Игорь! Пожалуйста помогите с кодом?! Надо написать простой советник по этим индикатор(вложил ссылки ниже). Я сам попробовал, но не получилось. Почему то не возможно получить сигнал от буфер индикатора. Есть какой то способ получить сигнал от него?

Условии: BUY когда линия индикатора више "0" и SELL когда линия индикатора ниже "0".
Очень прощу от вас, пожалуйста помогите?! Жду ваше ответы.

http://qclk.ru/kx/iWuC
http://qclk.ru/kN/OGO51

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





Сообщение: 808
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 18.09.14 09:36. Заголовок: Husanboy пишет: Ест..


Husanboy пишет:

 цитата:
Есть какой то способ получить сигнал от него?


Да. Причем способ очень простой, т. к. обращение к индикатору вовсе не требуется. Его код, отвечающий за расчет значения, умещается в одну строку.

Итак, что нужно сделать:
1. Скопировать в код советника из кода индикатора все настроечные параметры индикатора и тело функции priceSwitch.

2. Получить значения индикатора на двух последних барах:

 цитата:
double lastValue = priceSwitch(1) - iMA(NULL, NULL, DPOPeriod, MaShift, MaType, PriceType, 1);
double preLastSwitch = priceSwitch(2) - iMA(NULL, NULL, DPOPeriod, MaShift, MaType, PriceType, 2);



3. Написать условие для сигнала Buy:

 цитата:
if (lastValue > 0 && preLastValue < 0)
{
// Открыть Buy
}



4. Написать условие для сигнала Sell:

 цитата:
if (lastValue < 0 && preLastValue > 0)
{
// Открыть Sell
}




Советник готов.

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



Сообщение: 3
Зарегистрирован: 20.02.14
Репутация: 0
ссылка на сообщение  Отправлено: 18.09.14 10:16. Заголовок: Scriptong пишет: ..


Scriptong пишет:
[quote]`

Классно!!! Все получилось. Вы самый лучший MQL программист в мире. Спасибо за помощь! Еще раз скажу Вы самый лучший! Спасибо бесконечно!!!!

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





Сообщение: 810
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 19.09.14 08:15. Заголовок: Пожалуйста. Обращайт..


Пожалуйста. Обращайтесь.

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



Сообщение: 4
Зарегистрирован: 20.02.14
Репутация: 0
ссылка на сообщение  Отправлено: 19.09.14 23:30. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
Пожалуйста. Обращайтесь.


Снова приветствую! Уважаемый Игорь есть еще просьба. Вложенный в архиве есть индикатор и советник. С кодом нету ни каких проблему, но не работает в новым билдом метатрейдера(компилируется без ошибки). Помогите пожалуйста?!
http://qclk.ru/ks/0IUp


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 838
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 20.09.14 18:57. Заголовок: Husanboy пишет: С к..


Husanboy пишет:

 цитата:
С кодом нету ни каких проблему, но не работает в новым билдом метатрейдера(компилируется без ошибки). Помогите пожалуйста?!



В прежней версии этот индикатор состоял из 2- частей - сам индикатор RSH.mq4 в котором был такой вызов второго индикатора HullMA.mq4
rel=(iCustom(NULL,0,"HullMA",periodoMA,tipoPrecio,tipoPromedio,0,k)-iCustom(NULL,0,"HullMA",periodoMA,tipoPrecio,tipoPromedio,0,i+1))+iCustom(NULL,0,"HullMA",periodoMA,tipoPrecio,tipoPromedio,0,i)-iCustom(NULL,0,"HullMA",periodoMA,tipoPrecio,tipoPromedio,0,k+1);

В Вашей версии индикатор HullMA введен в индикатор RSH в виде функции и вызов теперь выглядит так:
rel=hma[x]-hma[x+1];

Я взял старую отдельную версию индикатора HullMA и накинул ее на график - она ничего не рисует. Так что проблема в этой части индикатора и
функция hma не работает.
Если получится найти причину и заставить работать hma, то и RSH начнет выдавать сигналы советнику.

Старая версия RSH и HullMA лежит здесь - на FOREX TSD




С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 839
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 20.09.14 20:26. Заголовок: Нашел рабочую версию..


Нашел рабочую версию HullMA от Mladen - Здесь

Так что можно посмотреть как работает советник со старой версией RSH и новой HullMA

С уважением! Спасибо: 0 
ПрофильЦитата Ответить



Сообщение: 5
Зарегистрирован: 20.02.14
Репутация: 0
ссылка на сообщение  Отправлено: 20.09.14 21:29. Заголовок: Genry пишет: Нашел..


Genry пишет:

 цитата:

Нашел рабочую версию HullMA от Mladen - Здесь

Так что можно посмотреть как работает советник со старой версией RSH и новой HullMA

С уважением!



Спасибо за помощь! Я сам исправил и это работает.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 840
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 21.09.14 09:12. Заголовок: Husanboy пишет: Спа..


Husanboy пишет:

 цитата:
Спасибо за помощь! Я сам исправил и это работает.



Ok!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 159
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.11.14 12:37. Заголовок: Делаю советник, одна..


Делаю советник, одна из функций которого, при параметре Symbols=false (не учитывать текущий символ) закрывать все открытые ордера, по всем валютным парам.

FindOrders();
if (CommonProfit>Profit || CommonProfit<-AccountBalance()/100*Loss)
{
while (true)
{
CloseAllOrders();
FindOrders();
if (BuyCount==0 && SellCount==0) break;
}
}

//+-------------------------------------------------------------------------------------+
//| Поиск своих ордеров. |
//+-------------------------------------------------------------------------------------+
void FindOrders()
{
//----
BuyCount = 0; SellCount = 0;
CommonProfit = 0;
//----
for (int i = 0; i < OrdersTotal(); i++) // Используется весь список ордеров
if (OrderSelect(i, SELECT_BY_POS)) // Убедимся, что ордер выбран
if ((OrderMagicNumber() == MagicNumber || MagicNumber<0) // Ордер соответствует настройкам MagicNumber
&& (OrderSymbol() == Symbol() || !Symbols)) // Ордер соответствует настройкам валютной паре
{
CommonProfit += OrderProfit()+OrderSwap(); // Подсчет совокупного профита
if (OrderType() == OP_SELL) SellCount++;
if (OrderType() == OP_BUY) BuyCount++;
}
}
//=======================================================================================

//+-------------------------------------------------------------------------------------+
//| Закрытие позиций |
//+-------------------------------------------------------------------------------------+
void CloseAllOrders()
{
for (int i = 0; i < OrdersTotal(); i++) // Используется весь список ордеров
if (OrderSelect(i, SELECT_BY_POS)) // Убедимся, что ордер выбран
if ((OrderMagicNumber() == MagicNumber || MagicNumber<0) // Ордер соответствует настройкам MagicNumber
&& (OrderSymbol() == Symbol() || !Symbols)) // Ордер соответствует настройкам валютной пары

if (WaitForTradeContext())
{
if (OrderType()==OP_BUY)
if(OrderClose(OrderTicket(), OrderLots(), NT(Bid), Slippeg))
continue;
if (OrderType()==OP_SELL)
if(OrderClose(OrderTicket(), OrderLots(), NT(Ask), Slippeg))
continue;
}
}
//=======================================================================================

Однако, как только параметр устанавливается Symbols=false, советник виснет, когда поступает команда на закрытие позиций, хотя с текущим символом (при Symbols=true) проблем таких нет.
В чем причина,понять не могу.

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





Сообщение: 946
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 2
ссылка на сообщение  Отправлено: 11.11.14 14:24. Заголовок: Sergey пишет: В чем..


Sergey пишет:

 цитата:
В чем причина,понять не могу.


Такой код не сможет закрыть рыночные ордера, открытые по символам, отличным от текущего, т. к. цена закрытия указывается в ценах текущего символа. Для мультивалютных программ следует использовать такую конструкцию закрытия:

 цитата:

double closePrice = SymbolInfoDouble(OrderSymbol(), SYMBOL_BID);
if (OrderType() == OP_SELL)
closePrice = SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK);

if (OrderClose(OrderTicket(), OrderLots(), closePrice, Slippeg))
continue;


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

Также при закрытии ордеров необходимо использовать обратный цикл перебора, а то будете закрывать ордера через один. Ну и не лучшее решение делать бесконечные циклы (while(true)). Как минимум, нужно использовать !IsStopped().



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





Сообщение: 161
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.11.14 14:36. Заголовок: Scriptong пишет: Т..


Scriptong пишет:


 цитата:
Такой код не сможет закрыть рыночные ордера, открытые по символам, отличным от текущего, т. к. цена закрытия указывается в ценах текущего символа. Для мультивалютных программ следует использовать такую конструкцию закрытия:



Блин! Вот я ...... Спасибо!

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





Сообщение: 162
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 13.11.14 16:58. Заголовок: Индикатор виснет на ..


При компиляции выпадает предупреждение old_color и old_startTime (possible loss of data due to type conversion)
Как правильно вывести данные по объекту?

double old_y1=ObjectGet(ObjName, OBJPROP_PRICE1);
double old_y2=ObjectGet(ObjName, OBJPROP_PRICE2);
color old_color=ObjectGet(ObjName, OBJPROP_COLOR);
datetime old_startTime=ObjectGet(ObjName, OBJPROP_TIME1);
Аналогично для
int A=round(B);
Как преобразовать данные? В учебнике ничего нет, или не могу найти где смотреть.

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





Сообщение: 163
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 16.11.14 08:49. Заголовок: Возможно мой вопрос ..


Возможно мой вопрос был не замечен, а потому просто повторюсь.

Sergey пишет:


 цитата:
В режиме # property strict При компиляции выпадает предупреждение old_color и old_startTime (possible loss of data due to type conversion)
Как правильно теперь вывести данные по объекту?

double old_y1=ObjectGet(ObjName, OBJPROP_PRICE1);
double old_y2=ObjectGet(ObjName, OBJPROP_PRICE2);
color old_color=ObjectGet(ObjName, OBJPROP_COLOR);
datetime old_startTime=ObjectGet(ObjName, OBJPROP_TIME1);

Аналогично для
int A=round(B);
Как преобразовать данные? В учебнике ничего нет, или не могу найти где смотреть.



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





Сообщение: 962
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 16.11.14 16:05. Заголовок: Sergey пишет: Возмо..


Sergey пишет:

 цитата:
Возможно мой вопрос был не замечен, а потому просто повторюсь.


Да, действительно, не заметил. Прошу прощения.

Sergey пишет:

 цитата:
При компиляции выпадает предупреждение old_color и old_startTime (possible loss of data due to type conversion)
Как правильно вывести данные по объекту?

double old_y1=ObjectGet(ObjName, OBJPROP_PRICE1);
double old_y2=ObjectGet(ObjName, OBJPROP_PRICE2);
color old_color=ObjectGet(ObjName, OBJPROP_COLOR);
datetime old_startTime=ObjectGet(ObjName, OBJPROP_TIME1);
Аналогично для
int A=round(B);
Как преобразовать данные? В учебнике ничего нет, или не могу найти где смотреть.


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

Суть проблемы заключается в том, что функция ObjectGet возвращает значение типа double, которое в коде присваивается типам color и datetime соответственно. Таким образом, имеем неявное приведение типов данных с возможной потерей точности значения. Именно об этом напоминает компилятор, заботясь о том, чтобы программа оперировала валидными данными.
Для решения вопроса есть два пути:

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

 цитата:
color old_color=(color)ObjectGet(ObjName, OBJPROP_COLOR);
datetime old_startTime=(datetime)ObjectGet(ObjName, OBJPROP_TIME1);
int A = (int)round(B);



2. Использовать специальные функции нового MQL4. Правда, для переменных типа color и datetime этот способ не поможет - нет для них специальных функций. А потому все равно придется прибегать к явному приведению:

 цитата:
color old_color=(color)ObjectGetInteger(0, ObjName, OBJPROP_COLOR);
datetime old_startTime=(datetime)ObjectGetInteger(0, ObjName, OBJPROP_TIME, 1);



Тем не менее, второй способ выгоднее тем, что делает код более универсальным. В будущем такой код будет проще портировать в MQL5.

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





Сообщение: 164
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 16.11.14 18:55. Заголовок: Спасибо! Все понятно..


Спасибо! Все понятно и все работает!

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





Сообщение: 165
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 17.11.14 23:12. Заголовок: Хочу сделать контрол..


Хочу сделать контроль тестового времени эксперта с использованием глобальных переменных.
Проблема в этой строке if (!GlobalVariableGet(ControlTimeExpert, TimeExpertControl)) return; // Вызов гл.пер.
Если ставлю &TimeExpertControl идет ошибка, а без & срабатывает return.
Возможно есть еще ошибки, не знаю.

string ControlTimeExpert;
double TimeExpertControl;
int j_TimeExpertControl;
datetime LastBar;

if (LastBar != iTime(NULL,PERIOD_D1,0)) // Если новый день, то делаем проверку
{
if (!GlobalVariableCheck(ControlTimeExpert)) // Если гл.пер. нет, то создаем
GlobalVariableSet(ControlTimeExpert,TimeCurrent()); // Время первого запуска советника
if (!GlobalVariableGet(ControlTimeExpert, TimeExpertControl)) return; // Вызов гл.пер.
j_TimeExpertControl=(int)TimeExpertControl;
if (TimeCurrent()>j_TimeExpertControl+7*24*60*60) // 7 суток на проверку
{
Alert("Время тестирования советника истекло");
return;
}
}
LastBar = iTime(NULL,PERIOD_D1,0);

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





Сообщение: 969
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 18.11.14 10:12. Заголовок: На вскидку код верны..


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

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

 цитата:
input datetime i_currentTime = __DATE__;

datetime g_testExpirationDate;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
g_testExpirationDate = i_currentTime + PERIOD_D1 * 60;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if (TimeCurrent() > g_testExpirationDate)
{
Alert("Срок демо-версии истек. Советник отключен!");
ExpertRemove();
return;
}
}



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





Сообщение: 166
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.11.14 10:35. Заголовок: Для отдельных пользо..


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

Scriptong пишет:


 цитата:
На вскидку код верный, если подразумевать, что приведен только участок кода, а не весь код. Если же это весь код, тогда проблема в том, что переменная ControlTimeExpert не инициализирована.



Вообще то это весь код. Но кажется я понял. string ControlTimeExpert= "ControlTimeEA"; Теперь задана как название гл.переменной в начале. Попробую.

Остался вопрос:
Чтобы осознать не бесполезность своих действий, подскажите где хранятся глобальные переменные? Я к примеру не знаю, думаю и большинство трейдеров тоже.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 946
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 18.11.14 13:35. Заголовок: Sergey пишет: Остал..


Sergey пишет:

 цитата:
Остался вопрос: Чтобы осознать не бесполезность своих действий, подскажите где хранятся глобальные переменные? Я к примеру не знаю, думаю и большинство трейдеров тоже.



Сергей, список появится при нажатии в терминале клавиши F3, его можно менять и удалять.

Могу добавить, что время тестового периода явно прописанное в программе, по крайней мере в старых билдах интерпретатора, видно при открытии
файла в редакторе (типа FAR, например). Т.е получив сообщение о том, что тестовый период истек - нажимается F4, поиск по дате, а потом год
меняется с 2014 на 3014... ву а ля.
Поэтому после компиляции имел смысл обработать код программой защиты от декомпиляции - программой типа ex4_protector.


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 167
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.11.14 13:43. Заголовок: Хреново! Идея была н..


Хреново! Идея была неплохой, как мне казалось. Развалилась простым нажатием F3.
У кого есть идеи по-лучше?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 947
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 18.11.14 13:45. Заголовок: Перечитай мой пост ..


Sergey пишет:

 цитата:
Хреново! Идея была неплохой, как мне казалось. Развалилась простым нажатием F3. У кого есть идеи по-лучше?



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

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 168
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.11.14 13:57. Заголовок: А если в коде пропис..


А если в коде прописать создание отдельного файла хранящего информацию о времени. И затем, при необходимости, вызывать эти данные. Такое возможно? Если да, то где об этом почитать?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 948
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 18.11.14 14:02. Заголовок: Sergey пишет: А есл..


Sergey пишет:

 цитата:
А если в коде прописать создание отдельного файла хранящего информацию о времени. И затем, при необходимости, вызывать эти данные. Такое возможно? Если да, то где об этом почитать?


тогда надо будет шифровать данные в файле или подписывать, иначе их можно просто поменять.
А чем плох вариант Игоря? Или есть желание менять только файл лицензии с демо на коммерческий без замены самой программы?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 169
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.11.14 15:27. Заголовок: Genry пишет: А чем..


Genry пишет:


 цитата:
А чем плох вариант Игоря?



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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 949
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 18.11.14 14:06. Заголовок: Sergey пишет: Если ..


Sergey пишет:

 цитата:
Если да, то где об этом почитать?



Например здесь: Методы защиты и взлома программ для торговли на Форекс.

Если все элементы секрета находятся у злоумышленника - то взлом это вопрос времени, добавит трудностей взломщику перенос части кода в dll.
Наиболее стойкая защита - это когда разделен и секрет, и алгоритм работы программы.
Здесь повторюсь: надо соизмерять собственные затраты на защиту (и неудобство от ее применения - например, пользователь не понимая
значения файла с датой его случайно удалил, получил сбой в торговле большими деньгами и выкатил претензию) с доходами от продажи.


С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 950
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 18.11.14 16:44. Заголовок: Sergey пишет: А хоч..


Sergey пишет:

 цитата:
А хочется не заморачиваться под каждого. Дать возможность пользователям скачивать, но автоматически ограничивать время с начала первого запуска.



Сергей, это путь сопряжен с различными проблемами. Отследить внешний файл и удалить его трудностей не составит, и снова наступил 1 запуск.
Лучше сделать полноценное Демо для какого-то экзотического инструмента, а остальные валюты - в коммерческой версии. Короче дать
полное представление о возможностях работы и ограничить по функционалу. Например история берется только за несколько дней назад, а не вся.
Или работать будет только на Демо-счете или закрыт прогон в тестере.
Вот и будут две версии, одна - демо доступная всем и всегда, вторая - коммерческая, которая берется с закрытого раздела сайта после оплаты или еще как-нибудь

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 170
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.11.14 18:22. Заголовок: Genry пишет: Серге..


Genry пишет:


 цитата:
Сергей, это путь сопряжен с различными проблемами. Отследить внешний файл и удалить его трудностей не составит



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

Genry пишет:


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



Этот стандартный подход хотелось немного дополнить.

А что касается 1% спецов, то любая защита для них не проблема. И вряд ли они могут заинтересоваться моими продуктами.


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





Сообщение: 972
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 18.11.14 21:08. Заголовок: Наиболее оптимальный..


Наиболее оптимальный способ демо-версии для советников - это пожизненная демо-версия для демо-счетов. В MQL4 тип счета определяется так:

 цитата:
ENUM_ACCOUNT_TRADE_MODE accountType = (ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
switch (accountType)
{
case ACCOUNT_TRADE_MODE_DEMO: Print("Демо-счет"); break;
case ACCOUNT_TRADE_MODE_CONTEST: Print("Конкурсный счет"); break;
case ACCOUNT_TRADE_MODE_REAL: Print("Реальный счет"); break;
}


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

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





Сообщение: 172
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 19.11.14 06:28. Заголовок: Спасибо всем! Есть в..


Игорь пишет:


 цитата:
Наиболее оптимальный способ демо-версии для советников - это пожизненная демо-версия для демо-счетов.



Идея была в защите демо-версии от копировальщиков ордеров.

Так или иначе, но Спасибо Всем! Есть вещи о которых не знал, теперь картина немного прояснилась.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 953
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 2
ссылка на сообщение  Отправлено: 19.11.14 09:21. Заголовок: Sergey пишет: Так ..


Sergey пишет:

 цитата:
Так или иначе, но Спасибо Всем! Есть вещи о которых не знал, теперь картина немного прояснилась.





С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 978
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 19.11.14 21:51. Заголовок: Sergey пишет: Идея ..


Sergey пишет:

 цитата:
Идея была в защите демо-версии от копировальщиков ордеров.


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

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





Сообщение: 177
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 24.11.14 17:39. Заголовок: Столкнулся с такой п..


Столкнулся с такой проблемой. При выводе StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL)*Point; // текущий уровень стопов
через Alert StopLevel=0.0 Однако в реалии брокер не дает устанавливать уровень столосс ближе 30 pip на пятизнаке.(Пробовал в ручную перетащить не получилось.) При этом TP перетащить на Ask для Buy ордеров можно. Получается, что функция проверки расчета уровней SL и TP и корректной установки или модификации ордеров, использующие StopLevel в качестве минимального уровня - бутафория.
Как выяснить действительный уровень? И почему они разные для SL и TP. Даже с учетом спреда ни чего не стыкуется. Спред всего 10-15 pip.

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





Сообщение: 997
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 24.11.14 22:11. Заголовок: Sergey пишет: Столк..


Sergey пишет:

 цитата:
Столкнулся с такой проблемой. При выводе StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL)*Point; // текущий уровень стопов
через Alert StopLevel=0.0 Однако в реалии брокер не дает устанавливать уровень столосс ближе 30 pip на пятизнаке.


Этим грешит Alpari. Возможно, есть другие брокеры. Стоплевел у них завуалированный - устанавливать стопы и отложки не ближе, чем 2 спреда. В своей библиотеке пришлось извратится следующим образом:


 цитата:
m_symbolInfo.digits = (int) SymbolInfoInteger(m_symbol, SYMBOL_DIGITS);
m_symbolInfo.point = SymbolInfoDouble(m_symbol, SYMBOL_POINT);

m_symbolInfo.tickSize = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_SIZE);

m_symbolInfo.ask = SymbolInfoDouble(m_symbol, SYMBOL_ASK);
m_symbolInfo.bid = SymbolInfoDouble(m_symbol, SYMBOL_BID);
m_symbolInfo.spread = m_symbolInfo.ask - m_symbolInfo.bid;

m_symbolInfo.freezeLevel = NormalizeDouble(MarketInfo(m_symbol, MODE_FREEZELEVEL) * m_symbolInfo.point, m_symbolInfo.digits);
m_symbolInfo.stopLevel = MarketInfo(m_symbol, MODE_STOPLEVEL) * m_symbolInfo.point;

// Коррекция Stop Level ля тех ДЦ, в которых его вроде бы нет (но на самом деле есть - скрытый) и для тех ДЦ, у которых есть. Для последних увеличивается на тик для повышения надежности
if (m_symbolInfo.stopLevel == 0)
{
if (!m_isECN)
m_symbolInfo.stopLevel = NormalizeDouble(2 * m_symbolInfo.spread, m_symbolInfo.digits);
}
else
m_symbolInfo.stopLevel = NormalizeDouble(m_symbolInfo.stopLevel + m_symbolInfo.tickSize, m_symbolInfo.digits);



Здесь m_isECN указывает программе, что нулевому стоплевелу можно верить. В противном случае используется вариант для Альпари.

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





Сообщение: 178
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 25.11.14 08:02. Заголовок: Scriptong пишет: Э..


Scriptong пишет:


 цитата:
Этим грешит Alpari.



В самую точку. Счета стандарт. Еще слышал об Альфа-банке.
Ситуацию понял. Но предложенный подход тоже не идеален. Во-первых потому, что спред плавающий, а m_symbolInfo.stopLevel возможно постоянный. Во-вторых под одну гребенку меряем все ДЦ с m_symbolInfo.stopLevel=0.
Созрела такая идея: Первоначальную информацию о m_symbolInfo.stopLevel получаем в int OnInit(). Далее при не удачной установке или модификации ордеров с ошибкой 130, запускаем функцию расчета m_symbolInfo.stopLevel в теле программы. Однако возникает новая проблема: Если m_symbolInfo.stopLevel величина постоянная - увеличение лучше делать по-шагово, скажем + 2pip. Один раз рассчитал и дальше проблем нет. А если плавающая и зависящая от спреда, то как предложено выше, но на каждом тике. И при этом нужно четко знать коэффициент увеличения.
Выходит нужен дополнительный механизм получения информации.


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





Сообщение: 1001
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 25.11.14 18:42. Заголовок: Sergey пишет: Но п..


Sergey пишет:

 цитата:
Но предложенный подход тоже не идеален.


Подход не идеален лишь потому, что от пользователя требуется правильная установка параметра m_isECN. Если пользователь укажет, что счет относится к ECN, а это на самом деле не так, то советник не сможет открыть ни одного ордера, если стопы/профиты располагаются слишком близко к базовой цене ордера.

Sergey пишет:

 цитата:
Во-первых потому, что спред плавающий, а m_symbolInfo.stopLevel возможно постоянный


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

Sergey пишет:

 цитата:
Во-вторых под одну гребенку меряем все ДЦ с m_symbolInfo.stopLevel=0.


Нет. Я ведь указал на параметр m_isECN.

Sergey пишет:

 цитата:
Далее при не удачной установке или модификации ордеров с ошибкой 130


К сожалению, получение ошибки №130 не дает нам гарантии того, что мы оперируем неправильным стоплевелом. Она, к примеру, может говорить о том, что тип исполнения Market Execution и мы пытаемся установить стопы/профиты в момент открытия рыночного ордера. Правда, это не очень удачный пример, т. к. тип исполнения уже можно узнать в новом MQL4. А вот тип счета (ECN или стандарт) программно узнать невозможно. Отсюда и куча проблем с этим стоплевелом.

Sergey пишет:

 цитата:
Выходит нужен дополнительный механизм получения информации.


Остается лишь надеяться на то, что в язык будет добавлена соответствующая функция, которая позволит программе самой определить тип счета, а значит и способ расчета Stop Level.

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





Сообщение: 179
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 25.11.14 20:42. Заголовок: Scriptong пишет: Н..


Scriptong пишет:


 цитата:
Нет. Я ведь указал на параметр m_isECN.



Я не о счетах ECN. Я о брокерах, которые реально выдерживают Stop Level=0 на других счетах.

Scriptong пишет:


 цитата:
К сожалению, получение ошибки №130 не дает нам гарантии того, что мы оперируем неправильным стоплевелом.



В таком случае мудрить с кодом не буду и как всегда последую опыту и профессионализму.
Спасибо!

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





Сообщение: 1008
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 26.11.14 20:03. Заголовок: Sergey пишет: Я не ..


Sergey пишет:

 цитата:
Я не о счетах ECN. Я о брокерах, которые реально выдерживают Stop Level=0 на других счетах.


Возможно, я неправильно назвал параметр, ошибочно предполагая, что нулевой стоплевел есть только на счетах типа ECN или STP. То есть речь только о неудачном названии, но не о сути параметра. Смысл в том, чтобы пользователь поставил его в "Да", когда у брокера реально нулевой стоплевел.

Посмотрел, как видно этот параметр в списке входных параметров. Получается не так уж и двузначно, вопрос конкретный: "Установить нулевой StopLevel?"



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





Сообщение: 181
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 29.11.14 07:54. Заголовок: Scriptong пишет: С..


Scriptong пишет:


 цитата:
Смысл в том, чтобы пользователь поставил его в "Да", когда у брокера реально нулевой стоплевел.



Я уже сообразил. Но в место да-нет решил установить коэффициент отступа в спредах, если счета не ECN. Предполагая, что отступ не всегда равен двум спредам, даю возможность настраивать StopLeve пользователю под любого брокера.

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





Сообщение: 1020
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 30.11.14 20:45. Заголовок: Sergey пишет: Но в ..


Sergey пишет:

 цитата:
Но в место да-нет решил установить коэффициент отступа в спредах, если счета не ECN.


Достаточно веское замечание. Ведь два спреда советует только Alpari. У других брокеров может быть иное значение.
И тут уже разворачиваем фантазию дальше: что, если брокер нам заявит, что отступ в спредах также не постоянный? Хотя это, конечно, уже вообще беспредел, мухлеж чистой воды. От таких "брокеров" нужно уходить сразу же после подобного ответа.

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





Сообщение: 182
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.12.14 20:19. Заголовок: Вернусь к старой тем..


Вернусь к старой проблеме.

Scriptong пишет:


 цитата:
Перекомпиляция программы перед отправкой - секундное дело, больше времени потратите на отправку письма.



Genry пишет:


 цитата:
Поэтому после компиляции имел смысл обработать код программой защиты от декомпиляции - программой типа ex4_protector.



Есть у кого нибудь рабочая версия перекомпилятора (free)? Скачал несколько версий ex4_protector, но все время выскакивают ошибки. Вроде все просто, но не получается.

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





Сообщение: 1030
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 03.12.14 20:27. Заголовок: Sergey пишет: Есть ..


Sergey пишет:

 цитата:
Есть у кого нибудь рабочая версия перекомпилятора (free)? Скачал несколько версий ex4_protector, но все время выскакивают ошибки. Вроде все просто, но не получается.


К сожалению, никогда не пользовался подобными "защитниками". Могу лишь сделать предположение о том, что эта версия разработана для старой версии MQL4. Для новой версии MQL4 подобные дополнительные защиты не нужны - новый компилятор на выходе выдает нативный код, который не так уж и легко взломать.

Даже если его и взломают, то почему таким профи будет не под силу взломать любую другую защиту, тем более распространяемую в сети?

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

Используйте ООП!

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





Сообщение: 183
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.12.14 21:45. Заголовок: Scriptong пишет: И..


Scriptong пишет:


 цитата:
Используйте ООП



"Чем дальше в лес, тем больше дров" Так и у меня. Что такое написание кода объектно-ориентированным способом?

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





Сообщение: 1032
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 04.12.14 17:18. Заголовок: Sergey пишет: Что т..


Sergey пишет:

 цитата:
Что такое написание кода объектно-ориентированным способом?


Использование классов.
Для этого любая задача разбивается на две и более подзадачи (как представляется удобнее для конкретного случая). Это подзадачи первого уровня. Они оформляются в виде классов, замкнутых в себе. Для передачи данных между этими классами создаются интерфейсы, которые гарантируют целостность данных в пределах одного класса, т. е. данные класса имеет право изменять только сам класс, и никто другой.

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

Простые задачи решать путем ООП, чаще всего, невыгодно. Но как только возникает задача хотя бы среднего уровня выигрыш от использования ООП становится очевидным.

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





Сообщение: 184
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 05.12.14 17:03. Заголовок: Спасибо. Конечно, с ..


Спасибо. Конечно, с примерами было бы лучше, но в целом понятно.

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





Сообщение: 1034
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 05.12.14 18:33. Заголовок: Sergey пишет: Спаси..


Sergey пишет:

 цитата:
Спасибо. Конечно, с примерами было бы лучше, но в целом понятно.


К сожалению, одними примерами не отделаться. На эту тему пишут книги по 300-400 страниц. Классы неплохо описаны у Шилдта, даже несмотря на то, что это справочник, а не полноценный учебник. Читайте с 237-ой страницы. Там, конечно, все про C++, но почти все справедливо и для современного MQL4. Если что-то будет непонятно, спрашивайте.

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





Сообщение: 196
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 02.02.15 10:14. Заголовок: Можно ли объекты тип..


Можно ли объекты типа ARROW привязавать к таким координатам? Ошибка не выдается, однако объект не отображается. Объект нужно отобразить в окне графика справа от него.

ObjectCreate("SD_D1_2", OBJ_ARROW, WindowFind(short_name), 10, 35);
ObjectSet("SD_D1_2", OBJPROP_ARROWCODE, 110);
ObjectSet("SD_D1_2", OBJPROP_WIDTH, 3);
ObjectSet("SD_D1_2", OBJPROP_CORNER,1); // угол пивязки
ObjectSet("SD_D1_2", OBJPROP_COLOR, UpColor);

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





Сообщение: 1165
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 02.02.15 19:35. Заголовок: Sergey пишет: Можно..


Sergey пишет:

 цитата:
Можно ли объекты типа ARROW привязавать к таким координатам?


Нет, нельзя.
Перечень типов объектов, для которых это разрешено, смотрите здесь.

Sergey пишет:

 цитата:
объект не отображается


Он отображается, но на 10-ом баре по цене 35 (где-то вверху, если график EURUSD).

Ошибку же проверяйте после вызова:

 цитата:
ObjectSet("SD_D1_2", OBJPROP_CORNER,1); // угол пивязки



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





Сообщение: 197
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 13.02.15 09:42. Заголовок: Нужно ограничить дем..


Нужно ограничить демку по валютной паре. Однако некоторые ДЦ используют, как мне сказали, префиксы и суффиксы. Я с этим не сталкивался, а потому проверить правильность кода не могу. Прошу дать квалифицированную оценку.

extern string prefix = "";
extern string suffix = "";

if (Symbol()!=prefix + "EURUSD" + suffix)
{
Alert("Demo version is only for EURUSD");
return(0);
}

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





Сообщение: 1194
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 16.02.15 21:35. Заголовок: Делайте проще: if (S..


Делайте проще:

 цитата:
if (StringFind(Symbol(), "EURUSD") < 0)
{
Alert("Demo version is only for EURUSD");
return(0);
}



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





Сообщение: 203
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 17.02.15 01:56. Заголовок: Scriptong пишет: Де..


Scriptong пишет:

 цитата:
Делайте проще:



Спасибо!

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





Сообщение: 222
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 09.03.15 16:25. Заголовок: Сейчас в темах затро..


Сейчас в темах затронуты уровни фибоначчи. Я раньше не сталкивался с проекцией. Она рисуется по 3 точкам. Как уровни проекции рассчитать математически для использования в советниках.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1298
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 09.03.15 17:49. Заголовок: Sergey пишет: Я ран..


Sergey пишет:

 цитата:
Я раньше не сталкивался с проекцией.


Расширение Фибоначчи?

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





Сообщение: 224
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 09.03.15 18:13. Заголовок: Нет проекция ..


Нет проекция


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1300
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 09.03.15 18:44. Заголовок: Sergey пишет: Нет п..


Sergey пишет:

 цитата:
Нет проекция


Этот объект называется "Расширение Фибоначчи"



Расширение представляет собой совокупность двух объектов "Линии Фибоначчи":


На рисунке:
    1. Красные линии - линии от расширения Фибо.
    2. Зеленая - от линий Фибо, которая совпадает с первой красной линией расширения.
    3. Темно-желтая - от линий Фибо, которая совпадает со второй линией расширения.


То есть мы взяли первый диапазон цен (зеленые линий Фибо и две первые точки расширения Фибо), потом в произвольном месте определили третью точку расширения (как бы откат), а затем хотим найти, куда будет двигаться цена, если за основу взять высоту волны от первых двух точек. Для этого взяли еще один объект "Линии Фибо" с таким же расстоянием между 0 и 100, как у первого объекта, но за ноль приняли третью точку расширения Фибо.

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





Сообщение: 225
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 09.03.15 20:13. Заголовок: Scriptong пишет: То..


Scriptong пишет:

 цитата:
То есть мы взяли первый диапазон цен (зеленые линий Фибо и две первые точки расширения Фибо), потом в произвольном месте определили третью точку расширения (как бы откат), а затем хотим найти, куда будет двигаться цена, если за основу взять высоту волны от первых двух точек. Для этого взяли еще один объект "Линии Фибо" с таким же расстоянием между 0 и 100, как у первого объекта, но за ноль приняли третью точку расширения


Все понял. Спасибо. Расчет делаем по первым двум точкам, а отсчитываем от третьей.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 226
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 09.03.15 20:18. Заголовок: Scriptong пишет: Эт..


Scriptong пишет:

 цитата:
Этот объект называется "Расширение Фибоначчи"


В теории, как я теперь понял, "проекция расширения Фибоначчи". Еще раз спасибо за подробное разъяснение.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1302
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 09.03.15 21:15. Заголовок: Sergey пишет: В тео..


Sergey пишет:

 цитата:
В теории, как я теперь понял, "проекция расширения Фибоначчи".


Так как мы подразумеваем терминал МТ4 (в крайнем случае - МТ5), то я ориентируюсь на его терминологию, чтобы не возникало путаницы.

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





Сообщение: 250
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.04.15 19:42. Заголовок: Нужно сделать push-у..


Нужно сделать push-уведомление и уведомление на e-mail.

C push-уведомлением вроде бы разобрался:
extern bool PushON = true;
if (PushON)
SendNotification("текст");

С e-mail-ом сложнее, не нашел примеров.
Пожалуйста подскажите.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1726
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 04.04.15 13:41. Заголовок: Sergey пишет: С e-m..


Sergey пишет:

 цитата:
С e-mail-ом сложнее, не нашел примеров. Пожалуйста подскажите.



Привет, Сергей!

А в доке есть, главное еще настроить в терминале параметры почты.

SendMail

Посылает электронное письмо по адресу, указанному в окне настроек на закладке "Почта".

Пример вызова: if (alertsEmail) SendMail("Message from MQL-Expert ", " Тrend UP");

bool SendMail(
string subject, // заголовок
string some_text // текст письма
);


Параметры

subject

[in] Заголовок письма.

some_text

[in] Тело письма.

Возвращаемое значение

true – если письмо поставлено в очередь на отсылку, иначе возвращает false.

Примечание

Отсылка может быть запрещена в настройках, также может быть не указан адрес электронной почты. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().

При работе в тестере стратегий функция SendMail() не выполняется.


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 251
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 04.04.15 19:17. Заголовок: Спасибо Genry!..


Спасибо Genry! Все оказалось так же просто.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1451
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 08.04.15 19:25. Заголовок: Sergey пишет: Спаси..


Sergey пишет:

 цитата:
Спасибо Genry! Все оказалось так же просто.


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

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





Сообщение: 266
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 16.04.15 18:48. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В итоге все это описал в статье Сигнальные уровни.



Спасибо! Взял на заметку нюансы.

Я решил написать советник для ручной парной торговли. Но не хочется изобретать велосипед. Тем более, что по первому разу получается не очень ... Игорь, есть ли у вас на примете готовый открытый код, подобный функции "Торговля в один клик" в терминале МТ4. Буду очень благодарен за помощь.
Еще интересует такой вопрос - как в кнопке сделать надпись в две строчки. Спасибо.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





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


Sergey пишет:

 цитата:
Игорь, есть ли у вас на примете готовый открытый код, подобный функции "Торговля в один клик" в терминале МТ4


То, что есть, уже безнадежно устарело (к примеру, Графическое управление экспертом), т. к. основано на зацикливании экспертов. В новом MQL4 такие вещи решаются без зацикливания, используя события, т. е значительно проще.

Sergey пишет:

 цитата:
Еще интересует такой вопрос - как в кнопке сделать надпись в две строчки.


Кнопка в MQL4 - это потомок класса CChartObjectText, основанном на графическом объекте Label. Поэтому можно наследовать свой объект от кнопки, в котором сделать эту кнопку, состоящей из двух Label, стоящих одна под другой. Если же неохота влезать в дебри ООП, то можно в область отображения кнопки добавить еще один Label, под основной надписью. Но в коде такой вариант будет выглядеть некрасиво, да и пользоваться им будет неудобно - всегда необходимо помнить о том, что при изменении свойств кнопки следует изменить свойства второго Label. При работе с ООП такая необходимость отпадет само собой.

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





Сообщение: 267
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 17.04.15 10:23. Заголовок: 1. В объектах типа O..



Как в объектах типа OBJ_EDIT ограничить ввод текста только форматом double?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1489
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 20.04.15 16:00. Заголовок: Пока приходит в голо..


Пока приходит в голову только вариант со своим полем ввода.
То есть использовать OBJ_LABEL (или OBJ_TEXT), для которого подписаться на события нажатия клавиш (обработчик OnChartEvent, событие CHART_EVENT_KEYDOWN). В обработчике проверяется код нажатой клавиши (из параметра lparam) и, если это цифра или точка, то символ копируется в объект. Иначе- пропускается. Но для такого поля ввода не совсем понятно, как сделать, чтобы был виден курсор, да еще и мигал.

Для других вариантов нужно смотреть класс CButton (MQL4\Include\Controls\Button.mqh) и думать, есть ли варианты по наследованию и переделке класса.

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





Сообщение: 268
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 20.04.15 17:30. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
Пока приходит в голову только вариант со своим полем ввода.


Спасибо. В целом идея понятна.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 277
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 05.05.15 18:08. Заголовок: Есть ли варианты! Ну..


Есть ли варианты! Нужно чтобы созданные индикатором объекты (вертикальные линии) не перерисовывались при смене ТФ, но удалялись при удалении индикатора с графика. Хочу задать диапазон расчета индикатора, который бы устанавливался перетаскиванием линий и не менялся при смене ТФ.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1526
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 06.05.15 08:57. Заголовок: Нужно анализировать ..


Нужно анализировать причину деинициализации:

 цитата:
void OnDeinit(const int reason)
{
if (reason != REASON_CHARTCHANGE)
{
// Удалить объекты
}
else
{
// Не удалять объекты
}
}



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





Сообщение: 278
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 06.05.15 20:48. Заголовок: Scriptong пишет: Ну..


Scriptong пишет:

 цитата:
Нужно анализировать причину деинициализации:



Спасибо! Все получилось.


 цитата:

void OnDeinit(const int reason)
{
//----
if (reason==REASON_REMOVE)
{
ObjectDelete(SIGN_RLINE);
ObjectDelete(SIGN_LLINE);
}
DeleteAllObjects();
//----
return;
}



С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1529
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 07.05.15 13:01. Заголовок: Sergey пишет: Спаси..


Sergey пишет:

 цитата:
Спасибо! Все получилось.


М-м. Этот код удаляет объекты в любом случае. Или у Вас какая-то специальная версия функции DeleteAllObjects?

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





Сообщение: 280
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 07.05.15 18:25. Заголовок: Scriptong пишет: Ил..


Scriptong пишет:

 цитата:
Или у Вас какая-то специальная версия функции DeleteAllObjects?


Скорее наоборот. DeleteAllObjects отбирает объекты по префиксу, а у вертикальных линий их нет.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1535
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 08.05.15 13:36. Заголовок: Sergey пишет: Скоре..


Sergey пишет:

 цитата:
Скорее наоборот. DeleteAllObjects отбирает объекты по префиксу, а у вертикальных линий их нет.


То есть индикатор создает объекты с префиксом. Эти объекты нужно удалять при каждой деинициализации. Также индикатор создает два объекта без префикса. Такие объекты нужно удалять только в случае удаления индикатора с графика.
Такая вот логика выходит.

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





Сообщение: 282
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 08.05.15 18:27. Заголовок: Scriptong пишет: То..


Scriptong пишет:

 цитата:
То есть индикатор создает объекты с префиксом. Эти объекты нужно удалять при каждой деинициализации. Также индикатор создает два объекта без префикса. Такие объекты нужно удалять только в случае удаления индикатора с графика.


Верно. Вроде все просто, но по функционалу получилось круто. Огромное спасибо за помощь!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 284
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 15.05.15 07:30. Заголовок: Иногда сталкиваюсь с..


Иногда сталкиваюсь с проблемами, когда при компиляции ошибок не выдается, но индикатор не работает должным образом или сильно тормозит комп. (при смене ТФ, смене символа, перезагрузки компа). Причины могут быть разные - не верно заданные размеры массивов, нехватка глубины исторических данных и много чего еще. Такие ошибки я ищу с помощью меток (Alert). Существует ли другая технология поиска скрытых ошибок? Как пользоваться "Отладкой" - слово обнадеживающее, а функционал не понятен. Где обо всем об этом можно узнать?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1547
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 15.05.15 14:45. Заголовок: Sergey пишет: Сущес..


Sergey пишет:

 цитата:
Существует ли другая технология поиска скрытых ошибок?


Технология одна и та же - как можно подробнее вывести в журнал значения переменных и проследить по этим сообщениям маршрут выполнения программы. Если программа достаточно большая, то сначала распечатываются данные по основным блокам с целью нахождения проблемного блока, а затем переход на более низкий уровень (внутри проблемного блока) распечатки значений. И так до тех пор, пока не будет найдена ошибка.

Sergey пишет:

 цитата:
Как пользоваться "Отладкой" - слово обнадеживающее, а функционал не понятен. Где обо всем об этом можно узнать?


Первоисточник описания всегда следует искать в том месте, где находится функционал, требующий описания. Так как отладчик является частью Meta Editor, то необходимо зайти в пункт меню "Справка" ME, нажать "Вызов справки", а затем просмотреть содержание. В данном случае путь к описанию таков: MetaEditor -> Разработка программ -> Отладка. Там дана первичная информация, так сказать, общее описание.
Более подробно пример работы с отладчиком описан в статье "Отладка программ на MQL5". Отладка в МТ4 и МТ5 - процесс практически идентичный.

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

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





Сообщение: 285
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 15.05.15 18:06. Заголовок: Scriptong пишет: Те..


Scriptong пишет:

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


Спасибо! Давно собирался задать этот вопрос, но все не решался.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить



Сообщение: 3
Зарегистрирован: 26.10.14
Репутация: 0
ссылка на сообщение  Отправлено: 17.05.15 19:58. Заголовок: На данный момент проблема отладки - невозможность использования ее в тестере.


В МТ5 уже доступна отладка на исторических данных, видимо будет и на МТ4.

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





Сообщение: 1549
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 17.05.15 20:21. Заголовок: Linker пишет: В МТ5..


Linker пишет:

 цитата:
В МТ5 уже доступна отладка на исторических данных, видимо будет и на МТ4.


Да, как раз недавно анонсирована. Так что ждем...

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





Сообщение: 286
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 18.05.15 11:23. Заголовок: Как прогнать индикат..


Как прогнать индикатор в тестере на истории? Теоретически нужно запустить советник в режиме визуализации не выставляющий ордера и к графику прикрепить тестируемый индикатор. Есть ли еще варианты? Просто не все индикаторы ставятся таким образом на график.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1550
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 18.05.15 14:42. Заголовок: Sergey пишет: Есть ..


Sergey пишет:

 цитата:
Как прогнать индикатор в тестере на истории? Теоретически нужно запустить советник в режиме визуализации не выставляющий ордера и к графику прикрепить тестируемый индикатор. Есть ли еще варианты? Просто не все индикаторы ставятся таким образом на график.


В МТ5 давно существует возможность полноценного тестирования индикаторов. А вот в МТ4 только-только появилось подобное. 810-й билд. Но пока это только бета-версия. Думаю, через пару-тройку недель состоится релиз и можно будет использовать новшество полноценно.


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





Сообщение: 316
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 30.08.15 09:15. Заголовок: Для экономии ресурсо..


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

if (LastBar == Time[0]) return(0);

int limit;
int counted_bars=IndicatorCounted();
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
if (limit>ShowBars)
limit=ShowBars;
if (LastBarDay!=iTime(NULL,PERIOD_D1,0))
{
ObDeleteObjectsByPrefix(PREFIX);
limit=ShowBars;
}
int i;
for (i = limit-1; i >= 0; i--)

Однако столкнулся с такой проблемой: После включения компа на следующий день, индикатор отрисовывается не верно. Как запрограммировать, чтобы при включении компа индикатор пересчитывал всю глубину истории, как при первом запуске.
Прием типа
if (LastBarDay!=iTime(NULL,PERIOD_D1,0))
{
ObDeleteObjectsByPrefix(PREFIX);
limit=ShowBars;
}
Не помогает...



С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1934
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 30.08.15 10:17. Заголовок: Sergey пишет: Однак..


Sergey пишет:

 цитата:
Однако столкнулся с такой проблемой: После включения компа на следующий день, индикатор
отрисовывается не верно. Как запрограммировать, чтобы при включении компа индикатор пересчитывал
всю глубину истории, как при первом запуске.



В этой ветке народ обсуждал вопросы подкачки истории при перезагрузке терминала: http://forum.mql4.com/ru/40689 и
ее влияние на работу индикаторов.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 317
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 30.08.15 10:42. Заголовок: Genry пишет: В этой..


Genry пишет:

 цитата:
В этой ветке народ обсуждал вопросы подкачки истории при перезагрузке терминала


Просмотрел. Дело не в подкачке истории, а в новой инициации индикатора при перезагрузке терминала.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1936
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 30.08.15 19:38. Заголовок: Sergey пишет: Дело ..


Sergey пишет:

 цитата:
Дело не в подкачке истории, а в новой инициации индикатора при перезагрузке терминала.


Обсуждение такой проблемы видел для мт5 здесь: https://www.mql5.com/ru/forum/694
Позже попалось еще здесь по мт4: https://www.mql5.com/ru/forum/34432

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 318
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 31.08.15 10:01. Заголовок: Genry пишет: Обсужд..


Genry пишет:

 цитата:
Обсуждение такой проблемы видел для мт5 здесь: https://www.mql5.com/ru/forum/694
Позже попалось еще здесь по мт4: https://www.mql5.com/ru/forum/34432



Спасибо Генри, все оказалось гораздо проще...

int Start()
{
if (LastBar != Time[0])
{
Тело индикатора
LastBar = Time[0];
}
return(0);
}

Но я в замешательстве, так как не могу понять, чем это отличается от

int Start()
{
if (LastBar == Time[0]) return(0);

Тело индикатора
LastBar = Time[0];
return(0);
}

при перезапуске терминала.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1940
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 31.08.15 11:00. Заголовок: Sergey пишет: LastB..


Sergey пишет:

 цитата:
LastBar == Time[0];



Просто у тебя уже усталость от редактирования и "глаз замылился".

надо присвоить LastBar = Time[0] , а здесь вместо присвоения - сравнение.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 319
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 31.08.15 11:09. Заголовок: Genry пишет: надо п..


Genry пишет:

 цитата:
надо присвоить LastBar = Time[0] , а здесь вместо присвоения - сравнение.



Это я просто копировал верхнюю строку и ошибся. Сейчас исправил.. Вопрос остался..

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1941
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 31.08.15 11:28. Заголовок: Sergey пишет: .. Во..


Sergey пишет:

 цитата:
.. Вопрос остался..


Тогда причина может быть в части "Тело индикатора"

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1740
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 31.08.15 13:01. Заголовок: Sergey пишет: Для э..


Sergey пишет:

 цитата:
Для экономии ресурсов компьютера расчеты некоторых индикаторов делаю на открытии бара.


В индикаторах нет такой необходимости - делать проверку на открытие нового бара. Для этого у него есть IndicatorCounted() или prev_total и rates_total в новой версии MQL4. На основании этих данных необходимо определить, с какого бара следует обновить значения индикатора.
В моих индикаторах обычно присутствует специальная функция:

 цитата:
int GetRecalcIndex(int &total, const int ratesTotal, const int prevCalculated)
{
total = ratesTotal - /*здесь период индикатора или то, что его заменяет*/ - 2;

if (i_indBarsCount > 0 && i_indBarsCount < total)
total = MathMin(i_indBarsCount, total);

if (prevCalculated < ratesTotal - 1)
{
BuffersInitializeAll();
return total;
}

return (MathMin(ratesTotal - prevCalculated, total));
}



А после расчета индекса бара просто производится новый расчет значений индикатора на измененных барах:

 цитата:
for (int i = limit; i >= 0; i--)
{
// Расчет
}




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





Сообщение: 320
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 31.08.15 14:41. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В индикаторах нет такой необходимости - делать проверку на открытие нового бара.


Но мне нужно, чтобы расчет на нулевом баре был произведен только на его открытии. А в случае
return (MathMin(ratesTotal - prevCalculated, total));
как я понял, делается постоянный (по тиковый) расчет значений нулевого бара, но сам код возьму на вооружение. Спасибо.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1752
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 03.09.15 18:41. Заголовок: Sergey пишет: Но мн..


Sergey пишет:

 цитата:
Но мне нужно, чтобы расчет на нулевом баре был произведен только на его открытии. А в случае
return (MathMin(ratesTotal - prevCalculated, total));
как я понял, делается постоянный (по тиковый) расчет значений нулевого бара, но сам код возьму на вооружение. Спасибо.


Нет проблем:

 цитата:

for (int i = limit; i > 0; i--)
buffer[i - 1] = расчет



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





Сообщение: 322
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 01.09.15 18:46. Заголовок: Кажется наконец наше..


Кажется наконец нашел в чем проблема. Индикатор установлен на 12 валютных парах. Имя объекта string name = PREFIX + IntegerToString(leftTime);
Однако бывает совпадение по времени разных графиков. Предполагаю, что при загрузке терминала обновление данных различных пар идет не синхронно по барам. В результате объекты с одинаковыми именами перерисовываются.
Решение - ввел PREFIX, как настраиваемый параметр. Но это не совсем удобно. Можно привязать к символу, но трейдер может открыть несколько одинаковых графиков.
Есть ли варианты?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 1946
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 01.09.15 23:00. Заголовок: Sergey пишет: Можно..


Sergey пишет:

 цитата:
Можно привязать к символу, но трейдер может открыть несколько одинаковых графиков. Есть ли варианты?


У каждого графика, даже если они одинаковые, есть его уникальный идентификатор, его возвращает функция ChartID.
//--- get handle of the current chart
long handle=ChartID();


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1751
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 03.09.15 18:37. Заголовок: Sergey пишет: Есть ..


Sergey пишет:

 цитата:
Есть ли варианты?


В дополнение к варианту Genry: прибавлять после префикса имя символа и, если нужно, таймфрейм графика.



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





Сообщение: 352
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 01.10.15 09:08. Заголовок: Игорь, в силу ряда р..


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

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 2033
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 01.10.15 09:31. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, в силу ряда реальных обстоятельств пришел к выводу, что брокеры учитывают алгоритм работы
прибыльных советников появившихся в сети. Можно ли программно скрыть имя и настройки советника от брокера.


Думаю при необходимости (или при желании) брокер может со своей стороны через МТ получить доступ к файлам трейдера и выкачать
необходимую информацию.
Так что имеет смысл, получив прибыльного советника, с него вообще не торговать, а копировать его сигналы на пустой МТ где стоит
только копировальщик сделок - имитируя ручное исполнение команд.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 353
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 01.10.15 12:31. Заголовок: Genry пишет: ак что..


Genry пишет:

 цитата:
Так что имеет смысл, получив прибыльного советника, с него вообще не торговать, а копировать его сигналы на пустой МТ где стоит
только копировальщик сделок - имитируя ручное исполнение команд.



Как вариант да, а еще можно выставить 0 магик, сойдет за ручную торговлю. Я торговал 5 месяцев с доходностью 40-80% в месяц и проблем не было, пока не выставил советник на продажу через mql5. Еще ровно месяц торговал, а затем все постепенно свелось к безубытку и что обидно, на демке, как и прежде все в ажуре, по крайней мере, результаты на много лучше. Не хочу отказываться от продаж, вот и ищу варианты.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 2034
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 01.10.15 18:13. Заголовок: Sergey пишет: Еще р..


Sergey пишет:

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


Да, по видимому подобрали индивидуальный фильтр

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1821
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 01.10.15 18:32. Заголовок: Genry пишет: Думаю ..


Genry пишет:

 цитата:
Думаю при необходимости (или при желании) брокер может со своей стороны через МТ получить доступ к файлам трейдера и выкачать
необходимую информацию.


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

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





Сообщение: 1820
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 01.10.15 18:27. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, в силу ряда реальных обстоятельств пришел к выводу, что брокеры учитывают алгоритм работы прибыльных советников появившихся в сети. Можно ли программно скрыть имя и настройки советника от брокера.


Поверьте, вывод в корне неверный. Рынок - это достаточно сложная система, являющаяся надстройкой над социальными процессами. А социальные процессы - это сложнее, чем термоядерные реакции. Для справки: управляемые термоядерные реакции только разрабатываются, но еще далеки от массового использования.

Другое дело, что есть много брокеров, нечистых на руку, которые убивают прибыльные стратегии своим прямым вмешательством.
Потому совет достаточно простой: торгуйте у нормальных брокеров (США, Канада, немного Западная Европа). Как только у брокера в регистрации видите какие-нибудь Виргинские о-ва - бегите от него.

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





Сообщение: 355
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 02.10.15 08:46. Заголовок: Scriptong пишет: Др..


Scriptong пишет:

 цитата:
Другое дело, что есть много брокеров, нечистых на руку, которые убивают прибыльные стратегии своим прямым вмешательством.


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

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1825
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 02.10.15 18:12. Заголовок: Sergey пишет: Появи..


Sergey пишет:

 цитата:
Появились советники в которых авторы вводят параметр скрывающий название эксперта от брокера. Идея перестраховаться будет не лишней. Но как это реализовать не знаю.


Тут придется немного попотеть. Схема такова:
1. Стратегия пишется в виде индикатора или неторгующего советника.
2. Все торговые операции выполняет специальный скрипт, который вызывается из программы (п. 1).
3. "Общение" между скриптом и программой производится через глобальные переменные, именованные каналы или специальную DLL.

Я такое делал в прошлом году. Подобный подход позволяет увеличить скорость отдачи торговых приказов в 8 раз (по числу доступных торговых потоков в МТ4) за счет их распараллеливания.

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





Сообщение: 361
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.10.15 13:14. Заголовок: Scriptong пишет: 3...


Scriptong пишет:

 цитата:
3. "Общение" между скриптом и программой производится через глобальные переменные, именованные каналы или специальную DLL.


Я предполагал наличие иного варианта, так как в mql5 запрещены dll и обращения к иным программам.
Scriptong пишет:

 цитата:
Я такое делал в прошлом году. Подобный подход позволяет увеличить скорость отдачи торговых приказов в 8 раз (по числу доступных торговых потоков в МТ4) за счет их распараллеливания.


Предложенный вариант тоже заинтересовал. Но для его реализации нужен пример (скажем при реализации советника на диверах) или более подробное описание (может в виде статьи).

Есть еще вопрос: Установка TP и SL путем модификации ордера.
if (!OrderModify(OrderTicket(), OpPrice, SL, TP,0))
{
Alert("Ошибка модификации ордера ",Type," = ",GetLastError());
return(false);
}

Выскакивает ошибка - 139 Ордер заблокирован и уже обрабатывается

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

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1829
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 05.10.15 16:16. Заголовок: Sergey пишет: Предл..


Sergey пишет:

 цитата:
Предложенный вариант тоже заинтересовал. Но для его реализации нужен пример (скажем при реализации советника на диверах) или более подробное описание (может в виде статьи).


К сожалению, там достаточно много кода получается. В статьях, которые бы читали другие (кратко и лаконично), его не опишешь.

Sergey пишет:

 цитата:
Есть еще вопрос: Установка TP и SL путем модификации ордера.
if (!OrderModify(OrderTicket(), OpPrice, SL, TP,0))
{
Alert("Ошибка модификации ордера ",Type," = ",GetLastError());
return(false);
}

Выскакивает ошибка - 139 Ордер заблокирован и уже обрабатывается


Скорее всего здесь речь идет о "заморозке" ордера. Это еще одно ограничение кухонь наряду со Stop Level. Называется Freeze Level. Его значение можно получить через:

 цитата:
MarketInfo(_Symbol, MODE_FREEZELEVEL);


Если цена открытия отложенного ордера ближе к текущей цене, чем на уровень заморозки, то ничего с ордером уже нельзя будет сделать. То же самое касается, рыночного ордера, когда рынок подходит слишком близко к Stop Loss и Take Profit.
В последние годы большинство брокеров устанавливают нулевой размер заморозки. Но, по всей видимости, еще остались динозавры .

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





Сообщение: 364
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 06.10.15 08:09. Заголовок: Scriptong пишет: Ск..


Scriptong пишет:

 цитата:
Скорее всего здесь речь идет о "заморозке" ордера.


Что же, придется ввести функцию корректной модификации ордера. и больше с ней не расставаться.


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 1832
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 06.10.15 19:29. Заголовок: Да, Sergey пишет: Ч..


Да, Sergey пишет:

 цитата:
Что же, придется ввести функцию корректной модификации ордера. и больше с ней не расставаться.


Да, для каждой торговой операции перед ее выполнением следует выполнять целый комплекс проверок на предмет корректности параметров. Если речь идет о модификации отложенного ордера, то список таков:
    1. Если изменяется цена открытия ордера, то:
      1.1 Проверить расстояние между текущей рыночной ценой и текущей ценой открытия на предмет попадания в коридор Freeze Level.
      1.2 Проверить расстояние между рынком и новой ценой открытия на предмет попадания в коридор Stop Level.
      1.3 Если не изменяются Stop Loss и Take Profit, то проверить, возможно ли перемещение цены открытия так, чтобы Stop Loss и Take Profit не оказались в коридоре Stop Level.

    2. Если изменяется цена Stop Loss, то проверить расстояние от нового Stop Loss до новой цены открытия ордера. Если расстояние менее Stop Level, то модификация невозможна.
    3. Если изменяется цена Take Profit, то проверить расстояние от нового Take Profit до новой цены открытия ордера. Если расстояние менее Stop Level, то модификация невозможна.
    4. Если изменяется время истечения ордера, то проверить, не будет ли новое время слишком близко к текущему времени. Зазор должен быть не менее 600 секунд.


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





Сообщение: 430
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 14.01.16 14:16. Заголовок: Игорь, помоги, я в т..


Игорь, помоги, я в тупике.
Индикатор рассчитывается по старшему ТФ (WorkTF) на периоде int ShowBars , но должен отрисовываться на графике младшего ТФ. Проблема с проверкой и подкачкой данных. При установке индикатора сразу на младший ТФ, ошибка выдается. А вот при смене ТФ со старшего на младший нет. Индикатор не удаляется, но и не отрисовывается. В чем причина не могу разобраться и, соответственно, исправить ошибку.
int OnInit()
{
datetime New_dtBegin = iTime(NULL,WorkTF,ShowBars);
if(!IsAllBarsAvailable(New_dtBegin))
{
Alert("Не достаточна глубина истории баров. Индикатор удален.");
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//----
bool IsAllBarsAvailable(datetime dtBeginBar)
{
int lastBar = iBarShift(NULL, 0, dtBeginBar);
if (GetLastError() == ERR_HISTORY_WILL_UPDATED)
return (false);
if(lastBar <= 0) return (false);

// Проверка доступности баров
for(int i=lastBar; i>=0; i--)
if(iTime(NULL,0,i)==0)
return (false);
// Все бары доступны
return (true);
}

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2019
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 21.01.16 20:56. Заголовок: Sergey пишет: Пробл..


Sergey пишет:

 цитата:
Проблема с проверкой и подкачкой данных.


В OnInit еще рано делать выводы о том, закачана история по нужному ТФ или нет. Проверить достаточность баров правильнее так:

 цитата:

if (iBars(NULL, WorkTF) <= ShowBars)
{
Alert("Недостаточная глубина истории. Индикатор отключен.");
return INIT_FAILED;
}



А вот проверять, загружена история по нужному ТФ или нет, нужно уже в OnCalculate:

 цитата:
int OnCalculate(...)
{
iTime(NULL, WorkTF, 1);
if (GetLastError() != ERR_NO_ERROR)
return prev_calculated;

// История по ТФ WorkTF успешно загружена
}



Чтобы определить, почему индикатор не отображается, нужно посмотреть, код OnCalculate.

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





Сообщение: 431
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.01.16 12:27. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В OnInit еще рано делать выводы о том, закачана история по нужному ТФ или нет. Проверить достаточность баров правильнее так:



На сколько я понял, пытаться подкачивать историю в OnInit не правильно. Тогда ошибка понятна. Исправил все с учетом рекомендаций, вроде работает.
Огромное спасибо!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2023
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 24.01.16 16:43. Заголовок: Sergey пишет: пыта..


Sergey пишет:

 цитата:
пытаться подкачивать историю в OnInit не правильно


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

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





Сообщение: 433
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 25.01.16 08:49. Заголовок: Scriptong пишет: Ка..


Scriptong пишет:

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



Игорь, а обращение к первому бару нужного таймфрейма запускает подкачку историии и в советниках тоже?


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2027
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 26.01.16 22:48. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, а обращение к первому бару нужного таймфрейма запускает подкачку историии и в советниках тоже?


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

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





Сообщение: 437
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 05.02.16 10:02. Заголовок: Игорь, подскажи, как..


Игорь, подскажи, как определить координату "y" в "окне" у осциллятора ( к примеру Sto), "окна" массштабируются, а координаты нет.
Мне нудно отобразить значения показаний индикатора (объектами Wingdings) на всех ТФ в "окне" осциллятора.



С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2038
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 06.02.16 18:39. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, подскажи, как определить координату "y" в "окне" у осциллятора ( к примеру Sto), "окна" массштабируются, а координаты нет.
Мне нудно отобразить значения показаний индикатора (объектами Wingdings) на всех ТФ в "окне" осциллятора.


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

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





Сообщение: 440
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 07.02.16 06:40. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
По моему пониманию, Y в подокнах - это значение индикатора.


Именно так. Текущее значение индикатора на всех ТФ в виде точки нужно отобразить под соответствующими надписями (М1.....MN) справа от индикатора текущего ТФ. Картинку я дал по Sto, но буду делать WPR . Осциллятор WPR ограничен значениями (-100-0).
Я не знаю, как можно перевести значение индикатора в пиксели с учетом масштабирования индикатора.
Единственная идея, которая мне пришла - это перевести координату Х надписи соответствующего ТФ в смещение показаний значения индикатора от нулевого бара. (Перевести координиту Х во время и рассчитать смещение в барах). Но я этого ни разу не делал, а возможно есть и другие способы. Нужна Ваша консультация - как грамотнее сделать.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2040
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 08.02.16 09:46. Заголовок: Sergey пишет: Именн..


Sergey пишет:

 цитата:
Именно так. Текущее значение индикатора на всех ТФ в виде точки нужно отобразить под соответствующими надписями (М1.....MN) справа от индикатора текущего ТФ. Картинку я дал по Sto, но буду делать WPR . Осциллятор WPR ограничен значениями (-100-0).
Я не знаю, как можно перевести значение индикатора в пиксели с учетом масштабирования индикатора.
Единственная идея, которая мне пришла - это перевести координату Х надписи соответствующего ТФ в смещение показаний значения индикатора от нулевого бара. (Перевести координиту Х во время и рассчитать смещение в барах). Но я этого ни разу не делал, а возможно есть и другие способы. Нужна Ваша консультация - как грамотнее сделать.


Тут получается, что Х-координата должна быть в пикселях, а Y - в значениях индикатора. Таким образом, проблема решается преобразованием не Х-координаты, а Y-координаты. Х-координата должна быть известна всегда - это смещение столбца "таблицы" относительно правого верхнего угла подокна. Далее нужно преобразовать значение индикатора в пиксели для подокна. Для этого существует функция ChartTimePriceToXY. Только с ее помощью преобразуйте именно "цену" (так будет представляться значение индикатора) в Y. Время и, соответственно, Х в данном случае преобразовывать не нужно.

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





Сообщение: 441
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 08.02.16 17:29. Заголовок: Scriptong пишет: Дл..


Scriptong пишет:

 цитата:
Для этого существует функция ChartTimePriceToXY.


Я уже пробовал делать через нее.
ChartTimePriceToXY(0, WindowFind(short_name),TimeCurrent(), SlowWPR, X_SlowWPR, Y_SlowWPR);
Но координата У, как выяснилось, отсчитывается от верхней границы графика, а не подокна. Т.е если поднять окно до верхней граници графика, то все отображается, правда все равно со смещением по у. В нормальном же виде, данные даже не попадают в зону видимости подокна.

Чтобы использовать данный способ, надо как то определить координату У подокна в системе координат окна основного графика. Я не знаю, как это сделать.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2042
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 10.02.16 22:07. Заголовок: Sergey пишет: Чтобы..


Sergey пишет:

 цитата:
Чтобы использовать данный способ, надо как то определить координату У подокна в системе координат окна основного графика. Я не знаю, как это сделать.


Эта задача точно такая же:

 цитата:

datetime GetAddBarToTime(datetime srcTime, int addBars)
{
int srcBar = iBarShift(NULL, 0, srcTime);
if (srcBar >= addBars)
return iTime(NULL, 0, srcBar - addBars);

return iTime(NULL, 0, 0) + (addBars - srcBar) * PeriodSeconds();
}

...
int subWnd = WindowFind("<имя индикатора>");
if (subWnd < 0)
return;

int x0, y0;
int firstBar = WindowFirstVisibleBar();
int totalBars = WindowBarsPerChart();
datetime lastBarTime = GetAddBarToTime(iTime(NULL, 0, firstBar), totalBars);

if (!ChartTimePriceToXY(0, subWnd, lastBarTime, indicator_maximum, x0, y0))
Print("ChartTimePriceToXY error: ", GetLastError());
else
Print("x0 = ", x0, ", y0 = ", y0);


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

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





Сообщение: 442
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.02.16 07:35. Заголовок: Scriptong пишет: Та..


Scriptong пишет:

 цитата:
Таким образом определяете координаты верхнего правого угла подокна относительно левого верхнего угла графика. А далее, получив координаты нужной точки, вычитаете из этих координат "нулевые" координаты.


Игорь, огромное спасибо! Идея понятна, реализация удалась.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 448
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.03.16 20:05. Заголовок: Игорь, есть вопрос, ..


Игорь, есть вопрос, но даже не знаю как его сформулировать, чтобы было понятно. Я сделал индикатор и советник на его основе. Обращение к данным индикатора сделал через iCustom. Теперь хочу встроить индикатор в советник. Проблема в том, что индикатор рассчитывается при помощи нескольких циклов, то есть нельзя взять и рассчитать нужные бары без циклов.
В индикаторе, чтобы повторно не рассчитывать циклы используем limit = GetRecalcIndex(total, rates_total, prev_calculated);
Как это можно реализовать в советнике?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2086
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 07.03.16 17:22. Заголовок: Sergey пишет: Тепер..


Sergey пишет:

 цитата:
Теперь хочу встроить индикатор в советник. Проблема в том, что индикатор рассчитывается при помощи нескольких циклов, то есть нельзя взять и рассчитать нужные бары без циклов.


Сегодня уже отвечал на подобный вопрос в другом месте (Недискретные рэндж-бары). Суть в том, что для каждого конкретного индикатора пишется свой собственный алгоритм расчета данных в советнике. В большинстве случаев такой алгоритм будет проще, если все сделать правильно.

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





Сообщение: 449
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 07.03.16 19:41. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В большинстве случаев такой алгоритм будет проще, если все сделать правильно.


А как правильно? В смысле, какие есть варианты? К примеру, я сейчас просто сокращаю количество проходов по циклам до достаточного и вместо динамического массива использую статический, плюс ограничиваю расчет только открытием нового бара. Была идея перекопирования массива со смещением на одну позицию, тогда в расчет попадает только последний бар. Но запнулся на проверке. Ведь возможны пробелы в следствии, к примеру, разрыва связи с терминалом.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2090
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 10.03.16 17:36. Заголовок: Sergey пишет: А как..


Sergey пишет:

 цитата:
А как правильно? В смысле, какие есть варианты?


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

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

Подобным образом работают индикатор Divergence_Viewer и советник Divergence. Чтобы не мучаться каждый раз со встраиванием индикатора во советник, я разработал единый класс CDivergence, который подключается к любой программе.

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





Сообщение: 451
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 10.03.16 19:26. Заголовок: Scriptong пишет: Чт..


Scriptong пишет:

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


Дааа! Пример явно выше моих познаний в программировании. Не думал, что все так сложно. Придется действовать по-старинке, решать проблемы по мере их поступления. Спасибо!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2095
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 15.03.16 11:39. Заголовок: Sergey пишет: Дааа!..


Sergey пишет:

 цитата:
Дааа! Пример явно выше моих познаний в программировании. Не думал, что все так сложно. Придется действовать по-старинке, решать проблемы по мере их поступления. Спасибо!


Индикатор дивергенций - сам по себе достаточно сложный инструмент. По этой причине это действительно сложный для понимания пример.

Если есть какой-то простенький индикатор, его показания основаны на данных предыдущих баров и индикатор необходимо встроить в советник, то прикрепите его здесь. Я постараюсь показать, как это делается, чтобы желающие делать подобное самостоятельно хотя бы смогли понять сам принцип (в каком направлении думать).

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





Сообщение: 452
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 15.03.16 17:15. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
По этой причине это действительно сложный для понимания пример.


Проблема не в сложности. Раньше ты практически к каждой строчки кода писал комментарий. Я просто учил программирование на примерах. В новом МТ введено много дополнительных параметров - класс, структура и т.д. Справочник не дает развернутого понимания их возможностей применения на примерах, он скорее рассчитан на профессионалов с кратким описанием, да еще с таким, что само описание требует к нему описание.
Получается, что не представляя в целом возможностей того или иного параметра и не имея описания при его применении сложно понять, что к чему.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2097
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 17.03.16 12:55. Заголовок: Sergey пишет: Раньш..


Sergey пишет:

 цитата:
Раньше ты практически к каждой строчки кода писал комментарий.


Да, потому что раньше (на Адмирале) статьи писал именно для обучения других, т. е. в качестве примеров, т. к. была соответствующая договоренность с администрацией компании. Сейчас же подобных договоренностей ни с кем нет. Программы пишутся именно для использования, а не для примеров.

Sergey пишет:

 цитата:
В новом МТ введено много дополнительных параметров - класс, структура и т.д. Справочник не дает развернутого понимания их возможностей применения на примерах, он скорее рассчитан на профессионалов с кратким описанием, да еще с таким, что само описание требует к нему описание.
Получается, что не представляя в целом возможностей того или иного параметра и не имея описания при его применении сложно понять, что к чему.


Да, с обучением языкам MQL4 и MQL5 сейчас достаточно сложно, нет учебника, как было ранее для MQL4. Но возможности ООП в MQL точно такие же, как и в С++. Поэтому для освоения ООП достаточно прочитать соответствующие разделы в учебниках по С++. Также могу порекомендовать неплохую статью Дмитрия Федосеева. В ней он кратко описывает суть ООП. На мой взгляд, достаточно понятно.

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





Сообщение: 455
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 17.03.16 21:23. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
Поэтому для освоения ООП достаточно прочитать соответствующие разделы в учебниках по С++. Также могу порекомендовать неплохую статью Дмитрия Федосеева. В ней он кратко описывает суть ООП. На мой взгляд, достаточно понятно.


Спасибо, посмотрю.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Сообщение: 2257
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация: 3
ссылка на сообщение  Отправлено: 03.03.16 21:35. Заголовок: Привет, Sergey! Я т..


Привет, Sergey!

Я тоже задавал Игорю аналогичные вопросы здесь: http://scriptong.myqip.ru/?1-0-15-00000003-000-15-0
Жаль со временем пропадают файлы и скрины.

Sergey, данный пример подойдет к описанной ситуации для решения задачи ?

//+------------------------------------------------------------------+ 
//| VolumeRSI_v1.mq4 |
//| Copyright © 2007, TrendLaboratory Ltd. |
//| http://finance.groups.yahoo.com/group/TrendLaboratory |
//| E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, TrendLaboratory Ltd."
#property link "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 LightBlue
#property indicator_width1 2
#property indicator_level1 50
//---- input parameters
extern int Price = 0; //Applied Price(0-Close;1-Open;2-High;3-Low;4-Median;5-Typical;6-Weighted)
extern int Length = 14; // Period of evaluation
extern int Smooth = 3; // Period of smoothing
extern int MA_Mode = 2; // Mode of MA
//---- buffers
double SmRSI[];
double vRSI[];
double vBulls[];
double vBears[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorBuffers(4);
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,SmRSI);
SetIndexBuffer(1,vRSI);
SetIndexBuffer(2,vBulls);
SetIndexBuffer(3,vBears);

//---- name for DataWindow and indicator subwindow label
string short_name="VolumeRSI("+Price+","+Length+","+Smooth+","+MA_Mode+")";
IndicatorShortName(short_name);
SetIndexLabel(0,"VolumeRSI");

//----
SetIndexDrawBegin(0,Length+Smooth);

return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int shift, limit, counted_bars=IndicatorCounted();
double Price1, Price2, Bulls, Bears, AvgBulls, AvgBears;
//----
if ( counted_bars < 0 ) return(-1);
if ( counted_bars ==0 ) limit=Bars-1;

if ( counted_bars < 1 )
for(int i=1;i<Length+Smooth-1;i++)
{vRSI[Bars-i]=0; SmRSI[Bars-i]=0; vBulls[Bars-i]=0; vBears[Bars-i]=0;}

if(counted_bars>0) limit=Bars-counted_bars;
limit--;

for( shift=limit; shift>=0; shift--)
{
Price1 = iMA(NULL,0,1,0,0,Price,shift);
Price2 = iMA(NULL,0,1,0,0,Price,shift+1);

Bulls = 0.5*(MathAbs(Price1-Price2)+(Price1-Price2));
Bears = 0.5*(MathAbs(Price1-Price2)-(Price1-Price2));

if(Bulls > 0) {vBulls[shift] = Volume[shift]; vBears[shift] = 0;}
else
if(Bears > 0) {vBears[shift] = Volume[shift]; vBulls[shift] = 0;}
else
if(Bears == Bulls) {vBears[shift]=0; vBulls[shift] = 0;}
}

for( shift=limit; shift>=0; shift--)
{
AvgBulls=iMAOnArray(vBulls,0,Length,0,MA_Mode,shift);
AvgBears=iMAOnArray(vBears,0,Length,0,MA_Mode,shift);

if (AvgBulls+AvgBears != 0) vRSI[shift] = 1.0/(1.0+AvgBears/AvgBulls);
else if (AvgBulls+AvgBears==0) vRSI[shift] = 0;
}
for( shift=limit; shift>=0; shift--)
SmRSI[shift] = 100*iMAOnArray(vRSI,0,Smooth,0,MA_Mode,shift);
//----
return(0);
}
//+------------------------------------------------------------------+


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 458
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 20.03.16 09:09. Заголовок: Genry пишет: Sergey..


Genry пишет:

 цитата:
Sergey, данный пример подойдет к описанной ситуации для решения задачи ?


Да вполне. Цикл рассчитанный на предыдущем цикле.

С уважением! Спасибо: 1 
ПрофильЦитата Ответить





Сообщение: 468
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 20.04.16 12:39. Заголовок: Мой мозг сейчас "..


Мой мозг сейчас "взорвется"!

1. for (int j = 0; j < OrdersTotal(); j++) // Используется весь список ордеров
if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран

2. for (int j = OrdersTotal(); j > 0; j--) // Используется весь список ордеров
if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран

В терминале два отложенных ордера. Почему в первом случае выбирается только один ордер, а во втором как положено два.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2139
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 21.04.16 17:24. Заголовок: Sergey пишет: В тер..


Sergey пишет:

 цитата:
В терминале два отложенных ордера. Почему в первом случае выбирается только один ордер, а во втором как положено два.


Немного путаете: как положено, два ордера, будет выбираться только в первом случае. Потому что, если OrdersTotal() = 2, то будет обращение к ордерам с индексами 0 и 1 (нумерация ведется с нуля). Тут все верно.

А вот второй случай описан неправильно. Цикл тоже проходит две итерации (i = 2 и i = 1), но ордера с индексом 2 нет в списке рабочих. Поэтому OrderSelect возвращает false и правильно предостерегает от обращения к ордеру, который не выбран.

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





Сообщение: 469
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 06:14. Заголовок: Scriptong пишет: Не..


Scriptong пишет:

 цитата:
Немного путаете: как положено, два ордера, будет выбираться только в первом случае. Потому что, если OrdersTotal() = 2, то будет обращение к ордерам с индексами 0 и 1 (нумерация ведется с нуля). Тут все верно.

А вот второй случай описан неправильно. Цикл тоже проходит две итерации (i = 2 и i = 1), но ордера с индексом 2 нет в списке рабочих. Поэтому OrderSelect возвращает false и правильно предостерегает от обращения к ордеру, который не выбран.



В том то и проблема, что я ничего не путаю. Цикл удаления отложенных ордеров. В первом случае один ордер всегда остается в рынке, а вот во втором удаляются все. Я рассуждаю, как Вы. Вот и не могу понять , почему? Логически правильный первый вариант, а работает второй. Вот я и подумал, что возможно обращение идет не с 0, а 1 ордера. Но цикл с закрытием рыночных ордеров работает правильно именно по первому варианту.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2142
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 22.04.16 10:21. Заголовок: Sergey пишет: Цикл ..


Sergey пишет:

 цитата:
Цикл удаления отложенных ордеров.


Теперь понятна проблема. Если требуется удалять/закрывать ордера, то следует использовать именно обратный цикл, как во втором случае. Только он должен выглядеть следующим образом:

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


Потому как при прямом переборе ордеров удаление любого ордера из середины списка приводит к изменению индексов всех остальных ордеров.

Простой пример. Есть три ордера с тикетами А, В и С. Соответственно у ордера А индекс в списке ордеров 0, у В - 1, у С - 2.
Если идти прямым перебором, то сначала удаляем ордер А. Сразу после его удаления ордер В получает индекс 0, ордер С - 1. Но в цикле то мы переходим ко второй итерации (i = 1), т. е. к ордеру с индексом 1. В итоге удаляем ордер С и получаем окончание цикла. Выходит, что ордер В так и не будет удален.

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





Сообщение: 473
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 14:40. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
Потому как при прямом переборе ордеров удаление любого ордера из середины списка приводит к изменению индексов всех остальных ордеров.


Игорь, огромное спасибо, наконец разобрался.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 470
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 08:15. Заголовок: Кажется я разобрался..


Кажется я разобрался.... Проблема аналогична той, которую я описывал 03.10.2015. - взаимодействие сервера брокера и терминала. Но возможно я не прав, поэтому приведу код полностью.
for (int j = 0; j < OrdersTotal(); j++) // Используется весь список ордеров
if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран
{
Alert(OrderTicket());
if (OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol() // ордер должен принадлежать текущей валютной паре
&& OrderType()>1)
if(!DeleteDeal(OrderTicket()))return;
}
//----
bool DeleteDeal(int ticket)
{
if ( OrderSelect(ticket, SELECT_BY_TICKET) && // Существует ордер с заданным..
OrderCloseTime() == 0 && // ..тикетом и ордер не закрыт ...
OrderType()>1) // ордер отложенный
{
if (!WaitForTradeContext()) return(false); // Свободен ли торговый поток?

if (!OrderDelete(OrderTicket())) // Если ордер не удалось удалить, то результат
{
Alert(GetLastError());
return(False); // функции - False
}
}
return(True); // Ордер удален
}
//----
Ошибки удаления или занятости торгового потока не выскакивают. Я выставил 8 отложенников - удалилось только 4. Alert при отборе ордеров даже не высветил их (не удаленных) тикеты. Этот глюк появился с 600 билдом - сервер еще не обработал ордер, а терминал продолжает отработку кода, при этом не выдает ошибки . С рыночными ордерами я эту проблему решил путем зацикливания функций закрытия и проверки ордеров.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2143
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 22.04.16 10:31. Заголовок: Sergey пишет: Проб..


Sergey пишет:

 цитата:
Проблема аналогична той, которую я описывал 03.10.2015. - взаимодействие сервера брокера и терминала.


Нет. Взаимодействие здесь не при чем. Проблема лишь с нумерацией ордеров в списке. При проведении торговых операций список, конечно же, претерпевает изменения. Не стоит производить торговые операции в цикле, а по большому счету вообще не рекомендую в одном обработчике событий (OnTick, OnChartEvent, OnTimer) совершать более одной торговой операции. То есть вне зависимости от результата выполнения операции следует перемещать выполнение программы на начало обработчика события. Ведь за время выполнение торгового запроса программа "спала" (в компьютерном исчислении пара секунд - это неимоверно много), а ситуация могла кардинально измениться.


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





Сообщение: 471
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 09:33. Заголовок: К стати, проблему вз..


К стати, проблему взаимодействия сервера и терминала при модернизации ордеров, описанную мной 03.10.2015 (ордер не успевал обрабатываться сервером до следующего тика) пришлось решать так...
if (!OrderModify(OrderTicket(), OpPrice, SL, TP,0))
{
int Error = GetLastError();
if (Error!=139 && Error!=0)
{
Alert("Order modification error ",OrderTicket()," = ",Error);
return(false);
}
}

Фигня какая то!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2144
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 22.04.16 10:33. Заголовок: Sergey пишет: ордер..


Sergey пишет:

 цитата:
ордер не успевал обрабатываться сервером до следующего тика


Если так, то советник никогда не узнает о приходе этого пропущенного тика. Пропущенные тики для советников теряются безвозвратно. Обработка тика советником происходит только в том случае, если советник закончил обработку предыдущего тика.

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





Сообщение: 474
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 14:48. Заголовок: Scriptong пишет: Ес..


Scriptong пишет:

 цитата:
Если так, то советник никогда не узнает о приходе этого пропущенного тика. Пропущенные тики для советников теряются безвозвратно. Обработка тика советником происходит только в том случае, если советник закончил обработку предыдущего тика.


Здесь имелось ввиду, что по приходу следующего тика информация об ордере не поменялась. В результате идет повторная команда на модификацию ордера. И выдается ошибка 139 или 0.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2147
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 22.04.16 17:52. Заголовок: Sergey пишет: Здесь..


Sergey пишет:

 цитата:
Здесь имелось ввиду, что по приходу следующего тика информация об ордере не поменялась.


Это более, чем странно. Никогда такого в МТ4 не замечал, т. к. в нем все команды синхронные. Такое может быть только в МТ5, но там для контроля есть соответствующие события.
В МТ4, если советник отправляет торговый приказ, то эксперт будет бездействовать до момента получения ответа от сервера. За это время советником не будут восприниматься какие-либо тики, т. к. советник "висит". Если же ответ получен, то вместе с этим будет получено новое состояние ордеров, если они изменились.
Ошибка 139 может быть получена, если отправляется приказ на модификацию/удаление/закрытие ордера, который в данный момент обрабатывается сервером в результате достижения ценой уровня его открытия (если отложенный ордер) или уровня Stop Loss/Take Profit. Еще такое может быть, если брокер использует уровень заморозки. Но тогда это брокер-динозавр, т. к. я уже давно не встречал, чтобы Freeze Level отличался от нуля.

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





Сообщение: 476
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 22.04.16 21:00. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В МТ4, если советник отправляет торговый приказ, то эксперт будет бездействовать до момента получения ответа от сервера. За это время советником не будут восприниматься какие-либо тики, т. к. советник "висит". Если же ответ получен, то вместе с этим будет получено новое состояние ордеров, если они изменились.


Вот и я так думал. И нормального объяснения этому у меня пока нет. Времени прошло много, всего точно не упомнишь. Знаю, что когда исключил ошибку 139, стала появляться ошибка 0 (модификация по тем же параметрам SL и TP). Причем, если исключить Alert, в журнале ошибка не проходит. Думаю, в свете тех рекомендаций, которые ты дал выше, причина может скрываться в сортировке ордеров. Модификация сделана в цикле перебора всех ордеров. А советник допускает наличие нескольких ордеров одновременно. Придется заменить простой перебор функцией слежения за ордерами.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2151
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 28.04.16 12:51. Заголовок: Sergey пишет: стала..


Sergey пишет:

 цитата:
стала появляться ошибка 0


Так ведь ошибка 0 - это отсутствие ошибки. Значит, все нормально .

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





Сообщение: 480
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 28.04.16 15:09. Заголовок: Scriptong пишет: Та..


Scriptong пишет:

 цитата:
Так ведь ошибка 0 - это отсутствие ошибки. Значит, все нормально


Не совсем. При модификации 0 означает и модификацию ордера по тем же параметрам. Ошибки с точки зрения торговли нет, а в алгоритме, скорее всего да.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





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


Sergey пишет:

 цитата:
При модификации 0 означает и модификацию ордера по тем же параметрам. Ошибки с точки зрения торговли нет, а в алгоритме, скорее всего да.


В таком случае получите ошибку 1.

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





Сообщение: 481
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 29.04.16 06:24. Заголовок: Scriptong пишет: В ..


Scriptong пишет:

 цитата:
В таком случае получите ошибку 1.


Учту.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 483
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 03.05.16 18:09. Заголовок: Столкнулся с непонят..


Столкнулся с непонятной ситуацией. Вот Журнал модификации ордера...

.. из которого следует, что отправлено две заявки на модификацию ордера. Причем конечные значения модификации по ТР на 40 тиков отличаются от расчетных. Ошибок не выдается. Я поставил метки на количество расчетов ТР и модификаций, которые показали, что расчет и заявка на модификацию выполняются, как положено,один раз. У кого нибудь есть разумные объяснения?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2156
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 03.05.16 19:37. Заголовок: Sergey пишет: Столк..


Sergey пишет:

 цитата:
Столкнулся с непонятной ситуацией.


Немного подробнее про ситуацию. Речь идет об общем журнале или о журнале экспертов? Также желательно видеть всю строку сообщения (можно обрезать название эксперта, если речь об автоторговле).

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





Сообщение: 484
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 04.05.16 09:22. Заголовок: Спасибо всем .... ра..


Спасибо всем .... разобрался. Оказалось все просто.....Одновременно работали 2 робота на одной паре и с одинаковыми идентификаторами.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 488
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 07.05.16 08:42. Заголовок: Нудно посчитать Prof..


Нудно посчитать Profit при закрытии нескольких Sell ордеров. На сколько корректен такой алгоритм.
for (int i = SellCount-1; i >= 0; i--)
if (OrderSelect(SellTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
if (OrderClose(OrderTicket(), OrderLots(), NT(Ask), 3))
Profit +=OrderProfit();

Или после закрытия нужно заново вытаскивать ордер уже из истории и лишь затем подсчитывать профит.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2161
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 11.05.16 16:47. Заголовок: Sergey пишет: Нудно..


Sergey пишет:

 цитата:
Нудно посчитать Profit при закрытии нескольких Sell ордеров. На сколько корректен такой алгоритм.
for (int i = SellCount-1; i >= 0; i--)
if (OrderSelect(SellTicket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
if (OrderClose(OrderTicket(), OrderLots(), NT(Ask), 3))
Profit +=OrderProfit();
Или после закрытия нужно заново вытаскивать ордер уже из истории и лишь затем подсчитывать профит.


Нет, неправильно. Ведь SellCount уже было откуда-то взято. Значит, был цикл, который посчитал количество закрытых ордеров. Зачем тогда второй цикл, если все это можно было посчитать в одном цикле?
Также непонятно, для чего представленный цикл нужен, если постоянно идет обращение к одному и тому же ордеру с тикетом SellTicket?

Подсчет прибыли/убытка некоторых закрытых ордеров осуществляется следующим образом:

 цитата:
double profit = 0.0;
for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
{
if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
continue;
if (OrderType() != OP_SELL)
continue;
profit += OrderProfit() + OrderSwap() + OrderComission();
}



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





Сообщение: 490
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.05.16 20:25. Заголовок: Scriptong пишет: Та..


Scriptong пишет:

 цитата:
Также непонятно, для чего представленный цикл нужен, если постоянно идет обращение к одному и тому же ордеру с тикетом SellTicket?


SellTicket|i| это массив тикетов Sell-ордеров отобранных для закрытия, не заметил, что квадратные скобки удалились. Меня интересует корректность такой последовательности
if (OrderClose(OrderTicket(), OrderLots(), NT(Ask), 3))
Profit +=OrderProfit() + OrderSwap() + OrderComission();
или все же так
if (OrderClose(OrderTicket(), OrderLots(), NT(Ask), 3))
if (OrderSelect(OrderTicket(), SELECT_BY_TICKET,, MODE_HISTORY)
Profit +=OrderProfit() + OrderSwap() + OrderComission();


С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2164
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 12.05.16 10:42. Заголовок: Sergey пишет: или в..


Sergey пишет:

 цитата:
или все же так
if (OrderClose(OrderTicket(), OrderLots(), NT(Ask), 3))
if (OrderSelect(OrderTicket(), SELECT_BY_TICKET,, MODE_HISTORY)
Profit +=OrderProfit() + OrderSwap() + OrderComission();


Конечно же, так. Ведь в первом случае получаем данные непонятно какого ордера, т. к. перед обращением к функциям OrderXXX обязательно требуется выбор ордера при помощи OrderSelect.

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





Сообщение: 489
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.05.16 15:10. Заголовок: Игорь, подскажи, мож..


Игорь, подскажи, можно ли с помощью обработчика"CHARTEVENT_OBJECT_ENDEDIT — событие окончания редактирования текста в поле ввода графического объекта LabelEdit" задавать советнику значения типа double? Если ДА и если не сложно, напиши пример.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2162
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 11.05.16 17:05. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, подскажи, можно ли с помощью обработчика"CHARTEVENT_OBJECT_ENDEDIT — событие окончания редактирования текста в поле ввода графического объекта LabelEdit" задавать советнику значения типа double? Если ДА и если не сложно, напиши пример.


В смысле, чтобы в обработчике

 цитата:
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)


параметр sparam был не строковый, а типа double? Если так, то нельзя такое делать. Да и не нужно. Ведь строку легко преобразовать в вещественное значение при помощи функции StringToDouble.
Таким образом, алгоритм будет следующий:

 цитата:
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
if (sparam != MY_LABEL_EDIT)
return;
string text = ObjectGetString(0, sparam, OBJPROP_TEXT);
double value = StringToDouble(text);
}



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





Сообщение: 491
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 11.05.16 20:38. Заголовок: Scriptong пишет: па..


Scriptong пишет:

 цитата:
параметр sparam был не строковый, а типа double?


Нет. К примеру я хочу изменить лот советнику на поле графика, не вызывая настройки советника. Конкретный пример- встроенная функция "Торговля в один клик". Лот можно менять набирая текст на клавиатуре. То есть мне нужно вывести часть настроек советника в таблицу на графике цены, так чтобы их можно было задавать, а они подхватывались советником, как будто были изменены в настройках.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2165
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 12.05.16 10:43. Заголовок: Sergey пишет: Нет. ..


Sergey пишет:

 цитата:
Нет. К примеру я хочу изменить лот советнику на поле графика, не вызывая настройки советника. Конкретный пример- встроенная функция "Торговля в один клик". Лот можно менять набирая текст на клавиатуре. То есть мне нужно вывести часть настроек советника в таблицу на графике цены, так чтобы их можно было задавать, а они подхватывались советником, как будто были изменены в настройках.


Посмотрите сам пример. Именно этому случаю он и соответствует.

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





Сообщение: 495
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 12.05.16 18:21. Заголовок: Scriptong пишет: По..


Scriptong пишет:

 цитата:
Посмотрите сам пример. Именно этому случаю он и соответствует.


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

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 514
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 30.06.16 11:29. Заголовок: Игорь, подскажи в че..


Игорь, подскажи в чем проблема....
Вот часть кода из советника
#define NumOrd 1 // Количество элементов массива (стратегий)
struct OrdInfo
{
double isPrice;
double isSL;
double isTP;
double isLot;
int isTicket;
int isType;
int isMagic;
string isComment;
};
OrdInfo g_ordInfo|NumOrd|;
//----
void Terminal()
{
Qnt=0; // Счётчик количества ордеров
//----
for(int i=0; i<OrdersTotal(); i++) // По рыночн. и отлож. ордерам
{
if(OrderSelect(i,SELECT_BY_POS)==true //Если есть следующ.
&& OrderSymbol()==Symbol() //.. и наша вал.пара
&& OrderMagicNumber()!=0 && OrderMagicNumber()<=NumOrd) //.. и он открыт экспертом
{
Alert("1");
g_ordInfo|i|.isPrice = OrderOpenPrice(); // Цена открытия ордера
Alert("2");
g_ordInfo|i|.isSL=OrderStopLoss(); // Стоп-лосс ордера
g_ordInfo|i|.isTP=OrderTakeProfit(); // Тейк-профит ордера
g_ordInfo|i|.isLot=OrderLots(); // Количество лотов
g_ordInfo|i|.isTicket=OrderTicket(); // Номер ордера
g_ordInfo|i|.isType=OrderType(); // Тип ордера
g_ordInfo|i|.isMagic=OrderMagicNumber(); // ID ордера
g_ordInfo|i|.isComment=OrderComment(); // Комментарий ордера
Qnt++; // Колич. ордеров
}
}
}

Советник прекрасно работает в тестере стратегий. Однако в реале зависает между метками 1 и 2. Причем комп не виснет, в журнале ничего. Но тики не проходят.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2227
Зарегистрирован: 03.03.13
Откуда: Украина, Днепродзержинск
Репутация: 3
ссылка на сообщение  Отправлено: 30.06.16 19:32. Заголовок: Sergey пишет: Совет..


Sergey пишет:

 цитата:
Советник прекрасно работает в тестере стратегий. Однако в реале зависает между метками 1 и 2. Причем комп не виснет, в журнале ничего. Но тики не проходят.


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

Правильная организация цикла такая:

 цитата:
for(int i=0; i<OrdersTotal(); i++) // По рыночн. и отлож. ордерам
{
if(OrderSelect(i,SELECT_BY_POS)==true //Если есть следующ.
&& OrderSymbol()==Symbol() //.. и наша вал.пара
&& OrderMagicNumber()!=0 && OrderMagicNumber()<=NumOrd) //.. и он открыт экспертом
{
g_ordInfo[Qnt].isPrice = OrderOpenPrice(); // Цена открытия ордера
g_ordInfo[Qnt].isSL=OrderStopLoss(); // Стоп-лосс ордера
g_ordInfo[Qnt].isTP=OrderTakeProfit(); // Тейк-профит ордера
g_ordInfo[Qnt].isLot=OrderLots(); // Количество лотов
g_ordInfo[Qnt].isTicket=OrderTicket(); // Номер ордера
g_ordInfo[Qnt].isType=OrderType(); // Тип ордера
g_ordInfo[Qnt].isMagic=OrderMagicNumber(); // ID ордера
g_ordInfo[Qnt].isComment=OrderComment(); // Комментарий ордера
Qnt++; // Колич. ордеров
}
}



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





Сообщение: 516
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 30.06.16 22:34. Заголовок: Scriptong пишет: Пр..


Scriptong пишет:

 цитата:
Правильная организация цикла такая:


Огромное спасибо! Ведь все так явно, но почему-то только когда тебе ткнут пальцем. Понимаю, как не просто разбираться в чужих писульках... Спасибо!

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 515
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 30.06.16 11:45. Заголовок: Блин! Проверил на ре..


Блин! Проверил на реале в Alpfri все работает, а в FXOpen нет. Что за лажа?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 523
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 28.08.16 15:30. Заголовок: Нужно сделать описан..


Нужно сделать описание объекта "кнопка". Рядом с объектом "кнопка" Установил "OBJ_LABEL" - "?". Как сделать, чтобы при наведении на "?" высвечивалось описание , а не имя объекта с ценой? Если выложите готовый блок алгоритма, буду очень признателен.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2315
Зарегистрирован: 03.03.13
Откуда: Украина, Каменское (Днепродзержинск)
Репутация: 3
ссылка на сообщение  Отправлено: 28.08.16 16:05. Заголовок: Sergey пишет: Нужно..


Sergey пишет:

 цитата:
Нужно сделать описание объекта "кнопка". Рядом с объектом "кнопка" Установил "OBJ_LABEL" - "?". Как сделать, чтобы при наведении на "?" высвечивалось описание , а не имя объекта с ценой? Если выложите готовый блок алгоритма, буду очень признателен.


Никакого алгоритма там нет. При создании кнопки нужно лишь воспользоваться назначением свойства всплывающей подсказки:

 цитата:
ObjectSetInteger(0, name, OBJPROP_TOOLTIP, <текст подсказки>);



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





Сообщение: 524
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 29.08.16 02:41. Заголовок: Scriptong пишет: Ни..


Scriptong пишет:

 цитата:
Никакого алгоритма там нет. При создании кнопки нужно лишь воспользоваться назначением свойства всплывающей подсказки:

 цитата:
ObjectSetInteger(0, name, OBJPROP_TOOLTIP, <текст подсказки>);



Спасибо, на конец разобрался. ObjectSetString(0, name, OBJPROP_TOOLTIP, "текст"); Оказывается упускал первый параметр (chart_id) в результате получал ошибку и не мог понять в чем дело.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 534
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 07.10.16 18:38. Заголовок: Игорь, знаком ли ты ..


Игорь, знаком ли ты с программой Forex Tester. Можно ли в ней тестировать индикаторы MQL4?

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2340
Зарегистрирован: 03.03.13
Откуда: Украина, Каменское (Днепродзержинск)
Репутация: 3
ссылка на сообщение  Отправлено: 07.10.16 21:27. Заголовок: Sergey пишет: Игорь..


Sergey пишет:

 цитата:
Игорь, знаком ли ты с программой Forex Tester. Можно ли в ней тестировать индикаторы MQL4?


Да, и не только по наслышке. В 2009-ом году переводил для Forex Tester один из индикаторов MQL4. Тогда же писал рекламную статью для них в журнале Fortrader.ru (47-й номер)

Sergey пишет:

 цитата:
Можно ли в ней тестировать индикаторы MQL4?


Нет, нельзя. Нужно переводить программы на Delphi или на C++.
Но справедливости ради нужно сказать, что API Forex Tester'a намеренно копирует функционал MQL4. Там даже также функции называются. Поэтому чисто алгоритмически перевод не очень сложен.

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





Сообщение: 535
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 08.10.16 07:54. Заголовок: Scriptong пишет: Н..


Scriptong пишет:

 цитата:
Нужно переводить программы на Delphi или на C++.


Спасибо.

С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 558
Зарегистрирован: 05.03.13
Репутация: 1
ссылка на сообщение  Отправлено: 24.01.18 14:31. Заголовок: Игорь, Привет! Я реш..


Игорь, Привет!
Я решил попробовать MQL5. Начал с простого. Попробовал раскрасить OsMA используя вызов стандартного индикатора.
Привожу код полностью
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 2
#property indicator_type1 DRAW_HISTOGRAM
#property indicator_color1 clrGreen
#property indicator_width1 2
#property indicator_type2 DRAW_HISTOGRAM
#property indicator_color2 clrRed
#property indicator_width2 2
#property indicator_level1 0
input int ShowBars = 300;
input int FastEMA = 34;
input int SlowEMA = 72;
input int SignalSMA = 9;
input ENUM_APPLIED_PRICE applied_price = PRICE_CLOSE;
//--- indicator buffers
double Up_OsMA_Buffer[];
double Dn_OsMA_Buffer[];
double OsMA_Buffer[];
//--- OsMA handles
int OsMA_Handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,Up_OsMA_Buffer,INDICATOR_DATA);
SetIndexBuffer(1,Dn_OsMA_Buffer,INDICATOR_DATA);
SetIndexBuffer(2,OsMA_Buffer,INDICATOR_CALCULATIONS);

IndicatorSetInteger(INDICATOR_DIGITS,_Digits+3);

PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);

IndicatorSetString(INDICATOR_SHORTNAME,"FW-OsMA("+string(FastEMA)+","+string(SlowEMA)+","+string(SignalSMA)+")");

PlotIndexSetString(0,PLOT_LABEL,"UpOsMA");
PlotIndexSetString(1,PLOT_LABEL,"DnOsMA");

OsMA_Handle = iOsMA(NULL,PERIOD_CURRENT ,FastEMA,SlowEMA,SignalSMA,applied_price);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Функция деинициализации |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им
ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных
ArrayFree(Dn_OsMA_Buffer);
ArrayFree(OsMA_Buffer);
}
//====================================================================
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int calculated=BarsCalculated(OsMA_Handle);
if(calculated<rates_total)
{
Alert("Not all data of OsMA_Handle is calculated (",calculated,"bars ). Error",GetLastError());
return(0);
}

//--- we can copy not all data
int to_copy;
if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
else
{
to_copy=rates_total-prev_calculated;
to_copy++;
}
//--- get OsMA_Buffer buffer
if(IsStopped()) return(0); //Checking for stop flag
if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0)
{
Print("Getting OsMA_Buffer is failed! Error",GetLastError());
return(0);
}

//---
int k,limit;
if(prev_calculated==0)
limit=0;
else limit=prev_calculated-1;
//--- the main loop of calculations
for(k=limit;k<rates_total;k++)
{
//Dn_OsMA_Buffer[k]=0.0; Up_OsMA_Buffer[k]=0.0;
//--- calculate OsMA
//if(OsMA_Buffer[k]>OsMA_Buffer[k+1])
//Up_OsMA_Buffer[k]=OsMA_Buffer[k];
//else Dn_OsMA_Buffer[k]=OsMA_Buffer[k];


Если вместо выше выделенного текста подставить нижнюю строку и (#property indicator_plots 1), то все работает, но в одном цвете.
А так, нет. Отображается абра-кадабра какая-то.

Up_OsMA_Buffer[k]=OsMA_Buffer[k];
}

//--- return value of prev_calculated for next call
return(rates_total);
}
//====================================================================

Что не правильно в выделенном тексте?
А если задать ArraySetAsSeries(OsMA_Buffer,true); , то и этот вариант не работает.



С уважением! Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 2572
Зарегистрирован: 03.03.13
Откуда: Украина, Каменское (Днепродзержинск)
Репутация: 3
ссылка на сообщение  Отправлено: 25.01.18 22:45. Заголовок: Sergey пишет: Что н..


Sergey пишет:

 цитата:
Что не правильно в выделенном тексте?
А если задать ArraySetAsSeries(OsMA_Buffer,true); , то и этот вариант не работает.


Дело в том, что без ArraySetAsSeries нумерация баров в таймсериях ведется слева направо по графику. То есть бар с индексом 0 - где-то глубоко в истории, а текущий бар - это rates_total - 1.
Поэтому для такой нумерации нужно:
  • Начинать перебор баров не с бара 0, а с бара 1, т. к. нам нужно взять высоты гистограммы предыдущего бара, которого для бара 0 нет. То есть limit ставится не на 0, а на 1.
  • Понять, что предыдущий бар, это не k + 1, а k - 1.

    Получаем такой вот работающий код:

     цитата:
    #property indicator_separate_window
    #property indicator_buffers 3
    #property indicator_plots 2
    #property indicator_type1 DRAW_HISTOGRAM
    #property indicator_color1 clrGreen
    #property indicator_width1 2
    #property indicator_type2 DRAW_HISTOGRAM
    #property indicator_color2 clrRed
    #property indicator_width2 2
    #property indicator_level1 0
    input int ShowBars= 300;
    input int FastEMA = 34;
    input int SlowEMA = 72;
    input int SignalSMA=9;
    input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE;
    //--- indicator buffers
    double Up_OsMA_Buffer[];
    double Dn_OsMA_Buffer[];
    double OsMA_Buffer[];
    //--- OsMA handles
    int OsMA_Handle;
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- indicator buffers mapping
    SetIndexBuffer(0,Up_OsMA_Buffer,INDICATOR_DATA);
    SetIndexBuffer(1,Dn_OsMA_Buffer,INDICATOR_DATA);
    SetIndexBuffer(2,OsMA_Buffer,INDICATOR_CALCULATIONS);

    IndicatorSetInteger(INDICATOR_DIGITS,_Digits+3);

    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);
    PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);

    IndicatorSetString(INDICATOR_SHORTNAME,"FW-OsMA("+string(FastEMA)+","+string(SlowEMA)+","+string(SignalSMA)+")");

    PlotIndexSetString(0,PLOT_LABEL,"UpOsMA");
    PlotIndexSetString(1,PLOT_LABEL,"DnOsMA");

    OsMA_Handle=iOsMA(NULL,PERIOD_CURRENT,FastEMA,SlowEMA,SignalSMA,applied_price);
    //---
    return(INIT_SUCCEEDED);
    }
    //+------------------------------------------------------------------+
    //| Функция деинициализации |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им
    ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных
    ArrayFree(Dn_OsMA_Buffer);
    ArrayFree(OsMA_Buffer);
    }
    //====================================================================
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
    const int prev_calculated,
    const datetime &time[],
    const double &open[],
    const double &high[],
    const double &low[],
    const double &close[],
    const long &tick_volume[],
    const long &volume[],
    const int &spread[])
    {
    int calculated=BarsCalculated(OsMA_Handle);
    if(calculated<rates_total)
    {
    Alert("Not all data of OsMA_Handle is calculated (",calculated,"bars ). Error",GetLastError());
    return(0);
    }

    //--- we can copy not all data
    int to_copy;
    if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
    else
    {
    to_copy=rates_total-prev_calculated;
    to_copy++;
    }
    //--- get OsMA_Buffer buffer
    if(IsStopped()) return(0); //Checking for stop flag
    if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0)
    {
    Print("Getting OsMA_Buffer is failed! Error",GetLastError());
    return(0);
    }

    //---
    int k,limit;
    if(prev_calculated==0)
    limit=1;
    else limit=prev_calculated-1;
    //--- the main loop of calculations
    for(k=limit;k<rates_total;k++)
    {
    Dn_OsMA_Buffer[k]=0.0; Up_OsMA_Buffer[k]=0.0;
    //-- calculate OsMA
    if(OsMA_Buffer[k]>OsMA_Buffer[k-1])
    Up_OsMA_Buffer[k]=OsMA_Buffer[k];
    else
    Dn_OsMA_Buffer[k]=OsMA_Buffer[k];
    }

    //--- return value of prev_calculated for next call
    return(rates_total);
    }





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





    Сообщение: 559
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 26.01.18 07:35. Заголовок: Спасибо! Но хотелось..


    Спасибо! Но хотелось бы разобраться до конца.
    Как изменить код с использованием ArraySetAsSeries(OsMA_Buffer,true);
    Поскольку именно этот вариант в дальнейшем будет использован в советниках и рекомендован во всех статьях, а у меня не вышел.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2573
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 26.01.18 17:44. Заголовок: Тогда нужно всю инде..


    Тогда нужно всю индексацию развернуть, а не просто использовать ArraySetAsSeries.
    Т. к. цикл расчета данных для каждого бара в "правильном" индикаторе должен следовать слева направо по графику, то нужно идти от rates_total (limit поддерживать) до 0 с декрементом.

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





    Сообщение: 560
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 27.01.18 10:00. Заголовок: Scriptong пишет: То..


    Scriptong пишет:

     цитата:
    Тогда нужно всю индексацию развернуть, а не просто использовать ArraySetAsSeries.
    Т. к. цикл расчета данных для каждого бара в "правильном" индикаторе должен следовать слева направо по графику, то нужно идти от rates_total (limit поддерживать) до 0 с декрементом.



    На словах я это понимаю, с практикой туго.
    Устанавливаем порядок индексации массива как в таймсерии
    if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0)
    {
    Print("Getting OsMA_Buffer is failed! Error",GetLastError());
    return(0);
    }
    ArraySetAsSeries(OsMA_Buffer,true);

    Отобразим первые 200 баров

    for(int k=200;k>=0;k--)
    {
    Dn_OsMA_Buffer[k]=0.0; Up_OsMA_Buffer[k]=0.0;
    //-- calculate OsMA
    if(OsMA_Buffer[k]>OsMA_Buffer[k+1])
    Up_OsMA_Buffer[k]=OsMA_Buffer[k];
    else
    Dn_OsMA_Buffer[k]=OsMA_Buffer[k];
    }

    Как не пересчитываю слева-направо или наоборот, получается фигня.
    В чем не прав не знаю. Я это смогу понять, лишь проанализировав правильный код. Не зачти за лишний труд. Плиз!

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2574
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 28.01.18 17:10. Заголовок: Sergey пишет: Как н..


    Sergey пишет:

     цитата:
    Как не пересчитываю слева-направо или наоборот, получается фигня.
    В чем не прав не знаю. Я это смогу понять, лишь проанализировав правильный код. Не зачти за лишний труд. Плиз!


    Установка признака таймсерии делается один раз, а не на каждом тике. И не для одного буфера, а для всех. Поэтому и проблема:

     цитата:

    #property indicator_separate_window
    #property indicator_buffers 3
    #property indicator_plots 2
    #property indicator_type1 DRAW_HISTOGRAM
    #property indicator_color1 clrGreen
    #property indicator_width1 2
    #property indicator_type2 DRAW_HISTOGRAM
    #property indicator_color2 clrRed
    #property indicator_width2 2
    #property indicator_level1 0
    input int ShowBars= 300;
    input int FastEMA = 34;
    input int SlowEMA = 72;
    input int SignalSMA=9;
    input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE;
    //--- indicator buffers
    double Up_OsMA_Buffer[];
    double Dn_OsMA_Buffer[];
    double OsMA_Buffer[];
    //--- OsMA handles
    int OsMA_Handle;
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- indicator buffers mapping
    SetIndexBuffer(0,Up_OsMA_Buffer,INDICATOR_DATA);
    SetIndexBuffer(1,Dn_OsMA_Buffer,INDICATOR_DATA);
    SetIndexBuffer(2,OsMA_Buffer,INDICATOR_CALCULATIONS);

    ArraySetAsSeries(Up_OsMA_Buffer, true);
    ArraySetAsSeries(Dn_OsMA_Buffer, true);
    ArraySetAsSeries(OsMA_Buffer, true);

    IndicatorSetInteger(INDICATOR_DIGITS,_Digits+3);

    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);
    PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,SlowEMA+SignalSMA-2);

    IndicatorSetString(INDICATOR_SHORTNAME,"FW-OsMA("+string(FastEMA)+","+string(SlowEMA)+","+string(SignalSMA)+")");

    PlotIndexSetString(0,PLOT_LABEL,"UpOsMA");
    PlotIndexSetString(1,PLOT_LABEL,"DnOsMA");

    OsMA_Handle=iOsMA(NULL,PERIOD_CURRENT,FastEMA,SlowEMA,SignalSMA,applied_price);
    //---
    return(INIT_SUCCEEDED);
    }
    //+------------------------------------------------------------------+
    //| Функция деинициализации |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им
    ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных
    ArrayFree(Dn_OsMA_Buffer);
    ArrayFree(OsMA_Buffer);
    }
    //====================================================================
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
    const int prev_calculated,
    const datetime &time[],
    const double &open[],
    const double &high[],
    const double &low[],
    const double &close[],
    const long &tick_volume[],
    const long &volume[],
    const int &spread[])
    {
    int calculated = BarsCalculated(OsMA_Handle);
    if(calculated < rates_total)
    {
    Alert("Not all data of OsMA_Handle is calculated (", calculated, "bars ). Error", GetLastError());
    return(0);
    }

    //--- we can copy not all data
    int to_copy;
    if(prev_calculated>rates_total || prev_calculated<0)
    to_copy = rates_total;
    else
    {
    to_copy = rates_total-prev_calculated;
    to_copy++;
    }
    //--- get OsMA_Buffer buffer
    if(CopyBuffer(OsMA_Handle, 0, 0, to_copy, OsMA_Buffer)<=0)
    {
    Print("Getting OsMA_Buffer is failed! Error", GetLastError());
    return(0);
    }

    //---
    int k,limit;
    if(prev_calculated == 0)
    limit = rates_total - 2;
    else
    limit = fmin(rates_total - prev_calculated, rates_total - 2);
    //--- the main loop of calculations
    for(k = limit; k >= 0; --k)
    {
    Dn_OsMA_Buffer[k] = 0.0;
    Up_OsMA_Buffer[k] = 0.0;

    //-- calculate OsMA
    if (OsMA_Buffer[k] > OsMA_Buffer[k + 1])
    Up_OsMA_Buffer[k] = OsMA_Buffer[k];
    else
    Dn_OsMA_Buffer[k] = OsMA_Buffer[k];
    }

    //--- return value of prev_calculated for next call
    return(rates_total);
    }



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





    Сообщение: 561
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 28.01.18 20:03. Заголовок: Scriptong пишет: Ус..


    Scriptong пишет:

     цитата:
    Установка признака таймсерии делается один раз, а не на каждом тике. И не для одного буфера, а для всех. Поэтому и проблема:



    Все точно! В этом проблема. А что с советниками? Вот пример на сайте mql5.com
    /---- indicator buffers
    double MA[]; // массив для индикатора iMA
    //---- handles for indicators
    int MA_handle; // указатель на индикатор iMA
    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- создание указателя на объект - индикатор iMA
    MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
    return(0);
    }
    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    //--- заполнение массива MA[] текущими значениями индикатора iMA
    //--- в массив будет записано 100 элементов
    CopyBuffer(MA_handle,0,0,100,MA);
    //--- задаём порядок индексации массива MA[] как в MQL4
    ArraySetAsSeries(MA,true);
    //--- а дальше делайте с этими данными всё что угодно, например:
    if(MA[0]>MA[1])
    {
    //--- выполнение каких-то операций
    }
    }

    1. Почему в советниках порядок индексации делается на каждом тике?
    2. Есть ли возможность в советниках обновлять последние бары как в индикаторах, если для анализа нужно большое их количество.
    3. И стоит ли использовать динамический массив, если для анализа брать 2 последних бара.


    Можно ли написать так:

    double MA[2]; // массив для индикатора iMA
    //---- handles for indicators
    int MA_handle; // указатель на индикатор iMA
    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- создание указателя на объект - индикатор iMA
    MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
    //--- задаём порядок индексации массива MA[] как в MQL4
    ArraySetAsSeries(MA,true);
    return(0);
    }
    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    //--- заполнение массива MA[] текущими значениями индикатора iMA
    //--- в массив будет записано 2 элементов
    CopyBuffer(MA_handle,0,0,2,MA);

    //--- а дальше делайте с этими данными всё что угодно, например:
    if(MA[0]>MA[1])
    {
    //--- выполнение каких-то операций
    }
    }

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2575
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 29.01.18 16:01. Заголовок: Sergey пишет: Можно..


    Sergey пишет:

     цитата:
    Можно ли написать так:


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

     цитата:
    double MA[];
    int MA_handle;
    void OnInit()
    {
    MA_handle = iMA(NULL, 0, 21, 0, MODE_EMA, PRICE_CLOSE);
    ArraySetAsSeries(MA, true);
    }

    void OnTick()
    {
    if (!IsNewBar())
    return;

    if (CopyBuffer(MA_handle, 0, 0, 2, MA) != 2)
    {
    Print("Receiving MA values error N", GetLastError());
    return;
    }

    if (MA[0] > MA[1])
    {
    Print("MA[0] (", MA[0], ") greater than MA[1] (", MA[1], ")");
    }
    else
    Print("MA[0] (", MA[0], ") less than MA[1] (", MA[1], ")");
    }

    bool IsNewBar()
    {
    static datetime dtLastTime = 0;
    datetime arrdtTime[1];

    if (CopyTime(Symbol(), PERIOD_CURRENT, 0, 1, arrdtTime) != 1)
    {
    Print("Receiving Time value error N", GetLastError());
    return false;
    }

    bool bResult = (arrdtTime[0] != dtLastTime);
    dtLastTime = arrdtTime[0];
    return bResult;
    }



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





    Сообщение: 562
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 29.01.18 17:37. Заголовок: Игорь, огромное спас..


    Игорь, огромное спасибо!
    Ситуацию по обращению к индикаторам прояснил.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 563
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 18.02.18 09:47. Заголовок: Столкнулся с не пони..


    Столкнулся с не пониманием обращения к функции... в mql4.
    //+------------------------------------------------------------------+
    //| Проверяет объем ордера на корректность |
    //+------------------------------------------------------------------+
    bool CheckVolumeValueStart(double volume,string &description)
    {
    //--- минимально допустимый объем для торговых операций
    double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
    if(volume<min_volume)
    {
    description=StringFormat("Объем меньше минимально допустимого SYMBOL_VOLUME_MIN=%.2f",min_volume);
    return(false);
    }

    //--- максимально допустимый объем для торговых операций
    double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
    if(volume>max_volume)
    {
    description=StringFormat("Объем больше максимально допустимого SYMBOL_VOLUME_MAX=%.2f",max_volume);
    return(false);
    }

    //--- получим минимальную градацию объема
    double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

    int ratio=(int)MathRound(volume/volume_step);
    if(MathAbs(ratio*volume_step-volume)>0.0000001)
    {
    description=StringFormat("Объем не является кратным минимальной градации SYMBOL_VOLUME_STEP=%.2f, ближайший корректный объем %.2f",
    volume_step,ratio*volume_step);
    return(false);
    }
    description="Корректное значение объема";
    return(true);
    }
    //=============================================================================
    Что делать с &description?
    if (!CheckVolumeValueStart(Lot,................)) return;
    Конечно, можно его убрать из функции, а в тексте заменить на Print. Но хотелось бы разобраться, что это значит и как правильно применить.
    Спасибо!


    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить



    Сообщение: 52
    Зарегистрирован: 03.03.13
    Репутация: 0
    ссылка на сообщение  Отправлено: 18.02.18 16:55. Заголовок: Sergey пишет: Что д..


    Sergey пишет:

     цитата:
    Что делать с &description?
    if (!CheckVolumeValueStart(Lot,................)) return;
    Конечно, можно его убрать из функции, а в тексте заменить на Print. Но хотелось бы разобраться, что это значит и как правильно применить.


    Этот аргумент функции нужно рассматривать как сообщение об ошибке. Пользоваться так:

     цитата:

    string description = "";
    if (!CheckVolumeValueStart(Lot, description))
    {
    Print(description);
    return;
    }


    Могу согласиться с тем, что в качестве примера такой прием вызывает недоумение. Скорее всего взято из какого-то готового проекта и вставлено как есть.

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





    Сообщение: 564
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 18.02.18 19:03. Заголовок: Admin пишет: Могу с..


    Admin пишет:

     цитата:
    string description = "";


    А вот это я и пропустил. Забыл объявить. Спасибо Игорь!
    Admin пишет:

     цитата:
    Могу согласиться с тем, что в качестве примера такой прием вызывает недоумение. Скорее всего взято из какого-то готового проекта и вставлено как есть.


    В маркете на mql5.com при валидации (автоматической проверки на наличие ошибок) это выдано в качестве примера. Авто контроль проверяет каждую из позиций: минимальный и максимальный лот, кратность шагу и достаточность свободных средств для стартового лота в советнике. Причем ошибка обязательно должна быть выведена в журнал (Print) иначе проверку сова на проходит. Пришлось сделать отдельную объединенную функцию на будущее. Замучился, пока понял, что ошибка неправильные объемы относятся к стартовому лоту.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 565
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 19.02.18 12:12. Заголовок: Сейчас другая пробле..


    Сейчас другая проблема:"Необходимо добавить возможность проверки торговых функций программы на наличие ошибок в Тестере стратегий." В советнике заложен вывод (Alert), если ордер не установлен, при условии, что все параметры заданы правильно. Что еще нужно не пойму. Ведь Alert в журнал тоже выводится. Может кто подскажет, что означает выше указанная ошибка.....
    И вот это:
    TickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double Lot = CalculatedProfit/TickValue/TakeProfit;

    TickValue почему-то именно для золота равно 0. Валютные пары тестирование проходят. Бред какой-то. Как обойти не знаю. В тестере ошибок нет.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2581
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 19.02.18 18:14. Заголовок: Sergey пишет: Сейча..


    Sergey пишет:

     цитата:
    Сейчас другая проблема:"Необходимо добавить возможность проверки торговых функций программы на наличие ошибок в Тестере стратегий." В советнике заложен вывод (Alert), если ордер не установлен, при условии, что все параметры заданы правильно. Что еще нужно не пойму. Ведь Alert в журнал тоже выводится. Может кто подскажет, что означает выше указанная ошибка.....


    Alert при тестировании выводится в журнал тестера по аналогии с функцией Print. Само окно и звуковой сигнал, конечно же, не отображается ни в одном из режимов тестирования.

    Sergey пишет:

     цитата:
    И вот это:
    TickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double Lot = CalculatedProfit/TickValue/TakeProfit;

    TickValue почему-то именно для золота равно 0. Валютные пары тестирование проходят. Бред какой-то. Как обойти не знаю. В тестере ошибок нет.


    Проверил для золота на Альпари. Есть значение.
    А в онлайн что показывает?
    Еще можно попробовать заменить на более современную форму:

     цитата:

    SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);





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





    Сообщение: 566
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 19.02.18 21:40. Заголовок: Scriptong пишет: ще..


    Scriptong пишет:

     цитата:
    ще можно попробовать заменить на более современную форму:


    За эту подсказку спасибо. Что современнее , то и надо применять.
    Scriptong пишет:

     цитата:
    А в онлайн что показывает?


    Значения есть. Мне видится дело не в этом, а в настойках стартового лота. Проблему решил так: Установил в стартовых настройках вместо расчетного постоянный лот. Таким образом строка в авто проверку не попала. Теперь жду замечания от модератора.....

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2582
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 20.02.18 10:35. Заголовок: Sergey пишет: Значе..


    Sergey пишет:

     цитата:
    Значения есть. Мне видится дело не в этом, а в настойках стартового лота. Проблему решил так: Установил в стартовых настройках вместо расчетного постоянный лот. Таким образом строка в авто проверку не попала. Теперь жду замечания от модератора


    Ну это пока Вы решили радикально. Но ведь такая возможность может потребоваться в будущем. Значит, следует разобраться, почему на золоте получены нулевые значения.
    Кроме того, в том коде, который Вы привели, нет проверки деления на 0. Может просто ввести ее и ждать, пока будет получен не 0? Такое часто бывает при необходимости подкачки данных.

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





    Сообщение: 567
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 20.02.18 15:35. Заголовок: Scriptong пишет: Кр..


    Scriptong пишет:

     цитата:
    Кроме того, в том коде, который Вы привели, нет проверки деления на 0. Может просто ввести ее и ждать, пока будет получен не 0? Такое часто бывает при необходимости подкачки данных.


    Идея верная... Тем более я допустил еще ряд ошибок.....
    TickValue = MarketInfo(Symbol(), MODE_TICKVALUE); Я закачиваю при инициации в функции OnInit() вместе с другими параметрами, что в принципе не верно, так как для обратных и кросс курсов эта величина не постоянная. Можно дополнить примерно так: в начале OnTick()

    TickValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);
    if (TickValue = 0) return;

    Верно? Или делать запрос при каждом тике не рационально,
    а лучше внутри функции расчета лота примерно так:

    while (true)
    {
    TickValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);
    if (TickValue !=0) break;
    }


    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2583
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 21.02.18 10:08. Заголовок: Sergey пишет: Верно..


    Sergey пишет:

     цитата:
    Верно? Или делать запрос при каждом тике не рационально,
    а лучше внутри функции расчета лота примерно так:


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

    Посмотрите, как у меня это реализовано на примере любого советника. Допустим, Quantum. В папке Include\Common есть файл Common_GetSymbolInfo.mqh. В нем - реализация класса GetSymbolInfo. Так вот, метод RefreshInfo этого класса вызывается в начале каждого тика. Внутри этого метода собираются все данные рыночного окружения. При этом неважно, что многие из них (величина пункта, к примеру) практически константы. Всякое может случиться, а потому необходимо быть готовым к изменению любого из этих параметров.

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





    Сообщение: 568
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 21.02.18 11:42. Заголовок: Scriptong пишет: По..


    Scriptong пишет:

     цитата:
    Посмотрите, как у меня это реализовано на примере любого советника.


    Огромное спасибо!
    Я пока сделал так
    if (!SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE,TickValue))
    {
    Comment((isRussianLang)? "Ошибка получения данных SYMBOL_TRADE_TICK_VALUE " :
    "Error retrieving data SYMBOL_TRADE_TICK_VALUE ",GetLastError());
    return;
    }
    Но обязательно посмотрю пример. Ваш опыт очень для меня важен. Я именно на ваших примерах научился mql4.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 569
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 09.05.18 15:31. Заголовок: Всем Привет! Игорь, ..


    Всем Привет! Игорь, подскажи, как определить дыры в истории котировок? Вот пример: индикатор установлен на график Н1, но обсчитывает данные с М1.
    Последовательность баров без дары 5,4,3,2,1,0
    Та же последовательность с дыркой 4,3,_,2,1,0
    Проверка типа:
    //+---------------------------------------------------------------------------+
    //| Проверка доступности баров указанного таймфрейма |
    //+---------------------------------------------------------------------------+
    bool IsAllBarsAvailable(int lastBar,int tf)
    {
    if(lastBar <= 0) return (false);
    // Проверка доступности баров
    for(int i=lastBar; i>=0; i--)
    if(iTime(Symb,tf,i)==0)
    return (false);
    // Все бары доступны
    return (true);
    }
    Эту дырку на М1 не замечает. Почему не пойму.... В результате проверка пройдена, а индикатор на участке с дыркой не рассчитывается.
    Просьба, если есть готовое решение обнаружения дыр в истории скинь пожалуйста.

    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2599
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 11.05.18 20:53. Заголовок: Sergey пишет: Игорь..


    Sergey пишет:

     цитата:
    Игорь, подскажи, как определить дыры в истории котировок?


    К сожалению, не существует универсального способа автоматической проверки наличия дыр в истории. Сам МТ4 довольно часто не замечает их и, соответственно, не заполняет дыры информацией с сервера. В таких случаях рецепт только один: вручную удалять всю историю и закачивать ее заново. Чаще всего помогает.

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

    Простой пример. Открываем график и видим, что между 27.04.2018 и 30.04.2018 имеется визуальный разрыв в значениях котировок. Логично предположить, что тут дыра. Но потом смотрим календарь и видим, что это пятница и понедельник соответственно. То есть на самом деле не дыра. Этот случай еще поддается автоматизации.
    Углубимся. Допустим, последняя свеча минутного графика 27.04.2018 - 22:30, хотя официальное закрытие недели значится как 22:55. Что это: недостаток данных длиной в 25 минут (дыра?) или действительно не было котировок до закрытия, потому что рынок под конец недели вялый? Вот такие случаи невозможно решить без наличия эталона. Только вот если эталон у нас имеется, то и сама проблема автоматически исчезает.

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





    Сообщение: 570
    Зарегистрирован: 05.03.13
    Репутация: 1
    ссылка на сообщение  Отправлено: 12.05.18 05:28. Заголовок: Scriptong пишет: То..


    Scriptong пишет:

     цитата:
    То есть нужен эталон, с которым возможно провести сравнение.


    Спасибо. Благодаря твоему разъяснению, возникла идея. Попробую ее изложить и проверить.
    Суть проблемы:
    Скажем, Вы не открывали терминал 3 рабочих дня. После открытия терминала на 4 день, данные по всем ТФ обновляются на истории 2048 баров. Для М1 это 1,4 дня, для М5-7,1 дней. Таким образом мы имеем пробел истории котировок только на М1. Теперь, если устроить проверку согласованности графиков для М1 по времени открытия баров старшего тайм-фрейма, мы получим ошибку. Следовательно нужно закачать историю.... Конечно, полностью дыры на М1 таким образом не проверить, но будет понимание в необходимости обновления истории. По крайней мере этого будет достаточно для подбора минимального ТФ с полной закаченной историей.
    Еще раз спасибо. Бегу реализовывать.....


    С уважением! Спасибо: 0 
    ПрофильЦитата Ответить





    Сообщение: 2600
    Зарегистрирован: 03.03.13
    Откуда: Украина, Каменское (Днепродзержинск)
    Репутация: 3
    ссылка на сообщение  Отправлено: 14.05.18 09:32. Заголовок: Sergey пишет: Бегу ..


    Sergey пишет:

     цитата:
    Бегу реализовывать.....


    Это уже реализовано на основе тиковой истории. Вот скрипт.

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

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