Ver en GitHub

Estrategia de Marco Temporal

Estrategia de cruce de EMA con gestión de riesgo adaptada al marco temporal.

Las pruebas indican un retorno anual promedio de aproximadamente el 31%. Funciona mejor en el mercado de criptomonedas.

La estrategia compra cuando una EMA rápida cruza por encima de una EMA más lenta y la tendencia a largo plazo es alcista. Las entradas cortas ocurren en el cruce opuesto. Las horas de operación y un filtro ADX simple ayudan a evitar períodos de bajo momentum. El riesgo se gestiona con toma de ganancias y stop loss basados en porcentajes.

Detalles

  • Criterios de entrada:
    • Largo: EMA9 cruza por encima de EMA20 mientras EMA50 está por encima de EMA200.
    • Corto: EMA9 cruza por debajo de EMA20 mientras EMA50 está por debajo de EMA200.
  • Largo/Corto: Ambos lados.
  • Criterios de salida:
    • Largo: Stop loss o toma de ganancias.
    • Corto: Stop loss o toma de ganancias.
  • Stops: Sí, trailing opcional.
  • Valores predeterminados:
    • TakeProfitPercent = 1.5
    • StopLossPercent = 1.0
    • TrailingPercent = 0.5
    • StartHour = 15
    • EndHour = 20
    • CooldownBars = 5
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Ambos
    • Indicadores: EMA, RSI, ADX
    • Stops: Sí
    • Complejidad: Moderado
    • Marco temporal: Corto plazo
    • 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>
/// Timeframe strategy using EMA crossover.
/// </summary>
public class TimeframeStrategy : 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 TimeframeStrategy()
	{
		_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); }
	}
}