X2MA JJRSX-Strategie
Strategie, die einen dualen gleitenden Durchschnitts-Trendfilter mit einem RSI-basierten Einstiegs-Trigger kombiniert. Der Trend wird auf einem höheren Zeitrahmen durch den Vergleich eines schnellen und eines langsamen gleitenden Durchschnitts bestimmt. Einstiege werden auf einem niedrigeren Zeitrahmen ausgeführt, wenn der RSI in Trendrichtung die überkauften oder überverkauften Zonen verlässt.
Details
- Einstiegskriterien:
- Long: Trend aufwärts und RSI kreuzt über
Oversold - Short: Trend abwärts und RSI kreuzt unter
Overbought
- Long: Trend aufwärts und RSI kreuzt über
- Long/Short: Beide
- Ausstiegskriterien: Entgegengesetzter RSI-Schwellenwert oder Trendumkehr
- Stops: Keine
- Standardwerte:
TrendCandleType= 4h-KerzenSignalCandleType= 30m-KerzenFastMaPeriod= 12SlowMaPeriod= 5RsiPeriod= 8Overbought= 70Oversold= 30
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>
/// Strategy that combines dual moving average trend filter with RSI entries.
/// </summary>
public class X2MaJjrsxStrategy : Strategy
{
private readonly StrategyParam<DataType> _trendCandleType;
private readonly StrategyParam<DataType> _signalCandleType;
private readonly StrategyParam<int> _fastMaPeriod;
private readonly StrategyParam<int> _slowMaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<bool> _useLong;
private readonly StrategyParam<bool> _useShort;
private SimpleMovingAverage _fastMa;
private SimpleMovingAverage _slowMa;
private RelativeStrengthIndex _rsi;
private int _trend;
private decimal _prevRsi;
/// <summary>
/// Constructor.
/// </summary>
public X2MaJjrsxStrategy()
{
_trendCandleType = Param(nameof(TrendCandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Trend Candle Type", "Timeframe for trend moving averages", "General");
_signalCandleType = Param(nameof(SignalCandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Signal Candle Type", "Timeframe for entry signals", "General");
_fastMaPeriod = Param(nameof(FastMaPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast MA Period", "Length of fast moving average", "Indicators");
_slowMaPeriod = Param(nameof(SlowMaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Slow MA Period", "Length of slow moving average", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Length of RSI filter", "Indicators");
_overbought = Param(nameof(Overbought), 75m)
.SetDisplay("Overbought", "RSI overbought threshold", "Risk");
_oversold = Param(nameof(Oversold), 25m)
.SetDisplay("Oversold", "RSI oversold threshold", "Risk");
_useLong = Param(nameof(UseLong), true)
.SetDisplay("Enable Long", "Allow long trades", "General");
_useShort = Param(nameof(UseShort), true)
.SetDisplay("Enable Short", "Allow short trades", "General");
}
/// <summary>
/// Candle type for trend calculation.
/// </summary>
public DataType TrendCandleType
{
get => _trendCandleType.Value;
set => _trendCandleType.Value = value;
}
/// <summary>
/// Candle type for entry signals.
/// </summary>
public DataType SignalCandleType
{
get => _signalCandleType.Value;
set => _signalCandleType.Value = value;
}
/// <summary>
/// Fast moving average period.
/// </summary>
public int FastMaPeriod
{
get => _fastMaPeriod.Value;
set => _fastMaPeriod.Value = value;
}
/// <summary>
/// Slow moving average period.
/// </summary>
public int SlowMaPeriod
{
get => _slowMaPeriod.Value;
set => _slowMaPeriod.Value = value;
}
/// <summary>
/// RSI period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// RSI overbought level.
/// </summary>
public decimal Overbought
{
get => _overbought.Value;
set => _overbought.Value = value;
}
/// <summary>
/// RSI oversold level.
/// </summary>
public decimal Oversold
{
get => _oversold.Value;
set => _oversold.Value = value;
}
/// <summary>
/// Enable long trades.
/// </summary>
public bool UseLong
{
get => _useLong.Value;
set => _useLong.Value = value;
}
/// <summary>
/// Enable short trades.
/// </summary>
public bool UseShort
{
get => _useShort.Value;
set => _useShort.Value = value;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, TrendCandleType), (Security, SignalCandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_trend = 0;
_prevRsi = 50m;
_fastMa = null;
_slowMa = null;
_rsi = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastMa = new SimpleMovingAverage { Length = FastMaPeriod };
_slowMa = new SimpleMovingAverage { Length = SlowMaPeriod };
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_prevRsi = 50m;
var trendSub = SubscribeCandles(TrendCandleType);
trendSub.Bind(_fastMa, _slowMa, ProcessTrend).Start();
var signalSub = SubscribeCandles(SignalCandleType);
signalSub.Bind(_rsi, ProcessSignal).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, signalSub);
DrawIndicator(area, _fastMa);
DrawIndicator(area, _slowMa);
DrawIndicator(area, _rsi);
DrawOwnTrades(area);
}
}
private void ProcessTrend(ICandleMessage candle, decimal fastMa, decimal slowMa)
{
if (candle.State != CandleStates.Finished)
return;
_trend = fastMa > slowMa ? 1 : fastMa < slowMa ? -1 : _trend;
}
private void ProcessSignal(ICandleMessage candle, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevRsi = rsi;
return;
}
if (UseLong && _trend > 0 && Position <= 0 && _prevRsi < Oversold && rsi >= Oversold)
BuyMarket();
if (UseShort && _trend < 0 && Position >= 0 && _prevRsi > Overbought && rsi <= Overbought)
SellMarket();
if (Position > 0 && (rsi >= Overbought || _trend < 0))
SellMarket();
if (Position < 0 && (rsi <= Oversold || _trend > 0))
BuyMarket();
_prevRsi = rsi;
}
}
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 SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class x2_ma_jjrsx_strategy(Strategy):
def __init__(self):
super(x2_ma_jjrsx_strategy, self).__init__()
self._trend_candle_type = self.Param("TrendCandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Trend Candle Type", "Timeframe for trend moving averages", "General")
self._signal_candle_type = self.Param("SignalCandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Signal Candle Type", "Timeframe for entry signals", "General")
self._fast_ma_period = self.Param("FastMaPeriod", 5) \
.SetDisplay("Fast MA Period", "Length of fast moving average", "Indicators")
self._slow_ma_period = self.Param("SlowMaPeriod", 20) \
.SetDisplay("Slow MA Period", "Length of slow moving average", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Length of RSI filter", "Indicators")
self._overbought = self.Param("Overbought", 75.0) \
.SetDisplay("Overbought", "RSI overbought threshold", "Risk")
self._oversold = self.Param("Oversold", 25.0) \
.SetDisplay("Oversold", "RSI oversold threshold", "Risk")
self._use_long = self.Param("UseLong", True) \
.SetDisplay("Enable Long", "Allow long trades", "General")
self._use_short = self.Param("UseShort", True) \
.SetDisplay("Enable Short", "Allow short trades", "General")
self._trend = 0
self._prev_rsi = 50.0
@property
def trend_candle_type(self):
return self._trend_candle_type.Value
@property
def signal_candle_type(self):
return self._signal_candle_type.Value
@property
def fast_ma_period(self):
return self._fast_ma_period.Value
@property
def slow_ma_period(self):
return self._slow_ma_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def overbought(self):
return self._overbought.Value
@property
def oversold(self):
return self._oversold.Value
@property
def use_long(self):
return self._use_long.Value
@property
def use_short(self):
return self._use_short.Value
def OnReseted(self):
super(x2_ma_jjrsx_strategy, self).OnReseted()
self._trend = 0
self._prev_rsi = 50.0
def OnStarted2(self, time):
super(x2_ma_jjrsx_strategy, self).OnStarted2(time)
self._trend = 0
self._prev_rsi = 50.0
fast_ma = SimpleMovingAverage()
fast_ma.Length = int(self.fast_ma_period)
slow_ma = SimpleMovingAverage()
slow_ma.Length = int(self.slow_ma_period)
rsi = RelativeStrengthIndex()
rsi.Length = int(self.rsi_period)
trend_sub = self.SubscribeCandles(self.trend_candle_type)
trend_sub.Bind(fast_ma, slow_ma, self._process_trend).Start()
signal_sub = self.SubscribeCandles(self.signal_candle_type)
signal_sub.Bind(rsi, self._process_signal).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, signal_sub)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, slow_ma)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def _process_trend(self, candle, fast_ma, slow_ma):
if candle.State != CandleStates.Finished:
return
fast_ma = float(fast_ma)
slow_ma = float(slow_ma)
if fast_ma > slow_ma:
self._trend = 1
elif fast_ma < slow_ma:
self._trend = -1
def _process_signal(self, candle, rsi):
if candle.State != CandleStates.Finished:
return
rsi = float(rsi)
ob = float(self.overbought)
os_val = float(self.oversold)
if self.use_long and self._trend > 0 and self.Position <= 0 and self._prev_rsi < os_val and rsi >= os_val:
self.BuyMarket()
if self.use_short and self._trend < 0 and self.Position >= 0 and self._prev_rsi > ob and rsi <= ob:
self.SellMarket()
if self.Position > 0 and (rsi >= ob or self._trend < 0):
self.SellMarket()
if self.Position < 0 and (rsi <= os_val or self._trend > 0):
self.BuyMarket()
self._prev_rsi = rsi
def CreateClone(self):
return x2_ma_jjrsx_strategy()