English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 22): Yeni emir sistemi (V)

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 22): Yeni emir sistemi (V)

MetaTrader 5Ticaret | 6 Ekim 2023, 15:11
374 0
Daniel Jose
Daniel Jose

Giriş

Yeni bir sistemi uygulamak o kadar da kolay değildir, zira sık sık süreci büyük ölçüde zorlaştıran sorunlarla karşılaşırız. Bu sorunlar ortaya çıktığında durmalı ve ilerlediğimiz yönü yeniden analiz etmeliyiz, her şeyi olduğu gibi bırakıp bırakamayacağımıza ya da yeni bir görünüm kazandırmamız gerekip gerekmediğine karar vermemiz gerekir.

Bir sistem oluştururken, özellikle de net bir son tarihimiz veya bütçemiz yoksa, bu tür kararlar oldukça sık alınabilir: baskı altında olmadığımızda, geliştirme ve iyileştirme açısından istikrarı sağlamak adına elimizden gelenin en iyisini yapmak için testler gerçekleştirebilir ve ayarlamalar yapabiliriz.

Belirli bir bütçe ile geliştirilen veya zamanında teslim edilmesi gereken büyük programlar, özellikle de ticari olanlar, genellikle daha sonra düzeltilmesi gereken birçok hata içerir. Çoğu zaman, sistemi geliştirenlerin sistem için çok faydalı olabilecek bazı çözümleri keşfetmek ve uygulamak için zamanları yoktur. Bu şekilde, çoğu durumda programcıların yaratabileceklerinin gerisinde kalan programlar ortaya çıkar. Bazen şirketler küçük iyileştirmeler veya hata düzeltmeleriyle sürüm üstüne sürüm yayınlar. Bunun nedeni hataların program yayınlandıktan sonra tespit edilmesi değil, programcıların ürünün yayınlanmadan önce baskı altında olmalarıdır.

Bu aslında birçok şirketin tüm üretim zinciri boyunca gerçekleşir. Ancak kendi yarattığımız bir şey söz konusu olduğunda, en iyi ve tercihen en kolay yolu ararız. Dahası, tüm olası ve uygulanabilir çözümleri keşfetmeyi göze alabiliriz. Gerekirse, sistem geliştirme sürecini değiştirmek ve iyileştirmek için durabilir ve biraz geriye gidebiliriz. Çoğu zaman, küçük bir durma ve yön değişikliği, istenen sistemin geliştirilmesine büyük ölçüde yardımcı olabilir.

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 21): Yeni emir sistemi (IV) makalesinde, sistem neredeyse hazırdı. Yalnızca emirleri doğrudan grafik üzerinde taşımaktan sorumlu kısım eksikti. Bu kısmı uygulamak için kodu kontrol ettim ve kodda bazı tuhaflıklar olduğunu fark ettim: kodda çok sayıda tekrar eden kısım vardı. Hâlbuki gereksiz tekrarlardan kaçınmak için çok da dikkatli davranmıştık. Daha da kötüsü, örneğin çok farklı varlıklar kullanıldığında bazı şeyler olması gerektiği gibi çalışmadı. Uzman Danışmanı tasarlamaya ve burada yayınlanan makalelerde belgelemeye başladığımda, çoğunlukla onu B3 borsasındaki vadeli işlemler üzerinde ticaret yapmak için kullanmayı düşünüyordum. Ama geliştirme süreci içerisinde, dolar vadeli işlemleri veya WDO ve WIN olarak bilinen endeksler üzerinde ticaret yapmak için geliştirmiş oldum. Ancak sistem başlangıçta kullanmak istediğim sisteme gittikçe yaklaştıkça, diğer piyasalara veya varlıklara genişletilebileceğini fark ettim. İşte sorun da burada ortaya çıktı.


1.0. Çalışma masasına geri dönüyoruz

Sorunu anlamak için, bir Uzman Danışman geliştirirken birçok kişinin gözden kaçırdığı önemli bir ayrıntıya dikkat etmemiz gerekir. Ticaret sisteminde sözleşmeler nasıl tanımlanır? MetaTrader 5 bu bilgileri sağlar ve MQL5 de bu bilgilere erişmemizi mümkün kılar. Dolayısıyla, hesaplamaları genelleştirecek matematiği oluşturmak ve böylece en eksiksiz sistemi elde etmek için verileri anlamamız gerekir.

Geliştirmekte olduğumuz emir sistemi, başka herhangi bir harici kaynağa veya gelecekte oluşturulabilecek herhangi bir şeye ihtiyaç duymadan doğrudan grafikten ticaret yapmak üzere tasarlanmıştır. Bu, platformlarda kullanılana çok benzer bir ticaret sistemi oluşturma girişimidir, ancak ihtiyacınız olan bilgileri özelleştirebilmeniz ve ekleyebilmeniz için de tamamen açık kaynaklıdır.

Buradaki fikir, kullanıcının sadece bakarak bir pozisyonda neler olup bittiğini bilmesini sağlamaktır. Fikir çok iyi gibi görünse de, ticaret sistemi forex ve B3 gibi borsalar için bir sistem oluşturmaya çalışanlara hayatı kolaylaştırmamaktadır. Mevcut bilgi seviyesi, emirleri bir piyasaya veya diğerine göre özelleştirmek için yeterlidir, ancak genel bir şey yaratmak bir sorundur. Ancak ben bu sorunla yüzleşmeye ve evrensel bir sistem oluşturmaya karar verdim.

