Esta estrategia es una adaptación StockSharp del experto MetaTrader Expert_AH_HM_RSI. Busca patrones de velas de martillo o de hombre colgado y requiere una señal de confirmación del índice de fuerza relativa (RSI) antes de operar. El enfoque refleja el Asesor Experto original, incluida su filosofía de gestión de riesgos de revertir posiciones cuando aparece una nueva señal.
Lógica de trading
Filtro de tendencias: se utiliza una media móvil simple corta (longitud predeterminada 2) para determinar si el mercado se encuentra en una micro tendencia bajista o alcista.
Patrón de vela: la estrategia analiza la vela completada más reciente:
Se detecta un martillo cuando el cuerpo se ubica en el tercio superior del rango, la vela tiene un hueco más bajo que la barra anterior y el punto medio de la vela está por debajo de la tendencia de la media móvil.
Se detecta un hombre ahorcado cuando el cuerpo se ubica en el tercio superior, la vela tiene un hueco más alto que la barra anterior y el punto medio de la vela está por encima de la tendencia de la media móvil.
RSI Filtro –
Las operaciones largas requieren que RSI esté por debajo del umbral de martillo configurable (predeterminado 40).
Las operaciones cortas requieren que RSI esté por encima del umbral del ahorcado (predeterminado 60).
Ejecución comercial: ante una señal válida, la estrategia ingresa con Volume + |Position|, por lo que las posiciones abiertas se revierten inmediatamente cuando llega la configuración opuesta.
Reglas de salida: las posiciones se aplanan cuando el RSI cruza los límites configurables inferior (predeterminado 30) o superior (predeterminado 70) en la dirección opuesta, replicando los votos de salida en el código original.
Indicadores
RelativeStrengthIndex (longitud 33 de forma predeterminada).
SimpleMovingAverage (longitud 2 por defecto) aplicada a los cierres de velas.
Parámetros
Nombre
Descripción
Predeterminado
Volume
Tamaño del pedido utilizado para las entradas.
1
RsiPeriod
RSI período retrospectivo.
33
MaPeriod
Período de media móvil para el filtro de tendencias.
2
HammerRsiThreshold
Valor máximo RSI que permite una entrada larga como martillo.
40
HangingManRsiThreshold
Valor mínimo RSI que permite una entrada corta del ahorcado.
60
LowerExitLevel
RSI límite utilizado para cerrar cortos después de un cruce alcista.
30
UpperExitLevel
RSI límite utilizado para cerrar posiciones largas después de un cruce a la baja.
70
CandleType
Plazo procesado por la estrategia.
1 hour velas
Todos los parámetros se pueden optimizar a través de la interfaz de usuario del parámetro StockSharp.
Notas de uso
La lógica funciona exclusivamente con velas terminadas. Asegúrese de que el período de tiempo seleccionado y la fuente de datos produzcan barras completas.
Debido a que la lógica de reversión siempre opera con Volume + |Position|, las posiciones cambian de dirección instantáneamente en la señal opuesta, coincidiendo con el Asesor Experto.
Inicie la gestión de riesgos integrada una vez en el lanzamiento (StartProtection() se llama en OnStarted).
Archivos
CS/AhHmRsiStrategy.cs – Implementación de la estrategia.
README.md – Documentación en inglés.
README_zh.md – Documentación china.
README_ru.md – Documentación rusa.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Hammer/Hanging Man + RSI strategy.
/// Buys on hammer with low RSI, sells on hanging man with high RSI.
/// </summary>
public class AhHmRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiLow;
private readonly StrategyParam<decimal> _rsiHigh;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiLow { get => _rsiLow.Value; set => _rsiLow.Value = value; }
public decimal RsiHigh { get => _rsiHigh.Value; set => _rsiHigh.Value = value; }
public AhHmRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiLow = Param(nameof(RsiLow), 40m)
.SetDisplay("RSI Low", "RSI oversold threshold for buy", "Signals");
_rsiHigh = Param(nameof(RsiHigh), 60m)
.SetDisplay("RSI High", "RSI overbought threshold for sell", "Signals");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
if (range <= 0 || body <= 0) return;
var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;
var isHammer = lowerShadow > body * 2 && upperShadow < body;
var isHangingMan = upperShadow > body * 2 && lowerShadow < body;
if (isHammer && rsiValue < RsiLow && Position <= 0)
BuyMarket();
else if (isHangingMan && rsiValue > RsiHigh && Position >= 0)
SellMarket();
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ah_hm_rsi_strategy(Strategy):
def __init__(self):
super(ah_hm_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._rsi_low = self.Param("RsiLow", 40.0)
self._rsi_high = self.Param("RsiHigh", 60.0)
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def RsiLow(self):
return self._rsi_low.Value
@RsiLow.setter
def RsiLow(self, value):
self._rsi_low.Value = value
@property
def RsiHigh(self):
return self._rsi_high.Value
@RsiHigh.setter
def RsiHigh(self, value):
self._rsi_high.Value = value
def OnStarted2(self, time):
super(ah_hm_rsi_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
body = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
rng = float(candle.HighPrice) - float(candle.LowPrice)
if rng <= 0 or body <= 0:
return
upper_shadow = float(candle.HighPrice) - max(float(candle.OpenPrice), float(candle.ClosePrice))
lower_shadow = min(float(candle.OpenPrice), float(candle.ClosePrice)) - float(candle.LowPrice)
is_hammer = lower_shadow > body * 2 and upper_shadow < body
is_hanging_man = upper_shadow > body * 2 and lower_shadow < body
if is_hammer and rsi_val < self.RsiLow and self.Position <= 0:
self.BuyMarket()
elif is_hanging_man and rsi_val > self.RsiHigh and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return ah_hm_rsi_strategy()