Auf GitHub ansehen

Martini Martingale-Strategie

Diese Strategie implementiert ein abgesichertes Martingale-Grid. Sie beginnt damit, Stop-Orders auf beiden Seiten des aktuellen Kurses zu platzieren und verdoppelt die Positionsgröße in der entgegengesetzten Richtung, wenn sich der Markt um einen festgelegten Schritt gegen die aktuelle Positionierung bewegt. Alle Trades werden geschlossen, sobald der angesammelte Gewinn das Ziel überschreitet.

Details

  • Einstiegskriterien:
    • Buy-Stop oberhalb und Sell-Stop unterhalb des Marktes im Abstand Step platzieren.
    • Wenn eine Order ausgelöst wird, den entgegengesetzten Stop stornieren.
  • Positionsverwaltung:
    • Den Kurs der zuletzt ausgeführten Order verfolgen.
    • Wenn sich der Kurs um Step * orderCount gegen die offene Position bewegt, eine Marktorder in der entgegengesetzten Richtung mit doppeltem Volumen senden.
  • Ausstiegskriterien:
    • Alle Positionen schließen, wenn der unrealisierte Gewinn ProfitClose erreicht.
  • Long/Short: Beide.
  • Stops: Verwendet Stop-Orders für erste Einstiege; kein Stop-Loss.
  • Indikatoren: Keine.
  • Filter: Keine.

Parameter

  • Step – Kursschritt in absoluten Einheiten.
  • ProfitClose – Gewinnschwelle zum Schließen aller Trades.
  • InitialVolume – Startvolumen für die erste Order.
  • CandleType – Kerzenserie für Kursaktualisierungen.
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>
/// Mean reversion strategy inspired by martingale.
/// Enters on RSI extremes, exits when price returns to SMA.
/// </summary>
public class MartiniMartingaleStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public MartiniMartingaleStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 7)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "SMA for mean reversion target", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var sma = new SimpleMovingAverage { Length = SmaPeriod };

		SubscribeCandles(CandleType).Bind(rsi, sma, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal sma)
	{
		if (candle.State != CandleStates.Finished) return;

		var close = candle.ClosePrice;

		// RSI oversold => buy
		if (rsi < 30 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		// RSI overbought => sell
		else if (rsi > 70 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}
		// Exit long at SMA
		else if (Position > 0 && close >= sma && rsi > 50)
		{
			SellMarket();
		}
		// Exit short at SMA
		else if (Position < 0 && close <= sma && rsi < 50)
		{
			BuyMarket();
		}
	}
}