Estratégia de controle de risco de pedidos fechados
Visão geral
A Estratégia de Fechamento de Pedidos é um utilitário de gerenciamento de risco que reflete o comportamento do consultor especialista MQL original CloseOrders.mq4. Ele monitora continuamente os lucros e perdas flutuantes das posições abertas e liquida automaticamente as ordens correspondentes assim que a meta de lucro ou o limite de perda for atingido. Isto o torna adequado para proteger um portfólio ou sincronizar saídas em múltiplas estratégias.
Como funciona
A estratégia assina uma série de velas configuráveis (1 minuto por padrão) e avalia o PnL flutuante atual sempre que uma vela fecha.
O PnL flutuante é calculado para as posições ativas da carteira. Quando um número mágico é fornecido, apenas as posições cujo StrategyId interno corresponda ao valor configurado são incluídas.
Se o lucro flutuante for igual ou superior ao valor alvo, todas as ordens e posições correspondentes serão fechadas.
Se o lucro flutuante cair abaixo da perda de corte configurada (um número negativo), a mesma rotina de liquidação é acionada para minimizar perdas adicionais.
As ordens ativas que satisfazem o filtro de número mágico são canceladas antes de nivelar as posições para garantir que nenhuma nova exposição seja aberta durante a liquidação.
A rotina de liquidação continua em execução até que todas as posições correspondentes estejam estáveis, garantindo que os preenchimentos parciais sejam tratados normalmente.
Parâmetros
Parâmetro
Descrição
Dinheiro de lucro alvo
Lucro flutuante (na moeda da conta) que desencadeia a liquidação de ordens correspondentes. Deve ser maior que zero.
Cortar dinheiro com perdas
PnL flutuante negativo (na moeda da conta) que força a liquidação. Um valor de 0 desativa a saída baseada em perdas.
Número Mágico
Identificador de estratégia opcional. Deixe em branco para gerenciar todas as posições abertas; caso contrário, apenas as posições cujo StrategyId seja igual ao valor fornecido serão afetadas.
Tipo de vela
Série de velas usada para acionar verificações periódicas de lucros. Ajuste o prazo quando o monitoramento de frequência mais alta for necessário.
Notas de implementação
O conceito de número mágico MQL é mapeado para os campos UserOrderId/StrategyId em StockSharp. Certifique-se de que as estratégias que devem ser gerenciadas utilizem o mesmo identificador.
Tabulações são usadas para recuo e o arquivo segue a estrutura comum solicitada para estratégias convertidas.
A estratégia cancela as ordens pendentes antes de enviar ordens de mercado para nivelar a exposição, evitando a reentrada imediata.
A proteção inicial pode ser adicionada se a estratégia for combinada com componentes de negociação em tempo real que necessitam de tratamento de emergência.
Dicas de uso
Implemente a estratégia junto com estratégias de negociação que definem um StrategyId personalizado para centralizar a lógica de saída.
Ajuste o parâmetro Candle Type para equilibrar a capacidade de resposta e o uso de recursos; prazos mais curtos proporcionam uma reação mais rápida às mudanças no PnL.
Combine o utilitário com alertas para receber notificações sempre que a liquidação automatizada for executada.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Close Orders Risk Control strategy: CCI crossover with risk management.
/// Buys when CCI crosses above zero, sells when crosses below zero.
/// </summary>
public class CloseOrdersRiskControlStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevCci;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public CloseOrdersRiskControlStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold for crossover", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCci = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevCci < -CciLevel && cciValue >= -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevCci > CciLevel && cciValue <= CciLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevCci = cciValue;
_hasPrev = true;
}
}