A Estratégia de 10 Pips EURUSD é um sistema de rompimento que reproduz a lógica do Expert Advisor original do MetaTrader. Ela observa a vela completada mais recente e coloca ordens stop acima e abaixo desse intervalo. As ordens são dimensionadas em pips, ajustadas ao tamanho de tick do instrumento atual, e opcionalmente gerenciadas por um trailing stop. A implementação usa assinaturas de velas de alto nível do StockSharp junto com atualizações do livro de ordens para manter o comportamento próximo à versão MQL enquanto permanece neutro com o broker.
Lógica da estratégia
Assinar o tipo de vela selecionado e aguardar até que uma nova barra se torne ativa.
Capturar a máxima e mínima da vela anterior quando essa barra termina. As ordens pendentes são canceladas neste momento porque o EA original as limita a uma barra.
No primeiro tick da nova barra verificar que:
A abertura atual está dentro do intervalo da vela anterior (filtragem de gaps).
O preço atual está pelo menos três unidades pip afastado de ambos os extremos (um proxy para o nível de stop do broker).
Calcular o spread atual usando o melhor bid/ask. Se não houver dados de nível 1, a estratégia recorre ao tamanho do pip.
Colocar duas ordens stop pendentes:
Buy Stop: ativação em máxima anterior + 2 × spread com stop loss abaixo do preço de entrada em StopLossPips e, se o trailing estiver desabilitado, take profit em máxima anterior + 2 × spread + TakeProfitPips.
Sell Stop: ativação em mínima anterior − spread com níveis de saída simétricos.
Assim que a vela se completa, ou ambas as ordens são preenchidas/canceladas, o processo se repete para a próxima barra.
Gerenciamento de posição
Enquanto uma posição está aberta, a estratégia monitora o melhor bid/ask em cada atualização do livro de ordens.
Se o trailing estiver desabilitado, a posição fecha quando o preço toca o stop ou take-profit fixo.
Se o trailing estiver habilitado:
Para operações compradas, o trailing stop é ativado assim que o preço avança TrailingStopPips. O stop é definido em bid − TrailingStopPips e se move cada vez que o preço melhora pelo menos TrailingStepPips.
Para operações vendidas, a lógica espelha o lado comprado usando o preço ask.
As saídas manuais reiniciam todos os níveis de proteção e mantêm qualquer ordem stop pendente do lado oposto ativa até que a vela termine, reproduzindo o comportamento straddle do EA.
Parâmetros
Nome
Padrão
Descrição
Volume
0.01
Volume da ordem em lotes (ou unidades de contrato para símbolos não FX).
StopLossPips
50
Distância entre a entrada e o stop de proteção, expressa em pips.
TakeProfitPips
150
Distância ao take-profit em pips, usada apenas quando o trailing está desabilitado.
UseTrailing
false
Habilita a lógica do trailing stop.
TrailingStopPips
50
Distância inicial para o trailing stop, medida em pips.
TrailingStepPips
25
Ganho mínimo (em pips) necessário para mover um trailing stop ativo.
CandleType
período de 15 minutos
Série de velas usada para detectar os níveis de rompimento.
Notas e recomendações
O tamanho do pip é derivado automaticamente de Security.PriceStep e emula o ajuste de dígitos MQL, por isso a estratégia se adapta a símbolos FX de 3 e 5 dígitos.
Todas as distâncias são recalculadas em unidades de preço antes de colocar ordens, o que mantém a estratégia compatível com ativos não FX, desde que o tamanho do tick esteja definido.
O fallback do nível de stop mínimo (três unidades pip) imita o comportamento do EA original quando o broker não reporta um nível de stop.
Como as ordens pendentes expiram no final de cada vela, você deve executar a estratégia no período desejado sem gaps no fluxo de velas recebido.
O gerenciamento de risco é crucial. Considere testar com spreads realistas e modelos de comissão antes de negociar com capital real.
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>
/// Breakout strategy: enters long when price breaks above previous candle high,
/// enters short when price breaks below previous candle low.
/// Uses ATR-based stop loss and take profit.
/// </summary>
public class TenPipsEurusdStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLossMult;
private readonly StrategyParam<decimal> _takeProfitMult;
private readonly StrategyParam<decimal> _trailingMult;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private decimal _entryPrice;
private decimal? _stopPrice;
private decimal? _takePrice;
private bool _hasPrev;
public decimal StopLossMult { get => _stopLossMult.Value; set => _stopLossMult.Value = value; }
public decimal TakeProfitMult { get => _takeProfitMult.Value; set => _takeProfitMult.Value = value; }
public decimal TrailingMult { get => _trailingMult.Value; set => _trailingMult.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TenPipsEurusdStrategy()
{
_stopLossMult = Param(nameof(StopLossMult), 1.0m)
.SetGreaterThanZero()
.SetDisplay("SL Mult", "Stop loss ATR multiplier", "Risk");
_takeProfitMult = Param(nameof(TakeProfitMult), 2.0m)
.SetGreaterThanZero()
.SetDisplay("TP Mult", "Take profit ATR multiplier", "Risk");
_trailingMult = Param(nameof(TrailingMult), 0.8m)
.SetGreaterThanZero()
.SetDisplay("Trail Mult", "Trailing stop ATR multiplier", "Risk");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR calculation length", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0;
_prevLow = 0;
_entryPrice = 0;
_stopPrice = null;
_takePrice = null;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atr)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_hasPrev = true;
return;
}
var close = candle.ClosePrice;
// Manage existing position
if (Position > 0)
{
// Trail
var trail = close - TrailingMult * atr;
if (_stopPrice == null || trail > _stopPrice)
_stopPrice = trail;
if (close <= _stopPrice || (_takePrice != null && close >= _takePrice))
{
SellMarket(Math.Abs(Position));
_stopPrice = null;
_takePrice = null;
_entryPrice = 0;
}
}
else if (Position < 0)
{
var trail = close + TrailingMult * atr;
if (_stopPrice == null || trail < _stopPrice)
_stopPrice = trail;
if (close >= _stopPrice || (_takePrice != null && close <= _takePrice))
{
BuyMarket(Math.Abs(Position));
_stopPrice = null;
_takePrice = null;
_entryPrice = 0;
}
}
// Entry on breakout
if (_hasPrev && Position == 0)
{
if (close > _prevHigh + atr * 0.5m)
{
BuyMarket();
_entryPrice = close;
_stopPrice = close - StopLossMult * atr;
_takePrice = close + TakeProfitMult * atr;
}
else if (close < _prevLow - atr * 0.5m)
{
SellMarket();
_entryPrice = close;
_stopPrice = close + StopLossMult * atr;
_takePrice = close - TakeProfitMult * atr;
}
}
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_hasPrev = true;
}
}
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
from StockSharp.Algo.Indicators import AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class ten_pips_eurusd_strategy(Strategy):
def __init__(self):
super(ten_pips_eurusd_strategy, self).__init__()
self._sl_mult = self.Param("StopLossMult", 1.0)
self._tp_mult = self.Param("TakeProfitMult", 2.0)
self._trail_mult = self.Param("TrailingMult", 0.8)
self._atr_period = self.Param("AtrPeriod", 14)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
self._stop_price = None
self._take_price = None
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(ten_pips_eurusd_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
self._stop_price = None
self._take_price = None
self._has_prev = False
def OnStarted2(self, time):
super(ten_pips_eurusd_strategy, self).OnStarted2(time)
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
self._stop_price = None
self._take_price = None
self._has_prev = False
atr = AverageTrueRange()
atr.Length = self._atr_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(atr, self.OnProcess).Start()
def OnProcess(self, candle, atr_val):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._has_prev = True
return
atr_v = float(atr_val)
close = float(candle.ClosePrice)
pos = float(self.Position)
if pos > 0:
trail = close - float(self._trail_mult.Value) * atr_v
if self._stop_price is None or trail > self._stop_price:
self._stop_price = trail
if close <= self._stop_price or (self._take_price is not None and close >= self._take_price):
self.SellMarket(abs(pos))
self._stop_price = None
self._take_price = None
self._entry_price = 0.0
elif pos < 0:
trail = close + float(self._trail_mult.Value) * atr_v
if self._stop_price is None or trail < self._stop_price:
self._stop_price = trail
if close >= self._stop_price or (self._take_price is not None and close <= self._take_price):
self.BuyMarket(abs(pos))
self._stop_price = None
self._take_price = None
self._entry_price = 0.0
pos = float(self.Position)
if self._has_prev and pos == 0:
if close > self._prev_high + atr_v * 0.5:
self.BuyMarket()
self._entry_price = close
self._stop_price = close - float(self._sl_mult.Value) * atr_v
self._take_price = close + float(self._tp_mult.Value) * atr_v
elif close < self._prev_low - atr_v * 0.5:
self.SellMarket()
self._entry_price = close
self._stop_price = close + float(self._sl_mult.Value) * atr_v
self._take_price = close - float(self._tp_mult.Value) * atr_v
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._has_prev = True
def CreateClone(self):
return ten_pips_eurusd_strategy()