Bunu gerçekten yapabileceğimden emin olmamakla birlikte, en azından gerekli bilgileri nasıl bulacağınızı gösterebilirim ve böylece Uzman Danışmanı yerel sisteminiz için özelleştirmeniz gerekirse, bunu nasıl yapacağınız konusunda deneyim ve bilgiye sahip olacaksınız. Sistem başlangıçta modellemeyi kaldıramasa bile, onu ihtiyaçlarınıza göre uyarlayabileceksiniz.

Bir gözlem: veriler MQL5 kodu kullanılarak elde edilebilir, ancak işi basitleştirmek adına verilerin nerede olduğunu göstermek için MetaTrader 5 kullanacağım.


1.0.1. B3'te işlem gören şirket varlıkları (hisse senetleri)

Aşağıdaki iki görüntüye bakalım:

     

Vurgulanan kısımlar, pozisyonun nasıl yerleştirileceğini hesaplamak için ihtiyaç duyduğumuz verileri göstermektedir.

Finansal değere dayalı bir pozisyon oluşturursanız, zararı durdur ve kârı al değerlerini hesaplamak için bu değerlere ihtiyacınız olacaktır. OCO emri kullanmazsanız, işler daha da kolay olacaktır, ancak burada tüm emirlerin OCO emirleri veya pozisyonları olduğunu varsayıyoruz.

Önemli: Bir varlık kısmi hisse olarak işlem görüyorsa (B3'teki piyasalar arasında farklılıklar vardır), minimum hacim belirtilen değerin %1'i olacaktır, bu nedenle 100'e 100 ticaret yapmak yerine 1'e 1 ticaret yapacağız. Hesaplama farklı olacaktır, bu yüzden bunu unutmayın.


1.0.2. B3'te vadeli işlem sözleşmeleri

Vadeli işlem sözleşmeleri için kurallar hisse senedi ticareti kurallarından farklıdır, hacim, bir tam sözleşme veya bir mini sözleşme ile ticaret yapmanıza ve hatta bir varlıktan diğerine bağlı olarak değişir. Örneğin, BOI ticareti yapmak için çarpan verilerinin nasıl doldurulduğuna bakmamız gerekir. Ben burada mini sözleşmelere odaklanacağım. Bazı durumlarda, bir tam sözleşme 25 mini sözleşmeye eşit olacaktır, ancak bu değişebilir, bu nedenle her zaman borsanın hacim kurallarını kontrol etmelisiniz.

Şimdi mini doların aşağıdaki görüntülerine bir göz atalım:

     

Bu sözleşmelerin bir sona erme tarihi vardır, ancak bu makale için bu önemli değildir, çünkü Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 11): Çapraz emir sistemi makalesinde, vadeli işlem sözleşmelerini doğrudan geçmişlerinden ticaret yapmak için nasıl çapraz emir sistemi yapılacağını ele aldık ve bu yöntemi kullanırsanız, Uzman Danışman bunu sizin için yapacağından, şu anda hangi sözleşmenin işlem gördüğü konusunda endişelenmenize gerek yoktur. İşaretli alanlara dikkat edin; bunlar hisse senedi sisteminden farklıdır. Bu bazen sorunlara neden olabilir, ancak bu kısım çok sezgisel olmasa da Uzman Danışman bu sorunu yönetmektedir. Zamanla belirli finansal hacimlerde ticaret yapmak için çarpan olarak kullanılması gereken doğru değerlere alışacaksınız.

Ancak ben daha yüksek bir hedef belirlemeye karar verdim. İşte zorluklar burada başlıyor.


1.0.3. Forex

Sorunum forex sistemiyle ilgiliydi ve Uzman Danışman bunu çözemedi. Forex’te çarpanı yönetmeyi başardığımda, B3’te Uzman Danışmandaki aynı kodun kullanılamayacağını öğrendim. Bu beni rahatsız etti çünkü neden sadece bu kısımda farklılık gösteren iki Uzman Danışmana sahip olmamız gerektiğini anlamıyorum. Neler olup bittiğini görmek için aşağıdaki görüntülere bir göz atalım:

     

B3'te dört değerimiz varken forex'te yalnızca iki değerimiz vardır. İki eksik değer nedeniyle iki piyasa arasındaki hesaplamalar eşleşmemektedir.

Bu nedenle, Uzman Danışman tarafından gerçekleştirilen hesaplamalar gerçekte ne yapıldığını anlamayı çok zorlaştırdı: bazen çarpan çok yüksek oluyordu, bazen hacim beklenen minimum hacme kıyasla çok küçük oluyordu, ki bu da ticaret sisteminin emri reddetmesine neden oluyordu ve bazen de OCO eşik seviyeleri yanlış pozisyonlar nedeniyle kabul edilmiyordu. Yani bir karmaşa vardı.

Bunu anladıktan sonra Uzman Danışmanı değiştirmeye karar verdim. Dolayısıyla, değeri önceki şekilde hesaplamayacağız, farklı bir yöntem kullanacağız. Aslında bu değer artık ister borsada ister forex piyasasında olsun, çalıştığımız varlığa göre ayarlanacaktır. Böylece Uzman Danışman verilere uyum sağlayacak ve hesaplamaları doğru şekilde gerçekleştirecektir. Ancak, çarpanı doğru bir şekilde ayarlamak için ne ticareti yaptığımızı bilmemiz gerekir. Burada hacimde ondalıklı değerlerin kullanılmasına izin versek de, bundan kaçınmalısınız. Aslında, kullanılan çarpanı gösteren tamsayı değerleri kullanmalısınız.

