Ver en GitHub

Estrategia Big Runner

La estrategia Big Runner opera cuando el precio de cierre y una SMA rápida cruzan en la dirección de una SMA más lenta, indicando un fuerte momentum. El tamaño de la posición se deriva de un porcentaje del valor del portafolio multiplicado por el apalancamiento. Niveles opcionales de stop-loss y take-profit gestionan el riesgo.

Detalles

  • Criterios de entrada:
    • Comprar cuando el cierre cruza hacia arriba la SMA rápida y la SMA rápida cruza hacia arriba la SMA lenta.
    • Vender cuando el cierre cruza hacia abajo la SMA rápida y la SMA rápida cruza hacia abajo la SMA lenta.
  • Largo/Corto: Largo y corto.
  • Criterios de salida:
    • Stop-loss y take-profit opcionales basados en el precio de entrada.
    • La señal contraria cierra la posición existente.
  • Stops: Porcentajes de stop-loss y take-profit configurables.
  • Valores predeterminados:
    • FastLength = 5
    • SlowLength = 20
    • TakeProfitLongPercent = 4
    • TakeProfitShortPercent = 7
    • StopLossLongPercent = 2
    • StopLossShortPercent = 2
    • PercentOfPortfolio = 10
    • Leverage = 1
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Largo y Corto
    • Indicadores: SMA
    • Stops: Sí
    • Complejidad: Bajo
    • Marco temporal: Cualquiera
    • 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>
/// Big Runner Strategy - trades SMA crossover with stop loss and take profit.
/// </summary>
public class BigRunnerStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _stopLossPercent;
	private readonly StrategyParam<decimal> _takeProfitPercent;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
	public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BigRunnerStrategy()
	{
		_fastLength = Param(nameof(FastLength), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast SMA period", "SMA");

		_slowLength = Param(nameof(SlowLength), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow SMA period", "SMA");

		_stopLossPercent = Param(nameof(StopLossPercent), 2m)
			.SetGreaterThanZero()
			.SetDisplay("Stop Loss %", "Stop loss percent from entry", "Risk");

		_takeProfitPercent = Param(nameof(TakeProfitPercent), 4m)
			.SetGreaterThanZero()
			.SetDisplay("Take Profit %", "Take profit percent from entry", "Risk");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

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

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

		var fastMa = new SimpleMovingAverage { Length = FastLength };
		var slowMa = new SimpleMovingAverage { Length = SlowLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastMa, slowMa, ProcessCandle)
			.Start();

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

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

		if (_prevFast == 0m || _prevSlow == 0m)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		// Golden cross - buy
		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{
			BuyMarket();
			_entryPrice = candle.ClosePrice;
		}
		// Death cross - sell
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{
			SellMarket();
			_entryPrice = candle.ClosePrice;
		}

		// Stop loss / take profit for long
		if (Position > 0 && _entryPrice > 0)
		{
			var pnlPercent = (candle.ClosePrice - _entryPrice) / _entryPrice * 100m;
			if (pnlPercent <= -StopLossPercent || pnlPercent >= TakeProfitPercent)
			{
				SellMarket();
				_entryPrice = 0m;
			}
		}
		// Stop loss / take profit for short
		else if (Position < 0 && _entryPrice > 0)
		{
			var pnlPercent = (_entryPrice - candle.ClosePrice) / _entryPrice * 100m;
			if (pnlPercent <= -StopLossPercent || pnlPercent >= TakeProfitPercent)
			{
				BuyMarket();
				_entryPrice = 0m;
			}
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}