Auf GitHub ansehen

AUD/USD Scalping Strategy

This strategy scalps AUD/USD on short timeframes using a combination of EMA trend filter, Bollinger Bands and RSI. The fast and slow EMAs define trend direction. Long trades are opened in uptrends when price touches the lower Bollinger Band and RSI is above the oversold threshold. Shorts are taken in downtrends when price reaches the upper band and RSI is below the overbought level. Fixed take profit and stop loss manage risk.

Details

  • Entry Criteria:
    • Long: Fast EMA above slow EMA, price at or below lower Bollinger Band, RSI above oversold level.
    • Short: Fast EMA below slow EMA, price at or above upper Bollinger Band, RSI below overbought level.
  • Long/Short: Both sides.
  • Exit Criteria: Stop loss or take profit.
  • Stops: Fixed stop loss and take profit.
  • Default Values:
    • EmaShort = 13
    • EmaLong = 26
    • RsiPeriod = 4
    • RsiOverbought = 70
    • RsiOversold = 30
    • BbLength = 20
    • BbMultiplier = 2.0
    • TakeProfit = 0.0005
    • StopLoss = 0.0004
  • Filters:
    • Category: Scalping
    • Direction: Both
    • Indicators: EMA, Bollinger Bands, RSI
    • Stops: Fixed
    • Complexity: Low
    • Timeframe: 1 minute
    • Seasonality: No
    • Neural networks: No
    • Divergence: No
    • Risk level: Medium
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>
/// Scalping strategy using EMA crossover with RSI filter.
/// Buys when fast EMA crosses above slow EMA and RSI exits oversold.
/// Sells when fast EMA crosses below slow EMA and RSI exits overbought.
/// </summary>
public class AudUsdScalpingStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaShort;
	private readonly StrategyParam<int> _emaLong;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _cooldownBars;

	private decimal _prevFastEma;
	private decimal _prevSlowEma;
	private int _barIndex;
	private int _lastTradeBar;

	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Fast EMA period.
	/// </summary>
	public int EmaShort
	{
		get => _emaShort.Value;
		set => _emaShort.Value = value;
	}

	/// <summary>
	/// Slow EMA period.
	/// </summary>
	public int EmaLong
	{
		get => _emaLong.Value;
		set => _emaLong.Value = value;
	}

	/// <summary>
	/// RSI calculation period.
	/// </summary>
	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	/// <summary>
	/// Cooldown bars between trades.
	/// </summary>
	public int CooldownBars
	{
		get => _cooldownBars.Value;
		set => _cooldownBars.Value = value;
	}

	/// <summary>
	/// Constructor.
	/// </summary>
	public AudUsdScalpingStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");

		_emaShort = Param(nameof(EmaShort), 13)
			.SetGreaterThanZero()
			.SetDisplay("Short EMA", "Fast EMA period", "Indicators");

		_emaLong = Param(nameof(EmaLong), 26)
			.SetGreaterThanZero()
			.SetDisplay("Long EMA", "Slow EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI calculation period", "Indicators");

		_cooldownBars = Param(nameof(CooldownBars), 350)
			.SetDisplay("Cooldown Bars", "Bars between trades", "Trading");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0;
		_prevSlowEma = 0;
		_barIndex = 0;
		_lastTradeBar = 0;
	}

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

		var emaFast = new ExponentialMovingAverage { Length = EmaShort };
		var emaSlow = new ExponentialMovingAverage { Length = EmaLong };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(emaFast, emaSlow, rsi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, emaFast);
			DrawIndicator(area, emaSlow);
			DrawOwnTrades(area);
		}
	}

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

		_barIndex++;

		var cooldownOk = _barIndex - _lastTradeBar > CooldownBars;

		// EMA crossover with RSI filter
		var crossUp = _prevFastEma > 0 && _prevFastEma <= _prevSlowEma && fastValue > slowValue;
		var crossDown = _prevFastEma > 0 && _prevFastEma >= _prevSlowEma && fastValue < slowValue;

		if (crossUp && rsiValue < 60 && Position <= 0 && cooldownOk)
		{
			BuyMarket();
			_lastTradeBar = _barIndex;
		}
		else if (crossDown && rsiValue > 40 && Position >= 0 && cooldownOk)
		{
			SellMarket();
			_lastTradeBar = _barIndex;
		}

		_prevFastEma = fastValue;
		_prevSlowEma = slowValue;
	}
}