Simulink: Expert Advisor'ların Geliştiricileri için Bir Kılavuz

Denis Kirichenko | 15 Aralık, 2021


Giriş

Matlab'ın büyük imkanlarını açıklayan birkaç makale mevcut. Daha açık olmak gerekirse, bu yazılımın programcının bir Expert Advisor geliştirmek için kullandığı araçlarını genişletebilmesi. Bu makalemde, Simulink gibi güçlü bir matlab paketinin çalışmasını örneklemeye çalışacağım.

Yatırımcılar için otomatik alım satım sistemi geliştirmenin alternatif bir yolunu sunmak istiyorum. Yatırımcının karşılaştığı sorunun karmaşıklığı - otomatik alım satım sisteminin oluşturulması, doğrulanması ve test edilmesi - nedeniyle bu tür bir yönteme başvurmak için ilham aldım. Profesyonel bir programcı değilim. Ve bu nedenle, otomatik alım satım sisteminin geliştirilmesinde "basitten karmaşığa gitmek" prensibi benim için birincil öneme sahiptir. Benim için basit olan tam olarak nedir? Her şeyden önce, bu, sistemi oluşturma sürecinin ve işleyişinin mantığının görselleştirilmesidir. Ayrıca, minimum elle yazılmış koddur. Bu beklentiler, matematiksel hesaplamaların görselleştirilmesi için enstrümanlar arasında dünya lideri olan, tanınmış bir MATLAB ürünü olan Simulink® paketinin özellikleriyle oldukça tutarlıdır.

Bu makalemde, bir Matlab paketine dayalı otomatik alım satım sistemini oluşturup test etmeye çalışacak ve ardından MetaTrader 5 için bir Expert Advisor yazacağım. Ayrıca, geriye dönük test için tüm geçmiş veriler MetaTrader 5'ten kullanılacaktır.

Terminolojik karışıklığı önlemek için Simulik'te çalışan alım satım sistemini geniş kapsamlı bir MTS sözcüğüyle ve MQL5'te çalışan alım satım sistemini yalnızca Expert Advisor olarak adlandıracağım.


1. Simulink ve Stateflow'un temelleri

Spesifik işlemlere geçmeden önce, teorik minimum formunun bir türünü tanıtmamız gerekiyor.

MATLAB'ın bir parçası olan Simulink® paketi yardımıyla kullanıcı dinamik sistemleri modelleyebilir, simüle edebilir ve analiz edebilir. Ayrıca, sistemin yapısı hakkında soru sormak, onu simüle etmek ve sonra ne olduğunu gözlemlemek mümkündür.

Simulink ile kullanıcı sıfırdan bir model oluşturabilir veya halihazırda mevcut olan bir modeli değiştirebilir. Paket, ayrık, sürekli ve karma davranış temelinde oluşturulan doğrusal ve doğrusal olmayan sistemlerin geliştirilmesini destekler.

Paketin ana özellikleri geliştiricinin sitesinde sunulmaktadır:

Simulink ortamının hemen gözden geçirilmesiyle başlayalım. Bu, halihazırda açık olan bir Matlab penceresinden aşağıdaki yollardan ikisiyle başlatılır:

  1. Komut penceresinde Simulink komutu kullanılarak,
  2. Araç çubuğundaki Simulink simgesi kullanılarak.

Şekil 1. Simulink'i Başlatma

Şekil 1. Simulink'i Başlatma

Komut yürütüldüğünde, kitaplıklara gözatma penceresi (Simulink Kitaplık Tarayıcı) görünür. 

Şekil 2. Kitaplık Tarayıcı

Şekil 2. Kitaplık Tarayıcı


Tarayıcı penceresi, Simulink kitaplıkları bileşenlerinin bir ağacını içerir. Kitaplığın belirli bir bölümünü görüntülemek için onu fare ile seçmeniz yeterlidir, ardından kitaplığın aktif bölümünün bir dizi simge bileşeni Simulink Kitaplık Tarayıcı penceresinin sağ bölümünde görünecektir. Şekil 2'de, Simulink kitaplığının ana bölümü gösterilmiştir.

Tarayıcı menüsünü veya araç çubuğunun düğmelerini kullanarak yeni bir model oluşturmak veya mevcut bir modeli yüklemek için bir pencere açabilirsiniz. Simulink ile yapılan tüm çalışmaların, çıktıları modelleme programı tarafından sağlandığı sürece, işlemlerin yürütülmesini izlemenin mümkün olduğu açık bir MATLAB sistemi ile birlikte gerçekleştiğini belirtmeliyim.


Şekil 3. Simulink boş penceresi

Şekil 3. Simpulink boş penceresi


Öncelikle modelimizin birkaç parametresini değiştirelim. Simulation Configuration Parameters'ı açalım. Bu pencerede birçok parametre içeren bir dizi sekme bulunur. Simulink modelleme sistemindeki çözücünün parametrelerini ayarlayabileceğiniz varsayılan Çözücü sekmesiyle ilgileniyoruz.

Simülasyon zamanında, modelleme zamanı başlangıç zamanı - Başlangıç zamanı (genellikle 0) ve bitiş zamanı - Durma zamanı ile belirlenir.

Görevimiz için Başlangıç zamanına 1 değerini atayalım. Durma zamanını olduğu gibi bırakacağız.

Çözücünün seçeneklerinde ayrıca Türü Sabit adım, çözücünün kendisini ayrık olarak ve adımı (sabit adım boyutu) 1 olarak değiştirdim.

Şekil 4. Yapılandırma Parametreleri Penceresi


Simulink ortamı, sınırlı-durum otomatları teorisine dayalı, olay güdümlü bir modelleme paketi olan Stateflow alt sistemi tarafından başarıyla tamamlanır. Bu, olaylara yanıt olarak olayları ve eylemleri belirleyen bir kurallar zincirine dayalı olarak sistemin çalışmasını temsil etmemizi sağlar.

