Mean Reversion Short Strategy Using RSI on NG Daily Charts.

Some financial instruments exhibit distinct market tendencies based on their inherent characteristics and trading behavior. For instance, the E-mini S&P 500 (ES) typically demonstrates a long side mean reversion tendency, meaning that after significant deviations from its average price, it tends to revert over an extended period. In contrast, Natural Gas (NG) has a short side mean reversion tendency, where price deviations correct themselves relatively quickly.

This strategy is a simple mean reversion short strategy applied to Natural Gas (NG), utilizing the Relative Strength Index (RSI) indicator as the primary trading signal. The core idea is to identify overbought conditions in the market where NG is likely to revert downward, and then execute short trades accordingly.

Strategy Overview

  • The strategy does not incorporate any additional filters or risk management layers; it is purely for educational purposes to illustrate the fundamental concept of mean reversion trading.

  • It demonstrates how to enter and exit trades based on the RSI indicator signals.

  • In addition to RSI-based exits, the strategy also includes an exit mechanism based on a predefined number of bars, ensuring that trades do not overstay in the market beyond a certain threshold.

This strategy serves as a basic framework for understanding mean reversion trading in NG and can be further refined by incorporating additional indicators, volatility filters, or risk management rules to enhance performance in real trading environments.

namespace CC.Strategies.ShortRSIMeanReversionStrategy;

using Tickblaze.Scripts.Indicators;

public class ShortRSIMeanReversionStrategy : Strategy
{
	[NumericRange(2, 10)]
	[Parameter("RSI Entry Period")]
	public int RsiEntryPeriod { get; set; } = 3;
	
	[NumericRange(2, 10)]
	[Parameter("RSI Exit Period")]
	public int RsiExitPeriod { get; set; } = 2;

	[NumericRange(60, 90)]
	[Parameter("RSI Entry Level")]
	public int RsiEntryValue { get; set; } = 90;

	[NumericRange(10, 40)]
	[Parameter("RSI Exit Level")]
	public int RsiExitValue { get; set; } = 30;

	[NumericRange(0, 20)]
	[Parameter("Exit - Number of bars")]
	public int ExitNumberOfBars { get; set; } = 5;
	
	[NumericRange(0, 1000)]
	[Parameter("Position size")]
	public int PositionSize { get; set; } = 1;

	private RelativeStrengthIndex _rsi_entry;
	private RelativeStrengthIndex _rsi_exit;
	private int _entryIndex;

	public ShortRSIMeanReversionStrategy()
	{
		Name = "Short RSI Mean Reversion Strategy";
		ShortName = "CC.SRSIMR";
		Description = "A mean reversion strategy based on the Relative Strength Index (RSI) generating a short signal when the RSI rises above the entry level and exiting when it falls below the exit level or after number of the bars.";
	}

	protected override void Initialize()
	{
		_rsi_entry = new RelativeStrengthIndex(Bars.Close, RsiEntryPeriod, MovingAverageType.Simple, 1);
		_rsi_exit = new RelativeStrengthIndex(Bars.Close, RsiExitPeriod, MovingAverageType.Simple, 1);
		_rsi_entry.Result.Color = Color.Blue;
		_rsi_exit.Result.Color = Color.Cyan;
		_rsi_entry.Average.IsVisible = false;
		_rsi_exit.Average.IsVisible = false;
		_rsi_entry.OverboughtLevel.Value = RsiEntryValue;
		_rsi_entry.OversoldLevel.Value = RsiExitValue;
		_rsi_exit.OverboughtLevel.Value = RsiEntryValue;
		_rsi_exit.OversoldLevel.Value = RsiExitValue;		
		_rsi_entry.ShowOnChart = true;
		_rsi_exit.ShowOnChart = true;
	}
	
	protected override void OnBar(int index)
	{
		if (index == 0)
		{
			return;
		}

		var rsi_entry = new[] { _rsi_entry.Result[index], _rsi_entry.Result[index - 1] };
		var rsi_exit = new[] { _rsi_exit.Result[index], _rsi_exit.Result[index - 1] };
		
		if (Position?.Direction is OrderDirection.Short && _entryIndex > 0)
		{
			_entryIndex--;
		}
		
		if (rsi_entry[1] <= RsiEntryValue && RsiEntryValue < rsi_entry[0])
		{
			EnterMarket(OrderDirection.Short, "Short RSI Mean Reversion");
		} else 
		if (rsi_exit[1] >= RsiExitValue && RsiExitValue > rsi_exit[0])
		{
			if (Position?.Direction is OrderDirection.Short)
			{
				ClosePosition("Exit RSI Mean Reversion");
				_entryIndex = 0;
			}
		} else 
		if (Position?.Direction is OrderDirection.Short && _entryIndex == 0)
		{
			ClosePosition("Exit RSI Mean Reversion Bars");
		}
	}

	private void EnterMarket(OrderDirection direction, string comment = "")
	{
		if (Position?.Direction == direction)
		{
			return;
		}
		
		_entryIndex = ExitNumberOfBars;

		var price = Bars.Close[^1];
		var action = direction is OrderDirection.Long ? OrderAction.Buy : OrderAction.SellShort;
		var exitMultiplier = direction is OrderDirection.Long ? 1 : -1;
		var quantity = PositionSize;
		var marketOrder = ExecuteMarketOrder(action, quantity, TimeInForce.Day, comment);
	}
}
NG_RSI_Short.zip
36.87KB
CC.Strategies.ShortRSIMeanReversionStrategy.zip
112.54KB
10
7 replies