İşlem Geçmişine Dayalı Alım Satım Oynatıcısı

Mykola Demko | 16 Aralık, 2021


Bir Kez Görmek İki Kez Duymaktan İyidir

Alım satım geçmişinin görsel analizi, al sat yapan kişinin analitik çalışmasının önemli bir parçasıdır. Öyle olmasaydı rakamları görsellere dönüştüren hiçbir teknik analiz olmazdı. Bunun sebebi insanın algılama işleminin %80'inin gözlerle yapılmasıdır. Bilgileri genelleştiren istatistikler pek çok ayrıntıyı veremez. Ve sadece rakamların sezgisel olarak algılanmasıyla yapılan görselleştirme ile bütün ayrıntılar tamamlanabilir. Bir kez görmek iki kez duymaktan daha iyidir derler.

Bu yazıda alım satım geçmişinin görselleştirmesinin otomasyonuna yönelik bir Uzman Danışmanın nasıl yazılacağını ele almayacağız. Nesneler arasındaki bilgi geçişi, büyük uygulamaların planlanması, grafiklerin yönetilmesi, farklı sembollerin bilgilerinin senkronize edilmesi vb. soruları ele alacağız.

İlk olarak size oynatıcı uygulamasının ve ilgili komut dosyasının faydalarından bahsetmek istiyorum, daha sonra kod analizine geçeceğiz.


MetaTrader 5 Strateji Test Edicide İşlemleri Çalıştırma

Oynatıcının çalışmasında MetaTrader 5 HTML raporu temel alınmıştır. Böylece Otomatik Alım Satım Şampiyonası 2010'un geçmişi gerekli bir ATC-2010 hesabına giriş yapılarak ve alım satım geçmişi bir HTML raporu olarak kaydedilerek elde edilebilir.

Otomatik Alım Satım Şampiyonası 2008 sunucusu durdurulduğu için bunu aynı şekilde yapamıyoruz. Sitede tek bir zip arşivi olarak paketlenmiş tüm yarışmacıların genel bir raporu bulunur. Automated_Trading_Championship_2008_All_Trades.zip

“Automated Trading Championship 2008 All Trades.zip” arşivi MetaTrader 5 kurulum dizininin \Files klasöründe açılmalıdır.

Otomatik Alım Satım Şampiyonası 2008'in geçmişini analiz etmek için geçmişi ayrıştıracak, belirtilen oturum açma için bir seçim yapacak ve ikili dosyaya kaydedecek MT4 Rapor Ayrıştırıcı komut dosyasını çalıştırmanız gerekir Bu ikili dosya Oynatıcı Raporu Uzman Danışmanı tarafından okunur.

Oynatıcı Raporu Uzman Danışmanı belirtilen gerekli oturum açma bilgileriyle strateji test edicide çalıştırılmalıdır. Test bittiğinde HTML formatında bir rapor kaydedin. Belirtilen oturum açma test sonucunu etkilemez, ancak raporda “oturum açma bilgisi” bir girdi parametresi olarak görüntülenecektir. Bu raporların daha iyi anlaşılmasını sağlar. Raporlar aynı Uzman Danışman tarafından oluşturulduğu için bunlara varsayılandan farklı adlar verilmesi önerilir.

Ayrıca MT4 Rapor Ayrıştırıcı komut dosyası geçmişini görmek istediğiniz bir yarışmacının oturum açma bilgilerini belirtmeniz gereken “oturum açma” girdi parametresine sahiptir. Bir yarışmacının oturum açma bilgilerini bilmiyorsanız ancak takma adı biliyorsanız komut dosyasını oturum açma değeri sıfır (varsayılan) olacak şekilde başlatın. Bu durumda komut dosyası oturum açarak bir seçim yapmaz; sadece tüm oturum açmaların alfabetik sırayla listelendiği bir csv dosyası oluşturacaktır. Dosyanın adı şöyledir: “Automated Trading Championship 2008 All Trades_plus” Bu dosyada gerekli bir katılımcı bulur bulmaz belirtilen oturum açma bilgisi ile komut dosyasını bir kez daha çalıştırın.

Böylece, MT4 Rapor Ayrıştırıcı komut dosyası ve Oynatıcı Raporu Uzman Danışmanı, alım satım geçmişi temelinde MetaTrader 5 Strateji Test Edicinin standart html raporunu MetaTrader 4 formatında oluşturur.

Oynatıcı Raporu Uzman Danışmanı işlemleri tam olarak gerçekte yapıldığı gibi gerçekleştirmez fakat buna benzer bir yol uygular. Bunun nedenleri farklı fiyat teklifleri, raporda zamanın dakikaya yuvarlanması ve uygulama sırasındaki kaymalardır. Çoğu durumda fark birkaç puandır ve bu da işlemlerin %10'unda gerçekleşir. Ancak, örneğin strateji test edicideki kârı ~ 170 binden ~ 160 bine düşürmek yeterlidir. Her şey kayma ve yapılan işlemlerin hacmine bağlıdır.


Oynatıcının Çalışması

Daha önce bahsettiğim gibi, oynatıcı ek uygulamalar kullanarak Otomatik Alım Satım Şampiyonası 2008 alım satım geçmişini izlemek için kullanabilir ve Automated Trading Championship 2010 doğrudan izlenebilir.

Ek olarak, oyuncu tüm MetaTrader 5 raporlarını destekler, böylece strateji test edicide çalıştırılan herhangi bir Uzman Danışmanın işlem geçmişini veya test edici tarafından biçimlendirilmemiş ancak “Toolbox” penceresinin “History” sekmesi üzerinden bir rapor olarak kaydedilmiş manuel alım satım geçmişini izleyebilirsiniz.

Alım Satım Geçmişi Oynatıcısı exp v5 Uzman Danışmanının Parametreleri:

MetaTrader 5 Strateji test edicinin bir raporu, işlem geçmişinin oynatıcısı için girdi dosyası olarak kullanılır. Alım Satım Geçmişi Oynatıcısı exp v5 EA “strateji test edici raporunun html dosyasının adı” olarak giriş parametresi şeklinde belirtilmesi gereken bir rapor dosyasının adıdır. Oynatıcıyı başlatırken kullanıcı “geçmiş başlangıcı” ve “geçmiş sonu” girdi değişkenlerinde bir oynatma periyodu belirleyebilir.