Stateflow paketinin grafik kullanıcı arayüzü aşağıdaki bileşenlere sahiptir:

Stateflow bölümünde yer alan en yaygın kullanılan blok diyagram (Grafik). O halde inceleyelim.

Bloğu kitaplıktan taşıyalım ve diyagramı açmak için üzerine çift tıklayalım. SF grafiği düzenleyicisinin boş bir penceresi görünecektir. Bu, gerekli işlevleri elde etmek için SF grafikleri oluşturmak ve bunların hatalarını ayıklamak için kullanılabilir.

Araç Çubuğu, sol tarafta dik konumda yer alır. 9 düğme vardır:

  1. Durum,
  2. Geçmiş Birleşimi,
  3. Varsayılan Geçiş,
  4. Bağlantı Birleşimi,
  5. Doğruluk Tablosu,
  6. İşlev,
  7. Gömülü MATLAB İşlevi,
  8. Kutu,
  9. Simulink İşlev Çağrısı.

Ne yazık ki, her öğeyi bu makale bağlamında ayrıntılı olarak ele almak imkansızdır. Bu nedenle, modelimiz için ihtiyaç duyacağımız bu öğelerin kısa bir açıklamasıyla kendimi sınırlayacağım. Daha ayrıntılı bilgi Matlab Yardım bölümünde veya geliştiricinin web sitesinde bulunabilir.

Şekil 5. SF grafiğinin düzenleyicideki görünümü

Şekil 5. SF grafiğinin düzenleyicideki görünümü

SF grafiklerinin anahtar nesnesi Durum'dur. Köşeleri yuvarlatılmış bir dikdörtgen ile temsil edilir.

Özel veya paralel olabilir. Her durum üst olabilir ve bunların mirasçıları olabilir. Durumlar aktif olabilir veya aktif olmayabilir, durumlar belirli prosedürleri uygulayabilir.

Geçiş, kavisli, oklu bir çizgi olarak temsil edilir; durumları ve diğer nesneleri birbirine bağlar. Kaynak nesne üzerinde sol fare düğmesiyle tıklayarak ve imleci hedef nesneye yönlendirerek geçiş yapılabilir. Geçişin, parantez içinde kaydedilen kendi koşulları olabilir. Geçiş prosedürü parantez içinde belirtilmiştir, koşul karşılanırsa yürütülecektir. Hedef nesnenin doğrulanması sırasında yürütülen prosedür, bir eğik çizgi ile gösterilir.

Alternatif düğüm (bağlantı birleşimi) bir daire şeklindedir ve her biri belirli bir koşulla tanımlanan farklı yollardan geçişe izin verir. Böyle bir durumda, belirtilen koşula karşılık gelen geçiş seçilir.

Stateflow prosedürel dilinin ifadelerini içeren bir akış grafiği olarak temsil edilen işlev. Akış grafiği, geçişlerin ve alternatif düğümlerin kullanımının mantıksal yapısını yansıtır.

Olay, Stateflow'un grafiksel olmayan nesneler grubuna ait başka bir önemli nesnesidir. Bu nesne, SF grafiğinin prosedürlerini başlatabilir.

Prosedür (eylem) de grafiksel olmayan bir nesnedir. İşlevi çağırabilir, belirli bir olay, geçiş vb. atayabilir.

SF modelindeki Veriler sayısal değerlerle temsil edilir. Veriler, grafik nesneleri olarak temsil edilmez. Model hiyerarşisinin herhangi bir düzeyinde oluşturulabilirler ve özelliklere sahiplerdir.

2. Alım Satım Stratejisinin Açıklaması

Şimdi, kısaca alım satımı ele alalım. Eğitim amaçlarımız için, Expert Advisor çok basit, hatta temel öğe olacaktır.

Otomatik alım satım sistemi, temel olarak, 21 ve 55 (Fibonacci sayıları) dönemiyle, kapanış fiyatlarının ortalaması alınarak Üstel Hareketlerin geçişinden sonra sinyal temelinde pozisyonlar açacaktır. Bu nedenle, EMA 21, EMA 55'i alttan keserse uzun bir pozisyon açılır, üstten keserse kısa bir pozisyon açılır.

Gürültü filtreleme için, 21/55 çaprazının ortaya çıkmasından sonra pozisyon, çubuğun açılış fiyatı ile K-th çubuğunda açılacaktır. EURUSD H1 üzerinde alım satım yapacağız. Yalnızca bir pozisyon açılacaktır. Yalnızca Kar Al veya Zararı Durdur düzeyine ulaşıldığında kapatılacaktır.

Otomatik alım satım sisteminin geliştirilmesi ve geçmiş geriye dönük testler sırasında, genel alım satım resminin bazı basitleştirmelerinin kabul edildiğini belirtmek isterim.

Örneğin, sistem bir sinyalin aracı yürütmesini kontrol etmeyecektir. Ayrıca alım satım kısıtlamalarını MQL5'te sistemin özüne ekleyeceğiz.


3. Simulink'te bir Alım Satım Stratejisini Modelleme

İlk olarak, geçmiş fiyat verilerini Matlab ortamına yüklememiz gerekiyor. Bunu, onları kaydedecek bir MetaTrader 5 script dosyası kullanarak yapacağız (testClose.mq5).

Matlab'da bu veriler (Açılış, Yüksek, Düşük, Kapanış, Spread) ayrıca basit bir m-script (priceTxt.m) kullanılarak yüklenecektir.

movavg'yi (standart Matlab işlevi) kullanarak Üstel Hareketli Ortalama dizileri oluşturacağız:

[ema21, ema55] = movavg(kapanış, 21, 55, 'e');

