Esta estrategia es una fiel versión StockSharp del asesor experto MetaTrader Combo_Right.mq4. Combina un filtro de impulso de índice de canal de productos básicos (CCI) con tres perceptrones que analizan el impulso del precio de apertura en pasos de barra configurables. Dependiendo de PassMode, los perceptrones pueden anular la señal CCI e indicar al supervisor que abra posiciones largas o cortas con sus parámetros de riesgo dedicados.
Lógica de trading
Suscríbase al tipo de vela configurado y calcule el CCI sobre los precios de apertura. La última vela completa proporciona tanto el precio de cierre como los valores de apertura históricos para las entradas del perceptrón.
Mantenga un búfer circular de precios de apertura para que los perceptrones puedan acceder a la apertura de las barras period, 2*period, 3*period y 4*period sin depender de los captadores del historial del indicador.
Cuando llegue una vela terminada:
Evalúe el valor CCI. Esto actúa como la señal predeterminada (> 0 = larga, < 0 = corta) con las distancias de protección base (TakeProfit1 / StopLoss1).
Dependiendo de PassMode, calcula uno o varios perceptrones. Cada perceptrón utiliza ponderaciones derivadas de las entradas originales MQL (X** - 100) y las diferencias entre el cierre más reciente y las aperturas históricas.
Si se cumple una condición del perceptrón, anula la señal predeterminada y asigna sus propias distancias de stop-loss/take-profit antes de enviar cualquier orden.
Cancele las órdenes de trabajo, aplane la exposición opuesta y abra la nueva posición usando el TradeVolume configurado. Después de enviar la orden de mercado, llame a SetTakeProfit y SetStopLoss con las compensaciones calculadas para que las órdenes de protección reflejen la rama activa del perceptrón.
Modos de pase
Pase 1: solo se considera el valor CCI. La señal es proporcional al último valor del indicador.
Pase 2: si el primer perceptrón (Perceptron1Period, X12…X42) produce un resultado negativo, la estrategia abre inmediatamente una operación corta con el segundo perfil de riesgo. De lo contrario, vuelve al resultado CCI.
Pase 3: si el segundo perceptrón es positivo, la estrategia abre una operación larga con el tercer perfil de riesgo. De lo contrario, se basa en la salida CCI.
Pase 4: primero verifique el tercer perceptrón. Un valor positivo requiere que el segundo perceptrón también sea positivo para permitir una entrada larga con el perfil de riesgo alcista. Si el tercer perceptrón es negativo y el primer perceptrón está por debajo de cero, el supervisor abre una posición corta con el perfil de riesgo bajista. Si ninguna de las ramas se activa, se utiliza la salida CCI.
En todos los modos, la estrategia ignora las señales hasta que se recolectan suficientes velas para alimentar el paso más profundo del perceptrón.
Gestión del riesgo
Cada entrada calcula nuevas compensaciones de precios basadas en el símbolo PriceStep. Si el instrumento no proporciona un paso, la distancia del punto bruto se utiliza tal cual. SetTakeProfit y SetStopLoss reciben las compensaciones deseadas junto con la posición neta resultante para que los soportes protectores permanezcan sincronizados con la exposición actual.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
TakeProfit1, StopLoss1
decimal
50 / 50
Distancias de pérdidas y ganancias (en puntos) cuando se utiliza la salida CCI.
CciPeriod
int
10
Período del CCI calculado sobre los precios de apertura.
X12, X22, X32, X42
int
100
Pesos brutos para el perceptrón bajista; la estrategia resta internamente 100 como en el código original.
TakeProfit2, StopLoss2
decimal
50 / 50
Distancias de riesgo (puntos) aplicadas cuando se activa el perceptrón bajista.
Perceptron1Period
int
20
Camina entre muestras para el perceptrón bajista (en barras).
X13, X23, X33, X43
int
100
Pesos brutos para el perceptrón alcista.
TakeProfit3, StopLoss3
decimal
50 / 50
Distancias de riesgo (puntos) aplicadas cuando se activa el perceptrón alcista.
Perceptron2Period
int
20
Paso entre muestras para el perceptrón alcista (en barras).
X14, X24, X34, X44
int
100
Pesos brutos para el perceptrón de confirmación utilizado en PassMode = 4.
Perceptron3Period
int
20
Camine entre muestras para el perceptrón de confirmación (en barras).
PassMode
int
1
Modo supervisor (1–4) que reproduce la lógica de ramificación del experto MQL.
TradeVolume
decimal
0,01
Volumen utilizado para nuevas entradas al mercado. La exposición opuesta se cierra antes de entrar.
CandleType
DataType
M1
Serie de velas que alimenta las entradas del CCI y del perceptrón.
Notas
La implementación espera intencionalmente hasta que todos los perceptrones tengan suficientes precios de apertura históricos antes de negociar, evitando problemas relacionados con la matriz que estaban implícitos en MetaTrader.
Los valores de los indicadores nunca se recuperan mediante acceso aleatorio. En cambio, el historial requerido se almacena en un buffer circular que cumple con las directrices del proyecto.
Todos los comentarios y la documentación se mantienen en inglés para cumplir con los requisitos del repositorio.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class ComboRightPerceptronStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldownRemaining;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ComboRightPerceptronStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 20).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 80).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 100).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevFast = fast;
_prevSlow = slow;
}
}