Zaman Serilerinin Tahmini için MetaTrader 5 Göstergelerini ENCOG Makine Öğrenimi Çerçevesi ile Kullanma
Giriş
Bu makale, MetaTrader 5'i Heaton Research tarafından geliştirilen gelişmiş sinir ağı ve makine öğrenimi çerçevesi olan ENCOG ile tanıştıracak. Bildiğim kadarıyla halihazırda MetaTrader'ın makine öğrenimi tekniklerini kullanmasını sağlamayı gösteren yöntemler var: FANN, NeuroSolutions, Matlab ve NeuroShell. ENCOG sağlam ve iyi tasarlanmış bir kod olduğu için tamamlayıcı bir çözüm olacağını umuyorum.
Neden ENCOG'u seçtim? Bunun bir kaç nedeni var.
- ENCOG, iki farklı ticari yazılım paketinde daha kullanılmakta. Biri C#', ikincisi JAVA tabanlı. Bu, mali zaman serisi verilerini tahmin etme konusunda test edilmiş demektir.
- ENCOG ücretsiz ve açık kaynaklı bir yazılımdır. Bir sinir ağının içinde neler olup bittiğini görmek isterseniz kaynak koduna göz atabilirsiniz. Zaman serisi tahmin probleminin bazı kısımlarını anlamak için ben de bunu yaptım. C# ise yalın ve anlaşılması kolay bir programlama dili.
- ENCOG çok detaylı şekilde hazırlanmış ve belgelenmiştir. Heaton Research'ün kurucusu Bay Heaton, Sinir Ağları, Makine Öğrenimi ve gelecekteki verileri tahmin etmek için ENCOG kullanımı hakkında ücretsiz bir çevrimiçi kurs sunuyor. Bu makaleyi yazmadan önce kendisinin birçok dersini aldım. Bu dersler Yapay Sinir Ağlarını anlamama çok yardımcı oldu. Ayrıca Heaton Research web sitesinde JAVA ve C# ile ENCOG programlama hakkında e-kitaplar da bulunuyor. ENCOG’un bütün belgeleri çevrimiçi olarak mevcut.
- ENCOG ölü bir proje değil. Ben bu makaleyi yazarken ENCOG 2.6 hala geliştirilmeye devam ediyor. ENCOG 3.0 yol haritası yakın zamanda yayınlandı.
- ENCOG sağlamdır. İyi tasarlanmıştır, sinir ağı hesaplamalarını hızlandırmak için birden fazla CPU çekirdeğini çoklu kullanım ile kullanabilir. Kodun bölümleri OpenCL - GPU etkin hesaplamaları için taşınmaya başlar.
- ECNOG’un halihazırda desteklenen özellikleri:
Makine Öğrenimi Çeşitleri
- İleri beslemeli ve Basit Tekrarlayan (Elman/Jordan)
- Genetik Algoritmalar
- NEAT(Ağ Topolojilerinin Artırılmasının Nöroevrimi)
- Olasılıksal Sinir Ağı/ Genel Regresyon Sinir Ağı (PNN/GRNN)
- Kendini Düzenleyen Harita (SOM/Kohonen)
- Benzetimli Tavlama
- Destek Vektör Makinesi
Sinir Ağı Mimarileri
Eğitim Teknikleri
- ADALINE Sinir Ağı
- Adaptif Rezonans Teorisi 1 (ART1)
- Çift Yönlü İlişkisel Bellek (BAM)
- Boltzmann Makinesi
- Karşı Yayılımlı Sinir Ağı (CPN)
- Elman Tekrarlayan Sinir Ağı
- İleri Beslemeli Sinir Ağı (Perceptron)
- Hopfield Sinir Ağı
- Jordan Tekrarlayan Sinir Ağı
- Ağ Topolojilerinin Artırılmasının Nöroevrimi(NEAT)
- Radyal Tabanlı Fonksiyon Ağı
- Tekrarlayan Kendini Düzenleyen Harita (RSOM)
- Kendini Düzenleyen Harita (Kohonen)
Aktivasyon Fonksiyonları
- Geri Yayılım
- Esnek Yayılım (RPROP)
- Ölçekli Eşlenik Gradyan (SCG)
- Manhattan Güncelleme Kuralı Yayılımı
- Rekabetçi Öğrenme
- Hopfield Öğrenmesi
- Levenberg-Marquardt Algoritması (LMA)
- Genetik Algoritma Eğitimi
- Instar Eğitimi
- Outstar Eğitimi
- ADALINE Eğitimi
- Eğitim Veri Modelleri
- Denetimli
- Denetimsiz
- Zamansal (Tahmin)
- Mali (Yahoo Finance adresinden indirilir)
- SQL
- XML
- CSV
- Görüntü Alt-Örnekleme
Rastgeleleştirme Teknikleri
- Rekabetçi
- Sigmoid
- Hiperbolik Teğet
- Doğrusal
- SoftMax
- Teğetsel
- Sinüs Dalgası
- Adım
- Çift Yönlü
- Gauss
- Aralık Rastgeleleştirme
- Gauss Rastgele Sayılar
- Fan Girişi
- Nguyen-Widrow
Planlanan özellikler:
- HyperNEAT
- Kısıtlanmış Boltzmann makinesi (RBN/Deep Belief)
- Spiking Sinir Ağı
Gördüğünüz üzere bu oldukça uzun bir özellik listesi.
Bu konuya giriş makalesi, Esnek Yayılım (RPROP) eğitimi ile ileri beslemeli Sinir Ağı mimarisine odaklanmaktadır. Ayrıca, veri hazırlamanın temellerini de kapsar. Örneğin zaman sınırlaması ve zamansal zaman dizileri tahmini için normalleştirme.
Bu makaleyi yazmamı sağlayan bilgiler, Heaton Research web sitesinde bulunan kılavuzlara ve NinjaTrader'daki mali zaman serilerinin tahmini üzerine fazlasıyla yakın zamanda yazılan makalelere dayanmaktadır. ENCOG'un JAVA ve C# tabanlı olduğunu lütfen unutmayın. Önceki çalışmalarım olmadan bu makaleyi yazmak mümkün olmazdı: Yönetilmeyen dışa aktarmaları kullanarak C# kodunu MQL5'e maruz bırakma. Bu çözüm, C# DLL'nin Metatrader 5 göstergesi ile ENCOG zaman serisi tahmincisi arasında bir köprü olarak kullanılmasına olanak sağladı.
1. Bir Sinir Ağı İçin Girdi Olarak Teknik Gösterge Değerlerini Kullanma
Yapay Sinir Ağı, beynin sinir ağını taklit etmeye çalışan, insan yapımı bir algoritmadır.
Çeşitli sinirsel algoritma türleri bulunur ve bunların içinde çeşitli sinir ağı mimarileri mevcuttur. Araştırma alanı o kadar geniştir ki, tamamı tek bir sinir ağı türü üzerine yazılan kitaplar vardır. Bu tür ayrıntılar bu makalenin kapsamı dışında olduğundan, yalnızca Heaton Research kılavuzlarını incelemenizi veya konuyla ilgili kitaplar okumanızı tavsiye edebilirim. Ben ileri beslemeli sinir ağının girdileri ve çıktılarına odaklanacağım ve mali zaman serisi tahmininin pratik örneğini açıklamaya çalışacağım.
Mali zaman serilerini öngörmeye başlamak için sinir ağına vermemiz gerekenleri ve bunun karşılığında ne bekleyebileceğimizi düşünmemiz gerek. Çoğu soyut kara kutu düşünme şeklinde, belirli bir menkul kıymetin sözleşmesinde uzun veya kısa pozisyonlar alarak ve bir süre sonra anlaşmayı kapatarak kâr veya zarar elde ederiz.
Bir menkul kıymetin geçmiş fiyatlarını ve teknik göstergelerin değerlerini gözlemleyerek, bir sözleşmeyi satın almak veya satmak için gelecekteki duyarlılığı veya fiyatların gideceği yönü tahmin etmeye çalışırız ve kararımızın yazı tura atar gibi alınmadığından emin oluruz. Durum hemen hemen aşağıdaki şekle benziyor:
Şekil 1. Teknik göstergeleri kullanarak mali zaman serilerini tahmin etme
Bunun aynısını yapay zeka ile başarmaya çalışacağız. Sinir ağı, gösterge değerlerini tanımaya çalışacak ve fiyatın yükselme veya düşme ihtimalinin olup olmadığına karar verecektir. Bunu nasıl başarabiliriz? Mali zaman serilerini ileri beslemeli sinir ağı mimarisini kullanarak tahmin edeceğimiz için bu mimariye de bir giriş yapmamız gerektiğini düşünüyorum.
İleri beslemeli sinir ağı, katmanlar halinde gruplandırılmış nöronlardan oluşur. En az 2 katmandan oluşabilir: girdi nöronlarını içeren bir giriş katmanı ve çıktı nöronlarını içeren bir çıkış katmanı. Giriş ve çıkış katmanları arasında gizli katmanlar da olabilir. Giriş katmanı temel olarak çift değerlerden oluşan bir dizi olarak düşünülebilir ve çıkış katmanı da aynı şekilde bir çift değerler dizisi oluşturan bir veya daha fazla nörondan oluşabilir. Aşağıdaki şekle bakınız:
Şekil 2. İleri beslemeli sinir ağı katmanları
Çizimi basitleştirmek için nöronlar arasındaki bağlantılar çizilmemiştir. Giriş katmanındaki her bir nöron, gizli katmandaki bir nörona bağlanır. Gizli katmandaki her nöron, çıkış katmanındaki bir nörona bağlanır.
Her bağlantının kendi ağırlığı vardır, bu aynı zamanda bir çift değerdir ve bir nöronu aktive etmekten ve bilgiyi bir sonraki nörona iletmekten sorumlu olan bir eşiği olan aktivasyon fonksiyonudur. Bu nedenle buna 'ileri beslemeli’ ağ denir - aktive edilmiş nöronların çıktılarına dayanan bilgi, bir katmandan başka bir nöron katmanına ileriye doğru beslenir. İleri beslemeli sinir ağları hakkındaki ayrıntılı bilgilendirici videolar için aşağıdaki bağlantıları ziyaret etmek isteyebilirsiniz:
- Sinir Ağı Hesaplaması (Bölüm 1): İleri Besleme Yapısı
- Sinir Ağı Hesaplaması (Bölüm 2): Aktivasyon Fonksiyonları ve Temel Hesaplama
- Sinir Ağı Hesaplaması (Bölüm 3): İleri Beslemeli Sinir Ağı Hesaplaması
Sinir ağı mimarisini ve mekanizmalarını öğrendikten sonra hala kafanız karışık olabilir.
Başlıca sorunlar şunlardır:
- Bir sinir ağına hangi verileri besleyeceğiz?
- Nasıl besleyeceğiz?
- Bir sinir ağı için girdi verileri nasıl hazırlanır?
- Sinir ağı mimarisi nasıl seçilir? Kaç adet girdi nöronu, gizli nöron ve çıktı nöronu gerekli?
- Ağ nasıl eğitilir?
- Çıktı olarak ne beklenmeli?
2. Sinir Ağına Beslenecek Veriler
Gösterge çıktılarına dayalı mali tahminlerle ilgilendiğimiz için, ağı göstergenin çıktı değerleriyle beslememiz gerekir. Bu makalede girdi olarak Stokastik %K’yi, Yavaş Stokastik %D’yi ve Williams %R’yi seçtim.
Şekil 3. Tahmin için kullanılan teknik göstergeler
Göstergelerin değerlerini çıkarmak için iStochastic ve iWPR MQL5 fonksiyonlarını kullanabiliriz:
double StochKArr[], StochDArr[], WilliamsRArr[]; ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, bufSize, StochKArr); CopyBuffer(hStochastic, 1, 0, bufSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, bufSize, WilliamsRArr);
Bu kod çalıştırıldıktan sonra üç StochKArr, StochDArr ve WilliamsRArr dizileri gösterge çıkış değeri ile doldurulmalıdır. Eğitim örneklem büyüklüğüne bağlı olarak bu, birkaç binlik değerlere kadar çıkabilir. Lütfen bu iki göstergenin yalnızca eğitim amaçlı seçildiğini unutmayın.
Tahmin için uygun bulduğunuz herhangi bir göstergeyi denemenizi tavsiye ederim. Hisse senedi endekslerini tahmin etmek için ağı altın ve petrol fiyatları ile beslemek isteyebilirsiniz veya başka bir döviz çiftini tahmin etmek için korelasyonlu forex çiftlerini kullanabilirsiniz.
3. Girdi Verilerine Zaman Sınırlaması Koymak
Birkaç göstergeden girdi verilerini topladıktan sonra sinir ağına beslemeden önce girdiye "zaman sınırı koymaya" ihtiyacımız var. Zaman sınırlaması, ağdaki girdilerin hareketli veri dilimleri olarak sunulmasına olanak sağlayan bir yöntemdir. Zaman ekseninde ilerleyen hareketli bir girdi verisi kutusu gibi hayal edebilirsiniz. Bu prosedürün temelde iki adımı vardır:
1. Her göstergenin ara belleğinden girdi verilerinin toplanması. Başlangıç konumundan geleceğe doğru INPUT_WINDOW (Girdi_Penceresi) sayıda öğe kopyalamamız gerekir. Girdi penceresi, tahmin için kullanılan çubuk sayısıdır.
Şekil 4. Gösterge ara belleğinden girdi penceresi verilerinin toplanması
Yukarıdaki örnekte görebileceğiniz gibi INPUT_WINDOW 4 çubuğa eşit ve unsurları I1 dizisine kopyaladık. I1[0] ilk öğedir, I1[3] son öğedir. Benzer şekilde, veriler diğer göstergelerden de INPUT_WINDOW boyutlu dizilere kopyalanmalıdır. Bu rakam, AS_SERIES işaretinin true(doğru) olarak ayarlandığı zaman serisi dizileri için geçerlidir.
2. INPUT_WINDOW dizilerini, sinir ağı giriş katmanına beslenen tek bir dizi olacak şekilde birleştirmek.
Şekil 5. Zaman sınırlı girdi penceresi dizileri
3 adet gösterge bulunuyor, önce her göstergenin ilk değerini, ardından her göstergenin ikinci değerini alıyoruz ve yukarıdaki şekildeki gibi girdi penceresi dolana kadar buna devam ediyoruz. Gösterge çıktılarından birleştirilen bu dizi, sinir ağımızın giriş katmanına beslenebilir. Yeni bir çubuk geldiğinde, veriler bir unsur tarafından dilimlenir ve tüm işlem tekrarlanır. Verileri tahmin için hazırlamak konusunda daha detaylı bilgi edinmek isterseniz konuyla ilgili bir video da izlemek isteyebilirsiniz.
4. Girdi Verilerini Normalleştirme
Sinir ağını etkili kılmak için verileri normalleştirmemiz gerekir. Bu, aktivasyon fonksiyonlarının doğru hesaplanması için gereklidir. Normalleştirme, verileri 0..1 veya -1..1 aralığına dönüştüren matematiksel bir işlemdir. Normalleştirilmiş veriler denormalize edilebilir, yani başka bir deyişle orijinal aralıklarına geri dönüştürülebilir.
Denormalizasyon, sinir ağı çıktısını insanlar tarafından okunabilir bir biçime dönüştürmek için gereklidir. Neyse ki ENCOG normalleştirme ve denormalizasyon işlemlerini halleder, bu nedenle uygulamaya gerek yoktur. Bunun nasıl işlediğini merak ediyorsanız aşağıdaki kodu inceleyebilirsiniz:
/** * Normalize the specified value. * @param value The value to normalize. * @return The normalized value. */ public static double normalize(final int value) { return ((value - INPUT_LOW) / (INPUT_HIGH - INPUT_LOW)) * (OUTPUT_HIGH - OUTPUT_LOW) + OUTPUT_LOW; } /** * De-normalize the specified value. * @param value The value to denormalize. * @return The denormalized value. */ public static double deNormalize(final double data) { double result = ((INPUT_LOW - INPUT_HIGH) * data - OUTPUT_HIGH * INPUT_LOW + INPUT_HIGH * OUTPUT_LOW) / (OUTPUT_LOW - OUTPUT_HIGH); return result; }
ve daha fazla ayrıntı için normalleştirmeyle ilgili bir makale okuyabilirsiniz
5. Ağ mimarisini ve nöron sayısını seçme
Bu konuda acemi olanlar için doğru ağ mimarisini seçmek zor bir kısımdır. Bu makalede, beslemeli sinir ağı mimarisini üç katmanla sınırlandırıyorum: bir giriş katmanı, bir gizli katman ve bir çıkış katmanı. Daha fazla sayıda katmanla deneme yapmakta özgürsünüz.
Giriş ve çıkış katmanı için gerekli nöron sayısını doğru bir şekilde sayabileceğiz. Gizli bir katman için, ileriye doğru bir seçim algoritması kullanarak sinir ağı hatalarını en aza indirmeye çalışacağız. Diğer yöntemleri de kullanmanızı tavsiye ederim; nöron sayısını hesaplamak için bazı genetik algoritmalar olabilir.
ENCOG tarafından kullanılan bir diğer yöntem ise geriye doğru seçim algoritması veya budama olarak adlandırılır, yapılan şey temel olarak katmanlar arasındaki bağlantıları değerlendirmek ve sıfır ağırlıklı bağlantılarla gizli nöronları kaldırmaktır, bunu da denemek isteyebilirsiniz.
5.1. Giriş nöronları katmanı
Zaman sınırlaması nedeniyle, giriş katmanındaki nöronların sayısı, bir sonraki çubuğu tahmin etmek için kullanılan gösterge sayısı çarpı çubuk sayısına eşit olmalıdır. Girdi olarak 3 gösterge kullanırsak ve giriş penceresi boyutu 6 çubuğa eşitse, giriş katmanı 18 nörondan oluşacaktır. Giriş katmanı, zaman sınırlaması ile hazırlanan verilerle beslenir.
5.2. Gizli nöron katmanı
Gizli ağların sayısı, eğitilmiş sinir ağı performansına dayalı olarak tahmin edilmelidir. Belirli sayıda gizli nöron için basit bir matematiksel denklem yoktur. Makaleyi yazmadan önce birden fazla deneme yanılma yaklaşımı kullandım ve Heaton Research web sitesinde ileriye doğru seçim algoritmasını anlamaya yardımcı olan bir algoritma buldum:
Şekil 6. Gizli nöron sayısı için ileriye doğru seçim algoritması
5.3. Çıktı nöronları katmanı
Amaçlarımız doğrultusunda, çıktı nöronlarının sayısı, tahmin etmeye çalıştığımız çubukların sayısıdır. Lütfen gizli ve çıktı nöron sayıları arttıkça ağın eğitilme süresinin de aynı ölçekte arttığını unutmayın. Bu makalede gelecekteki tek bir çubuğu tahmin etmeye çalışıyorum, bu nedenle çıkış katmanı tek bir nörondan oluşuyor.
6. Eğitim Verilerini MetaTrader 5'ten ENCOG'a Dışa Aktarma
Encog, sinir ağı eğitimi için CSV dosyalarını kabul eder.
Diğer ticari yazılımlardan ENCOG'a aktarılan dosya formatına baktım ve aynı dosya formatını eğitim için hazırlayan MQL5 komut dosyasını uyguladım. İlk önce tek bir göstergeyi dışa aktarmayı göstereceğim ve daha sonra birden fazla göstergeyle devam edeceğim.
İlk veri satırı, virgülle ayrılmış bir başlıktır:
DATE,TIME,CLOSE,Indicator_Name1,Indicator_Name2,Indicator_Name3
İlk üç sütun tarih, saat ve kapanış değerlerini içerir, sonraki sütunlar gösterge adlarını içerir. Eğitim dosyasının sonraki satırları virgülle ayrılmış veriler içermeli, gösterge değerleri de bilimsel formatta yazılmalıdır:
20110103,0000,0.93377000,-7.8970208860e-002
Aşağıda bulunan bir göstergenin hazır komut dosyasını inceleyiniz.
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 400; extern int maPeriod = 210; MqlRates srcArr[]; double expBullsArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(expBullsArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hBullsPower = iBullsPower(Symbol(), Period(), maPeriod); CopyBuffer(hBullsPower, 0, 0, trainSize, expBullsArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,BullsPower\n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(expBullsArr[i], -10)); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
Eğitim için kullanılabilecek sonuç dosyası aşağıdaki çıktı gibi görünmelidir:
DATE,TIME,CLOSE,BullsPower 20110103,0000,0.93377000,-7.8970208860e-002 20110104,0000,0.94780000,-6.4962292188e-002 20110105,0000,0.96571000,-4.7640374727e-002 20110106,0000,0.96527000,-4.4878854587e-002 20110107,0000,0.96697000,-4.6178012364e-002 20110110,0000,0.96772000,-4.2078647318e-002 20110111,0000,0.97359000,-3.6029181466e-002 20110112,0000,0.96645000,-3.8335729509e-002 20110113,0000,0.96416000,-3.7054869514e-002 20110114,0000,0.96320000,-4.4259373120e-002 20110117,0000,0.96503000,-4.4835729773e-002 20110118,0000,0.96340000,-4.6420936126e-002 20110119,0000,0.95585000,-4.6868984125e-002 20110120,0000,0.96723000,-4.2709941621e-002 20110121,0000,0.95810000,-4.1918330800e-002 20110124,0000,0.94873000,-4.7722659418e-002 20110125,0000,0.94230000,-5.7111591557e-002 20110126,0000,0.94282000,-6.2231529077e-002 20110127,0000,0.94603000,-5.9997865295e-002 20110128,0000,0.94165000,-6.0378312069e-002 20110131,0000,0.94414000,-6.2038328069e-002 20110201,0000,0.93531000,-6.0710334438e-002 20110202,0000,0.94034000,-6.1446445012e-002 20110203,0000,0.94586000,-5.2580791504e-002 20110204,0000,0.95496000,-4.5246755566e-002 20110207,0000,0.95730000,-4.4439392954e-002
Orijinal makaledeki Stokastik ve Williams' R göstergelerini içeren örneğe geri dönersek, göstergeleri virgülle ayrılmış üç sütunu dışa aktarmamız gerekiyor, her sütun ayrı gösterge değerleri içeriyor, bu nedenle de dosyayı genişletmemiz ve ek arabellekler eklememiz gerekiyor:
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 2000; MqlRates srcArr[]; double StochKArr[], StochDArr[], WilliamsRArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, trainSize, StochKArr); CopyBuffer(hStochastic, 1, 0, trainSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, trainSize, WilliamsRArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,StochK,StochD,WilliamsR\n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(StochKArr[i], -10), DoubleToString(StochDArr[i], -10), DoubleToString(WilliamsRArr[i], -10) ); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
Sonuç dosyası tüm gösterge değerlerini içermelidir:
DATE,TIME,CLOSE,StochK,StochD,WilliamsR 20030707,0000,1.37370000,7.1743119266e+001,7.2390220187e+001,-6.2189054726e-001 20030708,0000,1.36870000,7.5140977444e+001,7.3307139273e+001,-1.2500000000e+001 20030709,0000,1.35990000,7.3831775701e+001,7.3482018082e+001,-2.2780373832e+001 20030710,0000,1.36100000,7.1421933086e+001,7.2795323083e+001,-2.1495327103e+001 20030711,0000,1.37600000,7.5398313027e+001,7.3662986398e+001,-3.9719626168e+000 20030714,0000,1.37370000,7.0955352856e+001,7.2760441884e+001,-9.6153846154e+000 20030715,0000,1.38560000,7.4975891996e+001,7.3498925255e+001,-2.3890784983e+000 20030716,0000,1.37530000,7.5354107649e+001,7.4117319386e+001,-2.2322435175e+001 20030717,0000,1.36960000,7.1775345074e+001,7.3336661282e+001,-3.0429594272e+001 20030718,0000,1.36280000,5.8474576271e+001,6.8382632945e+001,-3.9778325123e+001 20030721,0000,1.35400000,4.3498596819e+001,6.0087954237e+001,-5.4946524064e+001 20030722,0000,1.36130000,2.9036761284e+001,4.9737556586e+001,-4.5187165775e+001 20030723,0000,1.34640000,1.6979405034e+001,3.8818172735e+001,-6.5989159892e+001 20030724,0000,1.34680000,1.0634573304e+001,2.9423639592e+001,-7.1555555556e+001 20030725,0000,1.34400000,9.0909090909e+000,2.2646062758e+001,-8.7500000000e+001 20030728,0000,1.34680000,1.2264922322e+001,1.9185682613e+001,-8.2705479452e+001 20030729,0000,1.35250000,1.4960629921e+001,1.7777331716e+001,-7.2945205479e+001 20030730,0000,1.36390000,2.7553336360e+001,2.1035999930e+001,-5.3979238754e+001 20030731,0000,1.36990000,4.3307839388e+001,2.8459946416e+001,-4.3598615917e+001 20030801,0000,1.36460000,5.6996412096e+001,3.7972101643e+001,-5.2768166090e+001 20030804,0000,1.34780000,5.7070193286e+001,4.4338132191e+001,-8.1833910035e+001 20030805,0000,1.34770000,5.3512705531e+001,4.7396323304e+001,-8.2006920415e+001 20030806,0000,1.35350000,4.4481132075e+001,4.6424592894e+001,-7.1972318339e+001 20030807,0000,1.35020000,3.3740028156e+001,4.2196404648e+001,-7.7681660900e+001 20030808,0000,1.35970000,3.0395426394e+001,3.8262745230e+001,-6.1245674740e+001 20030811,0000,1.35780000,3.4155781326e+001,3.6893757262e+001,-6.4532871972e+001 20030812,0000,1.36880000,4.3488943489e+001,3.9092152671e+001,-4.5501730104e+001 20030813,0000,1.36690000,5.1160443996e+001,4.3114916446e+001,-4.8788927336e+001 20030814,0000,1.36980000,6.2467599793e+001,4.9565810895e+001,-2.5629290618e+001 20030815,0000,1.37150000,6.9668246445e+001,5.6266622745e+001,-2.1739130435e+001 20030818,0000,1.38910000,7.9908906883e+001,6.4147384124e+001,-9.2819614711e+000
İkinci örneği ihtiyaçlarınıza uygun bir komut dosyasını kolayca oluşturmak için kolayca düzenleyebilirsiniz.
7. Sinir Ağı Eğitimi
Ağın eğitimi Heaton Research tarafından halihazırda C# dilinde hazırlanmıştır. ENCOG 2.6, mali zaman serisi tahmini için bir temel olan Encog.App.Quant ad alanını uygular. Eğitim komut dosyası çok esnektir, herhangi bir sayıda girdi göstergesine kolayca ayarlanabilir. MetaTrader 5 dizin konumunu yalnızca DIRECTORY sabitinde değiştirmelisiniz.
Ağ mimarisi ve eğitim parametreleri, aşağıdaki değişkenler değiştirilerek kolayca özelleştirilebilir:
/// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01;
Kod fazlasıyla açıktır, bu nedenle yapabileceğiniz en iyi şey dikkatlice okumak olacaktır:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Encog.App.Quant.Normalize; using Encog.Util.CSV; using Encog.App.Quant.Indicators; using Encog.App.Quant.Indicators.Predictive; using Encog.App.Quant.Temporal; using Encog.Neural.NeuralData; using Encog.Neural.Data.Basic; using Encog.Util.Simple; using Encog.Neural.Networks; using Encog.Neural.Networks.Layers; using Encog.Engine.Network.Activation; using Encog.Persist; namespace NetworkTrainer { public class Program { /// <summary> /// The directory that all of the files will be stored in. /// </summary> public const String DIRECTORY = "d:\\mt5\\MQL5\\Files\\"; /// <summary> /// The input file that starts the whole process. This file should be downloaded from NinjaTrader using the EncogStreamWriter object. /// </summary> public const String STEP1_FILENAME = DIRECTORY + "mt5export.csv"; /// <summary> /// We apply a predictive future indicator and generate a second file, with the additional predictive field added. /// </summary> public const String STEP2_FILENAME = DIRECTORY + "step2_future.csv"; /// <summary> /// Next the entire file is normalized and stored into this file. /// </summary> public const String STEP3_FILENAME = DIRECTORY + "step3_norm.csv"; /// <summary> /// The file is time-boxed to create training data. /// </summary> public const String STEP4_FILENAME = DIRECTORY + "step4_train.csv"; /// <summary> /// Finally, the trained neural network is written to this file. /// </summary> public const String STEP5_FILENAME = DIRECTORY + "step5_network.eg"; /// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01; static void Main(string[] args) { // Step 1: Create future indicators Console.WriteLine("Step 1: Analyze MT5 Export & Create Future Indicators"); ProcessIndicators ind = new ProcessIndicators(); ind.Analyze(STEP1_FILENAME, true, CSVFormat.DECIMAL_POINT); int externalIndicatorCount = ind.Columns.Count - 3; ind.AddColumn(new BestReturn(RESULT_WINDOW,true)); ind.Process(STEP2_FILENAME); Console.WriteLine("External indicators found: " + externalIndicatorCount); //Console.ReadKey(); // Step 2: Normalize Console.WriteLine("Step 2: Create Future Indicators"); EncogNormalize norm = new EncogNormalize(); norm.Analyze(STEP2_FILENAME, true, CSVFormat.ENGLISH); norm.Stats[0].Action = NormalizationDesired.PassThrough; // Date norm.Stats[1].Action = NormalizationDesired.PassThrough; // Time norm.Stats[2].Action = NormalizationDesired.Normalize; // Close norm.Stats[3].Action = NormalizationDesired.Normalize; // Stoch K norm.Stats[4].Action = NormalizationDesired.Normalize; // Stoch Dd norm.Stats[5].Action = NormalizationDesired.Normalize; // WilliamsR norm.Stats[6].Action = NormalizationDesired.Normalize; // best return [RESULT_WINDOW] norm.Normalize(STEP3_FILENAME); // neuron counts int inputNeurons = INPUT_WINDOW * externalIndicatorCount; int outputNeurons = PREDICT_WINDOW; // Step 3: Time-box Console.WriteLine("Step 3: Timebox"); //Console.ReadKey(); TemporalWindow window = new TemporalWindow(); window.Analyze(STEP3_FILENAME, true, CSVFormat.ENGLISH); window.InputWindow = INPUT_WINDOW; window.PredictWindow = PREDICT_WINDOW; int index = 0; window.Fields[index++].Action = TemporalType.Ignore; // date window.Fields[index++].Action = TemporalType.Ignore; // time window.Fields[index++].Action = TemporalType.Ignore; // close for(int i=0;i<externalIndicatorCount;i++) window.Fields[index++].Action = TemporalType.Input; // external indicators window.Fields[index++].Action = TemporalType.Predict; // PredictBestReturn window.Process(STEP4_FILENAME); // Step 4: Train neural network Console.WriteLine("Step 4: Train"); Console.ReadKey(); INeuralDataSet training = (BasicNeuralDataSet)EncogUtility.LoadCSV2Memory(STEP4_FILENAME, inputNeurons, outputNeurons, true, CSVFormat.ENGLISH); BasicNetwork network = new BasicNetwork(); network.AddLayer(new BasicLayer(new ActivationTANH(), true, inputNeurons)); network.AddLayer(new BasicLayer(new ActivationTANH(), true, HIDDEN1_NEURONS)); network.AddLayer(new BasicLayer(new ActivationLinear(), true, outputNeurons)); network.Structure.FinalizeStructure(); network.Reset(); //EncogUtility.TrainToError(network, training, TARGET_ERROR); EncogUtility.TrainConsole(network, training, 3); // Step 5: Save neural network and stats EncogMemoryCollection encog = new EncogMemoryCollection(); encog.Add("network", network); encog.Add("stat", norm.Stats); encog.Save(STEP5_FILENAME); Console.ReadKey(); } } }
Bir satırı yorumladığımı ve eğitim işlevini EncogUtility.TrainToError() yerine EncogUtility.TrainConsole() olarak değiştirdiğimi fark edebilirsiniz.
EncogUtility.TrainConsole(network, training, 3);
TrainConsole yöntemi, ağın eğitileceği dakika sayısını belirtir. Bu örnekte ağı üç dakika boyunca eğitiyorum. Ağın karmaşıklığına ve eğitim verilerinin boyutuna bağlı olarak, ağın eğitilmesi dakikalar, saatler hatta günler boyu sürebilir. Heaton Research web sitesinde veya konuyla ilgili başka herhangi bir kitapta hata hesaplama ve eğitim algoritmaları hakkında daha fazla okuma yapmanızı tavsiye ederim.
EncogUtility.TrainToError() yöntemleri, hedef koyulan bir ağ hatasına ulaşıldıktan sonra ağı eğitmeyi durdurur. Orijinal örnekte olduğu gibi ağı istenen bir hata bulunana kadar eğitmek için EncongUtiliy.TrainConsole() yorumunu yapabilir ve EncogUtility.TrainToError() yorumunu kaldırabilirsiniz.
EncogUtility.TrainToError(network, training, TARGET_ERROR);
Lütfen, bazen nöronların sayısı çok az olduğundan, ağın belirli bir hataya kadar eğitilemediğini unutmayın.
8. MetaTrader 5 Sinir Göstergesi Oluşturmak için Eğitilmiş Sinir Ağını Kullanma
Eğitilmiş ağ, en iyi yatırım getirisini tahmin etmeye çalışan bir sinir ağı göstergesi tarafından kullanılabilir.
MetaTrader 5’te ENCOG sinir göstergesi iki bölümden oluşur. Bir kısım MQL5'te yazılmıştır ve temelde ağın eğitildiği göstergelerle aynı göstergeleri alır ve girdi penceresi gösterge değerleri ile ağı besler. İkinci kısım C# ile yazılmıştır ve girdi verilerini zaman sınırlarının arasına yerleştirir ve sinir ağı çıkışını MQL5'e geri döndürür. C# gösterge kısmı, C# kodunu MQL5'e Tanıtma konusundaki daha önce yazdığım makaleme dayanmaktadır.
using System; using System.Collections.Generic; using System.Text; using RGiesecke.DllExport; using System.Runtime.InteropServices; using Encog.Neural.Networks; using Encog.Persist; using Encog.App.Quant.Normalize; using Encog.Neural.Data; using Encog.Neural.Data.Basic; namespace EncogNeuralIndicatorMT5DLL { public class NeuralNET { private EncogMemoryCollection encog; public BasicNetwork network; public NormalizationStats stats; public NeuralNET(string nnPath) { initializeNN(nnPath); } public void initializeNN(string nnPath) { try { encog = new EncogMemoryCollection(); encog.Load(nnPath); network = (BasicNetwork)encog.Find("network"); stats = (NormalizationStats)encog.Find("stat"); } catch (Exception e) { Console.WriteLine(e.StackTrace); } } }; class UnmanagedExports { static NeuralNET neuralnet; [DllExport("initializeTrainedNN", CallingConvention = CallingConvention.StdCall)] static int initializeTrainedNN([MarshalAs(UnmanagedType.LPWStr)]string nnPath) { neuralnet = new NeuralNET(nnPath); if (neuralnet.network != null) return 0; else return -1; } [DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total) { INeuralData input = new BasicNeuralData(3 * len); int index = 0; for (int i = 0; i <len; i++) { input[index++] = neuralnet.stats[3].Normalize(t1[i]); input[index++] = neuralnet.stats[4].Normalize(t2[i]); input[index++] = neuralnet.stats[5].Normalize(t3[i]); } INeuralData output = neuralnet.network.Compute(input); double d = output[0]; d = neuralnet.stats[6].DeNormalize(d); result[rates_total-1]=d; return 0; } } }
Üçten başka herhangi bir sayıda gösterge kullanmak isterseniz, computeNNIndicator() yöntemini ihtiyaçlarınıza uygun şekilde değiştirmeniz gerekir.
[DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total)
Bu durumda, ilk üç giriş parametresi, gösterge giriş değerlerini içeren tablolar olacaktır, dördüncü parametre ise girdi penceresinin uzunluğudur.
SizeParamIndex =3, giriş değişkenleri sayısı 0'dan itibaren artırıldığından, pencere uzunluğu değişkenliğini gösterir. Beşinci parametre, sinir ağı sonuçlarını içeren bir tablodur.
MQL5 gösterge bölümünün, bir C# EncogNNTrainDLL.dll dosyasını içe aktarması ve dll'den dışa aktarılan initializeTrainedNN() ve computingNNIndicator() işlevlerini kullanması gerekir.
//+------------------------------------------------------------------+ //| NeuralEncogIndicator.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" #property indicator_separate_window #property indicator_plots 1 #property indicator_buffers 1 #property indicator_color1 Blue #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #import "EncogNNTrainDLL.dll" int initializeTrainedNN(string nnFile); int computeNNIndicator(double& ind1[], double& ind2[],double& ind3[], int size, double& result[], int rates); #import int INPUT_WINDOW = 6; int PREDICT_WINDOW = 1; double ind1Arr[], ind2Arr[], ind3Arr[]; double neuralArr[]; int hStochastic; int hWilliamsR; int hNeuralMA; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, neuralArr, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_SHIFT, 1); ArrayResize(ind1Arr, INPUT_WINDOW); ArrayResize(ind2Arr, INPUT_WINDOW); ArrayResize(ind3Arr, INPUT_WINDOW); ArrayInitialize(neuralArr, 0.0); ArraySetAsSeries(ind1Arr, true); ArraySetAsSeries(ind2Arr, true); ArraySetAsSeries(ind3Arr, true); ArraySetAsSeries(neuralArr, true); hStochastic = iStochastic(NULL, 0, 8, 5, 5, MODE_EMA, STO_LOWHIGH); hWilliamsR = iWPR(NULL, 0, 21); Print(TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\Files\step5_network.eg"); initializeTrainedNN(TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\Files\step5_network.eg"); //--- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { //--- int calc_limit; if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start calc_limit=rates_total-34; else calc_limit=rates_total-prev_calculated; ArrayResize(neuralArr, rates_total); for (int i=0; i<calc_limit; i++) { CopyBuffer(hStochastic, 0, i, INPUT_WINDOW, ind1Arr); CopyBuffer(hStochastic, 1, i, INPUT_WINDOW, ind2Arr); CopyBuffer(hWilliamsR, 0, i, INPUT_WINDOW, ind3Arr); computeNNIndicator(ind1Arr, ind2Arr, ind3Arr, INPUT_WINDOW, neuralArr, rates_total-i); } //Print("neuralArr[0] = " + neuralArr[0]); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Lütfen USDCHF günlük verilerine dayalı eğitilen gösterge çıktılarını ve Stokastik ve Williams %R göstergelerine bakınız.
Şekil 7. Sinirsel Encog göstergesi
Gösterge, bir sonraki çubukta tahmin edilen en iyi yatırım getirisini gösterir.
Gelecek kısmında göstergeyi bir çubuk değiştirdiğimi fark etmiş olabilirsiniz:
PlotIndexSetInteger(0, PLOT_SHIFT, 1);
Bu, göstergenin tahmin etme görevi olduğunu belirtmek içindir. Sinirsel göstergeyi oluşturduğumuzdan, bu göstergeye dayalı bir Expert Advisor oluşturmaya hazırız.
9. Sinirsel Göstergeye Dayalı Expert Advisor
Expert Advisor, sinirsel gösterge çıktısını alır ve bir menkul kıymeti alıp satma konusunda karar verir. İlk izlenimim şu yöndeydi, gösterge sıfırın üzerindeyken satın almalı ve sıfırın altındayken satmalı, yani belirli bir zaman aralığındaki en iyi getiri tahmini pozitif olduğunda alınmalı ve en iyi getiri tahmini negatif olduğunda satılmalı.
Yaptığım ilk testlerden sonra performansın daha iyi olabileceği ortaya çıktı, bu yüzden 'güçlü yükseliş trendi' ve 'güçlü düşüş trendi' değişkenlerini tanıttım, yani meşhur 'trend dostunuzdur’ kuralına göre güçlü bir trend olduğunda ticaretten çıkmak için hiçbir neden yok.
Ek olarak Heaton Research forumunda hareketli kayıp durdurma için ATR kullanmam tavsiye edildi, bu yüzden MQL5 forumunda bulduğum Chandelier ATR göstergesini kullandım. Geriye dönük testler sırasında öz sermaye kazancını gerçekten artırdı. Expert Advisor'ın kaynak kodunu aşağıya yapıştırıyorum.
//+------------------------------------------------------------------+ //| NeuralEncogAdvisor.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" double neuralArr[]; double trend; double Lots=0.3; int INPUT_WINDOW=8; int hNeural,hChandelier; //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArrayResize(neuralArr,INPUT_WINDOW); ArraySetAsSeries(neuralArr,true); ArrayInitialize(neuralArr,0.0); hNeural=iCustom(Symbol(),Period(),"NeuralEncogIndicator"); Print("hNeural = ",hNeural," error = ",GetLastError()); if(hNeural<0) { Print("The creation of ENCOG indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("ENCOG indicator initialized"); hChandelier=iCustom(Symbol(),Period(),"Chandelier"); Print("hChandelier = ",hChandelier," error = ",GetLastError()); if(hChandelier<0) { Print("The creation of Chandelier indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("Chandelier indicator initialized"); //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- long tickCnt[1]; int ticks=CopyTickVolume(Symbol(),0,0,1,tickCnt); if(tickCnt[0]==1) { if(!CopyBuffer(hNeural,0,0,INPUT_WINDOW,neuralArr)) { Print("Copy1 error"); return; } // Print("neuralArr[0] = "+neuralArr[0]+"neuralArr[1] = "+neuralArr[1]+"neuralArr[2] = "+neuralArr[2]); trend=0; if(neuralArr[0]<0 && neuralArr[1]>0) trend=-1; if(neuralArr[0]>0 && neuralArr[1]<0) trend=1; Trade(); } } //+------------------------------------------------------------------+ //| Tester function | //+------------------------------------------------------------------+ double OnTester() { //--- //--- return(0.0); } //+------------------------------------------------------------------+ void Trade() { double bufChandelierUP[2]; double bufChandelierDN[2]; double bufMA[2]; ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufMA,true); CopyBuffer(hChandelier,0,0,2,bufChandelierUP); CopyBuffer(hChandelier,1,0,2,bufChandelierDN); MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,3,rates); bool strong_uptrend=neuralArr[0]>0 && neuralArr[1]>0 && neuralArr[2]>0 && neuralArr[3]>0 && neuralArr[4]>0 && neuralArr[5]>0 && neuralArr[6]>0 && neuralArr[7]>0; bool strong_downtrend=neuralArr[0]<0 && neuralArr[1]<0 && neuralArr[2]<0 && neuralArr[3]<0 && neuralArr[4]<0 && neuralArr[5]<0 && neuralArr[6]<0 && neuralArr[7]<0; if(PositionSelect(_Symbol)) { long type=PositionGetInteger(POSITION_TYPE); bool close=false; if((type==POSITION_TYPE_BUY) && (trend==-1)) if(!(strong_uptrend) || (bufChandelierUP[0]==EMPTY_VALUE)) close=true; if((type==POSITION_TYPE_SELL) && (trend==1)) if(!(strong_downtrend) || (bufChandelierDN[0]==EMPTY_VALUE)) close=true; if(close) { CTrade trade; trade.PositionClose(_Symbol); } else // adjust s/l { CTrade trade; if(copied>0) { if(type==POSITION_TYPE_BUY) { if(bufChandelierUP[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierUP[0],0.0); } if(type==POSITION_TYPE_SELL) { if(bufChandelierDN[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierDN[0],0.0); } } } } if((trend!=0) && (!PositionSelect(_Symbol))) { CTrade trade; MqlTick tick; MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,INPUT_WINDOW,rates); if(copied>0) { if(SymbolInfoTick(_Symbol,tick)==true) { if(trend>0) { trade.Buy(Lots,_Symbol,tick.ask); Print("Buy at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } if(trend<0) { trade.Sell(Lots,_Symbol,tick.bid); Print("Sell at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } } } } } //+------------------------------------------------------------------+
Expert Advisor, USDCHF para birimi D1 verileri kullanılarak çalıştırıldı. Verilerin yaklaşık %50'si eğitim örneğinden alınmıştı.
10. Expert Advisor’ın Geriye Dönük Test Sonuçları
Geriye dönük test sonuçlarını aşağıya yapıştırıyorum. Geriye dönük test 2000.01.01'den 2011.03.26'ya kadar yapılmıştır.
Şekil 8. Sinirsel Expert Advisor’ın geriye dönük test sonuçları
Şekil 9. Sinirsel Expert Advisor’ın Bakiye/Öz sermaye üzerine geriye dönük test grafiği
Lütfen bu performansın diğer zaman dilimleri ve diğer menkul kıymetler için tamamen farklı olabileceğini unutmayın.
Lütfen bu EA'yı eğitici olarak ele alın ve daha fazla araştırma için bir başlangıç noktası olarak kullanın. Benim kişisel görüşüm, ağın daha sağlam hale getirmek için belirli bir zaman diliminde yeniden eğitilebileceğidir, belki birileri bunu başarmak için iyi bir yol bulacaktır ve hatta belki çoktan bulmuştur. Belki de sinirsel bir göstergeye dayalı Al/Sat tahminleri yapmanın daha iyi bir yolu vardır. Okuyucuları bu konuda denemeler yapmaya teşvik ediyorum.
Sonuç
Aşağıdaki makalede, ENCOG makine öğrenimi çerçevesinin yardımıyla bu göstergeye dayalı bir sinirsel tahmin edici gösterge ve expert advisor oluşturmanın bir yolunu sundum. Tüm kaynak kod, derlenmiş ikili dosyalar, DLL'ler ve örnek bir eğitimli ağ makalede ek olarak verilmiştir.
".NET'te çift DLL kaydırma" nedeniyle Cloo.dll, encog-core-cs.dll ve log4net.dll dosyaları istemci terminalinin klasöründe bulunur.
EncogNNTrainDLL.dll dosyası \Terminal Data klasörü\MQL5\Libraries\ klasöründe bulunur.
MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/252
- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz