Ver en GitHub

Estrategia por lotes del panel comercial

Descripción general

TradingPanelBatchStrategy es una versión StockSharp del asesor experto MetaTrader 4 EA_TradingPanel. El script original exponía un panel manual donde el comerciante configuraba el número de operaciones simultáneas, el tamaño del lote y las distancias de protección antes de presionar COMPRAR o VENDER. En la versión StockSharp, el mismo comportamiento está automatizado: una vez que el operador establece el parámetro Direction, la estrategia dispara un lote de órdenes de mercado en la siguiente vela terminada y restablece instantáneamente la dirección a None.

La lógica es intencionalmente simple para que el módulo pueda combinarse con señales externas o supervisión manual. Todas las órdenes heredan distancias opcionales de stop-loss y take-profit medidas en pips, lo que refleja los controles de riesgo disponibles en la implementación MQL.

Flujo de trabajo

  1. Cuando comienza la estrategia, calcula el tamaño del pip desde Security.PriceStep. Para símbolos Forex de 1/3/5 dígitos, el valor se multiplica por diez, lo que coincide con la conversión MetaTrader entre puntos y pips.
  2. Si las compensaciones de stop-loss o take-profit son distintas de cero, la estrategia permite a StartProtection gestionar salidas con órdenes de mercado.
  3. La estrategia se suscribe a la serie de velas especificada por CandleType. Después de cada vela terminada, verifica el parámetro Direction.
  4. Si se solicita una dirección y el motor permite operar, la estrategia envía NumberOfOrders órdenes de mercado usando OrderVolume para cada ticket.
  5. Una vez enviado el lote, la estrategia registra la acción y automáticamente establece Direction de nuevo en None, listo para la siguiente activación manual.

Este diseño mantiene el módulo sin estado entre ejecuciones. Los comerciantes pueden configurar repetidamente Direction en Buy o Sell cada vez que requieran un nuevo lote de pedidos; la ejecución siempre ocurre en la siguiente vela completa para evitar actuar sobre datos de mercado parcialmente formados.

Parámetros

Nombre Tipo Predeterminado Descripción
NumberOfOrders int 1 Número de órdenes de mercado enviadas en el siguiente lote.
OrderVolume decimal 0.01 Volumen aplicado a cada orden de mercado.
StopLossPips decimal 2 Distancia de stop-loss convertida de pips a precio absoluto utilizando los metadatos del instrumento actual. Establezca en 0 para desactivar.
TakeProfitPips decimal 10 Distancia de toma de ganancias en pips. Establezca en 0 para desactivar.
Direction TradeDirection None Dirección solicitada para la próxima ejecución. La estrategia restablece el valor después de realizar las órdenes.
CandleType DataType TimeFrameCandle(1m) Serie de velas utilizadas para desencadenar la ejecución.

Notas

  • La estrategia requiere un Security válido con un PriceStep configurado correctamente (y opcionalmente Decimals). Sin estos metadatos, los cálculos de pips vuelven a 1.
  • StartProtection utiliza órdenes de mercado para salidas para imitar cómo el panel MQL cerró posiciones en niveles de stop-loss o take-profit.
  • Debido a que la ejecución ocurre en velas terminadas, los operadores pueden sincronizar lotes de órdenes con análisis personalizados o señales externas actualizando Direction antes de que se cierre la vela.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Trading Panel Batch strategy: DEMA crossover.
/// Buys when fast DEMA crosses above slow DEMA, sells on cross below.
/// </summary>
public class TradingPanelBatchStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public TradingPanelBatchStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast DEMA", "Fast DEMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow DEMA", "Slow DEMA period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
				SellMarket();
		}
		else
		{
			if (fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (fastValue < slowValue && Position >= 0)
				SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
		_hasPrev = true;
	}
}