Bu değişkenler ayarlanmazsa oynatıcı bunları ilk işlemden başlayıp son işleme kadar verilerin yer aldığı alım satım geçmişinden alacaktır. Alım satım için kullanılan sembollerin sayısı bir fark yaratmaz. Yalnızca hesaptaki ilk ve son işlemin zamanı dikkate alınır.

Buna ek olarak bir kullanıcı, grafikleri analiz edilmesi gereken sembollerin isimlerini belirleyebilir. İsimler “gerekli grafikler listesi” değişkeninde bir döküm olarak belirtilmelidir. Bu değişkenin analizi büyük ve küçük harf ile ayırıcı türüne duyarlı değildir. Değişken ayarlanmazsa hesapta işlem gören tüm semboller açılır. Bazen bunların sayısı fazladır.

Örneğin, Manov alım satımda 12 para birimi çifti kullandı. Bir seferde dörtten fazla sembol ayarlamamanızı öneririm. İlk olarak, bunları düzenlemek kolaydır; ikinci olarak da birçok grafik oynatma hızını yavaşlatır. Her sembol genel döngüde işlendiği için sembol sayısının artması tik oluşumunun yavaşlamasına yol açar.

Oynatıcı alım satımda kullanılmayan bir sembol belirtseniz bile çalışacaktır. Bu durumda grafik herhangi bir işlemi göstermez, tıpkı diğer grafikler gibi hareket eder. Buna ek olarak eklenmiş bakiye göstergesine sahip olacaktır ancak varyantlarının herhangi birinde yalnızca genel bakiyenin geçmişini gösterecektir.

“EA'yı silerken grafikleri de sil” parametresinin tanımını bilerek atladım. Bu durum Uzman Danışmanın yönetimiyle değil davranışıyla ilgilidir. Buradaki husus Uzman Danışmanın çalışmak için birçok bilgiyi analiz etmesidir. EA'nın sahip olduğu bazı bilgilerin dosya biçiminde bir analiz için yararlı olacağına karar verdim. Uzman Danışman her bir sembol için alım satım işlemlerini içeren csv dosyaları ve tüm sembollerin senkronize bakiyelerini içeren bir dosya oluşturur; bu işlem çoklu para birimi sepetindeki bir sembolü tespit etmek için faydalı olabilir.

Aynı değişken Uzman Danışman tarafından otomatik olarak açılan grafiklerin silinmesi için de kullanılır. Genellikle EA çalışma yerini işlemin sonunda temizlemelidir. Ancak bir kullanıcı EA kontrolü olmadan bir grafiği yakından analiz etmek isterse EA'yı “EA'yı silerken grafikleri de sil” parametresini “false” değerine ayarlayarak başlatmalıdır..

Aşağıdaki parametreler çok önemli değildir.

Üreticinin periyodu tik üreticinin ilk parametresini ayarlar. Buradaki "tik" terimi klasik anlamında kullanılmamaktadır; seviye değişimi anlamına gelir. Uzman Danışmanda tikler çubukların dört noktasına göre oluşturulur. “Üreticinin periyodu” parametresi üreticinin başlangıç durumunu ayarlar. Ayrıca oynatıcı çalışırken bu parametreyi değiştirebilirsiniz.

Neden M1'den başlayarak tüm periyotları üretmiyoruz? Üreticinin periyodunu neden değiştirmemiz gerekiyor? Mesele şu ki, daha büyük zaman dilimlerinin çubukları çok sayıda M1 çubuğu içerir, bu nedenle üretim sürecini hızlandırmamız gerekebilir. Bu nedenle periyot değiştirme imkânından yararlanılmaktadır. Üreticide tüm zaman dilimleri değil, yalnızca bazı dilimler uygulanır. Kod içinde bunu değiştirmenin yolu daha sonra açıklanacaktır.

“İşlemlere yapılan yorumların yazı tipi” parametresi örneğin, işlemlere yapılan yorumlar, işlemlerin görüntülenmesini engellediğinde yararlı olabilir. Boyutu 1 olarak ayarlarsanız yazı ince bir çizgi gibi görünür ve görüntülemeyi engellemez. Bu işlemden sonra araç ipucundan nesne adını öğrenirken “Nesnelerin listesi” sekmesinde işlemin hacmini ve pozisyonu görebileceksiniz.

Alım satım geçmişi ayrı işlemlerle çizilir ancak çizilen çizgi pozisyonun türüne bağlıdır.

“Satın alma işlemlerinin rengi” ve “satış işlemlerinin rengi”ni kullanarak istediğiniz renkleri ayarlayabilirsiniz.

Alım satım geçmişinin görüntülenmesi

Yukarıdaki ekran görüntüsünde pozisyon seviyesinin genellikle işlem seviyesinden farklı olduğunu görebilirsiniz.

Ancak kâr pozisyon düzeyine göre hesaplanır. Bu yüzden pozisyonu bir trend çizgisi ile göstermeye ve pozisyon seviyelerini birleştirmeye karar verdim ve dikey bir çizgi kullanarak işlem yaptım. Pozisyon düzeyine yakın yorum aşağıdaki bilgileri içerir:

[deal volume|position volume]

Eğer işlem türü pozisyon türüne uymuyorsa (örneğin kısmi bir kapanış varsa) hacimler ek işaretlerle görüntülenecektir:

[<deal volume>|position volume]

İlk etapta işlem hacmini işlem raporunda görüntülendiği şekliyle görebilirsiniz; pozisyon hacmi önceki pozisyon durumu ve işlem tarafından yapılan değişikliklere dayanılarak hesaplanır.

“Hız sayısı” parametresi oynatma hızını düşürme adımlarının sayısını düzenler. Oynatıcı maksimum hızda başlatılır. Ayrıca oynatma hızını “hız sayısı” parametresinin değeri dahilinde azaltıp arttırabilirsiniz. Böylece hız düğmesi ve üreticinin periyodu, alım satım geçmişinin oynatılma hızını yönetmeye ilişkin eksiksiz bir araç yelpazesi oluşturur.

Ve son parametre de “ilerleme düğmesinin dikey boyutu”dur. Bunun ilerleme çubuğunun düğmelerinin büyük olmasını tercih eden kullanıcılar için yaptım. Genel olarak amacım grafiğin kontrollerin ardına gizlenmesini engellemekti. Bu nedenle “ilerleme düğmesinin dikey boyutu” parametresi 8 olarak ayarlanmıştır.

Şimdi de oynatıcının kontrollerine geçelim.

Oynatıcının kontrolleri

