Auf GitHub ansehen

Cidomo-Strategie

Ausbruch-System konvertiert vom MetaTrader 5 Expert Advisor "Cidomo". Die Strategie wartet auf eine neue Kerze im konfigurierten Zeitrahmen, misst die jüngste Handelsspanne und platziert gepaarte Stop-Orders ober- und unterhalb dieser Spanne. Das Risiko wird mit klassischen Stop-Loss-/Take-Profit-Niveaus, einem optionalen Trailing Stop und zwei Geldverwaltungsmodi (festes Volumen oder prozentbasiertes Risiko) verwaltet.

Funktionsweise

  1. Bei jeder abgeschlossenen Kerze von CandleType werden die letzten BarsCount Hochs und Tiefs gesammelt, um den kurzfristigen Kanal zu definieren.
  2. Eine Buy-Stop-Order wird bei highest + IndentPips und eine Sell-Stop-Order bei lowest - IndentPips platziert (beide Werte in Pips ausgedrückt und in absolute Preise umgerechnet).
  3. Wenn eine Stop-Order ausgelöst wird, wird die entgegengesetzte ausstehende Order sofort storniert.
  4. Für eine offene Position verfolgt die Strategie:
    • Anfänglichen Stop-Loss (StopLossPips) und Take-Profit (TakeProfitPips).
    • Einen schrittweisen Trailing Stop (TrailingStopPips / TrailingStepPips). Der Stop wird erst bewegt nachdem der Preis mindestens TrailingStop + TrailingStep vorschreitet, den ursprünglichen EA nachahmend.
    • Marktausstiege werden verwendet um MetaTraders PositionModify-Aufrufe zu emulieren wenn der Stop oder Take-Profit berührt wird.
  5. Wenn UseTimeFilter aktiviert ist, werden neue Orders nur innerhalb von ±30 Sekunden von StartHour:StartMinute (Serverzeit) gesendet, was das enge Handelsfenster des Quellskripts repliziert.

Geldverwaltung

  • FixedVolume: handelt immer das vom Benutzer angegebene genaue TradeVolume.
  • RiskPercent: berechnet die Ordergröße so, dass ein verlusttragender Trade bei der konfigurierten Stop-Loss-Distanz das Eigenkapital um RiskPercent reduziert. Volumina werden auf den VolumeStep des Instruments gerundet und zwischen MinVolume / MaxVolume begrenzt.

Risikokontrollen

  • Anfängliche Stop-Loss- und Take-Profit-Niveaus werden lokal gespeichert und über Marktorders ausgeführt wenn der Preis das Ziel während der nächsten Kerze kreuzt.
  • Der Trailing Stop bewegt sich nur in eine Richtung und respektiert die Schrittweite vom ursprünglichen EA, was ständige kleine Anpassungen verhindert.
  • Wenn kein Stop-Loss konfiguriert ist, fällt die risikobasierte Positionsgrößenbestimmung automatisch auf das feste TradeVolume zurück.

Parameter

Name Typ Standard Beschreibung
CandleType DataType H4 Zeitrahmen zur Bestimmung des Ausbruchsbereichs.
BarsCount int 15 Anzahl abgeschlossener Kerzen zur Berechnung des höchsten Hochs und niedrigsten Tiefs.
IndentPips decimal 3 Offset (in Pips) über/unter dem Bereich vor dem Senden von Stop-Orders.
StopLossPips decimal 50 Schutz-Stop-Abstand in Pips. Wert 0 deaktiviert den Stop.
TakeProfitPips decimal 50 Gewinnziel-Abstand in Pips. Wert 0 deaktiviert das Ziel.
TrailingStopPips decimal 35 Trailing-Stop-Abstand in Pips. Auf 0 setzen um Trailing zu deaktivieren.
TrailingStepPips decimal 5 Mindest-Extragewinn erforderlich vor dem Anziehen des Trailing Stops.
MoneyManagement CidomoMoneyManagementMode RiskPercent Wählt zwischen fester Positionsgröße und risikobasierter Größenbestimmung.
RiskPercent decimal 1 Prozentsatz des Eigenkapitals pro Trade riskiert wenn MoneyManagement = RiskPercent.
TradeVolume decimal 0.1 Festes Order-Volumen im FixedVolume-Modus oder wenn risikobasierte Größenbestimmung nicht berechnet werden kann.
UseTimeFilter bool false Aktiviert den ±30-Sekunden-Zeitfensterfilter.
StartHour int 9 Stunde (0-23) des Handelsfenster-Zentrums.
StartMinute int 58 Minute (0-59) des Handelsfenster-Zentrums.

Hinweise

  • Alle pip-basierten Parameter passen sich automatisch an 3- oder 5-stellige Kurse an, indem der PriceStep des Instruments mit 10 multipliziert wird, genau wie die MetaTrader-Implementierung.
  • Da StockSharp Stops clientseitig in diesem Port verwaltet, stelle sicher dass die Strategie verbunden bleibt, damit Marktausstiege ausgegeben werden können wenn Schutzniveaus durchbrochen werden.
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;

public class CidomoStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public CidomoStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}