也谢谢你的帮助。但是,即使在创建异步交易专家 时有可能出现交易损失,不是由我,我们可以谈论什么样的验证?
而总的来说,我对这个答案感到满意。我没有足够的知识来详细讨论这个问题。
再次感谢。
也谢谢你。但是即使在创建,不是我的异步交易专家的时候,交易损失是可能的,我们可以谈什么样的验证?
总的来说,答案让我满意。而且我没有足够的知识来更详细地讨论这个话题。
再次感谢。
我写了一篇关于这个问题的文章。
它只是告诉如何不“丢失” OrderSendAsync命令下的订单
现在正在检查,但如果没有出来,那么这里是这篇文章的一个例子(远期市场 FORTS):
//+------------------------------------------------------------------+ //| Demo_1.mq5 | //| Copyright 2015, Mikalas | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Mikalas" #property link "https://www.mql5.com" #property version "1.00" input uint TimerPeriod = 1000 ; //Время ожидания проверки ордера (1 сек.) ulong order_ticket; uint request_id; // ulong magic_number = 1010000 ; //по 10000 на каждый символ ulong magic_storage; ulong mem_magic; datetime mem_time; uint mem_tick; ulong deal_volume; //Счётчик заливки ордера // //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit () { deal_volume = 0 ; //--- Установка таймера if ( ! EventSetMillisecondTimer ( 500 ) ) //0.5 cек. { MessageBox ( "Таймер не установлен!" , "Ошибка" , MB_OK | MB_ICONHAND ); return ( INIT_FAILED ); } return ( INIT_SUCCEEDED ); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit ( const int reason ) { //--- удаление таймера EventKillTimer (); } //+------------------------------------------------------------------+ //| Expert Get retcode function | //+------------------------------------------------------------------+ string GetRetCode( const uint code ) { string retcode; //--- switch ( code ) { case 10004 : retcode = "Реквота" ; break ; case 10006 : retcode = "Запрос отвергнут" ; break ; case 10007 : retcode = "Запрос отменен трейдером" ; break ; case 10008 : retcode = "Ордер размещен" ; break ; case 10009 : retcode = "Заявка выполнена" ; break ; case 10010 : retcode = "Заявка выполнена частично" ; break ; case 10011 : retcode = "Ошибка обработки запроса" ; break ; case 10012 : retcode = "Запрос отменен по истечению времени" ; break ; case 10013 : retcode = "Неправильный запрос" ; break ; case 10014 : retcode = "Неправильный объем в запросе" ; break ; case 10015 : retcode = "Неправильная цена в запросе" ; break ; case 10016 : retcode = "Неправильные стопы в запросе" ; break ; case 10017 : retcode = "Торговля запрещена" ; break ; case 10018 : retcode = "Рынок закрыт" ; break ; case 10019 : retcode = "Нет достаточных денежных средств для выполнения запроса" ; break ; case 10020 : retcode = "Цены изменились" ; break ; case 10021 : retcode = "Отсутствуют котировки для обработки запроса" ; break ; case 10022 : retcode = "Неверная дата истечения ордера в запросе" ; break ; case 10023 : retcode = "Состояние ордера изменилось" ; break ; case 10024 : retcode = "Слишком частые запросы" ; break ; case 10025 : retcode = "В запросе нет изменений" ; break ; case 10026 : retcode = "Автотрейдинг запрещен сервером" ; break ; case 10027 : retcode = "Автотрейдинг запрещен клиентским терминалом" ; break ; case 10028 : retcode = "Запрос заблокирован для обработки" ; break ; case 10029 : retcode = "Ордер или позиция заморожены" ; break ; case 10030 : retcode = "Указан неподдерживаемый тип исполнения ордера по остатку" ; break ; case 10031 : retcode = "Нет соединения с торговым сервером" ; break ; case 10032 : retcode = "Операция разрешена только для реальных счетов" ; break ; case 10033 : retcode = "Достигнут лимит на количество отложенных ордеров" ; break ; case 10034 : retcode = "Достигнут лимит на объем ордеров и позиций для данного символа" ; break ; case 10035 : retcode = "Неверный или запрещённый тип ордера" ; break ; case 10036 : retcode = "Позиция с указанным POSITION_IDENTIFIER уже закрыта" ; break ; default : retcode = "Нет кода возврата." ; break ; } return ( retcode ); } //+------------------------------------------------------------------+ //| Expert place order function | //+------------------------------------------------------------------+ bool PlaceOrder( const string a_symbol, const double price, const double volume, const bool buy_sell ) { MqlTradeRequest request = { 0 }; MqlTradeResult result = { 0 }; //--- order_ticket = 0 ; request_id = 0 ; mem_time = TimeTradeServer (); //Время установки ордера (для для сокращения поиска в истории) mem_tick = GetTickCount (); //Начало отсчёта времени (для проверки, если не сработала функция OnTradeTransaction) mem_magic = magic_storage + 1 ; //Уникальный номер (magic) ордера if ( mem_magic >= ( magic_number + 9999 ) ) mem_magic = magic_number; //Переполнение, начинаем сначала //--- Fill structure request.action = TRADE_ACTION_PENDING ; request.magic = mem_magic; request.symbol = a_symbol; request.volume = volume; request.price = price; if ( buy_sell ) { request.type = ORDER_TYPE_BUY_LIMIT ; } else { request.type = ORDER_TYPE_SELL_LIMIT ; } request.comment = "Отложенный ордер..." ; request.type_filling = ORDER_FILLING_RETURN ; request.type_time = ORDER_TIME_DAY ; //--- Send order if ( OrderSendAsync ( request, result ) ) { if ( result.retcode == TRADE_RETCODE_PLACED ) { request_id = result.request_id; magic_storage = mem_magic; return ( true ); } else { mem_magic = 0 ; mem_time = 0 ; mem_tick = 0 ; Print ( "Ордер не отправлен! " , a_symbol, " Код возврата = " , GetRetCode( result.retcode ) ); return ( false ); } } else { mem_magic = 0 ; mem_time = 0 ; mem_tick = 0 ; Print ( "Ордер не отправлен! " , a_symbol, " Код возврата = " , GetRetCode( result.retcode ) ); return ( false ); } } //+------------------------------------------------------------------+ //| Expert place order function | //+------------------------------------------------------------------+ void OnTick () { MqlTick a_tick; if ( SymbolInfoTick ( _Symbol , a_tick ) ) { PlaceOrder( _Symbol , a_tick.ask, 1 , false ); //Устанавливаем ордер } } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction ( const MqlTradeTransaction & trans, const MqlTradeRequest & request, const MqlTradeResult & result) { switch ( trans.type ) { case TRADE_TRANSACTION_REQUEST : if ( trans.order_state == ORDER_STATE_STARTED ) { if ( ( request_id != 0 ) && ( result.request_id == request_id ) ) { if ( result.retcode == TRADE_RETCODE_PLACED ) { order_ticket = result.order; //Получаем билет ордера mem_tick = GetTickCount (); //Начало отсчёта времени (для проверки, если не сработает функция OnTradeTransaction) } else { mem_tick = 0 ; Print ( "OnTradeTransaction: Не получен билет ордера. Запрос = " , request_id ); } request_id = 0 ; mem_magic = 0 ; mem_time = 0 ; } } break ; case TRADE_TRANSACTION_DEAL_ADD : if ( trans.order_state == ORDER_STATE_STARTED ) { if ( ( order_ticket != 0 ) && ( trans.order == order_ticket ) ) { if ( ! OrderSelect ( order_ticket ) ) order_ticket = 0 ; //Обнуляем билет, так как ордер залился полностью. Print ( "OnTradeTransaction: Сделка совершена, билет = " , trans.order ); } } break ; case TRADE_TRANSACTION_HISTORY_ADD : if ( (order_ticket != 0 ) && ( trans.order == order_ticket ) ) { order_ticket = 0 ; switch ( trans.order_state ) { case ORDER_STATE_REJECTED : Print ( "OnTradeTransaction: Ордер отклонён." ); break ; case ORDER_STATE_CANCELED : Print ( "OnTradeTransaction: Ордер удалён." ); break ; case ORDER_STATE_EXPIRED : Print ( "OnTradeTransaction: Срок действия ордера окончен." ); break ; } } break ; case TRADE_TRANSACTION_ORDER_UPDATE : if ( trans.order_state == ORDER_STATE_REQUEST_MODIFY ) { if ( ( order_ticket != 0 ) && ( trans.order == order_ticket ) ) { Print ( "OnTradeTransaction: Ордер в состоянии модифицикации." ); mem_tick = GetTickCount (); } } break ; } } //+------------------------------------------------------------------+ // Expert find histiry order function | //+------------------------------------------------------------------+ ulong FindHistoryOrder( const ulong a_magic, const datetime a_time, const datetime b_time ) { if ( HistorySelect ( a_time, b_time ) ) { for ( int i = HistoryOrdersTotal () - 1 ; i >= 0 ; i-- ) { ulong cur_ticket = HistoryOrderGetTicket ( i ); if ( ulong ( HistoryOrderGetInteger ( cur_ticket, ORDER_MAGIC ) ) == a_magic ) return ( cur_ticket ); } } return ( 0 ) ; } //+------------------------------------------------------------------+ // Expert find order function | //+------------------------------------------------------------------+ ulong FindOrder( const ulong a_magic ) { for ( int i = OrdersTotal () - 1 ; i >= 0 ; i-- ) { ulong cur_ticket = OrderGetTicket ( i ); if ( ulong ( OrderGetInteger ( ORDER_MAGIC ) ) == a_magic ) return ( cur_ticket ); } return ( 0 ); } //+------------------------------------------------------------------+ //| Expert Get order tiket function | //+------------------------------------------------------------------+ ulong GetOrderTicket( const ulong m_magic, const datetime m_time, const datetime cur_time ) { ulong a_ticket = FindOrder( m_magic ); //Ищем действующий ордер if ( a_ticket > 0 ) { return ( a_ticket ); } else { a_ticket = FindHistoryOrder( m_magic, m_time, cur_time ); //Ищем ордер в истории if ( a_ticket > 0 ) { return ( a_ticket ); } } return ( 0 ); } //+------------------------------------------------------------------+ //| Expert Check time function | //+------------------------------------------------------------------+ bool CheckTime( const uint start_value, const uint per_value ) { uint end_value = GetTickCount (); if ( end_value < start_value ) { if ( ( start_value - end_value ) >= per_value ) return ( true ); } else { if ( ( end_value - start_value ) >= per_value ) return ( true ); } return ( false ); } //+------------------------------------------------------------------+ // Expert Get History Deals function | //+------------------------------------------------------------------+ uint GetHistoryDeals( const ulong ticket ) { int deals_total = HistoryDealsTotal (); uint ticket_deals = 0 ; for ( int i = 0 ; i < deals_total; i++ ) { ulong deal_ticket = HistoryDealGetTicket ( i ); ulong ord_ticket = ulong ( HistoryDealGetInteger ( deal_ticket, DEAL_ORDER ) ); if ( ( ord_ticket > 0 ) && ( ord_ticket == ticket ) ) ticket_deals++; } if ( ticket_deals > 0 ) return ( ticket_deals ); return ( 0 ); } //+------------------------------------------------------------------+ //| Expert Check order function | //+------------------------------------------------------------------+ void CheckOrder() { if ( ( mem_tick > 0 ) && CheckTime( mem_tick, TimerPeriod ) ) //Проверка времени ожидания действия над ордером (установка, модификация или удадение) { if ( mem_magic > 0 ) //Нет билета, получаем билет { order_ticket = GetOrderTicket( mem_magic, mem_time, TimeTradeServer () ); if ( order_ticket > 0 ) { mem_tick = GetTickCount (); //Начало отсчёта времени, если в будующем вновь не сработает функция OnTradeTransaction } else { mem_tick = 0 ; Print ( "Timeout: Билет ордера не найден!" ); } mem_magic = 0 ; mem_time = 0 ; } else { if ( order_ticket > 0 ) //Есть билет, смотрим что произошло с ордером { if ( OrderSelect ( order_ticket ) ) //Ордер рабочий { double init_volume = OrderGetDouble ( ORDER_VOLUME_INITIAL ); double cur_volume = OrderGetDouble ( ORDER_VOLUME_CURRENT ); if ( init_volume != cur_volume ) { ulong d_volume = ( ulong ( init_volume - cur_volume ) - deal_volume ); deal_volume = deal_volume + d_volume; if ( d_volume > 0 ) { Print ( "Timeout: Сделка совершена, билет = " , order_ticket, " Объём = " , d_volume ); } } mem_tick = GetTickCount (); } else //Ордер исполнился, удален или экпирировался { if ( HistoryOrderSelect ( order_ticket ) ) { datetime ord_time = datetime ( HistoryOrderGetInteger ( order_ticket, ORDER_TIME_SETUP ) ); if ( HistorySelect ( ord_time, TimeTradeServer () ) ) { uint deals = GetHistoryDeals( order_ticket ); if ( deals > 0 ) { Print ( "Timeout: Сделка совершена, билет = " , order_ticket ); } } } else { Print ( "Timeout: Ордер " , order_ticket, " не найден в истории!" ); } deal_volume = 0 ; order_ticket = 0 ; mem_tick = 0 ; } } else { deal_volume = 0 ; mem_tick = 0 ; Print ( "Timeout: Нет билета ордера!" ); } } } } //+------------------------------------------------------------------+ //| Expert timer function | //+------------------------------------------------------------------+ void OnTimer () { CheckOrder(); } //+------------------------------------------------------------------+
我曾就这个问题写过一篇文章。
它确切地告诉我们如何不 "丢失 "由OrderSendAssync命令下的订单
现在正在测试,但如果失败了,这里有本文的一个例子(FORTS期货市场)。
仿佛我们都明白了,并为之拍手称快。对不起,但你的代码是一团糟。
有人承诺这很容易吗?
对不起,瓦西里,等文章出来再说吧....
P/S 如果文章没有出来,我就在这里写解释,举例说明。
P/S 如果文章没有出来,我将在这里贴出一个解释的例子。
为什么不应该出来呢?这些材料很有意思。
我认为你,Mikalas,在与MQ的对话中,在弄清关于门票和订单ID的很多事情方面做了很多努力。所以请等待吧。
我曾就这个问题写过一篇文章。
它确切地告诉我们如何不 "丢失 "由OrderSendAssync命令下的订单
现在正在测试,但如果它没有出来,这里有一篇文章(FORTS期货市场)的例子给你。
如果你不介意我问的话。为什么你专注于使用OrderSendAssync()函数下订单?如果我们使用OrderSend()函数下单,交易不会丢失吗?在这种情况下,有更多的保证?
在我没有经验的情况下,我想把这种或那种情况下的决策插入OnTradeTransactio()中。但到目前为止,它的效果并不理想。而在看到关于可能的交易损失的报道后,我向你要求澄清。
一般来说,要为FORTS市场写作,必须了解这个市场。目前,它不适合我,也许我不需要它。我决定重写我用mql4编写的EA,以研究mql5。我现在正在研究它。
如果你不介意的话,我有个问题。为什么你专注于用OrderSendAssync()下订单?如果你使用OrderSend()函数下单,交易不会丢失吗?在这种情况下,有更多的保证?
在我没有经验的情况下,我想把这种或那种情况下的决策插入OnTradeTransactio()中。但到目前为止,它的效果并不理想。而在看到关于可能的交易损失的报道后,我向你要求澄清。
一般来说,要为外汇市场写作,你需要了解这个市场。这还不适合我,也许我不需要它。我决定重写我用mql4编写的EA,以研究mql5。我现在正在研究它。
1.OrderSendAsync要快得多(它不需要等待服务器的响应)。
OrderSend保证从服务器获得响应。
2.这个例子在外汇市场上将完美地发挥作用
将result.retcode == TRADE_RETCODE_PLACED改为result.retcode == TRADE_RETCODE_DONE。
1.OrderSendAsync的速度更快(它不需要等待服务器的响应)。
2.这个例子在外汇市场上也能完美运作
将result.retcode == TRADE_RETCODE_PLACED改为result.retcode == TRADE_RETCODE_DONE。
也就是说,如果不应用异步,那么就不需要OnTradeTransaction 处理程序,因为猫头鹰将等待服务器的响应?
但到目前为止,我还没有找到确定止损单是否被激活的最佳方法。例如,我设置了市场买入0.1和卖出止损0.3,当它激活0.3时,它将保持0.2,在什么时候我应该跟随它...因此,事实证明,我们必须在每一次打勾时遵循两个命令。而我想解救猫头鹰,只在交易发生时进行监控。我想要的甚至不是控制,而是检查发生了什么并决定做什么。但我想情况并非如此......。也许最好是回到久经考验的老方法中去......。
所以,如果我们不使用异步,就不需要OnTradeTransaction处理程序,因为猫头鹰会等待服务器的响应?
但到目前为止,我还没有找到检测止损单是否已被激活的最佳方法。例如,我设置了市场买入0.1和卖出止损0.3,当它激活0.3时,它将保持0.2,在什么时候我应该跟随它...因此,事实证明,我们必须在每一次打勾时遵循两个命令。而我想解救猫头鹰,只在交易发生时进行监控。我想要的甚至不是控制,而是检查发生了什么并决定做什么。但我想情况并非如此......。也许最好是回到旧的、经过测试的方法......。
是的,你可以避免使用OnTradeTransaction,但在这种情况下,你将不得不查看历史记录,这将降低EA的整体性能。
每个开发者都有选择的权利!
根据帮助。
也就是说,它允许你在OnTradeTransaction函数中检查订单是否被正确执行。或者我有什么误解吗?
但这里有一个注意事项。
这些交易到达终端的顺序是不能保证的,所以我们不能把我们的交易算法建立在等待 一些交易在其他交易之后到达。此外,交易在从服务器传递到终端的过程中可能会丢失。
好吧,不保证一致性是麻烦的一半。但是,交易可能会丢失,因此我们不能使用OnTradeTransaction函数进行检查,怎么办?
那么问题来了:我们需要这个事件处理函数 做什么?它是绝对无用的终端附件吗?或者我又误解了什么?