Ver no GitHub

Estratégia de troca de símbolos

A Estratégia de troca de símbolos é a porta StockSharp do utilitário MetaTrader 5 "Symbol Swap". O programa MQL5 original abre um painel onde um trader pode inserir qualquer ticker, mudar imediatamente o gráfico atual para esse símbolo e monitorar uma janela de dados compacta com o horário mais recente, preços OHLC, volume de ticks e spread. Esta conversão C# mantém as mesmas responsabilidades enquanto depende exclusivamente da assinatura de alto nível API de StockSharp.

Comportamento

  1. No início, a estratégia resolve o instrumento a ser observado. Primeiro ele tenta WatchedSecurityId; se o campo estiver vazio, ele volta para Strategy.Security que está configurado no inicializador.
  2. Os dados da vela do CandleType escolhido são transmitidos por meio de SubscribeCandles(...). As barras finalizadas fornecem os volumes de abertura, máximo, mínimo, fechamento e tick que preenchem o painel.
  3. Os melhores valores de lance/venda em tempo real chegam por meio de SubscribeLevel1(...). O spread é recalculado a cada atualização de cotação para espelhar a janela de dados MQL.
  4. O bloco formatado é gravado no log de estratégia (OutputMode = Log) ou renderizado em um gráfico (OutputMode = Chart) com DrawText(...), recriando o painel flutuante de MetaTrader.
  5. Chamar SwapSecurity("TICKER") durante a execução resolve a nova segurança por meio de SecurityProvider.LookupById e inscreve novamente a vela e os feeds de Nível 1 no instrumento solicitado.

A estratégia é apenas informativa; não faz pedidos. Ele pode funcionar de forma independente como um painel de mercado ou junto com outros bots de negociação.

Parâmetros

Nome Descrição Padrão
CandleType Período que define a assinatura da vela usada para construir OHLC e dados de volume de ticks. TimeFrame(1 minute)
WatchedSecurityId Identificador de instrumento opcional. Deixe em branco para usar Strategy.Security. vazio
OutputMode Destino de renderização do bloco de informações. Escolha entre Chart (sobreposição perto do preço) ou Log (registro de estratégia). Chart

Métodos públicos

Método Descrição
SwapSecurity(string securityId) Resolve o ticker fornecido através do SecurityProvider ativo e muda imediatamente o painel para esse símbolo. O método pode ser chamado diversas vezes; cada chamada limpa assinaturas anteriores de vela/nível 1 antes de adicionar os novos feeds.

Notas de uso

  • Certifique-se de que o conector exponha o identificador solicitado; caso contrário, SecurityProvider.LookupById lança uma exceção.
  • Quando OutputMode = Chart, a estratégia cria automaticamente uma área do gráfico, desenha as velas subscritas e sobrepõe o bloco de status. Para o modo log, apenas as atualizações textuais são produzidas.
  • O volume do tick é igual ao TotalVolume da vela, que é como MetaTrader relata sua contagem de ticks por barra.
  • O spread é mostrado apenas quando o melhor lance e o melhor pedido estão disponíveis. Caso contrário, o campo exibirá n/a.

Detalhes da conversão

  • O loop do temporizador MetaTrader é substituído por assinaturas StockSharp. As velas são acionadas uma vez por barra finalizada e as cotações do Nível 1 atualizam o spread em tempo real.
  • Os rótulos do painel MQL são representados por um único bloco de texto multilinha. O texto usa a ordem exata da ferramenta original: Tempo, Período, Símbolo, Fechamento, Abertura, Alto, Baixo, Volume do Tick, Spread.
  • As trocas de símbolos em tempo de execução não precisam mais de gerenciamento manual do Market Watch – a estratégia resolve os instrumentos diretamente por meio do provedor de segurança StockSharp.
  • Somente chamadas API de alto nível são usadas (SubscribeCandles, SubscribeLevel1, DrawText, AddInfo). Não há cálculos manuais de indicadores ou manipulações diretas de conectores, satisfazendo as regras de codificação do repositório.
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>
/// Market monitoring strategy that tracks price metrics and trades on significant
/// spread changes. Simplified from the MetaTrader "Symbol Swap" display panel.
/// </summary>
public class SymbolSwapStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<decimal> _spreadThreshold;

	private SimpleMovingAverage _sma;
	private decimal _entryPrice;

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

	/// <summary>
	/// SMA period for trend detection.
	/// </summary>
	public int SmaPeriod
	{
		get => _smaPeriod.Value;
		set => _smaPeriod.Value = value;
	}

	/// <summary>
	/// Price deviation threshold for entry signals.
	/// </summary>
	public decimal SpreadThreshold
	{
		get => _spreadThreshold.Value;
		set => _spreadThreshold.Value = value;
	}

	/// <summary>
	/// Initializes strategy parameters.
	/// </summary>
	public SymbolSwapStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle series for signals", "General");

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

		_spreadThreshold = Param(nameof(SpreadThreshold), 3m)
			.SetGreaterThanZero()
			.SetDisplay("Spread Threshold", "Price deviation from SMA to trigger entry", "Signals");
	}

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

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

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

		_sma = new SimpleMovingAverage { Length = SmaPeriod };

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

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

		if (!IsFormed)
			return;

		var price = candle.ClosePrice;

		// Exit on mean reversion
		if (Position != 0 && _entryPrice > 0m)
		{
			var pnl = Position > 0
				? price - _entryPrice
				: _entryPrice - price;

			// Exit on profit or loss threshold
			if (pnl >= SpreadThreshold || pnl <= -SpreadThreshold * 2m)
			{
				if (Position > 0)
					SellMarket(Math.Abs(Position));
				else
					BuyMarket(Math.Abs(Position));

				_entryPrice = 0m;
				return;
			}
		}

		// Entry on deviation
		if (Position == 0)
		{
			var deviation = price - smaValue;

			if (deviation > SpreadThreshold)
			{
				SellMarket();
				_entryPrice = price;
			}
			else if (deviation < -SpreadThreshold)
			{
				BuyMarket();
				_entryPrice = price;
			}
		}
	}
}