Any rookie question, so as not to clutter up the forum. Professionals, don't pass by. Nowhere without you - 6. - page 640

 
Good afternoon, the language has such a market parameter as MarketInfo(Symbol(), MODE_TICKVALUE). Can you describe in general terms how this value is calculated?
 
mql_writer:
Good afternoon, the language has such a market parameter as MarketInfo(Symbol(), MODE_TICKVALUE). Can you describe in general terms how this value is calculated?

This is the value of minimal price change (1 pip) in the deposit currency at 1.00 lot! Calculation is very easy: 1.00(lot)/1.36030(current quote of Euro) = 0.7351 in Euro.
 
borilunad:

This is the value of minimal price change (1 pip) in the deposit currency at 1.00 lot! Calculated very simply: 1.00(lot)/1.36030(current quote of Euro) = 0.7351 in Euro.

Except that a request via marketinfo somehow returns 10 for all pairs except yen pairs ))))


Where did you get this formula from?

 
evillive:

except that a query through marketinfo somehow returns 10 for all pairs except yen pairs ))))


Where did you get this formula from?


I do all the formulas myself and now I took it from my chart.

And this one is from Doki:

MODE_TICKVALUE.

16

Size of minimal change of symbol price in the deposit currency

Calculations are not shared.

 
borilunad:


I make all the formulas myself and have now obtained them from my chart.

And this is from the Docks:

MODE_TICKVALUE

16

Size of minimum instrument price change in the deposit currency

Calculations are not shared.


Although for 1 eurodollar lot 1 pip really costs 10 dollars, so it's Ok.

And calculations should not be shared only with those who are ashamed to show them.

Yes, in this case the formula should be correct - MODE_TICKVALUE = MODE_LOTSIZE * MODE_TICKSIZE - for Euro, the formula for crosses and Yen is a bit different

 
Top2n:


To be honest, I haven't figured out how to apply it. There's a millimetre to go, it's a shame to stop when it's almost finished.

Task, don't write price to array if object time(2nd parameter+3600sec>current)||(time of 1st parameter - time of 2nd parameter)<3600sec )

Why emulate an error?

An error is it to signal that, for some reason related to system limitations/failures, the algorithm failed to execute and get a result with some (naturally limited, but - ) guarantees. The FillAndPrint() function just eloquently shows what an error situation means and what it doesn't. When an error occurs, it does not even try to print the result. If there is no error, the result can be trusted. That's how the logic "error/no error" should be built.

But here we need to modify the algorithm: we also need to apply an additional filter.

So it must be done:

/******************************************************************************/
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; // Нет ошибки, значение, если найдено, добавлено к массиву
}

First we "filtered" by object types and parameters, selecting only the objects we need from all the available ones, and then we apply an additional filter. It's roughly how a person would do it. That's what a person would do, right?

For each of these small subtasks, we need a separate function.

Numbers should not be in expressions, except in very special cases, for example, if it is necessary to double, and this doubling is in the nature of the algorithm. Then the number 2 can be used directly in expressions. And in other such very rare cases.

In other cases, mnemonics should be used. Firstly, they greatly improve the understanding of what is going on in a given place, and therefore help reduce the probability of making an error. And secondly, the value itself is set in one place and it is easy to change it if necessary, and it will be impossible to make a mistake compared to the case where the number is used repeatedly in the algorithm, and without using mnemonics have to correct the numbers in several places of the algorithm.

Result of the run:

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

Not a single object is found. Increase the values of both mnemonics 10 times to 36000 (10 hours), and run again:

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

One trend has already "passed" the filtering. We now restore the value of the first mnemonic to 3600 and run:

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

We can see that now both trendlines have "passed" filtering. By the way, I recommend to debug all branches (parts) of the program in such a way, not only one branch.

To help you somehow formalize it, I will try to explain it in this way. A program is apparently like a plan.

Each major item of the plan can be broken down into items of a smaller sub-plan. Smaller ones into even smaller ones. The points of the smallest sub-plans are executed directly.

Each plan, sub-plan and even the points of the smallest sub-plans correspond to functions in the programme. Items in the smallest sub-plans correspond to "end" functions that only call system functions, or even don't call them at all, e.g., AddValue() or DiffInSecs() are examples in the discussion above. The subplan items above correspond to the functions that call the functions that implement the subplan items below. In the ones discussed above, these are MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Low-level" functions should not call "high-level" functions, and "high-level" functions basically should not jump several levels down, i.e. should only call functions basically at the level below. This rule is much stricter for "low-level" than for "high-level".

Try to build your programs by organizing the actions in them as (short) functions linked by this kind of tree structure, in the sense of who calls whom.

