ForexالبورصةBourseBolsa股市AktienBorsaФорексFXFinançasGiełdaΧρηματιστήριοBeursBörsPörssi금융
22.05.2012 14:53 GMT
   
 
  New York   Londra   Tokyo 
   
 

Emirlerin Açılması ve Yerleştirilmesi

Yazar   |  Teknik Analiz  |  08.11.2009 21:38 GMT  |  Yorum Ekle
 

Piyasa emirlerinin açılması ve bekleyen emirlerin yerleştirilmesi işlemi OrderSend() işlevi ile yapılmaktadır.

OrderSend() İşlevi


int OrderSend (string symbol, int cmd, double volume, double price, int slippage,
double stoploss, double takeprofit, string comment = NULL, int magic = 0,
datetime expiration = 0, color arrow_color = CLR_NONE)

(Lütfen yukarıdaki yazımda sadece işlevin başlığının geçtiğini, bunun kullanıma bir örnek oluşturmadığına dikkat ediniz).
İşlevin içeriğine detaylı olarak bakalım.

OrderSend işlevin adıdır. İşlev bilet(ticket) numarasını geri döndürür (bilet numarası emre ait olan ve eşsiz bir numaradır), server tarafından emir ile ilişkilendirilir, eğer server emri açmaz ya da açamaz ise -1 değerini geri döndürür. Detaylı hata bilgisi almak için GetLastError() isimli işlev kullanılmalıdır (aşağıda bazı genel hata kodları incelenecektir).

symbol işlem yapılacak olan paritedir. Her paritenin bir string(yazı dizesi) olarak karşılığı vardır. Örneğin, Euro/Dolar paritesi için "EURUSD" olarak geçmektedir. Eğer emir önceden belirlenmiş bir pariteye verilmişse, bu parametre dışsal olarak bildirilebilir: "EURUSD", "EURGBP" gibi. Fakat, UzmanDanışman programı herhangi bir parite için kullanılacaksa standart işlev olan Symbol() kullanılabilir. Bu işlev, UzmanDanışman ya da scriptin çalıştırıldığı paritenin adını geri döndürür.

cmd yapılacak olan işlemin türüdür. İşlem türü ön tanımlı değişkenler yönetmiyle belirtilebilir.

volume lot miktarıdır. Piyasa emirleri için her zaman hesaptaki kullanılabilir teminat kontrol edilmelidir. Bekleyen emirler için ise girilecek olan lot miktarı sınırsızdır.

price açılış fiyatıdır. İşlem yapılabilmesi için kabul edilen sınırlamalar ve gereksinimler ile belirlenmektedir. Eğer piyasa emri girebilmek için gerekli olan fiyat bulunamadıysa ya da tamamen güncelliğini kaybetmişse, işlem isteği reddedilir. Fakat, eğer fiyat güncelliğini yitirmiş olmasına rağmen fiyat kanalında mevcut ise ve eğer değişim miktarı verilen kayma miktarlarıyla oluşturulan kanal içerisindeyse, işlem isteği müşteri terminali tarafından kabul edilerek server tarafına gönderilir.

slippage piyasa emirlerinin girişi sırasında fiyat için izin verilen en fazla değişme miktarıdır (pip miktarı olarak). Bu parametre bekleyen emirler için geçerli değildir.

stoploss verilen emir için kabul edilen en fazla kayıp miktarıdır (zarar durdurma sınırı). İşlem yapılabilmesi için kabul edilen sınırlamalar ve gereksinimler ile belirlenmektedir.

takeprofit verilen emir için kabul edilen en fazla kazanç miktarıdır.İşlem yapılabilmesi için kabul edilen sınırlamalar ve gereksinimler ile belirlenmektedir.

comment emir girildiğinde ekrana gönderilecek olan yazıdır. Bu yazının son parçası server tarafından değiştirilebilir.

magic emir için verilen özel bir ticket numarasıdır. Kullanıcı tarafından tanımlanmış bir değişken ile kullanılabilir. Bazı durumlarda hangi programa ait bir emir olduğunu bulmak için yardım alınabilecek tek bilgi magicnumber olmaktadır. Parametre kullanıcı tarafından belirlenir; diğer emirlerde girilen değerlerden farklı olabilir.

expiration emrin geçerliliğini yitireceği zamandır. Bu zamana gelir gelmez server tarafında bekleyen emir otomatik olarak iptal edilir. Bazı serverlarda bekleyen emirler için geçerlilik süresi parametresi sınırlandırılmıştır. Bu durumda eğer bu parametreye sıfırdan farklı bir değer girilirse işlem isteği reddedilir.

arrow_color emrin grafik penceresi üzerinde hangi renk bir ok ile betimleneceğini belirler. Eğer bu parametre eksik ise değer CLR_NONE olarak kabul edilir ve herhangi bir ok figürü gösterilmez.

Bazı serverlarda toplam açılmış ve bekleyen emir sayısı ile alakalı sınırlamalar olabilmektedir. Eğer bu limit aşılırsa, emir istekleri server tarafından reddedilecektir.

Piyasa Emirlerinin Açılması


OrderSend() işlevi en başta karmaşık görünebilir. Fakat, tüm parametreler oldukça basit, yardımcı ve işlemler sırasında başarı ile kullanılabilmektedir. Bunu görebilmek için piyasa emirleri açmak için OrderSend() işlevinin nasıl kullanıldığını basit bir örnekle deneyebilirsiniz.

