A estratégia TenPips é um port do StockSharp do consultor especialista MetaTrader "10PIPS". Combina médias móvidas lineares ponderadas rápidas/lentas calculadas no período de negociação com uma confirmação de Momentum multi-período e um filtro MACD macro (mensal). A conversão espelha o módulo original de gestão de capital, incluindo proteção de ponto de equilíbrio, trailing baseado em pips e metas de lucro em capital/absolutos.
Lógica de sinais
Período primário (parâmetro CandleType, padrão 15 minutos) fornece o fluxo de preços usado para as LWMAs rápidas e lentas calculadas no preço típico (H + L + C) / 3.
Confirmação de Momentum em período superior (MomentumCandleType, padrão 1 hora) converte a diferença de Momentum do StockSharp na proporção do MetaTrader. A distância absoluta de 100 nas últimas três barras concluídas deve exceder MomentumThreshold para que um trade seja armado.
Filtro MACD macro (MacdCandleType, padrão velas de 30 dias aproximando o período mensal do MetaTrader) requer que a linha principal do MACD esteja acima da linha de sinal para compras e abaixo para vendas.
Uma posição longa é aberta quando a vela anterior:
fechou acima da LWMA rápida após mergulhar abaixo dela,
a LWMA rápida está acima da LWMA lenta,
qualquer uma das últimas três leituras de Momentum atende ao MomentumThreshold,
o MACD macro é de alta.
Uma posição curta usa as condições simétricas (fechamento anterior abaixo da LWMA rápida, rápida abaixo de lenta, Momentum acima do limiar, MACD de baixa).
Como o StockSharp opera com um modelo de posição líquida, o port abre no máximo uma posição agregada por lado. Enviar uma compra enquanto vendido fecha automaticamente a parte vendida e deixa o volume longo solicitado.
Gestão de risco e capital
Distâncias de proteção – StopLossPips e TakeProfitPips traduzem pips do MetaTrader em offsets de preço usando o PriceStep do instrumento. Quando qualquer limite é atingido, a estratégia fecha toda a posição com uma ordem de mercado.
Trailing stop – TrailingStopPips segue o preço mais alto (longo) ou mais baixo (curto) desde a entrada.
Ponto de equilíbrio – quando habilitado, BreakEvenTriggerPips arma o stop e o desloca para a entrada mais o opcional BreakEvenOffsetPips.
Metas monetárias – o trio UseMoneyTakeProfit, UsePercentTakeProfit e EnableMoneyTrailing replica o TP_In_Money, TP_In_Percent do EA e o bloqueio de trailing baseado em saldo. O PnL não realizado é medido a cada fechamento de vela.
Stop de capital – UseEquityStop com EquityRiskPercent implementa a proteção original UseEquityStop/TotalEquityRisk fechando posições quando o drawdown do pico de capital excede o limiar.
Flag de saída MACD – UseMacdExit espelha o interruptor Exit do EA, fechando posições antecipadamente quando o MACD macro vira contra o trade.
Parâmetros
Parâmetro
Padrão
Descrição
TradeVolume
0.01
Volume de posição líquida usado para ordens de mercado (equivalente ao tamanho de lote do MetaTrader).
CandleType
Período 15m
Período primário para as LWMAs rápidas/lentas e execução de trades.
MomentumCandleType
Período 1h
Velas de período superior alimentando a confirmação de Momentum.
MacdCandleType
Período 30d
Período macro (aproximação mensal) para confirmação MACD.
FastMaPeriod
8
Período da média móvel linear ponderada rápida.
SlowMaPeriod
50
Período da média móvel linear ponderada lenta.
MomentumPeriod
14
Lookback para a proporção de Momentum.
MomentumThreshold
0.3
Distância absoluta mínima de 100 (Momentum do MetaTrader) necessária nas últimas três barras do período superior.
StopLossPips
20
Stop-loss de proteção em pips do MetaTrader. Definir como zero para desabilitar.
TakeProfitPips
50
Take-profit de proteção em pips do MetaTrader. Definir como zero para desabilitar.
TrailingStopPips
40
Distância do trailing stop em pips (zero desabilita o trailing).
UseBreakEven
true
Habilita o comportamento de mover para ponto de equilíbrio.
BreakEvenTriggerPips
30
Lucro (pips) necessário antes da ativação do ponto de equilíbrio.
BreakEvenOffsetPips
30
Pips extras adicionados ao stop de ponto de equilíbrio após ativação.
UseMoneyTakeProfit
false
Fecha posições ao atingir a meta de lucro absoluto MoneyTakeProfit.
MoneyTakeProfit
10
Meta de lucro expressa em moeda de conta.
UsePercentTakeProfit
false
Fecha posições após ganhar PercentTakeProfit por cento do capital inicial.
PercentTakeProfit
10
Meta percentual baseada no capital inicial.
EnableMoneyTrailing
true
Habilitar trailing stop baseado em saldo usando MoneyTrailTarget / MoneyTrailStop.
MoneyTrailTarget
40
Lucro (moeda) necessário antes que o money trail seja armado.
MoneyTrailStop
10
Recuo permitido após armar o money trail.
UseEquityStop
true
Habilitar proteção de drawdown de capital.
EquityRiskPercent
1
Drawdown máximo do pico de capital antes de forçar posição neutra.
UseMacdExit
false
Fechar posições em sinal MACD oposto do período macro.
Notas de implementação
A conversão de pips segue a lógica do EA: se o tick size do corretor for 0.00001 ou 0.001, um pip equivale a dez ticks; caso contrário, o PriceStep bruto é usado.
O indicador de Momentum do StockSharp produz uma diferença de preço. A estratégia converte isso para a proporção do MetaTrader (Close / Close(period) * 100) antes de aplicar MomentumThreshold.
O port opera em um ambiente de netting e portanto não replica o martingale multi-ticket do EA (IncreaseFactor, LotExponent, Max_Trades). Em vez disso, ajusta o volume da ordem automaticamente ao alternar entre posições longas e curtas.
Saídas de proteção e gestão de lucros enviam ordens de mercado, correspondendo ao comportamento original do advisor ao modificar tickets abertos.
Os gráficos exibem os indicadores processados (LWMA rápida, LWMA lenta, Momentum, MACD) quando a visualização está disponível.
Uso
Configure os períodos de velas para corresponder ao gráfico do MetaTrader e ao período superior usado pelo EA.
Ajuste os parâmetros de risco baseados em pips ao tamanho de ponto do instrumento. Zero desabilita o componente correspondente.
Habilite ou desabilite metas monetárias/percentuais, stop de capital e saída MACD de acordo com suas preferências de risco.
Inicie a estratégia; ela assinará os três períodos de tempo necessários, gerenciará posições de acordo com as regras originais e registrará quaisquer saídas de proteção acionadas pelas proteções baseadas em saldo ou capital.
using System;
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;
public class TenPipsMomentumStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public TenPipsMomentumStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ten_pips_momentum_strategy(Strategy):
def __init__(self):
super(ten_pips_momentum_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(ten_pips_momentum_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(ten_pips_momentum_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return ten_pips_momentum_strategy()