StochasticSlow indikatoru ve SMA kullanan bir stratejidir.

AL koşulu: Haftalık stoch K çizgisi stoch D nin üzerinde ise ve kesiştikleri noktada stoch değeri 40 ın altında ise ve Günlük Stoch K çizgisi stoch D’nin üstünde ise ve kapanış 4 saatlik periyotta SMA period 5 in altında ise piyasa alım emri gönderilir.

SAT koşulu: Haftalık Stoch K çizgisi stoch D nin altında ise ve kesiştikleri noktada stoch değeri 60 ın üzerinde ise ve Günlük Stoch K çizgisi stoch D nin altında ise ve KAPANIŞ 4 saatlik PERİYOTTA sma period 5 in üstünde ise piyasa satış emri gönderilir.

NOT: Tam kesiştikleri noktadaki stoch degeri kontrol edilmek isteniyorsa CrossAbove/Below ve WorkWithPermanentSignal(false); kullanılmalıdır.
Haftalik K’nin, D’nin altında(örneğin SAT için) olmasi yeterli ise o zaman stochasticSlow_Weekly.StochasticSlowK.CurrentValue<stochasticSlow_Weekly.StochasticSlowD.CurrentValue
kullanılmalıdır. Bu nedenle calistir menüsünde radyo butonu eklenmiştir, aktif oldugunda cross kapatildiginda >, < kullanılmaktadır.

using System;
using System.Collections.Generic;
using System.Linq;
using Matriks.Data.Symbol;
using Matriks.Engines;
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;



