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.
Ö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.
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.
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.
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.
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.
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 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 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.
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)
{
}
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)
{
}
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)
{
}
İş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)
{
}
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)
{
}
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)
{
}
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)
{
}
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)
{
}
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)
{
}
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)
{
}