Nasıl yapılır/ SSS #
Q. Mevcut varolan periyotlardan farklı bir bar periyotu nasıl kullanırım?
A. MatriksIQ AlgoTrader’da istediğiniz değerde bir bar periyotu tanımlayabilirsiniz. (şimdilik saniyelik barları desteklememektedir)
Örnek:
AddSymbol(Symbol, new PeriodInfo(PeriodType.Minute,2)); //Varsayılan sembol için 2 dakikalık bir bar periyotu tanımlamaktadır. //Dakikadan küçük barlar henüz desteklenmemektedir.
Q. Stratejiyi 2 farklı periyotta çalıştırabilir miyim?
A. Evet. MatriksIQ istenildiği kadar farklı periyot ve sembol ile çalışmamıza olanak sağlamaktadır. 2 farklı periyot ve 2 farklı enstrüman ile kullanım aşağıda örneklendirilmiştir.
public class rsiHareketliOrtalamasi : MatriksAlgo { [SymbolParameter("GARAN")] public string Symbol_0; [SymbolParameter("AKBNK")] public string Symbol_1; [Parameter(SymbolPeriod.Min5)] public SymbolPeriod SymbolPeriod_5; [Parameter(SymbolPeriod.Min10)] public SymbolPeriod SymbolPeriod_10; //… // public override void OnDataUpdate(BarDataEventArgs barData) { int symbolid_0 = GetSymbolId(Symbol_0); int symbolid_1 = GetSymbolId(Symbol_1); var barDataModel_0 = GetBarData(Symbol_0, SymbolPeriod.Min5); var barDataModel_1 = GetBarData(Symbol_0, SymbolPeriod.Min10); var barDataModel_2 = GetBarData(Symbol_1, SymbolPeriod.Min5); var barDataModel_3 = GetBarData(Symbol_1, SymbolPeriod.Min10); if (symbolid_0 == barData.SymbolId && barDataModel_0.PeriodInfo == barData.PeriodInfo) // Yukarıdaki kod asıl sembollerin datalarının ayrıştırıldığı önemli bölümdür. If bölümü, barData.Symbolid, yani bar kapanışında güncellenen datadan (rastgele) gelen id verisi GetSymbolId(Symbol_0) ile atadığımız unique ID ile karşılaştırılıyor. Aynı yöntemi rastgele gelmiş olan barData.PeriodInfo ile eşleşmek için de kullanmamız gerekiyor. { Close_0 = barDataModel.Close[barData.BarDataIndex-1]; // Ancak ve sadece bu id’ler ve Periotlar aynı oldugunda close olarak tanımladığımız yeni değişkene barDataModel.Close[barData.BarDataIndex-1] ile gelen Sembol’ün (yani bu örnekte ilk sembol(GARAN) ve ilk periyot(5 dakika)) bir önceki kapanışı atanıyor. Böylelikle 2 sembolü ve periyotu ayrıştırmış ve gelen doğru data ile eşleştirmiş oluyoruz. Bundan sonra artık Close_0 değişkenini kod içerisinde GARAN, 5dk’lık bir önceki kapanış olarak kullanabiliriz. } } } }
Q. Bir İndikatörün hareketli ortalamasını alabilir miyiz?
A. Evet, MatriksIQ’da bir indikatörün hareketli ortalamasını hatta indikatörün indikatörünü almak oldukça kolay hale getirilmiştir. Aşağıda RSI indikatörünün hareketli ortalamasını almak için kod içerisinde eklenebilecek satırlar ve eklenmesi gereken bölümler örnek olarak yazılmıştır.
public class rsiHareketliOrtalamasi : MatriksAlgo { [Parameter(10)] public int MovPeriod; MOV movrsi10; RSI myrsi; public override void OnInit() { myrsi = RSIIndicator(Symbol, SymbolPeriod, OHLCType.Close, 14); movrsi10 = MOVIndicator(myrsi, MovPeriod, MovMethod.Simple); }
Kısaca, normalde
mov = MOVIndicator(Symbol, SymbolPeriod, OHLCType.Close, MovPeriod, MovMethod.Simple);
şeklinde tanımlayacağımız mov indikatörünün içerisine Symbol, SymbolPeriod, OHLCType.Close parametrelerini silerek (çünkü bunlar zaten myrsi objesinde tanımlı olacak) RSI indikatörü olarak deklare ettiğimiz rsi objesini yazdığımızda movrsi10 objesi 14 periyotluk bir RSI indikatörünün 10 periyotluk hareketli ortalamasını almış oluyor.
Q. 2 veya daha fazla, farklı sembol kullanarak strateji yazılabilir mi?
A. Evet. Bununla ilgili örnek strateji Hazır Stratejilerde bulunmaktadır (GAOrt2Hisse *Günlük Ağırlıklı Ortalama, 2 Hisse).
Bu stratejide OnInit() fonksiyonu altına:
AddSymbol(Symbol, SymbolPeriod);
AddSymbol(Symbol_1, SymbolPeriod);
Yazılarak 2 sembol eklenmiştir. Daha sonra OnDataUpdate(BarDataEventArgs barData) fonksiyonu altına (her bar açılışında çalışacak fonksiyondur)
—————————————
int symbolid = GetSymbolId(Symbol); int symbolid1 = GetSymbolId(Symbol_1);
yazarak 2 ayrı unique sembol id saklanır.
var barDataModel = GetBarData(Symbol, SymbolPeriod.Min); var barDataModel_1 = GetBarData(Symbol_1, SymbolPeriod.Min);
yazarak 2 ayrı sembol için bar data alınır ve barDataModel ve barDataModel_1 şeklinde isimlendirdiğimiz objelere atar.
if (symbolid == barData.SymbolId) close = barDataModel.Close[barData.BarDataIndex]; if (symbolid1 == barData.SymbolId) close_1 = barDataModel_1.Close[barData.BarDataIndex];
Yukarıdaki kod asıl sembollerin datalarının ayrıştırıldığı önemli bölümdür. If bölümü, barData.Symbolid, yani bar kapanışında güncellenen datadan (rastgele) gelen id verisi GetSymbolId(Symbol) ile atadığımız unique ID ile karşılaştırılıyor. Ancak bu id’ler aynı oldugunda close olarak tanımladığımız yeni değişkene barDataModel.Close[barData.BarDataIndex] ile gelen Sembol’ün (yani ilk sembol/enstrüman) kapanışı atanıyor. Böylelikle 2 sembolü ayrıştırmış oluyoruz.
Bu 4 satır çalıştıktan sonra close değişkeninde 1. sembolün, close_1 değişkeninde ise 2. sembolün kapanış değerleri ayrıştılarak kaydedilmiş oluyor.
Yukarıdaki şekilde sembol eklemeye devam ederek, kod içerisinde kullanılan semboller istenildiği kadar çoğaltılabilmektedir.
Q. if(close < accBands.Lower) seklinde bir ifade tanimladim ama dogru sonuc vermiyor.
A. İndikatorler liste (array) gibi çalışmaktadır. Dolayisiyla accBands.Lower ifadesi büyüktür/küçüktür operatörüyle kullanabileceğimiz bir ifade değildir. Eğer close objesine atadığımız değerin bir indikatörden büyük/küçük olduğunu öğrenmek istiyorsak indikatörün belli bir noktadaki sabit değeri ile kıyaslamamız mantıklı olacaktır. Dolayısıyla bu ifade if(close < accBands.Lower. CurrentValue) şeklinde yazıldığında istenilen sonuç alınabilecektir.
Q. Algotrader rapor penceresine fiyat grafiğine ek grafik ekleyebilir miyiz?
A. Evet. Bu işlem için Fonksiyonlar başlığı altında ki AddChart, AddChartLineName ve Plot fonksiyonlarının kullanılması gerekmektedir.
Örnek:
//Grafiğin adını belirlediğimiz kısım String chartName = "MOST"; AddChart(chartName,2); //Most indikatöründeki most ve exmov çizgilerinin isimlendirilmesi AddChartLineName(chartName, 1, "Most"); AddChartLineName(chartName, 2, "ExMov"); //Most indikatörünün çizdirilmesi Plot(chartName, 1, most.CurrentValue); Plot(chartName, 2,most.ExMOV.CurrentValue);
Q. AlgoTrader’da önceki barlara nasıl erişim sağlayabilirim?
A. Önceki barlara erişim sağlayabilmek için “GetBarData” fonksiyonunu kullanmanız gerekmektedir. Fonksiyonlar başlığı altında bu fonksiyonun işlevlerinden bahsetmiştik. Aşağıdaki kod segmentinde detaylı açıklama bulabilirsiniz.
Ek olarak indikatör ve bardata serilerinin önceki datalarına erişebilmek için Ref() fonksiyonu da kullanılabilir. Örn. Ref(mov,1) mov indikatörünün bir önceki değerini dönecektir.
public override void OnDataUpdate(BarDataEventArgs barData) { //Kayıt olunan bardataya erişimi sağladık. Aşağıdaki kod satırından sonra tüm //bardatalara erisim saglayabiliriz var barDataModel = GetBarData(); //Daha sonra istediğimiz verinin indeksine göre bir koşul kurduk. barData.BarDataIndex //Son bardatanın indeksini bize döndürür. barDataModel.Close[barData.BarDataIndex] //Son bardatanın kapanış verisini döndürür. barDataModel.Open[barData.BarDataIndex-10] //Son bardatadan 10 önceki bardatanın açılış verisini döndürür. if(barDataModel.Close[barData.BarDataIndex] > barDataModel.Open[barData.BarDataIndex-10]) { Debug("Son gelen bar kapanış verisi, 10 bar önceki açılış verisinden daha buyuk"); } }
Q. Kendi endeksimi yaratıp, bu endeksin moving averajını alabilir miyim?
A. Evet! MatriksIQ Algo ile kendi oluşturduğunuz değişkenin hatta kendi indikatörünüzün bile moving averajını yaratabilir, bütün diğer indikatörlerin içerisinde de kullanabilirsiniz. Daha fazla bilgi için aşağıdaki örnek koda ve comment’lere bakınız.
namespace Matriks.Lean.Algotrader { public class rangeMA : MatriksAlgo { // Strateji çalıştırılırken kullanacağımız parametreler. Eğer sembolle ilgili bir parametre ise, // "SymbolParameter" ile, değilse "Parameter" ile tanımlama yaparız. Parantez içindeki değerler default değerleridir. [SymbolParameter("GARAN")] public string Symbol; [Parameter(SymbolPeriod.Min)] public SymbolPeriod SymbolPeriod; [Parameter(4)] public int MovPeriod; MOV mov; /// <summary> /// Strateji ilk çalıştırıldığında bu fonksiyon tetiklenir. Tüm sembole kayit işlemleri, /// indikator ekleme, haberlere kayıt olma işlemleri burada yapılır. /// </summary> public override void OnInit() { AddSymbol(Symbol, SymbolPeriod); mov = new MOV(MovPeriod, MovMethod.Exponential); SendOrderSequential(true); WorkWithPermanentSignal(true); } /// <summary> /// Init islemleri tamamlaninca, bardatalar kullanmaya hazir hale gelince bu fonksiyon tetiklenir. Data uzerinde bir defa yapilacak islemler icin kullanilir /// </summary> public override void OnInitComplated() { } /// <summary> /// Eklenen sembollerin bardata'ları ve indikatorler güncellendikçe bu fonksiyon tetiklenir. /// </summary> /// <param name="barData">Bardata ve hesaplanan gerçekleşen işleme ait detaylar</param> public override void OnDataUpdate(BarDataEventArgs barData) { var range = barData.BarData.High - barData.BarData.Low; //Range isminde, barin en yuksek degerinden en dusuk degerini cikaran yeni bir degisken tanimliyoruz mov.Update(range, barData.BarDataIndex, barData.BarData.Dtime); //Yukarida (OnInit() içerisinde) oluşturduğumuz moving average’a bu değişkeni besliyoruz. Boylelikle range’in 4 periyotluk ussel hareketli ortalamasini almis oluyoruz. Debug(mov.CurrentValue); //Artik range değişkenin ussel hareketli ortalamasi kullanima hazirdir. Kodumuz içerisinde kullanabiliriz. Bu satirda hareketli ortalamanin anlik değerini debug penceresine basarak kontrol sagliyoruz. } /// <summary> /// Gönderilen emirlerin son durumu değiştikçe bu fonksiyon tetiklenir. /// </summary> /// <param name="barData">Emrin son durumu</param> public override void OnOrderUpdate(IOrder order) { if (order.OrdStatus.Obj == OrdStatus.Filled) { } } } }