Ver en GitHub

Swing Cyborg Strategy

Overview

Swing Cyborg is a discretionary helper that automates execution based on a trader's own trend forecast. The user defines the expected trend direction and the time window when it should be valid. The strategy then confirms entries with the RSI indicator and manages exits with fixed targets.

Parameters

  • Volume – order volume in lots.
  • TrendPrediction – expected trend direction (Uptrend or Downtrend).
  • TrendTimeframe – timeframe used for RSI and trading (M30, H1 or H4).
  • TrendStart – beginning of the user defined trend period.
  • TrendEnd – end of the user defined trend period.
  • Aggressiveness – money management preset:
    • Low: take profit 300 pips, stop loss 200 pips.
    • Medium: take profit 500 pips, stop loss 250 pips.
    • High: take profit 600 pips, stop loss 300 pips.

Trading Logic

  1. Wait for a new candle on the selected timeframe.
  2. Trade only if current time is between TrendStart and TrendEnd.
  3. Calculate RSI(14).
  4. If there is no open position:
    • If TrendPrediction is Uptrend and RSI ≤ 65 → buy.
    • If TrendPrediction is Downtrend and RSI ≥ 35 → sell.
  5. StartProtection automatically closes the position when profit or loss reaches the predefined level.

The strategy operates on finished candles and does not open a new position while an existing one is active.

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;
	}
}