Double vs FLOAT - непонятная ошибка MathFloor - страница 6

 
fxsaber:
Да.
Спасибо
 
Vladislav Andruschenko:
Спасибо
На первой странице решение лежало... уже шестая.
 
fxsaber:
Тогда почему это работает без нормализации и MathFloor?
Если на входе 0.95?
 
Dmitry Fedoseev:
Если на входе 0.95?
Не понял.
 
Vladislav Andruschenko:
Я может не совсем понял что надо получить, но посмотри такой вариант
void OnStart()
{
double ask2 = 1.55557, ask3 = 1.55558, bid = 1.55555;
  Print("(ask2 + bid)/2 = ", (ask2 + bid)/2);
   Print("(ask3 + bid)/2 = ", (ask3 + bid)/2);
    int avPrice_2 = (int)NormalizeDouble((ask2/_Point + bid/_Point)/2, 0);
   int avPrice_3 = (int)NormalizeDouble((ask3/_Point + bid/_Point)/2, 0);
  Print("avPrice_2 = ", avPrice_2);
Print("avPrice_3 = ", avPrice_3);
}/*******************************************************************/
результат
2017.02.27 00:03:54.453 00 (EURUSD.m,H1)        (ask2 + bid)/2 = 1.55556
2017.02.27 00:03:54.456 00 (EURUSD.m,H1)        (ask3 + bid)/2 = 1.555565
2017.02.27 00:03:54.456 00 (EURUSD.m,H1)        avPrice_2 = 155556
2017.02.27 00:03:54.456 00 (EURUSD.m,H1)        avPrice_3 = 155557
 

"берем Аск и Бид. и вычисляем среднюю цену. Если спред нечетный (3,5,7,9 и тд) тогда приравниваем среднюю цену ближе к Бид."

Задача-то не поставлена:

- что означает нечетный спред. 1,3,..,9 раз по Point или 1,3,..,17,57 раз по Point? Округления ведь работают внутри единичных отрезков...

- что значит "ближе к Бид"? В частности, если спред величиной в 43 раза больше Point, например. Речь идет о приравнивании Бид к чему?

Нужна сначала ясность в задаче, только тогда можно будет сделать однозначное решение.

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

double Ask,Bid,Middle; // Уже известные курсы Ask и Bid, вычисляемый средний курс
int Mash,Spr; // Множитель перехода к целым числам. Для 4-разрядного EURUSD 10000. И целочисленный спред

Mash=MathRound(1.0/_Point);
Spr=MathRound((Ask-Bid)*Mash); // Целочисленный спред
// Придаем конкретность среднему курсу.  Предполагаем, что "ближе к Бид" значит "ближайший меньший среднего арифметического Ask и Bid, кратный Point"
Spr=Spr >> 1; // Целочисленный спред, деленный на 2 с отбрасыванием остатка
Middle=Bid+Spr*_Point;


// Если предположение неверно, канва последующих разборов такая
if ((Spr &  1)  != 0)) {  // Спред нечетный
  }
else {  // Спред четный
  }

 
У меня что-то похожее случилось в совсем простой задаче - скрипт читал из тайм-серий цены открытия дня EURUSD в доубл массив и затем этот массив записывал в файл. Пока цена была больше единицы, все было отлично. Но когда в нулевом году цена опустилась ниже 1, иногда, не часто, примерно раз 20 за год, стали появляться какие-то странности - где-то в 15-ом знаке после запятой стала отниматься единичка, естественно все предыдущие становились 9-ми. Вроде и фигня, но не красиво. Нормализацию делал везде и после чтения и перед записью в файл и во время записи, и перегонял из одного массива в другой с нормализацией - ничего не помогало. Если же прибавлял 1 при чтении из тайм-серии то все было о'k. Вобщем в конце концов мне это надоело, поменял доубл на флоат и успокоился. 
 
Vladimir:

"берем Аск и Бид. и вычисляем среднюю цену. Если спред нечетный (3,5,7,9 и тд) тогда приравниваем среднюю цену ближе к Бид."

