Если кому нужна информация о баге - получаю дублированные данные в файл (2 одинаковые записи на закрытие вместо одной), либо вообще несовпадающие ни с одной ранее открытой позицией которая была записана в файл.
Вот более точное описание:
Каждой записи в файле об открытии позиции должна соответствовать своя запись о закрытии. Как проверяю - сравниваю номера (id позиции), 2,3 и последний столбики, в которые я пишу эти самые id (немного некрасиво и избыточно, но в будущем думаю переделать). Чтобы не сбиваться и было наглядно я эти самые записи закрашиваю одинаковым цветом.
Красными рамками выделил проблемные места, а именно - дублирование закрывающихся записей, из-за чего отсутствует ещё одна необходимая закрывающая для белых записей (4 и 10 линии). Такое ощущение будто сдвиг какой по индексам при обращении к спискам в истории.
Если кто подумает, что проблема может быть в функции которая записывает данные в файл, то нет. Она у меня одна единственная. Пишет как открывающиеся, так и закрывающиеся, другие функции подготавливают данные и записывают её в структуру, а данные из структуры уже пишутся в файл.
Отсюда я их вызываю:
void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { if (CopierMode == MASTER) { if(trans.type == TRADE_TRANSACTION_DEAL_ADD) { if(!HistoryDealSelect(trans.deal)) Print(GetLastError()); if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) == DEAL_ENTRY_IN) { Print("Позиция открылась!"); if (CT.getLastOpenPosition()) CT.WriteFile(); } if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) == DEAL_ENTRY_OUT) { Print("Позиция закрылась!"); if (CT.getLastClosedPosition(7)) CT.WriteFile(); } } } }
Уже минимум неделю ломаю голову. Не знаю в чём может быть дело.
а что с остальным кодом? вы всегда только последнюю сделку смотрите? Не самое удачное решение. Вы её откуда вызываете, из ОнТрейда наверное. Две записи потому что две сделки (точно не помню, в случае СЛ или ТП) - одна по размещению ордера закрывающего, вторая - исполнение этого ордера.
Вам надо проверять что сделка DEAL_OUT и тогда уже писать её в файл. При этом надо учесть, что позиция может закрыться не полностью, т.е. ещё бы и объём проверять, но это уже от ваших целей зависит.
а что с остальным кодом? вы всегда только последнюю сделку смотрите? Не самое удачное решение. Вы её откуда вызываете, из ОнТрейда наверное. Две записи потому что две сделки (точно не помню, в случае СЛ или ТП) - одна по размещению ордера закрывающего, вторая - исполнение этого ордера.
Вам надо проверять что сделка DEAL_OUT и тогда уже писать её в файл. При этом надо учесть, что позиция может закрыться не полностью, т.е. ещё бы и объём проверять, но это уже от ваших целей зависит.
Это весь код в рамках данного вопроса. Метод getLastClosedPosition(int days) должен получать id последней закрытой позиции из истории и заталкивать в структуру (её свойства можно увидеть как раз в данном методе). Метод CT.WriteFile() записывает данные из структуры в файл. На этом вся логика.
Вызов происходит из куска кода во втором моём сообщении, в OnTradeTransaction(), отслеживаю события открытия и закрытия сделок (надеюсь не перепутал терминологию) и исходя из ситуаций вызываю нужные методы.
Пишу свой копировальщик сделок между двумя терминалами MT5. Смотрю только последнюю сделку чтобы понять какая позиция была закрыта на Мастере чтобы передать данные для закрытия дублирующей позиции в Слейве.
Вроде исправил. 3 теста прогнал, всё идеально. Завтра утром на свежую голову ещё несколько прогонов тестовых сделаю.
Добавил такую конструкцию из примера в документации:
if (total > 0) { if (total > 1){ ticket = (long)HistoryDealGetTicket((int)total - 1); } else { ticket = (long)HistoryDealGetTicket(0); } }
Вместо этого куска кода:
// уменьшим на единицу для правильного обращения к тикету последней сделки total--; // берём тикет последней сделки long ticket = (long)HistoryDealGetTicket(total);
Вроде исправил. 3 теста прогнал, всё идеально. Завтра утром на свежую голову ещё несколько прогонов тестовых сделаю.
Добавил такую конструкцию из примера в документации:
Вместо этого куска кода:
А если total будет равен 1, разве total-1 не будет равен 0?
if (total > 0) { if (total > 1){ ticket = (long)HistoryDealGetTicket((int)total - 1); } else { ticket = (long)HistoryDealGetTicket(0); } }
Зачем такой заворот кишок?
А если total будет равен 1, разве total-1 не будет равен 0?
Зачем такой заворот кишок?
Я сам ничего не понял. Но считаю аналогично. Вчера вечером подумал, что голова уже не варит. Но благодаря вашему комментарию я понимаю, что был прав)) Однако творится что-то непонятное. Ох уж эта магия MQL5.
Сейчас сделал ещё один прогон - всё пишется зеркально без всяких ошибок.
А вот теперь кажется понял, почему работало криво.
void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { if (CopierMode == MASTER) { if(trans.type == TRADE_TRANSACTION_DEAL_ADD) { if(!HistoryDealSelect(trans.deal)) Print(GetLastError()); if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) == DEAL_ENTRY_IN) { Print("Позиция открылась!"); if (CT.getLastOpenPosition()) CT.WriteFile(); } if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) == DEAL_ENTRY_OUT) { Sleep(1000); Print("Позиция закрылась!"); if (CT.getLastClosedPosition(7)) CT.WriteFile(); } } } }
Разгадка тайны кроется в Sleep(1000);
Т.е. по моим наблюдениям я сделал вывод - закрытие позиции не всегда успевает пройти через все эти "инстанции" организованные разработчиками торговой системы в момент моего обращения за информацией о последней закрытой позиции в историю. И после увеличения (замедления) интервала между срабатыванием действия на закрытие сделки - всё работает как нужно.
Хм, а разве ОнТрейд как раз и не предназначен для контроля списка. ОТТ генерируется при транзакции на сервере, а ОТ генерится при изменении списков, в т.ч. исторических. Ну дело ваше, кому какой костыль милее, здоровых мало осталось)
Хм, а разве ОнТрейд как раз и не предназначен для контроля списка. ОТТ генерируется при транзакции на сервере, а ОТ генерится при изменении списков, в т.ч. исторических. Ну дело ваше, кому какой костыль милее, здоровых мало осталось)
Событие Trade генерируется при завершении торговой операции на торговом сервере.
При появлении сделки в истории, породившего ее ордера там может еще не быть.
- www.mql5.com
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Доброго времени суток!
Столкнулся с багом в своей программе. Грешу на функцию получения ID последней закрытой позиции. Прошу помощи, что не так?
По сути мне необходим только ID, остальное второстепенно.
Если кому нужна информация о баге - получаю дублированные данные в файл (2 одинаковые записи на закрытие вместо одной), либо вообще несовпадающие ни с одной ранее открытой позицией которая была записана в файл.