Öncelikle, OrderSend() işlevi ön tanımlı değişkenlere sahiptir. Bunun anlamı bu işlevin en az sayıda parametre ile basitleştirilmiş olarak kullanılabileceğidir. Bu parametreler şu şekildedir:

symbol zorunlu bir parametredir çünkü emrin nerede açılacağını belirtmek gerekmektedir. Scriptin herhangi bir paritede emir açmasına imkan verelim. Bu durumda standart işlev olan Symbol() parametre olarak geçilmelidir;

cmd, örneğin bir alış emri verilmek isteniyorsa, bu durumda OP_BUY parametresi belirtilmelidir,

volume, kurallar dahilinde herhangi bir miktar belirtilebilir, örneğin ufak bir miktar olan 0.1 lot girelim,

price, alış emirleri için Ask ön tanımlı değişkeni kullanılmalıdır;

slippage, genellikle 0-3 aralığında girilmektedir. Örnek olarak 2 belirleyelim,

stoploss, değeri server tarafından belirlenen minimum uzaklıktan daha yakın olamaz, genellikle 5 pip olmasına rağmen paritelere ve işlem yapılan aracı kuruma göre değişebilmektedir. Bu örnekte kapanış için 15 pip olarak belirleyelim, bu durumda alış emri verdiğimiz için Bid - 15 * Point girelim,

takeprofit, bu değeri de 15 pip olarak belirleyelim, bu durumda Bid + 15 * Point girelim.

Aşağıda en basit script bulunmaktadır, simpleopen.mq4, bu programın amacı sadece bir alış emri açmaktır.

//--------------------------------------------------------------------
// simpleopen.mq4
//--------------------------------------------------------------------
int start()                                  // özel işlev olan start()
{                                          // Alış emri veriliyor
    OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, Bid - 15 * Point, Bid + 15 * Point);
    return;                                   // start() bitiyor
}
//--------------------------------------------------------------------

Eğer bu script müşteri terminali üzeride yürütülürse, birçok durumda çalışacaktır. Script özel bir işlev olan OrderSend() işlevini işlem isteği göndermek amacıyla kullanmaktadır ve return operatörü kullanılmıştır. Programın satır bazlı olarak yaptığı işlemler aşağıda açıklanmıştır.

1. Kullanıcı scripti "Navigator" penceresinden sürekleyerek 0.1 lotluk akış emri açmak istediği paritenin grafik penceresi üzerine bırakmıştır.

2. Script kodunun parite grafik penceresine sürüklenmesi anında müşteri terminali kontrolü start() işlevine devreder (burada hatırlatılması gereken bir nokta da şudur ki; scriptlerin çalıştırılması anında start() işlevleri devreye girerken UD programlarında start() işlevi en yakın tick geldiğinde yürütülür).

3. Programın start() işlevini başlatmasıyla kontrol işlem isteğini oluşturan ilk satır olan OrderSend() işlevine geçer:

 OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, Bid - 15 * Point, Bid + 15 * Point);

Bu işlevin yürütülmesinden önce program gerekli olan değerlerin hesaplamasını yapar:

3.1 Script Euro/Dolar paritesine eklenmiştir. Bu durumda standart işlev olan Symbol() EURUSD stringini geri döndürür.

3.2 İşlevin çağırılması anında Ask değerinin 1.2852 ve Bid değerinin 1.2850 olduğunu varsayalım.

3.3 Bu durumda StopLoss değeri 1.2850 - 15 * 0,001 = 1.2835 ve TakeProfit değeri 1.2865 olacaktır.

4. OrderSend() işlevinin çalışması:

4.1 İşlev bir işlem isteği oluşturarak bu isteği müşteri terminaline gönderir.

4.2 İşlev isteği müşteri terminaline gönderirken kontrolü de terminale devreder ve bu sırada programın çalışması da durur.

4.3 Müşteri terminali gönderilen işlem isteğini kontrol eder. Herhangi yanlış bir değerle karşılalmaz, bu yüzden de isteği server tarafına gönderir.

4.4 Server işlem isteğini alır, kontrol eder, herhangi bir yanlış değer bulamaz ve isteği yürütür.

4.5 Server isteği işleyerek veri tabanı içinde işlemi kaydeder ve bu bilgiyi müşteri terminaline geri gönderir.

4.6 Müşteri terminali son istekle alaklı gerekli bilgileri server tarafından alır, bu isteği terminal penceresinde ve parite penceresinde gösterir ve kontrolü programa bırakır.

4.7 Program kontrolü tekrar devraldıktan sonra çalışmasına kaldığı yerden devam eder.

Programın 4.2 adımı ile 4.7 adımı arasında hiçbir işlem yapmadığına, bu sırada bekleme modunda durarak server tarafından bir cevap beklediğine dikkat edin.

5. Program içindeki kontrol diğer operatöre geçmiştir, "return" operatörü.

6. "return" operatörünün işletilmesi start() işlevinin sonlanmasına neden olur, bu işlem de kontrolün tekrar müşteri terminaline verilmesi demektir (scriptlerin sadece bir defa çalışarak sonlandığı unutulmamalıdır).

Artık script tam amacını yerine getirmiştir: geçilen parametrelerle alış emri açılması. Scriptler oldukça kullanışlıdır, özellikle de tek bir iş yapılması gereken durumlarda. 4.6 adımından sonra kullanıcı emrin girildiğini grafik penceresinde görebilir.