Yani, Uzman Danışmana ne kadar hacimde ticaret yapmak istediğimizi söylemiyoruz. Bunun yerine, izin verilen minimum hacme uygulanacak çarpanı belirtiyoruz. Sorunu bu şekilde çözdüm. Kendiniz test edebilir ve nasıl çalıştığını görebilirsiniz.

Anlaşılmasını kolaylaştırmak ve uğraşı azaltmak için, bir sonraki başlıkta sonuçların kısa bir sunumunu yapacağım.


2.0. Veri görselleştirme

İlk olarak, borsa, özellikle de Brezilya borsası (B3) örneğini ele alalım. Aşağıda, verilerin MetaTrader 5'te Uzman Danışmanda nasıl görüntülendiğini göreceğiz.


2.0.1. B3 varlıkları

Brezilya borsasına kote bir şirket hissesi söz konusu olduğunda, minimum işlem hacmi 100'dür. 1'i belirterek, Uzman Danışmanı izin verilen minimum hacimde ticaret yapacak şekilde ayarlarız. Bu şekilde hacimle çalışmak çok daha kolaydır - minimum lotu tam olarak bilmeye gerek yoktur, sadece çarpanı kullanırız ve Uzman Danışman doğru emri oluşturmak için gerekli hesaplamaları yapacaktır.

Farklı değerler kullanmak istiyorsanız, sadece kullanılacak parça sayısını belirtin, yani 50, 50 parça kullanacağınız anlamına gelir, 15 belirtirseniz, 15 parça kullanılır vb.

Sonuç aşağıda MetaTrader 5 araç kutusu penceresinde gösterilmektedir. Minimum lot değerine sahip bir emrin nasıl oluşturulduğunu göstermektedir. Kârı Al ve Zararı Durdur değerlerini analiz ederseniz, onların grafikte belirtilenlerle eşleştiğini göreceksiniz, bu da Uzman Danışmanın burada çalıştığı anlamına gelir.


2.0.2. Mini dolar

Burada hacim 1'e 1'dir, ancak tam sözleşmeler söz konusu olduğunda değer farklıdır. Ticaret arayüzüne bakalım: Karı Al ve Zararı Durdur olarak belirtilen değerler yukarıdakilerle aynıdır. Ancak Uzman Danışman değerleri doğru bir şekilde ayarlamaktadır. Dolayısıyla, dikkate alınması gereken değerler grafik üzerinde ifade edilen değerlerdir, ticaret arayüzündeki değerler göz ardı edilmelidir, ancak bu değerler de grafikte belirtilen değerlere yakın olacaktır.


Araç kutusunda gösterilen veriler:

Tıpkı önceki varlıkta olduğu gibi, Zararı Durdur ve Kârı Al seviyelerini kontrol etmek için hesaplama yaparsak, onların Uzman Danışman tarafından belirtilenlerle eşleştiğini göreceğiz, yani Uzman Danışman bu aşamayı da kodu yeniden derlemeye gerek kalmadan, sadece varlığı değiştirerek geçti.


2.0.3. Forex

Bu kısım biraz daha karmaşıktır. Forex’e aşina olmayanlar için değerler oldukça garip görünebilir, ancak yine de Uzman Danışman onları çözmeyi başarıyor.


MetaTrader 5 bizi bu bekleyen işlem hakkında aşağıdaki şekilde bilgilendirecektir:


Forex'te çarpan seviyelerinin yukarıda gösterilenlerden farklı olduğunu unutmayın. Ancak hesaplamaları yaparsanız, Uzman Danışmanın doğru değerleri sağlamayı başardığını ve emrin mükemmel bir şekilde oluşturulduğunu göreceksiniz.

Tüm bunlar, uygulama bölümünde göstereceklerim dışında herhangi bir ek değişiklik yapılmadan gerçekleştirilmiştir, ancak buna ek olarak birçok farklı değişiklik de yapıldı, böylece Uzman Danışman yeniden derlemeye gerek kalmadan hem borsa hem de forex piyasası için uygun hale geldi. Burada önceki makaleleri tamamlıyoruz. Zararı durdur ve Kârı Al seviyelerini doğrudan grafik üzerinde nasıl hareket ettireceğimizi göreceğiz.


3.0. Uygulama

Koddaki bazı değişikliklere bakarak başlayalım.

İlk olarak, üç veya dört versiyon önce uygulanan eşik sistemini kaldırdım. Bunun nedeni, Uzman Danışmanın borsalar ve forex arasında geçiş yapıldığında zaman zaman lot hesaplamasına doğru bir şekilde uyum sağlayamamasıydı.

Uzman Danışmanın forex ve borsalarda eşit derecede iyi çalışmasını sağlamak için yeni bir hesaplama modeli ekledim. Bu versiyondan önce bu mümkün değildi. Başlangıçta, Uzman Danışman borsada çalışmaya odaklanmıştı, ancak ticaret yöntemleri çok farklı olmadığı için işlevselliğini forex'e genişletmeye karar verdim.

Uzman Danışmanın önceki versiyonlarda başa çıkamadığı lot hesaplama konusuyla ilgili çok sayıda ayrıntı vardır ancak yapılan değişikliklerle artık hem forex hem de borsada herhangi bir büyük kod değişikliği olmadan kullanılabilmektedir. Ancak, forex ve borsalarla uyumluluğu korumak için birden fazla değişiklik yapmak zorunda kaldım.

Bu değişikliklerden biri kodun en başında yer almaktadır:

