Ver en GitHub

Estrategia DoubleUp2 CCI MACD

DoubleUp2 es una estrategia estilo martingala que combina el Commodity Channel Index (CCI) y el MACD. Abre posiciones cortas cuando ambos indicadores muestran valores positivos extremos y posiciones largas cuando ambos son extremadamente negativos. Después de una operación perdedora, el tamaño de la posición se duplica buscando recuperar las pérdidas anteriores. Las operaciones rentables se cierran una vez que el precio avanza un número fijo de puntos.

Detalles

  • Criterios de Entrada:
    • Largo: CCI < -Threshold y MACD < -Threshold.
    • Corto: CCI > Threshold y MACD > Threshold.
  • Largo/Corto: Ambos.
  • Criterios de Salida:
    • Señal opuesta o el precio se mueve ExitDistance puntos en ganancia.
  • Stops: Sin stop-loss explícito.
  • Valores predeterminados:
    • CCI Period = 8
    • MACD Fast = 13
    • MACD Slow = 33
    • MACD Signal = 2
    • Threshold = 230
    • Base Volume = 0.1
    • ExitDistance = 120 * price step
  • Filtros:
    • Categoría: Reversión a la media
    • Dirección: Ambos
    • Indicadores: CCI, MACD
    • Stops: No
    • Complejidad: Moderado
    • Marco temporal: Corto plazo
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Alto
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// DoubleUp2 strategy combining CCI and MACD with volume doubling (martingale).
/// </summary>
public class DoubleUp2Strategy : Strategy
{
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<decimal> _threshold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _entryPrice;
	private int _martingaleStep;

	/// <summary>
	/// CCI period.
	/// </summary>
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }

	/// <summary>
	/// MACD fast EMA period.
	/// </summary>
	public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }

	/// <summary>
	/// MACD slow EMA period.
	/// </summary>
	public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }

	/// <summary>
	/// Threshold for CCI and MACD signals.
	/// </summary>
	public decimal Threshold { get => _threshold.Value; set => _threshold.Value = value; }

	/// <summary>
	/// Candle type for calculations.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	/// <summary>
	/// Constructor.
	/// </summary>
	public DoubleUp2Strategy()
	{
		_cciPeriod = Param(nameof(CciPeriod), 8)
			.SetDisplay("CCI Period", "Averaging period for CCI", "Indicators")
			.SetOptimize(4, 20, 1);

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 13)
			.SetDisplay("MACD Fast", "Fast EMA period for MACD", "Indicators")
			.SetOptimize(5, 20, 1);

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 33)
			.SetDisplay("MACD Slow", "Slow EMA period for MACD", "Indicators")
			.SetOptimize(20, 50, 1);

		_threshold = Param(nameof(Threshold), 70m)
			.SetDisplay("Threshold", "RSI extreme level", "Strategy")
			.SetOptimize(55m, 85m, 5m);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles used for calculations", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_entryPrice = 0m;
		_martingaleStep = 0;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = CciPeriod };
		var macd = new MovingAverageConvergenceDivergence(
			new ExponentialMovingAverage { Length = MacdSlowPeriod },
			new ExponentialMovingAverage { Length = MacdFastPeriod });

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

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

	private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal macdValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var step = Security?.PriceStep ?? 1m;
		var lowThreshold = 100m - Threshold;

		// Short entry condition
		if (rsiValue > Threshold && macdValue > 0m)
		{
			if (Position > 0)
			{
				var profit = candle.ClosePrice - _entryPrice;
				_martingaleStep = profit > 0m ? 0 : _martingaleStep + 1;
			}

			SellMarket();
			_entryPrice = candle.ClosePrice;
			return;
		}

		// Long entry condition
		if (rsiValue < lowThreshold && macdValue < 0m)
		{
			if (Position < 0)
			{
				var profit = _entryPrice - candle.ClosePrice;
				_martingaleStep = profit > 0m ? 0 : _martingaleStep + 1;
			}

			BuyMarket();
			_entryPrice = candle.ClosePrice;
			return;
		}

		// Exit profitable long position
		if (Position > 0 && candle.ClosePrice - _entryPrice > 120m * step)
		{
			SellMarket();
			_martingaleStep += 2;
			return;
		}

		// Exit profitable short position
		if (Position < 0 && _entryPrice - candle.ClosePrice > 120m * step)
		{
			BuyMarket();
			_martingaleStep += 2;
		}
	}
}