Este método de seguimento de tendência usa um Kalman Filter para suavizar flutuações de preço e estimar a direção subjacente. O filtro se adapta dinamicamente ao ruído do mercado, oferecendo uma visão refinada da força da tendência em comparação com médias móveis padrão.
Os testes indicam um retorno anual médio de aproximadamente 112%. Funciona melhor no mercado de forex.
Uma posição comprada é aberta quando o preço de fechamento sobe acima da estimativa do Kalman Filter. Por outro lado, uma posição vendida é tomada quando o fechamento cai abaixo do valor do filtro. Como o filtro se atualiza em cada barra, as operações mudam sempre que o preço cruza a linha, proporcionando participação contínua em mercados em tendência.
Traders que preferem abordagens sistemáticas podem achar o Kalman Filter útil para reduzir sinais falsos. Um stop de proteção baseado em ATR mantém o risco limitado caso a tendência reverta rapidamente.
Detalhes
Critérios de entrada:
Comprado: Fechamento > Kalman Filter
Vendido: Fechamento < Kalman Filter
Comprado/Vendido: Ambos os lados.
Critérios de saída:
Comprado: Sair quando fechamento < Kalman Filter
Vendido: Sair quando fechamento > Kalman Filter
Stops: Sim, stop-loss baseado em ATR.
Valores padrão:
ProcessNoise = 0.01m
MeasurementNoise = 0.1m
CandleType = TimeSpan.FromMinutes(5)
Filtros:
Categoria: Tendência
Direção: Ambos
Indicadores: Kalman Filter
Stops: Sim
Complexidade: Intermediário
Período: Intradiário
Sazonalidade: Não
Redes neurais: Não
Divergência: Não
Nível de risco: Médio
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()