namespace Matriks.Lean.Algotrader.BuildInStrategies
{
    [BuiltInStrategy]
    public class StochSMA_Strategy : 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(1)]
		public int Quantity;
		[Parameter(SymbolPeriod.Min240)]
		public SymbolPeriod Period_0;
		[Parameter(SymbolPeriod.Day)]
		public SymbolPeriod Period_1;
		[Parameter(SymbolPeriod.Week)]
		public SymbolPeriod Period_2;
		[Parameter(40)]
		public int StochasticBuyCutoff;
		[Parameter(60)]
		public int StochasticSellCutoff;
		[Parameter(true, "Bu parametre seçiliyken strateji koşulları indikatör değerlerinin kırılımlarını kontrol eder, değilse büyüktür/küçüktür kontrolü yapılır.")]
		public bool UseCross;
		[Parameter(true, "Bu parametre seçiliyken strateji kalıcı sinyalde çalışır. Seçilmediği zaman stratejinin geçici sinyalde nasıl çalışacağını bilerek kullanınız.")]
		public bool PermanentSignal;

		StochasticSlow stochasticSlow_Daily;
		StochasticSlow stochasticSlow_Weekly;
		MOV mov_min240;

		public override void OnInit()
		{
			mov_min240 = MOVIndicator(Symbol, Period_0, OHLCType.Close, 5, MovMethod.Simple);
			stochasticSlow_Daily = StochasticSlowIndicator(Symbol, Period_1, OHLCType.Close, 5, 3, 3);
			stochasticSlow_Weekly = StochasticSlowIndicator(Symbol, Period_2, OHLCType.Close, 5, 3, 3);

			AddSymbol(Symbol, Period_0);

			//Eger backtestte emri bir al bir sat seklinde gonderilmesi isteniyor bu true set edilir. 
			//Alttaki satırı silerek veya false geçerek emirlerin sirayla gönderilmesini engelleyebilirsiniz. 
			SendOrderSequential(true);
			WorkWithPermanentSignal(PermanentSignal);
		}

		/// <summary>
		/// Init islemleri tamamlaninca, bardatalar kullanmaya hazir hale gelince bu fonksiyon tetiklenir. Data uzerinde bir defa yapilacak islemler icin kullanilir
		/// </summary>
		public override void OnInitCompleted()
		{

		}

		/// <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(BarDataCurrentValues barDataCurrentValues)
		{
			if (barDataCurrentValues.LastUpdate.SymbolPeriod.Equals(Period_0))
			{
				var close = barDataCurrentValues.LastUpdate.Close;

				var stochSlowDay_K = stochasticSlow_Daily.StochasticSlowK;
				var stochSlowDay_D = stochasticSlow_Daily.StochasticSlowD;
				var stochSlowWeek_K = stochasticSlow_Weekly.StochasticSlowK;
				var stochSlowWeek_D = stochasticSlow_Weekly.StochasticSlowD;

				if (UseCross)
				{
					if (CrossAbove(stochasticSlow_Weekly.StochasticSlowK, stochasticSlow_Weekly.StochasticSlowD)
					&& stochasticSlow_Weekly.StochasticSlowK.CurrentValue < StochasticBuyCutoff
					&& stochasticSlow_Daily.StochasticSlowK.CurrentValue > stochasticSlow_Daily.StochasticSlowD.CurrentValue
					&& close < mov_min240.CurrentValue)
					{
						SendMarketOrder(Symbol, Quantity, OrderSide.Buy);
						Debug("Buy Market Order Sent");
						Debug("***************************************************");
						Debug("\t\tstochSlowK\tstochSlowD");
						//Debug($"60min		{Math.Round(Ref(stochSlow60_K, 1),2)}			{Math.Round(stochSlow60_K.CurrentValue,2)}");

						Debug($"Daily\t\t{Math.Round(stochSlowDay_K.CurrentValue,2)}\t\t{Math.Round(stochSlowDay_D.CurrentValue,2)}");
						Debug($"Weekly\t{Math.Round(stochSlowWeek_K.CurrentValue,2)}\t\t{Math.Round(stochSlowWeek_D.CurrentValue,2)}");
						Debug("---\t\t---\t\t---");
						Debug($"240min\tClose: {close}\tMOV: {Math.Round(mov_min240.CurrentValue,2)}");
					}

					if (CrossBelow(stochasticSlow_Weekly.StochasticSlowK, stochasticSlow_Weekly.StochasticSlowD)
					&& stochasticSlow_Weekly.StochasticSlowK.CurrentValue > StochasticSellCutoff
					&& stochasticSlow_Daily.StochasticSlowK.CurrentValue < stochasticSlow_Daily.StochasticSlowD.CurrentValue
					&& close > mov_min240.CurrentValue)
					{
						SendMarketOrder(Symbol, Quantity, OrderSide.Sell);
						Debug("Sell Market Order Sent");
						Debug("***************************************************");
						Debug("\t\tstochSlowK\tstochSlowD");
						//Debug($"60min		{Math.Round(Ref(stochSlow60_K, 1),2)}			{Math.Round(stochSlow60_K.CurrentValue,2)}");

						Debug($"Daily\t\t{Math.Round(stochSlowDay_K.CurrentValue,2)}\t\t{Math.Round(stochSlowDay_D.CurrentValue,2)}");
						Debug($"Weekly\t{Math.Round(stochSlowWeek_K.CurrentValue,2)}\t\t{Math.Round(stochSlowWeek_D.CurrentValue,2)}");
						Debug("---\t\t---\t\t---");
						Debug($"240min\tClose: {close}\tMOV: {Math.Round(mov_min240.CurrentValue,2)}");
					}
				}
				else
				{
					if (stochasticSlow_Weekly.StochasticSlowK.CurrentValue > stochasticSlow_Weekly.StochasticSlowD.CurrentValue
					&& stochasticSlow_Weekly.StochasticSlowK.CurrentValue < StochasticBuyCutoff
					&& stochasticSlow_Daily.StochasticSlowK.CurrentValue > stochasticSlow_Daily.StochasticSlowD.CurrentValue
					&& close < mov_min240.CurrentValue)
					{
						SendMarketOrder(Symbol, Quantity, OrderSide.Buy);
						Debug("Buy Market Order Sent");
						Debug("***************************************************");
						Debug("\t\tstochSlowK\tstochSlowD");
						//Debug($"60min		{Math.Round(Ref(stochSlow60_K, 1),2)}			{Math.Round(stochSlow60_K.CurrentValue,2)}");

						Debug($"Daily\t\t{Math.Round(stochSlowDay_K.CurrentValue,2)}\t\t{Math.Round(stochSlowDay_D.CurrentValue,2)}");
						Debug($"Weekly\t{Math.Round(stochSlowWeek_K.CurrentValue,2)}\t\t{Math.Round(stochSlowWeek_D.CurrentValue,2)}");
						Debug("---\t\t---\t\t---");
						Debug($"240min\tClose: {close}\tMOV: {Math.Round(mov_min240.CurrentValue,2)}");
					}

					if (stochasticSlow_Weekly.StochasticSlowK.CurrentValue < stochasticSlow_Weekly.StochasticSlowD.CurrentValue
					&& stochasticSlow_Weekly.StochasticSlowK.CurrentValue > StochasticSellCutoff
					&& stochasticSlow_Daily.StochasticSlowK.CurrentValue < stochasticSlow_Daily.StochasticSlowD.CurrentValue
					&& close > mov_min240.CurrentValue)
					{
						SendMarketOrder(Symbol, Quantity, OrderSide.Sell);
						Debug("Sell Market Order Sent");
						Debug("***************************************************");
						Debug("\t\tstochSlowK\tstochSlowD");
						//Debug($"60min		{Math.Round(Ref(stochSlow60_K, 1),2)}			{Math.Round(stochSlow60_K.CurrentValue,2)}");

						Debug($"Daily\t\t{Math.Round(stochSlowDay_K.CurrentValue,2)}\t\t{Math.Round(stochSlowDay_D.CurrentValue,2)}");
						Debug($"Weekly\t{Math.Round(stochSlowWeek_K.CurrentValue,2)}\t\t{Math.Round(stochSlowWeek_D.CurrentValue,2)}");
						Debug("---\t\t---\t\t---");
						Debug($"240min\tClose: {close}\tMOV: {Math.Round(mov_min240.CurrentValue,2)}");
					}
				}
			}
		}

		/// <summary>
		/// Gönderilen emirlerin son durumu değiştikçe bu fonksiyon tetiklenir.
		/// </summary>
		/// <param name="order">Emrin son durumu</param>
		public override void OnOrderUpdate(IOrder order)
		{
			if (order.OrdStatus.Obj == OrdStatus.Filled)
			{

			}
		}

		/// <summary>
		/// Strateji durdurulduğunda bu fonksiyon tetiklenir.
		/// </summary>
		public override void OnStopped()
		{
		}
    }
}