Die VR Overturn Strategie implementiert eine einfache Martingal/Anti-Martingal-Logik.
Sie hält immer nur eine einzige Position und eröffnet nach deren Schließung sofort eine neue,
basierend auf dem Ergebnis des vorherigen Trades.
Strategielogik
Erste Position gemäß StartSide mit Volumen StartVolume eröffnen.
Stop-Loss und Take-Profit anhand von Punktoffsets anhängen.
Wenn die Position geschlossen wird:
Gewinn des letzten Trades berechnen.
Für den Martingale-Modus:
Nach einem profitablen Trade: Volumen auf StartVolume zurücksetzen und dieselbe Richtung beibehalten.
Nach einem Verlust-Trade: Volumen mit Multiplier multiplizieren und Richtung umkehren.
Für den AntiMartingale-Modus:
Nach einem profitablen Trade: Volumen mit Multiplier multiplizieren und dieselbe Richtung beibehalten.
Nach einem Verlust-Trade: Volumen auf StartVolume zurücksetzen und Richtung umkehren.
Nächste Position mit der berechneten Richtung und dem berechneten Volumen eröffnen.
Der Vorgang wiederholt sich unbegrenzt, solange die Strategie läuft.
Parameter
Name
Beschreibung
Mode
Handelsmodus: Martingale oder AntiMartingale.
StartSide
Seite des allerersten Trades (Buy oder Sell).
TakeProfit
Take-Profit-Wert in Punkten vom Einstiegspreis.
StopLoss
Stop-Loss-Wert in Punkten vom Einstiegspreis.
StartVolume
Anfangsvolumen für die erste Order.
Multiplier
Multiplikator, der nach Gewinn oder Verlust auf das Volumen angewendet wird.
Hinweise
Schutzorders werden als Stop- und Limitorders registriert.
Zu jedem Zeitpunkt existiert nur eine Position.
Die Strategie verwendet keine Marktindikatoren.
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>
/// Overturn strategy using EMA crossover.
/// </summary>
public class VROverturnStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public VROverturnStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "General");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fastVal;
_prevSlow = slowVal;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}