Twisted SMA Strategie 4h
Die Twisted SMA Strategie verwendet drei einfache gleitende Durchschnitte und einen KAMA-Filter auf 4-Stunden-Kerzen. Eine Long-Position wird eröffnet, wenn der schnelle SMA über dem mittleren, der mittlere über dem langsamen liegt, der Kurs über einem längeren SMA notiert und der KAMA nicht flach ist. Die Position wird geschlossen, wenn die SMAs bärisch ausgerichtet sind.
Details
- Einstiegskriterien: schneller SMA > mittlerer SMA > langsamer SMA, Schluss > Haupt-SMA, KAMA nicht flach.
- Long/Short: Nur Long.
- Ausstiegskriterien: schneller SMA < mittlerer SMA < langsamer SMA.
- Stops: Nein.
- Standardwerte:
FastLength= 4MidLength= 9SlowLength= 18MainSmaLength= 100KamaLength= 25CandleType= TimeSpan.FromHours(4)
- Filter:
- Kategorie: Trend
- Richtung: Long
- Indikatoren: SMA, KAMA
- Stops: Nein
- Komplexität: Grundlegend
- 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;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Twisted SMA strategy using RSI momentum with EMA trend filter.
/// </summary>
public class TwistedSma4hStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _midLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _mainSmaLength;
private readonly StrategyParam<int> _kamaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevRsi;
private decimal _prevFast;
private decimal _prevSlow;
private int _cooldown;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int MidLength { get => _midLength.Value; set => _midLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public int MainSmaLength { get => _mainSmaLength.Value; set => _mainSmaLength.Value = value; }
public int KamaLength { get => _kamaLength.Value; set => _kamaLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TwistedSma4hStrategy()
{
_fastLength = Param(nameof(FastLength), 4)
.SetGreaterThanZero()
.SetDisplay("Fast SMA Length", "Length of the fastest SMA", "SMA");
_midLength = Param(nameof(MidLength), 9)
.SetGreaterThanZero()
.SetDisplay("Middle SMA Length", "Length of the middle SMA", "SMA");
_slowLength = Param(nameof(SlowLength), 18)
.SetGreaterThanZero()
.SetDisplay("Slow SMA Length", "Length of the slow SMA", "SMA");
_mainSmaLength = Param(nameof(MainSmaLength), 50)
.SetGreaterThanZero()
.SetDisplay("Main SMA Length", "Length of the main SMA", "SMA");
_kamaLength = Param(nameof(KamaLength), 10)
.SetGreaterThanZero()
.SetDisplay("KAMA Length", "Length of KAMA", "KAMA");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_prevFast = 0;
_prevSlow = 0;
_cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = 14 };
var emaFast = new ExponentialMovingAverage { Length = 8 };
var emaSlow = new ExponentialMovingAverage { Length = 21 };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, emaFast, emaSlow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaFast, decimal emaSlow)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0 || _prevFast == 0 || _prevSlow == 0)
{
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
return;
}
var hist = emaFast - emaSlow;
var histUp = hist > 0m;
var histDown = hist < 0m;
var rsiCrossUp = _prevRsi <= 50m && rsiVal > 50m;
var rsiCrossDown = _prevRsi >= 50m && rsiVal < 50m;
// Exit
if (Position > 0 && rsiCrossDown)
{
SellMarket();
_cooldown = 30;
}
else if (Position < 0 && rsiCrossUp)
{
BuyMarket();
_cooldown = 30;
}
// Entry
if (Position == 0)
{
if (rsiCrossUp && histUp)
{
BuyMarket();
_cooldown = 30;
}
else if (rsiCrossDown && histDown)
{
SellMarket();
_cooldown = 30;
}
}
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
}
}
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, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class twisted_sma_4h_strategy(Strategy):
"""RSI momentum crossing 50 with EMA histogram filter and cooldown."""
def __init__(self):
super(twisted_sma_4h_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(twisted_sma_4h_strategy, self).OnReseted()
self._prev_rsi = 0
self._prev_fast = 0
self._prev_slow = 0
self._cooldown = 0
def OnStarted2(self, time):
super(twisted_sma_4h_strategy, self).OnStarted2(time)
self._prev_rsi = 0
self._prev_fast = 0
self._prev_slow = 0
self._cooldown = 0
rsi = RelativeStrengthIndex()
rsi.Length = 14
ema_fast = ExponentialMovingAverage()
ema_fast.Length = 8
ema_slow = ExponentialMovingAverage()
ema_slow.Length = 21
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(rsi, ema_fast, ema_slow, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def OnProcess(self, candle, rsi_val, ema_fast_val, ema_slow_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
fv = float(ema_fast_val)
sv = float(ema_slow_val)
if self._prev_rsi == 0 or self._prev_fast == 0 or self._prev_slow == 0:
self._prev_rsi = rv
self._prev_fast = fv
self._prev_slow = sv
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_rsi = rv
self._prev_fast = fv
self._prev_slow = sv
return
hist = fv - sv
hist_up = hist > 0
hist_down = hist < 0
rsi_cross_up = self._prev_rsi <= 50 and rv > 50
rsi_cross_down = self._prev_rsi >= 50 and rv < 50
# Exit
if self.Position > 0 and rsi_cross_down:
self.SellMarket()
self._cooldown = 30
elif self.Position < 0 and rsi_cross_up:
self.BuyMarket()
self._cooldown = 30
# Entry
if self.Position == 0:
if rsi_cross_up and hist_up:
self.BuyMarket()
self._cooldown = 30
elif rsi_cross_down and hist_down:
self.SellMarket()
self._cooldown = 30
self._prev_rsi = rv
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return twisted_sma_4h_strategy()