Diese Strategie handelt mit dem Relative Vigor Index (RVI) auf drei verschiedenen Zeitrahmen. Die längerfristigen RVI-Trends fungieren als Filter, während der kürzeste Zeitrahmen für Einstiege verwendet wird. Eine Long-Position wird eröffnet, wenn der kurzfristige RVI seine Signallinie nach unten kreuzt, während beide höheren Zeitrahmen bullisch bleiben. Eine Short-Position wird eröffnet, wenn der kurzfristige RVI seine Signallinie nach oben kreuzt und beide höheren Zeitrahmen bärisch sind. Positionen werden geschlossen, wenn ein Zeitrahmen einen Trendwechsel gegen die aktuelle Position anzeigt.
Parameter
RviPeriod – Periode zur Berechnung des RVI.
CandleType1 – Zeitrahmen des obersten RVI-Filters.
CandleType2 – Zeitrahmen des mittleren RVI-Filters.
CandleType3 – Handelszeitrahmen, in dem Einstiegssignale generiert werden.
Volume – Ordergröße für Marktorders.
Hinweise
Es werden nur abgeschlossene Kerzen verarbeitet.
Die Strategie verwendet die High-Level-API von StockSharp.
Standard-Zeitrahmen entsprechen 30-, 15- und 5-Minuten-Kerzen.
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 trades using Relative Vigor Index with multiple period confirmations.
/// Uses a long-period RVI for trend, mid-period for confirmation, and short for entry.
/// </summary>
public class TripleRviStrategy : Strategy
{
private readonly StrategyParam<int> _rviPeriod;
private readonly StrategyParam<DataType> _candleType;
private int _trend1;
private int _trend2;
private decimal _prevSignal = decimal.MinValue;
public int RviPeriod { get => _rviPeriod.Value; set => _rviPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TripleRviStrategy()
{
_rviPeriod = Param(nameof(RviPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("RVI Period", "Base period of RVI", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Trading timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_trend1 = 0;
_trend2 = 0;
_prevSignal = decimal.MinValue;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_trend1 = 0;
_trend2 = 0;
_prevSignal = decimal.MinValue;
var trendRsi = new RelativeStrengthIndex { Length = RviPeriod * 3 };
var midRsi = new RelativeStrengthIndex { Length = RviPeriod * 2 };
var signalRsi = new RelativeStrengthIndex { Length = RviPeriod };
var sub = SubscribeCandles(CandleType);
sub.Bind(trendRsi, midRsi, signalRsi, ProcessCandle).Start();
StartProtection(
new Unit(2000m, UnitTypes.Absolute),
new Unit(1000m, UnitTypes.Absolute));
}
private void ProcessCandle(ICandleMessage candle, decimal trendValue, decimal midValue, decimal signalValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
_trend1 = trendValue > 55m ? 1 : trendValue < 45m ? -1 : 0;
_trend2 = midValue > 55m ? 1 : midValue < 45m ? -1 : 0;
if (_prevSignal == decimal.MinValue)
{
_prevSignal = signalValue;
return;
}
var crossUp = _prevSignal <= 50m && signalValue > 50m;
var crossDown = _prevSignal >= 50m && signalValue < 50m;
if (crossUp && _trend1 > 0 && _trend2 > 0 && Position <= 0)
BuyMarket();
else if (crossDown && _trend1 < 0 && _trend2 < 0 && Position >= 0)
SellMarket();
if (Position > 0 && (_trend1 < 0 || _trend2 < 0))
SellMarket();
else if (Position < 0 && (_trend1 > 0 || _trend2 > 0))
BuyMarket();
_prevSignal = signalValue;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class triple_rvi_strategy(Strategy):
def __init__(self):
super(triple_rvi_strategy, self).__init__()
self._rvi_period = self.Param("RviPeriod", 10)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._trend1 = 0
self._trend2 = 0
self._prev_signal = None
@property
def RviPeriod(self): return self._rvi_period.Value
@RviPeriod.setter
def RviPeriod(self, v): self._rvi_period.Value = v
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, v): self._candle_type.Value = v
def OnStarted2(self, time):
super(triple_rvi_strategy, self).OnStarted2(time)
self._trend1 = 0
self._trend2 = 0
self._prev_signal = None
trend_rsi = RelativeStrengthIndex()
trend_rsi.Length = self.RviPeriod * 3
mid_rsi = RelativeStrengthIndex()
mid_rsi.Length = self.RviPeriod * 2
signal_rsi = RelativeStrengthIndex()
signal_rsi.Length = self.RviPeriod
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(trend_rsi, mid_rsi, signal_rsi, self.ProcessCandle).Start()
self.StartProtection(Unit(2000, UnitTypes.Absolute), Unit(1000, UnitTypes.Absolute))
def ProcessCandle(self, candle, trend_value, mid_value, signal_value):
if candle.State != CandleStates.Finished: return
if not self.IsFormedAndOnlineAndAllowTrading(): return
tv = float(trend_value)
mv = float(mid_value)
sv = float(signal_value)
self._trend1 = 1 if tv > 55.0 else (-1 if tv < 45.0 else 0)
self._trend2 = 1 if mv > 55.0 else (-1 if mv < 45.0 else 0)
if self._prev_signal is None:
self._prev_signal = sv
return
cross_up = self._prev_signal <= 50.0 and sv > 50.0
cross_down = self._prev_signal >= 50.0 and sv < 50.0
if cross_up and self._trend1 > 0 and self._trend2 > 0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and self._trend1 < 0 and self._trend2 < 0 and self.Position >= 0:
self.SellMarket()
if self.Position > 0 and (self._trend1 < 0 or self._trend2 < 0):
self.SellMarket()
elif self.Position < 0 and (self._trend1 > 0 or self._trend2 > 0):
self.BuyMarket()
self._prev_signal = sv
def OnReseted(self):
super(triple_rvi_strategy, self).OnReseted()
self._trend1 = 0
self._trend2 = 0
self._prev_signal = None
def CreateClone(self):
return triple_rvi_strategy()