Очень хочется услышать начальника транспортного цеха! Up
Уже много раз говорили, что нельзя сравнивать два вещественных числа на равенство значений.
Заходите на www.mql4.com
Заходите на www.mql4.com
А нормализованные можно?
у мну
double EnterLongStopLevel = NormalizeDouble( hhv + ( EnterLongStop + SymbolSpread) * SymbolPoint , 4);
double StopLevel = NormalizeDouble( EnterLongStopLevel - StopLoss * SymbolPoint, 4);
получается, что OrderOpenPrice() возвращает ненормализованное значение? или, и нормализованные double отличаются.
И второй вопрос, кто генерирует ошибку 1 сервер или терминал? То есть отправляются ли на сервер ошибочные комманды?
И третий вопрос, можно увидеть код нормализации на c? Думаю, это не know how. :) Мне в dll охота вставить его.
Кстати, первый вопрос изначально звучал так.
Как сделать, чтобы эта ошибка никогда не вылазила? То есть я не хочу выполнять Modify, если она вернет ошибку 1.
А может, мой вариант с qEqual и есть самый правильный и пацанский?
у мну
double EnterLongStopLevel = NormalizeDouble( hhv + ( EnterLongStop + SymbolSpread) * SymbolPoint , 4);
double StopLevel = NormalizeDouble( EnterLongStopLevel - StopLoss * SymbolPoint, 4);
получается, что OrderOpenPrice() возвращает ненормализованное значение? или, и нормализованные double отличаются.
И второй вопрос, кто генерирует ошибку 1 сервер или терминал? То есть отправляются ли на сервер ошибочные комманды?
И третий вопрос, можно увидеть код нормализации на c? Думаю, это не know how. :) Мне в dll охота вставить его.
Кстати, первый вопрос изначально звучал так.
Как сделать, чтобы эта ошибка никогда не вылазила? То есть я не хочу выполнять Modify, если она вернет ошибку 1.
А может, мой вариант с qEqual и есть самый правильный и пацанский?
Нормализованные значения тоже нельзя сравнивать на равенство. Нормализуйте разницу значений и сравните её с 0. С 0 можно сравнивать любые значения.
Ошибку 1 генерирует клиентский терминал.
Код нормализации очень прост. Умножить число на 10 в степени digits (можно сразу заготовить таблицу степеней, чтобы каждый раз не возводить), округлить с учётом знака (+0.5 или -0.5) и присвоить длинному целому типа __int64. После этого разделить полученное целое на 10 в степени digits с присвоением к вещественному типу.
Нет, всё-таки лучше сделайте return(NormalizeDouble(val1-val2,8)==0.0);
а ещё лучше сразу if(NormalizeDouble(val1-val2,8)==0.0)
Ошибку 1 генерирует клиентский терминал.
Код нормализации очень прост. Умножить число на 10 в степени digits (можно сразу заготовить таблицу степеней, чтобы каждый раз не возводить), округлить с учётом знака (+0.5 или -0.5) и присвоить длинному целому типа __int64. После этого разделить полученное целое на 10 в степени digits с присвоением к вещественному типу.
Нет, всё-таки лучше сделайте return(NormalizeDouble(val1-val2,8)==0.0);
а ещё лучше сразу if(NormalizeDouble(val1-val2,8)==0.0)
Спасибо
и присвоить длинному целому типа __int64.
Что за тип? Какие еще есть типы, не упомянутые в документации?
Это тип на с и с++. целое 64 бита.
Это не тип на с и с++. Такого типа там нет. typedef может быть в конкретных реализациях соответствующих библиотек.
В любом случае, здесь обсуждается не с и с++, а платформа Метатрейдер.
В любом случае, здесь обсуждается не с и с++, а платформа Метатрейдер.
Код нормализации очень прост. Умножить число на 10 в степени digits (можно сразу заготовить таблицу степеней, чтобы каждый раз не возводить), округлить с учётом знака (+0.5 или -0.5) и присвоить длинному целому типа __int64. После этого разделить полученное целое на 10 в степени digits с присвоением к вещественному типу.
Трудно представить, что после нормализации по этому алгоритму двух "близких" чисел не будет выполнено равенсто double. Возможно, в указанном мною случае используется 2 разных алгоритма или 2 компилятора разных или на сервере происходит изменение цены ордера, стопа или профита. Или Ваш алгоритм сравнения double на равенство не правильный.
У меня обычно нет большого желания double сравнивать, но если уж значения нормализуются, они должны быть равными, иначе, в чем смысл нормализации?
Это не тип на с и с++. Такого типа там нет. typedef может быть в конкретных реализациях соответствующих библиотек.
В любом случае, здесь обсуждается не с и с++, а платформа Метатрейдер.
В любом случае, здесь обсуждается не с и с++, а платформа Метатрейдер.
Человек задал вопрос, как ему самостоятельно делать нормализацию в его собственной dll, написанной на c++. Каждый производитель компиляторов реализует что-то сверх стандарта.
__int64 - это Microsoft specific. Ещё есть такие нотации: __int8, __int16 и __int32
для 64-разрядного целого есть даже форматный символ преобразования, используемый в функциях типа printf - %I64
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
// parameters string SymbolName = "EURUSD"; int SymbolPeriod = PERIOD_M1; int MagicNumber = 1; double dLot = 0.1; int EnterLongStop = 10; int StopLoss = 10; int SymbolSpread; double SymbolPoint; double CurrentLot; int lastBars = 0; int init() { SymbolSpread = MarketInfo( SymbolName, MODE_SPREAD); SymbolPoint = MarketInfo( SymbolName, MODE_POINT); CurrentLot = NormalizeDouble( dLot, 1); return(0); } int deinit() { Print("deinit()"); return(0); } int start() { // проверим тип счета, и если это не демо счет выдадим предупрежение // и закончим работу if (!IsDemo()) {Alert("На реальном счете работа запрещена"); return;} if ( isNewBar()) OnNewBar(); OnTick(); return(0); } bool isNewBar() { if ( lastBars != Bars) { lastBars = Bars; return ( true); } return ( false); } void OnNewBar() { // Print("Новый бар"); int iHighBar = iHighest( SymbolName, SymbolPeriod, MODE_HIGH, 5, 1); double hhv = iHigh( SymbolName, SymbolPeriod, iHighBar); double EnterLongStopLevel = NormalizeDouble( hhv + ( EnterLongStop + SymbolSpread) * SymbolPoint , 4); double StopLevel = NormalizeDouble( EnterLongStopLevel - StopLoss * SymbolPoint, 4); Print("HHV(4)=", hhv); int new_ticket; // Ищем наш ордер bool found = false; for( int i = OrdersTotal() - 1; i>=0; i--) { if ( ! OrderSelect( i, SELECT_BY_POS, MODE_TRADES)) continue; if ( OrderMagicNumber() != MagicNumber) continue; if ( found) Print( "Double Order"); switch ( OrderType()) { case OP_BUYSTOP: if ( OrderOpenPrice() != EnterLongStopLevel) OrderModify( OrderTicket(), EnterLongStopLevel, StopLevel, 0, 0, CLR_NONE); Print("Modify Order", EnterLongStopLevel, " Error = ", GetLastError(), " OrderTime = ", TimeToStr( OrderOpenTime())); break; default: Print("Wrong Order Type", OrderType()); } found = true; } if ( !found) { new_ticket = OrderSend( SymbolName, OP_BUYSTOP, CurrentLot, EnterLongStopLevel, 0, StopLevel, 0, "Cool", MagicNumber, 0, CLR_NONE); if( new_ticket < 0) Print("OrderSend failed with error #",GetLastError()); else Print("Set OP_BUYSTOP ", EnterLongStopLevel); } return; } void OnTick() { // Print("Новый тик"); return; }на минутном графике иногда возникает Ошибка 1 (при изменении ордера). Хотя, у мну стоит проверка
if ( OrderOpenPrice() != EnterLongStopLevel)
Как сделать, чтобы эта ошибка никогда не вылазила? То есть я не хочу выполнять Modify, если она вернет ошибку 1.
Я пробовал Normalaze, но не получилось. иправил вот так
if( qEqual( OrderOpenPrice(), qGetPrice(i), qGetPoint(i)) && qEqual( OrderStopLoss(), qGetStopLoss(i), qGetPoint(i)) && qEqual( OrderTakeProfit(), qGetTakeProfit(i), qGetPoint(i))) { return (COMMAND_DONE); } OrderModify( qGetTicket( i), qGetPrice( i), qGetStopLoss( i), qGetTakeProfit( i), 0, CLR_NONE); ................ bool qEqual( double value1, double value2, double point_value) { return ( MathAbs( value1 - value2) < 0.5 * point_value); }Хотелось бы увидеть "человеческий вариант"