Задача-то не поставлена:

 

На самом деле, задача вроде бы простая? и ее может выполнить школьник? :-) я тоже так думал.

Но в ценах, полученных с сервера, в нормализации данных и остальном - есть такие темные уголки, о которых даже не подразумеваешь.

я 9 лет программирую на mql - и у меня никогда не возникало проблем с нормализацией потому, что я воспринимал ее верно. и точность до 1 миллипункта  всегда работала верно.

 

Но есть задачи. которые требуют высокой точности.

И есть условия.

А именно:

  1. Берем цену АСК и БИД - вычисляем ее среднюю цену = все просто? ок.
  2. Соответственно, если спред нечетный(3 пункта например) то мы не можем поделить без остатка, все верно?

Так вот, нам надо нормализовать цену так, чтобы если есть остаток(а он будет даже при четном спреде ! :-)) то мы усредняем цену ближе к нижней точке, т.е. к Бид.

например:

  • аск = 1.23455 бид = 1.23457 спред = 2 Средняя цена: 1.23456
  • аск = 1.23455 бид = 1.23458 спред = 3 Средняя цена: 1.23456 
  • аск = 1.23455 бид = 1.23459 спред = 4 Средняя цена: 1.23457  

 

И вроде бы все просто?  все должно работать и я сам дурак? и я 2 дня сидел надеялся, что я не дурак. Понимая про хвосты и даблы и триблы и библы..................

Но! при одной и той же формуле, при четных спредах и нечетных спредах - в некоторых ситуациях - Формула не работала. (см.выше) .

В том числе, она может работать на валютах, а на нефти - не работать.

Она может работать на JPY а на USD в какой то момент времени не работать.

Может быть она смотрит на влияние Луны? погоду в Африке .................

Но, когда ты уверен, что формула работает, ты не замечаешь этот 1 милипипс. и работаешь дальше..... и тут "Бац,Бац,бац,бац" а этот милипунктик, решил убежать, или позвать второго миллипунктика, Который  мешает.

 

ИМХО.

Вы можете считать меня дураком, недопрограммистом, школьником.... и так далее.

Но факт остается фактом.

При разных комбинациях - с double значениями происходит ошибка. При этом с float все четко.  

Почему? пока не осознал сам. Помощь это очень хорошо, и я всегда прибегаю к помощи, это нормально. и через 10 лет я могу попросить помощи у сообщества. Это нормально. И я отвечаю на призыв помощи, если знаю какие -то подводные камни.Это нормально.  

Конечно же, после таких тестов, я проведу "доп.расследование", чтобы понять для себя, почему так происходит.

Спасибо всем за отзывчивость и помощь.   

 
Vladislav Andruschenko:

На самом деле, задача вроде бы простая? и ее может выполнить школьник? :-) я тоже так думал.

Но в ценах, полученных с сервера, в нормализации данных и остальном - есть такие темные уголки, о которых даже не подразумеваешь.

я 9 лет программирую на mql - и у меня никогда не возникало проблем с нормализацией потому, что я воспринимал ее верно. и точность до 1 миллипункта  всегда работала верно.

Но! при одной и той же формуле, при четных спредах и нечетных спредах - в некоторых ситуациях - Формула не работала. (см.выше) .

При разных комбинациях - с double значениями происходит ошибка. При этом с float все четко.  

При чем здесь вообще нормализация данных по версии Метаквотес? Этот термин для программистов означает совсем другое, вовсе не округление. Прочтите стандарт IEEE 754, например, здесь: http://www.softelectro.ru/ieee754.html. Ненормализованные вещественные числа располагаются в диапазоне до 1,17549421*10^(-38) в случае 4 байт длины и до 4....*10^(-324) в случае 8 байт длины, мы с ними встречаемся крайне редко и уж точно не при расчетах курса. Надо будет вызывать OrderSend, тогда и округлите по требованиям этой функции. Не надо использовать округление, пока задача этот не требует.