Mql Şekil 81
Mql Şekil 81


Şekil 81. simpleopen.mq4 scriptiyle emir yerleştirildi.

Olaylar her zaman yukarıda gösterildiği gibi değildir. İsteğin müşteri terminali ya da server tarafından reddedilme ihtimali vardır. Bir başka örneği daha inceleyelim, bu sefer parite ismini "GBPUSD" olarak verelim. Bu durumda sadece belirli bir paritede çalışan bir program üretmiş oluyoruz.

int start()                                  // özel işlev olan start()
{                                          // Alış emri veriliyor
    OrderSend("GBPUSD", OP_BUY, 0.1, Ask, 3, Bid - 15 * Point, Bid + 15 * Point);
    return;                                   // start() bitiyor
}

Scripti yine Euro/Dolar paritesinde çalıştıralım. Scriptin amacı Sterlin/Dolar paritesinde emir açmaktır. Fakat, Euro/Dolar paritesine eklendiğinde Sterlin/Dolar paritesinde bir emir açılmaz.

Bu tür programların dezavantajı işlevsel limitlerinin bulunmasıdır. Scriptin parite penceresine eklenmesi durumunda, kullanıcı sadece bir emrin açılmasını beklemektedir. Fakat emir açılmamıştır. Kullanıcı emrin açılmama sebebinin farkında değildir. Bunun sebebi algoritmik bir hata da olabilir, isteğin server tarafına gönderilirken "kaybolmuş" olması da olabilir, işlem isteğinin müşteri terminali tarafından reddedilmiş olması da olabilir.

Kullanıcıya olaylar hakkında bilgi sağlamak açısından işlem isteklerininde karşılaşılan hata kodlarının işlenmesi gerekmektedir.

Hata İşleme


Müşteri terminalinin çok önemli bir özelliği eğer programın çalışması sırasında bir hata oluşursa müşteri terminalinin programı yürütmeyi durdurmamasıdır. Hatalar genellikle kodların içerisinde hata olması nedeniyle oluşmaktadır. Bazı durumlarda dışa bağlı faktörler nedeniyle hatalar oluşmaktadır. Hataların içsel sebeplerle oluşma nedeni MQL4 gereksinimlerini ya da işlem kurallarını çiğnemiş olmasıdır, örneğin yanlış fiyatların girilmesi. Dışsal sebepler ise programa bağlı olmayan hatalardır, örneğin bağlantı olmayışı.

Eğer programın çalışması sırasında bir hata ortaya çıkarsa, program yürütülmeye devam edilir ve müşteri terminali bir hata kodu oluşturur. Program içinde bu hata kodu GetLastError() işlevi ile alınabilir.

GetLastError() İşlevi


İşlev en son ortaya çıkan hatanın kodunu geri dönüş değeri ile verir daha sonra da last_error isimli özel değişkenin içeriği sıfırlanır. Hemen ardından gelen GetLastError() çağırısı bu yüzden 0 değerini geri döndürür.

Bundan sonra bütün ortaya çıkan hatalar bu işlevle belirlenecektir. Programın çalışması sırasında birden çok hata ortaya çıkabilir; GetLastError() işlevi bunların sadece en son hata kodunu almayı sağlar. Bu yüzden de her hata kontrolü yapılacak koddan hemen sonraki satırda GetLastError() işlevi çağırılmalıdır.

Hata 130. Geçersiz Stop Değeri


En son incelenen script hata kodlarını analiz etmiyor, bu yüzden de programın işleyişi sırasında ortaya çıkabilecek hatalardan kullanıcı tamamen habersiz kalıyordu. En basit haliyle GetLastError() işlevi hata kodunun işlenmesini ve kullanıcının bu durumdan haberdar edilmesini sağlar. confined.mq4 isimli scripti Euro/Dolar penceresinde çalıştırırsanız bir hata oluşacaktır.

//--------------------------------------------------------------------------
// confined.mq4
//--------------------------------------------------------------------------
int start()                                     // özel işlev start()
{                                             // Alış emri veriliyor
    OrderSend("GBPUSD", OP_BUY, 0.1, Ask, 3, Bid - 15 * Point, Bid + 15 * Point);
    Alert (GetLastError());                      // Hata mesajı
    return;                                      // start() işlevinin sonu
}
//--------------------------------------------------------------------------

Çok kısa fakat çok bilgilendirici bir satırı kodumuza ekledik:

Alert(GetLastError());

GetLastError() işlevi en son oluşan hata kodunu geri döndürür, Alert() işlevi de bu kodu ekranda göstermek için kullanılmıştır. confined.mq4 scripti Euro/Dolar ekranına eklendikten sonra script çalıştırılacaktır bu da aşağıdaki mesaja neden olacaktır.

Mql Şekil 82
Mql Şekil 82


Şekil 82. confined.mq4 scriptinin Euro/Dolar penceresinde çalıştırılmasıyla elde edilen hata kodu

Ek içerisinde hata kodlarının açıklamalarını bulabilirsiniz. Şu anda 130 numaralı hata kodu (geçersiz stop değeri) oluştu. Bunun anlamı OrderSend() işlevine gönderilen parametrelerin gerekliliklere veya limitlere uymadığıdır. Eğer yakından bakılırsa hata sebebinin kaynağı net olarak görülebilir, Ask ve Bid değerleri scriptin çalıştırıldığı pariteden alınmıştır fakat OrderSend() işlevi içerisinde GBPUSD paritesi kullanılmaktadır. Sonuç olarak fiyatların tutmaması sebebiyle hata oluşmuştur.

