Auf GitHub ansehen

iTrade-Strategie

Diese Strategie ist ein manueller Verkaufsmanager, der aus dem MetaTrader Expert Advisor iTrade konvertiert wurde. Sie bildet den Chart-Schaltflächenablauf des ursprünglichen EA nach: Jedes Mal, wenn der Benutzer einen Verkauf anfordert, wird eine Martingale-Position eröffnet. Danach überwacht die Strategie den schwebenden Gewinn aller Short-Trades und liquidiert die profitabelsten und unprofitabelsten Tickets, sobald vordefinierte Gewinnziele erreicht sind.

Kernlogik

  • Orders werden nur auf ausdrückliche Benutzeranforderungen eröffnet. Rufen Sie QueueSellRequest() auf, um den MetaTrader-Schaltflächendruck zu simulieren.
  • Die erste Position verwendet das konfigurierte Anfangsvolumen. Nach jedem Verlusttrade wird die nächste Ordergröße mit dem Martingale-Multiplikator multipliziert. Gewinntrades setzen die Sequenz auf das Basisvolumen zurück.
  • Schwebender Gewinn wird mit dem aktuellen besten Ask-Preis gemessen. Wenn der durchschnittliche Gewinn pro offenem Trade das durchschnittliche Gewinnziel erreicht, schließt die Strategie die profitabelsten und unprofitabelsten Trades aus dem aktiven Batch (bis zu Basis-Trade-Anzahl Trades).
  • Wenn mehr als Basis-Trade-Anzahl Positionen offen sind, wird das strengere erweiterte Gewinnziel angewendet, bevor zwei Trades geschlossen werden.
  • Gewinnberechnungen stützen sich auf die Wertpapierwerte PriceStep und StepPrice. Die Strategie wirft beim Start eine Ausnahme, wenn sie fehlen.

Parameter

Name Beschreibung
InitialVolume Basis-Lotgröße für die erste Martingale-Order.
MartingaleMultiplier Multiplikator, der nach jedem Verlusttrade angewendet wird.
AverageProfitTarget Durchschnittlicher schwebender Gewinn (in Währung), der zum Schließen von Trades im ersten Batch erforderlich ist.
ExtendedAverageProfitTarget Durchschnittlicher schwebender Gewinnschwellenwert, wenn mehr als der Basis-Batch aktiv ist.
BaseTradeCount Anzahl der Trades, die als Teil des Anfangsbatches gelten.
ControlInterval Frequenz interner Prüfungen (Timerintervall).

Nutzungshinweise

  1. Setzen Sie Security, Portfolio und gewünschte Parameter, bevor Sie die Strategie starten.
  2. Rufen Sie QueueSellRequest() auf, wann immer ein neuer Verkauf eröffnet werden soll. Die Strategie dimensioniert die Order gemäß den Martingale-Regeln und sendet einen Marktverkauf.
  3. Der Algorithmus speichert eine Historie geschlossener Traderesultate (bis zu 200 Einträge), um das ursprüngliche Martingale-Verhalten zu reproduzieren.
  4. Schließorders werden als Marktkäufe für das exakte Volumen der Zieltrades gesendet.

Unterschiede zur MetaTrader-Version

  • Die MetaTrader-Version stützte sich auf Chart-Schaltflächen; hier löst der Benutzer Verkäufe programmatisch über QueueSellRequest() aus.
  • Orderausführung erfolgt über StockSharp-Marktorders. Teilausführungen werden von der Strategie automatisch aggregiert.
  • Gewinnschwellen arbeiten mit dezimalen Währungswerten unter Verwendung von StepPrice, während der ursprüngliche EA MetaTrader-Ticketgewinnfunktionen nutzte.
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 ITradeStrategy : 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 ITradeStrategy()
	{
		_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;
	}
}