Algolab Tanıtım

Size daha iyi, hızlı ve güvenli bir kullanım sağlamak amacıyla web sitemizde çerezleri kullanıyoruz.
Gerçekleştirilen işlemlerin log kayıtları alınmakta ve geriye dönük saklanmaktadır.
Çerezleri kapatmak için “Ayarlar/Gizlilik/İçerik Ayarları/Çerez kullanımını kapat” seçeneğini kullanabilirsiniz. Ayrıntılı bilgi için Çerez Politikasını inceleyiniz..

check_circle_outline highlight_off
Kodlama Rehberi

Engine Kütüphanesi Nedir?

Engine Kütüphanesi, algoritmalarınızı kolayca kodlayabilmeniz için bazı finansal indikatör ve fonksiyonları barındıran kütüphanedir. Engine kütüphanesi C# yazılım dili altyapısıyla oluşturulmuştur. Engine kütüphanesi içinde bulunan tüm metotları temel C# bilgisiyle kullanabilirsiniz. Kodlama editöründe "Engine." komutu ile kullanabileceğiniz bu kütüphane ile ilgili bilgilere bu makalede yer vereceğiz.

Stratejilerinizi Kodlamaya Başlarken

Öncelikle Kodlama yapısından bahsedelim.


                                       public void Load()
                                       {

                                       }

                                       public void PriceChanged(Tick t)
                                       {

                                       }

                                       public void OrderStatusChanged(Order o)
                                       {

                                       }

                                       public void DepthChanged(Depth d)
                                       {

                                       }
                                

Kodlama yaparken Load, PriceChanged, OrderStatusChanged ve DepthChanged adında dört adet fonksiyonumuz mevcuttur. Bu fonksiyonlar adlarından da anlaşılacağı üzere Load fonksiyonu strateji çalışmadan önce yükleme yapacağı fonksiyondur. PriceChanged fonksiyonu fiyat değişikliklerinde çalışan bir fonksiyondur. OrderStatusChanged fonksiyonu emrin statüsü değiştiğinde çalışan fonksiyondur. DepthChanged fonksiyonu ise sembolün derinliği değiştiğinde çalışan fonksiyondur.

Ayrıca Engine kütüphanesi kendi içinde kolaylık sağlayan bazı genel tanımlamalara sahiptir. Bu tanımları kodunuzun içinde istediğiniz yerde kullanabilirsiniz.

Sistem Fonksiyonları

Sembole Abone Olma

SubscribePrice(Sembol);

Bu fonksiyon ile yazmış olduğunuz sembole abone olarak ona ait fiyatları çekebilirsiniz. Bu fonksiyonu Load fonksiyonu içerisinde kullanmadan fiyatlara erişim sağlayamazsınız. Detaylı örneklerine sonraki bölümlerde yer verilecektir.

Fiyat Getir

public List<Bar> GetCandles(string symbol, string period, int count = 250, string provider = "")

Stratejinizde birden fazla sembolün verisini kullanmak istiyorsanız bu fonksiyon ile o sembole ait verileri çekebilirsiniz. Bu fonksiyonu kodunuzun başında bir defa çağırmanız yeterlidir. İlk parametreye büyük harflerle sembolün adı, ikinci parametreye ise dakika cinsinden periyot verilmelidir.count parametresine bar sayısını giriyoruz. Girilmez ise 250 adet bar getirmektedir.

Derinlik Getir

public Dictionary<int,Depth> GetDepths(string symbol, string provider = "")

Stratejinizde birden fazla sembolün derinlik verisini kullanmak istiyorsanız bu fonksiyon ile o sembole ait derinlik verileri çekebilirsiniz. Bu fonksiyonu kodunuzun başında bir defa çağırmanız yeterlidir. İlk parametreye büyük harflerle sembolün adı girilmelidir.

EmirGonder

