La estrategia replica la lógica del asesor experto Caudate X Period Candle TM Plus. Suaviza los precios de apertura, máximo, mínimo y cierre de la vela con una media móvil configurable, construye un rango estilo Donchian y clasifica cada vela finalizada en uno de seis códigos de color dependiendo de la posición del cuerpo dentro del rango. Las entradas largas se activan por los colores de cola inferior alcista (0 o 1), mientras que las entradas cortas se activan por los colores de cola superior bajista (5 o 6). Los grupos de colores opuestos se usan para salir de posiciones existentes.
Reglas de Trading
Suscribirse a la serie de velas seleccionada y suavizar cada componente con la media móvil elegida.
Calcular el máximo más alto y el mínimo más bajo de los máximos y mínimos suavizados durante el Donchian Period especificado, luego expandir el rango para que siempre contenga la apertura y el cierre suavizados.
Determinar el color de la vela:
Colores 0/1 – cuerpo cerca de la parte superior del rango (cola inferior).
Colores 2/4 – cuerpo centrado dentro del rango.
Colores 5/6 – cuerpo cerca de la parte inferior del rango (cola superior).
Evaluar el color de la barra desplazada por Signal Bar (el valor predeterminado 1 usa la vela completada anterior).
Abrir posiciones cuando el color pertenece al grupo de entrada y la posición opuesta no está activa.
Cerrar posiciones cuando el color pertenece al grupo de salida o cuando expira el tiempo máximo de retención.
Los offsets opcionales de stop-loss y take-profit se establecen a través del módulo de protección incorporado.
Parámetros
Parámetro
Descripción
Candle Type
Marco temporal usado para los cálculos de señal.
Donchian Period
Número de velas para el rango suavizado de máximo/mínimo.
Signal Bar
Número de barras para retrasar la evaluación de señal (0 = barra actual).
Smoothing Method
Media móvil aplicada a los precios OHLC (SMA, EMA, SMMA, LWMA, aproximación Jurik JJMA, Kaufman AMA).
MA Length
Longitud del filtro de suavizado.
MA Phase
Reservado para compatibilidad JJMA (no usado por las medias de StockSharp).
Enable Long/Short Entries
Activar la apertura de nuevas posiciones largas o cortas.
Enable Long/Short Exits
Activar el cierre de posiciones largas o cortas existentes en señales.
Enable Time Exit
Habilitar el filtro de tiempo máximo de retención.
Time Exit (minutes)
Duración de retención antes de un cierre forzado.
Stop Loss (points)
Distancia de stop-loss en pasos de precio (multiplicado por Security.PriceStep).
Take Profit (points)
Distancia de take-profit en pasos de precio.
Notas
Signal Bar = 1 coincide con el comportamiento del experto MQL5 actuando en la última vela completamente cerrada.
Cuando las distancias de stop o objetivo son mayores que cero, la estrategia llama a StartProtection con offsets absolutos basados en el paso de precio del instrumento.
MA Phase se mantiene por compatibilidad pero no es consumido por las implementaciones de media móvil de StockSharp.
Establecer el tamaño base de la orden a través de la propiedad Strategy.Volume heredada; la implementación siempre cierra posiciones opuestas antes de abrir una nueva.
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;
/// <summary>
/// Caudate X Period Candle TM Plus strategy (simplified). Detects candle body/tail
/// patterns using ATR-based filtering and EMA trend direction.
/// </summary>
public class CaudateXPeriodCandleTmPlusStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<int> _emaLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public CaudateXPeriodCandleTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_atrLength = Param(nameof(AtrLength), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Length", "ATR period", "Indicators");
_emaLength = Param(nameof(EmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "Trend EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var atr = new AverageTrueRange { Length = AtrLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ema, (ICandleMessage candle, decimal atrValue, decimal emaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (atrValue <= 0)
return;
var close = candle.ClosePrice;
var body = Math.Abs(close - candle.OpenPrice);
// Strong body candle in the trend direction.
if (body > atrValue * 0.75m)
{
if (close > candle.OpenPrice && close > emaValue && Position <= 0)
BuyMarket();
else if (close < candle.OpenPrice && close < emaValue && Position >= 0)
SellMarket();
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
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, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class caudate_x_period_candle_tm_plus_strategy(Strategy):
def __init__(self):
super(caudate_x_period_candle_tm_plus_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period", "Indicators")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend EMA period", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def AtrLength(self):
return self._atr_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
def OnStarted2(self, time):
super(caudate_x_period_candle_tm_plus_strategy, self).OnStarted2(time)
atr = AverageTrueRange()
atr.Length = self.AtrLength
ema = ExponentialMovingAverage()
ema.Length = self.EmaLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, atr_value, ema_value):
if candle.State != CandleStates.Finished:
return
av = float(atr_value)
if av <= 0:
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
ev = float(ema_value)
body = abs(close - open_p)
if body > av * 0.75:
if close > open_p and close > ev and self.Position <= 0:
self.BuyMarket()
elif close < open_p and close < ev and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return caudate_x_period_candle_tm_plus_strategy()