советник - разные вопросы - страница 3

 
double LotCalculator(double lots)
  {
   double minlot  = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN),
          maxlot  = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX),
          lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   lots = MathFloor(lots/lotstep)*lotstep;
   lots = MathMax(lots,minlot);
   lots = MathMin(lots,maxlot);
   return(NormalizeDouble(lots,2));
  }
 
honest_knave:
double LotCalculator(double lots){}

Большое спасибо.

Я просто хочу начать писать этот код :)

Вы спасли меня не один раз.

Большое спасибо!

 
Я получил такое же сообщение для Lot Size.
Я вызываю 'LotCalculator()' в 'OnChartEvent()', так что это неправильно?
 

Я ищу хороший форум для вычисления'MarketInfo & LotSize'.
Кто знает такой хороший форум, пожалуйста, поделитесь со мной.

Спасибо.

 
Вы случайно не использовали мой фрагмент кода до того, как я отредактировал последнюю строку (NormalizeDouble)? Я вижу, что с момента моего сообщения до вашего прошло всего 3 минуты, и я отредактировал его почти сразу.
 
Max Enrik: Я использую NormalizeDouble для своих советников. Но меня беспокоит сообщение'NormalizeDouble', но я вижу размер лота на графике следующим образом: 0.07

Поэтому мне нужен хороший совет, пожалуйста.

02:00:00.069 - custom expert EURUSD,H1: | _lotSize - NormalizeDouble: 0.07000000000000001
02:00:00.069 - custom expert EURUSD,H1: | _lotSize - DoubleToString : 0.07
  1. NormalizeDouble возвращает двойное число. Плавающая точка имеет бесконечное число десятичных знаков, это ваше непонимание плавающей точки и того, что некоторые числа не могут быть представлены точно. (например, 1/10.) Формат двойной точности с плавающей точкой - Википедия, свободная энциклопедия См. также Операнд ==. - Форум MQL4
  2. НЕ используйте NormalizeDouble, НИКОГДА. По любой причине. Это ошибка, не используйте ее. Его использование всегда неправильно
 
whroeder1:
  1. НЕ используйтеNormalizeDouble, НИКОГДА. По любой причине. Это ошибка, не используйте ее.Ее использование всегда неправильно.

Я считаю, что вам все еще нужна функция NormalizeDouble().

Вот пример, использующий ваш фрагмент кода (то же самое относится и к моему примеру с использованием MathFloor):

double NormalizeLots(double lots, string pair=""){
    if (pair == "") pair = Symbol();
    double  lotStep     = MarketInfo(pair, MODE_LOTSTEP),
            minLot      = MarketInfo(pair, MODE_MINLOT);
    lots                = MathRound(lots/lotStep) * lotStep;
    if (lots < minLot) lots = 0;    // or minLot
    return(lots);
}

Вызвано:

Print(NormalizeLots(2/3.0));

Результат:

0.7000000000000001

Теперь код скорректирован:

double NormalizeLots(double lots, string pair=""){
    if (pair == "") pair = Symbol();
    double  lotStep     = MarketInfo(pair, MODE_LOTSTEP),
            minLot      = MarketInfo(pair, MODE_MINLOT);
    lots            = MathRound(lots/lotStep) * lotStep;
    if (lots < minLot) lots = 0;    // or minLot
    return(NormalizeDouble(lots,2));
}

Результат:

0.7


 

 Result: 0.7000000000000001

Какая часть фразы "Вы не понимаете, что такое плавающая точка и что некоторые числа не могут быть представлены точно. (например, 1/10.) Формат двойной точности с плавающей точкой - Википедия, свободная энциклопедия" была непонятна?

NormalizeDouble(0.7, 2) даст такой же точный результат (или, возможно, 0.69999999999999999).

 
whroeder1:

Какая часть фразы "Вы не понимаете, что такое плавающая точка и что некоторые числа не могут быть представлены точно. (например, 1/10.) Формат двойной точности с плавающей точкой - Википедия, свободная энциклопедия" была непонятна?

NormalizeDouble(0.7, 2) даст такой же точный результат (или, возможно, 0.69999999999999999).

Я не говорю, что NormalizeDouble() требуется для правильной OrderSend. Именно поэтому мой первый фрагмент кода исключил ее. Мне также неясно, каким образом представляются числа с плавающей запятой.

Я отредактировал фрагмент, включив его, потому что почувствовал, что он лучше отражает мое понимание проблемы ОП (по сути, проблема отображения, которая может быть решена либо использованием NormalizeDouble() в коде "нормализатора лота", либо использованием printf или DoubleToStr, когда значение должно быть отображено).

Возможно, я неправильно понял ОП.

02:00:00.069 - custom expert EURUSD,H1: | _lotSize - NormalizeDouble: 0.07000000000000001
02:00:00.069 - custom expert EURUSD,H1: | _lotSize - DoubleToString : 0.07

(отредактировано для удаления ненужной резкости)

 
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- get minimum stop level
   double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   Print("Minimum Stop Level=",minstoplevel," points");
   double price=Ask;
//--- calculated SL and TP prices must be normalized
   double stoploss=NormalizeDouble(Bid-minstoplevel*Point,Digits);
   double takeprofit=NormalizeDouble(Bid+minstoplevel*Point,Digits);
//--- place market order to buy 1 lot
   int ticket=OrderSend(Symbol(),OP_BUY,1,price,3,stoploss,takeprofit,"My order",16384,0,clrGreen);
   if(ticket<0)
     {
      Print("OrderSend failed with error #",GetLastError());
     }
   else
      Print("OrderSend placed successfully");
//---
  }

Это может смутить людей, потому что в документации MQL4 в большинстве примеров используется функция NormalizeDouble().

Она даже предупреждает, что ненормализованная цена не может быть применена:

Примечание

При открытии рыночного ордера (OP_SELL или OP_BUY) в качестве цены открытия могут быть использованы только последние цены Bid (для продажи) или Ask (для покупки). Если операция производится с ценной бумагой, отличной от текущей, то для получения последних котировок по этой бумаге необходимо использовать функцию MarketInfo() с параметром MODE_BID или MODE_ASK.

Расчетная или ненормированная цена не может быть применена. Если в потоке цен не было запрошенной цены открытия или она не была нормализована по количеству цифр после десятичной точки, будет сгенерирована ошибка 129 (ERR_INVALID_PRICE). Если запрашиваемая цена открытия полностью устарела, то независимо от параметра проскальзывания будет сгенерирована ошибка 138 (ERR_REQUOTE). Если запрашиваемая цена устарела, но присутствует в потоке, ордер будет открыт по текущей цене и только если текущая цена лежит в диапазоне цена+проскальзывание.

И даже в некоторых лучших книгах по MQL они используют его довольно активно.

Возможно, это зависит от сферы применения, и проблема отображения менее драматична, чем сбои ордеров или модификаций.

Лично я всегда конвертирую в целые числа, поэтому редко с этим сталкиваюсь.