Hız, sol ve sağ oklar kullanılarak kontrol edilir. Kontrol modu orta (kare) düğmenin durumuna bağlı olarak çalışır. Basılmamış durumda hızı değiştirir, basılı durumdaysa üreticinin periyodunu değiştirir.

Bakiye göstergesini kontrol etme nesnesi tam bir oval şeklinde görüntülenir ancak aslında görsel boyutunun sınırlarını büyük ölçüde aşan iki büyük düğmeden yapılmıştır. Sol düğme tabloya bakiye göstergesi eklemek ve bunları tablodan silmek içindir ve sağ düğme de veri içeriğini kontrol eder.

“Tümü” durumuna geçildiğinde hesabın toplam bakiyesi ile ilgili bilgiler görüntülenir; “Toplam” durumu göstergenin çalıştırıldığı grafik sembolüne ilişkin bir bakiye örneğini görüntülemek için tasarlanmıştır. Göstergenin eşzamanlı olarak kontrol edilemez, bu da göstergenin bir grafikte çalıştırılabilirken diğerinde çalıştırılamayacağı anlamına gelir. 

Bakiye göstergesi

Denge göstergesini kontrol etme nesnesi grafiklerin senkronizasyonunda tek istisnadır, kontrollerin diğer tüm nesneleri senkronize edilirken bu edilmez. Başka bir deyişle, bir sembol için yapılan değişiklikler diğer sembollerde otomatik olarak yapılır.

Oynat/durdur, bastığınız anda hangi işlemin gerçekleştirileceğini görüntüler. Oynatma sırasında eğer basarsanız işlemin duraklatılacağını gösteren iki küçük çizgi görüntülenir. Tam tersi durumdaysa üçgen duraklatılmış durumda görüntülenir. Yani bastığınızda oynatıcı çalışmaya başlayacaktır.

İlerleme çizgisi tetikleyici olarak çalışan 100 kontrol düğmesinden oluşur; bir düğme basılı durumdayken diğer tüm düğmelere basılı olmayan konuma geçer. 100 adet düğme olduğu için oynatma periyodu 100 parçaya bölünmüştür. Çubuk sayısı 100'e bölünemezse kalan parça son kısma eklenir. Bu nedenle ayarlar “geçmiş başlangıcı” ve “geçmiş sonu” parametrelerini içerir. Bu parametreleri değiştirerek ihtiyaç duyulan geçmiş periyoda gidebilirsiniz.

Bir düğmeye basarak kullanıcı dâhili tik üreticinin tarihini değiştirir ve sıfır çubuğuna gider. Eğer bir düğmeye basılmazsa ancak üreticinin dâhili zamanı aktif düğmenin dışına çıkmışsa oynatıcı ilgili değişimi kendi başına gerçekleştirecektir.

Böylece “ilerleme çizgisi” nesnesi hem ilerlemenin göstergesi hem de navigasyonun aktif kontrolü olarak kullanılır. Oynatıcının kontrol nesneleri otomatik olarak gizlenir ve grafiğin ortasına doğru genişletilir; dolayısıyla ilerleme çizgisinin belirli bir düğmesine basmanız gerekiyorsa grafiği tam ekran yapın.

Şimdi oynatıcı tarafından yönetilen grafiklerin davranışından bahsedelim. Oynatıcı tüm grafiklerin senkronizasyonunu yapar ancak bu işlem ana grafikte yapılan herhangi bir ölçek, grafik türü, renk şeması, sıfır çubuğunun kayması vb. değişikliğinin diğer grafiklerde de tekrarlandığı anlamına gelmez.

Değişiklikler zaman diliminin değiştirilmesini kapsar. Burada oynatıcının ana grafik olarak kabul ettiği grafiğin mavi aktivite çizgisine sahip olan değil de kontrollerin görüntülendiği grafik olduğuna dikkat etmeliyiz. Bu genellikle tek ve aynı grafiktir ancak her zaman böyle olmaz. Bir grafiği etkinleştirmek için grafik alanında üzerine tıklayın.

Oynatıcıyı kullanma özelliği mevcuttur. Aynı alanda iki nesne varsa düğmeler çalışmayı durdurur. Bu nedenle bazen teklif çizgisi oynatıcı alanını geçtiğinde bir düğmeye basmak için başka bir grafiğe geçmeniz veya grafiğin dikey ölçeğini değiştirmeniz gerekir.



İlgili video ATC 2010 katılımcılarından biri olan Manov'un alım satım işleminin oynatılmasını gösterir. Bunu yapmak için login=630165 ve password=MetaTrader parametrelerini kullanarak müşteri terminalindeki hesabına bağlandım. Alım satım raporu, terminal_data_folder\MQL5\Files klasörüne ReportHistory-630165.html adı altında kaydedilmiştir. Bu dosyayı arşiv olarak indirebilir ve belirtilen klasörde açabilirsiniz.


Başlamaya Hazırlanma

  1. Her şeyin çalışması için player_history_trades.zip dosyasını indirin ve terminal_data_folder/MQL5/Indicators klasöründe açın.
  2. Kopyalanan Alım Satım Geçmişi Oynatıcısı klasörünü açın ve derleyin. Dosyaların derlenme sırası önemli değildir.
  3. Alım satım raporundaki tüm semboller için gerekli geçmiş periyodunun М1 zaman diliminde olduğundan emin olun. Bunu yapmak için M1 zaman diliminde gerekli grafiği manuel olarak açın, dikey bir çizgi yerleştirin ve bağlam menüsünün Ctrl+B tuş kombinasyonunu kullanarak Nesneler listesini açın. Ardından dikey çizginin tarihini alım satımın başlama tarihi yapın.
  4. Daha sonra da “Göster” düğmesine basın. Eğer fiyat teklifi yoksa bunun iki nedeni olabilir. Ya indirilmediler ya da “Grafikteki maksimum çubuk” parametresi çok küçük. Görmek için Tools->Options->Charts seçeneğine gidin.

Artık her şey çalışmalı.


Geliştirmeye Başlama

