Hedger EES (avançado)
Visão geral
A estratégia reflete o comportamento do clássico consultor especialista MetaTrader "EES Hedger". Sempre que um trader externo, operador discricionário ou outro sistema automatizado abre uma posição na mesma conta, a estratégia cria imediatamente uma cobertura oposta utilizando um volume configurável. Em seguida, ele gerencia o hedge com regras de stop-loss, take-profit, ponto de equilíbrio e trailing stop, para que a exposição seja neutralizada enquanto os lucros do hedge são protegidos.
Ao contrário das estratégias tradicionais baseadas em sinais, este módulo assume que as entradas são produzidas em outro lugar. Sua única responsabilidade é observar as negociações da conta, reagir aos tickets correspondentes e proteger a posição de hedge até que ela seja fechada pelas ordens de proteção ou manualmente.
Lógica de negociação
- Detecção de negociações externas – o fluxo do conector de negociações da conta é monitorado. As negociações cujo comentário corresponde a
OriginalOrderComment (ou todas as negociações quando o campo está vazio) são tratadas como a fonte que deve ser protegida. As negociações produzidas pela própria estratégia são filtradas armazenando seus identificadores de transação.
- Ordens espelhadas – assim que uma negociação qualificada é recebida, a estratégia envia uma ordem de mercado imediata na direção oposta com volume
HedgeVolume. Um HedgerOrderComment opcional ajuda as ferramentas de back-office a separar as ordens de hedge de outras atividades.
- Gerenciamento de risco – após o preenchimento do hedge a estratégia coloca ordens de stop-loss e take-profit em distâncias definidas pelos parâmetros pip. Quando as condições de equilíbrio são atendidas, o stop é movido para o preço de entrada mais um pip. Se o trailing estiver habilitado, o stop avança ainda mais à medida que o mercado continua a se mover a favor do hedge.
- Limpeza de estado – quando a posição chega a zero (por exemplo, após um fechamento manual) todas as ordens de proteção são canceladas e os sinalizadores internos são redefinidos para que a próxima negociação externa possa ser protegida do zero.
Parâmetros
| Parâmetro |
Descrição |
HedgeVolume |
Volume utilizado para abrir a posição de hedge oposta. |
StopLossPips |
Distância do preço de entrada até a ordem de stop loss de proteção. |
TakeProfitPips |
Distância do preço de entrada até a ordem de take-profit. |
TrailingStopPips |
Distância mantida pelo trailing stop quando o limite de ativação é excedido. Defina como zero para desativar o rastreamento. |
TrailingActivationPips |
Lucro mínimo (em pips) necessário antes que o trailing stop comece a se mover. |
BreakEvenPips |
Limite de lucro (em pips) após o qual o stop loss é movido para o preço de entrada mais um pip. |
OriginalOrderComment |
Filtro de comentários opcional que seleciona quais negociações externas devem ser protegidas. Deixe em branco para proteger todas as negociações do instrumento. |
HedgerOrderComment |
Comentário anexado às ordens de hedge e stops de proteção gerados pela estratégia. |
Notas práticas
- Atribua à estratégia a mesma carteira/conta que o trader externo. Todas as posições criadas nessa conta ficarão visíveis para o conector e poderão, portanto, ser cobertas.
- Quando usado com pontes MetaTrader, configure o consultor especialista ou ponte para copiar o comentário do pedido original para que a filtragem funcione conforme o esperado.
- O tamanho do pip é derivado da etapa de preço do instrumento. Para símbolos FX de cinco dígitos, a distância traduz automaticamente os valores de pip especificados em compensações de preço corretas.
- A lógica do ponto de equilíbrio e do trailing nunca afasta o stop do preço de entrada. Apenas melhorias são aplicadas, garantindo que, uma vez atingido o ponto de equilíbrio, o stop nunca volte a um nível deficitário.
- A estratégia não gerencia a posição original. Fechar ou modificá-lo continua sendo responsabilidade do sistema de negociação principal.
Fluxo de trabalho de uso
- Configure os parâmetros da estratégia, prestando especial atenção aos filtros de comentários e ao volume do hedge.
- Inicie a estratégia e confirme se ela está conectada ao feed da corretora. Permanecerá ocioso até que chegue um comércio externo.
- Assim que aparecer uma negociação qualificada, observe como a ordem de hedge é criada e como as ordens de proteção são colocadas no DOM.
- Monitore o ponto de equilíbrio e o comportamento de trilha para garantir que as distâncias de pip configuradas correspondam às especificações do contrato do corretor.
- Pare a estratégia quando o hedge não for mais necessário. Todas as ordens de proteção em funcionamento são canceladas durante o desligamento.
Limitações
- O módulo pressupõe acesso ao fluxo de negociação da conta. Ele não pode proteger negociações que sejam completamente invisíveis para o conector.
- As regras de arredondamento de volume são específicas da corretora. Certifique-se de que o
HedgeVolume configurado seja compatível com a etapa do lote do instrumento.
- Como a estratégia coloca ordens de mercado imediatamente, a derrapagem em mercados rápidos pode resultar em coberturas imperfeitas. Aumente as distâncias de stop-loss para compensar isso quando necessário.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Adapted from the MetaTrader "EES Hedger" expert advisor.
/// Uses EMA crossover signals with break-even and trailing stop risk management.
/// </summary>
public class EesHedgerAdvancedStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPips;
private readonly StrategyParam<int> _takeProfitPips;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Fast EMA period.
/// </summary>
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
/// <summary>
/// Slow EMA period.
/// </summary>
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
/// <summary>
/// Stop-loss distance in price steps.
/// </summary>
public int StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance in price steps.
/// </summary>
public int TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes default parameters.
/// </summary>
public EesHedgerAdvancedStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_stopLossPips = Param(nameof(StopLossPips), 500)
.SetDisplay("Stop Loss", "Stop-loss distance", "Risk Management");
_takeProfitPips = Param(nameof(TakeProfitPips), 500)
.SetDisplay("Take Profit", "Take-profit distance", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles used for calculations", "Market Data");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return new[] { (Security, CandleType) };
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
var fastEma = new EMA { Length = FastPeriod };
var slowEma = new EMA { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
// Use StartProtection for SL/TP
var tp = TakeProfitPips > 0 ? new Unit(TakeProfitPips, UnitTypes.Absolute) : null;
var sl = StopLossPips > 0 ? new Unit(StopLossPips, UnitTypes.Absolute) : null;
StartProtection(tp, sl);
base.OnStarted2(time);
}
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
if (!_hasPrev)
{
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
// EMA crossover detection
var crossedUp = _prevFast <= _prevSlow && fastValue > slowValue;
var crossedDown = _prevFast >= _prevSlow && fastValue < slowValue;
if (crossedUp)
{
// Close short if any, then go long
if (Position < 0)
BuyMarket(Math.Abs(Position));
if (Position <= 0)
BuyMarket(Volume);
}
else if (crossedDown)
{
// Close long if any, then go short
if (Position > 0)
SellMarket(Position);
if (Position >= 0)
SellMarket(Volume);
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, UnitTypes, Unit
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage
class ees_hedger_advanced_strategy(Strategy):
def __init__(self):
super(ees_hedger_advanced_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._stop_loss_pips = self.Param("StopLossPips", 500) \
.SetDisplay("Stop Loss", "Stop-loss distance", "Risk Management")
self._take_profit_pips = self.Param("TakeProfitPips", 500) \
.SetDisplay("Take Profit", "Take-profit distance", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles used for calculations", "Market Data")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
@property
def StopLossPips(self):
return self._stop_loss_pips.Value
@property
def TakeProfitPips(self):
return self._take_profit_pips.Value
@property
def CandleType(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(ees_hedger_advanced_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self.ProcessCandle).Start()
tp = Unit(self.TakeProfitPips, UnitTypes.Absolute) if self.TakeProfitPips > 0 else None
sl = Unit(self.StopLossPips, UnitTypes.Absolute) if self.StopLossPips > 0 else None
self.StartProtection(tp, sl)
def ProcessCandle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_value = float(fast_value)
slow_value = float(slow_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_fast = fast_value
self._prev_slow = slow_value
self._has_prev = True
return
if not self._has_prev:
self._prev_fast = fast_value
self._prev_slow = slow_value
self._has_prev = True
return
crossed_up = self._prev_fast <= self._prev_slow and fast_value > slow_value
crossed_down = self._prev_fast >= self._prev_slow and fast_value < slow_value
if crossed_up:
if self.Position < 0:
self.BuyMarket(abs(self.Position))
if self.Position <= 0:
self.BuyMarket(self.Volume)
elif crossed_down:
if self.Position > 0:
self.SellMarket(self.Position)
if self.Position >= 0:
self.SellMarket(self.Volume)
self._prev_fast = fast_value
self._prev_slow = slow_value
def OnReseted(self):
super(ees_hedger_advanced_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def CreateClone(self):
return ees_hedger_advanced_strategy()