VWAP Mean Magnet v9 (Simple Alert) Strategy
This simplified version of the VWAP Mean Magnet strategy uses VWAP and RSI without volume filtering. Trades open when price deviates from VWAP and RSI reaches extreme levels. Positions are closed when price reverts back to VWAP.
Details
- Entry Criteria:
- Long: price < VWAP and RSI < oversold.
- Short: price > VWAP and RSI > overbought.
- Long/Short: Both.
- Exit Criteria:
- Close position when price returns to VWAP.
- Stops: Yes, percent stop-loss.
- Default Values:
VWAP length= 60RSI length= 14RSI overbought= 65RSI oversold= 25Stop loss %= 0.5
- Filters:
- Category: Mean reversion
- Direction: Both
- Indicators: Multiple
- Stops: Yes
- Complexity: Simple
- Timeframe: Intraday
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;
/// <summary>
/// VWAP mean reversion with RSI.
/// </summary>
public class VwapMeanMagnetV9SimpleAlertStrategy : Strategy
{
private readonly StrategyParam<int> _vwapLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _rsiOverbought;
private readonly StrategyParam<int> _rsiOversold;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
public int VwapLength { get => _vwapLength.Value; set => _vwapLength.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int RsiOverbought { get => _rsiOverbought.Value; set => _rsiOverbought.Value = value; }
public int RsiOversold { get => _rsiOversold.Value; set => _rsiOversold.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public VwapMeanMagnetV9SimpleAlertStrategy()
{
_vwapLength = Param(nameof(VwapLength), 20).SetDisplay("VWAP Length", "VWAP Length", "General");
_rsiLength = Param(nameof(RsiLength), 14).SetDisplay("RSI Length", "RSI Length", "General");
_rsiOverbought = Param(nameof(RsiOverbought), 65).SetDisplay("RSI Overbought", "RSI Overbought", "General");
_rsiOversold = Param(nameof(RsiOversold), 35).SetDisplay("RSI Oversold", "RSI Oversold", "General");
_stopLossPercent = Param(nameof(StopLossPercent), 0.5m).SetDisplay("Stop Loss %", "Stop Loss %", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame()).SetDisplay("Candle Type", "Candle Type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var vwap = new VolumeWeightedMovingAverage { Length = VwapLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(vwap, rsi, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, vwap);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal vwapValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (candle.ClosePrice < vwapValue && rsiValue < RsiOversold && Position <= 0)
BuyMarket();
else if (candle.ClosePrice > vwapValue && rsiValue > RsiOverbought && Position >= 0)
SellMarket();
if (Position > 0 && candle.ClosePrice >= vwapValue)
SellMarket();
else if (Position < 0 && candle.ClosePrice <= vwapValue)
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 RelativeStrengthIndex, VolumeWeightedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class vwap_mean_magnet_v9_simple_alert_strategy(Strategy):
def __init__(self):
super(vwap_mean_magnet_v9_simple_alert_strategy, self).__init__()
self._vwap_length = self.Param("VwapLength", 20) \
.SetDisplay("VWAP Length", "VWAP Length", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI Length", "General")
self._rsi_overbought = self.Param("RsiOverbought", 65) \
.SetDisplay("RSI Overbought", "RSI Overbought", "General")
self._rsi_oversold = self.Param("RsiOversold", 35) \
.SetDisplay("RSI Oversold", "RSI Oversold", "General")
self._stop_loss_percent = self.Param("StopLossPercent", 0.5) \
.SetDisplay("Stop Loss %", "Stop Loss %", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle Type", "General")
@property
def vwap_length(self):
return self._vwap_length.Value
@property
def rsi_length(self):
return self._rsi_length.Value
@property
def rsi_overbought(self):
return self._rsi_overbought.Value
@property
def rsi_oversold(self):
return self._rsi_oversold.Value
@property
def stop_loss_percent(self):
return self._stop_loss_percent.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(vwap_mean_magnet_v9_simple_alert_strategy, self).OnStarted2(time)
vwap = VolumeWeightedMovingAverage()
vwap.Length = self.vwap_length
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(vwap, rsi, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, vwap)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def on_process(self, candle, vwap_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if candle.ClosePrice < vwap_value and rsi_value < self.rsi_oversold and self.Position <= 0:
self.BuyMarket()
elif candle.ClosePrice > vwap_value and rsi_value > self.rsi_overbought and self.Position >= 0:
self.SellMarket()
if self.Position > 0 and candle.ClosePrice >= vwap_value:
self.SellMarket()
elif self.Position < 0 and candle.ClosePrice <= vwap_value:
self.BuyMarket()
def CreateClone(self):
return vwap_mean_magnet_v9_simple_alert_strategy()