Çubuk dizinlerinin yardımcı dizisinin yanı sıra:

sayı=1:uzunluk(kapanış),

Aşağıdaki değişkenleri oluşturalım:

K=3, sl=0,0065, tp=0,0295,

Modelleme işlemine başlayalım.

Bir Simulink boş penceresi oluşturun ve kaydederken mts olarak adlandırın. Aşağıdaki eylemlerin tümü bir video biçiminde çoğaltılmıştır. Bir şey tam olarak net değilse, hatta hiç net değilse, videoyu izleyerek yaptığım işlemlere bakabilirsiniz.

Modeli kaydederken sistem aşağıdaki hatayı yazdırabilir:

??? "C:\\Simulink\\mts.mdl" dosyası, geçerli karakter kodlaması windows-1251 ile uyumlu olmayan karakterler içeriyor. Bu hatayı önlemek için aşağıdaki işlemlerden birini gerçekleştirin:
1) Geçerli karakter kodlamasını şunlardan biriyle değiştirmek için slCharacterEncoding işlevini kullanın: Shift_JIS, windows-1252, ISO-8859-1.
2) Desteklenmeyen karakterleri kaldırın. İlk desteklenmeyen karakter, satır 23, bayt ofset 15'tedir.

Bunu ortadan kaldırmak için tüm modellerin pencerelerini kapatmanız ve aşağıdaki komutları kullanarak kodlamayı değiştirmeniz gerekir:

bdclose all
set_param(0, 'CharacterEncoding', 'windows-1252');

Modelimizin bilgi kaynağını belirtelim.

Bu tür bilgi kaynağının rolü, açılış, maksimum, minimum ve kapanış fiyatlarını içeren MetaTrader 5'ten alınan geçmiş veriler olacaktır. Ayrıca, nispeten yakın zamanda dalgalanmaya başlamış olsa da, Spread'i dikkate alacağız. Son olarak, çubuğun açılış zamanını kaydediyoruz. Modelleme amaçları için, bazı ilk veri dizileri bir sinyal olarak, yani zaman içinde ayrık noktalarda bir zaman işlevinin değerlerinin bir vektörü olarak yorumlanacaktır.

Matlab çalışma alanından verileri almak için bir "FromWorkspace" alt sistemi oluşturalım. Simulink kitaplıkları tarayıcısında Bağlantı Noktaları ve Alt Sistemler bölümünü seçin. Fareyi kullanarak "Alt Sistem" bloğunu Simulink model penceresine sürükleyin. Alt Sisteme tıklayarak "FromWorkspace" olarak yeniden adlandırın. Ardından, giriş ve çıkış değişkenlerini ve sistem için sabitleri oluşturmak için bloktaki sol fare düğmesine çift tıklayarak oturum açın.

Kitaplık Tarayıcısında sinyal kaynakları oluşturmak için Sinyal İşleme Blok Kümesini ve kaynakları (Sinyal İşleme Kaynakları) seçin. Farenizi kullanarak "Çalışma Alanından Gelen Sinyal" bloğunu FromWorkspace modelinin alt sistem penceresine sürükleyin. Model 4 giriş sinyaline sahip olacağı için bloğu çoğaltıyoruz ve bunun 3 kopyasını daha oluşturuyoruz. Hangi değişkenlerin blok ile işleneceğini hemen belirleyelim. Bunu yapmak için, bloğa çift tıklayın ve değişken adını özelliklere girin. Bu değişkenler şunlar olacaktır: open, ema21, ema55, num. Blokları şu şekilde adlandıracağız: açık sinyal, ema21 sinyali, ema55 sinyali, num sinyali.

Şimdi "Sık kullanılan bloklar" Simulink bölümünden kanal oluşturmak için bir blok (Veriyolu Oluşturucu) ekleyeceğiz. Bloğu açın ve giriş sayısını 4 olarak değiştirin. Açık sinyal, ema21 sinyali, ema55 sinyali, num sinyal bloklarını Veriyolu Oluşturucu bloğunun girişlerine bağlayın.

Ayrıca, 5 tane daha giriş sabitimiz olacak. "Sabit" bloğu, "Sık kullanılan bloklar" bölümünden eklenir. Değer (Sabit değeri) olarak değişkenlerin adlarını belirtiyoruz: spread, yüksek, düşük, tp, sl:

Blokları şu şekilde çağıracağız: Spread dizisi, yüksek dizisi, düşük dizisi, Kar Al, Zararı Durdur.

"Bağlantı Noktaları ve Alt Sistemler" Simulink bölümünde çıkış bağlantı noktası bloğunu (Out1) seçin ve alt sistem penceresine taşıyın. Çıkış bağlantı noktasının 5 kopyasını alın. İlki, Veriyolu Oluşturucu bloğu ve diğerleri ile - dönüşümlü olarak, spread, yüksek, düşük, Kar Al ve Zararı Durdur bloklarıyla bağlanacağız.

İlk bağlantı noktasını fiyat olarak, diğerlerini ise çıkış değişkeninin adıyla yeniden adlandıracağız.

Alım satım sinyali oluşturmak için "Matematiksel İşlemler" Simulink bölümünden toplama bloğunu (Add) ekleyelim. Biz bunu emas diferansiyeli olarak adlandıracağız. Blok içinde c + + olan işaretlerin listesini + - olarak değiştireceğiz. Ctrl+ K tuş kombinasyonunu kullanarak bloğu saat yönünde 90° çevirin. ema21 sinyal bloğunu "+" girişine ve ema55 sinyalini "-" ile bağlayın. 

Ardından, Sinyal İşlemlerinin Sinyal İşleme Blok Kümesi bölümünden Delay bloğunu ekleyin. Bunu, K Delay olarak adlandıracağız. Bu bloğun Delay (örnekler) alanına K değişkeninin adını giriyoruz. Önceki blokla bağlayın.

