A Estratégia de Exp Color PEMA Digit Tm Plus é um port direto do consultor especialista do MetaTrader 5 "Exp_ColorPEMA_Digit_Tm_Plus". A estratégia reconstrói o indicador original de Média Móvel Exponencial Quíntupla (PEMA) e reproduz cada flag de permissão de trading presente no EA. As ordens são executadas na série de velas selecionada somente após o indicador confirmar uma mudança de cor e o período de espera opcional (Signal Bar) ter decorrido.
A versão StockSharp mantém as mesmas opções de gestão monetária, controles de stop/alvo e saída baseada em tempo que existiam na implementação MQL. Cada configuração é exposta através de StrategyParam<T> para suportar configuração de UI e otimização.
Lógica do indicador
O indicador alimenta uma cascata de oito médias móveis exponenciais usando o PEMA Length e o Applied Price configurados.
A linha final é arredondada para os Rounding Digits solicitados, exatamente como no indicador original.
A inclinação da linha arredondada produz três estados:
Up (magenta) – pressão de alta, possível configuração comprada.
Flat (cinza) – neutro, sem ação.
Down (azul dodger) – pressão de baixa, possível configuração vendida.
A estratégia armazena o estado do indicador de cada vela concluída para poder referenciar barras mais antigas quando Signal Bar é maior que zero.
Regras de trading
Detecção de sinal – em uma vela concluída, avaliar o estado do indicador que tem Signal Bar velas de idade e compará-lo com o estado anterior.
Configuração comprada – quando o estado muda para Up de qualquer outra coisa:
enfileirar uma entrada comprada se Allow Long Entries está habilitado;
enfileirar uma saída de vendidos existentes se Allow Short Exits está habilitado.
Configuração vendida – quando o estado muda para Down de qualquer outra coisa:
enfileirar uma entrada vendida se Allow Short Entries está habilitado;
enfileirar uma saída de comprados existentes se Allow Long Exits está habilitado.
Camada de execução – as ações enfileiradas são executadas somente quando:
a estratégia está online e o trading está permitido;
o timestamp de ativação vinculado à vela fonte foi atingido; e
as regras de dimensionamento de posição permitem um volume não nulo.
Gestão de risco –
os níveis opcionais de stop-loss e take-profit são derivados do preço de execução usando as mesmas distâncias em pontos do MetaTrader;
Use Time Exit fecha posições que excedam o tempo de vida configurado em Holding Minutes;
os sinais opostos podem imediatamente zerar a exposição se a permissão de saída respectiva estiver ativa.
Parâmetros
Nome
Descrição
Money Management
Valor base usado pelas regras de dimensionamento de posição.
Money Mode
Escolhe entre dimensionamento baseado em lotes ou modelos de percentual de saldo/margem livre.
Stop Loss (points)
Distância ao stop loss em pontos de preço.
Take Profit (points)
Distância ao take profit em pontos de preço.
Allowed Deviation
Parâmetro de marcador preservado do EA por completude.
Allow Long Entries / Allow Short Entries
Habilitar ou desabilitar a abertura de operações em cada direção.
Allow Long Exits / Allow Short Exits
Habilitar ou desabilitar o fechamento de operações quando sinais opostos aparecem.
Use Time Exit
Ativa a lógica de zeragem baseada em tempo.
Holding Minutes
Tempo máximo de manutenção de uma posição, expresso em minutos.
Candle Type
Série de velas processada pela estratégia. Padrão H4.
PEMA Length
Comprimento usado para todos os oito estágios EMA na PEMA Quíntupla.
Applied Price
Preço fonte usado no cálculo do indicador.
Rounding Digits
Dígitos decimais usados para arredondar a saída do indicador.
Signal Bar
Número de barras concluídas a aguardar antes de avaliar um sinal.
Notas de uso
Colocar a estratégia dentro de um conector StockSharp que forneça acesso ao instrumento desejado e à série de velas.
Configurar os parâmetros para corresponder ao setup do MetaTrader que deseja replicar.
Executar backtests ou trading ao vivo conforme necessário; a estratégia reage apenas a velas completamente fechadas.
Status de conversão
Versão C# – implementada (CS/ExpColorPemaDigitTmPlusStrategy.cs).
Versão Python – não criada (conforme instrução).
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 ExpColorPemaDigitTmPlusStrategy : 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 ExpColorPemaDigitTmPlusStrategy()
{
_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 exp_color_pema_digit_tm_plus_strategy(Strategy):
def __init__(self):
super(exp_color_pema_digit_tm_plus_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(exp_color_pema_digit_tm_plus_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(exp_color_pema_digit_tm_plus_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 exp_color_pema_digit_tm_plus_strategy()