Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Кто знает, могу ли я передать функции не члену класса в качестве аргумента ссылку (адрес) на другую функцию, которая вообще не является членом никакого класса?
Или, могу ли я передать функции члену класса в качестве аргумента ссылку (адрес) на другую функцию, которая вообще не является членом никакого класса?
Кто знает, могу ли я передать функции не члену класса в качестве аргумента ссылку (адрес) на другую функцию, которая вообще не является членом никакого класса?
Или, могу ли я передать функции члену класса в качестве аргумента ссылку (адрес) на другую функцию, которая вообще не является членом никакого класса?
Нет. Нет.
Не можете. В MQL5 нет понятия "адрес функции" или "ссылка на функцию".
Спасибо!
Другой вопрос.
Есть два файла с кодом на mql5. Первый файл основной – индикатор или скрипт. Второй файл mqh.
Возможно, перестраховываюсь, но ещё такой вопрос. Перед отправкой запроса на постановку рыночного ордера (с целью открытия позиции) обнуляю тикет сделки, т.е. делаю result.deal=0. Может ли произойти такая ситуация, что сервер в структуре ответа MqlTradeResult вернёт нулевой тикет сделки, но при этом чуть позже сделка всё-таки совершится и позиция будет открыта? Или же возврат сервером нулевого тикета сделки гарантированно означает, что позицию не получилось открыть и она в дальнейшем не будет открыта на основании этого запроса?
ОК, в силу отсутствия ответа и в силу вот этой строчки
struct MqlTradeResult
{
ulong deal; // Тикет сделки, если она совершена
};
прихожу к выводу, что возврат сервером нулевого тикета сделки гарантированно означает, что позицию не получилось открыть и она в дальнейшем не будет открыта на основании этого запроса.
не очень разобрался в структуре форума, если не туда, прошу направить в нужном направлении
т.к. я не профильный спец, но интерес в программировании есть и исходя из собственных наклонностей в процессе обучения пытаюсь разобраться путем анализа существующего кода
для простоты взял фрагмент кастом кода МА , и пытаюсь понять что происходит в нем (отразил в комментах)
в общем если не сложно, прокомментируйте пожалуйста код, хочется понимать что происходит после каждой команды. Спасибо.
void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[]) //разобрался вроде с &price[]
вывел в распринтовку и вижу что значение в ExtLineBuffer присваиваются с индекса limit-1 по индекс rates_total-1, а на графике индикатор отрисован на всем пространстве, хм, где же тогда происходит присвоение значения буферу индикатора на промежутке от 1 до limit-1 ???
не очень разобрался в структуре форума, если не туда, прошу направить в нужном направлении
т.к. я не профильный спец, но интерес в программировании есть и исходя из собственных наклонностей в процессе обучения пытаюсь разобраться путем анализа существующего кода
для простоты взял фрагмент кастом кода МА , и пытаюсь понять что происходит в нем (отразил в комментах)
в общем если не сложно, прокомментируйте пожалуйста код, хочется понимать что происходит после каждой команды. Спасибо.
Подробно комментировать не буду, возможно достаточно будет поправить основную ошибку вашего восприятия, и тогда сами соберёте пазл - это гораздо полезнее.
Итак, основа вашей запутанности в том, что многие индикаторы в mql5 (в частности этот) пишутся без разворота индексации индикаторных буферов, т.е. при значении AsSeries=false.
Это значит, что индекс самого старого бара на истории = 0, а самого "свежего" = RatesTotal-1
// Проясняется что-то??..
Смысл такого подхода - некоторый выигрыш в скорострельности, т.к. индексация при обращении к буферу не требует [скрытого] пересчёта (остаётся "аппаратной")
// Путаница у вас возникла вероятно из убеждённости (ошибочной) что для индикаторных буферов индексация ВСЕГДА происходит от конца истории к началу. Это всегда верно в mql4, но в mql5 не обязательно.
// Здесь направление индексации по умолчанию всегда от начала истории к концу, для переворота индексации нужно пользоваться функцией SetAsSeries(...) в явном виде.
// Причём в справке разработчики вообще не рекомендуют опираться на умолчания (на тот случай если они таки поменяются) и ВСЕГДА пользоваться функцией SetAsSeries() для задания направления индексации.
void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[]) //разобрался вроде с &price[]
вывел в распринтовку и вижу что значение в ExtLineBuffer присваиваются с индекса limit-1 по индекс rates_total-1, а на графике индикатор отрисован на всем пространстве, хм, где же тогда происходит присвоение значения буферу индикатора на промежутке от 1 до limit-1 ???
Спасибо что отозвались )
Про порядок направленности в массивах и рекомендациях о явном указании направленности прочитал в справке, правда оставались сомнения, которые были ликвидированы после распринтовки промежуточных данных в переменных.
Пока только определилась направленность, т.е. коммент про инициализацию был ошибочным, инициализируются значения буфера индикатора на указанном диапазоне слева на графике.
Остались вопросы про
1. переменную begin, за его значение передаваемое в обработчик события отвечает терминал? откуда берется его значение?
2. переменную типа double можно значением типа int?
3. судя по всему, за значение переменной prev_calculated тоже отвечает терминал
4. непонятно? где происходит расчет индикатора на промежутке от 0 до limit-1
Остались вопросы про
1. переменную begin, за его значение передаваемое в обработчик события отвечает терминал? откуда берется его значение?
3. судя по всему, за значение переменной prev_calculated тоже отвечает терминал
Скорее всего, обсуждаемая функция писалась под первую форму вызова функции OnCalculate(). См. Справочник.
Остались вопросы про
2. переменную типа double можно значением типа int?
Да, можно. См. раздел про неявное приведение типов. Компилятор часто будет выдавать предупреждение о возможности потери данных при использовании неявного приведения типов.
Остались вопросы про
4. непонятно? где происходит расчет индикатора на промежутке от 0 до limit-1
Отвечают ли эти строчки на Ваш вопрос:
//--- set empty value for first limit bars for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0; //--- calculate first visible value ... и далее по коду
?Спасибо что отозвались )
Про порядок направленности в массивах и рекомендациях о явном указании направленности прочитал в справке, правда оставались сомнения, которые были ликвидированы после распринтовки промежуточных данных в переменных.
Пока только определилась направленность, т.е. коммент про инициализацию был ошибочным, инициализируются значения буфера индикатора на указанном диапазоне слева на графике.
Остались вопросы про
1. переменную begin, за его значение передаваемое в обработчик события отвечает терминал?
Здесь важно отметить назначение этого параметра. Этот параметр указывает индикатору сколько начальных исторических значений входного ряда необходимо проигнорировать (пропустить), так как они являются некорректными и не должны принимать участия в расчётах. Откуда может взяться такая некорректность, каково её происхождение? Она связана с с возможностью построения индикаторов рассчитываемых не на ценовых данных, а на данных предоставленных другими индикаторами. В МТ5 существует три механизма позволяющих получить на вход индикатора данные другого индикатора.Первый способ. Последовательность шагов:
1. Создать хендл входного индикатора при помощи одной из функций серии iIndicator(...). либо функции IndicatorCreate(...).
2. По мере необходимости забирать его значения из его буферов при помощи функции CopyBuffer(...).
Второй способ. Является расширением первого. Необходим, если при первом способе на вход входного индикатора нужно подать не ценовой ряд, а индикаторный. Т.е. в этом случае мы намереваемся получать в программе значения рассчитываемые входным индикатором (2) берущим на свой собственный вход данные другого индикатора (1). Т.е. построить цепочку индикатор-от-индикатора.
Последовательность шагов:
1. Создать хендл первого (1) входного индикатора при помощи одной из функций серии iIndicator(...). либо функции IndicatorCreate(...).
2. Создать хендл второго (2) индикатора тем же способом, но при создании указать в качестве последнего параметра (applied_price) хендл первого (1).
3. По мере необходимости забирать его значения из его буферов при помощи функции CopyBuffer(...).
Третий способ. Также используется при построении цепочек индикаторов-от-индикаторов. Но в отличии от предыдущего варианта источник данных (входной ряд) не фиксируется до компиляции, а может быть задан пользователем непосредственно в терминале. Путём указания соответствующего параметра в момент запуска индикатора.
Предоставляю вам возможность самостоятельно разобраться в этих механизмах. Я указал в предыдущем тексте довольно много прямых ссылок на ключевые места в документации, которые вам помогут в этом.
Остановимся лишь на параметрах короткой формы вызова OnCalculate(). Итак:
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
Их назначение вполне внятно документировано. Здесь я хочу лишь объяснить саму необходимость (обоснованность) их передачи в данную функцию. С первым и последним параметром, надеюсь, всё достаточно ясно. Для вычислений мы должны иметь буфер с входными данными (price[]) и знать его текущую длину. (не забываем что длина его растёт по мере послупления котировок в терминал).
Но кроме того нам необходимо знать также с самого ли начала входного ряда его данные строго корректны или начальные значения следует проигнорировать, в связи с их (возможной или гарантированной) некорректностью. Некорректность в большинстве случаев гарантированно возникает когда входные данные являются выходом другого индикатора. Ну а как иначе? Большинство индикаторов для вычисления значения на каком либо баре, должны использовать некоторый объём исторических данных. А где им взяться "в начале времён"? Их там нетути, и поэтому они вынужденны приступить к генерации выходных значений не со стартового исторического бара, а несколько позже (правее), с того бара, раньше ( левее) которого уже есть необходимое количество исторических данных.
Вот теперь, благодаря расписанным мной выше деталям, ответ на вопрос
откуда берется его значение? // речь про параметр begin
и будет понятен целиком и полностью. Отвечаю: несмотря на то, что этот параметр в функцию передаёт терминал, о его содержимом должен должен позаботиться входной индикатор! Терминал сам в состоянии проконтролировать только ценовые входные ряды (в этом случае значение begin будет равно 0, и это правильное значение). Поэтому, при написании любого индикатора (кроме разве что чисто экспериментальных) следует позаботиться о том, чтобы он сообщал терминалу индекс начала корректных данных в его выходном буфере. Это понятно? Иначе "потомки" этого индикатора могут скушать очень невкусные некорректные данные и в ряде случаев даже сильно отравиться... :) Теперь о том как это делается. Для этого используется функция PlotIndexSetInteger() с указанием идентификатора свойства PLOT_DRAW_BEGIN. Важно! Для 100% корректности формируемого свойства индикатора, невозможно ограничиться однократным вызовом PlotIndexSetInteger(...,PLOT_DRAW_BEGIN,...) в OnInit() ! Почему так? А потому, что наш индикатор может быть сам, в свою очередь, сформирован на данных другого индикатора, который уже имеет начальный отступ на истории.! Т.е. мы имеем ненулевое значение begin на входной истории, и получить его в OnInit() нет возможности. Итак, мы обязаны сделать примерно такой
PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod-1+begin);
вызов. И сделать его мы вынуждены (желательно однократно) в OnCalculate(), поскольку в OnInit значение begin неизвестно.
Что конечно оставляет за нами право сделать также предварительный (хотя и не очень осмысленный) вызов
PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);
в OnInit().
Именно так и сделано в том индикаторе (Custom Moving Average.mq5) из которого вы взяли ваш образец для изучения.
2. переменную типа double можно значением типа int?
Да, переменную типа double совершенно безболезненно можно инициализировать значением типа int, если оно задано константой. // как это и обстоит в вашем примере
3. судя по всему, за значение переменной prev_calculated тоже отвечает терминал
4. непонятно? где происходит расчет индикатора на промежутке от 0 до limit-1
В данном случае эти значения не могут быть корректно рассчитаны (не хватает истории для вычисления). Поэтому им тупо присваиваются нулевые значения.
// я бы предпочёл присвоить им соответствующие входные данные, но это суть дела особо не меняет.