Ver en GitHub

Estrategia ComFracti

Descripción general

ComFracti es una estrategia direccional traducida del asesor experto MT4 "ComFracti". La lógica combina la confirmación fractal de múltiples marcos temporales con RSI y filtros estocásticos, mientras que los filtros opcionales de promedio móvil, parabólico SAR, canal y perceptrón controlan la alineación de tendencias. La implementación de C# comercializa una sola posición a la vez y evalúa señales en velas completadas utilizando StockSharp API de alto nivel.

Lógica de trading

  • Señal primaria
    • Confirma una configuración alcista cuando tanto el marco temporal actual como el marco temporal superior producen una señal fractal alcista.
    • Confirma una configuración bajista cuando ambos marcos temporales producen una señal fractal bajista.
    • RSI (3 períodos predeterminados en el período de tiempo superior) debe ubicarse por debajo de 50 - RsiLevelBuy para posiciones largas o por encima de 50 + RsiLevelSell para posiciones cortas cuando el filtro RSI está habilitado.
    • El oscilador estocástico (%K período 5 predeterminado con %D suavizado 3/3) debe estar por debajo de 50 - StochasticLevelBuy para posiciones largas o por encima de 50 + StochasticLevelSell para posiciones cortas cuando el filtro estocástico está habilitado.
  • Filtros opcionales
    • EMA pendiente: el EMA en el período de tiempo del filtro debe aumentar para las posiciones largas y disminuir para las posiciones cortas.
    • Parabolic SAR: el valor SAR debe permanecer por debajo de la barra abierta para largos o por encima para cortos.
    • Desglose del canal: compara la barra anterior con un canal adaptable de estilo Donchian; Los mínimos anteriores deben permanecer por encima del piso del canal para las posiciones largas, mientras que los máximos anteriores deben permanecer por debajo del techo para las posiciones cortas.
    • Perceptrón: una suma ponderada de las diferencias recientes entre máximos y mínimos debe ser positiva para las posiciones largas y negativa para las posiciones cortas.
  • Gestión de posiciones
    • Sólo hay una posición activa a la vez; la estrategia cierra la exposición existente antes de abrir una nueva operación en la dirección opuesta.
    • Las distancias fijas de stop-loss y take-profit se expresan en puntos del instrumento.
    • Un trailing stop opcional se mueve en dirección a las ganancias una vez que se alcanza el buffer de seguimiento (cuando ProfitTrailing es verdadero).
    • Cuando CloseOnOppositeSignal está habilitado, la estrategia sale temprano si aparece la señal principal opuesta.

Gestión del riesgo

  • El tamaño de la posición base es igual al parámetro BaseVolume (lotes 0,1 predeterminados). Cuando AccountMicro está habilitado, el volumen se divide por diez.
  • Si UseMoneyManagement está habilitado, la estrategia arriesga RiskPercent del valor de la cuenta por operación, utilizando la distancia de stop-loss configurada y el valor del paso del instrumento para aproximar el tamaño de la posición. El volumen calculado está bloqueado por MinimumVolume.

Parámetros

Nombre Descripción
TakeProfitPoints, StopLossPoints Distancias de toma de ganancias y stop-loss en puntos del instrumento.
UseTrailingStop, TrailingStopPoints, ProfitTrailing Controles de trailing stop (distancia y si el trailing requiere ganancias abiertas).
BaseVolume, UseMoneyManagement, RiskPercent, AccountMicro, MinimumVolume Configuración del tamaño de posición.
UseFractals, FractalShift* Habilita la confirmación fractal y define los desplazamientos de barras para inspeccionar en los marcos de tiempo actuales y superiores.
UseRsi, RsiLevelBuy, RsiLevelSell, RsiType RSI filtra compensaciones y períodos de tiempo.
UseStochastic, StochasticPeriod*, StochasticLevel* Stochastic períodos y umbrales del oscilador.
UseMaFilter, MaPeriod EMA configuración del filtro en el período de tiempo del filtro.
UsePsarFilter, PsarStep Parabolic SAR configuración del filtro.
UseChannelFilter, ChannelLookback, ChannelK Parámetros del filtro de ruptura de canal.
UsePerceptronFilter, PerceptronV1PerceptronV4 Pesos de filtro de perceptrón (0–100, centrado alrededor de 50).
CandleType, HigherFractalType, FilterType Plazos de datos utilizados por la estrategia.

Notas

  • La estrategia procesa únicamente velas terminadas, por lo que el comportamiento puede diferir ligeramente del asesor experto original impulsado por ticks.
  • El rastreador de fractales reproduce la lógica fractal de cinco barras MT4 y permite al usuario cambiar qué barra histórica se evalúa, coincidiendo con los parámetros MT4 sh1/ sh2.
  • La gestión del dinero se basa en la valoración de la cartera disponible dentro de StockSharp; cuando no hay valoración disponible, la estrategia vuelve al volumen base fijo.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// ComFracti: Fractal detection with RSI confirmation and ATR stops.
/// </summary>
public class ComFractiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _entryPrice;
	private decimal _h1, _h2, _h3, _h4, _h5;
	private decimal _l1, _l2, _l3, _l4, _l5;
	private int _barCount;

	public ComFractiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");

		_emaLength = Param(nameof(EmaLength), 50)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_entryPrice = 0;
		_barCount = 0;
		_h1 = _h2 = _h3 = _h4 = _h5 = 0;
		_l1 = _l2 = _l3 = _l4 = _l5 = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_entryPrice = 0;
		_barCount = 0;
		_h1 = _h2 = _h3 = _h4 = _h5 = 0;
		_l1 = _l2 = _l3 = _l4 = _l5 = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, ema, atr, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_h5 = _h4; _h4 = _h3; _h3 = _h2; _h2 = _h1;
		_h1 = candle.HighPrice;
		_l5 = _l4; _l4 = _l3; _l3 = _l2; _l2 = _l1;
		_l1 = candle.LowPrice;
		_barCount++;

		if (_barCount < 5 || atrVal <= 0)
			return;

		var close = candle.ClosePrice;

		var fractalUp = _h3 > _h1 && _h3 > _h2 && _h3 > _h4 && _h3 > _h5;
		var fractalDown = _l3 < _l1 && _l3 < _l2 && _l3 < _l4 && _l3 < _l5;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 3m || close <= _entryPrice - atrVal * 2m || (fractalUp && rsiVal > 65))
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 3m || close >= _entryPrice + atrVal * 2m || (fractalDown && rsiVal < 35))
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		if (Position == 0)
		{
			if (fractalDown && rsiVal < 55)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (fractalUp && rsiVal > 45)
			{
				_entryPrice = close;
				SellMarket();
			}
		}
	}
}