int OnInit()
{
        static string   memSzUser01 = "";
        
        Terminal.Init();
        WallPaper.Init(user10, user12, user11);
        Mouse.Init(user50, user51, user52);
        if (memSzUser01 != user01)
        {
                Chart.ClearTemplateChart();
                Chart.AddThese(memSzUser01 = user01);
        }
        Chart.InitilizeChartTrade(user20 * Terminal.GetVolumeMinimal(), user21, user22, user23);
        VolumeAtPrice.Init(user32, user33, user30, user31);
        TimesAndTrade.Init(user41);
        TradeView.Initilize();
                
        OnTrade();
        EventSetTimer(1);
   
        return INIT_SUCCEEDED;
}

Vurgulanan kısım daha önce mevcut değildi. Başka birçok değişiklik de mevcuttur. Ancak biz buraya odaklanmayacağız. Bunun yerine, başka herhangi bir hüner kullanmadan doğrudan grafikte bulunan Kârı Al ve Zararı Durdur seviyelerini taşımak için Uzman Danışmanı nasıl kullanacağımızı göreceğiz. Şimdi bu konuya geçelim.


3.0.1. Emirleri doğrudan grafik üzerinde taşıma

Bunu önceki versiyonlarda yapmak kolay değildi, çünkü zaman içerisinde ortaya çıkan ve bu görevi zorlaştıran bir dizi çözülmemiş sorun vardı. Bir diğer neden de kodun çok dağınık olmasıydı ve bu da emir taşıma sistemini doğrudan grafik üzerinde etkili bir şekilde uygulamayı zorlaştırıyordu. Sistem başlangıçta bunu gerçekleştirebilmek için tasarlanmamıştı.

Uzman Danışmanın gerektirdiği değişikliklerin (bekleyen emirler ve pozisyonlar dahil olmak üzere emir hareketini fareyi kullanarak doğrudan grafikte üzerinden yönetebilmek amacıyla) kapsamı hakkında size bir fikir vermek için, Uzman Danışmanın daha önce neye benzediğini görelim.

Sorun, nesneler oluşturulduğunda C_HLineTrade sınıfının yerini almış olmalarıdır. Bu, Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 20): Yeni emir sistemi (III) makalesinde yapıldı. Sistem artık çok daha karmaşık bir yapıya sahiptir, bu nedenle yukarıdaki görüntünün tamamını tekrar göstermemek için sadece ne olduğuna bakacağız.

Ok, yeni sınıflara yer açmak için C_HLineTrade sınıfının kaldırıldığı bağlantı noktasını göstermektedir. Bu, önceki makalelerde yaptığımız daha fazla uygulamayı mümkün kıldı. Ancak C_OrderView sınıfının varlığı geliştirmeyi engelledi ve sonunda onu hariç tutmak zorunda kaldık. Ancak hepsi bu kadar değildir. C_TradeGraphics sınıfı eski C_OrderView sınıfı ile birleştirildi ve C_IndicatorTradeView adında yeni bir sınıf ortaya çıktı. Böylece, bu sınıf iki sınıfın yerini aldı ve bu da emir hareket sistemini geliştirmemizi sağladı.

Burada sunacağım şey bu sistemin ilk versiyonudur. Şu anda geliştirilmekte olan başka bir versiyon daha vardır, ancak bu başka bir makalede sunulacaktır.


3.0.1.1. Yeni sistem için kodun yazılması


Birleştirmeden sonra yeni sistem aşağıdaki yapılandırmaya sahiptir:


Yeşil alan, serbest olan, yani Uzman Danışman tarafından değil MetaTrader 5 tarafından yönetilecek sınıfları göstermektedir. Bu ne anlama geliyor? Süreci ayrıntılı olarak inceleyelim. Aslında, Uzman Danışman yalnızca sınıfları ve bu sınıflar tarafından yaratılan tüm nesneleri oluşturacak, yerleştirecek ve silecektir. Uzman Danışman kodunun içerisine baktığınızda, yeşil alanda oluşturulan nesnelere atıfta bulunacak herhangi bir yapı veya değişken bulamazsınız. Bu, MetaTrader 5 işletim sisteminde bellek tahsis edebildiği sürece sınırsız sayıda nesnenin oluşturulmasına izin verir. Nesnelerin sayısı Uzman Danışman içerisindeki yapılar veya değişkenler ile sınırlı değildir.

Sadece çılgın bir insanın böyle bir yapı oluşturabileceğini düşünebilirsiniz. Tamam o zaman, bana çılgın diyebilirsiniz, çünkü bunu oluşturdum ve çalışıyor. Ayrıca, şaşırtıcı bir şekilde sisteme de çok fazla yüklenmiyor. İnsanlar bana çoktan çılgın diyor, bu yüzden bu yeni bir şey değil :) Biraz daha ilerleyelim. Bekleyen emirleri veya eşikleri taşırken belirli bir yavaşlık fark edebilirsiniz. Bunun nedeni bir kod hatası veya bilgisayarınızdaki veya MetaTrader 5'teki bir sorun değildir, sorun sistemin bekleyen emirleri veya eşikleri işlem sunucusunun kendisinde hareket ettirerek yönetmesidir ve hareket ile sunucunun yanıtı arasında bir gecikme vardır. Ancak bu, bazı senaryolarda çalışmanın en iyi ve daha güvenli yoludur, ama Uzman Danışmanın yapmasını istediğim diğer şeyleri yapmamıza izin vermez. Bu nedenle, sonraki makalelerde Uzman Danışmana yeni bir işlevsellik ekleyerek bunu düzelteceğiz, ayrıca sistemi daha akıcı hale getireceğiz, ancak bunu yukarıdaki yapıyı değiştirmeden yapacağız. Sistemi daha az güvenli hale getirse de, kodu uygun bir şekilde değiştireceğiz, ancak o zamana kadar kim bilir, bu sorun için iyi bir çözüm bulabilirim.

