Ver en GitHub

Estrategia Swing Cyborg

Descripción general

Swing Cyborg es un asistente discrecional que automatiza la ejecución basándose en el pronóstico de tendencia del propio operador. El usuario define la dirección esperada de la tendencia y la ventana de tiempo durante la cual debe ser válida. La estrategia confirma las entradas con el indicador RSI y gestiona las salidas con objetivos fijos.

Parámetros

  • Volume – volumen de orden en lotes.
  • TrendPrediction – dirección esperada de la tendencia (Uptrend o Downtrend).
  • TrendTimeframe – marco temporal usado para RSI y trading (M30, H1 o H4).
  • TrendStart – inicio del período de tendencia definido por el usuario.
  • TrendEnd – fin del período de tendencia definido por el usuario.
  • Aggressiveness – preset de gestión de dinero:
    • Bajo: take profit 300 pips, stop loss 200 pips.
    • Medio: take profit 500 pips, stop loss 250 pips.
    • Alto: take profit 600 pips, stop loss 300 pips.

Lógica de trading

  1. Esperar una nueva vela en el marco temporal seleccionado.
  2. Operar solo si el tiempo actual está entre TrendStart y TrendEnd.
  3. Calcular RSI(14).
  4. Si no hay posición abierta:
    • Si TrendPrediction es Uptrend y RSI ≤ 65 → comprar.
    • Si TrendPrediction es Downtrend y RSI ≥ 35 → vender.
  5. StartProtection cierra automáticamente la posición cuando la ganancia o pérdida alcanza el nivel predefinido.

La estrategia opera sobre velas terminadas y no abre una nueva posición mientras haya una activa.

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>
/// SwingCyborg strategy using RSI overbought/oversold levels.
/// </summary>
public class SwingCyborgStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SwingCyborgStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Parameters");
		_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();
		_prevRsi = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		SubscribeCandles(CandleType)
			.Bind(rsi, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevRsi = rsiVal;
			_hasPrev = true;
			return;
		}

		// Buy when RSI exits oversold
		if (_prevRsi <= 30m && rsiVal > 30m && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		// Sell when RSI exits overbought
		else if (_prevRsi >= 70m && rsiVal < 70m && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevRsi = rsiVal;
	}
}