Şu anda algoritmik bir hata oluşmuş durumda. Bu hatayı düzeltebilmek için pariteye ait doğru verilerin alınması gerekir. Değerleri MarketInfo() işlevini kullanarak elde edebilirsiniz. improved.mq4 scripti herhangi bir parite penceresinde çalıştırılabilir:

//------------------------------------------------------------------------------
// improved.mq4
//------------------------------------------------------------------------------
int start()
{
    double bid = MarketInfo("GBPUSD", MODE_BID); // Bid değerinin istenmesi
    double ask = MarketInfo("GBPUSD", MODE_ASK); // Ask değerinin istenmesi
    double point = MarketInfo("GBPUSD", MODE_POINT); // Point değerinin istenmesi
    // Alış emrinin verilmesi
    OrderSend("GBPUSD", OP_BUY, 0.1, ask, 3, bid - 15 * Point, bid + 15 * Point);
    Alert(GetLastError());
    return;
}
//------------------------------------------------------------------------------

Scriptin çalışmasıyla ortaya çıkan yukarıdaki hata artık çıkmayacaktır bu yüzden ekrana yazdırılacak hata kodu 0 olacaktır. Bunun anlamı GetLastError() işlevinin bu değeri döndürdüğü yani programda bir hata meydana gelmediğidir.

Hata 129. Geçersiz Fiyat


Bazı durumlarda basit hatalar meydana gelmektedir. Piyasaya alış emri Ask fiyatı ile verilmelidir. Aşağıda mistaken.mq4 kodunda, eğer yanlışlıkla Bid değeri geçildiğinde ne olacağı gösterilmiştir:

//-------------------------------------------------------------------------
// mistaken.mq4 
//-------------------------------------------------------------------------
int start()
{
    OrderSend(Symbol(), OP_BUY, 0.1, Bid, 3, Bid - 15 * Point, Bid + 15 * Point);
    Alert(GetLastError());
    return;
}
//-------------------------------------------------------------------------

 
İşlem isteğinin server tarafına gönderilmesinden önce müşteri terminali gönderilen fiyatın, stop ve limit değerlerinin uygun olup olmadığını kontrol eder. Bu kontrol sırasında, gönderilen emrin giriş fiyatı geçersiz olarak belirlenecektir, bu yüzden müşteri terminali isteği server tarafına göndermeyecektir. GetLastError() işlevinin geri dönüş değeri 129 olacaktır. Scriptin yürütülmesi aşağıdaki hata kodunun görüntülenmesiyle sonlanacaktır:

Mql Şekil 83
Mql Şekil 83


Şekil 83. mistaken.mq4 kodunun çalıştırılmasıyla ortaya çıkan hata 129 (geçersiz fiyat)

Hata 134. İşlem İçin Yetersiz Teminat


Eğer işlem yapılan hesapta yeterli miktarda teminat yoksa benzer bir durum (hata 134) oluşabilir. MarketInfo(parite_adı, MODE_MARGINREQUIRED) işlevini kullanarak herhangi bir paritede bir lotluk işlem yapmak için gerekli olan teminat miktarını öğrenebilirsiniz.

Aynı parite için işlem ücreti aracı kurumlara göre farklılık gösterebilmektedir.

Bir paritede bir lotluk işlem yapmak için gerekli olan kullanılabilir teminat miktarı kullanılan kaldıraç oranına göre değişmektedir. Tablo 3\'te 1 lot ve 1 pip için gerekli ücretlerin kombinasyonları gösterilmektedir.


İşlem Merkezi 1 İşlem Merkezi 2 İşlem Merkezi 3
Buy Sell Pip Buy Sell Pip Buy Sell Pip
EUR/USD 1296,40 1296,20 10,00 1296,50 1296,20 10,00 1000,00 1000,00 10,00
GBP/USD 1966,20 1966,00 10,00 1376,48 1376,20 7,50 1000,00 1000,00 10,00
AUD/USD 784,40 784,20 10,00 1569,20 1568,40 20,00 1000,00 1000,00 10,00
USD/JPY 1000,00 1000,00 8,29 1000,00 1000,00 8,29 1000,00 1000,00 8,29
USD/CHF 1000,00 1000,00 8,02 1000,00 1000,00 8,02 1000,00 1000,00 8,02
EUR/CHF 1296,40 1296,20 8,02 1296,35 1296,35 8,02 1000,00 1000,00 8,02

16.12.2007 tarihiyle alınan fiyatlar.

Şimdi 1 lot ve 1 pip için genel hesaplama yöntemlerine göz atalım.

İşlem Merkezi 1 (en geneli)

Karşılığı USD olan paritelerde 1 lota karşılık gelen fiyat, anlık fiyatın 1000 ile çapılmış halidir, 1 pip için fiyat ise 10$ olarak belirlenir.

Pay kısmında USD olan paritelerde 1 lota karşılık gelen fiyat 1000.00$, 1 pipe karşılık gelen fiyat ise 1/Satış olmaktadır. Örneğin, USDCHF paritesinde satış 1,2466 olduğundan 1 pip 1/1,2466 = 8,02\'dir. Çapraz paritelerde ise 1 lot için gerekli olan teminat pay kısmında yer alan döviz ile, 1 pip için fiyat ise paydada yer alan döviz ile hesaplanır. Örneğin EURCHF paritesinde 1 lotun karşılığı 129.40 (EURUSD paritesinde olduğu gibi), 1 pipe karşılık gelen miktar 8.02\'dir (USDCHF paritesinde olduğu gibi).