Emas diferansiyel blokları ve K Delay, yalnızca değişikliğin olduğu modelleme aşaması için hesaplamalar için kontrol sinyalinin önünü (düzey farkı) biçimlendirir. Biraz sonra oluşturacağımız alt sistem, en az bir öğenin sinyal düzeyinde değişiklik olması durumunda devreye girecektir.

Daha sonra Simulink "Sık kullanılan bloklar" bölümünden çoğullayıcı ile ve (Mux) bloğu ekleyeceğiz. Benzer şekilde, bloğu saat yönünde 90 ° döndürün. Delay bloğunun sinyal çizgisini ikiye böleceğiz ve bunu çoğullayıcılara bağlayacağız.

Stateflow bölümünden bir Grafik bloğu ekleyin. Grafiği girin. 2 gelen olay (Buy ve Sell) ve 2 giden olay (OpenBuy ve OpenSell) ekleyin. Buy olayı için tetikleyici değeri (Tetikleyici), Falling olarak (alt sistemin negatif bir cephe tarafından etkinleştirilmesi) ve Sell olayları için Rising (alt sistemin pozitif bir cephe tarafından etkinleştirilmesi) olarak ayarlayacağız. OpenBuy ve OpenSell olayları için tetikleyici değeri (Tetikleyici), İşlev çağrısı (Çağrı) pozisyonu olarak (alt sistemin etkinleştirilmesi, verilen S-işlevinin çalışma mantığı tarafından belirlenecektir) ayarlayacağız.

Varsayılan olarak 3 alternatif düğüm ile bir geçiş oluşturacağız. İlk düğümü ikinci düğüme geçiş yaparak bağlayacağız, koşulları ve onlar için prosedürü Al {OpenBuy;} olarak ve üçüncüsü için prosedürü Sat {OpenSell;} olarak ayarlayacağız. Grafik girişini çoğullama ile ve iki çıkışı ilkinden kopyalanabilen başka bir çoğullama ile bağlayın. Son blok, benzerinden kopyalayacağımız ve Alış/Satış olarak adlandıracağımız çıkış bağlantı noktasına bağlanacaktır.

Neredeyse unutuyordum! Modelin düzgün çalışması için Matlab çalışma alanında yer alacak bir sanal kanal nesnesi oluşturmamız gerekiyor. Bunun için Araçlar menüsünden Veriyolu Düzenleyicisine giriyoruz. Düzenleyicide Veriyolu Ekle öğesini seçin. Bunu InputBus olarak adlandırın.

Öğeleri giriş değişkenlerinin adlarına göre ekleyin: open, ema21, ema55 ve num. Veriyolu Oluşturucuyu açın ve veriyolu nesnesi aracılığıyla Özellikleri belirt (Özellikleri veriyolu nesnesi aracılığıyla ayarlayın) yanındaki onay kutusunu işaretleyin. Yani, bloğumuzu oluşturduğumuz sanal kanal nesnesi ile bağladık. Sanal kanal, sinyallerin bellek dağılımı etkilenmeden yalnızca grafiksel olarak birleştirildiği anlamına gelir.

Alt sistem penceresindeki değişiklikleri kaydedin. Bu, FromWorkspace alt sistemiyle çalışmamızı sonlandırır.


Şimdi "Kara Kutu" oluşturmanın zamanı geldi. Bu, gelen sinyallere göre bir blok olacak, bilgileri işleyecek ve alım satım kararları verecektir. Elbette ki, bir bilgisayar programından ziyade bizim tarafımızdan oluşturulması gerekiyor. Sonuç olarak, sistemin hangi koşullar altında alım satım yapması gerektiğine yalnızca biz karar verebiliriz. Ayrıca, bloğun, tamamlanan yatırımlar hakkındaki bilgileri sinyaller şeklinde göstermesi gerekecektir.

İhtiyaç duyulan blok, Grafik olarak adlandırılır ve Stateflow bölümünde bulunur. Onun hakkında zaten bilgi vermiştik, değil mi? "Sürükle ve bırak" özelliğini kullanarak onu model penceremize taşıyoruz.

Şekil 6. Giriş alt sistemi blokları ve StateFlow grafiği

Şekil 6. Giriş alt sistemi blokları ve StateFlow grafiği


Grafiği açın ve verilerimizi grafiğe girin. İlk olarak, FromWorkspace alt sisteminde yaptığımız gibi bir kanal nesnesi oluşturalım. Ancak, bize çalışma alanından gelen sinyalleri sağlayan öncekinden farklı olarak, bu, elde edilen sonucu döndürecektir. Ve böylece, OutputBus nesnesini çağıracağız. Öğeleri şunlar olacaktır: barOpen, OpenPrice, TakeProfit, StopLoss, ClosePrice, barClose, Comment, PositionDir, posN, AccountBalance.

