Mean Reversion Pro Strategy
Mean Reversion Pro is a mean reversion system built for major indices. It uses two moving averages and intrabar range levels to detect pullbacks. Long trades are preferred as indices tend to move upward.
Details
- Entry Criteria:
- Long: Close below fast SMA, close below 20% range level, close above slow SMA, no position.
- Short: Close above fast SMA, close above 80% range level, close below slow SMA, no position.
- Long/Short: Both (long recommended).
- Exit Criteria:
- Long: Close crosses above fast SMA.
- Short: Close crosses below fast SMA.
- Stops: None.
- Default Values:
Fast SMA= 5Slow SMA= 100Direction= Long only
- Filters:
- Category: Mean reversion
- Direction: Configurable
- Indicators: SMA
- Stops: None
- Complexity: Simple
- Timeframe: Daily
using System;
using System.Linq;
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;
public class MeanReversionProStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _fastSma;
private SimpleMovingAverage _slowSma;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MeanReversionProStrategy()
{
_fastLength = Param(nameof(FastLength), 5);
_slowLength = Param(nameof(SlowLength), 50);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastSma = new SimpleMovingAverage { Length = FastLength };
_slowSma = new SimpleMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_fastSma, _slowSma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_fastSma.IsFormed || !_slowSma.IsFormed)
return;
var range = candle.HighPrice - candle.LowPrice;
var longThreshold = candle.LowPrice + 0.2m * range;
var shortThreshold = candle.HighPrice - 0.2m * range;
var longSignal = candle.ClosePrice < fast &&
candle.ClosePrice < longThreshold &&
candle.ClosePrice > slow;
var shortSignal = candle.ClosePrice > fast &&
candle.ClosePrice > shortThreshold &&
candle.ClosePrice < slow;
var exitLong = candle.ClosePrice > fast && Position > 0;
var exitShort = candle.ClosePrice < fast && Position < 0;
if (longSignal && Position <= 0)
BuyMarket();
else if (shortSignal && Position >= 0)
SellMarket();
else if (exitLong)
SellMarket();
else if (exitShort)
BuyMarket();
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class mean_reversion_pro_strategy(Strategy):
"""
Mean Reversion Pro: fast/slow SMA with candle range threshold.
"""
def __init__(self):
super(mean_reversion_pro_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 5).SetDisplay("Fast", "Fast SMA", "Indicators")
self._slow_length = self.Param("SlowLength", 50).SetDisplay("Slow", "Slow SMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candles", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(mean_reversion_pro_strategy, self).OnReseted()
def OnStarted2(self, time):
super(mean_reversion_pro_strategy, self).OnStarted2(time)
self._fast_sma = SimpleMovingAverage()
self._fast_sma.Length = self._fast_length.Value
self._slow_sma = SimpleMovingAverage()
self._slow_sma.Length = self._slow_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_sma, self._slow_sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._fast_sma)
self.DrawIndicator(area, self._slow_sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if not self._fast_sma.IsFormed or not self._slow_sma.IsFormed:
return
fast = float(fast_val)
slow = float(slow_val)
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
rng = high - low
long_threshold = low + 0.2 * rng
short_threshold = high - 0.2 * rng
long_signal = close < fast and close < long_threshold and close > slow
short_signal = close > fast and close > short_threshold and close < slow
exit_long = close > fast and self.Position > 0
exit_short = close < fast and self.Position < 0
if long_signal and self.Position <= 0:
self.BuyMarket()
elif short_signal and self.Position >= 0:
self.SellMarket()
elif exit_long:
self.SellMarket()
elif exit_short:
self.BuyMarket()
def CreateClone(self):
return mean_reversion_pro_strategy()