Bir uygulama geliştirmek için üzerinde çalıştıkça bir blok diyagrama ve sonra da koda dönüşen bir planınız olmalıdır. Ancak projenin kendisi daha erkenden planlanır. Herhangi bir projenin başlangıç noktası kullanıcının ihtiyaç duyduğu uygulama özellikleridir. Peki alım satım geçmişi oynatıcısı hangi özelliklere sahip olmalıdır? 

  1. Çoklu para birimli olmak.
  2. Gerekli grafikleri otomatik açmak.
  3. Kullanışlı gezinti arayüzü ve geçmişi her iki yöne kaydırma imkanı.
  4. Tüm grafiklerde senkronize görüntüleme.
  5. Oynatmayı Başlatma/Duraklatma.
  6. Görüntülenen grafiklerin sayısını ve sembollerini (ve varsayılan modu) seçme imkânı.
  7. Oynatıcının çalışacağı bir periyodu (ve varsayılan modu) seçme imkânı.
  8. Bir grafik üzerinde işlemlerin geçmişinin görüntülenmesi.
  9. Bakiye ve öz sermaye geçmişinin görüntülenmesi.
  10. Bir sembolün bakiyesinin (öz sermaye) ve bir hesabın toplam bakiyesinin (öz kaynak) ayrı görüntülenmesi.

İlk dört madde genel konsepti belirler. Diğer özellikler yöntemlerin uygulanma yönünü belirler.

Oynatıcının genel çalışma planı:

  1. Bir HTML raporu yükleme;
  2. İşlemlere ayrıştırma ve pozisyon geçmişini geri yükleme;
  3. İşlemleri açılış veya kapanış için bir emir kuyruğu olarak hazırlama:
  4. Bir kullanıcı komutunda göstergeler (öz sermaye çizelgeleri, düşüşler, vb.) şeklinde gerekli oranların hesaplanması ile işlem geçmişinin dinamiklerini görüntülemeye başlama;
  5. Diğer oranları içeren grafikteki bir bilgi panelinin görüntülenmesini düzenleme.

Ayrıca bir MetaTrader 4 raporuna göre strateji test edicide işlem yapmak için özel bir Uzman Danışman gereklidir:

  1. Ayrıştırılan işlemler Uzman Danışman için ikili veri dosyası olarak yazılmalıdır;
  2. MetaTrader 5 Strateji Test Edici raporunu oluşturun.

Bu, geliştirmeyi başlatmaya ilişkin gereksinimlerin ayrıntılarının bulunduğu genel bir şemadır. Buna sahipseniz konseptten fonksiyonelliğin uygulanmasına kadar kodun yukarıdan aşağıya yazılmasını planlayabilirsiniz.

Makaleyi uzatmamak adına kodun sadece en önemli kısımlarını anlatacağım. İyi yorumlandığı için kodu okurken herhangi bir sorunla karşılaşmamalısınız.


Emirler ve İşlemler

Şu anda iki adet alım satım kavramı vardır. MetaTrader 4'te kullanılan eski kavram ile gerçek teklif verme için kullanılan ve MetaTrader 5'te yer alan "netleştirme" kavramı. Aralarındaki farkın ayrıntılı açıklaması MetaTrader 5’te Emirler, Pozisyonlar ve İşlemler makalesinde verilmiştir.

Sadece önemli bir farkı anlatacağım. MetaTrader 4'teki bir emir açılış zamanı, açılış fiyatı ve işlem hacmi hakkındaki bilgileri saklayan bir kutu olarak ifade edilebilir. Ve bu kutunun kapağı açıkken aktif alım satım durumundadır. Kutunun kapağı kapanır kapanmaz kutudaki tüm bilgiler geçmişe taşınır.

MetaTrader 5'teki pozisyonlar bu tür kutular olarak kullanılır. Ancak aradaki önemli bir fark pozisyonların geçmişinin olmamasıdır. Sadece emirlerin ve işlemlerin geçmişi vardır. Tarih pozisyonların geçmişini geri yüklemek için gerekli tüm bilgileri içermesine rağmen bu fikri yeniden düzenlemek için biraz zaman harcamanız gerekir.

Sırasıyla ORDER_POSITION_ID ve DEAL_POSITION_ID tanımlayıcılarını kullanarak seçilen bir emir veya işlemin hangi pozisyona ait olduğunu öğrenebilirsiniz. Böylece geçmişi MetaTrader 5'e uygun bir formata dönüştürmek için MetaTrader 4 geçmişinin emirlerini açılış ve kapanış işlemleri olacak şekilde iki ayrı işleme böleceğim.


HTML Ayrıştırıcı

Bilgisayar terimlerine aşina olmayanlar için ayrıştırma kelimesinin ne anlama geldiğini anlatacağım. Ayrıştırma işlemi bir metnin veya herhangi bir sözcükbirim dizisinin (semboller, kelimeler, baytlar, vb.) sözdizimsel (dilbilgisel veya sözlüksel) analizi anlamına gelir; giriş metninin belirli bir dilbilgisine göre uygunluğunu kontrol eder ve daha fazla hesaplama ve dönüşüm yapabileceğiniz bir ayrıştırma ağacı oluşturur.

Ayrıştırıcıda iki büyük sınıf olan CTable ve CHTML kullanılır. CTable sınıfının kullanımı MQL5'te Elektronik Tablolar makalesinde detaylı olarak anlatılmıştır, o yüzden bunu tekrar anlatmayacağım.

HTML'yi ayrıştırmak için CHTML sınıfını geliştirdim. İlk fikrime göre sınıfın tanımı bir makale haline gelmeliydi. Ama sınıf bir makale yazmak için fazla basit, bu yüzden onun kısa bir tanımını vereceğim.

Sınıfın genel kavramı “etiket” terimi ile tanımlanabilir. Bir etiket muhafazalı bir fonksiyon olarak ifade edilebilir. Örneğin, Tag(header,casket) dediğimizde buradaki “header” (başlık) etiket başlığıdır (sayfanın görünümünü kontrol eden etiket değişkenleri genellikle burada belirtilir) ve “casket” (kutu) ise etiket kapsayıcısının içeriğidir. Bu tür etiketler tüm HTML dilini barındırır.

Sınıfın genel yapısı üç aşamalı bir nesne çağrısı olarak ifade edilebilir. CHTML sınıfının örneği içeriğindeki tüm olası etiketlerin nesnelerini oluşturur. Etiketlerin fonksiyonları bir şablon tarafından oluşturulur ve birbirlerinden yalnızca adları ve iki bayrağın ayarları açısından farklıdır.

Bir bayrak başlığın varlığını diğeri ise kutunun varlığını belirler. Bu bayraklar tüm etiketlerin ortak bir yapı ile sunulmasına izin verir. Her etiket örneği kendi içeriğinde CTegs sınıfının bir örneğini oluşturur. Bu sınıf tüm etiketler için ortak yöntemlere sahiptir ve bir belge içeriğinde gerekli bir etiketi aramaya ilişkin ana işlemleri gerçekleştirir.

