
MetaTrader 5 Alım Satım Olayları
Giriş
Alım satım işlemlerini gerçekleştirmek için tüm komutlar, istek gönderilerek MetaTrader 5 müşteri terminalinden alım satım sunucusuna iletilir. Her istek, istenen işleme göre doğru bir şekilde doldurulmalıdır; aksi takdirde birincil doğrulamayı geçemez ve daha sonraki işlemler için sunucu tarafından kabul edilmez.
Alım satım sunucusu tarafından kabul edilen istekler, bekleyen veya piyasa fiyatına göre anında uygulanabilen emirler şeklinde saklanır. Emirler, doldurulana veya iptal edilene kadar sunucuda saklanır. Bir emir yürütmenin sonucunda bir yatırım gerçekleşir.
Bir yatırım, alım satım pozisyonunu belirli bir sembolle değiştirir; pozisyonu açabilir, kapatabilir, artırabilir, azaltabilir veya tersine çevirebilir. Bu nedenle, açık bir pozisyon her zaman bir veya daha fazla yatırım gerçekleştirmenin bir sonucu olarak ortaya çıkar. Daha detaylı bilgi, MetaTrader 5 makalesindeki Emirler, Pozisyonlar ve Yatırımlar bölümünde verilmiştir.
Bu makale, bir isteğin ilk olarak gönderilmesinden, işlendikten sonra alım satım geçmişinde taşınmasına kadar geçen süre içinde gerçekleşen kavram, terim ve süreçleri açıklar.
İstemci Terminalinden Alım Satım Sunucusuna İsteğin İletilmesi
Bir alım satım işlemi gerçekleştirmek için alım satım sistemine bir emir göndermelisiniz. Alım satım sunucusuna gönderilen istekler her zaman müşteri terminalinden emir girilerek gönderilir. Bir isteğin yapısı, nasıl alım satım yaptığınızdan bağımsız olarak, manuel veya bir MQL5 programı kullanılarak doğru bir şekilde doldurulmalıdır.
Manuel işlem yapmak için diyalog penceresini açmanız veya F9 tuşuna basarak alım satım isteği doldurmanız gerekmektedir. MQL5 aracılığıyla otomatik alım satım yaparken, OrderSend() fonksiyonu kullanılarak istekler gönderilir. Çok sayıda hatalı istek, alım satım sunucusunun istenmeyen şekilde aşırı yüklenmesine neden olabileceğinden her istek gönderilmeden önce OrderCheck() fonksiyonu kullanılarak kontrol edilmelidir. Bir isteği kontrol etmenin sonucu, MqlTradeCheckresult yapısı tarafından tanımlanan bir değişkene yerleştirilir.
Alım satım sunucusuna bir istek geldiğinde, birincil kontrolden geçer:
- Bu kontrol, işlemi gerçekleştirmek için yeterli varlığa sahip olup olmadığınızı,
- açık fiyatlar, Zararı Durdur, Kâr Al vb. belirtilen fiyatın doğru olup olmadığını,
- anında yürütme için fiyat akışında belirtilen fiyatın mevcut olup olmadığını.
- Piyasa Yürütmesi modunda Zararı Durdur ve Kâr Al seviyelerinin mevcut olup olmadığını.
- minimum ve maksimum hacim, adım, pozisyonun maksimum hacmi (SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_MAX, SYMBOL_VOLUME_STEP ve SYMBOL_VOLUME_LIMIT) gibi hacmin doğru olup olmadığını,
- fiyat teklifi veya alım satım oturumu, sembolle işlem yapma olasılığı, belirli bir işlem modu (örn. sadece pozisyon kapatma), vb. sembolün durumunu,
- belirli hesap türleri için farklı sınırlamalar gibi alım satım hesabının durumunu
- kontrol eder ve istenilen alım satım işlemine bağlı olarak diğer kontrolleri yapar.
Sunucudaki birincil kontrolü geçemeyen yanlış istekler reddedilir. Müşteri terminali, her zaman bir yanıt göndererek isteğin kontrol edilmesinin sonucu hakkında bilgilendirilir. Bir istek gönderilirken alım satım sunucusunun yanıtı, OrderSend() fonksiyonunda ikinci parametre olarak geçen MqlTradeResult türünün bir değişkeninden alınabilir.
Bir istek birincil doğruluk kontrolünden geçerse, işlenmeyi bekleyen isteğe yerleştirilecektir. İsteğin işlenmesinin sonucunda, alım satım sunucusu tabanında bir emir (bir alım satım işlemi gerçekleştirme komutu) oluşturulur. Ancak emrin oluşturulmasıyla sonuçlanmayan iki tür istek vardır:
- bir pozisyonu değiştirme isteği (Zararı Durdur ve/veya Kâr Al).
- bekleyen bir emri değiştirme isteği (fiyat seviyeleri ve zaman aşımı süresi.
Müşteri terminali, isteğin kabul edildiğine ve MetaTrader 5 platformunun alım satım alt sistemine yerleştirildiğine dair bir mesaj alır. Sunucu, kabul edilen isteği, aşağıdakilerle sonuçlanabilecek daha ileri işlemler için istek kuyruğuna yerleştirir:
- bekleyen bir emir verilmesi.
- piyasa fiyatına göre anlık bir emir gerçekleştirilmesi.
- bir emir veya pozisyonun değiştirilmesi.
Sunucunun kuyruğundaki bir isteğin ömrü üç dakikadır. Süre aşıldığında istek, istek kuyruğundan kaldırılır.
Alım Satım Sunucusundan Müşteri Terminaline Alım Satım Olayları Gönderme
Olay modeli ve olay işleme fonksiyonları MQL5 dilinde uygulanmaktadır. Bu, MQL5 yürütme ortamının önceden tanımlanmış herhangi bir olaya yanıt olarak uygun fonksiyonu, yani olay işleyiciyi çağırdığı anlamına gelir. Alım satım olaylarının işlenmesi için önceden tanımlanmış olan OnTrade() fonksiyonu mevcuttur. Emir, pozisyonlar ve yatırımlarla çalışmak için olan kod bunun içine yerleştirilmelidir. Bu fonksiyon yalnızca Uzman Danışmanlar için çağrılır, aynı ad ve türde bir fonksiyon ekleseniz bile göstergelerde ve komut dosyalarında kullanılmaz.
Alım satım olayları, aşağıdaki durumlarda sunucu tarafından oluşturulur:
- aktif emirlerin değiştirilmesi,
- pozisyon değişikliği,
- yatırım değişikliği,
- alım satım geçmişi değişimi.
Bir işlemin birkaç olayın gerçekleşmesine neden olabileceğini unutmayın. Örneğin bekleyen bir emri tetiklemek, iki olayın meydana gelmesine yol açar:
- alım satım geçmişinde yazılmış bir yatırımın ortaya çıkması.
- bekleyen emrin aktif olanlar listesinden geçmiş emirler listesine taşınması (emir, geçmişe taşınır).
Birden fazla olaya başka bir örnek ise gerekli hacmin tek bir karşı tekliften elde edilememesi durumunda tek bir emir bazında birden fazla yatırımın gerçekleştirilmesidir. Alım satım sunucusu, tüm olaylarla ilgili mesajları oluşturur ve müşteri terminaline gönderir. Bu nedenle OnTrade() fonksiyonu, tek bir olay gibi görünen bir olay için birkaç kez çağrılabilir. Bu, MetaTrader 5 platformunda alım satım alt sisteminin emir işleme prosedürüne basit bir örnektir.
Bir örnek verelim: 10 lot EURUSD alımı için bekleyen bir emir gerçekleşmeyi beklerken, 1, 4 ve 5 lotluk satış için zıt teklifler ortaya çıkıyor. Bu üç istek birlikte gerekli 10 lotluk hacmi verir, bu nedenle emir türü parça parça alım satım işlemine izin veriyorsa bunlar tek tek yürütülür.
4 emrin yürütülmesi sonucunda sunucu mevcut karşıt istekler bazında 1, 4 ve 5 lotluk 3 yatırım gerçekleştirecektir. Peki bu durumda kaç alım satım olayı oluşturulur? Bir lot satışı için ilk ters talep, 1 lotluk satışın gerçekleşmesine yol açacaktır. Bu, ilk Alım Satım olayıdır (1 lotluk yatırım). Ancak 10 lotluk alım için bekleyen emir de değiştirilir ve 9 lotluk EURUSD alma emrine dönüşür. Bekleyen emrin hacmindeki değişiklik, ikinci Alım Satım olayıdır (bekleyen bir emrin hacmindeki değişiklik).
4 lotluk ikinci yatırım için, diğer iki Alım Satım olayı oluşturulacak, 10 lot EURUSD satın almak için bekleyen ilk emri giren müşteri terminaline her biri hakkında birer mesaj gönderilecektir.
5 lotluk son yatırım, üç alım satım olayının gerçekleşmesine yol açacaktır:
- 5 lotluk yatırım,
- hacim değişikliği,
- emrin alım satım geçmişine taşınması.
Yatırımın yürütülmesinin bir sonucu olarak, müşteri terminaline art arda 7 alım satım olayı Alım Satım gelir (müşteri terminali ile alım satım sunucusu arasındaki bağlantının stabil olduğu ve hiçbir mesajın kaybolmadığı varsayılır). Bu mesajlar, OnTrade() fonksiyonu kullanılarak bir Uzman Danışman’da işlenmelidir.
Emirlerin Alım Satım Sunucusu Tarafından İşlenmesi
Yürütülmeyi bekleyen tüm emirler sonunda geçmişe taşınacaktır - ya gerçekleşme koşulu yerine getirilecek ya da iptal edilecektir. Bir emir birkaç farklı şekilde iptal edilebilir:
- emir bazında bir yatırımın gerçekleştirilmesi.
- emrin bir satıcı tarafından reddedilmesi.
- Satıcının isteği üzerine emrin iptal edilmesi (manuel istek veya bir MQL5 programından yapılan otomatik bir istek).
- Satıcı tarafından istek gönderilirken veya mevcut alım satım sisteminin alım satım koşulları tarafından belirlenen zaman aşımı.
- işlem koşullarının yerine getirildiği anda alım satım hesabında yatırımı gerçekleştirmek için gereken varlığın olmaması.
- Emir türü nedeniyle emrin iptal edilmesi (kısmen doldurulmuş bir emrin iptal edilmesi).
Aktif bir emrin geçmişe taşınmasının nedeni ne olursa olsun, değişiklikle ilgili mesaj müşteri terminaline gönderilir. Alım satım olayıyla ilgili mesajlar tüm müşteri terminallerine değil, yalnızca ilgili hesaba bağlı olanlara gider.
Bu nedenle OrderSend() fonksiyonunun belgelerinde aşağıdaki ibare geçmektedir:
Dönüş değeri
Bir isteğin temel kontrolünün başarılı olması durumunda, OrderSend() fonksiyonu true değerini geri gönderir- bu, bir alım satım işleminin başarılı bir şekilde yürütüldüğü anlamına gelmez. Fonksiyonun yürütülmesinin sonuçlarının detaylı açıklamaları için, MqlTradeResult yapısının alanlarını analiz ediniz.
İstemci Terminalinde Alım Satımın ve Geçmişin Güncellenmesi
Alım satım olayları ve alım satım geçmişindeki değişikliklerle ilgili mesajlar ayrı kanallardan gelir. OrderSend() fonksiyonunu kullanarak satın alma isteği gönderirken, isteğin başarılı bir şekilde doğrulanması sonucunda oluşturulan emrin fişini alabilirsiniz. Aynı zamanda, emrin kendisi müşteri terminalinde görünmeyebilir ve OrderSelect() kullanarak seçmek mümkün olmayabilir.
Yukarıdaki şekilde, alım satım sunucusunun emir fişini MQL5 programına nasıl ilettiğini görebilirsiniz, ancak alım satım olayı (yeni emrin görünmesi) ile ilgili mesaj henüz gelmedi. Aktif emirler listesinin değiştirilmesi ile ilgili mesaj da gelmedi.
Programa yeni bir emrin ortaya çıkmasıyla ilgili bir alım satım mesajı geldiğinde, tabanında bir yatırım zaten yapılmışsa ve bu nedenle emir aktif emirler listesinde yoksa geçmişte olabilir. Bu gerçek bir durumdur, çünkü isteklerin işlenme hızı, bir ağ üzerinden bir mesajın iletilmesinin mevcut hızına kıyasla çok daha yüksektir.
MQL5'te Alım Satım Olaylarının İşlenmesi
Alım satım sunucusundaki tüm işlem ve alım satım olayları ile ilgili mesajların gönderilmesi asimetrik olarak gerçekleştirilir. Alım satım hesabında tam olarak neyin değiştiğini öğrenmenin tek bir kesin yöntemi vardır. Bu yöntem, alım satım durumunu ve alım satım geçmişini ezberlemek ve ardından yeni durumla karşılaştırmaktır.
Uzman Danışman’da alım satım olaylarını takip etme algoritması şu şekilde çalışır:
- global kapsamda yatırım, pozisyon ve anlaşma sayaçlarını ilan etme.
- MQL5 program önbelleğine istenilecek alım satım geçmişinin derinliğini belirleyin. Önbelleğe ne kadar çok geçmiş yüklersek, terminalin ve bilgisayarın kaynakları o kadar fazla tüketilecektir.
- OnInit fonksiyonunda emir, pozisyon ve yatırımların sayaçlarını başlatın.
- alım satım geçmişini önbelleğe isteyecek işleyici fonksiyonlarını belirleyin.
- Burada, alım satım geçmişinin yüklenmesinden sonra, hafızaya alınan durum ile mevcut durumu karşılaştırarak alım satım hesabına ne olduğunu da bulacağız.
Bu en basit algoritmadır, açık pozisyonların (emir, yatırımlar) sayısının değişip değişmediğini ve değişimin yönünün ne olduğunu görmeyi sağlar. Değişiklik olursa daha detaylı bilgi alabiliriz. Emir sayısı değiştirilmeyip emirlerin kendileri değiştirilirse farklı bir yaklaşım gerekir, bu nedenle, bu varyant bu makalede ele alınmamıştır.
Sayaç değişiklikleri, bir Uzman Danışman’ın OnTrade() ve OnTick() fonksiyonlarından kontrol edilebilir.
Adım adım bir program örneği yazalım.
1. Global kapsamda emir, yatırım ve pozisyonların sayacı.
int orders; // number of active orders int positions; // number of open positions int deals; // number of deals in the trade history cache int history_orders; // number of orders in the trade history cache bool started=false; // flag of initialization of the counters
2. Önbelleğe yüklenecek alım satım geçmişinin derinliği, giriş değişkeni günlerinde ayarlanır (bu değişkende belirtilen gün sayısı için alım satım geçmişini yükleyin).
input int days=7; // depth of the trade history in days //--- set the limit of the trade history on the global scope datetime start; // start date of the trade history in cache datetime end; // end date of the trade history in cache
3. Sayaçların başlatılması ve alım satım geçmişinin sınırları. Kodun daha iyi okunabilmesi için sayaçların başlatılmasını InitCounters() fonksiyonuna alın:
int OnInit() { //--- end=TimeCurrent(); start=end-days*PeriodSeconds(PERIOD_D1); PrintFormat("Limits of the trade history to be loaded: start - %s, end - %s", TimeToString(start),TimeToString(end)); InitCounters(); //--- return(0); }
InitCounters() fonksiyonu, alım satım geçmişini önbelleğe yüklemeye çalışır ve başarılı olması durumunda tüm sayaçları başlatır. Ayrıca, geçmiş başarıyla yüklenirse, 'started' global değişkeninin değeri 'true' olarak ayarlanır, bu, sayaçların başarıyla başlatıldığını gösterir.
//+------------------------------------------------------------------+ //| initialization of the counters of positions, orders and deals | //+------------------------------------------------------------------+ void InitCounters() { ResetLastError(); //--- load history bool selected=HistorySelect(start,end); if(!selected) { PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d", __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError()); return; } //--- get current values orders=OrdersTotal(); positions=PositionsTotal(); deals=HistoryDealsTotal(); history_orders=HistoryOrdersTotal(); started=true; Print("The counters of orders, positions and deals are successfully initialized"); }
4. Alım satım hesabı durumundaki değişikliklerin kontrolü OnTick() ve OnTrade() işleyicilerinde gerçekleştirilir. Önce 'started' değişkeni kontrol edilir - değeri 'true' ise, SimpleTradeProcessor() fonksiyonu, aksi takdirde ise InitCounters() sayaçlarının başlatma fonksiyonu çağrılır.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(started) SimpleTradeProcessor(); else InitCounters(); } //+------------------------------------------------------------------+ //| called when the Trade event occurs | //+------------------------------------------------------------------+ void OnTrade() { if(started) SimpleTradeProcessor(); else InitCounters(); }
5. SimpleTradeProcessor() fonksiyonu emir, yatırım ve pozisyonların sayısının değişip değişmediğini kontrol eder. Tüm kontrolleri yaptıktan sonra gerekirse 'start' değerini mevcut ana yaklaştıran CheckStartDateInTradeHistory() fonksiyonunu çağırıyoruz.
//+------------------------------------------------------------------+ //| simple example of processing changes in trade and history | //+------------------------------------------------------------------+ void SimpleTradeProcessor() { end=TimeCurrent(); ResetLastError(); //--- load history bool selected=HistorySelect(start,end); if(!selected) { PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d", __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError()); return; } //--- get current values int curr_orders=OrdersTotal(); int curr_positions=PositionsTotal(); int curr_deals=HistoryDealsTotal(); int curr_history_orders=HistoryOrdersTotal(); //--- check whether the number of active orders has been changed if(curr_orders!=orders) { //--- number of active orders is changed PrintFormat("Number of orders has been changed. Previous number is %d, current number is %d", orders,curr_orders); /* other actions connected with changes of orders */ //--- update value orders=curr_orders; } //--- change in the number of open positions if(curr_positions!=positions) { //--- number of open positions has been changed PrintFormat("Number of positions has been changed. Previous number is %d, current number is %d", positions,curr_positions); /* other actions connected with changes of positions */ //--- update value positions=curr_positions; } //--- change in the number of deals in the trade history cache if(curr_deals!=deals) { //--- number of deals in the trade history cache has been changed PrintFormat("Number of deals has been changed. Previous number is %d, current number is %d", deals,curr_deals); /* other actions connected with change of the number of deals */ //--- update value deals=curr_deals; } //--- change in the number of history orders in the trade history cache if(curr_history_orders!=history_orders) { //--- the number of history orders in the trade history cache has been changed PrintFormat("Number of orders in the history has been changed. Previous number is %d, current number is %d", history_orders,curr_history_orders); /* other actions connected with change of the number of order in the trade history cache */ //--- update value history_orders=curr_history_orders; } //--- check whether it is necessary to change the limits of trade history to be requested in cache CheckStartDateInTradeHistory(); }
CheckStartDateInTradeHistory() fonksiyonu, mevcut an (curr_start) için alım satım geçmişi isteğinin başlangıç tarihini hesaplar ve bunu 'start' değişkeniyle karşılaştırır. Aralarındaki fark 1 günden fazla ise 'start' düzeltilir ve geçmiş emir ve yatırımların sayaçları güncellenir.
//+------------------------------------------------------------------+ //| Changing start date for the request of trade history | //+------------------------------------------------------------------+ void CheckStartDateInTradeHistory() { //--- initial interval, as if we started working right now datetime curr_start=TimeCurrent()-days*PeriodSeconds(PERIOD_D1); //--- make sure that the start limit of the trade history period has not gone //--- more than 1 day over intended date if(curr_start-start>PeriodSeconds(PERIOD_D1)) { //--- we need to correct the date of start of history loaded in the cache start=curr_start; PrintFormat("New start limit of the trade history to be loaded: start => %s", TimeToString(start)); //--- now load the trade history for the corrected interval again HistorySelect(start,end); //--- correct the counters of deals and orders in the history for further comparison history_orders=HistoryOrdersTotal(); deals=HistoryDealsTotal(); } }
Uzman Danışman DemoTradeEventProcessing.mq5'in tam kodu makaleye eklenmiştir.
Sonuç
Çevrimiçi işlem platformu MetaTrader 5'teki tüm işlemler asenkron olarak gerçekleştirilir ve bir alım satım hesabındaki değişikliklerle ilgili tüm mesajlar birbirinden bağımsız olarak gönderilir. Bu nedenle, "Bir istek - bir alım satım olayı" kuralına dayanarak tekil olayları takip etmeye çalışmanın bir anlamı yoktur. Eğer bir Alım Satım olayı gerçekleştiğinde tam olarak neyin değiştirdiğini belirlemeniz gerekiyorsa OnTrade işleyicisinin her çağrısında tüm yatırım, pozisyon ve emirlerinizi mevcut durumlarını bir öncekiyle karşılaştırarak incelemeniz gerekir.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/232





- Ü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