Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Я же описывал эту ситуацию... :)
Она будет возникать часто, если НЕ использовать OrderSendAsync()...
OnTradeTransaction() позволяет отслеживать состояния ордера ОЧЕНЬ быстро.
(у меня не возникает таких проблем)
Да, буду переводить на асинхронный режим.
Не забудьте, событие OnTradeTransaction - НЕ ГАРАНТИРОВАНО!
Моя статья почему-то не выходит :(
В примерах РЫНОК ФОРЕКС
Отслеживание ордера, после команды OrderSendAsync
Михаил | 23 апреля, 2015
В статье рассказывается принцип отслеживания ордера после команды OrderSendAsync, если нет события TradeTransaction.
Введение
Сокращение времени выставления, удаления и модификации ордера является краеугольным камнем многих стратегий торговли.
В терминале МТ5 команда OrderSendAsync позволяет существенно сократить время исполнения приказов.
Она (команда) OrderSendAsync, обрабатывается функцией OnTradeTransaction, но к сожалению,
событие TradeTransaction не гарантированно.
Идею отслеживания ордера после команды OrderSendAsync (при отсутствии событияTradeTransaction),
с использование уникальных номеров (magic number), предложил комрад Yurich, за что ему большое спасибо.
Проблему отслеживания ордеров рассмотрим на примере покупки-продажи.
Обычный алгоритм
//+------------------------------------------------------------------+ //| Demo_1.mq5 | //| Copyright 2015, Mikalas | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Mikalas" #property link "http://www.mql5.com" #property version "1.00" // #define BUY true #define SELL false // bool open_close; ulong magic_number; ulong order_ticket; uint req_id; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Установка переменных magic_number = 1010000; open_close = true; //--- if( !ObjectCreate( 0, "buy_sell", OBJ_BUTTON, 0, 0, 0 ) ) { MessageBox( "Кнопка 'Buy-Sell' не создана!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); } else { ObjectSetInteger( 0, "buy_sell", OBJPROP_CORNER, CORNER_RIGHT_LOWER ); //LEFT ObjectSetInteger( 0, "buy_sell", OBJPROP_XDISTANCE, 40 ); //0 ObjectSetInteger( 0, "buy_sell", OBJPROP_YDISTANCE, 18 ); ObjectSetInteger( 0, "buy_sell", OBJPROP_XSIZE, 40 ); ObjectSetInteger( 0, "buy_sell", OBJPROP_YSIZE, 18 ); //--- if ( open_close ) { ObjectSetInteger( 0, "buy_sell", OBJPROP_BGCOLOR, clrWhite ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Buy" ); } else { ObjectSetInteger( 0, "buy_sell", OBJPROP_BGCOLOR, clrWhite ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Sell" ); } } ChartRedraw(); return( INIT_SUCCEEDED ); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit( const int reason ) { //--- удаление таймера ObjectDelete( 0, "buy_sell" ); } //+------------------------------------------------------------------+ //| Expert set order function | //+------------------------------------------------------------------+ void SetOrder( const string aSymbol, const double price, const double volume, const bool buy_sell ) { MqlTradeRequest request = {0}; MqlTradeResult result = {0}; req_id = 0; order_ticket = 0; //--- Fill structure request.magic = magic_number; request.symbol = aSymbol; request.volume = volume; request.deviation = 50; request.type_filling = ORDER_FILLING_IOC; request.type_time = ORDER_TIME_DAY; request.price = price; request.action = TRADE_ACTION_DEAL; //--- if ( buy_sell ) { request.type = ORDER_TYPE_BUY; } else { request.type = ORDER_TYPE_SELL; } //--- Send order if ( OrderSendAsync( request, result ) ) { if ( result.retcode == TRADE_RETCODE_PLACED ) { req_id = result.request_id; } } else { Print( "Установка ордера не выполнена! ", aSymbol ); } } //+------------------------------------------------------------------+ //| Expert Chart event function | //+------------------------------------------------------------------+ void OnChartEvent( const int id, const long& lparam, const double& dparam, const string& sparam ) { MqlTick cur_tick; if ( SymbolInfoTick( _Symbol, cur_tick ) ) { long b_state; if ( id == CHARTEVENT_OBJECT_CLICK ) { if ( sparam == "buy_sell" ) { if ( ObjectGetInteger( 0, "buy_sell", OBJPROP_STATE, 0, b_state ) ) { if ( b_state == 1 ) { if ( open_close ) { SetOrder( _Symbol, cur_tick.ask, 1, open_close ); open_close = false; ObjectSetInteger( 0, "buy_sell", OBJPROP_STATE, false ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Sell" ); } else { SetOrder( _Symbol, cur_tick.bid, 1, open_close ); open_close = true; ObjectSetInteger( 0, "buy_sell", OBJPROP_STATE, false ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Buy" ); } } } } ChartRedraw(); } } } //+------------------------------------------------------------------+ //| Expert On Trade Transaction 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 ( ( req_id != 0 ) && ( result.request_id == req_id ) ) { if ( result.retcode == TRADE_RETCODE_DONE ) { order_ticket = result.order; } else { Print( "Не получен билет ордера!" ); } req_id = 0; } } break; case TRADE_TRANSACTION_HISTORY_ADD: if ( order_ticket > 0 ) { switch( trans.order_state ) { case ORDER_STATE_FILLED: Print( "Сделка совершена, Билет = ", order_ticket ); order_ticket = 0; break; case ORDER_STATE_REJECTED: case ORDER_STATE_CANCELED: case ORDER_STATE_EXPIRED: Print( "Сделка не совершена, Билет = ", order_ticket ); order_ticket = 0; break; } } break; } } //+------------------------------------------------------------------+ //| The END | //+------------------------------------------------------------------+Если ордер отправлен (SetOrder()), то мы получаем номер отправки запроса (request_id), далее,
если ордер выставлен в рынок, то мы получаем его билет (OnTradeTransaction --> TRADE_TRANSACTION_REQUEST --> order_ticket = result.order).
Зная билет ордера, мы можем отследить что с ним произошло.
Но если не произошло событие(события) TradeTransaction, узнать что
произошло с ордером невозможно, так как мы можем не получить билет ордера или
событий с ордером происходящие (отклонение биржей или брокером, удаление, экспирация или модификация).
Рассмотрим алгоритм, позволяющий отследить состояния ордера, при отсутствии событий TradeTransaction.
Алгоритм, при отсутствии событий ТradeTransaction
//+------------------------------------------------------------------+ //| Demo_2.mq5 | //| Copyright 2015, Mikalas | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Mikalas" #property link "http://www.mql5.com" #property version "1.00" // #define BUY true #define SELL false // input uint SecTimer = 1000; //Период проверки ответа сервера (мсек) // int timer_time; bool open_close; datetime mem_start_time; ulong order_ticket; uint mem_tick; ulong magic_number; ulong magic_storage; ulong mem_magic; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Установка переменных magic_number = 1010000; magic_storage = magic_number - 1; timer_time = 500; open_close = true; //--- if( !ObjectCreate( 0, "buy_sell", OBJ_BUTTON, 0, 0, 0 ) ) { MessageBox( "Кнопка 'Buy-Sell' не создана!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); } else { ObjectSetInteger( 0, "buy_sell", OBJPROP_CORNER, CORNER_RIGHT_LOWER ); //LEFT ObjectSetInteger( 0, "buy_sell", OBJPROP_XDISTANCE, 40 ); //0 ObjectSetInteger( 0, "buy_sell", OBJPROP_YDISTANCE, 18 ); ObjectSetInteger( 0, "buy_sell", OBJPROP_XSIZE, 40 ); ObjectSetInteger( 0, "buy_sell", OBJPROP_YSIZE, 18 ); //--- if ( open_close ) { ObjectSetInteger( 0, "buy_sell", OBJPROP_BGCOLOR, clrWhite ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Buy" ); } else { ObjectSetInteger( 0, "buy_sell", OBJPROP_BGCOLOR, clrWhite ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Sell" ); } } //--- Установка таймера if ( !EventSetMillisecondTimer( timer_time ) ) { MessageBox( "Таймер не установлен!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); } ChartRedraw(); return( INIT_SUCCEEDED ); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit( const int reason ) { //--- удаление таймера EventKillTimer(); ObjectDelete( 0, "buy_sell" ); } //+------------------------------------------------------------------+ //| Expert timer function | //+------------------------------------------------------------------+ void OnTimer() { CheckOrders(); } //+------------------------------------------------------------------+ //| Expert set order function | //+------------------------------------------------------------------+ void SetOrder( const string aSymbol, const double price, const double volume, const bool buy_sell ) { MqlTradeRequest request = {0}; MqlTradeResult result = {0}; mem_start_time = TimeTradeServer(); order_ticket = 0; mem_tick = GetTickCount(); mem_magic = magic_storage + 1; if ( mem_magic >= ( magic_number + 9999 ) ) mem_magic = magic_number; //--- Fill structure request.magic = mem_magic; request.symbol = aSymbol; request.volume = volume; request.deviation = 50; request.type_filling = ORDER_FILLING_IOC; request.type_time = ORDER_TIME_DAY; request.price = price; request.action = TRADE_ACTION_DEAL; //--- if ( buy_sell ) { request.type = ORDER_TYPE_BUY; } else { request.type = ORDER_TYPE_SELL; } //--- Send order if ( OrderSendAsync( request, result ) ) { if ( result.retcode == TRADE_RETCODE_PLACED ) { magic_storage = mem_magic; } } else { mem_magic = 0; mem_start_time = 0; mem_tick = 0; Print( "Установка ордера не выполнена! ", aSymbol ); } } //+------------------------------------------------------------------+ //| Expert Chart event function | //+------------------------------------------------------------------+ void OnChartEvent( const int id, const long& lparam, const double& dparam, const string& sparam ) { MqlTick cur_tick; if ( SymbolInfoTick( _Symbol, cur_tick ) ) { long b_state; if ( id == CHARTEVENT_OBJECT_CLICK ) { if ( sparam == "buy_sell" ) { if ( ObjectGetInteger( 0, "buy_sell", OBJPROP_STATE, 0, b_state ) ) { if ( b_state == 1 ) { if ( open_close ) { SetOrder( _Symbol, cur_tick.ask, 1, open_close ); open_close = false; ObjectSetInteger( 0, "buy_sell", OBJPROP_STATE, false ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Sell" ); } else { SetOrder( _Symbol, cur_tick.bid, 1, open_close ); open_close = true; ObjectSetInteger( 0, "buy_sell", OBJPROP_STATE, false ); ObjectSetString( 0, "buy_sell", OBJPROP_TEXT, "Buy" ); } } } } ChartRedraw(); } } } //+------------------------------------------------------------------+ // 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 Check main order function | //+------------------------------------------------------------------+ ulong GetOrderTicket( const ulong m_magic, const datetime mem_time, const datetime cur_time ) { ulong a_ticket = FindOrder( m_magic ); if ( a_ticket > 0 ) { return( a_ticket ); } else { a_ticket = FindHistoryOrder( m_magic, mem_time, cur_time ); if ( a_ticket > 0 ) { return( a_ticket ); } } return( 0 ); } //+------------------------------------------------------------------+ // Expert Check main order function | //+------------------------------------------------------------------+ bool CheckOrdersTimer( 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 Check Orders function | //+------------------------------------------------------------------+ void CheckOrders() { if ( ( mem_tick > 0 ) && CheckOrdersTimer( mem_tick, SecTimer ) ) { mem_tick = 0; //--- if ( order_ticket > 0 ) { mem_magic = 0; //--- if ( ( order_ticket > 0 ) && ( HistoryOrderSelect( order_ticket ) ) ) { ENUM_ORDER_STATE order_state = ENUM_ORDER_STATE( HistoryOrderGetInteger( order_ticket, ORDER_STATE ) ); //--- if ( ( order_state == ORDER_STATE_FILLED ) || ( order_state == ORDER_STATE_PARTIAL ) ) { Print( "Сделка совершена! Билет = ", order_ticket ); } else { Print( "Сделка не совершена! Билет = ", order_ticket ); } } //--- mem_start_time = 0; order_ticket = 0; } else { if ( mem_magic > 0 ) { order_ticket = GetOrderTicket( mem_magic, mem_start_time - 2000, TimeTradeServer() + 5000 ); //--- if ( order_ticket > 0 ) { mem_tick = GetTickCount(); } else { mem_magic = 0; mem_start_time = 0; Print( "CheckOrders: Не получен билет ордера!" ); } } else { mem_start_time = 0; Print( "CheckOrders: Не возможно получить билет ордера, mem_magic = 0!" ); } } } } //+------------------------------------------------------------------+ //| The END | //+------------------------------------------------------------------+Дополнительные переменные, необходимые для отслеживания ордера:
SecTimer - период времени ожидания события TradeTransaction
magic_number - начало диапазона магических чисел, задаваемый для каждого символа.
Т.е, например, для EURUSD - c 1010000 по 1019999,
для GBPUSD - c 102000 по1029999 и т.д
10000 уникальных номеров для одного символа вполне достаточно,
чтобы эти уникальные номера "разнести" во времени.
При достижении 10000 происходит новый цикл:
Одинаковые уникальные номера будут, но они будут "разнесены" во времени, для чего
и служит переменная - mem_time.
mem_magic - уникальное число КАЖДОГО ордера.
magic_storage - переменная для хранения текущего уникального числа.
mem_tick - начало отсчёта времени для сравнения с периодом ожидания события TradeTransaction.
Для цикла проверки времени создаётся миллисекундный таймер:
{ MessageBox( "Таймер не установлен!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); } return( INIT_SUCCEEDED ); }Событие OnTimer() вызывает функцию CheckOrders();
И если время ожидания события TradeTransaction превышено,
{ ....... }то происходит выполнение функции.
Если мы не получили билет ордера в OnTradeTransaction, то
mem_magic > 0 и мы пытаемся получить билет вызывая функцию:
GetOrderTicket( mem_magic, mem_time - 2000, TimeTradeServer() + 5000);Если же ордер был получен ( order_ticket > 0 ) но не пришло событие
OnTradeTransaction, то мы можем отследить его состояние, просмотрев историю.
Заключение
В статье рассмотрены общие принципы отслеживания ордера (с примерами), после команды OrderSendAsync.
При проектировании советника, с использованием этого принципа, необходимо рассмотреть
более подробно все аспекты действия с ордером.
Это означает, что приведённый выше код, может и не дать
желаемого результата, если его просто скопировать в свой советник.
Данный метод (не примеры кода для ФОРЕКС, изложенные выше) отслеживания применён мною в советниках для ФОРТС,
где с успехом работает более 9 месяцев.
С уважением, и успехов в программировании советников!
а почему не выходит? Что говорят в MQ? Давно послали на проверку?
Говорят, что по объёму "не дотягивет".
Понимаю... Mikalas, так у Вас такой опыт тестирования и проверок, что, имхо, можно книжку написать :-)
Не ленитесь, воды долейте, в смысле добавьте что-то ещё, например сравнительный анализ Forex'a и ФОРТСа в контексте заявленной темы...
Понимаю... Mikalas, так у Вас такой опыт тестирования и проверок, что, имхо, можно книжку написать :-)
Не ленитесь, воды долейте, в смысле добавьте что-то ещё, например сравнительный анализ Forex'a и ФОРТСа в контексте заявленной темы...
Нет, спасибо, что-то не хочется....
У меня есть более важные дела.
Нет, спасибо, что-то не хочется....
Ну хозяин - барин... а вообще, первая статья (вроде Вы не писали) даётся непросто... сужу по собственному опыту... помню, как меня модератор носом ткнёт то туда, то сюда...
Тут нужно набраться терпения и дойти до конца ;-)
Продолжение о модификации ордера....
Ваш код:
Для модификации нужно делать так (думаю, что и при установке ордера, Вы не правильно указываете тип экспирации):