İşlem Merkezi 2

Bazı işlem merkezlerinde, fiyatların hesaplamasında aynı yöntemlerin izlendiği varsayılıyor, paritelerin fiyatları farklılık gösterebilir. 1 lotun fiyatı ve 1 pipe karşılık gelen değer bir oran dahilinde artmış ya da azalmış olabilir. Örneğin, GBPUSD paritesinde bu çarpan 0,75 iken, AUDUSD paritesinde çarpan 2,0\'dır. Fiyat değerlerinin bu şekildeki sunumu hiçbir ekonomik değişime neden olmaz. Bu tip durumlar sadece vereceğiniz emirler için fiyat hesaplamasında kullanılırken oluşmaktadır. Ayrıca dikkat edilmelidir ki çapraz paritelerde alış ve satış için gerekli olan teminat miktarları aynıdır.

İşlem Merkezi 3

Bazı işlem merkezleri her parite için 1 lot için gerekli olan teminatı 1000,00$ olarak belirlemiştir. Aynı zamanda 1 pipe denk gelen fiyat da anlık fiyatlara göre orantılıdır. Bu her parite için özel bir kaldıraç değerine karşılık gelmektedir.

Genel olarak fiyatların yapılmasında farklı prensipler de uygulanıyor olabilir. Gerçek işlem yapmaya başlamadan önce işlem merkezinin hesaplamalarında hangi yöntemi kullandığını bilmek  önemlidir.

Kullanılabilir Teminat

Kodlama sırasında kullanılabilir değerlerin göz önünde tutulması önemlidir. Kullanılabilir teminat işlem yapabilmek için açıkta olan miktardır.

Teminatın 5000,00$ olduğunu ve terminalde açık bir emir bulunmadığını düşünelim. İşlem merkezi 3 üzerinden bir alış emri verdiğimizi düşünelim. Bu durumda;

Müşteri terminal penceresi açılan emir hakkında bilgiyi gösterecektir. Teminatın 1000,00$ tuttuğunu, emirin karının -30,00$ olduğunu, bu yüzden de kullanılabilir teminat miktarının 3970,00$ olduğunu görüyoruz.

Mql Şekil 84

Şekil 84. Terminal penceresinde alış emri

Aynı değerden bir satış girildikten sonra kullanılabilir teminat miktarı artacaktır. Her yöne konulan emirlerin teminatı 1000,00$ yapmaktadır, bu yüzden de kullanılabilir teminat 1000,00$ artacaktır. Şekil 85\'te  farklı yönde açılan emirlerin aynı miktara malolduğu görülmektedir, bu yüzden de emirler kapatıldığında teminat artacaktır.

Mql Şekil 85
 Mql Şekil 85


Şekil 85. Terminal penceresinde Alış ve Satış emirleri

Daha küçük miktarda bir satış emri girildiğinde kullanılabilir teminat miktarı artacaktır. Bu durumda da daha küçük bir dahil edilmek ücreti ödenecektir bu da 0,7 lot için 700,00$ olacaktır.

Mql Şekil 86

Şekil 86. Terminal pencersinde Alış ve Satış emirleri

Eğer 0,1 lotluk daha satış emri girilirse (ücreti 100,00$), tek yönlü emirde piyasa teminatı 800,00$ olacaktır. Bu yüzden, serbest teminat miktarı (sadece alış emrinin girildiği duruma göre) 800,00$ azalmıştır. Şekil 86\'da gösterilen duruma göre serbest teminat azalmıştır, bakiye de bu sırada 100,00$ artacaktır (Şekil 87).

Mql Şekil 87
 Mql Şekil 87


Şekil 87. Terminal penceresinde Alış ve Satış emirleri

Şekil 86 ve Şekil 87\'de gösterilen serbest teminatlar birbirlerinden 100,00$\'dan fazla fark etmektedir çünkü elde edilen kar miktarlarına göre serbest teminat miktarı da değişmektedir.

Eğer bir başka işlem merkezinde aynı uygulamaları yaparsak, üstteki emirlerinden oluşan serbest teminatların birbirini tutmadığı görülecektir. Bazı işlem merkezlerindeki kurallar aşağıdaki gibidir:

Herhangi bir piyasa emrinin açılması bakiyenin serbest bırakılmasına veya serbest teminatın artmasına neden olmaz. Piyasa emirlerinin açılması alınan ücret kadar bakiyenin artmasına neden olur (her işlem merkezinde geçerli değildir).

Örneğin, işlem merkezide 2\'de USDJPY paritesinde 4 lotluk işlem yapılırsa, 4 lotluk satış işlemi için bakiye ve serbest teminat miktarı değişmeyecektir.

Mql Şekil 88

Şekil 88. Farklı yönlerde açılan emirler bakiyeyi serbest bırakmaz

