Hull MA RSI Strategie
Implementierung der Strategie Hull Moving Average + RSI. Kaufen, wenn der HMA steigt und der RSI unter 30 (überverkauft) liegt. Verkaufen, wenn der HMA fällt und der RSI über 70 (überkauft) liegt.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 64%. Am besten geeignet für den Forex-Markt.
Der Hull MA liefert eine geglättete Trendlinie und der RSI hebt Impulsdivergenz hervor. Trades erfolgen, wenn der RSI an Extrempunkten dreht, während der Preis der Hull-Richtung folgt.
Geeignet für kurzfristige Swing-Trader, die frühe Signale suchen. ATR-basierte Stops schützen den Trade.
Details
- Einstiegskriterien:
- Long:
HullMA turning up && RSI < RsiOversold - Short:
HullMA turning down && RSI > RsiOverbought
- Long:
- Long/Short: Beide
- Ausstiegskriterien:
- Richtungswechsel des Hull MA
- Stops: ATR-basiert mit
StopLoss - Standardwerte:
HmaPeriod= 9RsiPeriod= 14RsiOversold= 30mRsiOverbought= 70mStopLoss= new Unit(2, UnitTypes.Absolute)CandleType= TimeSpan.FromMinutes(5).TimeFrame()
- Filter:
- Kategorie: Mean Reversion
- Richtung: Beide
- Indikatoren: Hull MA, Moving Average, RSI
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Mittelfristig
- 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;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Implementation of strategy - Hull Moving Average + RSI.
/// Buy when HMA is rising and RSI is below 30 (oversold).
/// Sell when HMA is falling and RSI is above 70 (overbought).
/// </summary>
public class HullMaRsiStrategy : Strategy
{
private readonly StrategyParam<int> _hmaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<Unit> _stopLoss;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private decimal _hmaValue;
private decimal _prevHmaValue;
private int _cooldown;
/// <summary>
/// Hull Moving Average period.
/// </summary>
public int HmaPeriod
{
get => _hmaPeriod.Value;
set => _hmaPeriod.Value = value;
}
/// <summary>
/// RSI period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// RSI oversold level.
/// </summary>
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
/// <summary>
/// RSI overbought level.
/// </summary>
public decimal RsiOverbought
{
get => _rsiOverbought.Value;
set => _rsiOverbought.Value = value;
}
/// <summary>
/// Stop-loss value.
/// </summary>
public Unit StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Bars to wait between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Candle type used for strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="HullMaRsiStrategy"/>.
/// </summary>
public HullMaRsiStrategy()
{
_hmaPeriod = Param(nameof(HmaPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("HMA Period", "Period for Hull Moving Average", "HMA Parameters");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Period for Relative Strength Index", "RSI Parameters");
_rsiOversold = Param(nameof(RsiOversold), 30m)
.SetRange(1, 100)
.SetDisplay("RSI Oversold", "RSI level to consider market oversold", "RSI Parameters");
_rsiOverbought = Param(nameof(RsiOverbought), 70m)
.SetRange(1, 100)
.SetDisplay("RSI Overbought", "RSI level to consider market overbought", "RSI Parameters");
_stopLoss = Param(nameof(StopLoss), new Unit(2, UnitTypes.Absolute))
.SetDisplay("Stop Loss", "Stop loss in ATR or value", "Risk Management");
_cooldownBars = Param(nameof(CooldownBars), 130)
.SetRange(5, 500)
.SetDisplay("Cooldown Bars", "Bars between trades", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "General");
_prevHmaValue = 0;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_hmaValue = 0;
_prevHmaValue = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
var hma = new HullMovingAverage { Length = HmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
// Setup candle subscription
var subscription = SubscribeCandles(CandleType);
// Store HMA value in field, process logic on RSI callback.
subscription.Bind(hma, OnHma);
subscription
.Bind(rsi, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, hma);
// Create separate area for RSI
var rsiArea = CreateChartArea();
if (rsiArea != null)
{
DrawIndicator(rsiArea, rsi);
}
DrawOwnTrades(area);
}
}
private void OnHma(ICandleMessage candle, decimal hmaValue)
{
_hmaValue = hmaValue;
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_hmaValue == 0)
return;
if (_prevHmaValue == 0)
{
_prevHmaValue = _hmaValue;
return;
}
// Determine if HMA is rising or falling
var isHmaRising = _prevHmaValue != 0 && _hmaValue > _prevHmaValue;
var isHmaFalling = _prevHmaValue != 0 && _hmaValue < _prevHmaValue;
LogInfo($"Candle: {candle.OpenTime}, Close: {candle.ClosePrice}, " +
$"HMA: {_hmaValue}, Previous HMA: {_prevHmaValue}, " +
$"HMA Rising: {isHmaRising}, HMA Falling: {isHmaFalling}, " +
$"RSI: {rsiValue}");
if (_cooldown > 0)
{
_cooldown--;
_prevHmaValue = _hmaValue;
return;
}
// Trading rules
if (isHmaRising && rsiValue < RsiOversold && Position == 0)
{
BuyMarket();
_cooldown = CooldownBars;
LogInfo($"Buy signal: HMA rising and RSI oversold ({rsiValue} < {RsiOversold}).");
}
else if (isHmaFalling && rsiValue > RsiOverbought && Position == 0)
{
SellMarket();
_cooldown = CooldownBars;
LogInfo($"Sell signal: HMA falling and RSI overbought ({rsiValue} > {RsiOverbought}).");
}
// Exit conditions based on HMA direction change
else if (isHmaFalling && Position > 0)
{
SellMarket();
_cooldown = CooldownBars;
LogInfo($"Exit long: HMA started falling. Position: {Position}");
}
else if (isHmaRising && Position < 0)
{
BuyMarket();
_cooldown = CooldownBars;
LogInfo($"Exit short: HMA started rising. Position: {Position}");
}
// Update HMA value for next iteration
_prevHmaValue = _hmaValue;
}
}
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 HullMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class hull_ma_rsi_strategy(Strategy):
"""
Hull Moving Average + RSI strategy.
Buy when HMA is rising and RSI is oversold.
Sell when HMA is falling and RSI is overbought.
"""
def __init__(self):
super(hull_ma_rsi_strategy, self).__init__()
self._hma_period = self.Param("HmaPeriod", 9) \
.SetDisplay("HMA Period", "Period for Hull Moving Average", "HMA Parameters")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Period for Relative Strength Index", "RSI Parameters")
self._rsi_oversold = self.Param("RsiOversold", 30.0) \
.SetRange(1, 100) \
.SetDisplay("RSI Oversold", "RSI level to consider market oversold", "RSI Parameters")
self._rsi_overbought = self.Param("RsiOverbought", 70.0) \
.SetRange(1, 100) \
.SetDisplay("RSI Overbought", "RSI level to consider market overbought", "RSI Parameters")
self._cooldown_bars = self.Param("CooldownBars", 130) \
.SetRange(5, 500) \
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._candle_type = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Candle type for strategy", "General")
self._hma_value = 0.0
self._prev_hma_value = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(hull_ma_rsi_strategy, self).OnStarted2(time)
self._hma_value = 0.0
self._prev_hma_value = 0.0
self._cooldown = 0
hma = HullMovingAverage()
hma.Length = self._hma_period.Value
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(hma, self.OnHma)
subscription.Bind(rsi, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, hma)
rsi_area = self.CreateChartArea()
if rsi_area is not None:
self.DrawIndicator(rsi_area, rsi)
self.DrawOwnTrades(area)
def OnHma(self, candle, hma_value):
self._hma_value = float(hma_value)
def ProcessCandle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if self._hma_value == 0:
return
if self._prev_hma_value == 0:
self._prev_hma_value = self._hma_value
return
is_hma_rising = self._hma_value > self._prev_hma_value
is_hma_falling = self._hma_value < self._prev_hma_value
rv = float(rsi_value)
if self._cooldown > 0:
self._cooldown -= 1
self._prev_hma_value = self._hma_value
return
cd = self._cooldown_bars.Value
os_level = self._rsi_oversold.Value
ob_level = self._rsi_overbought.Value
if is_hma_rising and rv < os_level and self.Position == 0:
self.BuyMarket()
self._cooldown = cd
elif is_hma_falling and rv > ob_level and self.Position == 0:
self.SellMarket()
self._cooldown = cd
elif is_hma_falling and self.Position > 0:
self.SellMarket()
self._cooldown = cd
elif is_hma_rising and self.Position < 0:
self.BuyMarket()
self._cooldown = cd
self._prev_hma_value = self._hma_value
def OnReseted(self):
super(hull_ma_rsi_strategy, self).OnReseted()
self._hma_value = 0.0
self._prev_hma_value = 0.0
self._cooldown = 0
def CreateClone(self):
return hull_ma_rsi_strategy()