public string SendOrder(string symbol, Directions direction, double lot, PriceTypes pricetype, double price = 0, string comment = """")

Emir göndermek için bu fonksiyon kullanılır. İlk üç parametresi zorunlu olmakla birlikte emir tipi, emir fiyatı ve emir geçerlilik süresi gibi değişkenler isteğe bağlı olarak ayarlanabilir.

symbol : Emrin gönderileceği sembol string olarak verilmelidir.

direction : Emrin yönü birkaç farklı şekilde verilebilir; Directions.BUY, Directions.SELL şeklinde alış veya satış verilebilir.

lot : Emrin kaç lot olacağı float olarak verilmelidir.

pricetype :PriceTypes.Market veya PriceTypes.Limit olmalıdır. Limit emir verilmesi durumunda sonraki parametrede fiyat bilgisi girilmelidir.

price : Limit emirlerde emrin fiyatını belirler.


Pozisyonlari Kapat

public string ClosePositions(string sembol)

Bu metot stratejinizin o anki pozisyon bilgisini okuyarak ters yönde aynı miktarda emir gönderir. Böylece stratejiye ait açık pozisyonlarınız sıfırlanmış olur.

Engine Fonksiyonları

Engine kütüphanesi fonksiyonları algoritmalarda sık kullanılan işlemleri barındır. Örneğin standart sapma, kare kök alma gibi fonksiyonlara sahiptir. Ayrıca "FiyatGetir" gibi fonksiyonlarla bar listesinden kapanış, açılış, yüksek, düşük gibi listeleri elde edebileceğiniz fonksiyonlarda bulunur. Engine fonksiyonlarının detaylarına diğer makalelerde yer verilmiştir.

Engine İndikatörleri

Engine kütüphanesi 80 üzerinde indikatörle geniş bir yelpazeye sahiptir. Bu indikatörleri "Engine." komutuyla listeletebilir ve parametrelerini görebilirsiniz. İndikatörlerin ne işe yaradıkları, kullanımları ile ilgili makaleleri Teknik Kütüphane'de bulabilirsiniz.

İlk Stratejim

Bir sembolde belirli bir fiyat seviyesi kesildiğinde işlem yapacak bir strateji yazalım.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int rsiperiod =1;
                    int lot = 1000;
                    double seviye = 2.06f;

                    public void PriceChanged(Tick t)
                    {
                        var candles = GetCandles("GARAN","5");
                        var C = Engine.GetPriceList(candles, PriceFields.Close);

                        if(Engine.PreviousValue(C,1) >= seviye && SonYon != "A")
                        {
                            //ALIŞ koşulu gerçekleşti, SonYon değerimizi eşitliyoruz.
                            SonYon = "A";
                            //Emir gönder fonksiyonu ile emri belirlediğimiz “lot” miktarında gönderiyoruz.
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

İndikatör Kullanmak

Hareketli ortalamanın kesişimine göre çalışan bir strateji yazalım. Buna göre Hareketli ortalama değeri 30 değerini aşağıdan yukarı keserse “ALIŞ”, 70 değerini yukarıdan aşağı keserse “SATIŞ” yapalım.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int rsiperiod =1;
                    int lot=1;

                    public void PriceChanged(Tick t)
                    {
                        var candles = GetCandles("GARAN","5");
                        var C = Engine.GetPriceList(candles, PriceFields.Close);
                        var RSI = Engine.RSI(C, rsiperiod);
                        if( Engine.PreviousValue(RSI, 1) < 30 && Engine.PreviousValue(RSI, 2) > 30 && SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                        }
                        else if(Engine.PreviousValue(RSI,1) > 70 && Engine.PreviousValue(RSI, 2) < 70 && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

İndikatör Kullanmak 2

Bazı indikatörlerde birden fazla çizgi bulunur. Örneğin Bollinger Bantları Üst, Orta ve Alt bantlar olmak üzere 3 çizgiye sahiptir. Bollinger Bantları kullanan bir strateji oluşturalım.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int rsiperiod =1;
                    int lot=1;

                    public void PriceChanged(Tick t)
                    {
                        var candles = GetCandles("GARAN","5");
                        var C = Engine.GetPriceList(candles, PriceFields.Close);
                        //Bollinger indikatörünü alalım.
                        var bollinger = Engine.BollingerBands(candles,14,2);

                        //Bollinger çizgilerinden hangisini almak istediğimizi aşağıdaki gibi belirteceğiz.
                        //Alt çizgi
                        List<double> altBollinger = bollinger[2];
                        //Orta çizgi
                        List<double> ortaBollinger = bollinger[1];
                        //Üst çizgi 0 verilmesinin sebebi ilk sıranın her zaman 0'dan başlamısıdır.
                        List<double> ustBollinger = bollinger[0];
                        //Üst çizginin kapanmış son mumdaki değerini alalım.
                        double ustSonDeger = Engine.PreviousValue(ustBollinger, 1);
                        //Alt çizginin kapanmış son mumdaki değerini alalım.
                        double altSonDeger = Engine.PreviousValue(altBollinger, 1);
                        //Bir önceki kapanış değerimizi alalım.
                        double sonKapanis = Engine.PreviousValue(C, 1);

                        //Kapanış değeri üst çizginin üstünde kalırsa ALIŞ yapalım
                        if(sonKapanis > ustSonDeger && SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                        }
                        //Kapanış değeri alt çizginin altında kalırsa SATIŞ yapalım
                        else if(sonKapanis < altSonDeger && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Double Lot Strateji

İşleme girerken bir önceki pozisyonu kapatacak ve diğer yönde pozisyona geçecek bir strateji yazalım. Bu stratejide açığa satış durumu söz konusu olduğu için sadece VİOP sembollerinde çalıştırılması tavsiye edilir. Emir gönderilirken “SonPozisyon” değişkeni otomatik olarak emir miktarı kadar artar veya azalır. Örneğin 3 lot ALIŞ işlemi sonrası SonPozisyon = 3 olacaktır. Daha sonra 4 lot SATIŞ işlemi gönderildiğinde SonPozisyon = (3 -4) = -1 olacaktır.

Aşağıda geçmiş örnekte verdiğimiz stratejiyi ters işleme girecek şekilde değiştireceğiz.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;

                    public void PriceChanged(Tick t)
                    {
                        var candles = GetCandles("GARAN","5");
                        var C = Engine.GetPriceList(candles, PriceFields.Close);                        

                        var ma1 = Engine.MovingAverage(C,MovingAverageMethods.Simple,50);
                        var madeger1 = Engine.PreviousValue(ma1,1);
                        var ma2 = Engine.MovingAverage(C,MovingAverageMethods.Simple,200);
                        var madeger2 = Engine.PreviousValue(ma2,1);

                        if(madeger1 > madeger2 && SonYon != "A")
                        {
                            SonYon = "A";
                            //SonPozisyon değişkeninin mutlak değerini alıp üzerine lot miktarımızı ekliyoruz.
                            SendOrder("GARAN",Directions.BUY,Engine.AbsoluteValue(SonPozisyon) + lot,PriceTypes.Market);
                            SonPozisyon=lot*1;
                        }
                        if(madeger1 < madeger2 && SonYon != "S")
                        {
                            SonYon = "S";
                            //SonPozisyon değişkeninin mutlak değerini alıp üzerine lot miktarımızı ekliyoruz.
                            SendOrder("GARAN",Directions.SELL,Engine.AbsoluteValue(SonPozisyon) + lot,PriceTypes.Market);
                            SonPozisyon=lot*(-1);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Zamana Bağlı Strateji

Stratejilerde zamana bağlı koşullar yazılabilir. Örneğin saat 17 sonrasında işlemleri kapatacak bir koşul yazabiliriz. Zamana bağlı strateji kullanırken iki farklı tarihten yola çıkabiliriz. Birincisi sistem saatini kullanarak o anki saati elde etmek. İkincisi ise mum grafiğindeki son mum çubuğunun tarihini alarak en yakın saati elde etmek.

Örnek verecek olursak 5 dakikalık periyotta çalışan bir strateji için;


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;

                    public void PriceChanged(Tick t)
                    {
                        var candles = GetCandles("GARAN","5");
                        var C = Engine.GetPriceList(candles, PriceFields.Close);

                        //RSI indikatörünün 30 ve 70 seviyelerini geçmesi durumunda işlem yapan ve saat 17’de pozisyonları kapatan bir strateji yazalım.
                        var rsi = Engine.RSI(C,14);
                        var rsideger1 = Engine.PreviousValue(rsi,1);

                        //Stratejinin çalıştığı mum grafiğindeki son mum tarihini alalım.
                        DateTime sonMumTarihi = candles[candles.Count - 1].Date;

                        //Son mum barının saati 17'den küçükse ALIŞ veya SATIŞ yapılabilsin.
                        if(sonMumTarihi.Hour < 17)
                        {
                            if(rsideger1 > 70 && SonYon != "A")
                            {
                                SonYon = "A";
                                SendOrder("GARAN",Directions.BUY,Engine.AbsoluteValue(SonPozisyon) + lot,PriceTypes.Market);
                                SonPozisyon=lot*1;
                            }
                            if(rsideger1 < 30 && SonYon != "S")
                            {
                                SonYon = "S";
                                SendOrder("GARAN",Directions.SELL,Engine.AbsoluteValue(SonPozisyon) + lot,PriceTypes.Market);
                                SonPozisyon=lot*(-1);
                            }
                        }
                        //Son mum barının saati 17 ise işlemler kapansın.
                        if(sonMumTarihi.Hour == 17 && SonYon != "F")
                        {
                            //Pozisyonları kapat ve son yönü flat yap.
                            SonYon = "F";
                            ClosePositions("GARAN");
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Çoklu Sembol&Periyot Stratejisi

Stratejiler çalıştırılırken bir sembol ve periyot seçilir. Fakat bazı stratejilerde birden fazla sembol ve periyot kullanma ihtiyacı olabilir. Bu durumda stratejinin çalıştırıldığı sembol ve periyot haricinde bir veri almak için aşağıdaki gibi kodlama yapılmalıdır. Bu örnekte stratejiyi GARAN 15 dakikalık periyotta çalıştırdığımızı düşünelim. Buna ek olarak stratejide GARAN 120 dakikalık periyota ait verileri de kullanacağız.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;

                    public void PriceChanged(Tick t)
                    {
                        //Kodun en başında kullanmak istediğimiz sembol ve periyotu belirtiyoruz.
                        var candles15 = GetCandles("GARAN","15");

                        //Kodun en başında kullanmak istediğimiz birden fazla sembol ve periyotu belirtiyoruz.
                        var candles120 = GetCandles("GARAN","120");

                        //120 dakikalık periyotta SAR indikatörü kullanalım.
                        var SAR120 = Engine.SAR(candles120, 0.02,0.2);

                        //Stratejinin ilk sembol ve periyotunda kapanış listesi ve hareketli ortalama alalım
                        var C = Engine.GetPriceList(candles15, PriceFields.Close);
                        var MA = Engine.MovingAverage(C,MovingAverageMethods.Simple, 22);

                        //120 dakikalık SAR ve diğer periyottaki kapanış değerini karşılaştıran koşulumuz
                        if(Engine.PreviousValue(C,1) > Engine.PreviousValue(SAR120,1) && Engine.PreviousValue(C,1) > Engine.PreviousValue(MA,1) && SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                        }
                        else if(Engine.PreviousValue(C,1) < Engine.PreviousValue(SAR120,1) && Engine.PreviousValue(C,1) < Engine.PreviousValue(MA,1) && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Özel Parametre Kullanmak

Stratejiler içinde tanımlanan değişkenler her fiyat değişiminde yeniden hesaplanır. Bazı durumlarda değişkenleri hafızada tutma ihtiyacı ortaya çıkabilir. Örneğin yapılan son işlemin fiyatını bir değişkende saklayıp daha sonra bu değişkene göre farklı bir işlem yapılmasını istersek stratejide özel bir parametre tanımlamamız gerekecektir.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;
                    //Emir fiyatımızı hafızada tutacak değişkeni ekleyelim.
                    string hangiKosulGerceklesti="";

                    public void PriceChanged(Tick t)
                    {
                        //Kodun en başında kullanmak istediğimiz sembol ve periyotu belirtiyoruz.
                        var candles15 = GetCandles("GARAN","15");

                        var C = Engine.GetPriceList(candles15, PriceFields.Close);
                        var MA5 = Engine.MovingAverage(C,MovingAverageMethods.Simple, 5);
                        var MA22 = Engine.MovingAverage(C,MovingAverageMethods.Simple, 22);
                        var RSI14 = Engine.RSI(C, 14);

                        //Kar al yüzdemizi belirleyelim
                        float karAlYuzde = 0.01f;
                        //Stop yüzdemizi belirleyelim
                        float stopYuzde = 0.01f;

                        //Hareketli ortalama ALIŞ koşulu
                        if(Engine.PreviousValue(MA5,1) > Engine.PreviousValue(MA22,1) &&  SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                            //Emrin gönderildiği koşulu hafızaya alalım.
                            hangiKosulGerceklesti = "MA";
                        }
                        //Hareketli ortalama ALIŞ koşulu
                        if(Engine.PreviousValue(RSI14,1) > 70 &&  SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                            //Emrin gönderildiği koşulu hafızaya alalım.
                            hangiKosulGerceklesti = "RSI";
                        }


                        //Eğer RSI koşulu ile işleme girildiyse
                        //RSI 30 altında SATIŞ yap
                        if(hangiKosulGerceklesti == "RSI" && Engine.PreviousValue(RSI14,1) < 30 && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                        //Eğer MA koşulu ile işleme girildiyse
                        //MA 5 periyot 22 den küçük olduğunda SATIŞ yap
                        if(hangiKosulGerceklesti == "MA" && Engine.PreviousValue(MA5,1) < Engine.PreviousValue(MA22,1) && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Take Profit & Stop Loss Örneği

Belirli bir yüzde ile kar al veya zarar durdur yapan bir strateji oluşturalım. Bu stratejide hareketli ortalama koşuluna göre işleme gireceğiz. İşleme girdiğimiz fiyatı bir değişkende saklamamız gerekiyor çünkü daha sonra bu fiyata göre kar al veya zarar durdur işlemi yapacağız.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;
                    //Emir fiyatımızı hafızada tutacak değişkeni ekleyelim.
                    double SonEmirFiyat=0;

                    public void PriceChanged(Tick t)
                    {
                        //Kodun en başında kullanmak istediğimiz sembol ve periyotu belirtiyoruz.
                        var candles15 = GetCandles("GARAN","15");

                        //Kapanışları ve 2 farklı hareketli ortalamayı alalım
                        var C = Engine.GetPriceList(candles15, PriceFields.Close);
                        var MA5 = Engine.MovingAverage(C,MovingAverageMethods.Simple, 5);
                        var MA22 = Engine.MovingAverage(C,MovingAverageMethods.Simple, 22);

                        //Kar al yüzdemizi belirleyelim
                        float karAlYuzde = 0.01f;
                        //Stop yüzdemizi belirleyelim
                        float stopYuzde = 0.01f;

                        //Hareketli ortalama ALIŞ koşulu
                        if(Engine.PreviousValue(MA5,1) > Engine.PreviousValue(MA22,1) &&  SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                            //Emrin gönderildiği fiyatı hafızaya alalım.
                            SonEmirFiyat = Engine.LastValue(C);
                        }
                        //ALIŞ yönlü işlem yapıldıysa.
                        if(SonYon == "A")
                        {
                            //Kar al kontrolü
                            if(SonEmirFiyat * (1+karAlYuzde) < Engine.LastValue(C))
                            {
                                //Pozisyonları kapat ve yönü Flat yap
                                ClosePositions("GARAN");
                                SonYon = "F";
                            }
                            //Stop loss kontolü
                            if(SonEmirFiyat * (1-karAlYuzde) > Engine.LastValue(C))
                            {
                                //Pozisyonları kapat ve yönü Flat yap
                                ClosePositions("GARAN");
                                SonYon = "F";
                            }
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Kendi İndikatörünü Yaratmak

Engine kütüphanesinde bulunmayan veya size özel indikatörleri de kodlayarak oluşturabilirsiniz. Örneğin son 10 mum çubuğundaki en yüksek ve düşük değerin ortalamasını alan ve bunu bir indikatör gibi kullanan bir strateji yazalım.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int SonPozisyon=0;
                    int lot=500;


                    public void PriceChanged(Tick t)
                    {
                        //Kodun en başında kullanmak istediğimiz sembol ve periyotu belirtiyoruz.
                        var candles15 = GetCandles("GARAN","15");

                        //Yüksek, düşük ve kapanış listelerini alalım.
                        var H = Engine.GetPriceList(candles15, PriceFields.High);
                        var L = Engine.GetPriceList(candles15, PriceFields.Low);
                        var C = Engine.GetPriceList(candles15, PriceFields.Close);

                        //İndikatörümüzün periyotunu belirleyelim
                        int period = 10;
                        //İndikatörümüzü yeni bir liste olarak oluşturalım.
                        List<double> indikatorum = new List<double>();
                        //10. bardan itibaren son bara kadar indikatörümüzü hesaplayacağız.
                        for(int i = period; i < candles15.Count; i ++)
                        {
                            //Son 10 barı listeye alalım.
                            var subList = C.GetRange(i-period, period);
                            //Son 10 barın en düşüğünü bulalım
                            double enDusuk = Engine.LowestValue(subList);
                            //Son 10 barın en yükseğini bulalım
                            double enYuksek = Engine.HighestValue(subList);
                            //En yüksek ve düşüğün ortalamasını alalım
                            double ortalama = (enYuksek + enDusuk) / 2f;
                            //İndikatör listemize değeri ekleyelim.
                            indikatorum.Add(ortalama);
                        }

                        //İndikatörümüzü kullanarak ALIŞ ve SATIŞ koşulu oluşturalım.
                        if(Engine.PreviousValue(indikatorum, 1) > Engine.PreviousValue(indikatorum, 2) && SonYon != "A")
                        {
                            SonYon = "A";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                        }
                        else if(Engine.PreviousValue(indikatorum, 1) < Engine.PreviousValue(indikatorum, 2) && SonYon != "S")
                        {
                            SonYon = "S";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                        }
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }
                                

Log Yazdırmak

Kodlama yaparken sorun çözmek için kullanılabilecek en önemli yöntem backtest’e log yazdırmaktır. Böylece stratejinizde hangi değerlerin kullanıldığını veya hangi koşulların gerçekleştiğini backtest içinde kontrol edebilirsiniz. Aşağıdaki örnekte her yeni mum çubuğunda hareketli ortalamaların son değerlerini log olarak yazdıracaktır. Ayrıca alış ve satış durumunda da tarihle birlikte log yazdıracaktır. Backtest yapıldığında log sekmesi açılacak ve yazdırılanlar burada görülecektir.


                    public void Load()
                    {
                        SubscribePrice("GARAN");
                    }

                    //Genel parametreleri burada tanımlıyoruz.
                    string SonYon = "";
                    int lot=500;
                    string Log="";

                    public void PriceChanged(Tick t)
                    {
                        //Kodun en başında kullanmak istediğimiz sembol ve periyotu belirtiyoruz.
                        var candles15 = GetCandles("GARAN","15");
                        var C = Engine.GetPriceList(candles15, PriceFields.Close);
                        var ma1 = Engine.MovingAverage(C,MovingAverageMethods.Simple,50);
                        var madeger1 = Engine.PreviousValue(ma1,1);
                        var ma2 = Engine.MovingAverage(C,MovingAverageMethods.Simple,200);
                        var madeger2 = Engine.PreviousValue(ma2,1);

                        if(madeger1 > madeger2 && SonYon != "ALIS")
                        {
                            SonYon = "ALIS";
                            SendOrder("GARAN",Directions.BUY,lot,PriceTypes.Market);
                            Log = candles15[candles15.Count - 1].Date + " :: ALIŞ KOŞULU TETİKLENDİ.";
                            SendMessage(MessageTypes.Log, Log);
                        }

                        if(madeger1 < madeger2 && SonYon != "SATIS")
                        {
                            SonYon = "SATIS";
                            SendOrder("GARAN",Directions.SELL,lot,PriceTypes.Market);
                            Log = candles15[candles15.Count - 1].Date + " :: SATIŞ KOŞULU TETİKLENDİ.";
                            SendMessage(MessageTypes.Log, Log);
                        }

                        Log = candles15[candles15.Count - 1].Date + " :: "+ madeger1 + " " + madeger2;
                        SendMessage(MessageTypes.Log, Log);
                    }

                    public void OrderStatusChanged(Order o)
                    {
                    }

                    public void DepthChanged(Depth d)
                    {
                    }