Не много дополнил этот кусок из функции удаления:
Print ("Pos.iCurTicket = ", Pos.iCurTicket); Print ("OrderTicket() = ", OrderTicket()); Print ("Pos.iType = ", Pos.iType); Print ("OrderType() = ", OrderType()); Print ("Pos.dOpenPrice = ", Pos.dOpenPrice); Print ("OrderOpenPrice() = ", OrderOpenPrice()); Print ("ТУТ_3"); if (OrderDelete (Pos.iCurTicket, fc_Arrow)) { Print ("Позиция закрыта"); return (SUCCESS); }
Вот что имеем:
2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderDelete error 4108 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: unknown ticket 4 for OrderDelete function 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: ÒÓÒ_3 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderOpenPrice() = 1.09155 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.dOpenPrice = 1.09155 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderType() = 5 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iType = 5 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderTicket() = 4 2015.08.16 10:29:53.750 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iCurTicket = 4 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderDelete error 4108 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: unknown ticket 4 for OrderDelete function 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: ÒÓÒ_3 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderOpenPrice() = 1.09155 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.dOpenPrice = 1.09155 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderType() = 5 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iType = 5 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderTicket() = 4 2015.08.16 10:29:53.749 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iCurTicket = 4
Т.е. очевидно, что структура возвращает верные данные, такие же как и просто переменные позиций (OrderTicket(), OrderType(), OrderOpenPrice()). Ордер выбран! Иначе не возвратились бы данные. К тому же я их сразу же на уровне выше выбираю... Тут без вариантов. Почему его тогда не удалить? Проблема в чём?
Есть подозрение, что ордер был выбран по тикету, а не по порядковому номеру. В таком случае ордер может располагаться в списке "История счета". Из этого списка невозможно удалить ордер, о чем и пишет терминал.
Когда выбор происходит по тикету, то для определения, какому списку он принадлежит, нужно проверять время закрытия:
if (OrderSelect(ticket, SELECT_BY_TICKET)) { if (OrderCloseTime() == 0) { // Ордер находится в списке рабочих ордеров } else { // Ордер находится в истории счета (удален или закрыт) } }
Есть подозрение, что ордер был выбран по тикету, а не по порядковому номеру. В таком случае ордер может располагаться в списке "История счета". Из этого списка невозможно удалить ордер, о чем и пишет терминал.
Когда выбор происходит по тикету, то для определения, какому списку он принадлежит, нужно проверять время закрытия:
Так по ходу позиции не в истории. Вот переделал так в функции удаления ордеров:
Print ("Pos.iCurTicket = ", Pos.iCurTicket); Print ("OrderTicket() = ", OrderTicket()); Print ("Pos.iType = ", Pos.iType); Print ("OrderType() = ", OrderType()); Print ("Pos.dOpenPrice = ", Pos.dOpenPrice); Print ("OrderOpenPrice() = ", OrderOpenPrice()); Print ("OrderCloseTime() = ", OrderCloseTime()); Print ("ТУТ_3"); if (OrderDelete (Pos.iCurTicket, fc_Arrow)) { Print ("Позиция закрыта"); return (SUCCESS); } else
Вот в журнале видим так:
2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: ТУТ_3 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderCloseTime() = 1970.01.01 00:00:00 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderOpenPrice() = 1.09155 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.dOpenPrice = 1.09155 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderType() = 5 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iType = 5 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderTicket() = 4 2015.08.16 22:14:23.340 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iCurTicket = 4 2015.08.16 22:14:23.340 2015.06.02 04:55 Tester: stop button pressed 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderDelete error 4108 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: unknown ticket 4 for OrderDelete function 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: ТУТ_3 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderCloseTime() = 1970.01.01 00:00:00 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderOpenPrice() = 1.09155 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.dOpenPrice = 1.09155 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderType() = 5 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iType = 5 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: OrderTicket() = 4 2015.08.16 22:14:23.338 2015.06.02 04:55 ZZBaseVariant EURUSD,M5: Pos.iCurTicket = 4
так у вас ордер не удалился, конечно он в открытых и сидит.
пишите обработку ошибок
Все это, конечно, очень странно. Но проблема в том, что мы смотрим на ситуацию через замочную скважину - видим только некоторый кусочек информации, согласно которому все верно: ордер действительно отложенный (Sell Stop), его тикет 4 и он находится в списке рабочих ордеров. В этом свете непонятно, почему тестер выдает ошибку "неверный номер тикета".
Чтобы решить проблему, нужно увидеть всю предысторию (открытие ордеров), что можно сделать показав содержимое вкладки "Результаты", а также распечатав состояние текущего рыночного окружения (цены, стоплевелы, фризлевелы и прочее).
В общем-то, действительно, там была не корректна одна функция. Я когда переписывал класс, кавычки сдвинул. Появилась другая проблема. Тут уже канкретно не понятно как решить её нормально.
В общем, есть структура:
struct Position_Properties { string sInstrument; // Символ торгового инструмента int iType; // Тип торговой операции int iCurTicket; // Тикет выбранного ордера double dOpenPrice; // Цена открытия double dLots; // Объём позиции на открытие double dCurSL; // Текущий Stop Loss double dCurTP; // Текущий Take Profit double dNewSL; // Новый Stop Loss double dNewTP; // Новый Take Profit string sComment; // Комментарий int iMagic; // Магик };
Создаю экземпляр структуры.
Position_Properties SPos[100];
В метод TrailingByFixedValue() передаю структуру. Там пытаюсь модифицировать позицию вызывая метод fOrderModify (Pos, 0, Gold). Все данные о позиции переданные в метод fOrderModify (Pos, 0, Gold) корректны. Там возникает ошибка 130. В данном методе fOrderModify (Pos, 0, Gold) вызывается метод обработки ошибок на предмет некорректного стоплевела, в который я передаю экземпляр структуры:
bool PositionsManipulations::CheckValidStops (Position_Properties& Pos, // Структура свойств позиции double fd_Price, // Текущая цена bool fb_IsNewOrder = true) // Открытие ордера { Print (__FUNCTION__, ": Вошли в метод "); bool lb_Result = true; double ld_OrigSL = Pos.dCurSL, ld_OrigTP = Pos.dCurTP; string lsa_Txt [2] = { "","" }, ls_Symbol = Pos.sInstrument; if (!fb_IsNewOrder) ls_Symbol = OrderSymbol(); //---- ResetLastError(); //---- Если SL не 0 if (Pos.dNewSL != 0.0) { Print (__FUNCTION__, ": Pos.dNewSL = ", Pos.dNewSL); if (Pos.iType % 2 == OP_BUY) { Pos.dNewSL = fd_Price - SSym.gi_StopLevel; Print (__FUNCTION__, ": Pos.dNewSL = ", Pos.dNewSL); lsa_Txt [0] = StringConcatenate (__FUNCTION__, ": SL = ", DToS (ld_OrigSL), " | new SL [", DToS (Pos.dNewSL), "] = price [", DToS (fd_Price), "] - MinSTOP [", IToS (SSym.gi_StopLevel), "]"); if (fb_IsNewOrder) { Pos.dNewSL -= SSym.gd_Spread; lsa_Txt [1] = StringConcatenate (__FUNCTION__, ": Minus spread [", DToS (SSym.gd_Spread), "]"); } Pos.dNewSL = MathMin (Pos.dCurSL, Pos.dNewSL); if (!fb_IsNewOrder) { if (OrderStopLoss() != 0.0) { if (ND (OrderStopLoss() - Pos.dCurSL) >= 0.0) lb_Result = false; } } } //--- остальная логика
В методе CheckValidStops() получается корректное значение СТОПА. НО с CheckValidStops() должны посредством структуры передацца данные в экземпляр. Тока вот по факту там оказываются значения 0.0 у СТОПА постоянно. Значение теряется. Почему? Его нельзя передавать несколько уровней т.е. несколько методов вложенных друг в друга?
Тока вот по факту там оказываются значения 0.0 у СТОПА постоянно. Значение теряется. Почему? Его нельзя передавать несколько уровней т.е. несколько методов вложенных друг в друга?
Поля структуры dCurSL и dNewSL должны изменяться. То, что по факту в каком-то из них оказывается 0, говорит о неверном алгоритме или входных данных функции CheckValidStops. К примеру, значение fd_Price может быть равно нулю (ведь непонятно, что там возвращает CBase.GetTradePrice).
Также заметьте, что функция CheckValidStops написана вроде бы для обработки любых типов ордеров, но, в то же время, вызывается она только для рыночных ордеров. Зачем тогда универсальность функции, что усложняет ее?
Еще есть такие непонятные моменты, как:
if (ND (Pos.dCurSL - Pos.dCurSL) != 0.0)
и
if (ND (Pos.dCurTP - Pos.dCurSL) != 0.0)
Код после этих условий ни при каких обстоятельствах не будет исполнен, т. к. эквивалентен такому коду:
if (1 != 1) { // Никогда не исполнится }
Попробуйте вывести в журнал выполнение функций пошагово и увидите, где же затирается значение стопа.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Есть структура:
Для неё создан массив с некоторым запасом:
Position_Properties SPos[100];
В общем, ситуация такая:
До сих пор, в тестах то что писал, - работало. Но вчера столкнулся с косяком. И, судя по всему, не у меня в коде, а на стороне платформы. В метод удаления ордера попадает тикет, который почему-то функция удаления не "распознаёт". Почему?
Вот метод, где ошибка:
Вот лог, в котором видно, что до стандартной функции OrderDelete() всё принтуется исправно, а дальше, судя по логу тикет не читается функцией:
Возник вопрос. Почему тикет не опознан? Ведь в цикле перебора ордеров я выбираю его при помощи OrderSelect(), а значит данный ордер с данным тикетом присутствует. Номер тикета в принт возвразщается. Что ещё нужно?