Bir emir açabilmek için gerekli olan teminata sahip olunup olunmadığı hesaplamalar yapılarak bulunabilir. Ayrıca AccountFreeMarginCheck() işlevi kullanılabilir, bu işlev belirli bir paritede ve belirli bir lot miktarında piyasa emri açılmasından sonra kalacak olan serbest teminat miktarını geri döndürür. Eğer geri döndürülen değer 0\'a eşit ya da daha büyükse hesapta yeterli para vardır. Eğer 0\'dan daha düşük bir değer döndürürse, bu paritede bu kadar miktarda işlem yapılamayacağı anlamına gelmektedir ve müşteri terminali 134 numaralı hatayı üretir.

İşlem merkezi tarafından desteklenen koşulları ve serbest teminatı bilmek bir lotluk emir açmak için gereklidir. Aşağıdaki basit scripti deneyebilirsiniz:

//--------------------------------------------------------------------------
// conditions.mq4
//--------------------------------------------------------------------------
int start()
{
    Alert(Symbol(), "  Satis = ", AccountFreeMargin() - AccountFreeMarginCheck(Symbol(), OP_SELL, 1));           
// Satışta    
    Alert(Symbol(),"  Alis = ",AccountFreeMargin() - AccountFreeMarginCheck(Symbol(), OP_BUY, 1));
// Alışta

    return;
}
//--------------------------------------------------------------------------

Script içinde kullanılan deyim sayesinde elinizde bulunan serbest teminat ile gerekli işlemin yapılabilmesi için gereken serbest teminat arasındaki farkı öğrenilebilir.

Eğer bu scripti çalıştırırsanız, eğer terminal üzerinde piyasa emri yok ise, gerekli olan bakiyeyi ve bir lotluk emir açmak için gerekli ücreti öğrenebilirsiniz:

Mql Şekil 89

Şekil 89. Farklı paritelerde bir lotun fiyatı

Eğer conditions.mq4 scriptini üzerinde açık emir bulunan bir parite üzerinde çalıştırırsanız, diğer değerleri de elde edebilirsiniz, bu işlem merkezinin sağladığı izinlere bağlıdır.

Diğer Hatalar ve MarketInfo() İşlevi


OrderSend() işlevinin parametreleri için başka sınırlamalar da vardır. Bunlar en az ve en çok fiyat değişim miktarları, en az ve en fazla fiyat miktarları vs.\'dir. MarketInfo() işlevinin kullanımı parite hakkında müşteri terminalinin "Piyasa Gözlem" penceresinde bulunan birçok bilgiyi edinmenize yardımcı olur.

MarketInfo() İşlevi


double MarketInfo(string parite, int tür)

İşlev bir parite hakkında "Market Watch (Piyasa Gözlem)" penceresinde yer alan birçok türde veriyi geri döndürebilir. Parite hakkında veri parçaları ön tanımlı değişkenlerde saklanmaktadır.

Parametreler:
symbol: Parite adı;
type: Geri döndürülecek olan verinin türünü belirleyen değişken. İstenilen türlerden herhangi birisi olabilir.

Server tarafında oluşabilecek bazı sorunlar nedeniyle hatalar meydana gelebilir, fiyatların geçilmesi sırasında, aracı kurumunuz bekleyen emirler veya stop değerleri için en az fiyat mesafesi sınırını arttırabilir. Daha sonra, piyasanın daha sakin bir halinde, aracı kurum en az fiyat mesafesini tekrar azaltabilir. Bu yüzden bazı parametrelerin değerleri her an değişebilir.

Programın daha kararlı çalışabilmesi için, en az sayıda isteğin reddedilmesi adına, OrderSend() işlevini kullanmadan önce MarketInfo() ve RefreshRates() işlevleriyle gönderilecek olan parametrelerin yenilenmesi ve çevresel verilerin doğrulanması gerekir.

Örnek bir script ile %35 kullanılabilir teminat gerektiren ve anlık veriler ile stop değerleri belirten bir Alış emri gerçekleştiriliyor (openbuy.mq4).

