Merhaba Matt Ricks,
Side lastSide = LastOrderSide;
Debug("LastOrderSide = " + LastOrderSide);
Bu özelliği kullanmak için aşağıdaki kodun neresine ekleme yapmam gerekiyor.
İlginiz için teşekkür ederim. Ayrıca yeni sürüm çok başarılı elinize sağlık.
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 PMaxStratejisi : 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)
{
}
}
}
}