Mevcut yeni koddaki bazı önemli noktalara bir göz atalım. Az çalışılmış bir fonksiyonla başlayacağız, kodu şu şekilde görünmektedir:

void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
#define def_IsBuy(A) ((A == ORDER_TYPE_BUY_LIMIT) || (A == ORDER_TYPE_BUY_STOP) || (A == ORDER_TYPE_BUY_STOP_LIMIT) || (A == ORDER_TYPE_BUY))

        ulong ticket;
        
        if (trans.symbol == Terminal.GetSymbol()) switch (trans.type)
        {
                case TRADE_TRANSACTION_DEAL_ADD:
                case TRADE_TRANSACTION_ORDER_ADD:
                        ticket = trans.order;
                        ticket = (ticket == 0 ? trans.position : ticket);
                        TradeView.IndicatorInfosAdd(ticket);
                        TradeView.UpdateInfosIndicators(0, ticket, trans.price, trans.price_tp, trans.price_sl, trans.volume, (trans.position > 0 ? trans.deal_type == DEAL_TYPE_BUY : def_IsBuy(trans.order_type)));
                        break;
                case TRADE_TRANSACTION_ORDER_DELETE:
                                if (trans.order != trans.position) TradeView.RemoveIndicator(trans.order);
                                else
                                        TradeView.UpdateInfosIndicators(0, trans.position, trans.price, trans.price_tp, trans.price_sl, trans.volume, trans.deal_type == DEAL_TYPE_BUY);
                                if (!PositionSelectByTicket(trans.position))
                                        TradeView.RemoveIndicator(trans.position);
                        break;
                case TRADE_TRANSACTION_ORDER_UPDATE:
                        TradeView.UpdateInfosIndicators(0, trans.order, trans.price, trans.price_tp, trans.price_sl, trans.volume, def_IsBuy(trans.order_type));
                        break;
                case TRADE_TRANSACTION_POSITION:
                        TradeView.UpdateInfosIndicators(0, trans.position, trans.price, trans.price_tp, trans.price_sl, trans.volume, trans.deal_type == DEAL_TYPE_BUY);
                        break;
        }
        
        
#undef def_IsBuy
}

Bu kod çok ilginçtir çünkü bizi ortaya çıkan veya değiştirilen her yeni pozisyonu kontrol etmek zorunda bırakmaz. Aslında, sunucunun kendisi bizi neler olduğu hakkında bilgilendirecektir, bu nedenle yalnızca Uzman Danışmanın olaylara doğru yanıt verdiğinden emin olmamız gerekir. Bu kodlama ve OnTradeTransaction olayını kullanma şeklini iyi inceleyin, çünkü kodun önceki versiyonunda yapıldığı gibi analiz modelini kullansaydım, kontroller için çok zaman harcardık. Şimdi, sunucu bizim için tüm zor işi yapmaktadır ve grafikteki değerlerin sunucunun o anda ne gördüğünü gerçekten gösterdiğinden emin olabiliriz.

Yukarıdaki kodda vurgulanan noktalara geçmeden önce, başka bir kod parçasına bakalım.

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
        Mouse.DispatchMessage(id, lparam, dparam, sparam);
        switch (id)
        {
                case CHARTEVENT_CHART_CHANGE:
                        Terminal.Resize();
                        WallPaper.Resize();
                        TimesAndTrade.Resize();
        break;
        }
        Chart.DispatchMessage(id, lparam, dparam, sparam);
        VolumeAtPrice.DispatchMessage(id, sparam);
        TradeView.DispatchMessage(id, lparam, dparam, sparam);
        ChartRedraw();
}

Böylece her şey tek bir yerde yapılmaktadır. Sınıfa girip içeride neler olduğunu görebiliriz.


3.1. C_IndicatorTradeView sınıfı

Bu sınıf, verileri sunmak ve manipüle etmek için kullanılır. Temel olarak, daha önce de belirtildiği gibi eski C_OrderView ve C_TradeGraphics sınıflarını içerir. Ancak verileri tamamen farklı bir şekilde manipüle eder. Bu sınıftaki bazı kısımlara göz atalım.

Kodu aşağıda bulunan başlatma fonksiyonu ile başlayacağız:

