Bunun için de teşekkürler. Ancak, benim tarafımdan değil, asenkron ticaret uzmanları yaratırken bile, işlem kayıpları mümkün olsa bile, ne tür bir doğrulamadan bahsedebiliriz?
Genel olarak, cevap beni tatmin ediyor. Ve bu konuyu daha detaylı tartışmak için yeterli bilgiye sahip değilim.
Ve tekrar teşekkürler.
Bunun için de teşekkürler. Ancak, benim tarafımdan değil, asenkron ticaret uzmanları yaratırken bile, işlem kayıpları mümkün olsa bile, ne tür bir doğrulamadan bahsedebiliriz?
Genel olarak, cevap beni tatmin ediyor. Ve bu konuyu daha detaylı tartışmak için yeterli bilgiye sahip değilim.
Ve tekrar teşekkürler.
Bu konuyla ilgili bir makale yazdım.
Sadece OrderSendAsync komutu tarafından verilen emrin nasıl "kaybedilmeyeceğini" söyler.
Şimdi kontrol ediliyor, ancak çıkmazsa, işte bu makaleden bir örnek (forward market 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(); } //+------------------------------------------------------------------+
Bu konuyla ilgili bir makale yazdım.
Sadece OrderSendAssync komutu tarafından verilen emrin nasıl "kaybedilmeyeceğini" söyler.
Şimdi kontrol ediliyor, ancak çıkmazsa, işte bu makaleden bir örnek (forward market FORTS):
Sanki her şeyi anladık ve sevinç için ellerimizi çırptık. Üzgünüm ama şeytan senin kodunda bacağını kıracak.
Ve birisi bunun kolay olacağına söz verdi mi?
Üzgünüm Vasily, makalenin yayınlanmasını bekle ....
P/S Yazı çıkmazsa mesela buraya açıklamaları yazacağım.
P/S Yazı çıkmazsa mesela buraya açıklamaları yazacağım.
Neden dışarı çıkmasın? Malzeme ilginç.
Bence sen, Mikalas, bir zamanlar MQ ile diyalogda biletler ve sipariş kimliği üzerindeki birçok noktayı açıklığa kavuşturmak için çok çaba sarfettiniz. O halde bekleyelim.
Bu konuyla ilgili bir makale yazdım.
Sadece OrderSendAssync komutu tarafından verilen emrin nasıl "kaybedilmeyeceğini" söyler.
Şimdi kontrol ediliyor, ancak çıkmazsa, işte bu makaleden bir örnek (forward market FORTS):
Bir soru sorun olmazsa. Neden OrderSendAssync() işleviyle sipariş vermeye odaklanıyorsunuz? OrderSend() işleviyle bir sipariş vermediğiniz sürece, işlem kaybolmayacak mı? Bu durumda, daha fazla garanti?
Tecrübesizliğimden dolayı, şu veya bu durumda bir kararı OnTradeTransactio()'ya eklemek istedim. Ancak şu ana kadar işler pek iyi gitmedi. Ve olası işlem kaybını okuduktan sonra, açıklama için size döndü.
Genel olarak FORTS piyasası için yazabilmek için bu piyasayı anlamanız gerekir. Bu benim için olmasa da ve belki de buna ihtiyacım yok. Mql5'i incelemek için mql4'te yazılmış baykuşları yeniden yazmaya karar verdim. Ben ders çalışırken...
Bir soru sorun olmazsa. Neden OrderSendAssync() işleviyle sipariş vermeye odaklanıyorsunuz? OrderSend() fonksiyonu ile sipariş verildiğinde işlem kaybolmuyor mu? Bu durumda, daha fazla garanti?
Tecrübesizliğimden dolayı, şu veya bu durumda bir kararı OnTradeTransactio()'ya eklemek istedim. Ancak şu ana kadar işler pek iyi gitmedi. Ve olası işlem kaybını okuduktan sonra, açıklama için size döndü.
Genel olarak FORTS piyasası için yazabilmek için bu piyasayı anlamanız gerekir. Bu benim için olmasa da ve belki de buna ihtiyacım yok. mql5'i incelemek için mql4'te yazılmış baykuşları yeniden yazmaya karar verdim. Ben ders çalışırken...
1. OrderSendAsync çok daha hızlıdır (sunucudan yanıt beklemez)
OrderSend'in sunucudan yanıt alması garanti edilir.
2. Örnek FOREX'te de harika çalışacak
sonuç.retcode == TRADE_RETCODE_PLACED'i sonuç.retcode olarak değiştirme == TRADE_RETCODE_DONE
1. OrderSendAsync çok daha hızlıdır (sunucudan yanıt beklemez)
2. Örnek FOREX'te de harika çalışacak
sonuç.retcode == TRADE_RETCODE_PLACED'i sonuç.retcode olarak değiştirme == TRADE_RETCODE_DONE
Yani, asenkron kullanmazsanız, baykuşlar sunucudan bir yanıt bekleyeceğinden OnTradeTransaction işleyicisine gerek yoktur?
Ancak şu ana kadar bir durdurma emrinin etkinleştirildiğini belirlemenin en iyi yolunu bulamadım. Örneğin, bir piyasa Buy 0.1 ve SellStop 0.3 ayarlanır ve 0.3 etkinleştirildiğinde, 0.2 kalır ve hangi noktada izlemeniz gerekir ... Her tikte iki siparişi izlemeniz gerektiği ortaya çıkıyor. Ben de baykuşları indirip ancak işlem tamamlandıktan sonra kontrol etmek istedim. Kontrol bile etmeyin, ancak bir kez ne olduğunu kontrol edin ve ne yapacağınıza karar verin. Ama görünüşe göre bu kader değil ... Muhtemelen eski kanıtlanmış yöntemlere dönmek daha iyidir ...
Yani, asenkron kullanmazsanız, baykuşlar sunucudan bir yanıt bekleyeceğinden OnTradeTransaction işleyicisine gerek yoktur?
Ancak şu ana kadar bir durdurma emrinin etkinleştirildiğini belirlemenin en iyi yolunu bulamadım. Örneğin, bir piyasa Buy 0.1 ve SellStop 0.3 ayarlanır ve 0.3 etkinleştirildiğinde, 0.2 kalır ve hangi noktada izlemeniz gerekir ... Her tikte iki siparişi izlemeniz gerektiği ortaya çıkıyor. Ben de baykuşları indirip ancak işlem tamamlandıktan sonra kontrol etmek istedim. Kontrol bile etmeyin, ancak bir kez ne olduğunu kontrol edin ve ne yapacağınıza karar verin. Ama görünüşe göre bu kader değil ... Muhtemelen eski kanıtlanmış yöntemlere dönmek daha iyidir ...
Evet, OnTradeTransaction'ı kullanamazsınız , ancak daha sonra danışmanın genel performansını büyük ölçüde azaltacak olan geçmişi araştırmanız gerekecektir.
Her geliştiricinin bir seçeneği vardır!
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz
referansa göre
Yani, OnTradeTransaction işlevinde siparişin yürütülmesinin doğruluğunu kontrol etmenizi sağlar. Yoksa bir şeyi yanlış mı anlıyorum?
Ama burada uyarı geliyor:
Aynı zamanda, bu işlemlerin terminalde alınma sırası garanti edilmez, bu nedenle alım satım algoritmanızı, bazı alım satım işlemlerinin diğerlerinin gelmesinden sonra alınması beklentisi üzerine kuramazsınız. Ayrıca sunucudan terminale teslimat sırasında işlemler kaybolabilir.
Eh, garantili bir sekans değil, sorunun yarısıdır. Ancak, işlemin kaybolabileceği ve bu nedenle çekler için OnTradeTransaction işlevini kullanamayacağımız gerçeğiyle ne yapmalı.
Burada ayrıca bir soru gelir: O halde bir olayı ele alma işlevi ne için gereklidir? Terminale kesinlikle işe yaramaz losyon??? Yoksa yine bir şeyi yanlış mı anlıyorum?