Strategie Logistic RSI STOCH ROC AO
Die Strategie wendet eine logistische Abbildung auf einen ausgewählten Indikator (AO, ROC, RSI, Stochastic) an und handelt, wenn die vorzeichenbehaftete Standardabweichung die Null kreuzt.
Details
- Einstiegskriterien: Vorzeichenbehaftete Standardabweichung kreuzt über null.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Vorzeichenbehaftete Standardabweichung kreuzt unter null.
- Stops: Keine.
- Standardwerte:
Indicator= LogisticDominanceLength= 13LenLd= 5LenRoc= 9LenRsi= 14LenSto= 14CandleType= TimeSpan.FromMinutes(1)
- Filter:
- Kategorie: Oszillator
- Richtung: Beide
- Indikatoren: AwesomeOscillator, RateOfChange, RelativeStrengthIndex, StochasticOscillator, Highest
- Stops: Nein
- Komplexität: Mittel
- Zeitrahmen: Intraday (1m)
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy using RSI and ROC with logistic-style normalization.
/// Trades on zero crossovers of a composite signal.
/// </summary>
public class LogisticRsiStochRocAoStrategy : Strategy
{
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _rocLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private RelativeStrengthIndex _rsi;
private RateOfChange _roc;
private decimal? _prevSignal;
private int _barsSinceSignal;
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int RocLength { get => _rocLength.Value; set => _rocLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public LogisticRsiStochRocAoStrategy()
{
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period", "General");
_rocLength = Param(nameof(RocLength), 9)
.SetDisplay("ROC Length", "ROC period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_cooldownBars = Param(nameof(CooldownBars), 20)
.SetDisplay("Cooldown Bars", "Min bars between signals", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_rsi = null;
_roc = null;
_prevSignal = null;
_barsSinceSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevSignal = null;
_barsSinceSignal = 0;
_rsi = new RelativeStrengthIndex { Length = RsiLength };
_roc = new RateOfChange { Length = RocLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_rsi, _roc, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal rocVal)
{
if (candle.State != CandleStates.Finished)
return;
_barsSinceSignal++;
if (!_rsi.IsFormed || !_roc.IsFormed)
return;
// Composite signal: normalized RSI (-0.5 to 0.5) + sign of ROC
var rsiNorm = rsiVal / 100m - 0.5m;
var rocSign = rocVal > 0 ? 0.5m : rocVal < 0 ? -0.5m : 0m;
var signal = rsiNorm + rocSign;
if (_prevSignal.HasValue && _barsSinceSignal >= CooldownBars)
{
var prev = _prevSignal.Value;
var crossUp = prev <= 0m && signal > 0m;
var crossDown = prev >= 0m && signal < 0m;
if (crossUp && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_barsSinceSignal = 0;
}
else if (crossDown && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_barsSinceSignal = 0;
}
}
_prevSignal = signal;
}
}
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, RateOfChange
from StockSharp.Algo.Strategies import Strategy
class logistic_rsi_stoch_roc_ao_strategy(Strategy):
def __init__(self):
super(logistic_rsi_stoch_roc_ao_strategy, self).__init__()
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "General")
self._roc_length = self.Param("RocLength", 9) \
.SetDisplay("ROC Length", "ROC period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candles", "General")
self._cooldown_bars = self.Param("CooldownBars", 20) \
.SetDisplay("Cooldown Bars", "Min bars between signals", "General")
self._prev_signal = None
self._bars_since_signal = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(logistic_rsi_stoch_roc_ao_strategy, self).OnReseted()
self._prev_signal = None
self._bars_since_signal = 0
def OnStarted2(self, time):
super(logistic_rsi_stoch_roc_ao_strategy, self).OnStarted2(time)
self._prev_signal = None
self._bars_since_signal = 0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self._rsi_length.Value
self._roc = RateOfChange()
self._roc.Length = self._roc_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._rsi, self._roc, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def OnProcess(self, candle, rsi_val, roc_val):
if candle.State != CandleStates.Finished:
return
self._bars_since_signal += 1
if not self._rsi.IsFormed or not self._roc.IsFormed:
return
rv = float(rsi_val)
rcv = float(roc_val)
rsi_norm = rv / 100.0 - 0.5
if rcv > 0:
roc_sign = 0.5
elif rcv < 0:
roc_sign = -0.5
else:
roc_sign = 0.0
signal = rsi_norm + roc_sign
if self._prev_signal is not None and self._bars_since_signal >= self._cooldown_bars.Value:
prev = self._prev_signal
cross_up = prev <= 0.0 and signal > 0.0
cross_down = prev >= 0.0 and signal < 0.0
if cross_up and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._bars_since_signal = 0
elif cross_down and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._bars_since_signal = 0
self._prev_signal = signal
def CreateClone(self):
return logistic_rsi_stoch_roc_ao_strategy()