void Initilize(void)
{
        int orders = OrdersTotal();
        ulong ticket;
        bool isBuy;
        long info;
        double tp, sl;

        ChartSetInteger(Terminal.Get_ID(), CHART_SHOW_OBJECT_DESCR, false);
        ChartSetInteger(Terminal.Get_ID(), CHART_SHOW_TRADE_LEVELS, false);
        ChartSetInteger(Terminal.Get_ID(), CHART_DRAG_TRADE_LEVELS, false);
        for (int c0 = 0; c0 <= orders; c0++) if ((ticket = OrderGetTicket(c0)) > 0) if (OrderGetString(ORDER_SYMBOL) == Terminal.GetSymbol())
        {
                info = OrderGetInteger(ORDER_TYPE);
                isBuy = ((info == ORDER_TYPE_BUY_LIMIT) || (info == ORDER_TYPE_BUY_STOP) || (info == ORDER_TYPE_BUY_STOP_LIMIT) || (info == ORDER_TYPE_BUY));
                IndicatorInfosAdd(ticket);
                UpdateInfosIndicators(-1, ticket, OrderGetDouble(ORDER_PRICE_OPEN), OrderGetDouble(ORDER_TP), OrderGetDouble(ORDER_SL), OrderGetDouble(ORDER_VOLUME_CURRENT), isBuy);
        }
        orders = PositionsTotal();
        for (int c0 = 0; c0 <= orders; c0++) if (PositionGetSymbol(c0) == Terminal.GetSymbol())
        {
                tp = PositionGetDouble(POSITION_TP);
                sl = PositionGetDouble(POSITION_SL);
                ticket = PositionGetInteger(POSITION_TICKET);
                IndicatorInfosAdd(ticket);
                UpdateInfosIndicators(1, ticket, PositionGetDouble(POSITION_PRICE_OPEN), tp, sl, PositionGetDouble(POSITION_VOLUME), PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
        }
        CreateIndicatorTrade(def_IndicatorTicket0, IT_PENDING);
        CreateIndicatorTrade(def_IndicatorTicket0, IT_TAKE);
        CreateIndicatorTrade(def_IndicatorTicket0, IT_STOP);
}

Temel olarak yaptığımız şey, çalışmak için gerekli göstergeleri oluşturmak ve hesapta şu anda var olan pozisyonlar veya bekleyen emirler gibi her şeyi sunmaktır. Ancak vurgulanan satırlar burada önemlidir, çünkü çapraz emir sistemi kullanmıyorsanız, grafikte emir seviyelerine sahip olacaksınız (MetaTrader 5'ten) ve bu seviyeleri tıklayıp sürüklerseniz, Uzman Danışman yeni seviyeleri göstergelerdeki değişikliklerle güncelleyecektir. Bu çok fazla engel teşkil etmiyor, ancak geliştirdiğimiz sistemi gerçekten kullanmamız gerekiyor, aksi takdirde onu geliştirmenin ne anlamı var?

Aşağıdaki koda dikkat edin:

void UpdateInfosIndicators(char test, ulong ticket, double pr, double tp, double sl, double vol, bool isBuy)
{
        bool isPending;
                                
        isPending = (test > 0 ? false : (test < 0 ? true : (ticket == def_IndicatorTicket0 ? true : OrderSelect(ticket))));
        PositionAxlePrice(ticket, (isPending ? IT_RESULT : IT_PENDING), 0);
        PositionAxlePrice(ticket, (isPending ? IT_PENDING : IT_RESULT), pr);
        SetTextValue(ticket, (isPending ? IT_PENDING : IT_RESULT), vol);
        PositionAxlePrice(ticket, IT_TAKE, tp);
        PositionAxlePrice(ticket, IT_STOP, sl);
        SetTextValue(ticket, IT_TAKE, vol, (isBuy ? tp - pr : pr - tp));
        SetTextValue(ticket, IT_STOP, vol, (isBuy ? sl - pr : pr - sl));
}

Verileri alır ve günceller, böylece finansal değerler açısından doğru değerleri ve emirlerin bulunduğu seviyeleri sunar. Temel olarak, bir bekleyen emir veya pozisyon olup olmadığı konusunda endişelenmek istemiyoruz - fonksiyon onu grafikte doğru bir şekilde görebilmemiz için konumlandıracaktır.

Bu da bizi aşağıdaki fonksiyona yönlendirir:

inline double SecureChannelPosition(void)
{
        double Res = 0, sl, profit, bid, ask;
        ulong ticket;
                                
        bid = SymbolInfoDouble(Terminal.GetSymbol(), SYMBOL_BID);
        ask = SymbolInfoDouble(Terminal.GetSymbol(), SYMBOL_ASK);
        for (int i0 = PositionsTotal() - 1; i0 >= 0; i0--) if (PositionGetSymbol(i0) == Terminal.GetSymbol())
        {
                ticket = PositionGetInteger(POSITION_TICKET);
                SetTextValue(ticket, IT_RESULT, PositionGetDouble(POSITION_VOLUME), profit = PositionGetDouble(POSITION_PROFIT), PositionGetDouble(POSITION_PRICE_OPEN));
                sl = PositionGetDouble(POSITION_SL);
                if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                {
                        if (ask < sl) ClosePosition(ticket);
                }else
                {
                        if ((bid > sl) && (sl > 0)) ClosePosition(ticket);
                }
                Res += profit;
        }
        return Res;
};

OnTick olayı tarafından çağrılır, bu nedenle hız ve sistem yükü açısından oldukça kritiktir. Kontroller dışında yaptığı tek şey, vurgulanan kod tarafından uygulanan grafikteki değeri güncellemektir. Lütfen burada pozisyon fişinin çok önemli olduğunu unutmayın.

Yukarıda vurgulanan fonksiyona daha yakından bakalım.

void SetTextValue(ulong ticket, eIndicatorTrade it, double value0, double value1 = 0.0, double priceOpen = 0.0)
{
        double finance;
                                
        switch (it)
        {
                case IT_RESULT  :
                        PositionAxlePrice(ticket, it, priceOpen);
                        PositionAxlePrice(ticket, IT_PENDING, 0);
                        m_EditInfo2.SetTextValue(MountName(ticket, it, EV_PROFIT), value1);
                case IT_PENDING:
                        m_EditInfo1.SetTextValue(MountName(ticket, it, EV_EDIT), value0 / Terminal.GetVolumeMinimal(), def_ColorVolumeEdit);
                        break;
                case IT_TAKE    :
                case IT_STOP    :
                        finance = (value1 / Terminal.GetAdjustToTrade()) * value0;
                        m_EditInfo1.SetTextValue(MountName(ticket, it, EV_EDIT), finance);
                        break;
        }
}

Doğru değerler bu şekilde görüntülenir. Ama asıl konu onları nasıl hareket ettireceğimizdir. Bu, diğer üç kod tarafından yapılır. Tabii ki, onlardan kaçınabilir ve mevcut Uzman Danışman sisteminden çok daha hızlı olan MetaTrader 5 sisteminin kendisini kullanabilirsiniz. Ancak, dediğim gibi, yakında başka iyileştirmeler de alacağı için Uzman Danışmanı kullanmayı tercih ediyorum.

Hareket ettirmeden sorumlu ilk fonksiyon aşağıda görülebilir, ancak tüm kod çok daha kapsamlı olduğundan ve fare hareketlerini kullanarak nasıl hareket ettirileceğini anlamak için gerekli olmadığından, eşikler veya emrin kendisi olsun yalnızca seviyeleri taşımak için gerekli olan kod parçaları gösterilmektedir.

void DispatchMessage(int id, long lparam, double dparam, string sparam)
{
        ulong   ticket;

// ... Code ....

        switch (id)
        {
                case CHARTEVENT_MOUSE_MOVE:
                        Mouse.GetPositionDP(dt, price);
                        mKeys   = Mouse.GetButtonStatus();
                        bEClick  = (mKeys & 0x01) == 0x01;    //Left mouse click 
                        bKeyBuy  = (mKeys & 0x04) == 0x04;    //SHIFT press 
                        bKeySell = (mKeys & 0x08) == 0x08;    //CTRL press 
                        if (bKeyBuy != bKeySell)
                        {
                                if (!bMounting)
                                {
                                        Mouse.Hide();
                                        bIsDT = Chart.GetBaseFinance(leverange, valueTp, valueSl);
                                        valueTp = Terminal.AdjustPrice(valueTp * Terminal.GetAdjustToTrade() / leverange);
                                        valueSl = Terminal.AdjustPrice(valueSl * Terminal.GetAdjustToTrade() / leverange);
                                        m_TradeLine.SpotLight(MountName(def_IndicatorTicket0, IT_PENDING, EV_LINE));
                                        bMounting = true;
                                }
                                tp = price + (bKeyBuy ? valueTp : (-valueTp));
                                sl = price + (bKeyBuy ? (-valueSl) : valueSl);
                                UpdateInfosIndicators(0, def_IndicatorTicket0, price, tp, sl, leverange, bKeyBuy);
                                if ((bEClick) && (memLocal == 0)) CreateOrderPendent(leverange, bKeyBuy, memLocal = price, tp, sl, bIsDT);
                        }else if (bMounting)
                        {
                                UpdateInfosIndicators(0, def_IndicatorTicket0, 0, 0, 0, 0, false);
                                Mouse.Show();
                                memLocal = 0;
                                bMounting = false;
                        }else if ((!bMounting) && (bKeyBuy == bKeySell))
                        {
                                if (bEClick)
                                {
                                        bIsMove = false;
                                        m_TradeLine.SpotLight();
                                }
                                MoveSelection(price, mKeys);
                        }
                        break;

// ... Code ...
                case CHARTEVENT_OBJECT_CLICK:
                        if (GetIndicatorInfos(sparam, ticket, price, it, ev)) switch (ev)
                        {

// ... Code ...

                                case EV_MOVE:
                                        if (bIsMove)
                                        {
                                                m_TradeLine.SpotLight();
                                                bIsMove = false;
                                        }else
                                        {
                                                m_TradeLine.SpotLight(MountName(ticket, it, EV_LINE));
                                                bIsMove = true;
                                        }
                                        break;
                        }
                        break;
        }
}

Neler olduğunu anlamaya çalışalım. Makalenin sonunda nasıl yapılacağını ve gerçekte ne olacağını gösteren bir video bulunmaktadır. Ama önce anlamaya çalışalım.

Her bir göstergenin seçilmesine izin veren bir nesnesi vardır (hareket ettirilemeyen sonuç hariç). Buraya tıklamak gösterge çizgisini değiştirecektir (kalınlaşacaktır). Bu gerçekleştiğinde, nesnenin hareketine izin veren seçim nesnesinin dışında yeni bir tıklama yapana kadar fare hareketleri yakalanacak ve bu nesne için yeni bir konuma dönüştürülecektir. Fare düğmesini basılı tutmanın gerekli olmadığına dikkat edin: sadece bir kez tıklayın, sürükleyin ve ardından tekrar tıklayın.

Ancak gerçekte, işin sadece bir kısmı burada yapılır. Bize yardımcı olacak iki fonksiyon daha vardır. Hesaplanan değerleri görüntülemekten sorumlu olan biri yukarıda zaten görülmüştür; diğeri, emir veya eşik seviyesi hareket sistemini kullanırken Uzman Danışmanın bir sümüklü böcek gibi davranmasını sağlamaktan sorumludur: Aşağıda gösterilmektedir:

void MoveSelection(double price, uint keys)
{
        static string memStr = NULL;
        static ulong ticket = 0;
        static eIndicatorTrade it;
        eEventType ev;
        double tp, sl, pr;
        bool isPending;
                                
        string sz0 = m_TradeLine.GetObjectSelected();
        
        if (sz0 != NULL)
        {
                if (memStr != sz0) GetIndicatorInfos(memStr = sz0, ticket, pr, it, ev);
                isPending = OrderSelect(ticket);
                switch (it)
                {
                        case IT_TAKE:
                                if (isPending) ModifyOrderPendent(ticket, macroGetPrice(IT_PENDING), price, macroGetPrice(IT_STOP));
                                else ModifyPosition(ticket, price, macroGetPrice(IT_STOP));
                                break;
                        case IT_STOP:
                                if (isPending) ModifyOrderPendent(ticket, macroGetPrice(IT_PENDING), macroGetPrice(IT_TAKE), price);
                                else ModifyPosition(ticket, macroGetPrice(IT_TAKE), price);
                                break;
                        case IT_PENDING:
                                pr = macroGetPrice(IT_PENDING);
                                tp = macroGetPrice(IT_TAKE);
                                sl = macroGetPrice(IT_STOP);
                                ModifyOrderPendent(ticket, price, (tp == 0 ? 0 : price + tp - pr), (sl == 0 ? 0 : price + sl - pr));
                                break;
                }
        };
}

Ben buna taş fonksiyonu diyorum çünkü konumlandırma sisteminin yavaş olmasına neden olmaktadır. Eğer anlamadıysanız, vurgulanan noktalara bakın. Her biri C_Router sınıfının içerisinde bulunan ve işlem sunucusuna istek gönderen bir fonksiyondur, bu nedenle sunucunun yanıt vermesi şu veya bu nedenle biraz zaman alırsa (ve bu, gecikme nedeniyle her zaman olacaktır), konumlandırma sistemi az çok yavaş olacaktır, ancak sunucu hızlı yanıt verirse, sistem akıcı olacaktır veya daha doğrusu, çalışma daha sorunsuz gerçekleşecektir. Daha sonra bunu değiştireceğiz, çünkü bu sistem başka şeyler daha yapmamıza izin vermemektedir. Yine de, yavaş olsa da bu şekilde biraz daha güvenli bir şekilde çalışacağınızı aklınızda bulundurmalısınız (özellikle de fiyatların çok hızlı hareket edebileceği oldukça volatil hareketlerde çalışmayı sevenler için), ancak yine de eşiklerin atlama riskiyle karşı karşıya olacaksınız. Bunun bir yolu yok, bir şeylerin feda edilmesi gerekiyor. Sunucunun içerisinde tam olarak ne olacağını bilerek çalışmayı kabul edenler için Uzman Danışman bu noktada hazırdır. Ancak Uzman Danışmanın işleyişinde akışkanlık kazanmak isteyenler için sonraki makalelerde işler değişecek ve daha ilginç hale gelecektir.

Aşağıdaki video sistemin gerçekte nasıl çalıştığını göstermektedir, dolayısıyla grafikteki ve araç kutusundaki değerlere dikkat edin.


Sonuç

Artık ticaret için çok ilginç bir Uzman Danışmana sahibiz, buna rağmen nasıl çalıştığına alışmak için onu bir süre bir demo hesapta kullanmanızı tavsiye ederim. Çalışma şeklinde daha büyük değişiklikler olmayacağına söz veriyorum. Sadece iyileştirmeler olacaktır ve bir sonraki makalede, bir miktar güvenlik pahasına, Uzman Danışmanın eksik olduğu bazı şeyleri ekleyeceğiz. Her iki durumda da bu, ticaret sisteminin nasıl çalıştığını ve ihtiyacımız olan her türlü veri modellemesini elde etmek için platformu nasıl manipüle edeceğimizi öğrenmek için harika bir kaynak olacaktır.

Unutmayın, emirleri veya eşik seviyelerini taşımanın çok yavaş olduğunu fark ederseniz, makalede gösterdiğim noktaları kaldırabilir ve emirleri veya eşikleri taşımak için MetaTrader 5'in kendisini kullanabilirsiniz; Uzman Danışmanı ise verileri yorumlamaya yardımcı olmak için bir destek olarak kullanabilirsiniz. Bunu yapmak ya da yapmamak sizin seçiminiz...


MetaQuotes Ltd tarafından Portekizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/pt/articles/10516

Ekli dosyalar |
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 23): Yeni emir sistemi (VI) Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 23): Yeni emir sistemi (VI)
Emir sistemini daha akıcı hale getireceğiz. Bu makalede, pozisyon eşik seviyelerini çok daha hızlı değiştirebilmek için kodda yapılması gereken değişiklikleri ele alacağız.
Awesome Oscillator göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Awesome Oscillator göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
Serimizin bu yeni makalesinde, ticaretimizde faydalı olabilecek yeni bir teknik araç hakkında bilgi edineceğiz. Bu, Awesome Oscillator (AO) göstergesidir. Bu göstergeyi kullanarak bir ticaret sisteminin nasıl tasarlayacağını öğreneceğiz.
MQL5'te ONNX modelleri nasıl kullanılır? MQL5'te ONNX modelleri nasıl kullanılır?
Açık sinir ağı santrali (Open Neural Network eXchange, ONNX), makine öğrenimi modellerini temsil etmek için oluşturulmuş açık bir formattır. Bu makalede, finansal zaman serilerini öngörmek için bir CNN-LSTM modelinin nasıl oluşturulacağını ele alacağız. Ayrıca oluşturulan ONNX modelinin bir MQL5 Uzman Danışmanında nasıl kullanılacağını da göstereceğiz.
Relative Vigor Index göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Relative Vigor Index göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
En popüler teknik göstergelere dayalı ticaret sistemlerini nasıl geliştireceğimizi öğrendiğimiz serimizin yeni makalesindeyiz. Bu makalede Relative Vigor Index göstergesi üzerinde çalışacağız.