Hull Candles Strategie
Hull Candles ist eine einfache Trendfolge-Strategie, die einen Hull Moving Average des Durchschnittspreises (OHLC4) verwendet. Wenn das HMA steigt und der Schlusskurs über seiner SMA liegt, werden Long-Positionen eröffnet; wenn das HMA fällt und der Schlusskurs unter seiner SMA liegt, werden Short-Positionen eröffnet.
Details
- Daten: Preiskerzen.
- Einstiegskriterien:
- Long: HMA steigt und Schlusskurs > SMA.
- Short: HMA fällt und Schlusskurs < SMA.
- Ausstiegskriterien: Umgekehrtes Signal.
- Stops: Keine.
- Standardwerte:
BodyLength= 10SmaLength= 1
- Filter:
- Kategorie: Trendfolge
- Richtung: Long/Short
- Indikatoren: HMA, SMA
- Komplexität: Niedrig
- Risikolevel: Hoch
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Hull Candles strategy.
/// A Hull moving average of BodyLength is built on the OHLC4 price and smoothed by an SMA of SmaLength. When the HMA rises and the
/// close is above that SMA the strategy goes long; when the HMA falls and the close is below it the strategy goes short, reversing
/// an opposite position.
/// </summary>
public class HullCandlesStrategy : Strategy
{
private readonly StrategyParam<int> _bodyLength;
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<DataType> _candleType;
private HullMovingAverage _hma;
private SimpleMovingAverage _sma;
private decimal? _prevHma;
/// <summary>
/// Hull moving average length.
/// </summary>
public int BodyLength
{
get => _bodyLength.Value;
set => _bodyLength.Value = value;
}
/// <summary>
/// Length of the SMA that smooths the HMA.
/// </summary>
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HullCandlesStrategy()
{
_bodyLength = Param(nameof(BodyLength), 10)
.SetGreaterThanZero()
.SetDisplay("Body Length", "Hull moving average length", "Indicators");
_smaLength = Param(nameof(SmaLength), 1)
.SetGreaterThanZero()
.SetDisplay("SMA Length", "Length of the SMA that smooths the HMA", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHma = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHma = null;
_hma = new HullMovingAverage { Length = BodyLength };
_sma = new SimpleMovingAverage { Length = SmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _hma);
DrawIndicator(area, _sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var ohlc4 = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
var hmaValue = _hma.Process(new DecimalIndicatorValue(_hma, ohlc4, candle.OpenTime) { IsFinal = true });
if (!_hma.IsFormed)
return;
var hma = hmaValue.GetValue<decimal>();
var smaValue = _sma.Process(new DecimalIndicatorValue(_sma, hma, candle.OpenTime) { IsFinal = true });
var prevHma = _prevHma;
_prevHma = hma;
if (!_sma.IsFormed || prevHma is not decimal previous)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var sma = smaValue.GetValue<decimal>();
var close = candle.ClosePrice;
if (hma > previous && close > sma && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (hma < previous && close < sma && 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, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import HullMovingAverage, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class hull_candles_strategy(Strategy):
"""
Hull Candles strategy.
A Hull moving average of BodyLength is built on the OHLC4 price and smoothed by an SMA of SmaLength. When the HMA rises and the
close is above that SMA the strategy goes long; when the HMA falls and the close is below it the strategy goes short, reversing
an opposite position.
"""
def __init__(self):
super(hull_candles_strategy, self).__init__()
self._body_length = self.Param("BodyLength", 10).SetGreaterThanZero().SetDisplay("Body Length", "Hull moving average length", "Indicators")
self._sma_length = self.Param("SmaLength", 1).SetGreaterThanZero().SetDisplay("SMA Length", "Length of the SMA that smooths the HMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._hma = None
self._sma = None
self._prev_hma = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(hull_candles_strategy, self).OnReseted()
self._prev_hma = None
def OnStarted2(self, time):
super(hull_candles_strategy, self).OnStarted2(time)
self._prev_hma = None
self._hma = HullMovingAverage()
self._hma.Length = self._body_length.Value
self._sma = SimpleMovingAverage()
self._sma.Length = self._sma_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._hma)
self.DrawIndicator(area, self._sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
ohlc4 = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / Decimal(4)
hma_value = process_float(self._hma, ohlc4, candle.OpenTime, True)
if not self._hma.IsFormed:
return
hma = float(hma_value)
sma_value = process_float(self._sma, Decimal(hma), candle.OpenTime, True)
prev_hma = self._prev_hma
self._prev_hma = hma
if not self._sma.IsFormed or prev_hma is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
sma = float(sma_value)
close = float(candle.ClosePrice)
if hma > prev_hma and close > sma and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif hma < prev_hma and close < sma and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return hull_candles_strategy()