RAVI Histogramm-Strategie
Diese Strategie konvertiert den MetaTrader RAVI Histogram Expert nach StockSharp. Sie misst die Trendstärke als prozentualen Unterschied zwischen einem schnellen und einem langsamen EMA. Das Ergebnis wird mit oberen und unteren Levels verglichen, um Handelsentscheidungen zu treffen.
Wenn der RAVI-Wert über das obere Level steigt, gilt der Markt als bullish. Short-Positionen werden geschlossen und, wenn aktiviert, eine Long-Position eröffnet. Wenn der Wert unter das untere Level fällt, schließt die Strategie Longs und kann eine Short-Position eröffnen. Standardmäßig arbeitet sie mit Vier-Stunden-Kerzen.
Details
- Einstiegskriterien:
- Long: RAVI kreuzt aufwärts durch
UpLevel. - Short: RAVI kreuzt abwärts durch
DownLevel.
- Long: RAVI kreuzt aufwärts durch
- Long/Short: Beide.
- Ausstiegskriterien:
- Das entgegengesetzte RAVI-Signal schließt bestehende Positionen.
- Stops: Keine.
- Filter: Keine.
- Zeitrahmen: standardmäßig 4-Stunden-Kerzen.
- Parameter:
FastLengthundSlowLength– EMA-Perioden für die RAVI-Berechnung.UpLevelundDownLevel– Schwellenwerte zur Definition von Trendzonen.BuyOpen,SellOpen,BuyClose,SellClose– aktivieren oder deaktivieren Operationen in jede Richtung.
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>
/// RAVI Histogram trend strategy based on fast and slow EMA difference.
/// </summary>
public class RaviHistogramStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<decimal> _upLevel;
private readonly StrategyParam<decimal> _downLevel;
private readonly StrategyParam<bool> _buyOpen;
private readonly StrategyParam<bool> _sellOpen;
private readonly StrategyParam<bool> _buyClose;
private readonly StrategyParam<bool> _sellClose;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevRavi;
private bool _isFirst = true;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
public bool BuyOpen { get => _buyOpen.Value; set => _buyOpen.Value = value; }
public bool SellOpen { get => _sellOpen.Value; set => _sellOpen.Value = value; }
public bool BuyClose { get => _buyClose.Value; set => _buyClose.Value = value; }
public bool SellClose { get => _sellClose.Value; set => _sellClose.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RaviHistogramStrategy()
{
_fastLength = Param(nameof(FastLength), 7)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Fast EMA length", "General");
_slowLength = Param(nameof(SlowLength), 65)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Slow EMA length", "General");
_upLevel = Param(nameof(UpLevel), 0.1m)
.SetDisplay("Upper Level", "Upper threshold for trend", "General");
_downLevel = Param(nameof(DownLevel), -0.1m)
.SetDisplay("Lower Level", "Lower threshold for trend", "General");
_buyOpen = Param(nameof(BuyOpen), true)
.SetDisplay("Open Long", "Allow opening long positions", "Trading");
_sellOpen = Param(nameof(SellOpen), true)
.SetDisplay("Open Short", "Allow opening short positions", "Trading");
_buyClose = Param(nameof(BuyClose), true)
.SetDisplay("Close Long", "Allow closing long positions", "Trading");
_sellClose = Param(nameof(SellClose), true)
.SetDisplay("Close Short", "Allow closing short positions", "Trading");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).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();
_prevRavi = 0;
_isFirst = true;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_isFirst = true;
_prevRavi = 0;
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
// Subscribe to candle data and bind indicators.
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished || slow == 0)
return;
// Calculate RAVI value from EMA difference.
var ravi = 100m * (fast - slow) / slow;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevRavi = ravi;
_isFirst = false;
return;
}
if (_isFirst)
{
_prevRavi = ravi;
_isFirst = false;
return;
}
// Handle signals when RAVI crosses thresholds.
if (ravi > UpLevel)
{
if (SellClose && Position < 0)
BuyMarket();
if (BuyOpen && _prevRavi <= UpLevel && Position <= 0)
BuyMarket();
}
else if (ravi < DownLevel)
{
if (BuyClose && Position > 0)
SellMarket();
if (SellOpen && _prevRavi >= DownLevel && Position >= 0)
SellMarket();
}
_prevRavi = ravi;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ravi_histogram_strategy(Strategy):
def __init__(self):
super(ravi_histogram_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 7) \
.SetDisplay("Fast Length", "Fast EMA length", "General")
self._slow_length = self.Param("SlowLength", 65) \
.SetDisplay("Slow Length", "Slow EMA length", "General")
self._up_level = self.Param("UpLevel", 0.1) \
.SetDisplay("Upper Level", "Upper threshold for trend", "General")
self._down_level = self.Param("DownLevel", -0.1) \
.SetDisplay("Lower Level", "Lower threshold for trend", "General")
self._buy_open = self.Param("BuyOpen", True) \
.SetDisplay("Open Long", "Allow opening long positions", "Trading")
self._sell_open = self.Param("SellOpen", True) \
.SetDisplay("Open Short", "Allow opening short positions", "Trading")
self._buy_close = self.Param("BuyClose", True) \
.SetDisplay("Close Long", "Allow closing long positions", "Trading")
self._sell_close = self.Param("SellClose", True) \
.SetDisplay("Close Short", "Allow closing short positions", "Trading")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_ravi = 0.0
self._is_first = True
@property
def fast_length(self):
return self._fast_length.Value
@property
def slow_length(self):
return self._slow_length.Value
@property
def up_level(self):
return self._up_level.Value
@property
def down_level(self):
return self._down_level.Value
@property
def buy_open(self):
return self._buy_open.Value
@property
def sell_open(self):
return self._sell_open.Value
@property
def buy_close(self):
return self._buy_close.Value
@property
def sell_close(self):
return self._sell_close.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ravi_histogram_strategy, self).OnReseted()
self._prev_ravi = 0.0
self._is_first = True
def OnStarted2(self, time):
super(ravi_histogram_strategy, self).OnStarted2(time)
self._is_first = True
self._prev_ravi = 0.0
fast = ExponentialMovingAverage()
fast.Length = self.fast_length
slow = ExponentialMovingAverage()
slow.Length = self.slow_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fast = float(fast)
slow = float(slow)
if slow == 0:
return
ravi = 100.0 * (fast - slow) / slow
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_ravi = ravi
self._is_first = False
return
if self._is_first:
self._prev_ravi = ravi
self._is_first = False
return
up_level = float(self.up_level)
down_level = float(self.down_level)
if ravi > up_level:
if self.sell_close and self.Position < 0:
self.BuyMarket()
if self.buy_open and self._prev_ravi <= up_level and self.Position <= 0:
self.BuyMarket()
elif ravi < down_level:
if self.buy_close and self.Position > 0:
self.SellMarket()
if self.sell_open and self._prev_ravi >= down_level and self.Position >= 0:
self.SellMarket()
self._prev_ravi = ravi
def CreateClone(self):
return ravi_histogram_strategy()