Esta estrategia utiliza el oscilador UltraFATL para detectar cambios en la fuerza de la tendencia. El indicador genera niveles discretos del 0 al 8. Se abre una posición larga cuando el valor anterior supera el nivel 4 y el valor actual cae por debajo de 5 manteniéndose positivo. Se abre una posición corta cuando el valor anterior es inferior a 5 pero mayor que cero y el valor actual sube por encima de 4. El algoritmo trabaja con velas de 4 horas por defecto, pero el marco temporal puede ajustarse.
El enfoque espera la continuación de la tendencia tras un retroceso desde lecturas extremas de UltraFATL. Las posiciones se invierten cuando aparece la condición opuesta.
Detalles
Criterios de entrada:
Largo: UltraFATL(prev) > 4 y UltraFATL(curr) < 5 y UltraFATL(curr) != 0.
Corto: UltraFATL(prev) < 5 y UltraFATL(prev) != 0 y UltraFATL(curr) > 4.
Largo/Corto: Ambos lados.
Criterios de salida: La señal opuesta invierte la posición.
Stops: No se usan por defecto.
Valores predeterminados:
Candle Type = velas de 4 horas.
Length = 3.
Signal Bar = 1 (usar la barra anterior para señales).
Filtros:
Categoría: Seguimiento de tendencia
Dirección: Ambos
Indicadores: Único (UltraFATL)
Stops: No
Complejidad: Moderado
Marco temporal: Medio plazo
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Moderado
using System;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on UltraFATL-style threshold signals.
/// </summary>
public class UltraFatlStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _length;
private readonly StrategyParam<int> _signalBar;
private decimal _prevValue;
private bool _isInitialized;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Smoothing period.
/// </summary>
public int Length
{
get => _length.Value;
set => _length.Value = value;
}
/// <summary>
/// Bar index used for signal calculation.
/// </summary>
public int SignalBar
{
get => _signalBar.Value;
set => _signalBar.Value = value;
}
/// <summary>
/// Initialize the UltraFATL strategy.
/// </summary>
public UltraFatlStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_length = Param(nameof(Length), 8)
.SetDisplay("Length", "Smoothing period", "UltraFATL")
.SetOptimize(4, 20, 1);
_signalBar = Param(nameof(SignalBar), 1)
.SetDisplay("Signal Bar", "Bar index for signal calculation", "UltraFATL");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevValue = 0m;
_isInitialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = Length };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Map RSI to the 0..8 discrete UltraFATL-style scale.
var current = Math.Max(0m, Math.Min(8m, rsiValue / 12.5m));
if (!_isInitialized)
{
_prevValue = current;
_isInitialized = true;
return;
}
var previous = _prevValue;
_prevValue = current;
var isBuySignal = previous >= 5m && current < 5m && current > 0m;
var isSellSignal = previous <= 4m && current > 4m;
if (isBuySignal && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (isSellSignal && Position >= 0)
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, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ultra_fatl_strategy(Strategy):
def __init__(self):
super(ultra_fatl_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._length = self.Param("Length", 8) \
.SetDisplay("Length", "Smoothing period", "UltraFATL")
self._signal_bar = self.Param("SignalBar", 1) \
.SetDisplay("Signal Bar", "Bar index for signal calculation", "UltraFATL")
self._prev_value = 0.0
self._is_initialized = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Length(self):
return self._length.Value
@Length.setter
def Length(self, value):
self._length.Value = value
@property
def SignalBar(self):
return self._signal_bar.Value
@SignalBar.setter
def SignalBar(self, value):
self._signal_bar.Value = value
def OnStarted2(self, time):
super(ultra_fatl_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.Length
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi = float(rsi_value)
current = max(0.0, min(8.0, rsi / 12.5))
if not self._is_initialized:
self._prev_value = current
self._is_initialized = True
return
previous = self._prev_value
self._prev_value = current
is_buy_signal = previous >= 5.0 and current < 5.0 and current > 0.0
is_sell_signal = previous <= 4.0 and current > 4.0
pos = self.Position
if is_buy_signal and pos <= 0:
self.BuyMarket(self.Volume + abs(pos))
elif is_sell_signal and pos >= 0:
self.SellMarket(self.Volume + abs(pos))
def OnReseted(self):
super(ultra_fatl_strategy, self).OnReseted()
self._prev_value = 0.0
self._is_initialized = False
def CreateClone(self):
return ultra_fatl_strategy()