Ver en GitHub

Estrategia BuySell

Esta estrategia emula el experto BuySell de MetaTrader. Combina una media móvil con el Average True Range (ATR) para detectar reversiones de tendencia. Cuando la media móvil se orienta hacia arriba, el sistema considera el mercado alcista; cuando se orienta hacia abajo, lo considera bajista. Una operación se abre solo si la vela anterior estaba en el estado contrario, confirmando una reversión. Los niveles opcionales de stop-loss y take-profit se expresan en puntos de precio.

Detalles

  • Lógica de entrada
    • Largo: la media móvil pasa de caer a subir y la vela anterior era bajista.
    • Corto: la media móvil pasa de subir a caer y la vela anterior era alcista.
  • Lógica de salida
    • Largo: la media móvil se gira a la baja o se activa el stop-loss / take-profit.
    • Corto: la media móvil se gira al alza o se activa el stop-loss / take-profit.
  • Indicadores: Media Móvil Simple (SMA) y ATR.
  • Stops: Stop-loss y take-profit en puntos.
  • Permisos: indicadores separados permiten o prohíben abrir/cerrar posiciones largas y cortas.
  • Marco temporal predeterminado: velas de 4 horas.

Parámetros

Nombre Predeterminado Descripción
MaPeriod 14 Período de la media móvil.
AtrPeriod 60 Período del ATR.
StopLoss 1000 Stop-loss en puntos de precio.
TakeProfit 2000 Take-profit en puntos de precio.
AllowLongEntry true Permiso para abrir posiciones largas.
AllowShortEntry true Permiso para abrir posiciones cortas.
AllowLongExit true Permiso para cerrar posiciones largas.
AllowShortExit true Permiso para cerrar posiciones cortas.
CandleType H4 Marco temporal utilizado para los cálculos.

Uso

  1. Añade la estrategia a tu solución StockSharp.
  2. Configura los parámetros según sea necesario.
  3. Ejecuta la estrategia en modo en vivo o de backtesting. Las operaciones se ejecutan mediante órdenes BuyMarket y SellMarket.

El enfoque es adecuado para mercados donde las reversiones de tendencia van acompañadas de cambios de volatilidad capturados por el ATR.

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>
/// Buy/Sell strategy based on EMA crossover.
/// </summary>
public class BuySellStrategy : 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 BuySellStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 28)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_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;
	}
}