Merhaba asagidaki kodu direkt strateji olarak eklerseniz, optimize edebilirsiniz. Indicator builder ile eklenen indikatorlerin strateji icerisinde optimize edilmesiyle ilgili gelistirmeler hala devam etmekte.
using System;
using System.Collections.Generic;
using System.Linq;
using Matriks.Data.Symbol;
using System.Windows.Media;
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;
//*******************************************************ACIKLAMA*******************************************************//
//Gecici sinyal ile kullaniniz. bufferlength strateji canli calistirildiginda averajlarin onceden hesaplanarak gelmesini//
//saglamaktadir. 200'un altina dusurmeyiniz. Hareketli ortalama PMAX in uzerinde kirdiginda alim, altina kirdiginda		//
//satim yapilmaktadir. Sirali emir gonderimi AKTIFTIR (Strateji ilk olarak alim emri bekleyecek ve sirayla gidecektir) 	//
//Ilk satis sinyali gelirse "Satış emri gönderildi" Debug ekraninda ciksa bile log ekranina baktiginizda Emir sinyali   //
//geldi fakat emirlerin sıralı gitmesi seçeneği aktif olduğundan emir gönderilmedi ifadesini goreceksiniz. 				//
//EMIR GONDERIMI SIRALI OLDUGU ICIN SIRASIZ GELEN EMIR BORSAYA ILETILMEMISTIR.											//
namespace Matriks.Lean.Algotrader
{
	public class PMAX_strat_buffer_release : 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("BTC_USDT_BIN")]
		public string Symbol;
		[Parameter(SymbolPeriod.Min)]
		public SymbolPeriod SymbolPeriod;
		[Parameter(5)]
		public decimal BuySellQuantity;
		[Parameter(14)]
		public int AtrPeriod;
		[Parameter(8)]
		public int MovPeriod;
		[Parameter(2)]
		public decimal Coeff;
		[Parameter(MovMethod.E)]
		public MovMethod MovMethod;
		
		public bool firstrun = true;
		int bufferlength = 200;
		WILDERS wilders;
		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);
			wilders = new WILDERS(AtrPeriod);
			mov = new MOV(MovPeriod, MovMethod);
			// Algoritmanın kalıcı veya geçici sinyal ile çalışıp çalışmayacağını belirleyen fonksiyondur.
			// true geçerseniz algoritma sadece yeni bar açılışlarında çalışır, bu fonksiyonu çağırmazsanız veya false geçerseniz her işlem olduğunda algoritma tetiklenir.
			WorkWithPermanentSignal(false);
			//Eger 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);
		}
		Dictionary<int, decimal> fubDict = new Dictionary<int, decimal>();
		Dictionary<int, decimal> flbDict = new Dictionary<int, decimal>();
		Dictionary<int, decimal> PMAX_Dict = new Dictionary<int, decimal>();
		/// <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)
		{
			var currentBar = barDataCurrentValues.LastUpdate.BarDataIndex;
			if (currentBar < AtrPeriod)
			{
				fubDict[currentBar] = 0;
				flbDict[currentBar] = 0;
				PMAX_Dict[currentBar] = 0;
				return ;
			}
			if (firstrun)
			{
				int i = bufferlength;
				fubDict[currentBar - i -1] = 0;
				flbDict[currentBar - i -1] = 0;
				PMAX_Dict[currentBar - i -1] = 0;
				var _barData_ = GetBarData();
				if (currentBar - 1 < 0 || !_barData_.Close.ContainsKey(currentBar - 1) || currentBar<=bufferlength) return ;
				Debug("currentBar = " + currentBar + ", buffer LENGTH = " + bufferlength + " indikator buffer hesaplaniyor");
				for (; i >= 0; i--)
				{
					var _high_ = _barData_.High[currentBar - i];
					var _low_ = _barData_.Low[currentBar - i];
					var _diff_ = _high_ - _low_;
					var _range2_ = Math.Abs(_high_ - _barData_.Close[currentBar - 1 - i]);
					var _range3_ = Math.Abs(_low_ - _barData_.Close[currentBar - 1 - i]);
					var _value_ = Math.Max(_diff_, Math.Max(_range2_, _range3_));
					wilders.Update(_value_, currentBar - i, _barData_.Time[currentBar - i]);
					mov.Update((_high_ + _low_) / 2, (currentBar - i), _barData_.Time[currentBar - i]);
					//Debug($"mov Updated: with value: {(_high_ + _low_) / 2}, @{currentBar - i}, with TIME = {_barData_.Time[currentBar - i]}");
					var _k = mov.Value[0][currentBar - i];
					var _offset = Coeff * wilders.CurrentValue;
					var _str = _k + _offset;
					var _sts = _k - _offset;
					var _prev = PMAX_Dict[currentBar - i -1];
					var _fub = _str<_prev || mov.Value[0][currentBar -1 - i] >_prev? _str:_prev;
					var _flb = _sts>_prev || mov.Value[0][currentBar -1 - i] <_prev? _sts:_prev;
					fubDict[currentBar - i] = _fub;
					flbDict[currentBar - i] = _flb;
					var _pmax = _prev == fubDict[currentBar - i -1] && _k < _fub? _fub : (_prev == fubDict[currentBar - i -1] && _k>_fub? _flb:(_prev == flbDict[currentBar - i -1] && _k>_flb? _flb
								   :(_prev == flbDict[currentBar - i -1] && _k < _flb? _fub:_fub)));
					PMAX_Dict[currentBar - i] = _pmax;
					//Debug($"PMAX = {Math.Round(_pmax,4)}, mov = {Math.Round(mov.Value[0][currentBar-i],4)}, @{currentBar - i}");
				}
				firstrun = false;
			}
			else{
				var barData = GetBarData();
				if (currentBar - 1 < 0 || !barData.Close.ContainsKey(currentBar - 1)) return ;
				var high = barData.High[currentBar];
				var low = barData.Low[currentBar];
				var diff = high - low;
	
				var range2 = Math.Abs(high - barData.Close[currentBar - 1]);
				var range3 = Math.Abs(low - barData.Close[currentBar - 1]);
				var value = Math.Max(diff, Math.Max(range2, range3));
	
				wilders.Update(value, currentBar, barDataCurrentValues.LastUpdate.DTime);
				mov.Update((high + low) / 2, currentBar, barDataCurrentValues.LastUpdate.DTime);
				var k = mov.CurrentValue;
				var offset = Coeff * wilders.CurrentValue;
				var str = k + offset;
				var sts = k - offset;
				var prev = PMAX_Dict[currentBar -1];
				var fub = str<prev || mov.Value[0][currentBar -1] >prev? str:prev;
				var flb = sts>prev || mov.Value[0][currentBar -1] <prev? sts:prev;
				fubDict[currentBar] = fub;
				flbDict[currentBar] = flb;
				var pmax = prev == fubDict[currentBar -1] && k<fub? fub : (prev == fubDict[currentBar -1] && k>fub? flb:(prev == flbDict[currentBar -1] && k>flb? flb
												   :(prev == flbDict[currentBar -1] && k<flb? fub:fub)));
				PMAX_Dict[currentBar] = pmax;
				
				if (barDataCurrentValues.LastUpdate.IsNewBar == true)
				{
					Debug($"PMAX = {Math.Round(pmax,4)}, mov = {Math.Round(mov.Value[0][currentBar],4)}");
					if (mov.Value[0][currentBar -1] <PMAX_Dict[currentBar -1] && mov.Value[0][currentBar] > PMAX_Dict[currentBar])
					{
						SendMarketOrder(Symbol, BuySellQuantity, OrderSide.Buy);
						Debug("Alış emri gönderildi");
					}
		
					if (PMAX_Dict[currentBar -1] <mov.Value[0][currentBar -1] && PMAX_Dict[currentBar] >mov.Value[0][currentBar])
					{
						SendMarketOrder(Symbol, BuySellQuantity, OrderSide.Sell);
						Debug("Satış emri gönderildi");
					}
				}
			}
		}
		/// <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)
			{
			}
		}
	}
}