Ver en GitHub

Plantilla de robot comercial AIS3

Descripción general

La plantilla del robot comercial AIS3 es un sistema de ruptura MetaTrader que se basa en dos marcos de tiempo coordinados. El plazo principal captura la estructura de la vela anterior, mientras que un período de tiempo secundario mide la volatilidad reciente para controlar las actualizaciones finales. Este puerto StockSharp reproduce fielmente el tamaño del pedido original, las comprobaciones de entrada y la lógica de seguimiento, pero se implementa en parte superior de la estrategia de alto nivel API para que pueda ejecutarse dentro de Designer, Shell o cualquier host StockSharp personalizado.

Flujo de trabajo comercial

  • Suscripciones a datos de mercado: la estrategia se suscribe a dos series de velas. La serie principal (predeterminada de 15 minutos) proporciona el máximo, mínimo, cierre, punto medio y rango de la vela anterior. La serie secundaria (por defecto 1 minuto) mide el rango rápido utilizado para paradas finales. Un feed del libro de pedidos en vivo mantiene los mejores precios de oferta y demanda actuales sincronizados con el MQL MarketInfo original solicitudes.
  • Validación de rupturas:
    • Una configuración larga se activa cuando el cierre anterior está por encima del punto medio y el precio de venta actual supera el anterior. alto más el diferencial medido. El precio de entrada es el pedido actual.
    • Una configuración corta requiere que el cierre anterior se mantenga por debajo del punto medio y que la oferta supere el mínimo anterior. el precio de entrada es la oferta actual.
    • Ambas direcciones heredan las comprobaciones de seguridad del corredor de la plantilla: la distancia entre la entrada y la parada/objetivo proyectado. debe exceder el buffer de parada configurado, y la parada debe permanecer en el lado correcto del precio de entrada incluso después de sumar el difundir.
  • Órdenes de protección:
    • La distancia de stop-loss es igual a primaryRange × StopMultiplier y está anclada por encima (para largos) o por debajo (para cortos) del vela de ruptura como se describe en el manual de integración.
    • La distancia de obtención de beneficios es igual a primaryRange × TakeMultiplier y se coloca desde el precio de entrada en la dirección comercial.
  • Gestión comercial:
    • Cuando una posición está abierta, el rango del período de tiempo secundario multiplicado por TrailMultiplier define la distancia de seguimiento.
    • El trailing stop solo se actualiza si la operación genera ganancias y el nuevo nivel está más lejos que la congelación y parada configuradas. zonas de amortiguamiento y la distancia entre la parada actual y la propuesta supera TrailStepMultiplier × spread. Esto refleja el Requisito de plantilla de que el precio debe avanzar al menos un paso del recorrido antes de modificar la parada.
    • Las posiciones se cierran con órdenes de mercado siempre que la oferta/demanda toque los niveles almacenados de stop-loss o take-profit.

Gestión del riesgo

  • Reserva de cuenta: AccountReserve mantiene bloqueada una fracción del capital de la cartera. La estrategia se niega a abrir nuevas posiciones si el capital reservado fuera inferior al presupuesto del pedido solicitado. Esto coincide con el comportamiento de la plantilla donde el riesgo La reserva protege la cuenta de pérdidas en cascada.
  • Reserva de orden: OrderReserve controla la parte del capital restante que se puede arriesgar por operación. El tamaño de la posición se calcula como riskBudget / |entry - stop| y luego se alinea con el paso de volumen de seguridad. Si no hay métricas de cartera disponible, en su lugar se utiliza el parámetro alternativo BaseVolume.
  • Detener y congelar buffers: StopBufferTicks y FreezeBufferTicks traducen las limitaciones de detención del corredor (por ejemplo, MODE_STOPLEVEL y MODE_FREEZELEVEL de MetaTrader) en unidades de precio utilizando el paso del precio del valor. Impiden que la estrategia se emita órdenes que violen las restricciones cambiarias o que muevan el trailing stop de manera demasiado agresiva.
  • Multiplicador de pasos finales: TrailStepMultiplier refleja la constante acd.TrailStepping de la plantilla MQ4. Asegura que las actualizaciones finales solo ocurren cuando la nueva parada está al menos a un múltiplo del valor anterior.

Parámetros