Üç aşamalı çağrı şöyle görünür:

h.td.base.casket

Bu ibare “h” nesnesinin “td” nesnesi aracılığıyla “casket” değişkeninin değerini (bu <td header >casket</td> etiketinin bir örneğidir) iç içe geçmiş nesne olan “base” aracılığıyla çağırdığı anlamına gelir (bu CTegs sınıfının bir nesnesidir).

Sınıf ayrıca etiketleri arama yöntemlerine de sahiptir, etiketin sonundaki arama değerini döndüren

h.td.Search(text,start);

ve etiketin “header” ve “casket” değişkenlerini dolduran genel yöntemde birleştirilirler.

Sınıfta hazırlanan diğer fonksiyonlar kullanılmadığı için onları anlatmayacağım; anlatılacak daha bir sürü ilginç şey var.

HTML belgeleriyle çalışma tanımının sonunda bu makalede iki tür ayrıştırıcı kullanıldığını belirtmek isterim; bunlar yalnızca dosyadan elde edilen bilgilerin kaydedilme şekline göre farklılık gösterir. İlk tür tüm belgenin “string” türündeki tek bir değişkene kaydedilmesiyle çalışır ve oynatıcıda kullanılır. İkinci tür de raporun satır satır ayrıştırılmasıyla çalışır. Komut dosyasında 2008 Şampiyonası geçmişini hazırlamak için kullanılır.

