A Estratégia de Painel de Troca de Símbolos é uma conversão StockSharp do painel MQL "Painel de Troca de Símbolos". O especialista original atuou como um widget de gráfico que permitia aos traders digitar um símbolo, mudar o gráfico ativo para esse símbolo e monitorar informações de mercado em tempo real, como valores de OHLC, volume de ticks e spread. A estratégia convertida recria o mesmo fluxo de trabalho no ambiente StockSharp. Ele pode ser iniciado em qualquer título e fornece uma alternância manual para pular para outro instrumento enquanto registra continuamente as métricas de mercado mais relevantes.
Comportamento central
Assina dados de velas e cotações de nível um para o título ativo.
Registra cada vela concluída com abertura, máximo, mínimo, fechamento, volume total e o último spread computado.
Armazena cotações de compra/venda e obtém um spread atualizado que reflete a leitura do painel MQL.
Reage a solicitações de troca manual e substitui a segurança monitorada pelo identificador escolhido sem exigir a reinicialização da estratégia.
Mantém a segurança previamente selecionada para que trocas redundantes sejam ignoradas e ativações duplas acidentais não interrompam as assinaturas.
Parâmetros
Nome
Tipo
Descrição
TargetSecurityId
string
Identificador de segurança que deve ser ativado quando a solicitação de troca for acionada. Strings vazias são ignoradas com um aviso.
CandleType
DataType
Agregação de velas para atualizações periódicas (o padrão é velas de 1 hora, replicando o período do painel MQL).
SwapRequested
bool
Sinalizador manual que solicita uma mudança imediata para TargetSecurityId. Ele é redefinido para false após o processamento da tentativa de troca.
Assinaturas de dados
Assinatura Candle criada com CandleType para a segurança atualmente ativa.
Assinatura de nível um usada para rastrear cotações de compra/venda e calcular um valor de spread ao vivo.
As assinaturas são reiniciadas com segurança sempre que a segurança muda, garantindo que fluxos de dados obsoletos não sejam deixados em execução.
Fluxo de trabalho
Quando a estratégia é iniciada ela resolve a segurança inicial de Strategy.Security ou, se faltar, de TargetSecurityId.
Assinaturas de vela e nível um são abertas para esse instrumento.
Cada vela concluída aciona uma mensagem de registro detalhada que reflete o texto mostrado nos rótulos originais do painel.
As atualizações de nível um recebidas atualizam os valores de compra/venda em cache.
Definir SwapRequested como true e fornecer um TargetSecurityId válido alterna imediatamente a segurança monitorada e reinicia as assinaturas.
Notas de uso
A estratégia foi projetada para monitoramento manual e não realiza pedidos.
O spread só é reportado quando os valores de compra e venda estão presentes e positivos.
Quando um símbolo inválido ou desconhecido é fornecido, um aviso é registrado e a solicitação é descartada sem interromper as assinaturas em execução.
Como a ferramenta original atualizava a IU uma vez por segundo, você pode diminuir o período da vela se precisar de atualizações de log mais frequentes.
Recursos originais MQL preservados
Troca manual de símbolos através de um identificador textual.
Exibição em tempo real de valores, volume e spread de OHLC para o símbolo escolhido.
Salvaguardas contra entradas vazias e adições falhadas do Market Watch (traduzidas em StockSharp avisos).
Diferenças da implementação MQL
A estratégia StockSharp usa mensagens de registro em vez de rótulos na tela. Isso corresponde ao fluxo de trabalho típico dentro de StockSharp enquanto ainda expõe as mesmas informações.
A troca de gráficos é implementada reatribuindo a segurança da estratégia e recriando assinaturas em vez de alterar uma janela de gráfico do terminal.
A lógica de atualização baseada em temporizador é substituída por eventos de conclusão de vela para permanecer alinhado com APIs StockSharp de alto nível.
Requisitos
Conector StockSharp com acesso aos títulos desejados.
Feed de dados de nível um para obter cotações de compra/venda para cálculo de spread.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class symbol_swap_panel_strategy(Strategy):
def __init__(self):
super(symbol_swap_panel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle series for monitoring and signals", "General")
self._ma_period = self.Param("MaPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("MA Period", "Moving average period for entry signals", "Indicators")
self._entry_price = 0.0
self._prev_close = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
def OnReseted(self):
super(symbol_swap_panel_strategy, self).OnReseted()
self._entry_price = 0.0
self._prev_close = 0.0
def OnStarted2(self, time):
super(symbol_swap_panel_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.MaPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(sma, self._process_candle) \
.Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
sma_v = float(sma_value)
# Exit: reversal against trend
if self.Position != 0 and self._entry_price > 0:
if (self.Position > 0 and price < sma_v) or \
(self.Position < 0 and price > sma_v):
if self.Position > 0:
self.SellMarket(abs(self.Position))
else:
self.BuyMarket(abs(self.Position))
self._entry_price = 0.0
self._prev_close = price
return
# Entry: follow MA trend with momentum confirmation
if self.Position == 0 and self._prev_close > 0:
if price > sma_v and self._prev_close <= sma_v:
self.BuyMarket()
self._entry_price = price
elif price < sma_v and self._prev_close >= sma_v:
self.SellMarket()
self._entry_price = price
self._prev_close = price
def CreateClone(self):
return symbol_swap_panel_strategy()