Ver en GitHub

Estrategia Lossless MA

Esta estrategia opera cruzamientos entre una Media Móvil Simple (SMA) rápida y una lenta. Opcionalmente evita realizar pérdidas moviendo las posiciones perdedoras al punto de equilibrio cuando aparece la señal opuesta.

Cómo Funciona

  1. Indicadores
    • SMA rápida
    • SMA lenta
  2. Entradas
    • Largo cuando SMA rápida > SMA lenta y la dirección actual no es larga.
    • Corto cuando SMA rápida < SMA lenta y la dirección actual no es corta.
    • Se permiten entradas adicionales si Close Losses está deshabilitado y el número de operaciones abiertas está por debajo de Max Deals.
  3. Salidas
    • En un cruzamiento opuesto.
    • Si Close Losses está habilitado, la posición se cierra inmediatamente.
    • Si Close Losses está deshabilitado y la operación está en pérdida, se coloca una orden limitada al precio de entrada para salir en el punto de equilibrio.

Parámetros

Nombre Descripción Predeterminado
FastLength Período de la SMA rápida. 10
SlowLength Período de la SMA lenta. 30
MaxDeals Número máximo de operaciones simultáneas. 5
CloseLosses Cerrar operaciones con pérdidas inmediatamente. true
Volume Volumen de la orden. 1
CandleType Velas para los cálculos. 1-minute

Notas

La estrategia utiliza órdenes de mercado para entradas y salidas. Cuando CloseLosses está deshabilitado, intenta proteger las posiciones colocando una orden limitada al precio de entrada en lugar de cerrar con pérdida.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Lossless Moving Average strategy.
/// Trades fast and slow SMA crossovers.
/// </summary>
public class LosslessMaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevFast;
	private decimal? _prevSlow;

	/// <summary>
	/// Fast SMA period.
	/// </summary>
	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }

	/// <summary>
	/// Slow SMA period.
	/// </summary>
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }

	/// <summary>
	/// Type of candles used for calculations.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	/// <summary>
	/// Constructor.
	/// </summary>
	public LosslessMaStrategy()
	{
		_fastLength = Param(nameof(FastLength), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast MA", "Fast SMA length", "Parameters");

		_slowLength = Param(nameof(SlowLength), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow MA", "Slow SMA length", "Parameters");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candles for strategy", "General");
	}

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

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

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

		var fastMa = new ExponentialMovingAverage { Length = FastLength };
		var slowMa = new ExponentialMovingAverage { 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 (!IsFormedAndOnlineAndAllowTrading())
			return;

		var prevFast = _prevFast;
		var prevSlow = _prevSlow;

		_prevFast = fastValue;
		_prevSlow = slowValue;

		if (prevFast is null || prevSlow is null)
			return;

		// Bullish crossover
		if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}

		// Bearish crossover
		if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}