Ver en GitHub

Máquina comercial AIS5

Descripción general

AIS5 Trade Machine traslada el MetaTrader 4 asesor experto AIS5TM.mq4 a la StockSharp estrategia de alto nivel API. el original programa centrado en construir histogramas de perfil de mercado en dos períodos de tiempo y ofrecer una consola de ejecución semiautomática. el La versión StockSharp mantiene la idea de resaltar las zonas de precios fuertes y débiles a partir de la agregación de volumen de ticks y lo convierte en un sistema de ruptura automatizado con control de riesgo adaptativo basado en el rango verdadero promedio (ATR).

La estrategia se suscribe a dos flujos de velas:

  • Un período de tiempo del perfil (predeterminado 15 minutos) que acumula volumen para detectar zonas fuertes y débiles.
  • Un período de negociación (predeterminado 1 minuto) que busca rupturas confirmadas por volumen fuera de esas zonas.

Las posiciones están protegidas por paradas proporcionales ATR y objetivos escalables. Las contracciones de volumen desencadenan salidas tempranas para imitar la disciplina de monitoreo que se encuentra en el código MT4.

Lógica estratégica

Detección de zona de volumen (período de tiempo del perfil)

  • Cada vela terminada con un período de tiempo más alto actualiza dos promedios móviles simples (SMA) del volumen de ticks.
  • Una vela se etiqueta como zona fuerte cuando su volumen excede el promedio por el multiplicador configurable (Strong Volume Mult). El precio de cierre de la vela se convierte en el nivel fuerte más reciente.
  • Una vela se etiqueta como zona débil cuando su volumen cae por debajo del promedio dividido por el divisor configurado (Weak Volume Divider). El precio de cierre de esa vela se convierte en el último nivel débil.
  • Sólo participan velas terminadas. La estrategia ignora zonas hasta que el perfil SMA esté completamente formado para evitar cambios prematuros. señales durante el período de calentamiento.

Entradas de ruptura (período de negociación)

  • El período de tiempo inferior espera a que terminen de formarse tanto su volumen SMA como el indicador ATR.
  • Una configuración larga requiere que el cierre supere el nivel fuerte más reciente por la suma de los Puntos Base de Zona y Búfers de puntos de paso de zona (convertidos a través del paso de precio del instrumento). La vela también debe generar un pico de volumen relativo al promedio intradiario.
  • Una configuración breve refleja la lógica en torno al último nivel débil, lo que requiere una ruptura más allá del buffer combinado y confirma expansión de volumen.
  • El experto MT4 original permitía comandos manuales y cuadrículas de múltiples órdenes. El puerto StockSharp mantiene un modelo de posición única, por lo que un La ruptura solo se activa cuando la posición neta actual es plana.

Gestión de salidas

  • Al ingresar, la estrategia almacena el precio de ejecución, calcula una parada protectora basada en ATR (ATR multiplicada por ATR Multiplier y sujeta por el buffer de la zona base), y establece el objetivo como la distancia de parada multiplicada por el divisor de volumen débil. Esto mantiene riesgo y recompensa alineados con la estructura de volumen.
  • Mientras una posición está abierta, la estrategia monitorea cada vela comercial terminada:
    • Si el precio alcanza el objetivo de beneficio o el stop de protección, la posición se aplana inmediatamente.
    • Si el volumen de ticks se contrae por debajo del umbral de volumen débil antes de alcanzar cualquiera de los niveles, la operación se cierra anticipadamente para evitar persistiendo en zonas inactivas.
  • Cuando la posición neta vuelve a cero, el estado interno se restablece, lo que permite evaluar la siguiente ruptura desde cero.

Parámetros

  • Vela de perfil: tipo de vela que alimenta el perfil de volumen (predeterminado: velas de 15 minutos).
  • Vela comercial: período de tiempo más bajo utilizado para rupturas y salidas (predeterminado: velas de 1 minuto).
  • Retrospectiva de volumen: número de velas tanto para las SMA de volumen como para el período ATR.
  • Múlt. de volumen fuerte: multiplicador por encima del volumen promedio que marca una zona fuerte (se asigna a Parameter.1 en MQL).
  • Divisor de volumen débil: divisor por debajo del volumen promedio que marca zonas débiles y dimensiona el objetivo de ganancias (se asigna a Parameter.2).
  • ATR Multiplicador: factor de escala aplicado a ATR al calcular la distancia de parada adaptativa (se asigna a Parameter.3).
  • Puntos base de zona: búfer mínimo en puntos agregados al nivel de zona antes de verificar las rupturas (se asigna a ZoneBasePoints).
  • Puntos de paso de zona: zona de influencia de ruptura adicional en puntos que amplía la distancia desde la zona antes de que se realicen las entradas. activado (se asigna a ZoneStepPoints).
  • Volumen – heredado de la clase base Strategy; define el tamaño de la orden para las entradas al mercado.

Notas adicionales

  • La estrategia vuelve automáticamente a un paso de precio predeterminado de 0.0001 si el valor no especifica uno. Esto mantiene el Parámetros basados en puntos compatibles con la mayoría de los símbolos FX.
  • Todos los cálculos de indicadores se basan en velas terminadas para que coincidan con la implementación de MT4 que funcionó en barras completamente cerradas.
  • A diferencia del EA original, no hay un panel de control manual ni un cargador de perfiles basado en archivos. Las zonas se reconstruyen exclusivamente a partir de datos en vivo. datos de velas para mantener el puerto autónomo.
  • La versión StockSharp no incluye una traducción de Python.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// AIS5 Trade Machine: EMA breakout with RSI filter and ATR stops.
/// </summary>
public class Ais5TradeMachineStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevClose;
	private decimal _entryPrice;

	public Ais5TradeMachineStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

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

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");

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

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

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

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

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

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

		_prevClose = 0;
		_entryPrice = 0;
	}

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

		_prevClose = 0;
		_entryPrice = 0;

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

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, rsi, 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 rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var close = candle.ClosePrice;

		if (_prevClose == 0 || atrVal <= 0)
		{
			_prevClose = close;
			return;
		}

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 75)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 25)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		if (Position == 0)
		{
			if (close > emaVal && _prevClose <= emaVal && rsiVal > 50)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (close < emaVal && _prevClose >= emaVal && rsiVal < 50)
			{
				_entryPrice = close;
				SellMarket();
			}
		}

		_prevClose = close;
	}
}