Parámetro Descripción
AccountReserve Fracción del capital mantenido como reserva de seguridad (0–0,95).
OrderReserve Fracción de capital negociable asignada al presupuesto de riesgo por operación (0–0,5 por defecto).
PrimaryCandleType Plazo de trabajo para la detección de rupturas (velas predeterminadas de 15 minutos).
SecondaryCandleType Marco de tiempo más rápido que controla la distancia de seguimiento (velas predeterminadas de 1 minuto).
TakeMultiplier Multiplicador del rango principal utilizado para realizar la orden de toma de ganancias.
StopMultiplier Multiplicador del rango primario utilizado para calcular la parada de protección.
TrailMultiplier Multiplicador del rango secundario que define la distancia de seguimiento.
BaseVolume Tamaño de la posición alternativa cuando las métricas de la cartera no están disponibles.
StopBufferTicks Distancia adicional, en ticks de precio, que debe permanecer entre los niveles de entrada y stop/objetivo.
FreezeBufferTicks Búfer adicional que evita detener las actualizaciones demasiado cerca del nivel de congelación del broker.
TrailStepMultiplier Multiplicador de diferencial que define el incremento mínimo entre los ajustes finales.

Notas de uso

  • Alimente la estrategia con series de velas y un flujo de libro de órdenes o de nivel 1 para que los mejores precios de oferta y demanda estén disponibles. corriendo basarse únicamente en los datos de la última operación alterará los controles de ruptura porque dependen del diferencial.
  • Los valores de parámetros predeterminados replican el ejemplo de plantilla MQ4 (TakeMultiplier = 1, StopMultiplier = 2, TrailMultiplier = 3). Ajústelos para que coincidan con los activos con los que opera o para experimentar con la intensidad de la ruptura.
  • El trailing stop es virtual: las órdenes no se modifican en la bolsa. Cuando se cumple la condición de seguimiento, la estrategia simplemente emite una salida de mercado, reflejando cómo el asesor experto original gestionó las paradas internamente.
  • Combine la estrategia con el módulo de protección integrado de StockSharp (ya habilitado en el constructor) para mantener la emergencia. manejo de stop-loss incluso si la estrategia se desconecta temporalmente.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// AIS3 Trading Robot: breakout strategy with ATR-based stops and trailing.
/// Enters on breakout above/below previous candle range with EMA filter.
/// </summary>
public class Ais3TradingRobotTemplateStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<decimal> _takeMultiplier;
	private readonly StrategyParam<decimal> _stopMultiplier;

	private decimal _prevHigh;
	private decimal _prevLow;
	private decimal _entryPrice;
	private decimal _stopPrice;

	public Ais3TradingRobotTemplateStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "EMA period for trend filter.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");

		_takeMultiplier = Param(nameof(TakeMultiplier), 2.0m)
			.SetDisplay("Take Multiplier", "ATR multiplier for TP.", "Risk");

		_stopMultiplier = Param(nameof(StopMultiplier), 1.5m)
			.SetDisplay("Stop Multiplier", "ATR multiplier for SL.", "Risk");
	}

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

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public decimal TakeMultiplier
	{
		get => _takeMultiplier.Value;
		set => _takeMultiplier.Value = value;
	}

	public decimal StopMultiplier
	{
		get => _stopMultiplier.Value;
		set => _stopMultiplier.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevHigh = 0;
		_prevLow = 0;
		_entryPrice = 0;
		_stopPrice = 0;
	}

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

		_prevHigh = 0;
		_prevLow = 0;
		_entryPrice = 0;
		_stopPrice = 0;

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, atr, ProcessCandle)
			.Start();

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

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

		if (_prevHigh == 0 || atrVal <= 0)
		{
			_prevHigh = candle.HighPrice;
			_prevLow = candle.LowPrice;
			return;
		}

		var close = candle.ClosePrice;
		var takeDistance = atrVal * TakeMultiplier;
		var stopDistance = atrVal * StopMultiplier;

		// Manage position
		if (Position > 0)
		{
			if (close - _entryPrice >= takeDistance)
			{
				SellMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else if (_stopPrice > 0 && close <= _stopPrice)
			{
				SellMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else
			{
				var trail = close - stopDistance;
				if (trail > _stopPrice) _stopPrice = trail;
			}
		}
		else if (Position < 0)
		{
			if (_entryPrice - close >= takeDistance)
			{
				BuyMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else if (_stopPrice > 0 && close >= _stopPrice)
			{
				BuyMarket();
				_entryPrice = 0;
				_stopPrice = 0;
			}
			else
			{
				var trail = close + stopDistance;
				if (trail < _stopPrice || _stopPrice == 0) _stopPrice = trail;
			}
		}

		// Entry on breakout + EMA filter
		if (Position == 0)
		{
			if (close > _prevHigh && close > emaVal)
			{
				_entryPrice = close;
				_stopPrice = close - stopDistance;
				BuyMarket();
			}
			else if (close < _prevLow && close < emaVal)
			{
				_entryPrice = close;
				_stopPrice = close + stopDistance;
				SellMarket();
			}
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
	}
}