A Estratégia Wedge Pattern é uma conversão do expert advisor Wedge pattern.mq4 do MetaTrader para a API de alto nível do StockSharp. A estratégia procura consolidações de cunha simétricas derivadas dos fractais de Bill Williams e negocia os rompimentos quando filtros de tendência e momentum se alinham.
A implementação de alto nível substitui a gestão manual de ordens original por recursos StockSharp enquanto preserva a lógica de decisão:
Filtro de tendência: compara uma média móvel linearmente ponderada (LWMA) rápida e uma lenta calculadas em preços típicos.
Filtro de momentum: avalia a distância absoluta do indicador de momentum de 14 períodos em relação ao nível neutro (100). As três últimas leituras de momentum devem exceder um limiar configurável.
Confirmação MACD: exige que a linha principal MACD esteja acima da linha de sinal para compras (ou abaixo para vendas).
Detecção de cunha fractal: coleta pontos fractais superiores e inferiores para construir linhas de tendência convergentes. Sinais de negociação são produzidos quando o preço fecha além dessas linhas mais um buffer de confirmação configurável.
Gestão de risco: imita a implementação MQL com distâncias fixas de stop-loss e take-profit, movimento automático para break-even e ajustes de trailing stop.
Como funciona
Assinar um único timeframe definido pelo parâmetro CandleType.
Atualizar valores dos indicadores a cada candle concluído e manter buffers rolantes de máximas e mínimas para detectar novos fractais.
Construir linhas de tendência da cunha a partir dos dois fractais de máxima e mínima mais recentes. Apenas cunhas convergentes (máximas descendentes e mínimas ascendentes) são consideradas setups válidos.
Uma compra é aberta quando:
LWMA rápida > LWMA lenta.
Linha MACD > linha de sinal.
Qualquer uma das três últimas leituras de momentum excede o limiar configurado.
O candle atual fecha acima da linha de tendência superior projetada por pelo menos o buffer de rompimento.
Uma venda espelha as condições com linhas e limiares invertidos.
Após a entrada, a estratégia coloca imediatamente ordens de stop-loss e take-profit. Depois pode mover o stop para break-even e trailar conforme a posição se torna lucrativa.
Parâmetros
Parâmetro
Descrição
CandleType
Timeframe usado para análise e ordens.
FastMaPeriod
Comprimento do filtro LWMA rápido.
SlowMaPeriod
Comprimento do filtro LWMA lento.
MomentumPeriod
Período de retrospectiva do indicador de momentum (padrão 14).
MomentumThreshold
Distância mínima de 100 exigida do indicador de momentum para considerar o mercado impulsivo.
Habilita e configura o comportamento do trailing-stop.
BreakoutBufferPips
Buffer extra aplicado à confirmação do rompimento da cunha.
Todas as configurações baseadas em pips são convertidas em distâncias de preço usando o tamanho de tick do ativo. O cálculo padrão de pip considera precificação fracionária (3 ou 5 casas decimais) exatamente como no Expert Advisor original.
Diretrizes de uso
Anexe a estratégia ao instrumento desejado e selecione o timeframe de candles correspondente ao setup original (por exemplo, candles de 15 minutos).
Configure o tamanho da posição pela propriedade base Strategy.Volume.
Opcionalmente ajuste filtros e parâmetros de risco para corresponder à volatilidade do mercado-alvo.
Inicie a estratégia; ela assinará candles, desenhará dados no gráfico e negociará automaticamente quando rompimentos de cunha ocorrerem.
Diferenças em relação à versão MQL
A versão StockSharp usa APIs de alto nível SubscribeCandles e binding de indicadores, evitando processamento manual de ticks.
Gestão de trailing stop e break-even depende de SetStopLoss/SetTakeProfit, integrando-se ao comportamento protetor incorporado.
Apenas uma posição é mantida por vez; o script MetaTrader suportava piramidação até um número máximo de operações.
Funções de alerta, e-mail e notificação são omitidas; o tratamento de eventos deve ser implementado externamente se necessário.
Apesar dessas adaptações, a lógica central de entrada e as regras protetoras seguem de perto o expert MetaTrader original usando padrões idiomáticos do StockSharp.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Wedge Pattern strategy: WMA crossover + Momentum.
/// Buys when fast WMA crosses above slow WMA and momentum > 100.
/// Sells on cross below with momentum < 100.
/// </summary>
public class WedgePatternStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int MomPeriod
{
get => _momPeriod.Value;
set => _momPeriod.Value = value;
}
public WedgePatternStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 40)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_momPeriod = Param(nameof(MomPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Momentum", "Momentum period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new WeightedMovingAverage { Length = FastPeriod };
var slow = new WeightedMovingAverage { Length = SlowPeriod };
var mom = new Momentum { Length = MomPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, mom, (candle, fastVal, slowVal, momVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && momVal > 100m && Position <= 0)
BuyMarket();
else if (crossDown && momVal < 100m && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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 WeightedMovingAverage, Momentum
from StockSharp.Algo.Strategies import Strategy
class wedge_pattern_strategy(Strategy):
def __init__(self):
super(wedge_pattern_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 40) \
.SetGreaterThanZero() \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._mom_period = self.Param("MomPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Momentum", "Momentum period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(wedge_pattern_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(wedge_pattern_strategy, self).OnStarted2(time)
self._fast_ind = WeightedMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = WeightedMovingAverage()
self._slow_ind.Length = self._slow_period.Value
self._mom_ind = Momentum()
self._mom_ind.Length = self._mom_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._mom_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, mom_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
mom_val = float(mom_value)
if self._prev_fast is not None and self._prev_slow is not None:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and mom_val > 100.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and mom_val < 100.0 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return wedge_pattern_strategy()