using System;
using System.Collections.Generic;
using System.Linq;
using Matriks.Data.Symbol;
using Matriks.Engines;
using System.Windows.Media;
using Matriks.Indicators;
using Matriks.Symbols;
using Matriks.AlgoTrader;
using Matriks.Trader.Core;
using Matriks.Trader.Core.Fields;
using Matriks.Trader.Core.TraderModels;
using Matriks.Lean.Algotrader.AlgoBase;
using Matriks.Lean.Algotrader.Models;
using Matriks.Lean.Algotrader.Trading;
using System.Text;
/*
Bu strateji kademeli olarak enstrüman biriktirmeye ya da birikenleri ters işlemle elden çıkartmaya yarar.
EmirYonu -> Bu seçenek işlem açılacak emrin yönünü belirler. ( Buy-Sell )
Örneğe göre strateji alış yönlü emir gönderip enstrüman biriktirecek
BaslangicFiyati -> Bu değişken ilk emrin hangi seviyedeyken gönderileceğini gösterir.
Örneğe göre SISE için son fiyat 14.30'a eşit ya da altındayken alış emri gönderilecek
( isteğe bağlı )
DerinligiKullan -> Bu seçenek aktif edildiğinde BaslangicFiyati olarak emir yönüne göre derinlikteki Aktif1 değeri kullanılır.
AdetArtisYuzdesi-> Bu değişken kademeli işlemlerde BaslangicAdedi'ni belirlenen oranda artırılıp, azaltılmak için kullanılabilir.
Örnek BaslangicAdedi=100, AdetArtisYuzdesi=20 olarak belirlendiğinde ilk emir 100 lot olarak gönderilirken
sonraki emirler 120,144 ...lot olarak gönderilecektir.
Negatif değer olduğunda da ( mesela -20 ) ilk emir 100 sonrakiler 80,64 ... gibi ilerleyecektir.
KademeFarki -> BaslangicFiyati seviyesine gelindiğinde o anki fiyattan emir gönderilir.
Emir gerçekleştiğinde yeni seviye gerçekleşme fiyatından KademeFarki'na göre hesaplanır.
Örneğe göre 14.30'dan alış emri gönderilir. Bu emir 14.30'dan gerçekleştiğiniz varsayalım yeni seviye 14.29 (14.30-0.01) olacaktır.
EmirGonderilmeSayisi -> Şartların sağlanması durumunda üst üste gönderilecek emir sayısı ifade eder ( sadece EmirYonu değişkenindekiler)
örneğe göre 14.30, 14.29, 14.28, 14.27, 14.26, 14.25, 14.24, 14.23, 14.22, 14.21 seviyesinden 10 adet alış emri gönderilecek
( isteğe bağlı )
Makas -> Son fiyat işlem seviyesinden Makas değeri kadar fark olursa işlem seviyesi yeniden hesaplanıp bekleyende emir varsa da düzeltme yapılır.
Örneğe göre 14.30'dan alış emri gönderildi ve bu emir gerçekleşmeden son fiyat yükseldi ve 14.40'a gelirse yeni seviye 14.39 olur
ve bekleyen alış emri de 14.39 olarak düzeltilir.
( isteğe bağlı )
KarAlSeviyesi -> EmirYonu'deki emirler gerçekleştikçe gerçekleşen emre göre belirnen oranda (percent, pricepoint) kar alacak şekilde ters emir gönderilir.
percent-> yüzde, pricepoint puan
örneğe göre 14.30'dan gönderilen alış emri 14.30'dan gerçekleştiğini varsayalım 14.35 satış emri gönderilecek.
***STRATEJİLERİ TEST/DENEME ORTAMINDA SINAMADAN VE SİZİN İSTEDİĞİNİZ ŞEKİLDE ÇALIŞTIĞINA EMİN OLMADAN GERÇEK ORTAMDA HİÇBİR ZAMAN ÇALIŞTIRMAYINIZ ***
*/
namespace Matriks.Lean.Algotrader
{
public class KademeliAlSatSade : MatriksAlgo
{
[Parameter(OrderSide.Buy)]
public OrderSide EmirYonu;
[SymbolParameter("SISE")]
public string Sembol;
[Parameter(14.30)][Output]
public decimal BaslangicFiyati;
[Parameter(false)]
public bool DerinligiKullan;
[Parameter(1)]
public decimal BaslangicAdedi;
[Parameter(0)]
public decimal AdetArtisYuzdesi;
[Parameter(0.01)]
public decimal KademeFarki;
[Parameter(10)]
public int EmirGonderilmeSayisi;
[Parameter(false)]
public bool MakasKullan;
[Parameter(0.1)]
public decimal Makas;
[Parameter(false)]
public bool KarAlKullan;
[Parameter(5)]
public decimal KarAlSeviyesi;
[Parameter(SyntheticOrderPriceType.PricePoint)]
public SyntheticOrderPriceType OranTipi;
[Output]
public bool StrarejiAktifMI = true;
[Output]
public bool durum = true;
[Output]
public decimal CurrentClose;
int Sayac = 1;
decimal carpan = 1;
string emirYonuText = "Satış";
string emirTersYonuText = "Alış";
bool alisMI = false, kriptoMU = false;
decimal priceStep;
double tradeFraction;
double decimalCount;
int exchangeID;
Side orderEmirYonu = new Side(Side.Sell), ordertersEmirYonu = new Side(Side.Buy);
OrderSide tersEmirYonu = OrderSide.Buy;
public override void OnInit()
{
AddSymbol(Sembol, SymbolPeriod.Min);
if (DerinligiKullan)
{
AddSymbolMarketDepth(Sembol);
StrarejiAktifMI = false;
}
}
public override void OnInitComplated()
{
if (EmirYonu == OrderSide.Buy)
{
carpan = -1;
emirYonuText = "Alış ";
emirTersYonuText = "Satış ";
alisMI = true;
tersEmirYonu = OrderSide.Sell;
orderEmirYonu.Obj = Side.Buy;
ordertersEmirYonu.Obj = Side.Sell;
}
var symbolDetail = GetSymbolDetail(Sembol);
tradeFraction = symbolDetail.TradeFraction;
decimalCount = symbolDetail.DecimalCount;
exchangeID = symbolDetail.ExchangeDetail.ExchangeID;
if (exchangeID != (int) ExchangeType.Ise &&
exchangeID != (int) ExchangeType.Viop)
{
kriptoMU = true;
priceStep = 1 / (decimal) Math.Pow(10, symbolDetail.DecimalCount);
BaslangicAdedi = FX_LotAyarla(BaslangicAdedi);
BaslangicFiyati = FX_FiyatAyarla(BaslangicFiyati);
}else
{
var barDataModel = GetBarData();
var close = Ref(barDataModel, OHLCType.Close, 0);
priceStep = GetPriceStepForBistViop(Sembol, close);
BaslangicAdedi = Math.Ceiling(BaslangicAdedi);
BaslangicFiyati = FX_FiyatAyarla(BaslangicFiyati);
}
}
string orderID = string.Empty;
bool ilkIslem = true;
public override void OnDataUpdate(BarDataCurrentValues barDataCurrentValues)
{
// Derinlik kullan
if (DerinligiKullan)
{
var derinlik = GetMarketDepth(Sembol);
var _bayrak = false;
if (alisMI && derinlik.BidRows[1].Price != 0)
{
_bayrak = true;
BaslangicFiyati = derinlik.BidRows[1].Price;
}else if (!alisMI && derinlik.AskRows[1].Price != 0)
{
_bayrak = true;
BaslangicFiyati = derinlik.AskRows[1].Price;
}
if (_bayrak)
{
DerinligiKullan = false;
StrarejiAktifMI = true;
}else
{
Debug("derinlik datası bekleniyor.");
}
}
if (ilkIslem)
{
ilkIslem = false;
Debug("======================== BAŞLA ========================");
Debug("Son fiyat: " + barDataCurrentValues.LastUpdate.Close + " Fiyat seviyesi: " + BaslangicFiyati);
}
// alış ya da satışa göre son fiyat takibi
if (StrarejiAktifMI)
{
CurrentClose = barDataCurrentValues.LastUpdate.Close;
if (Sayac <= EmirGonderilmeSayisi && durum)
{
if ((alisMI && CurrentClose <= BaslangicFiyati) ||
(!alisMI && CurrentClose >= BaslangicFiyati))
{
Debug("======================== YENİ EMİR ========================");
orderID = SendLimitOrder(Sembol, BaslangicAdedi, EmirYonu, BaslangicFiyati);
Debug(emirYonuText + " - fiyat: " + BaslangicFiyati + " adet: " + BaslangicAdedi + " emir gönderildi.");
if (!kriptoMU)
{
BaslangicAdedi = Math.Ceiling(BaslangicAdedi * (1 + AdetArtisYuzdesi / 100));
}else
{
BaslangicAdedi = FX_LotAyarla(BaslangicAdedi * (1 + AdetArtisYuzdesi / 100));
}
Sayac++;
durum = false;
}
}else if (Sayac > EmirGonderilmeSayisi)
{
Debug("======================== BİTİR ========================");
Debug("Belirlenen sayısı kadar işlem yapıldı. Strateji durduruldu.");
StrarejiAktifMI = false;
durum = false;
}
// makas kullan
if (MakasKullan &&
(
(BaslangicFiyati + Makas <= CurrentClose && alisMI) ||
(BaslangicFiyati + Makas >= CurrentClose && !alisMI)
)
)
{
Debug("======================== MAKAS ========================");
Debug("Makas belirlenen seviyede düzenleme yapıldı. Son fiyat: " + CurrentClose);
BaslangicFiyati = CurrentClose + (KademeFarki * carpan);
if (orderID != string.Empty)
{
if (!kriptoMU)
{
SendReplaceOrder(orderID, BaslangicFiyati);
Debug("Gönderilen limit emir düzeltildi. Yeni fiyat: " + BaslangicFiyati);
}else
{
SendCancelOrder(orderID);
orderID = SendLimitOrder(Sembol, BaslangicAdedi, EmirYonu, BaslangicFiyati);
Debug("Emir silinip yeniden gönderildi.");
}
}
}
}
}
public override void OnOrderUpdate(IOrder order)
{
if (order.OrdStatus.Obj == OrdStatus.Filled && order.Side.Obj == orderEmirYonu.Obj)
{
Debug("======================== GERÇELEŞTİ ========================");
Debug(emirYonuText + " emir gerçekleşti. Fiyat: " + order.Price + " - adet: " + order.OrderQty);
BaslangicFiyati = order.Price + (KademeFarki * carpan);
Debug("Yeni fiyat: " + BaslangicFiyati + " yeni adet: " + BaslangicAdedi + " adım: " + Sayac);
durum = true;
if (KarAlKullan)
{
var satisFiyati = 0.0m;
if (OranTipi == SyntheticOrderPriceType.Percent)
{
satisFiyati = FX_FiyatAyarla(order.Price * (1 + (-1 * carpan) * (KarAlSeviyesi / 100)));
}else
{
satisFiyati = FX_FiyatAyarla(order.Price + (-1 * carpan) * (KarAlSeviyesi * priceStep));
}
SendLimitOrder(Sembol, order.OrderQty, tersEmirYonu, satisFiyati);
Debug(emirTersYonuText + " emir gönderildi. Fiyat: " + satisFiyati + " adet: " + order.OrderQty);
}
}
if (order.OrdStatus.Obj == OrdStatus.Filled && order.Side.Obj == ordertersEmirYonu.Obj)
{
Debug("======================== GERÇELEŞTİ ========================");
Debug("Karlı işlem gerçekleşti");
}
if (order.OrdStatus.Obj == OrdStatus.Rejected && order.Side.Obj == orderEmirYonu.Obj)
{
Debug(emirYonuText + " emri iptal oldu");
durum = true;
}
}
public decimal FX_LotAyarla(decimal quantity)
{
double _kuvvet = Math.Pow(10, tradeFraction);
return (decimal)(Math.Truncate((double) quantity * _kuvvet) / _kuvvet);
}
public decimal FX_FiyatAyarla(decimal price)
{
double _kuvvet = Math.Pow(10, decimalCount);
return (decimal)(Math.Truncate((double) price * _kuvvet) / _kuvvet);
}
}
}