Auf GitHub ansehen

Roulette-Spiel

Die Roulette-Spielstrategie bildet den Casino-ähnlichen Expertenberater von MetaTrader in StockSharp nach. Es behandelt jede fertige Kerze als eine neue Drehung des Rades, wählt eine zufällige Richtung und skaliert seine Ordergröße nach Verlusten mithilfe einer Progression im Martingale-Stil. Die Implementierung verfolgt eine virtuelle Bankroll und begrenzt das Risiko durch konfigurierbare Obergrenzen.

Jede Runde beginnt mit dem Abflachen einer vorhandenen Position, dem Werfen einer virtuellen Münze, die Rot oder Schwarz darstellt, und dem Senden einer Marktorder in die ausgewählte Richtung. Wenn die nächste Kerze schließt, prüft die Strategie, ob sich der Schlusskurs zugunsten der Wette bewegt hat. Bei Gewinnen wird der Einsatz auf das Basisvolumen zurückgesetzt, bei Verlusten vervielfacht sich der Einsatz bis zu einer definierten Obergrenze. Ein maximaler Pechsträhneschutz erzwingt ein Zurücksetzen, bevor die Gefährdung extrem wird. Zwischen den Runden können optional Abklingkerzen eingefügt werden, um das Wetttempo zu verlangsamen.

Diese Konvertierung konzentriert sich auf das vom ursprünglichen Experten vorgestellte, vom Glücksspiel inspirierte Geldmanagement anstelle von Indikatorsignalen. Es zeigt, wie man zeitbasierte Runden orchestriert, den internen Status aufrechterhält und über Kerzenabonnements mit StockSharps übergeordnetem API interagiert.

Einzelheiten

  • Eintrittskriterien: Kein technischer Filter. Die Richtung wird am Ende einer fertigen Kerze zufällig ausgewählt.
  • Lang/Kurz: Beide Richtungen, in jeder Runde zufällig ausgewählt.
  • Ausstiegskriterien: Die Position wird bei der nächsten abgeschlossenen Kerze geschlossen, wobei bewertet wird, ob der Preis über oder unter dem Einstiegspunkt schloss.
  • Haltestellen: Keine herkömmlichen Haltestellen. Das Risiko wird durch Einsatzobergrenzen und Streak-Limits gesteuert.
  • Standardwerte:
    • BaseVolume = 1m
    • LossMultiplier = 2m
    • MaxMultiplier = 16m
    • RoundCooldown = 1
    • MaxLosingStreak = 5
    • CandleType = TimeSpan.FromMinutes(1)
  • Filter:
    • Kategorie: Geldmanagement
    • Richtung: Beide
    • Indikatoren: Keine
    • Stopps: Nein
    • Komplexität: Anfänger
    • Zeitrahmen: Kurzfristig
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikostufe: Hoch

Notizen

  • Die Größe der Market Orders richtet sich nach dem multiplikatorbereinigten Einsatz und wird auf die Volumenstufe des Instruments gerundet.
  • Bei Gewinnen wird der Einsatz auf das Basisvolumen zurückgesetzt; Verluste skalieren mit dem Multiplikator, bis der maximale Multiplikator oder das Maximum für die Pechsträhne erreicht ist.
  • Abklingbalken verhindern den sofortigen Wiedereintritt und ermöglichen die Synchronisierung mit langsameren Datenfeeds.
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Roulette Game strategy: random-like entries based on candle direction with SMA filter.
/// Buys when candle is bullish and close above SMA. Sells when bearish and below SMA.
/// </summary>
public class RouletteGameStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int SmaPeriod
	{
		get => _smaPeriod.Value;
		set => _smaPeriod.Value = value;
	}

	public RouletteGameStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "SMA period", "Indicators");
	}

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

		var sma = new SimpleMovingAverage { Length = SmaPeriod };

		decimal? prevClose = null;
		decimal? prevSma = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, (candle, smaVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;
				var isBullish = close > candle.OpenPrice;

				if (prevClose.HasValue && prevSma.HasValue)
				{
					var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
					var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;

					if (isBullish && crossUp && Position <= 0)
						BuyMarket();
					else if (!isBullish && crossDown && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevSma = smaVal;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, sma);
			DrawOwnTrades(area);
		}
	}
}