Ошибки возникают не в формате double или float, а в используемых операциях. То, что формула не решала задачу, говорит о несоответствии формулы задаче. Не более. Скажите, какие ошибки возникают при обычном расчете без нормализации (это кусок из моего сообщения выше):

Spr=MathRound((Ask-Bid)/_Point); Spr=Spr >> 1; Middle=Bid+Spr*_Point;

IEEE 754 - стандарт двоичной арифметики с плавающей точкой
  • Yashkardin Vladimir
  • www.softelectro.ru
double-precision длина числа, бит 32 64 смещенная экспонента (E), бит 8 11 остаток от мантиссы (M), бит 23 52 смещение 127 1023 двоичное денормализованое число (-1)S∙0,M∙exp2-127 ,где M-бинарное (-1)S∙0,M∙exp2-1023 ,где M-бинарное двоичное нормализованое число (-1)S∙1,M∙exp2(E-127) ,где M-бинарное (-1)S∙1,M∙exp2(E-1023) ,где M-бинарное...
 
Vladislav Andruschenko:

 

На самом деле, задача вроде бы простая? и ее может выполнить школьник? :-) я тоже так думал.

Но в ценах, полученных с сервера, в нормализации данных и остальном - есть такие темные уголки, о которых даже не подразумеваешь.

я 9 лет программирую на mql - и у меня никогда не возникало проблем с нормализацией потому, что я воспринимал ее верно. и точность до 1 миллипункта  всегда работала верно.

 

Но есть задачи. которые требуют высокой точности.

И есть условия.

А именно:

  1. Берем цену АСК и БИД - вычисляем ее среднюю цену = все просто? ок.
  2. Соответственно, если спред нечетный(3 пункта например) то мы не можем поделить без остатка, все верно?

Так вот, нам надо нормализовать цену так, чтобы если есть остаток(а он будет даже при четном спреде ! :-)) то мы усредняем цену ближе к нижней точке, т.е. к Бид.

например:

  • аск = 1.23455 бид = 1.23457 спред = 2 Средняя цена: 1.23456
  • аск = 1.23455 бид = 1.23458 спред = 3 Средняя цена: 1.23456 
  • аск = 1.23455 бид = 1.23459 спред = 4 Средняя цена: 1.23457  

 

И вроде бы все просто?  все должно работать и я сам дурак? и я 2 дня сидел надеялся, что я не дурак. Понимая про хвосты и даблы и триблы и библы..................

Но! при одной и той же формуле, при четных спредах и нечетных спредах - в некоторых ситуациях - Формула не работала. (см.выше) .

В том числе, она может работать на валютах, а на нефти - не работать.

Она может работать на JPY а на USD в какой то момент времени не работать.

Может быть она смотрит на влияние Луны? погоду в Африке .................

Но, когда ты уверен, что формула работает, ты не замечаешь этот 1 милипипс. и работаешь дальше..... и тут "Бац,Бац,бац,бац" а этот милипунктик, решил убежать, или позвать второго миллипунктика, Который  мешает.

 

ИМХО.

Вы можете считать меня дураком, недопрограммистом, школьником.... и так далее.

Но факт остается фактом.

При разных комбинациях - с double значениями происходит ошибка. При этом с float все четко.  

Почему? пока не осознал сам. Помощь это очень хорошо, и я всегда прибегаю к помощи, это нормально. и через 10 лет я могу попросить помощи у сообщества. Это нормально. И я отвечаю на призыв помощи, если знаю какие -то подводные камни.Это нормально.  

Конечно же, после таких тестов, я проведу "доп.расследование", чтобы понять для себя, почему так происходит.

Спасибо всем за отзывчивость и помощь.   

В зависимости от целей, иногда стоит вообще переходить в целые числа. Сильно бережёт нервы :-) Как-то была задача где надо было точно разметить много-много уровней, сначала умуторился с double, а потом перевёл всё в целые пункты с 0 и всё стало легко,просто и без ошибок.