mql_writer: Добрый день, в языке есть такой параметр рынка, как MarketInfo(Symbol(), MODE_TICKVALUE). Можете в общих словах описать, как считается это значение?
Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.
Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.
только вот на запрос через маркетинфо чего-то возвращает 10 для всех пар, кроме йеновых )))
Я сам делаю все формулы и сейчас взял со своего графика.
А это из Доки:
MODE_TICKVALUE
16
Размер минимального изменения цены инструмента в валюте депозита
Вычислениями не делятся.
Вот именно это самое скриптом задаю и возвращает всегда 10 ) Хотя для 1 лота евродоллара 1 пункт и правда стоит 10 долларов, так что всё правильно.
А вычислениями не делятся только те, кому стыдно их показывать, математика - она и в Африке математика
И да, в данном случае формулу переделать надо бы, правильно будет MODE_TICKVALUE = MODE_LOTSIZE * MODE_TICKSIZE - для евродоллара, для кроссов и йеновых формула немного другая
Если честно, то не понял как применить. Осталось до конца миллиметр, обидно останавливаться когда почти все законченно.
Задача, не записывать в массив цену, если время объекта(2-ого параметра+3600сек>текущего)||(время 1-ого параметра - время 2-ого параметра)<3600сек )
А зачем эмулировать ошибку?
Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".
Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.
Так и надо сделать:
/******************************************************************************/bool AddValueIfFiltered(double &array[], conststring name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600#define MAX_SECS_AFTER_PRICE2 3600constdatetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
constdatetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
constdatetime dt = TimeCurrent();
Print("name = ", name, ", dt = ", dt, ", dt1 = ", dt1, ", dt2 = ", dt2);
if (dt <= dt2 + MAX_SECS_AFTER_PRICE2 && dt1 + MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 <= dt2) { // Фильтруем, прежде чем попытаться добавитьif (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавитьreturnfalse; // Ошибка, значение не добавлено
}
}
returntrue; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}
/******************************************************************************/bool AddValueIfFound(double &array[], conststring name) {
constint type = ObjectType(name);
if (type == OBJ_TREND) {
switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switchcase Goldenrod:
case Gainsboro:
case White:
if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтрreturnfalse;
}
}
}
returntrue; // Нет ошибки, значение, если найдено, добавлено к массиву
}
Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?
Для каждой такой маленькой подзадачки напрашивается отдельная функция.
Чисел в выражениях не должно быть, кроме очень особых случаев, например, если надо удвоить, и это удвоение - в природе алгоритма. Тогда можно использовать число 2 напрямую в выражениях. И в других подобных очень редких случаях.
В остальных случаях следует использовать мнемоники. Во-первых, они значительно улучшают понимание того, что в данном месте происходит, и поэтому способствуют уменьшению вероятности допустить ошибки. А, во-вторых, само значение задано в одном месте, и его легко при необходимости поменять, причём ошибиться уже будет невозможно по сравнению со случаем, когда число используется в алгоритме неоднократно, и без использования мнемоник приходится править числа в нескольких местах алгоритма.
Видно, что теперь обе трендовые "прошли" фильтрацию. Кстати, рекомендую подобным образом отлаживать все ветви (части) программы, а не какую-то одну ветвь.
Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.
Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.
Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".
Попробуйте строить свои программы, организуя действия в них в виде (коротких) функций, связанных такой вот древовидной структурой, в смысле, кто кого вызывает.
В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().
Всё правильно! С 4-х значной котировкой показывало всегда 1, а с 5-ти значной котировкой показывает сейчас 10, т.к. пипсов стало в 10 раз больше (и мельче). А стоимость мин.тика нужно вычислять от текущей цены!
У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
Все эти вычисления верны только при условии что счёт ваш в долларах:
В таком случае, для хUSD (EURUSD, GBPUSD etc) tickvalue = lot*point = 100000*0.0001 = 10,0
для USDх (USDCHF, USDJPY etc) tickvalue = lot*point/Bid = 100000*0.01/101.93=9,8107
У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс евордоллара = 1,3604, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
У меня всё просто и практично! А в то время, когда была 4-х значная котировка, я ещё не писал программ, потому судить не могу. :)
Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".
Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.
Так и надо сделать:
Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?
Для каждой такой маленькой подзадачки напрашивается отдельная функция.
Чисел в выражениях не должно быть, кроме очень особых случаев, например, если надо удвоить, и это удвоение - в природе алгоритма. Тогда можно использовать число 2 напрямую в выражениях. И в других подобных очень редких случаях.
В остальных случаях следует использовать мнемоники. Во-первых, они значительно улучшают понимание того, что в данном месте происходит, и поэтому способствуют уменьшению вероятности допустить ошибки. А, во-вторых, само значение задано в одном месте, и его легко при необходимости поменять, причём ошибиться уже будет невозможно по сравнению со случаем, когда число используется в алгоритме неоднократно, и без использования мнемоник приходится править числа в нескольких местах алгоритма.
Результат прогона:
Ни одного объекта не найдено. Увеличим значения обоих мнемоник в 10 раз до 36000 (10 часов) и прогоним ещё раз:
Одна трендовая уже "прошла" фильтрацию. Теперь восстановим значение первой мнемоники до 3600 и прогоним:
Видно, что теперь обе трендовые "прошли" фильтрацию. Кстати, рекомендую подобным образом отлаживать все ветви (части) программы, а не какую-то одну ветвь.
Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.
Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.
Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".
Попробуйте строить свои программы, организуя действия в них в виде (коротких) функций, связанных такой вот древовидной структурой, в смысле, кто кого вызывает.
В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().
Выкладываю готовый код.
Задача: Поиск линий тренда (OBJ_TREND), запись значений цены относительно текущего бара в массив. С фильтрацией относительно существования параметров времени объекта (OBJ_TREND).
#property strict/******************************************************************************/bool AddValue(double &array[], constdouble value) {
constint size = ArraySize(array);
if (ArrayResize(array, size + 1) != size + 1) {
returnfalse; // Ошибка, значение не может быть добавлено к массиву
}
array[size] = value; //записываемreturntrue; // Нет ошибки, значение добавлено к массиву
}
/******************************************************************************/bool AddValueIfFound(double &array[], conststring name) {
constint type = ObjectType(name);
if (type == OBJ_TREND) {
switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switchcase Goldenrod:
case Gainsboro:
case White:
if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтрreturnfalse;
}
}
}
returntrue; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/bool MassTrendNumber(double &array[], constbool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masBconststring subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второеif (ArrayResize(array, 0) != 0) {
returnfalse; // Ошибка, массив не может быть заполнен достоверно
}
for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i <limit+2; i++) {
if (!AddValueIfFound(array, subname + IntegerToString(i))) {
returnfalse; // Ошибка, массив, если и заполнен, то недостоверно
}
}
returntrue; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/long DiffInSecs(constdatetime dt1, constdatetime dt2) {
return dt1 - dt2;
}
/******************************************************************************/bool AddValueIfFiltered(double &array[], conststring name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600#define MAX_SECS_AFTER_PRICE2 3600constdatetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
constdatetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
constdatetime dt = TimeCurrent();
Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));
if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавитьreturnfalse; // Ошибка, значение не добавлено
}
}
returntrue; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}
/******************************************************************************/void FillAndPrint(double &array[], constbool buy) {
if (MassTrendNumber(array, buy)) {
constint limit = ArraySize(array);
Print("Найдено объектов: ", limit);
for (int i = 0; i < limit; i++) {
Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
}
} else {
Print("Чёрт!");
}
}
/******************************************************************************/
У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
Все эти вычисления верны только при условии что счёт ваш в долларах:
В таком случае, для хUSD (EURUSD, GBPUSD etc) tickvalue = lot*point = 100000*0.0001 = 10,0
для USDх (USDCHF, USDJPY etc) tickvalue = lot*point/Bid = 100000*0.01/101.93=9,8107
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Добрый день, в языке есть такой параметр рынка, как MarketInfo(Symbol(), MODE_TICKVALUE). Можете в общих словах описать, как считается это значение?
Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.
Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.
только вот на запрос через маркетинфо чего-то возвращает 10 для всех пар, кроме йеновых )))
А вы откуда такую формулу-то взяли?
только вот на запрос через маркетинфо чего-то возвращает 10 для всех пар, кроме йеновых )))
А вы откуда такую формулу-то взяли?
Я сам делаю все формулы и сейчас взял со своего графика.
А это из Доки:
MODE_TICKVALUE
16
Размер минимального изменения цены инструмента в валюте депозита
Вычислениями не делятся.
Я сам делаю все формулы и сейчас взял со своего графика.
А это из Доки:
MODE_TICKVALUE
16
Размер минимального изменения цены инструмента в валюте депозита
Вычислениями не делятся.
Вот именно это самое скриптом задаю и возвращает всегда 10 ) Хотя для 1 лота евродоллара 1 пункт и правда стоит 10 долларов, так что всё правильно.
А вычислениями не делятся только те, кому стыдно их показывать, математика - она и в Африке математика
И да, в данном случае формулу переделать надо бы, правильно будет MODE_TICKVALUE = MODE_LOTSIZE * MODE_TICKSIZE - для евродоллара, для кроссов и йеновых формула немного другая
Если честно, то не понял как применить. Осталось до конца миллиметр, обидно останавливаться когда почти все законченно.
Задача, не записывать в массив цену, если время объекта(2-ого параметра+3600сек>текущего)||(время 1-ого параметра - время 2-ого параметра)<3600сек )
А зачем эмулировать ошибку?
Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".
Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.
Так и надо сделать:
Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?
Для каждой такой маленькой подзадачки напрашивается отдельная функция.
Чисел в выражениях не должно быть, кроме очень особых случаев, например, если надо удвоить, и это удвоение - в природе алгоритма. Тогда можно использовать число 2 напрямую в выражениях. И в других подобных очень редких случаях.
В остальных случаях следует использовать мнемоники. Во-первых, они значительно улучшают понимание того, что в данном месте происходит, и поэтому способствуют уменьшению вероятности допустить ошибки. А, во-вторых, само значение задано в одном месте, и его легко при необходимости поменять, причём ошибиться уже будет невозможно по сравнению со случаем, когда число используется в алгоритме неоднократно, и без использования мнемоник приходится править числа в нескольких местах алгоритма.
Результат прогона:
Ни одного объекта не найдено. Увеличим значения обоих мнемоник в 10 раз до 36000 (10 часов) и прогоним ещё раз:
Одна трендовая уже "прошла" фильтрацию. Теперь восстановим значение первой мнемоники до 3600 и прогоним:
Видно, что теперь обе трендовые "прошли" фильтрацию. Кстати, рекомендую подобным образом отлаживать все ветви (части) программы, а не какую-то одну ветвь.
Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.
Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.
Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".
Попробуйте строить свои программы, организуя действия в них в виде (коротких) функций, связанных такой вот древовидной структурой, в смысле, кто кого вызывает.
В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().
https://www.mql5.com/ru/forum/152102 у меня вопрос
Всё правильно! С 4-х значной котировкой показывало всегда 1, а с 5-ти значной котировкой показывает сейчас 10, т.к. пипсов стало в 10 раз больше (и мельче). А стоимость мин.тика нужно вычислять от текущей цены!
У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
Все эти вычисления верны только при условии что счёт ваш в долларах:
В таком случае, для хUSD (EURUSD, GBPUSD etc) tickvalue = lot*point = 100000*0.0001 = 10,0
для USDх (USDCHF, USDJPY etc) tickvalue = lot*point/Bid = 100000*0.01/101.93=9,8107
для кросс-курсов xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16,98
для кроссов xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9,8126
У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс евордоллара = 1,3604, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
У меня всё просто и практично! А в то время, когда была 4-х значная котировка, я ещё не писал программ, потому судить не могу. :)
Спокойной ночи!
А зачем эмулировать ошибку?
Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".
Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.
Так и надо сделать:
Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?
Для каждой такой маленькой подзадачки напрашивается отдельная функция.
Чисел в выражениях не должно быть, кроме очень особых случаев, например, если надо удвоить, и это удвоение - в природе алгоритма. Тогда можно использовать число 2 напрямую в выражениях. И в других подобных очень редких случаях.
В остальных случаях следует использовать мнемоники. Во-первых, они значительно улучшают понимание того, что в данном месте происходит, и поэтому способствуют уменьшению вероятности допустить ошибки. А, во-вторых, само значение задано в одном месте, и его легко при необходимости поменять, причём ошибиться уже будет невозможно по сравнению со случаем, когда число используется в алгоритме неоднократно, и без использования мнемоник приходится править числа в нескольких местах алгоритма.
Результат прогона:
Ни одного объекта не найдено. Увеличим значения обоих мнемоник в 10 раз до 36000 (10 часов) и прогоним ещё раз:
Одна трендовая уже "прошла" фильтрацию. Теперь восстановим значение первой мнемоники до 3600 и прогоним:
Видно, что теперь обе трендовые "прошли" фильтрацию. Кстати, рекомендую подобным образом отлаживать все ветви (части) программы, а не какую-то одну ветвь.
Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.
Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.
Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".
Попробуйте строить свои программы, организуя действия в них в виде (коротких) функций, связанных такой вот древовидной структурой, в смысле, кто кого вызывает.
В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().
Выкладываю готовый код.
Задача: Поиск линий тренда (OBJ_TREND), запись значений цены относительно текущего бара в массив. С фильтрацией относительно существования параметров времени объекта (OBJ_TREND).
void OnTick() //============================================================================================= //====================================== Линии тренда ========================================= //============================================================================================= double masS[]; double masB[]; Print("Sell:"); FillAndPrint(masS, false); Print("Buy:"); FillAndPrint(masB, true);simpleton: Спасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))У меня сейчас 4-знак, на евордолларе при 1 лоте 1 пункт стоит 10 долларов и всегда так было. Для кроссов стоимость будет от 8 до 16, там формула сложнее немного.
Вот, например, маркетинфо для еврофунта вернул 16,984, курс фунта к доллару = 1,6984, то есть 1 пункт еврофунта стоит 1 фунтдоллар умноженный на стоимость пункта фунтодоллара, которая равна всегда 10,0 (100000*0,0001=10,0 или 100000*0,00010=10,0 - кому как нравится).
Все эти вычисления верны только при условии что счёт ваш в долларах:
В таком случае, для хUSD (EURUSD, GBPUSD etc) tickvalue = lot*point = 100000*0.0001 = 10,0
для USDх (USDCHF, USDJPY etc) tickvalue = lot*point/Bid = 100000*0.01/101.93=9,8107
для кросс-курсов xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16,98
для кроссов xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9,8126
Что-то вы напутали! Нашёл время заглянуть в код, выбрал выражения, и смотрите:
Проще не может быть! Никаких 10, 16 и т.д.