Neden iki tane yaklaşım kullanıyorum? Bunun sebebi CTegs sınıfının fonksiyonlarının doğru çalışması için etiketin tamamının analiz edilen dizgeye yerleştirilmesidir. Ve bu her zaman mümkün değildir. Örneğin tablo, html, içerik gibi (çok satırlı) etiketler olması durumunda . Dize türündeki bir değişken tablolama sembolleri olmadan 32750 sembolün (hesaplamalarıma göre) depolanmasına izin verir. Ve “\r” ile (her 32748'inci sembolden sonra) 2.000.000’a kadar sembolü depolamayı başardım; bu değere ulaştıktan sonra da denemelerimi durdurdum. Büyük olasılıkla daha fazla sembol depolanabilir.

Peki neden iki tane yaklaşım kullanıyoruz? Mesele şu ki, oynatıcının evrensel bir ayrıştırıcısı için uygun bir tablo bulmanız gerekiyor. Test edici raporu ve işlem geçmişi raporu için gerekli tablolar farklı yerlerdedir. Çok yönlülüğü korumak için (ayrıştırıcının her iki raporu da anlaması için) “işlemleri” içeren “td” etiketiyle tablo arama şemasını kullanıyorum.

2008 Şampiyonası raporunun yapısı bilinmektedir ve gerekli tabloyu aramaya ihtiyaç yoktur. Ancak rapor belgesi çok büyük (35 MB) ve tüm raporu tek bir değişkene yerleştirmek çok zaman alacaktı. Bu durum da ayrıştırma için ikinci yaklaşımı şart koşmaktadır.


Oynatıcı

Oynatıcıya ilişkin 10 gereksinim, “Geliştirmeye Başlama” bölümünde açıklanmıştır. Çoklu para birimi ilk sırada olduğundan dolayı Uzman Danışman grafikleri yönetmelidir. Her bir grafiğin oynatıcının çalışması için gereken tüm fonksiyonelliğe sahip ayrı bir nesne tarafından işlenmesi mantıklı olacaktır.

Geçmiş ile çalıştığımızdan dolayı, istediğimiz zaman elde edebileceğimizi düşünmek yerine kesintisiz bir çalışma için ayrı bir geçmiş örneğine ihtiyacımız var. Buna ek olarak, aynı geçmişi tekrar tekrar almak onu oynatıcıda tutmaya kıyasla mantıksız bir davranış olacaktır. Sonunda aşağıdaki şema ortaya çıkar:

Alım satım geçmişi oynatıcısının genel şeması

Nesne yönelimli programlama (OOP) blok sistemleri kullanarak oldukça büyük uygulamaların yazılmasına izin verir. Uzman Danışman kodunun geliştirilmiş kısmı önceden bir komut dosyasına yazılabilir, üzerinde hata ayıklama yapılabilir ve daha sonra minimum uyarlama ile Uzman Danışmana bağlanabilir.

Bu tür bir geliştirme şeması kullanıma uygundur çünkü bağlı olan kodun hata içermediğinden emin olursunuz (çünkü komut dosyasında hatasız çalışır) ve bulunan herhangi bir hata da uyarlama hatasıdır. Bir kod aşağıdan yukarıya yazıldığında ve her şeyi prosedür olarak tek bir yerde anlattığınızda böyle bir avantaj yoktur. Ve uygulamanın herhangi bir yerinde yeni bir hata görünebilir.

Bu nedenle yukarıdan aşağıya programlama bir uygulama yazma konusunda basitlik ve hız açısından avantajlara sahiptir. “Burada basit olan nedir?” diye sorabilirsiniz, bir alegori ile cevap vereyim; bisiklet sürmeyi öğrenmek zordur ancak bir kez öğrendikten sonra sürme işlemini düşünmezsiniz bile. Sadece hızlı bir sürüşün tadını çıkarırsınız. OOP sözdizimini öğrendikten sonra büyük bir avantaj elde edeceksiniz.


Anlatıma devam etmek için üç OOP terimini tanımlamam gerekiyor: İlişkilendirme, Toplama ve Bileşim.

İlişkilendirme kavramı toplamayı ve bileşimi kapsadığı için detaylı bir analiz sırasında toplama veya bileşim olarak tanımlanamayan tüm durumlara ilişkilendirme denir. Genellikle üç terimin tümüne ilişkilendirme denir.

class Base
  {
public:
                     Base(void){};
                    ~Base(void){};
   int               a;
  };
//+------------------------------------------------------------------+

class A_Association
  {
public:
                     A_Association(void){};
                    ~A_Association(void){};
   void              Association(Base *a_){};
   // At association, data of the bound object 
   // will be available through the object pointer only in the method, 
   // where the pointer is passed.
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class A_Aggregation
  {
   Base             *a;
public:
                     A_Aggregation(void){};
                    ~A_Aggregation(void){};
   void              Aggregation(Base *a_){a=a_;};
   // At aggregation, data of the bound object 
   // will be available through the object pointer in any method of the class.
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class A_Composition
  {
   Base             *a;
public:
                     A_Composition(void){ a=new Base;};
                    ~A_Composition(void){delete a;};
   // At composition, the object becomes the class member.
  };

MQL5'te bir parametreden bir işaretçi geçiren bir fonksiyon mevcuttur: 

GetPointer(pointer)

Bunun parametresi nesne işaretçisidir.

Örneğin:

void OnStart()
  {
   Base a; 
   A_Association b;
   b.Association(GetPointer(a));
  }


Kodumun OnInit() fonksiyonunda çağrılan fonksiyonlar genellikle ilişkilendirme kullanır. Bileşim CHTML sınıfında uygulanır. Ve CPlayer sınıfındaki nesneleri bağlamak için toplama ve bileşimi birlikte kullanıyorum. Örneğin, toplama kullanarak CChartData ve SBase sınıflarının nesneleri oynatıcıda bileşim aracılığıyla oluşturulan tüm nesneler için ortak bir veri alanı oluşturur.

Görsel olarak bu durum aşağıdaki gibidir:

Verilerin bağlanması

Nesneleri CPlayer sınıfında bileşik halinde oluşturulan sınıflar fonksiyonelliği daha da genişleten bir şablon yapısına sahiptir. Şablonların kullanımı C++ Şablonlarına Alternatif Olarak Sözde Şablonları Kullanma makalesinde açıklanmıştır, bu yüzden burada ayrıntılı açıklamasını vermeyeceğim.

Sınıfa ilişkin bir şablon aşağıdaki gibi görünür:

//this_is_the_start_point
//+******************************************************************+
class _XXX_
  {
private:
   long              chart_id;
   string            name;
   SBase            *s;
   CChartData       *d;
public:
   bool              state;
                     _XXX_(){state=0;};
                    ~_XXX_(){};
   void              Create(long Chart_id, SBase *base, CChartData *data);
   void              Update();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void _XXX_::Create(long Chart_id, SBase *base, CChartData *data)
  {
   chart_id=Chart_id;
   s=base; // binding data to the player structure
   d=data; // binding data to the chart structure
   name=" "+ChartSymbol(chart_id);

   if(ObjectFind(chart_id,name)<0)// if there is no object yet
     {//--- try to create the object         
      if(ObjectCreate(chart_id,name,OBJ_TREND,0,0,0,0,0))
        {//---
        }
      else
        {//--- failed to create the object, tell about it
         Print("Failed to create the object"+name+". Error code ",GetLastError());
         ResetLastError();
        }
     }       
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void _XXX_::Update()
  {
  };
//+******************************************************************+
//this_is_the_end_point

Böylece boş sınıfları şablona göre oluşturdum, onları bağladım, tüm istekleri doğru işleyip işlemediklerini kontrol ettim ve ancak ondan sonra bileşik sınıflara gerekli fonksiyonelliği eklemeye başladım. İşte buna yukarıdan aşağıya programlama denir. Herhangi bir hata durumunda hatanın kökenini nerede arayacağınızı bilirsiniz.

Artık nasıl oluşturacağımıza ilişkin genel konsepti açıkladığımıza göre ayrıntılara geçebiliriz.

Öncelikle Alım Satım Geçmişi Oynatıcısı exp v5 Uzman Danışmanında açıklanan fonksiyonların işleyişine bir göz atalım.

OnInit() fonksiyonu genellikle bilgileri hazırlar. Bu fonksiyon strateji test edicinin bir raporunu ayrıştıran, alım satım yapılan tüm finansal araçların listesini alan, işlemleri işleyen, hacimleri ve pozisyon seviyelerini hesaplayan ve ardından geçmiş grafiğini çizen CParser_Tester sınıfının bir nesnesini oluşturur. Son öge veri iletildikten hemen sonra nesnenin neden silinmediğinin sebebini açıklar. Şöyle ki, bilgiler grafikler açılmadan önce hazırlanır. Ve grafik nesneler çizim yapılması için bir grafik kimliğine ihtiyaç duyar. Bu nedenle CParser_Tester sınıfının nesnesi daha sonra silinir.

Ayrıca alım satım için kullanılan sembollerinin isimlerini bildiğimiz için Balance_Process() fonksiyonu çağrılır, kendisine iletilen tüm sembollerin bakiyelerinin ve öz sermayelerinin yanı sıra M1 geçmişine dayanarak toplam bakiyeyi ve öz sermayeyi hesaplar.

Bu bölümde, uygulama özellikle bilgi eksikliğine karşı hassas davranır, bu nedenle sembollerden birinin bilgisinin indirilmemesi durumunda EA'nın çalışmasını kesintiye uğrattım. Uygulama çalışmayı durdurduğunda indirilmesi gereken sembol bilgisini içeren bir uyarı görüntüler.

Balance_Process() fonksiyonunun çalışması sonucunda daha sonra bakiye göstergesi tarafından gerekli periyotlara bölünen M1 temelindeki bakiye ve öz sermaye geçmişinin ikili dosyaları oluşur. Biraz fazla anlattım, bakiye göstergesinin çalışmasını daha sonra açıklayacağım.

Uzman Danışmanı başlatmanın bir sonraki adımı da sembollerin seçimidir. Bu aşamada “gerekli grafiklerin listesi” adlı giriş parametresini analiz ediyoruz; gerekli sembolün “Market Watch (Piyasa İzleyici) listesinde olması durumunda bunu sembol dizisine ekleyin. Bir kullanıcı bir sembol adı yerine anlamsız bir söz belirtebileceği veya yanlış yazabileceği için bu şekilde yaparak böyle hatalardan kaçınmış oluyoruz.

Açmak için bir kullanıcı tarafından talep edilen doğrulanmış sembol listesine sahip olduğumuza göre artık grafikleri açabiliriz. Bu işlem aşağıdaki fonksiyon kullanılarak yapılır:

ChartOpen(symbol,period)

Bu fonksiyon parametrelerde kendisine iletilen sembolün ve periyotun bulunduğu bir grafik açar. Teoride bu fonksiyon açılan grafiğin kimliğini döndürür ancak bu her zaman gerçekleşmez.

Kimlik kaybetme sonucunda uygulama arızalanır. Bunu önlemek için iki fonksiyon oluşturdum:

ChartTotal(arrayID);   // get the list of charts before opening additional charts
CurrentChart(arrayID); // get the list of chart for operation

İlk fonksiyon grafikleri açmadan önce ikincisi de açtıktan sonra yürütülür. ChartTotal() fonksiyonu EA başlamadan önce açılan grafiklerin listesini (EA'nın çalıştırıldığı grafik dâhil) alır ve kimliklerini giriş dizisinde kaydeder.

CurrentChart() fonksiyonu bu bilgiyi alır ve önceden açılmış grafikler doğrultusunda yeni bir liste oluşturur; daha sonra listelerin farklılığına göre EA tarafından oluşturulan grafiklerin kimliklerini parametrik diziye geçirir. Bu şema güvenilirdir çünkü grafiği açma üzerine çalışır.

Artık gerekli grafiklerin kimlikleri elimizde olduğuna göre onları kontrol altına alabiliriz. Bunu yapmak için bir döngü içindeki tüm grafikleri gözden geçirin ve CParser_Tester nesnesini kullanarak (hatırlarsanız daha önce buna ihtiyacımız olacağını söylemiştim) işlemlerin geçmişini çizin ve grafiği yönetmeye ilişkin nesneleri oluşturun.

OnInit() fonksiyonundaki son eylem olarak zamanlayıcıyı oluşturun ve çalışmaya çağırın. Diğer tüm eylemler OnTimer() içinde gerçekleştirilecektir.

Oynatıcı oluşturmada ilk sorun geliştirmenin ilk aşamasında ortaya çıkar. Bu sorun bir zamanlayıcı oluşturma sorunudur. EventSetTimer(timer) fonksiyon 1 saniyeden az olmayan bir frekansa sahip bir zamanlayıcı oluşturulmasına olanak tanır. Bu varyant sayesinde tikler saniyede bir kez oluşturulur. İnsanlar bunu çok fark etmese bile bir saniye çok uzun bir süredir. En az 100 milisaniye olmasına ihtiyacım var.

Bu yüzden zamanlayıcının içine bir döngü ekledim; yeni bir Zamanlayıcı olayından birkaç milisaniye önce başlıyor. Ancak bu uygulama birçok teknik çözümü imkânsız hale getirir. Örneğin, bu şekilde olayları alma olasılığı ortadan kalkar çünkü sürekli olarak zamanlayıcının döngüden çıkmasını beklerle. Olayları almanın imkânsızlığı sebebiyle oynatıcıların nesnelerini göstergeye yerleştirme ve tüm grafiklerin paralel hesaplamalarını aynı anda yapma imkânı ortadan kalkar. Ancak grafiklerin ardışık işlenmesinde bile Uzman Danışman oldukça hızlı çalışır.

Grafik etkinleştirme olayı, nesneleri Click(n) fonksiyonunun döngüsünde işlenmekte olan aktif grafiğin değiştiğine dair bir sinyal oluşturan bileşik sınıf CClick ile değiştirilir. Click() fonksiyonu grafik etkinleştirme düğmesindeki değişiklikleri izleyen bir tetikleyicidir. Düğmeye basıldığını algılarsa diğer tüm nesneleri pasif duruma geçirir. Grafik etkinleştirme düğmesi her zaman kullanıcının gözü önündedir ancak tüm grafiğin boyutu kadar olduğu için görünmez; arka plan rengindedir ve arka planda yer alır. Bir grafik etkinleştirildiğinde bu düğme grafiğin görünür sınırlarının arkasına taşınır; bu da pasif modda grafik etkinleştirme düğmesi tarafından gizlenen oynatıcı kontrollerinin grafik nesnelerini görmenizi sağlar.

Ayrıca Click() fonksiyonunu kullanarak ana grafiği tespit ettiğimize göre zaman hareketinin hesaplanmasına gidip aktif oynatıcının Progress(Time) fonksiyonunu çağırabilirsiniz. Bu fonksiyon aşağıdaki hesaplamaları gerçekleştirir: kullanıcının gezinme eylemleri gerçekleştirip gerçekleştirmediğini kontrol eder, eğer gerçekleştirmediyse bir sonraki çubuğa gitme zamanının gelip gelmediğini kontrol eder. Gitme zamanı geldiyse ilerlemenin bir sonraki bölüme taşınmasının gerekli olup olmadığını kontrol eder.

Sonunda Progress(Time) fonksiyonundan çıktığımızda ise döngü daha sonraki hesaplamalar için kullanılan mevcut zaman bilgisini almış olur. Ardından aktif grafiğin ayarları bağımlı grafiklere kopyalanır. Bu işlem CopyPlayer(n) fonksiyonunda bir döngü kullanılarak yapılır. Daha sonra Play(Time) fonksiyonunda grafikte yapılması gereken tüm değişiklikleri gerçekleştirerek kullanıcının zamanın ilerlediğini, fiyat tekliflerinin geldiğini ve alım satım yapıldığını düşünmesini sağlayın.


Oynatıcının Bileşik Sınıfları

  1. CArrayRuler*: geçerli bir zaman dilimlerinin çubukları arasında hızlı hareket etmek için bilgileri saklar ve arar.
  2. CRuler*: tiklerin oluşturulması için M1 geçmiş bilgilerini saklar ve arar.
  3. CSpeed: hız ayarlarını ve tik oluşturucunun süresini kontrol eder.
  4. CProgress: tüm ilerleme düğmelerini tek bir nesnede birleştirir, yalnızca bir düğmeye basılıp basılmadığını takip eder, düğmelerin renklerini değiştirir.
  5. CPlay: oynatıcıyı başlatmak ve durdurmaktan sorumludur, ayrıca bakiye göstergesini de kontrol eder.
  6. CClick: grafik etkinleştirme sinyallerinden sorumludur.
  7. CBackGround: nesne, sıfır çubuğunu kullanıcılardan gizlediği gibi grafiğin sağ sınırdan kayma durumu etkinleştirildiğinde gelecekteki çubukları da gizler.
  8. CBarDraw: grafiğin ölçeğine ve türüne (çubuklu, şamdan veya çizgi) bağlı olarak sıfır çubuğunu çizer.
  9. CHistoryDraw: son işlemin gerçek zamanlı olarak değiştiğine dair kullanıcıya bir yanılsama yaratır.

*: bu sınıflar grafik nesnelerini içermez.

Daha önce de belirttiğim gibi, CChartData ve SBase sınıflarının nesneleri toplama aracılığıyla oynatıcı içindeki tüm nesneler için ortak bir veri alanı oluşturur. CChartData sınıfının nesnesi grafikle ilgili bilgilerin depolanması ve güncellenmesinin yanı sıra onu yönetmek için kullanılır. Grafiği yönetme derken ana grafiğin ayarlarını kopyalayarak onun ayarını değiştirmekten bahsediyoruz. Grafiklerin senkronizasyonu bu şekilde gerçekleştirilir. Bir kullanıcı aktif grafiğin ayarlarını değiştirerek bir başlangıç sinyali verir ve ardından çeşitli oynatıcı fonksiyonları senkronizasyon işlemlerinin geri kalanını halleder.

Bu şu şekilde yapılır:

Uzman Danışmanda tanımlanan CopyPlayer(n) fonksiyonu, işaretçiyi aktif grafiğin oynatıcısına ilişkisel olarak ileten bir döngü içinde CPlayer::Copy(CPlayer *base) fonksiyonunu çağırır. Oyuncu işaretçisinden CPlayer::Copy(CPlayer *base) içinde aktif oynatıcının CChartData nesnesinin işaretçisi ilişkisel olarak iletilir. Böylece aktif grafiğin durumu hakkındaki bilgiler kopyalamaya yönelik bağımlı grafiğin CChartData sınıfının nesnesine yerleştirilir. Bu işlemden sonra gerekli tüm kontrollerin yapıldığı ve tüm nesnelerin gerekli durumlara getirildiği CPlayer::Update() fonksiyonunda bilgiler güncellenir.

Daha önce size üreticinin mevcut periyotlar listesine nasıl periyot ekleyeceğinizi anlatacağımı söylemiştim. Bunu yapmak için “Player5_1.mqh” ekleme dosyasını açın. Statik dizi TFarray[] dosyanın başında bildirilir. Gerekli bir periyodu dizide bulunan dökümdeki yerine ekleyin; dizinin boyutunu ve CountTF değişkenini değiştirmeyi unutmayın. Bundan sonra Alım Satım Geçmişi Oynatıcısı exp v5 Uzman Danışmanını derleyin.


Bakiye ve Düşüş Grafikleri

Grafik göstergesi CPlay sınıfının nesnesiyle yönetilir. Bu göstergede kontrol yöntemleri ve düğmeler bulunur.

Göstergenin kontrol yöntemleri şunlardır:

   Ind_Balance_Create();                 // add the indicator
   IndicatorDelete(int ind_total);     // delete the indicator
   EventIndicators(bool &prev_state);   // send an event to the indicator
   StateIndicators();                  // state of the indicator, state checks

name_on_balance düğmesinin durumuna bağlı olarak ekleme veya silme yöntemleri çalışır. IndicatorCreate() ve ChartIndicatorDelete() adlı standart MQL5 fonksiyonlarını kullanırlar.

Gösterge bir olay alır ve olay koduna bağlı olarak göstergenin OnChartEvent() fonksiyonunda bulunan hesaplamaları gerçekleştirir. Olaylar üç türe ayrılır. 

Bunlar “göstergeyi güncelle”, “toplam bakiyeyi hesapla” ve “bir sembol için bakiyeyi hesapla”dır. Böylece bir olay gönderirken name_all_balance düğmesinin durumuna bağlı olarak kullanıcı hesaplama türünü kontrol eder. Ancak gösterge kodunda alım satım geçmişinin ayrıştırılması, pozisyonun hesaplanması veya kârın yeniden hesaplanması yer almaz. Göstergenin buna ihtiyacı yoktur.

Bakiye göstergesi geçmiş verilerin görüntülenmesi için tasarlanmıştır, bu nedenle türü her değiştirdiğinizde veya göstergeyi eklediğinizde ya da kaldırdığınızda her şeyi baştan yapmanın bir anlamı yoktur. Gösterge M1 zaman dilimi için hesaplanan verilerin ikili dosyasını okur ve ardından grafiğin geçerli zaman dilimine bağlı olarak verileri böler.

Bu ikili dosya OnInit() ile çağrılan Balance_Process() fonksiyonu tarafından hazırlanır. Kullanıcı alım satım için kullanılmayan bir sembol eklerse ve buna karşılık gelen bir ikili dosya mevcut değilse gösterge her iki değişkenin toplam bakiye geçmişini görüntüler.

Şimdi göstergeye iletilen verinin formatından bahsedelim. Bilgileri doğru bir şekilde bölmek için bir çubuğun dört hususunu (Açılış, Yüksek, Düşük ve Kapanış) bilmek yeterli değildir.

Bunun yanı sıra ilk olarak yüksek mi yoksa düşük mü olduğunu da bilmeniz gerekiyor. Bilgileri geri yüklemede Balance_Process() fonksiyonu strateji test edicinin “1 dakika OHLC” moduyla aynı yöntemi kullanır: bir çubuğun kapanış fiyatı açılış fiyatından düşükse ikinci nokta maksimumdur, aksi durumdaysa minimumdur.

Aynı şema üçüncü nokta için de geçerlidir. Sonuç olarak her şeyin tutarlı ve kesin olduğu veri formatını (açılış, 2. nokta, 3. nokta, kapanış) elde ederiz. Bu format M1 fiyat teklifi geçmişini bölmek için kullanılır. Ve çıkan sonuç da ayrıştırılmış alım satım geçmişine bağlı olarak (aynı formatta) bakiye ve öz sermaye geçmişinin hesaplanması için kullanılır.


Sonuç

Sonuç olarak şunu söylemek isterim ki, her ne kadar bu şekilde kullanabilsek de bu geliştirme test edici grafiği yerine geçmez. Ancak içinde uygulanan fikirler gerçek grafikte faydalı olur gibi görünüyorsa bu beni mutlu eder. Bu oynatıcının geliştirilmesi alım satım yapan kişilere ve EA yazarlarına yaklaşan şampiyonaya hazırlanmalarına ve alım satım stratejilerini analiz etme konusundaki sıkı çalışmalarına yardımcı olmayı amaçlamaktadır.

Ayrıca MQL5 dilinin oldukça büyük projelerin uygulanmasına izin veren güçlü bir programlama aracı olduğunu söylemek isterim. Hâlâ bu makaleyi okuyorsanız muhtemelen “oynatıcı” projesinin yaklaşık 8000 satır koddan oluştuğunu fark etmişsinizdir. MQL4'te böyle bir kod yazmayı hayal bile edemiyorum ki mesele hepsini prosedürlerle açıklamak da değil. Hazır bir geliştirme varsa bu prosedür şeklinde yeniden yapılabilir. Ancak bu tür projeleri sıfırdan geliştirmek gerçekten zor.

Kolay gelsin!