Diese Trendfolge-Methode verwendet einen Kalman Filter, um Preisschwankungen zu glätten und die zugrunde liegende Richtung zu schätzen. Der Filter passt sich dynamisch an das Marktrauschen an und bietet eine verfeinerte Ansicht der Trendstärke im Vergleich zu Standard-Gleitenden Durchschnitten.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 112%. Sie funktioniert am besten auf dem Forex-Markt.
Eine Long-Position wird eröffnet, wenn der Schlusskurs über die Kalman-Filter-Schätzung steigt. Umgekehrt wird eine Short-Position eingegangen, wenn der Schluss unter den Filterwert fällt. Da der Filter bei jeder Bar aktualisiert wird, wechseln Trades immer dann, wenn der Preis die Linie kreuzt, was eine kontinuierliche Teilnahme an Trendmärkten ermöglicht.
Trader, die systematische Ansätze bevorzugen, können den Kalman Filter nützlich finden, um Whipsaws zu reduzieren. Ein Schutz-Stop basierend auf ATR hält das Risiko begrenzt, falls der Trend schnell umkehrt.
Details
Einstiegskriterien:
Long: Schluss > Kalman Filter
Short: Schluss < Kalman Filter
Long/Short: Beide Seiten.
Ausstiegskriterien:
Long: Ausstieg bei Schluss < Kalman Filter
Short: Ausstieg bei Schluss > Kalman Filter
Stops: Ja, ATR-basierter Stop-Loss.
Standardwerte:
ProcessNoise = 0.01m
MeasurementNoise = 0.1m
CandleType = TimeSpan.FromMinutes(5)
Filter:
Kategorie: Trend
Richtung: Beide
Indikatoren: Kalman Filter
Stops: Ja
Komplexität: Mittel
Zeitrahmen: Intraday
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Kalman Filter Trend strategy.
/// Uses a custom Kalman Filter indicator to track price trend.
/// </summary>
public class KalmanFilterTrendStrategy : Strategy
{
private readonly StrategyParam<decimal> _processNoiseParam;
private readonly StrategyParam<decimal> _measurementNoiseParam;
private readonly StrategyParam<DataType> _candleTypeParam;
private KalmanFilter _kalmanFilter;
private AverageTrueRange _atr;
/// <summary>
/// Process noise coefficient for Kalman filter.
/// </summary>
public decimal ProcessNoise
{
get => _processNoiseParam.Value;
set => _processNoiseParam.Value = value;
}
/// <summary>
/// Measurement noise coefficient for Kalman filter.
/// </summary>
public decimal MeasurementNoise
{
get => _measurementNoiseParam.Value;
set => _measurementNoiseParam.Value = value;
}
/// <summary>
/// Candle type for strategy.
/// </summary>
public DataType CandleType
{
get => _candleTypeParam.Value;
set => _candleTypeParam.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public KalmanFilterTrendStrategy()
{
_processNoiseParam = Param(nameof(ProcessNoise), 0.01m)
.SetRange(0.0001m, 1)
.SetDisplay("Process Noise", "Process noise coefficient for Kalman filter", "Parameters")
.SetOptimize(0.001m, 0.1m, 0.005m);
_measurementNoiseParam = Param(nameof(MeasurementNoise), 0.1m)
.SetRange(0.0001m, 1)
.SetDisplay("Measurement Noise", "Measurement noise coefficient for Kalman filter", "Parameters")
.SetOptimize(0.01m, 1.0m, 0.1m);
_candleTypeParam = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "Common");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_kalmanFilter = null;
_atr = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
_kalmanFilter = new KalmanFilter
{
ProcessNoise = ProcessNoise,
MeasurementNoise = MeasurementNoise
};
_atr = new AverageTrueRange { Length = 14 };
// Create subscription and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_kalmanFilter, _atr, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _kalmanFilter);
DrawOwnTrades(area);
}
// Enable position protection
StartProtection(
takeProfit: new Unit(0, UnitTypes.Absolute), // No take profit
stopLoss: new Unit(2, UnitTypes.Absolute) // Stop loss at 2*ATR
);
}
private void ProcessCandle(ICandleMessage candle, decimal kalmanValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Calculate trend direction
var trend = candle.ClosePrice > kalmanValue ? 1 : -1;
// Trading logic based on price position relative to Kalman filter
if (trend > 0 && Position <= 0)
{
// Buy when price is above Kalman filter (uptrend)
BuyMarket(Volume + Math.Abs(Position));
}
else if (trend < 0 && Position >= 0)
{
// Sell when price is below Kalman filter (downtrend)
SellMarket(Volume + Math.Abs(Position));
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import KalmanFilter, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class kalman_filter_trend_strategy(Strategy):
"""
Kalman Filter trend: trades based on price position relative to Kalman filter.
"""
def __init__(self):
super(kalman_filter_trend_strategy, self).__init__()
self._process_noise = self.Param("ProcessNoise", 0.01).SetDisplay("Process Noise", "Kalman process noise", "Parameters")
self._measurement_noise = self.Param("MeasurementNoise", 0.1).SetDisplay("Measurement Noise", "Kalman measurement noise", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(kalman_filter_trend_strategy, self).OnReseted()
def OnStarted2(self, time):
super(kalman_filter_trend_strategy, self).OnStarted2(time)
kf = KalmanFilter()
kf.ProcessNoise = self._process_noise.Value
kf.MeasurementNoise = self._measurement_noise.Value
atr = AverageTrueRange()
atr.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(kf, atr, self._process_candle).Start()
self.StartProtection(None, Unit(2, UnitTypes.Absolute))
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, kf)
self.DrawOwnTrades(area)
def _process_candle(self, candle, kf_val, atr_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
kf = float(kf_val)
if close > kf and self.Position <= 0:
self.BuyMarket()
elif close < kf and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return kalman_filter_trend_strategy()