Diese Strategie ist eine vereinfachte Übersetzung des originalen MQL5-Expertenberaters "DVD Level". Sie verwendet den Range Action Verification Index (RAVI) zur Bestimmung der Marktrichtung. RAVI wird mit exponentiellen gleitenden Durchschnitten mit Perioden 2 und 24 auf 1-Stunden-Kerzen berechnet.
Parameter
Volume – Ordervolumen für Trades.
Logik
1-Stunden-Kerzen abonnieren und EMA(2) und EMA(24) berechnen.
RAVI = (EMA2 - EMA24) / EMA24 * 100 berechnen.
Wenn RAVI unter null kreuzt, kauft die Strategie, wenn sie flat oder short ist.
Wenn RAVI über null kreuzt, verkauft die Strategie, wenn sie flat oder long ist.
Der integrierte Positionsschutz wird über StartProtection() aktiviert.
Der Ansatz erfasst potenzielle Umkehrungen, wenn der kurzfristige Momentum vom langfristigen Trend abweicht.
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>
/// RAVI based level strategy. Opens long when the RAVI crosses below zero and short when above.
/// </summary>
public class DvdLevelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly ExponentialMovingAverage _emaFast = new() { Length = 2 };
private readonly ExponentialMovingAverage _emaSlow = new() { Length = 24 };
private decimal _prevRavi;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public DvdLevelStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRavi = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRavi = 0m;
_hasPrev = false;
var sub = SubscribeCandles(CandleType);
sub.Bind(_emaFast, _emaSlow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, sub);
DrawIndicator(area, _emaFast);
DrawIndicator(area, _emaSlow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaFast, decimal emaSlow)
{
if (candle.State != CandleStates.Finished || emaSlow == 0)
return;
var ravi = (emaFast - emaSlow) / emaSlow * 100m;
if (!_hasPrev)
{
_prevRavi = ravi;
_hasPrev = true;
return;
}
var crossAbove = _prevRavi <= 0 && ravi > 0;
var crossBelow = _prevRavi >= 0 && ravi < 0;
if (crossBelow && Position <= 0)
BuyMarket();
else if (crossAbove && 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 as EMA
from StockSharp.Algo.Strategies import Strategy
class dvd_level_strategy(Strategy):
def __init__(self):
super(dvd_level_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._prev_ravi = 0.0
self._has_prev = False
@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(dvd_level_strategy, self).OnStarted2(time)
self._prev_ravi = 0.0
self._has_prev = False
self._ema_fast = EMA()
self._ema_fast.Length = 2
self._ema_slow = EMA()
self._ema_slow.Length = 24
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(self._ema_fast, self._ema_slow, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_fast, ema_slow):
if candle.State != CandleStates.Finished:
return
ef = float(ema_fast)
es = float(ema_slow)
if es == 0:
return
ravi = (ef - es) / es * 100.0
if not self._has_prev:
self._prev_ravi = ravi
self._has_prev = True
return
cross_above = self._prev_ravi <= 0 and ravi > 0
cross_below = self._prev_ravi >= 0 and ravi < 0
if cross_below and self.Position <= 0:
self.BuyMarket()
elif cross_above and self.Position >= 0:
self.SellMarket()
self._prev_ravi = ravi
def OnReseted(self):
super(dvd_level_strategy, self).OnReseted()
self._prev_ravi = 0.0
self._has_prev = False
def CreateClone(self):
return dvd_level_strategy()