Este método de seguimiento de tendencia utiliza un Kalman Filter para suavizar las fluctuaciones de precio y estimar la dirección subyacente. El filtro se adapta dinámicamente al ruido del mercado, ofreciendo una visión refinada de la fortaleza de la tendencia en comparación con las medias móviles estándar.
Las pruebas indican un retorno anual promedio de aproximadamente 112%. Funciona mejor en el mercado de forex.
Se abre una posición larga cuando el precio de cierre sube por encima de la estimación del Kalman Filter. Por el contrario, se toma una posición corta cuando el cierre cae por debajo del valor del filtro. Dado que el filtro se actualiza en cada barra, las operaciones cambian cada vez que el precio cruza la línea, proporcionando participación continua en mercados en tendencia.
Los traders que prefieren enfoques sistemáticos pueden encontrar el Kalman Filter útil para reducir los movimientos erráticos. Un stop de protección basado en ATR mantiene el riesgo limitado en caso de que la tendencia revierta rápidamente.
Detalles
Criterios de entrada:
Largo: Cierre > Kalman Filter
Corto: Cierre < Kalman Filter
Largo/Corto: Ambos lados.
Criterios de salida:
Largo: Salir cuando cierre < Kalman Filter
Corto: Salir cuando cierre > Kalman Filter
Stops: Sí, stop-loss basado en ATR.
Valores predeterminados:
ProcessNoise = 0.01m
MeasurementNoise = 0.1m
CandleType = TimeSpan.FromMinutes(5)
Filtros:
Categoría: Tendencia
Dirección: Ambos
Indicadores: Kalman Filter
Stops: Sí
Complejidad: Intermedio
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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()