Convertida do expert advisor MQL original PINBAR.mq4 (pasta MQL/22269). A estratégia detecta reversões de pin bar no período primário e as confirma com filtros de momentum e MACD de períodos superiores. Reproduz o espírito do sistema fonte enquanto usa os recursos de API de alto nível do StockSharp.
Lógica de negociação
Período primário – tipo de candle configurável usado para identificar padrões de ação do preço.
Período superior – tipo de candle configurável usado para confirmar o viés de momentum e tendência MACD.
Detecção de pin bar – uma barra é aceita quando o corpo real é pequeno em relação ao intervalo completo e um pavio domina o candle (razões de corpo e pavio configuráveis).
Filtro de tendência – a EMA rápida deve estar acima (ou abaixo) da EMA lenta para configurações compradas (ou vendidas), espelhando os filtros LWMA do código original.
Confirmação de momentum – o momentum no período superior deve estar acima (comprado) ou abaixo (vendido) de um limiar configurável para pelo menos uma das últimas três barras do período superior.
Confirmação MACD – o valor MACD deve estar acima de sua linha de sinal para operações compradas e abaixo da linha de sinal para vendidas, coincidindo com a confirmação MACD mensal usada no expert MQL.
Confirmação fractal – a estratégia mantém uma janela deslizante de cinco barras e requer a presença do último fractal altista/baixista antes de aceitar uma nova operação, similar ao gate FindFractals() na fonte.
Gestão de risco – stop-loss configurável, take-profit, gatilho de break-even/offset e lógica de trailing stop rastreiam a posição aberta. A operação é encerrada quando qualquer nível é tocado ou quando o nível de trailing é violado.
Regras de entrada
Configuração comprada
Último candle no período primário forma um pin bar altista (pavio inferior longo, corpo pequeno).
EMA rápida > EMA lenta.
Último momentum do período superior (ou um dos dois valores anteriores) está acima do limiar.
MACD do período superior está acima de sua linha de sinal.
Um fractal altista foi detectado recentemente e o preço não o invalidou.
A estratégia está flat ou vendida (as posições vendidas são revertidas).
Configuração vendida
Último candle no período primário forma um pin bar baixista (pavio superior longo, corpo pequeno).
EMA rápida < EMA lenta.
Último momentum do período superior (ou um dos dois valores anteriores) está abaixo do limiar negativo.
MACD do período superior está abaixo de sua linha de sinal.
Um fractal baixista foi detectado recentemente e o preço não o invalidou.
A estratégia está flat ou comprada (as posições compradas são revertidas).
Regras de saída
Stop-loss e take-profit são expressos em porcentagem relativa ao preço de entrada.
O break-even ativa-se uma vez que o preço se move pelo porcentual de gatilho; o stop é movido para entrada mais/menos um offset.
O trailing stop ativa-se após o porcentual de ativação ser atingido e segue o preço na distância configurada.
Sinais opostos também revertem a posição.
Parâmetros
Nome
Padrão
Descrição
CandleType
Candles de 15 minutos
Período primário para detecção de padrões.
TrendCandleType
Candles de 1 hora
Período superior para filtros de momentum/MACD.
FastMaLength
6
Comprimento EMA rápida (substitui LWMA rápida).
SlowMaLength
85
Comprimento EMA lenta (substitui LWMA lenta).
MomentumLength
14
Comprimento do indicador de momentum no período superior.
MomentumThreshold
0.1
Valor mínimo absoluto de momentum para confirmação.
MacdFastLength
12
Comprimento EMA rápida MACD.
MacdSlowLength
26
Comprimento EMA lenta MACD.
MacdSignalLength
9
Comprimento EMA de sinal MACD.
BodyToRangeRatio
0.3
Tamanho máximo do corpo relativo ao intervalo do candle.
WickRatio
0.6
Razão mínima do pavio dominante que define um pin bar.
StopLossPercent
2
Tamanho do stop protetor em porcentagem.
TakeProfitPercent
4
Tamanho do alvo de lucro em porcentagem.
BreakEvenTriggerPercent
1.5
Lucro necessário para mover o stop para break-even.
BreakEvenOffsetPercent
0.2
Offset adicional adicionado ao stop de break-even.
TrailingActivationPercent
2.5
Limiar de lucro para habilitar o trailing stop.
TrailingDistancePercent
1
Distância do trailing stop uma vez ativado.
Notas
O volume está fixado em 1 contrato por padrão; ajuste o volume da estratégia para diferentes tamanhos de posição.
A detecção fractal reinicia quando o preço viola o nível fractal registrado, exigindo um novo padrão antes de uma nova operação.
Os intervalos de otimização estão incluídos para os parâmetros principais para facilitar o backtesting e o ajuste no StockSharp Designer.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PinbarReversal2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast, _prevSlow;
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 PinbarReversal2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 6).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 25).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class pinbar_reversal2_strategy(Strategy):
def __init__(self):
super(pinbar_reversal2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 6) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 25) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(pinbar_reversal2_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(pinbar_reversal2_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return pinbar_reversal2_strategy()