//-------------------------------------------------------------------------------
// openbuy.mq4
//-------------------------------------------------------------------------- 1 --
int start()
{
    int Dist_SL = 10;                             // Anlık StopLoss (pip)
    int Dist_TP = 3;                              // Anlık TakeProfit (pip)
    double Prots = 0.35;                           // Kullanılabilir teminat yüzdesi
    string Symb = Symbol();                        // Parite
//-------------------------------------------------------------------------- 2 --
    while(true) {                                  // Emri açan döngü
        int Min_Dist = MarketInfo(Symb, MODE_STOPLEVEL); // En az mesafe
        double Min_Lot = MarketInfo(Symb, MODE_MINLOT); // En az lot miktarı
        double Step = MarketInfo(Symb, MODE_LOTSTEP); // Lotu değiştiren adım
        double Free = AccountFreeMargin(); // Kullanılabilir teminat
        double One_Lot = MarketInfo(Symb, MODE_MARGINREQUIRED);// 1 lotun                                             // ücreti
    //-------------------------------------------------------------------- 3 --
        double Lot = MathFloor(Free * ProtsOne_LotStep) * Step; // Lot
        if (Lot < Min_Lot) {                       // Eğer izin verilenden az ise   
            Alert(Min_Lot," lot için yeterli teminat yok!");
            break;                                 // Döngüden çık
        }
    //-------------------------------------------------------------------- 4 --
        if (Dist_SL < Min_Dist) {                  // Eğer izin verilenden az ise
                    Dist_SL = Min_Dist;                      // İzin verileni ata
            Alert("StopLoss ", Dist_SL, " pip arttırıldı");
        }
        double SL = Bid - Dist_SL * Point;            // StopLoss için istenilen nokta
    //-------------------------------------------------------------------- 5 --
                if (Dist_TP < Min_Dist) {                   // Eğer izin verilenden az ise
                    Dist_TP = Min_Dist;                      // İzin verileni ata
                    Alert("TakeProfit ", Dist_TP, " pip arttırıldı");
                }
                double TP = Bid + Dist_TP * Point;            // TakeProfit için istenilen nokta
    //-------------------------------------------------------------------- 6 --
                Alert("İstek server tarafına gönderildi. Cevap bekleniyor...");
                int ticket = OrderSend(Symb, OP_BUY, Lot, Ask, 2, SL, TP);
    //-------------------------------------------------------------------- 7 --
                if (ticket > 0) {                             // İşlem yapıldı mı?
                    Alert ("Alış emri açıldı, ",ticket);
                    break;                                 // Döngüden çık
                }
    //-------------------------------------------------------------------- 8 --
                int Error = GetLastError();                 // İşlem yapılamadı mı?
                switch(Error) {                            // Üstesinden gelinebilir hatalar
                    case 135:Alert("Fiyat değişmiş. Tekrar deneniyor..");
                            RefreshRates();                     // Veriyi güncelle
                            continue;                           // Bir sonraki adım
                    case 136:Alert("Fiyat yok. Yeni tick bekleniyor..");
                            while(RefreshRates() == false)        // Yeni tick alınıyor
                                    Sleep(1);                        // Döngüyü geciktir
                            continue;                           // Bir sonraki adım
                    case 146:Alert("İşlem merkezi meşgul. Tekrar deneniyor..");
                            Sleep(500);                         // Basit çözüm
                            RefreshRates();                     // Veriyi güncelle
                            continue;                           // Bir sonraki adım
                }
                switch(Error) {                            // Önemli hatalar
                    case 2 : Alert("Genel hata.");
                            break;                              // \'switch\' deyiminden çık
                    case 5 : Alert("Müşteri terminalinin eski versiyonu.");
                            break;                              // \'switch\' deyiminden çık
                    case 64: Alert("Hesap bloke edilmiş.");
                           break;                              // \'switch\' deyiminden çık
                    case 133:Alert("İşlem yasaklanmış.");
                            break;                              // \'switch\' deyiminden çık
                    default: Alert("Oluşan hata: ", Error); // Diğer ihtimaller
                }
                break;                                    // Döngüden çık
        }
//-------------------------------------------------------------------------- 9 --
    Alert ("Script işlemlerini tamamladı ---------------------------");
    return;                                      // start() işlevinden çık
}
//-------------------------------------------------------------------------- 10 --

Script özel bir işlev olan start() işlevini içermektedir(1 - 10 arasındaki bloklar). 1. ve 2. blokta emrin açılması gereken değerler atanıyor. 2-9 arasındaki bloklar while() döngü operatörünü temsil ediyor, içinde de bütün gerekli olan hesaplamalar gerçekleştiriliyor. Bu döngü işlemin yapılabilmesi için birçok denemede bulunuyor ve çevre değişkenleri güncelliyor. 3. 4. 5. ve 6. bloklar içinde lot miktarı ve stop değerleri hesaplanıyor. 7. 8. ve 9. bloklar içinde hata işlemeleri yapılıyor. 9-10 bloğu içinde scriptin yaptığı işlemler Alert() işlevi ile ekrana yazdırılıyor.

Şimdi program kodu içerisinde bazı özellikleri gözden geçirelim. Görüldüğü gibi işlem isteği 6-7 bloğu içinde gönderiliyor. 3-4 bloğu içinde lot miktarı hesaplanıyor. Ayrıca en az açılabilecek lot miktarını karşılayan teminatın olup olmadığı da kontrol ediliyor. Bu yüzden 3-4 bloğunda yetersiz teminat olduğunu ekrana yazdırdıkan sonra 2-9 bloğu içinde yer alan döngüden break deyimi ile çıkıyoruz. Kontol 9-10 bloğuna geçiyor ve script işlemlerini tamamlıyor. 9. blokta yer alan mesaj gereksiz. Sadece kullanıcılar için başıyla sonu arasındaki ayrımı daha rahat yapabilmeleri sağlamak amacıyla kullanılmıştır. Ne zaman program sonlandırılıyor ne zaman gecikmeler nedeniyle duraksamalar meydana geliyor anlaşılabilmesi için.

Eğer emrin girilebilmesi için gerekli olan teminat var ise, kontrol 4-5 bloğuna oradan da 5-6 bloğuna geçecektir. Bu bloklar içerisinde bir çıkış yoktur. Bunun anlamı aracı kurum tarafından konulan en az fiyat mesafesi ne olursa olsun yeni stop değerleri belirlenecektir. 1-2 bloğunda TakeProfit için 3 pip seçilmiştir. Aracı kurumların birçoğu en az fiyat mesafesini 5 pip olarak belirlerler. 5-6 bloğunda program bu değerin çok az olduğunu anlayacak ve hesaplamalar ile yeni değeri belirleyecektir. Program aracı kurumun sınırlamalarıyla çakışmayacak şekilde yeni stop değerleri belirlemektedir.

