Ver en GitHub

Estrategia de Swing Trader Coensio

Estrategia de ruptura de líneas de tendencia definidas por el usuario. La estrategia calcula proyecciones lineales a partir de los parámetros de pendiente e intercepto tanto para las líneas alcistas como bajistas. Cuando el precio de cierre supera la línea de compra proyectada por un umbral, se abre una posición larga. Cuando el precio cae por debajo de la línea de venta menos el umbral, se entra en una posición corta.

Las posiciones están protegidas por valores de take profit y stop loss en ticks. Un stop trailing opcional actualiza el stop de protección conforme el precio se mueve a favor. Una opción adicional cierra la operación si la ruptura falla en la siguiente vela.

Detalles

  • Criterios de entrada:
    • Largo: Close > BuyLine + EntryThreshold
    • Corto: Close < SellLine - EntryThreshold
  • Largo/Corto: Ambos
  • Criterios de salida: Stop loss, take profit, stop trailing o señal opuesta
  • Stops:
    • Take profit en ticks
    • Stop loss en ticks
    • Stop trailing opcional en ticks
    • Cierre opcional por ruptura falsa en la siguiente vela
  • Valores predeterminados:
    • EntryThreshold = 15m
    • StopLossTicks = 50
    • TakeProfitTicks = 100
    • EnableTrailing = false
    • TrailingStepTicks = 5
    • FalseBreakClose = true
    • CandleType = TimeSpan.FromMinutes(5).TimeFrame()
    • BuyLineSlope = 0m
    • BuyLineIntercept = 0m
    • SellLineSlope = 0m
    • SellLineIntercept = 0m
  • Filtros:
    • Categoría: Ruptura de línea de tendencia
    • Dirección: Ambos
    • Indicadores: Ninguno
    • Stops: Sí
    • Complejidad: Medio
    • Marco temporal: Intradía
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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>
/// Swing trader using EMA crossover.
/// </summary>
public class CoensioSwingTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CoensioSwingTraderStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Trading");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Trading");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}