Ver en GitHub

Estrategia del panel de intercambio de símbolos

Descripción general

La Estrategia de panel de intercambio de símbolos es una conversión StockSharp del panel MQL "Panel de intercambio de símbolos". El experto original actuó como un widget de gráfico que permitía a los operadores escribir un símbolo, cambiar el gráfico activo a ese símbolo y monitorear información de mercado en tiempo real, como valores OHLC, volumen de ticks y spread. La estrategia convertida recrea el mismo flujo de trabajo en el entorno StockSharp. Se puede iniciar con cualquier valor y proporciona un cambio manual para saltar a otro instrumento mientras registra continuamente las métricas de mercado más relevantes.

Comportamiento central

  • Se suscribe a datos de velas y cotizaciones de nivel uno para el valor activo.
  • Registra cada vela completa con apertura, máximo, mínimo, cierre, volumen total y el último diferencial calculado.
  • Almacena cotizaciones de oferta/demanda y obtiene un margen actualizado que refleja la lectura del panel MQL.
  • Reacciona a solicitudes de intercambio manuales y reemplaza la seguridad monitoreada con el identificador elegido sin necesidad de reiniciar la estrategia.
  • Mantiene la seguridad previamente seleccionada para que se ignoren los intercambios redundantes y las activaciones dobles accidentales no interrumpan las suscripciones.

Parámetros

Nombre Tipo Descripción
TargetSecurityId string Identificador de seguridad que debe activarse cuando se activa la solicitud de intercambio. Las cadenas vacías se ignoran con una advertencia.
CandleType DataType Agregación de velas para actualizaciones periódicas (el valor predeterminado es velas de 1 hora, replicando el período de tiempo del panel MQL.
SwapRequested bool Marcador manual que solicita un cambio inmediato a TargetSecurityId. Se restablece a false después de que se procesa el intento de intercambio.

Suscripciones de datos

  • Suscripción de vela creada con CandleType para la seguridad actualmente activa.
  • Suscripción de nivel uno utilizada para realizar un seguimiento de las cotizaciones de oferta y demanda y calcular un valor de diferencial en vivo.
  • Las suscripciones se reinician de forma segura cada vez que cambia la seguridad, lo que garantiza que no se dejen en ejecución flujos de datos obsoletos.

Flujo de trabajo

  1. Cuando la estrategia comienza resuelve la seguridad inicial desde Strategy.Security o, si falta, desde TargetSecurityId.
  2. Se abren suscripciones de vela y de nivel uno para ese instrumento.
  3. Cada vela completa activa un mensaje de registro detallado que refleja el texto que se muestra en las etiquetas originales del panel.
  4. Las actualizaciones entrantes de nivel uno actualizan los valores de oferta/demanda almacenados en caché.
  5. Configurar SwapRequested en true y proporcionar un TargetSecurityId válido cambia inmediatamente la seguridad monitoreada y reinicia las suscripciones.

Notas de uso

  • La estrategia está diseñada para seguimiento manual y no realiza pedidos.
  • El diferencial solo se informa cuando los valores de oferta y demanda están presentes y son positivos.
  • Cuando se proporciona un símbolo no válido o desconocido, se registra una advertencia y la solicitud se descarta sin interrumpir las suscripciones en ejecución.
  • Debido a que la herramienta original actualizaba la interfaz de usuario una vez por segundo, puede reducir el período de tiempo de la vela si necesita actualizaciones de registro más frecuentes.

Se conservan las características originales de MQL

  • Cambio manual de símbolo a través de un identificador textual.
  • Visualización en tiempo real de valores, volumen y extensión de OHLC para el símbolo elegido.
  • Protege contra entradas vacías y adiciones fallidas de Market Watch (traducidas a advertencias StockSharp.

Diferencias con la implementación MQL

  • La estrategia StockSharp utiliza mensajes de registro en lugar de etiquetas en pantalla. Esto coincide con el flujo de trabajo típico dentro de StockSharp y al mismo tiempo expone la misma información.
  • El cambio de gráfico se implementa reasignando la seguridad de la estrategia y recreando las suscripciones en lugar de alterar la ventana del gráfico del terminal.
  • La lógica de actualización basada en temporizador se reemplaza por eventos de finalización de velas para mantenerse alineado con las API StockSharp de alto nivel.

Requisitos

  • Conector StockSharp con acceso a los valores deseados.
  • Alimentación de datos de nivel uno para obtener cotizaciones de oferta y demanda para el cálculo del diferencial.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Price monitoring strategy that logs OHLC metrics and trades on candle patterns.
/// Simplified from the "Symbol Swap Panel" MQL display widget.
/// </summary>
public class SymbolSwapPanelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _maPeriod;

	private SimpleMovingAverage _sma;
	private decimal _entryPrice;
	private decimal _prevClose;

	/// <summary>
	/// Candle type for monitoring.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Moving average period for trend signals.
	/// </summary>
	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	/// <summary>
	/// Initializes strategy parameters.
	/// </summary>
	public SymbolSwapPanelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle series for monitoring and signals", "General");

		_maPeriod = Param(nameof(MaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Moving average period for entry signals", "Indicators");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, CandleType);
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_sma = null;
		_entryPrice = 0m;
		_prevClose = 0m;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_sma = new SimpleMovingAverage { Length = MaPeriod };

		SubscribeCandles(CandleType)
			.Bind(_sma, ProcessCandle)
			.Start();
	}

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

		var price = candle.ClosePrice;
		var high = candle.HighPrice;
		var low = candle.LowPrice;

		// Log price info
		LogInfo(
			$"Time: {candle.CloseTime:O}, O: {candle.OpenPrice}, H: {high}, L: {low}, C: {price}, " +
			$"Vol: {candle.TotalVolume}, SMA: {smaValue:F5}");

		// Exit: reversal or profit target
		if (Position != 0 && _entryPrice > 0m)
		{
			var pnl = Position > 0
				? price - _entryPrice
				: _entryPrice - price;

			// Exit on trend reversal
			if ((Position > 0 && price < smaValue) ||
				(Position < 0 && price > smaValue))
			{
				if (Position > 0)
					SellMarket(Math.Abs(Position));
				else
					BuyMarket(Math.Abs(Position));

				_entryPrice = 0m;
				_prevClose = price;
				return;
			}
		}

		// Entry: follow MA trend with momentum confirmation
		if (Position == 0 && _prevClose > 0m)
		{
			if (price > smaValue && _prevClose <= smaValue)
			{
				BuyMarket();
				_entryPrice = price;
			}
			else if (price < smaValue && _prevClose >= smaValue)
			{
				SellMarket();
				_entryPrice = price;
			}
		}

		_prevClose = price;
	}
}