Strategie Color JLaguerre
Strategie basierend auf dem farbcodierten Laguerre-Oszillator.
Der Indikator glättet die Kursbewegung mit einem Jurik-Filter und färbt seine Linie entsprechend der Position innerhalb vordefinierter Niveaus. Ein Farbwechsel markiert eine potenzielle Trendumkehr.
Die Strategie kauft, wenn der Oszillator das mittlere Niveau nach oben kreuzt, und verkauft, wenn er es nach unten kreuzt. Positionen werden geschlossen, wenn der Oszillator extreme Niveaus erreicht oder ein entgegengesetztes Signal erscheint.
Details
- Einstiegskriterien: Farbwechsel des Laguerre-Oszillators um das mittlere Niveau.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Gegensignal oder Erreichen eines extremen Niveaus.
- Stops: Ja.
- Standardwerte:
RsiLength= 14HighLevel= 85MiddleLevel= 50LowLevel= 15StopLossPercent= 2mCandleType= TimeSpan.FromHours(1)
- Filter:
- Kategorie: Oszillator
- Richtung: Beide
- Indikatoren: RSI
- Stops: Ja
- Komplexität: Grundlegend
- Zeitrahmen: Stündlich (1h)
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// RSI oscillator smoothed through Jurik MA. Middle-level reversals and
/// extreme-level exits are based on formed indicators and completed candles.
/// </summary>
public class ColorJLaguerreStrategy : Strategy
{
private readonly StrategyParam<int> _rsiLength, _jmaLength;
private readonly StrategyParam<decimal> _highLevel, _middleLevel, _lowLevel, _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private JurikMovingAverage _jma;
private decimal? _previous;
private Order _pending;
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int JmaLength { get => _jmaLength.Value; set => _jmaLength.Value = value; }
public decimal HighLevel { get => _highLevel.Value; set => _highLevel.Value = value; }
public decimal MiddleLevel { get => _middleLevel.Value; set => _middleLevel.Value = value; }
public decimal LowLevel { get => _lowLevel.Value; set => _lowLevel.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorJLaguerreStrategy()
{
_rsiLength = Param(nameof(RsiLength), 14).SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI lookback period", "Indicator");
_jmaLength = Param(nameof(JmaLength), 14).SetGreaterThanZero()
.SetDisplay("JMA Length", "Jurik smoothing of RSI", "Indicator");
_highLevel = Param(nameof(HighLevel), 85m)
.SetDisplay("High Level", "Close long at this threshold", "Levels");
_middleLevel = Param(nameof(MiddleLevel), 50m)
.SetDisplay("Middle Level", "Entry crossover threshold", "Levels");
_lowLevel = Param(nameof(LowLevel), 15m)
.SetDisplay("Low Level", "Close short at this threshold", "Levels");
_stopLossPercent = Param(nameof(StopLossPercent), 2m).SetNotNegative()
.SetDisplay("Stop Loss %", "Native percent stop distance", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_jma = null;
_previous = null;
_pending = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previous = null;
_pending = null;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
_jma = new JurikMovingAverage { Length = JmaLength };
Indicators.Add(_jma);
SubscribeCandles(CandleType)
.Bind(rsi, (candle, value) =>
{
if (candle.State == CandleStates.Finished && rsi.IsFormed)
ProcessCandle(candle, value);
}).Start();
StartProtection(
takeProfit: new Unit(0m, UnitTypes.Percent),
stopLoss: new Unit(StopLossPercent, UnitTypes.Percent),
useMarketOrders: true);
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
var result = _jma.Process(rsiValue, candle.OpenTime, true);
if (!result.IsFormed)
return;
var value = result.ToDecimal();
var crossUp = _previous is decimal prior && prior <= MiddleLevel && value > MiddleLevel;
var crossDown = _previous is decimal before && before >= MiddleLevel && value < MiddleLevel;
_previous = value;
if (!IsFormedAndOnlineAndAllowTrading()
|| (_pending is not null && _pending.State is not (OrderStates.Done or OrderStates.Failed)))
return;
if (Position > 0m && value >= HighLevel)
{
_pending = SellMarket(Position);
return;
}
if (Position < 0m && value <= LowLevel)
{
_pending = BuyMarket(-Position);
return;
}
if (crossUp)
{
if (Position < 0m)
_pending = BuyMarket(-Position + Volume);
else if (Position == 0m)
_pending = BuyMarket(Volume);
}
else if (crossDown)
{
if (Position > 0m)
_pending = SellMarket(Position + Volume);
else if (Position == 0m)
_pending = SellMarket(Volume);
}
}
}
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, OrderStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import RelativeStrengthIndex, JurikMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import process_float
class color_j_laguerre_strategy(Strategy):
"""RSI-JMA oscillator crosses middle and exits at extreme levels on finished candles."""
def __init__(self):
super(color_j_laguerre_strategy, self).__init__()
self._rsi_length = self.Param("RsiLength", 14).SetGreaterThanZero() \
.SetDisplay("RSI Length", "RSI lookback", "Indicator")
self._jma_length = self.Param("JmaLength", 14).SetGreaterThanZero() \
.SetDisplay("JMA Length", "Jurik smoothing of RSI", "Indicator")
self._high_level = self.Param("HighLevel", 85.0) \
.SetDisplay("High Level", "Close long at upper threshold", "Levels")
self._middle_level = self.Param("MiddleLevel", 50.0) \
.SetDisplay("Middle Level", "Middle crossover threshold", "Levels")
self._low_level = self.Param("LowLevel", 15.0) \
.SetDisplay("Low Level", "Close short at lower threshold", "Levels")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0).SetNotNegative() \
.SetDisplay("Stop Loss %", "Native percent stop", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._rsi = None
self._jma = None
self._previous = None
self._pending = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(color_j_laguerre_strategy, self).OnReseted()
self._rsi = self._jma = self._previous = self._pending = None
def OnStarted2(self, time):
super(color_j_laguerre_strategy, self).OnStarted2(time)
self._previous = self._pending = None
self._rsi = RelativeStrengthIndex()
self._rsi.Length = int(self._rsi_length.Value)
self._jma = JurikMovingAverage()
self._jma.Length = int(self._jma_length.Value)
self.Indicators.Add(self._jma)
self.SubscribeCandles(self.CandleType).Bind(self._rsi, self.ProcessCandle).Start()
self.StartProtection(
takeProfit=Unit(0.0, UnitTypes.Percent),
stopLoss=Unit(self._stop_loss_percent.Value, UnitTypes.Percent),
useMarketOrders=True)
def ProcessCandle(self, candle, rsi_value):
if candle.State != CandleStates.Finished or not self._rsi.IsFormed:
return
smooth = process_float(self._jma, rsi_value, candle.OpenTime, True)
if not smooth.IsFormed:
return
value = float(smooth)
middle = float(self._middle_level.Value)
up = self._previous is not None and self._previous <= middle and value > middle
down = self._previous is not None and self._previous >= middle and value < middle
self._previous = value
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self._pending is not None and self._pending.State not in (OrderStates.Done, OrderStates.Failed):
return
if self.Position > 0 and value >= float(self._high_level.Value):
self._pending = self.SellMarket(self.Position)
return
if self.Position < 0 and value <= float(self._low_level.Value):
self._pending = self.BuyMarket(-self.Position)
return
if up:
if self.Position < 0:
self._pending = self.BuyMarket(-self.Position + self.Volume)
elif self.Position == 0:
self._pending = self.BuyMarket(self.Volume)
elif down:
if self.Position > 0:
self._pending = self.SellMarket(self.Position + self.Volume)
elif self.Position == 0:
self._pending = self.SellMarket(self.Volume)
def CreateClone(self):
return color_j_laguerre_strategy()