This program has a degenerate tree: one branch that "branches" several times. And it "branches" not into two small branches but into one. But the point that "high-level" functions consistently call "low-level" ones can be seen. In this modification, I have inserted one more level into this structure, another "unbranched branch" - AddValueIfFiltered().

 
Sorry I didn't see the thread straight away.
https://www.mql5.com/ru/forum/152102 Ihave a question
 
borilunad:

All is correct! With a 4-digit quote it was always 1, and witha 5-digit quote it is now 10, because there are 10 times more pips (and shallower). And the value of a min. tick should be calculated from the current price!

I have 4 digits now, on ewardollar at 1 lot 1 point costs $10 and has always been so. For crosses the cost will be 8 to 16, the formula is a bit more complicated there.

For example, for the euro pound marketinfo has returned 16.984, the pound-dollar exchange rate = 1.6984, that is, 1 point of the euro pound is worth 1 pound, multiplied by the pound-dollar point value, which is always 10.0 (100000 * 0.0001 = 10.0 or 100000 * 0.00010 = 10.0 - whatever one likes).


All these calculations are correct only if your account is in dollars:

In this case, for xUSD (EURUSD, GBPUSD etc.) tickvalue = lot*point = 100000*0.0001 = 10.0

for USDx (USDCHF, USDJPY etc) tickvalue = lot*point/Bid = 100000*0.01/101.93 = 9.8107

for xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98

for crosses xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9.8126

 
evillive:

I have 4 digits now, on ewardollar at 1 lot 1 point costs $10 and has always been so. For crosses the cost will be from 8 to 16, the formula is a bit more complicated there.

For example, for the euro pound marketinfo has returned 16.984, the exchange rate of evodollar = 1.3604, the pound-dollar exchange rate = 1.6984, that is, 1 pip of the euro pound is worth 1 pound, multiplied by the pound-dollar point value, which is always 10.0 (100000*0.0001 = 10.0 or 100000*0.00010 = 10.0 - whatever one likes).




Mine is simple and practical! And at the time when there was a 4-digit quote, I had not yet written programs, so I can't judge. :)

Good night!

 
simpleton:

Why emulate an error?

Error - it is to signal that, for some reason related to system limitations/failures, the algorithm could not be executed and the result obtained with some (limited, of course, but - ) guarantees. The FillAndPrint() function just eloquently shows what an error situation means and what it doesn't. When an error occurs, it does not even try to print the result. If there is no error, the result can be trusted. This is how the error/no error logic should be constructed.

You need to modify the algorithm here: you need to apply an additional filter.

This is how it should be done:

First, we "filter" by object types and parameters, selecting only the objects we need from all the available ones, and then we apply an additional filter. It's roughly how a person would do it. That's what a person would do, right?

For each such small subtask, a separate function is desirable.

There should be no numbers in expressions, except in very special cases, for example if you need to double and it is in the nature of the algorithm to do so. Then the number 2 can be used directly in expressions. And in other such very rare cases.

In other cases, mnemonics should be used. Firstly, they greatly improve the understanding of what is going on in a given place, and therefore help reduce the chance of making a mistake. And secondly, the value itself is defined in one place and it is easy to change it if necessary, and it will be impossible to make a mistake compared to the case where the number is used in the algorithm more than once, and without using mnemonics you have to fix the numbers in several places of the algorithm.

Result of the run:

Not a single object is found. Increase the values of both mnemonics 10 times to 36000 (10 hours), and run again:

One trend has already "passed" the filtering. Now let's restore the value of the first mnemonic to 3600 and run:

It can be seen that both trends have now "passed" filtering. By the way, I recommend debugging all branches (parts) of the program in such a way, rather than any one branch.

To help formalise somehow, I'll try to explain it this way. The program is apparently like a plan.

Each major plan item can be broken down into smaller sub-plan items. Smaller ones into even smaller ones. The items of the smallest sub-plans are executed directly.

Each plan, sub-plan, and even the smallest sub-plans correspond to functions in the program. Items in the smallest sub-plans correspond to "end" functions that call only system functions or even don't call them at all, for example, AddValue() or DiffInSecs() are examples of those discussed above. The subplan items above correspond to the functions that call the functions that implement the subplan items below. In the ones discussed above, these are MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Low-level" functions should not call "high-level" functions, and "high-level" functions basically should not jump several levels down, i.e. should only call functions basically at the level below. This rule is much stricter for "low-level" than for "high-level".

Try to build your programs by organizing the actions in them as (short) functions linked by this kind of tree structure, in the sense of who calls whom.

This program has a degenerate tree: one branch that "branches" several times. And it "branches" not into two small branches but into one. But the point that "high-level" functions consistently call "low-level" ones can be seen. In this modification, I have inserted one more level into this structure, one more "nonbranched branch" - AddValueIfFiltered().

I am pasting the ready code.

The task: to search for trend lines(OBJ_TREND) and record price values relative to the current bar into an array. Filtered against existence of object time parameters (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Спасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))