Ver en GitHub

Estrategia de Stop Porcentual y Toma de Ganancias

Esta estrategia utiliza dos medias móviles simples (SMA) para detectar la dirección de la tendencia. Cuando la SMA rápida cruza por encima de la SMA lenta, abre una posición larga. Cuando la SMA rápida cruza por debajo de la SMA lenta, abre una posición corta. Tras la entrada, la estrategia establece niveles de stop-loss y toma de ganancias como porcentajes del precio de entrada.

Detalles

  • Criterios de entrada:
    • Largo: La SMA rápida cruza por encima de la SMA lenta.
    • Corto: La SMA rápida cruza por debajo de la SMA lenta.
  • Criterios de salida:
    • Stop-loss y toma de ganancias basados en porcentajes del precio de entrada.
  • Stops: Sí, tanto stop-loss como toma de ganancias.
  • Indicadores: SMA.
  • Categoría: Seguimiento de tendencia.
  • Marco temporal: Cualquiera.
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>
/// Percent Stop TakeProfit strategy using EMA crossover.
/// </summary>
public class PercentStopTakeProfitStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public PercentStopTakeProfitStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}