Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 6. - страница 640

 
mql_writer:
Добрый день, в языке есть такой параметр рынка, как MarketInfo(Symbol(), MODE_TICKVALUE). Можете в общих словах описать, как считается это значение?

Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.
 
borilunad:

Это стоимость минимального изменения цены (1 пип) в валюте депозита при лоте 1.00! Вычисляется очень просто: 1.00(лот)/ 1.36030(котир евродоллара на текущий момент) = 0.7351 в евро.

только вот на запрос через маркетинфо чего-то возвращает 10 для всех пар, кроме йеновых )))


А  вы откуда такую формулу-то взяли?

 
evillive:

только вот на запрос через маркетинфо чего-то возвращает 10 для всех пар, кроме йеновых )))


А  вы откуда такую формулу-то взяли?


Я сам делаю все формулы и сейчас взял со своего графика.

А это из Доки: 

MODE_TICKVALUE

16

Размер минимального изменения цены инструмента в валюте депозита

 

Вычислениями не делятся. 

 
borilunad:


Я сам делаю все формулы и сейчас взял со своего графика.

А это из Доки: 

MODE_TICKVALUE

16

Размер минимального изменения цены инструмента в валюте депозита

 Вычислениями не делятся. 


Вот именно это самое скриптом задаю и возвращает всегда 10 ) Хотя для 1 лота евродоллара 1 пункт и правда стоит 10 долларов, так что всё правильно.

А вычислениями не делятся только те, кому стыдно их показывать, математика - она и в Африке математика

И да, в данном случае формулу переделать надо бы, правильно будет MODE_TICKVALUE = MODE_LOTSIZE * MODE_TICKSIZE - для евродоллара, для кроссов и йеновых формула немного другая

[Удален]  
Top2n:


Если честно, то  не понял как применить. Осталось до конца миллиметр, обидно останавливаться когда почти все законченно.

Задача, не записывать в массив цену, если время объекта(2-ого параметра+3600сек>текущего)||(время 1-ого параметра - время 2-ого параметра)<3600сек )

А зачем эмулировать ошибку?

Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".

Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.

Так и надо сделать:

/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime 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))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}

Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?

Для каждой такой маленькой подзадачки напрашивается отдельная функция.

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

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

Результат прогона:

02:08:46 Script 2 EURUSDm,H1: loaded successfully
02:08:46 2 EURUSDm,H1: initialized
02:08:46 2 EURUSDm,H1: Sell:
02:08:46 2 EURUSDm,H1: name = downtrendline1, dt = 2014.06.24 22:09:02, dt1 = 2014.06.24 10:00:00, dt2 = 2014.06.24 17:00:00
02:08:46 2 EURUSDm,H1: Найдено объектов: 0
02:08:46 2 EURUSDm,H1: Buy:
02:08:46 2 EURUSDm,H1: name = uptrendline0, dt = 2014.06.24 22:09:02, dt1 = 2014.06.23 09:00:00, dt2 = 2014.06.24 16:00:00
02:08:46 2 EURUSDm,H1: Найдено объектов: 0
02:08:46 2 EURUSDm,H1: uninit reason 0
02:08:46 Script 2 EURUSDm,H1: removed

Ни одного объекта не найдено. Увеличим значения обоих мнемоник в 10 раз до 36000 (10 часов) и прогоним ещё раз:

02:09:03 Script 2 EURUSDm,H1: loaded successfully
02:09:03 2 EURUSDm,H1: initialized
02:09:03 2 EURUSDm,H1: Sell:
02:09:03 2 EURUSDm,H1: name = downtrendline1, dt = 2014.06.24 22:09:14, dt1 = 2014.06.24 10:00:00, dt2 = 2014.06.24 17:00:00
02:09:03 2 EURUSDm,H1: Найдено объектов: 0
02:09:03 2 EURUSDm,H1: Buy:
02:09:03 2 EURUSDm,H1: name = uptrendline0, dt = 2014.06.24 22:09:14, dt1 = 2014.06.23 09:00:00, dt2 = 2014.06.24 16:00:00
02:09:03 2 EURUSDm,H1: Найдено объектов: 1
02:09:03 2 EURUSDm,H1: Price[0] = 1.35869
02:09:03 2 EURUSDm,H1: uninit reason 0
02:09:03 Script 2 EURUSDm,H1: removed

Одна трендовая уже "прошла" фильтрацию. Теперь восстановим значение первой мнемоники до 3600 и прогоним:

