La Estrategia de Exp Color PEMA Digit Tm Plus es un port directo del asesor experto de MetaTrader 5 "Exp_ColorPEMA_Digit_Tm_Plus". La estrategia reconstruye el indicador original de Media Móvil Exponencial Quíntuple (PEMA) y reproduce cada flag de permiso de trading presente en el EA. Las órdenes se ejecutan en la serie de velas seleccionada solo después de que el indicador confirma un cambio de color y ha transcurrido el período de espera opcional (Signal Bar).
La versión de StockSharp mantiene las mismas opciones de gestión monetaria, controles de stop/objetivo y salida basada en tiempo que existían en la implementación MQL. Cada configuración se expone a través de StrategyParam<T> para soportar la configuración de UI y la optimización.
Lógica del indicador
El indicador alimenta una cascada de ocho medias móviles exponenciales usando la PEMA Length y el Applied Price configurados.
La línea final se redondea a los Rounding Digits solicitados, exactamente como en el indicador original.
La pendiente de la línea redondeada produce tres estados:
Up (magenta) – presión alcista, posible configuración larga.
Flat (gris) – neutral, sin acción.
Down (azul dodger) – presión bajista, posible configuración corta.
La estrategia almacena el estado del indicador de cada vela completada para poder referenciar barras más antiguas cuando Signal Bar es mayor que cero.
Reglas de trading
Detección de señal – en una vela completada, evaluar el estado del indicador que tiene Signal Bar velas de antigüedad y compararlo con el estado anterior.
Configuración larga – cuando el estado pasa a Up desde cualquier otra cosa:
encolar una entrada larga si Allow Long Entries está habilitado;
encolar una salida de cortos existentes si Allow Short Exits está habilitado.
Configuración corta – cuando el estado pasa a Down desde cualquier otra cosa:
encolar una entrada corta si Allow Short Entries está habilitado;
encolar una salida de largos existentes si Allow Long Exits está habilitado.
Capa de ejecución – las acciones en cola se ejecutan solo cuando:
la estrategia está en línea y el trading está permitido;
se ha alcanzado el timestamp de activación vinculado a la vela fuente; y
las reglas de dimensionamiento de posición permiten un volumen no nulo.
Gestión de riesgo –
los niveles opcionales de stop-loss y take-profit se derivan del precio de llenado usando las mismas distancias en puntos que en MetaTrader;
Use Time Exit cierra posiciones que excedan el tiempo de vida configurado en Holding Minutes;
las señales opuestas pueden aplanar inmediatamente la exposición si el permiso de salida respectivo está activo.
Parámetros
Nombre
Descripción
Money Management
Valor base usado por las reglas de dimensionamiento de posición.
Money Mode
Elige entre dimensionamiento basado en lotes o modelos de porcentaje de saldo/margen libre.
Stop Loss (points)
Distancia al stop loss en puntos de precio.
Take Profit (points)
Distancia al take profit en puntos de precio.
Allowed Deviation
Parámetro de marcador de posición preservado del EA por completitud.
Allow Long Entries / Allow Short Entries
Habilitar o deshabilitar la apertura de operaciones en cada dirección.
Allow Long Exits / Allow Short Exits
Habilitar o deshabilitar el cierre de operaciones cuando aparecen señales opuestas.
Use Time Exit
Activa la lógica de aplanamiento basada en tiempo.
Holding Minutes
Tiempo máximo de tenencia de una posición, expresado en minutos.
Candle Type
Serie de velas procesada por la estrategia. Por defecto H4.
PEMA Length
Longitud usada para las ocho etapas EMA en la PEMA Quíntuple.
Applied Price
Precio fuente usado en el cálculo del indicador.
Rounding Digits
Dígitos decimales usados para redondear la salida del indicador.
Signal Bar
Número de barras completadas a esperar antes de evaluar una señal.
Notas de uso
Colocar la estrategia dentro de un conector StockSharp que proporcione acceso al instrumento deseado y la serie de velas.
Configurar los parámetros para que coincidan con la configuración de MetaTrader que desea replicar.
Ejecutar backtests o trading en vivo según sea necesario; la estrategia solo reacciona a velas completamente cerradas.
Estado de conversión
Versión C# – implementada (CS/ExpColorPemaDigitTmPlusStrategy.cs).
Versión Python – no creada (según instrucción).
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()