В штатной форме МТ5 наверно мы не скоро дождемся опции установки SL/TP в процентах или деньгах. Поэтому только MQL5-программа нас спасет.
Вот код от ИИ, вставленный в сервис MQL5, без всякой проверки (!).
Мониторит все позиции по всем символам или опциональному списку инструментов.
// Общая функция для модификации стоп-лосса с проверкой "лучшей цены" bool ModifySL(ulong ticket, double riskAmountMoney) { // 1. Выбираем позицию if(!PositionSelectByTicket(ticket)) return false; string symbol = PositionGetString(POSITION_SYMBOL); double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double currentSL = PositionGetDouble(POSITION_SL); double lot = PositionGetDouble(POSITION_VOLUME); double tp = PositionGetDouble(POSITION_TP); int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); double point = SymbolInfoDouble(symbol, SYMBOL_POINT); ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // 2. Рассчитываем стоимость дистанции через OrderCalcProfit double testPoints = 100.0 * point; double testPrice = (type == POSITION_TYPE_BUY) ? (openPrice - testPoints) : (openPrice + testPoints); double profitInMoney = 0; // Используем тип ордера, соответствующий типу позиции ENUM_ORDER_TYPE orderType = (type == POSITION_TYPE_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; if(!OrderCalcProfit(orderType, symbol, lot, openPrice, testPrice, profitInMoney)) return false; double lossForTestPoints = MathAbs(profitInMoney); if(lossForTestPoints <= 0) return false; // 3. Рассчитываем целевую цену стоп-лосса double finalDistance = (riskAmountMoney / lossForTestPoints) * testPoints; double newSL = (type == POSITION_TYPE_BUY) ? (openPrice - finalDistance) : (openPrice + finalDistance); newSL = NormalizeDouble(newSL, digits); // 4. ПРОВЕРКА: Нужно ли менять стоп-лосс? // Меняем, если СЛ не установлен (0) ИЛИ если новый СЛ "безопаснее" (ближе к цене или в плюсе) bool needModify = false; if(currentSL == 0) { needModify = true; // Стопа нет — ставим } else { if(type == POSITION_TYPE_BUY) { if(newSL > currentSL) needModify = true; // Для Buy новый стоп выше старого } else if(type == POSITION_TYPE_SELL) { if(newSL < currentSL || currentSL == 0) needModify = true; // Для Sell новый стоп ниже старого } } if(!needModify) return false; // Текущий стоп уже лучше или такой же // 5. Отправка запроса через чистое API MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_SLTP; request.position = ticket; request.symbol = symbol; request.sl = newSL; request.tp = tp; return OrderSend(request, result); } // Функции-обертки (без изменений) bool SetSLByPercent(ulong ticket, double percent) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); return ModifySL(ticket, balance * (percent / 100.0)); } bool SetSLByMoney(ulong ticket, double moneyAmount) { return ModifySL(ticket, moneyAmount); }
Вот код от ИИ, вставленный в сервис MQL5, без всякой проверки (!).
А вы точно автор учебника? Вас на взломали?😁
Сомнительная нормализация.
if(type == POSITION_TYPE_BUY) { if(newSL > currentSL) needModify = true; // Для Buy новый стоп выше старого } else if(type == POSITION_TYPE_SELL) { if(newSL < currentSL || currentSL == 0) needModify = true; // Для Sell новый стоп ниже старого }
Очень сомнительное сравнение цен.
А вы точно автор учебника? Вас на взломали?😁
Сомнительная нормализация.
Очень сомнительное сравнение цен.
Я ж написал - без проверки - с восклицательным знаком.
Дотошные могут заменить нормализацию цены на MathRound(price / tick) * tick, где tick = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE).
А проблем со сравнениями я не вижу - утоните, что не так. Там есть лишняя проверка на ноль, но она не играет роли.
А проблем со сравнениями я не вижу - утоните, что не так. Там есть лишняя проверка на ноль, но она не играет роли.
Я вот этим сравниваю. CCompare - старый код, который мигрировал с MQL4 и живет в отдельном файле.
В eps я передаю (tickSize / 2.0).
#define _greater(a, b, x) ((a) - (b) > x) #define _less(a, b, x) _greater(b, a, x) #define _greaterOrEqual(a, b, x) ((a) - (b) > -x) #define _lessOrEqual(a, b, x) ((a) - (b) < x) class CCompare { public: static bool greater(double v1, double v2, double eps) { return _greater(v1, v2, eps); } static bool less(double v1, double v2, double eps) { return _less(v1, v2, eps); } static bool goe(double v1, double v2, double eps) { return _greaterOrEqual(v1, v2, eps); } static bool loe(double v1, double v2, double eps) { return _lessOrEqual(v1, v2, eps); } }; #undef _greater #undef _less #undef _greaterOrEqual #undef _lessOrEqual
утоните, что не так
Я подозреваю, что если разница между ценами больше нуля и меньше половины tickSize, то могут возникнуть проблемы, когда tickSize > _Point. Но это не точно, я уже не помню. Поэтому я и написал "сомнительное сравнение", а не "неправильное сравнение".
[edit]
Примерно как-то так:
- type: POSITION_TYPE_BUY
- newSL (unnormalized): 1.106
- currentSL: 1.105
- tickSize: 0.005
- _Digits: 3
Если нормализуете с помощью NormalizeDouble, то newSL должен получиться невалидным с точки зрения торгового сервера.
Если нормализуете с помощью tickSize, то newSL будет строго равен currentSL.
Это все навскидку, я не проверял и могу ошибаться.
#define _greater(a, b, x) ((a) - (b) > x) #define _less(a, b, x) _greater(b, a, x) #define _greaterOrEqual(a, b, x) ((a) - (b) > -x) #define _lessOrEqual(a, b, x) ((a) - (b) < x)
Те макросы неидеальные, к стати. Там 2 разных макроса могут вернуть true для одних и тех-же аргументов, когда разница строго равна 'x' или что-то типа того (не помню точно). Но в реальности 'x' подбирается таким образом, чтобы разница не совпала с ним настрого, поэтому я поленился отлаживать макросы.
Примерно как-то так:
- type: POSITION_TYPE_BUY
- newSL (unnormalized): 1.106
- currentSL: 1.105
- tickSize: 0.005
- _Digits: 3
Если нормализуете с помощью NormalizeDouble, то newSL должен получиться невалидным с точки зрения торгового сервера.
Если нормализуете с помощью tickSize, то newSL будет строго равен currentSL.
Это все навскидку, я не проверял и могу ошибаться.
По поводу замены NormalizeDouble - согласен - написал предложение выше. Тогда в коде сравнение делается уже для нормализованного newSL и проблем нет.
Прикладываю файл с изменениями.
По поводу замены NormalizeDouble - согласен - написал предложение выше. Тогда в коде сравнение делается уже для нормализованного newSL и проблем нет.
Прикладываю файл с изменениями.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
На форме Новый Ордер, в отложенном ордере, при вводе Цены и нажатии на клавишу Tab, я хочу, чтобы автозаполнялось значения поля Стоп Лосс так, что если стоп лосс сработает, у меня оставалось 50% депозита.
Да, я хочу, чтобы я мог менять (нечасто) сколько процентов депозита у меня останется, если стоп лосс сработает, но пока нет идей, где...