Şimdi oluşturmaya başlayacağız. Grafik penceresinde, varsayılan geçişi (# 1) görüntüleyeceğiz.

Koşullar ve prosedürler için şunları belirteceğiz:

[Input.num>=56 && Input.num>Output.barClose] {Output.barOpen=Input.num;i = Input.num-1;Output.posN++;}

Bu koşul, giriş çubuklarının sayısı en az 56 olduğunda ve giriş çubuğunun önceki konumun kapanış çubuğundan daha yüksek olacağı durumlarda verilerin işleneceği anlamına gelir. Ardından, açılış çubuğuna (Output.barOpen) gelen çubuğun numarası, i - indeks (0'dan başlayarak) indeks değişkeni tarafından atanır ve açık pozisyonların sayısı 1 değer artar.

2. geçiş yalnızca açık pozisyon ilk olmayacaksa gerçekleştirilir. Aksi takdirde, hesap bakiyesi değişkenine (Output.AccountBalance) 100000 değerini atayacak olan üçüncü geçiş gerçekleştirilir.

Grafik OpenBuy olayı tarafından başlatıldıysa 4. geçiş gerçekleştirilir. Böyle bir durumda, pozisyon alışa yönlendirilecek (Output.PositionDir = 1), açılış fiyatı spread (Output.OpenPrice = Input.open + spread [i] * 1e-5) dikkate alınarak açılış çubuk fiyatına eşit olacaktır. StopLoss ve TakeProfit çıkış sinyallerinin değerleri de belirtilecektir.

Bir OpenSell olayı meydana gelirse akış 5. geçişi takip edecek ve çıkış sinyalleri için değerlerini ayarlayacaktır.

Pozisyon uzun ise 6. geçiş gerçekleşir; pozisyon kısa ise akış 7. geçişe kadar devam eder.

8. geçiş, maksimum çubuk fiyatının Kar Al düzeyine ulaşıp ulaşmadığını veya minimum çubuk fiyatının Zararı Durdur düzeyine ulaşıp ulaşmadığını kontrol eder. Aksi takdirde, i indeks değişkeninin değeri bir değer artar (9. geçiş).

10. geçiş, Zararı Durdur'da ortaya çıkan koşulları doğrular: Çubuğun minimum fiyatı, Zararı Durdur düzeyini geçmiştir. Onaylanırsa, akış 11'inci geçişe ve ardından kapanış ve açılış pozisyonlarının fiyat farklarının değerlerinin, cari hesap bakiyesinin ve kapanış çubuğu indeksinin tanımlandığı 12'nci geçişe kadar devam edecektir.

10. geçiş onaylanmazsa, pozisyon Kar Al'da (13. geçiş) kapatılacaktır. Ve bunun ardından, 14'üncüden, akış 12'nci geçişe kadar devam edecektir.

Kısa pozisyon geçişleri için prosedür ve koşullar tam tersidir.

Son olarak, grafikte yeni değişkenler oluşturduk. Bunları otomatik olarak modelimize entegre etmek için "Simülasyonu Başlat" düğmesine tıklayarak modeli doğrudan grafik penceresinde çalıştırmamız gerekir. Bu, müzik çalarlardaki "Yürüt" düğmesine benzerdir. Bu noktada, Stateflow Sembol Sihirbazı (SF ana nesneleri) başlatılacak ve oluşturulan nesnelerin kaydedilmesini önerecektir. Tümünü Seç düğmesine basın ve ardından Oluştur düğmesine tıklayın. Nesneler oluşturuldu. Şimdi Model Tarayıcısını açalım. Solda, Model Hiyerarşisindeki Grafiğimize tıklayın. Nesneleri veri türüne (DataType) göre sıralayalım.

"Ekle" ve "Veri" menü komutlarını kullanarak daha fazla veri ekleyin. İlk değişkeni Giriş olarak adlandıracağız. Kapsamların değerini Giriş olarak ve Tür değerini "Veriyolu:<veriyolu nesne adı> . Ardından, daha önce oluşturulan InputBus kanalının adını doğrudan bu alana girin. Böylece Giriş değişkenimiz InputBus türünde olacaktır. Bağlantı noktasının değerini bir olarak ayarlayalım.

Aynı işlemi Çıkış değişkeni ile tamamlayın. Yalnızca Çıkış Kapsamı ve Çıkış Veri Yolu türüne sahip olmalıdır.

Yüksek, düşük, sl, tp ve spread değişkenlerinin kapsamını "Giriş" değeri olarak değiştirelim. Sırasıyla, bağlantı noktası numaralarını aşağıdaki sırayla ayarlayacağız: 3, 4, 6, 5, 2.

Ayrıca Lotlar değişkeninin kapsamını Sabit olarak değiştirelim. "Değer Öznitelikleri" sekmesinde, "Başlangıç" alanına (sağda) Giriş için 1, OpenBuy ve OpenSell olaylarını girelim.  Olaylarda, "İşlev çağrısı" için tetikleyici değerini değiştirin.

Sabit kapsamı ile bir len dahili değişkeni oluşturun. "Değer Öznitelikleri" sekmesinde, "Başlangıç değeri" alanına bir m-işlev uzunluğu gireceğiz (kapanış). Böylece, bu, Matlab çalışma alanında bulunan yakın dizinin uzunluğuna eşit olacaktır.

Yüksek ve düşük değişkenler için Boyut alanına [len 1] değerini gireceğiz. Böylece, bellekte yüksek ve düşük dizi boyutlarını [len 1] değeri olarak ayırmış olduk.

Ayrıca "Değer Öznitelikleri" sekmesinde K değişkeni için, "Başlangıç değeri" alanında (sağda) K'nin çalışma alanından alınan gerçek değişkenini belirtelim.

Sonuç olarak, 7 giriş bağlantı noktası ve bir çıkış bağlantı noktası olan bir Grafik alt sistemimiz var. Bloğu giriş olayları () bağlantı noktası en altta olacak şekilde konumlandıralım. "Pozisyon işleme" bloğunu yeniden adlandıracağız. Grafiğin kendisinde, bloğun adını da görüntüleyeceğiz. Uygun bağlantı noktaları aracılığıyla FromWorkspace alt sisteminin bloklarını ve "Pozisyon işleme" bloğunu birleştirin. Ve blokların rengini değiştirin.

"Pozisyon işleme" alt sisteminin yalnızca gelen OpenBuy veya OpenSell olayları tarafından "uyandırılması" durumunda çalışacağına dikkat edilmelidir. Bu şekilde, gereksiz hesaplamalardan kaçınmak için alt sistemin çalışmasını optimize ediyoruz.

Şekil 7. FromWorkspace ve Pozisyon işleme Alt Sistemleri


Şimdi, Matlab çalışma alanındaki işleme sonuçlarını yazdırmak için bir alt sistem oluşturmamız ve onu "Pozisyon işleme" alt sistemi ile birleştirmemiz gerekiyor. Bu, en kolay görev olacak.

Sonuçları çalışma alanına almak için bir "ToWorkspace" alt sistemi oluşturalım. "FromWorkspace" alt sistemini oluşturduğumuzda uyguladığımız adımları tekrarlayın. Kitaplık tarayıcısında, Simulink Bağlantı Noktaları ve Alt Sistemler bölümünü seçin. Fareyi kullanarak "Alt Sistem" bloğunu Simulink model penceresine sürükleyin. "Alt Sistem" bloğunun üzerine tıklayarak bunu "ToWorkspace" olarak yeniden adlandırın. Bloğu "Pozisyon işleme" alt sistemiyle birleştirin.

Değişkenleri oluşturmak için sol fare düğmesiyle bloğa çift tıklayarak giriş yapın.

Alt sistem sanal olmayan bir veriyolu olan OutputBus nesnesinden veri alacağı için bu kanaldan gelen sinyalleri seçmemiz gerekiyor. Bunu yapmak için, kitaplık tarayıcısında "Sık kullanılan bloklar" bölümünü seçiyoruz ve bir "Veriyolu Seçici" ekliyoruz. Blok, 1 giriş ve 2 çıkış sinyali içerecektir; oysa bu tür sinyallerden 10'una ihtiyacımız var.

Bloğu giriş bağlantı noktasına bağlayalım. "Simülasyonu başlat" düğmesine basın (bu, bizim "Yürüt" düğmemizdir). Derleyici, modeli oluşturmaya başlayacaktır. Bu, başarıyla oluşturulmayacaktır, ancak veri yolu seçme bloğu için giriş sinyalleri oluşturacaktır. Bloğa girersek pencerenin sol tarafında OutputBus aracılığıyla iletilen gerekli sinyallerin belirdiğini göreceğiz. "Seç" düğmesi kullanılarak tümünün seçilmesi ve bunların sağ tarafa "Seçilen sinyaller" bölümüne taşınması gerekir.

Şekil 8. Veriyolu Seçici blok parametreleri

Şekil 8. Veriyolu Seçici blok parametreleri


Simulink kitaplıkları tarayıcısının "Sık kullanılan bloklar" bölümüne tekrar başvuralım ve Mux çoğullama bloğunu ekleyelim. 10'a eşit olan giriş sayısını gösterir.

Ardından Simulink kitaplık Tarayıcısının "Sinks" bölümüne giriş yapın ve ToWorkspace bloğunu alt sistem penceresine taşıyın. Orada, "AccountBalance" değişkeninin yeni adını belirteceğiz ve "Yapı" olan çıktı biçimini (Kaydetme biçimi) "Dizi" olarak değiştireceğiz. Bloğu çoğullama ile birleştirin. Artık gerekli olmayacağı için çıkış bağlantı noktasını silin. Blokların rengini özelleştirin. Pencereyi kaydedin. Alt sistem hazır.

Modeli oluşturmadan önce, çalışma alanındaki değişkenlerin varlığını doğrulamalıyız. Şu değişkenler mevcut olmalıdır: InputBus, K, OutputBus, kapanış, ema21, ema55, yüksek, düşük, num, açılış, sl, spread, tp.

num (bitiş) değişkenini tanımlamak için Durma Zamanı değerini parametre olarak ayarlayalım. Yani, işlenen vektör, num dizisinin son öğesi tarafından belirlenen uzunluğa sahip olacaktır.

Bir model oluşturmaya başlamadan önce, aşağıdaki komutu kullanarak bir derleyici seçmemiz gerekir:

mex-kurulumu

Lütfen harici arayüz oluşturmak için derleyicinizi seçin (MEX) dosyaları:
Mex'in yüklü derleyicileri [y] / n bulmasını ister misiniz? y

Bir derleyici seçin:

[1] Lcc-win32 C 2.4.1, dizin: C:\PROGRA~2\MATLAB\R2010a\sys\lcc
[2] Microsoft Visual C++ 2008 SP1, dizin: C:\Program Files (x86)\Microsoft Visual Studio 9.0
[0] Yok

Derleyici: 2

Gördüğünüz gibi Microsoft Visual C ++ 2008 derleyici SP1'i seçtim.

Oluşturmaya başlayalım. "Simülasyonu başlat" düğmesine basın. Bir hata oluştu: Stateflow Arayüz Hatası: Bağlantı noktası genişliği uyuşmazlığı. "spread"(#139) girişi bir skaler bekliyor. Sinyal, 59739 öğeli tek boyutlu vektördür.

"spread" değişkeni double türünde olmamalı, bunun yerine türünü Simulink'ten gelen sinyalden devralmalıdır.

Model Tarayıcısı'nda bu değişken için "Devral: Simulink'e Benzer Şekilde" öğesini ve Boyut alanında ise "-1" öğesini belirtiyoruz. Değişiklikleri kaydedin.

Modeli tekrar çalıştıralım. Artık derleyici çalışıyor. Bu, bazı küçük uyarılar gösterecektir. Ve 40 saniyeden daha kısa bir sürede model yaklaşık 60.000 çubuk verisini işleyecektir. Alım satım işlemi '01.01.2001 00:00' ila '16.08.2010 11:00' zaman aralığında gerçekleştirilir. Toplam açık pozisyon miktarı 461'dir. Aşağıdaki klipte modelin nasıl çalıştığını görebilirsiniz.



4. Stratejiyi MQL5'te Uygulama

Böylece, otomatik alım satım sistemimiz Simulink'te derlendi. Şimdi bu alım satım fikrini MQL5 ortamına aktarmamız gerekiyor. Alım satım Expert Advisor'ımızın mantığını ifade ettiğimiz Simulink bloklarını ve nesnelerini ele almamız gerekti. Mevcut görev, alım satım sisteminin mantığını MQL5 Expert Advisor'a aktarmaktır.

Ancak, bazı blokların MQL5 kodunda bir şekilde tanımlanmış olması gerekmediğine dikkat edilmelidir; zira işlevleri gizlenebilir. Asıl kodda hangi satırın hangi blokla ilgili olduğu hakkında azami düzeyde ayrıntıya girerek yorum yapmaya çalışacağım. Bazen, bu ilişki dolaylı olabilir. Ve bazen blokların veya nesnelerin bir arayüz bağlantısını yansıtabilir.

Bu bölüme başlamadan önce, "Yeni Başlayanlar için MQL5'te Expert Advisor'lar Yazmak için Adım Adım Kılavuz" başlıklı bir makaleye dikkatinizi çekeceğim. Bu makale, MQL5'te bir Expert Advisor yazmanın ana fikirlerinin ve temel kurallarının kolayca kavranabilir bir tanımını sağlar. Ama şimdi bunlar üzerinde durmayacağım. Oradan bazı MQL5 kod satırlarını kullanacağım.

4.1 "FromWorkspace" Alt Sistemi

Örneğin, "FromWorkspace" alt sisteminde bir "açık sinyal" bloğumuz var. Simulink'te, geriye dönük test sırasında açılış çubuk fiyatını elde etmek ve alım satım sinyali alınması durumunda bu fiyattan bir pozisyon açmak için gereklidir. Bu blok MQL5 kodunda açıkça mevcut değildir; zira Expert Advisor alım satım sinyalini aldıktan hemen sonra fiyat bilgisini ister.

Expert Advisor'da hareketli ortalamalardan alınan verileri işlememiz gerekecek. Bu nedenle, onlar için dinamik diziler ve tanıtıcılar gibi karşılık gelen yardımcı değişkenler oluşturacağız.

int ma1Handle;  // Moving Average 1 indicator handle: block "ema21 signal"
int ma2Handle;  // indicator handle Moving Average 2: block "ema55 signal"

ma1Handle=iMA(_Symbol,_Period,MA1_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 1 indicator 
ma2Handle=iMA(_Symbol,_Period,MA2_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 2 indicator

double ma1Val[]; // dynamic array for storing the values of Moving Average 1 for every bar: block "ema21 signal"
double ma2Val[]; // dynamic array for storing the values of Moving Average 2 for every bar: block "ema55 signal"

ArraySetAsSeries(ma1Val,true);// array of indicator values MA 1: block "ema21 signal"
ArraySetAsSeries(ma2Val,true);// array of indicator values MA 2: block "ema55 signal"

Hareketli ema21 ve ema55'i bir şekilde etkileyen diğer tüm çizgiler yardımcı olarak kabul edilebilir.

"Kar Al" ve "Zararı Durdur", giriş değişkenleri olarak tanımlanır:

input int TakeProfit=135;   // Take Profit: Take Profit in the FromWorkspace subsystem
input int StopLoss=60;      // Stop Loss:  Stop Loss in the FromWorkspace subsystem
EURUSD için 5 önemli basamak olduğu dikkate alındığında, TakeProfit ve StopLoss değerinin şu şekilde güncellenmesi gerekecektir:
int sl,tp;
sl = StopLoss;
tp = TakeProfit;
if(_Digits==5)
 {
  sl = sl*10;
  tp = tp*10;
 }

"Spread", "yüksek" ve "düşük" dizileri, alım satım koşullarını tanımlamak için ilgili fiyat verilerinin bir matrisi biçiminde geçmiş verileri sağlamaktan sorumlu oldukları için değerlere hizmet etmek için kullanılırlar.

Kodda açıkça temsil edilmezler. Ancak, örneğin "spread" dizisinin, bir satış fiyatı akışı oluşturmak için gerekli olduğu iddia edilebilir. Diğer ikisi ise, belirli bir fiyat düzeyine ulaşıldığında MetaTrader 5'te otomatik olarak yürütüldükleri için kodda belirtilmeyen bir pozisyonu kapatmanın koşullarını belirlemek için gereklidir.

"Num sinyal" bloğu yardımcıdır ve Expert Advisor kodunda görüntülenmez.

"Emas diferansiyel" bloğu, farkları bularak kısa veya uzun pozisyon açma koşullarını kontrol eder. "K Gecikmesi", K değerine ortalama olan diziler için bir gecikme oluşturur.

Alış veya Satış olayı oluşturulur, bu, Pozisyon açma alt sistemi için bir giriş olayıdır.

Kodda, tamamı aşağıdaki gibi ifade edilir:

// event Buy (activation by the negative front)
bool Buy=((ma2Val[1+K]-ma1Val[1+K])>=0 && (ma2Val[K]-ma1Val[K])<0) ||
         ((ma2Val[1+K]-ma1Val[1+K])>0 && (ma2Val[K]-ma1Val[K])==0);

// event Sell (activation by the positive front)
bool Sell=((ma2Val[1+K]-ma1Val[1+K])<=0 && (ma2Val[K]-ma1Val[K])>0)||
         ((ma2Val[1+K]-ma1Val[1+K])<0 && (ma2Val[K]-ma1Val[K])==0);
Pozisyon açma alt sistemi, koşullar ve prosedürler kullanılarak "Pozisyon işleme" alt sisteminde işlenen "OpenBuy" ve "OpenSell" olaylarının kendisini oluşturur.

 

4.2 "Posizyon İşleme" Alt Sistemi

Alt sistem, OpenBuy OpenSell olaylarını işleyerek çalışmaya başlar.

Alt sistemin ilk geçişi için koşullardan biri, kodda bu tür koşulların kontrol edilmesiyle belirtilen 56 çubuktan az olmamasıdır:

if(Bars(_Symbol,_Period)<56) // 1st transition of the «Position handling»subsystem : condition [Input.num>=56]
      {
        Alert("Not enough bars!");
        return(-1);
      }

Geçiş için ikinci koşul: Açılış çubuğu sayısı kapanış çubuğu (Input.num; Output.barClose) sayısından fazla olmalıdır; yani pozisyon kapatılmıştır.

Bu, kodda şu şekilde belirtilmiştir:

//--- 1st transition of the «Position handling» subsystem: condition [Input.num>Output.barClose]

bool IsBought = false;  // bought
bool IsSold = false;    // sold
if(PositionSelect(_Symbol)==true) // there is an opened position
 {
   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
     {
      IsBought=true;  // long
     }
   else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
     {
      IsSold=true;    // short
     }
  }
// check for opened position
if(IsTraded(IsBought,IsSold))
 {
   return;
 }

//+------------------------------------------------------------------+
//| Function of the check for opened position                        |
//+------------------------------------------------------------------+
bool IsTraded(bool IsBought,bool IsSold)
  {
   if(IsSold || IsBought)
     {
      Alert("Transaction is complete");
      return(true);
     }
   else
      return(false);
  }

4. geçiş, uzun bir pozisyon açmaktan sorumludur.

Bu, şu şekilde temsil edilir:

// 4th transition procedures of the «Position handling» subsystem: open long position
 mrequest.action = TRADE_ACTION_DEAL;                                  // market buy
 mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // latest ask price
 mrequest.sl = NormalizeDouble(latest_price.bid - STP*_Point,_Digits);  // place Stop Loss
 mrequest.tp = NormalizeDouble(latest_price.bid + TKP*_Point,_Digits);  // place Take Profit
 mrequest.symbol = _Symbol;                                           // symbol
 mrequest.volume = Lot;                                              // total lots
 mrequest.magic = EA_Magic;                                          // Magic Number
 mrequest.type = ORDER_TYPE_BUY;                                       // order to buy
 mrequest.type_filling = ORDER_FILLING_FOK;                            // the specified volume and for a price, 
                                                                               // equal or better, than specified
 mrequest.deviation=100;                                             // slippage
 OrderSend(mrequest,mresult);
 if(mresult.retcode==10009 || mresult.retcode==10008) // request completed or order placed
    {
     Alert("A buy order has been placed, ticket #:",mresult.order);
    }
 else
    {
     Alert("A buy order has not been placed; error:",GetLastError());
     return;
    }

5. geçiş, kısa pozisyon açmaktan sorumludur.

Bu, şu şekilde temsil edilir:

// 5th transition procedures of the «Position handling» subsystem: open a short position
 mrequest.action = TRADE_ACTION_DEAL;                                  // market sell
 mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // latest bid price
 mrequest.sl = NormalizeDouble(latest_price.ask + STP*_Point,_Digits);  // place a Stop Loss
 mrequest.tp = NormalizeDouble(latest_price.ask - TKP*_Point,_Digits);  // place a Take Profit
 mrequest.symbol = _Symbol;                                          // symbol
 mrequest.volume = Lot;                                             // lots
 mrequest.magic = EA_Magic;                                         // Magic Number
 mrequest.type= ORDER_TYPE_SELL;                                      // sell order
 mrequest.type_filling = ORDER_FILLING_FOK;                           // in the specified volume and for a price, 
                                                                              // equal or better, than specified in the order
 mrequest.deviation=100;                                             // slippage
 OrderSend(mrequest,mresult);
 if(mresult.retcode==10009 || mresult.retcode==10008) // request is complete or the order is placed
    {
     Alert("A sell order placed, ticket #:",mresult.order);
    }
 else
    {
     Alert("A sell order is not placed; error:",GetLastError());
     return;
    }

Uygun prosedürler (durdurmaların etkinleştirilmesi veya bir Kar Al düzeyine ulaşılması) MQL5'te otomatik olarak gerçekleştirildiği için alt kategorilerdeki diğer geçişler Expert Advisor'da açıkça sunulmaz.

Görevi çıktıyı Matlab Çalışma Alanlarına sunmak olduğu için "ToWorkspace" alt sistemi MQL5 kodunda temsil edilmez.


Sonuçlar

Örnek olarak basit bir alım satım fikri kullanarak, Simulink'te geçmiş veriler üzerinde geriye dönük bir test yaptığım otomatik alım satım sistemini oluşturdum. İlk başta şu soru beni rahatsız etti: "MQL5 kodu aracılığıyla bir alım satım sistemini hızlı bir şekilde uygulayabildiğiniz zaman, tüm bu yaygaraya karışmanın bir anlamı var mı?"

Elbette ki, bunu, sistemi oluşturma sürecinin ve çalışmasının mantığının görselleştirilmesi olmadan yapabilirsiniz. Ancak, bu çoğu kez, yalnızca deneyimli programcılar veya yalnızca yetenekli kişiler içindir. Alım satım sistemi yeni koşullar ve işlevlerle genişlediğinde, blok diyagramın varlığı ve çalışması açıkça yatırımcının görevi olacaktır.

Simulink dil özelliklerini MQL5 diliyle karşılaştırmaya çalışmadığımı da belirtmek isterim. Ben yalnızca bir blok tasarımı kullanarak otomatik bir alım satım sistemini nasıl oluşturabileceğinizi gösterdim. Belki gelecekte, MQL5 geliştiricileri, Expert Advisor yazma sürecini kolaylaştıracak görsel bir strateji oluşturucu oluşturacaktır.