Ver en GitHub

Estrategia experta de Wajdyss MA

Descripción general

Wajdyss MA Expert Strategy es una versión de C# del MetaTrader 4 asesor experto "wajdyss MA expert v3". Compara dos promedios móviles configurados con períodos, modos de cálculo, turnos y precios aplicados independientes. Un cruce alcista del promedio rápido por encima del promedio lento abre una exposición larga, mientras que un cruce bajista abre una exposición corta. La conversión reproduce las reglas originales de administración de dinero, el cierre automático opcional de operaciones opuestas y los filtros de liquidación de fin de día/fin de semana.

Lógica de trading

  1. Suscríbase a las CandleType seleccionadas (velas de 15 minutos de forma predeterminada) y calcule los promedios móviles rápido y lento utilizando las configuraciones MovingAverageMethod y PriceSource elegidas para cada tramo.
  2. Guarde los valores del indicador para velas terminadas. Evalúe una señal alcista cuando el promedio rápido (con su cambio configurado) está por encima del promedio lento en la última barra cerrada mientras que hace dos barras estaba por debajo. Evalúe una señal bajista con la condición inversa.
  3. Aplicar un tiempo de reutilización entre nuevas entradas de la misma dirección. La estrategia debe esperar al menos una vela completa del período de tiempo suscrito después de la última operación de ese lado, reflejando la guardia de tiempo variable global de la versión MT4.
  4. Cuando AutoCloseOpposite está habilitado, cancele las órdenes de trabajo y revierta la exposición en una sola orden de mercado: el nuevo volumen de la orden incluye cualquier posición pendiente en la dirección opuesta, por lo que la cuenta cambia inmediatamente.
  5. Aplicar filtros de cierre diario y viernes. Después del DailyCloseHour/DailyCloseMinute o FridayCloseHour/FridayCloseMinute configurado, todas las posiciones se aplanan y las nuevas operaciones se bloquean hasta la siguiente sesión.

Gestión de riesgos y dinero

  • TakeProfitPips, StopLossPips y TrailingStopPips se interpretan en pips completos. La implementación los convierte en incrementos de precios utilizando los metadatos de seguridad e impulsa el motor StartProtection de StockSharp con salidas de mercado para lograr la paridad con la lógica de seguimiento original.
  • UseMoneyManagement emula el cálculo del lote MT4: volume = (account_balance / BalanceReference) * InitialVolume. Los límites de intercambio se respetan mediante controles de volumen, mínimo y máximo.
  • Si la administración del dinero está deshabilitada, los pedidos usan InitialVolume directamente.

Parámetros

Parámetro Tipo Predeterminado Descripción
FastPeriod int 10 Período de la media móvil rápida.
FastShift int 0 Barras para cambiar el promedio rápido antes de comparar valores cruzados.
FastMethod MovingAverageMethod Ema Modo de media móvil para la línea rápida (Sma, Ema, Smma, Lwma).
FastPriceType PriceSource Close El precio de la vela se introduce en la media móvil rápida (Close, Open, High, Low, Median, Typical, Weighted).
SlowPeriod int 20 Período de la media móvil lenta.
SlowShift int 0 Barras para desplazar el promedio lento antes de la comparación.
SlowMethod MovingAverageMethod Ema Modo de media móvil para la línea lenta.
SlowPriceType PriceSource Close El precio de las velas alimentó el promedio lento.
TakeProfitPips decimal 100 Distancia al objetivo de ganancias en pips (establecido en 0 para desactivarlo).
StopLossPips decimal 50 Distancia hasta la parada de protección en pips (establecida en 0 para desactivarla).
TrailingStopPips decimal 0 Distancia del trailing stop en pips (establezca en 0 para desactivarlo).
AutoCloseOpposite bool true Cierre la exposición opuesta antes de abrir una nueva operación en la otra dirección.
InitialVolume decimal 0.1 Volumen comercial base antes de aplicar la gestión del dinero.
UseMoneyManagement bool true Habilite el tamaño de posición basado en el equilibrio.
BalanceReference decimal 1000 Divisor utilizado al escalar el volumen con el saldo de la cuenta.
DailyCloseHour int 23 Hora (0-23) tras la cual se cierran las posiciones diarias.
DailyCloseMinute int 45 Componente minucioso del filtro de cierre diario.
FridayCloseHour int 22 Hora (0-23) después de la cual se detiene la negociación del viernes.
FridayCloseMinute int 45 Componente de minutos del filtro de cierre del viernes.
CandleType DataType 15m período de tiempo Serie de velas utilizadas para cálculos y tiempos de enfriamiento.

Notas

  • La estrategia se basa exclusivamente en el StockSharp API de alto nivel: las velas se procesan a través de SubscribeCandles, los enlaces de indicadores alimentan los promedios móviles y StartProtection gestiona órdenes de parada, toma de ganancias y seguimiento.
  • El aplanamiento de posiciones utiliza órdenes de mercado para reflejar los cierres inmediatos de tickets opuestos por parte del experto en MT4.
  • No se incluye ninguna traducción de Python en esta carpeta; solo se proporciona la implementación de C#.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Wajdyss MA Expert: Fast/slow EMA crossover with ATR stops.
/// </summary>
public class WajdyssMaExpertStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

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

		_fastLength = Param(nameof(FastLength), 10)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");

		_slowLength = Param(nameof(SlowLength), 20)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

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

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

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

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

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

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
	}

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

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;

		var fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var atr = new AverageTrueRange { Length = AtrLength };

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

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

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

		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var close = candle.ClosePrice;

		// Exit
		if (Position > 0)
		{
			if (close <= _entryPrice - atrVal * 2m || close >= _entryPrice + atrVal * 3m || fastVal < slowVal)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close >= _entryPrice + atrVal * 2m || close <= _entryPrice - atrVal * 3m || fastVal > slowVal)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		// Entry: EMA crossover
		if (Position == 0)
		{
			if (_prevFast <= _prevSlow && fastVal > slowVal)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (_prevFast >= _prevSlow && fastVal < slowVal)
			{
				_entryPrice = close;
				SellMarket();
			}
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}