02:09:12 Script 2 EURUSDm,H1: loaded successfully
02:09:12 2 EURUSDm,H1: initialized
02:09:12 2 EURUSDm,H1: Sell:
02:09:12 2 EURUSDm,H1: name = downtrendline1, dt = 2014.06.24 22:09:26, dt1 = 2014.06.24 10:00:00, dt2 = 2014.06.24 17:00:00
02:09:12 2 EURUSDm,H1: Найдено объектов: 1
02:09:12 2 EURUSDm,H1: Price[0] = 1.36152
02:09:12 2 EURUSDm,H1: Buy:
02:09:12 2 EURUSDm,H1: name = uptrendline0, dt = 2014.06.24 22:09:26, dt1 = 2014.06.23 09:00:00, dt2 = 2014.06.24 16:00:00
02:09:12 2 EURUSDm,H1: Найдено объектов: 1
02:09:12 2 EURUSDm,H1: Price[0] = 1.35869
02:09:12 2 EURUSDm,H1: uninit reason 0
02:09:12 Script 2 EURUSDm,H1: removed

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

Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.

Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.

Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".

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

В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().

 
 извините не увидел тему сразу 
https://www.mql5.com/ru/forum/152102 у меня вопрос
 
borilunad:

Всё правильно! С 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

 
evillive:

У меня сейчас 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-х значная котировка, я ещё не писал программ, потому судить не могу. :)  

Спокойной ночи! 

 
simpleton:

А зачем эмулировать ошибку?

Ошибка - она для сигнализации того, что по каким-то причинам, связанным с ограничениями/отказами системы, не удалось выполнить алгоритм и получить результат с какими-то (естественно, ограниченными, но - ) гарантиями. Функция FillAndPrint() как раз красноречиво и показывает, что значит ошибочная ситуация, а что - нет. Когда возникает ошибка, она даже не пытается выдавать результат. Если же ошибки не возникло, результату можно доверять. Именно таким образом должна строиться логика "ошибка/не ошибка".

Здесь же нужна модификация алгоритма: требуется ещё наложить дополнительный фильтр.

Так и надо сделать:

Сначала "отфильтровали" по типам и параметрам объектов, выбрав из всех имеющихся объектов только нужные нам, а затем наложили дополнительный фильтр. Примерно, как это делал бы человек. Человек, ведь, примерно так и делал бы?

Для каждой такой маленькой подзадачки напрашивается отдельная функция.

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

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

Результат прогона:

Ни одного объекта не найдено. Увеличим значения обоих мнемоник в 10 раз до 36000 (10 часов) и прогоним ещё раз:

Одна трендовая уже "прошла" фильтрацию. Теперь восстановим значение первой мнемоники до 3600 и прогоним:

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

Чтобы помочь как-то формализовывать, попробую так объяснить. Программа, видимо, подобна плану.

Каждый крупный пункт плана может быть разбит на пункты более мелкого подплана. Мелкий - на ещё более мелкий. Пункты самых мелких подпланов исполняются непосредственно.

Каждый план, подплан и даже пункты самых мелких подпланов соответствует функциям в программе. Пункты самых мелких подпланов соответствуют "концевым" функциям, которые вызывают только системные функции или даже их не вызывают, например, в обсуждаемых выше в качестве примера можно привести AddValue() или DiffInSecs(). Пункты подпланов, стоящих выше, соответствуют функциям, которые вызывают функции, реализующие пункты подпланов, стоящих ниже. В обсуждаемых выше это - MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Низкоуровневые" функции не должны вызывать "высокоуровневые", а "высокоуровневые", в основном, не должны перескакивать на несколько уровней вниз, то есть, должны вызывать функции, в основном, только на уровень ниже. Для "низкоуровневых" это правило намного строже, чем для "высокоуровневых".

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

В данной программе получилось вырожденное дерево: одна несколько раз "ветвящаяся" ветвь. И "ветвится" она не на две маленьких ветви, а на одну. Но суть, что "высокоуровневые" функции последовательно вызывают "низкоурвневые", прослеживается. В данной модификации я вставил в эту структуру ещё один уровень, ещё одну "неразветвлённую ветвь" - AddValueIfFiltered().

Выкладываю готовый код. 

Задача: Поиск линий тренда (OBJ_TREND), запись значений цены относительно текущего бара в массив. С фильтрацией относительно существования параметров времени объекта (OBJ_TREND).

 

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime 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))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpleton: Спасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

У меня сейчас 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


Что-то вы напутали! Нашёл время заглянуть в код, выбрал выражения, и смотрите: 

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

Проще не может быть! Никаких 10, 16 и т.д.