Ver en GitHub

Estrategia Auto Trading Publish

Visión general

Esta estrategia porta la utilidad de MetaTrader 4 "Auto Trading Publish" a StockSharp. En lugar de enviar órdenes de mercado, se centra en controlar cuándo se permite operar. Supervisa el reloj de mercado mediante una suscripción de velas y cambia la bandera AutoTradingActive cuando se alcanza la hora configurada de inicio o parada. La bandera replica el comportamiento de la utilidad original, que alternaba programáticamente el botón "AutoTrading" de MT4.

Lógica de negociación

  • Suscribirse a un flujo ligero de velas (por defecto, velas de un minuto) para seguir la hora de mercado incluso si no se realizan operaciones.
  • Cuando una vela terminada informa la StartHour configurada, activar AutoTradingActive y registrar el evento.
  • Cuando una vela terminada informa la StopHour configurada, desactivar AutoTradingActive y registrar el evento.
  • Suprimir alternancias duplicadas dentro de la misma hora para que el log no se sature si llegan varias velas o ticks durante esa hora.

Parámetros

Parámetro Descripción
StartHour Hora del día (0-23) que activa el trading automático.
StopHour Hora del día (0-23) que desactiva el trading automático.
CandleType Marco temporal usado para consultar el reloj de mercado. Marcos menores reaccionan más rápido.

Notas de uso

  • La estrategia no envía órdenes; solo expone la propiedad AutoTradingActive, que otras estrategias o paneles pueden observar para decidir cuándo enviar operaciones.
  • Cuando la hora de inicio y parada son iguales, el evento de parada se ejecuta después del inicio, dejando el trading desactivado, idéntico al asesor experto original.
  • Elija un marco de velas que coincida con la rapidez requerida para el cambio. Un marco de un minuto ofrece buen equilibrio entre respuesta y uso de recursos.

Diferencias frente a MetaTrader

  • MT4 alternaba un botón global de plataforma mediante mensajes de Windows. StockSharp expone en cambio una bandera a nivel de estrategia, facilitando la integración con configuraciones complejas.
  • El port StockSharp se ejecuta íntegramente dentro de la API de alto nivel, lo que facilita combinarlo con gráficos u otras estrategias auxiliares sin hooks de mensajes de bajo nivel.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Auto Trading Publish strategy: SMA crossover + RSI confirmation.
/// Buys when close crosses above SMA and RSI is below 40.
/// Sells when close crosses below SMA and RSI is above 60.
/// </summary>
public class AutoTradingPublishStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

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

	public int SmaPeriod
	{
		get => _smaPeriod.Value;
		set => _smaPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public AutoTradingPublishStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "SMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

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

		var sma = new SimpleMovingAverage { Length = SmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal? prevClose = null;
		decimal? prevSma = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, rsi, (candle, smaVal, rsiVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;

				if (prevClose.HasValue && prevSma.HasValue)
				{
					var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
					var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;

					if (crossUp && rsiVal < 55m && Position <= 0)
						BuyMarket();
					else if (crossDown && rsiVal > 45m && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevSma = smaVal;
			})
			.Start();

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