İşlemlerin ardından emrin açılabilmesi için kontrol 6-7 bloğuna geçiyor. Bu bloğun başında mesaj ekrana yazdırılıyor. İşlem isteği ancak 2. satırda gönderiliyor. Burada bir soru oluşuyor: Neden emri gerçtek göndermeden önce gönderildi mesajını yazdırıyoruz? Önce isteği gönderip daha sonra kullanıcıyı bu konuda bilgilendirebiliriz. Bu sorunun cevabı işlem isteğini önce müşteri terminaline ardından da server tarafına gönderen teknoloji ile yakından alakalı (Şekil 66). Bizim durumumuzda işlem isteği atama operatörünün sağında olan OrderSend() işlevi ile yapılmaktadır. Bu işlev içinde oluşturulan ve server tarafına gönderilen isteğin kaderi ancak server bir cevap gönderdikten sonra belli olacaktır. Bu yüzden de kullanıcıyı olayların başlamasından önce bilgilendirmek çok daha iyi bir kullanım şeklidir.

Er ya da geç müşteri terminali kontrolü tekrar programa verecek, 6-7 bloğunda yer alan atama operatörü işleyecek ve \'ticket\' isimli değişken bir değer alacaktır. Bunun ardından hata işlemek için kontrol 7-8-9 bloğuna gönderilecektir.

Eğer server tarafında işlem açılısa, açılan emrin numarası (bilet) \'ticket\' isimli değişken içinde saklanacaktır. Bunun anlamı scriptin amacını yerine getirdiği ve programın daha fazla çalışmasına gerek olmadığıdır. 7-8 bloğunda \'break\' operatörünü kullanarak while() döngüsünden çıkıyoruz. Kontro bundan sonra 9-10 bloğuna geçecek ve program işlemlerini tamamlayacaktır.

Fakat, eğer işlem isteği reddedilirse, kontrol hata işlemek için 8-9 bloğuna geçecektir. Burada iki farklı tür hata göz önüne alınmaktadır: hala işlemin yapılabilmesi ihtimali bulunan hatalar ve programın sonlanmasını gerektiren hatalar. \'Error\' değişkenine OrderSend() işlevinin gönderilmesinden sonra müşteri terminali ya da server tarafından oluşturulan son hata bilgisi atanmaktadır.

8-9 bloğunda yer alan \'switch\' operatörü üstesinden gelinebilen hataları inceliyor. Bu grupta yer alan her hata farklı şekilde işleniyor. Örneğin, eğer fiyat değiştiyse (hata 135), parametreleri RefreshRates() işlevi ile güncellemek ve tekrar işlem isteğinde bulunmak yetecektir. Eğer hata fiyatın olmamasıysa (hata 136), işlem isteğini tekrar göndermenin hiçbir mantığı yoktur. Bu durumda yeni bir tick beklemek (bu durumda sistemde hiçbir yeni fiyat yoktur) ve bundan sonra tekrar emir açmayı denemek iyi olacaktır. Bu yüzden 136 numaralı hatayı işleyen kod içinde bir bekleme işlemi yapılmıştır. Bu bekleme döngüsü yeni bir tick gelir gelmez sonlanacaktır. \'continue\' operatörü ile switch deyiminden çıkarak döngünün bir sonraki adımına geçilmektedir.

Önemli hatalar farklı bir şekilde işlenmektedir. Eğer bu tür bir hata meydana gelirse, program bu konuda sadece kullanıcıyı uyaracak ve işlemlerine son verecektir. Bu amaçla \'break\' operatörünü kullanıyoruz (8-9 bloğundaki en sonuncusu), bu sayede while() döngüsünden çıkılıyor.

Kurgu açısında bütün hata kodlarının incelenmediğini göz önüne almalısınız. Burada kullanıcı için gerçek bir program yapmayı amaçlamadık. Programcının tamamen bağımsız bir şekilde hataları göz önüne alarak hangilerini işleyeceğine ve hatalar meydana geldiğinde neler yapabileceğine karar vermesi gerekir. Aynı zamanda bazı hatalar işlenemezdir çünkü program bu şekilde tasarlanmamış ve bu hatalar meydana geldiğinde herhangi birşey yapmayı amaçlamamıştır, örneğin bu kodun içinde 129 ve 130 numaralı hata kodları işlenmemiştir.

Yukarıdaki örnekte ufak bir algoritmik hata vardır ve ne derleme sırasında ne de müşteri terminali ya da server tarafından bulunabilir.

4-5 bloğunda yer alan kod:


Feragat: Fusion Media would like to remind you that the data contained in this website is not necessarily real-time nor accurate. All CFDs (stocks, indexes, futures) and Forex prices are not provided by exchanges but rather by market makers, and so prices may not be accurate and may differ from the actual market price, meaning prices are indicative and not appropriate for trading purposes. Therefore Fusion Media doesn`t bear any responsibility for any trading losses you might incur as a result of using this data .

Fusion Media or anyone involved with Fusion Media will not accept any liability for loss or damage as a result of reliance on the information including data, quotes, charts and buy/sell signals contained within this website. Please be fully informed regarding the risks and costs associated with trading the financial markets, it is one of the riskiest investment forms possible.

Yorum Ekle

 
 
 
 

Başarıyla raporlandı

Teşekkür ederiz. Yorum, yöneticinin incelemesi için işaretlendi.
_touchLoadingMsg
 
 
Kampanyalar
Anket
Hangi alanda yayıncılığımızı genişletmemizi istersiniz?
Analizlerde
Eğitimde
Oranlar & Grafikler
Brokerler
Yazılım
Forumlar