This strategy combines the Stochastic oscillator with Williams %R to detect extreme market conditions.
A long position is opened when the Stochastic value drops below 0.1 and Williams %R is under -90, signaling deep oversold pressure.
A short position is opened when the Stochastic rises above 99.9 and Williams %R exceeds -5, indicating strong overbought conditions.
The strategy works on any instrument and timeframe supported by the selected candle type. It can trade both long and short positions and offers an optional percentage stop loss for risk management.
Details
Entry Criteria:
Long: Stochastic < 0.1 and Williams %R < -90.
Short: Stochastic > 99.9 and Williams %R > -5.
Long/Short: Both.
Exit Criteria: Opposite signal or triggered stop loss.
Stops: Optional percentage-based stop loss.
Indicators:
Stochastic oscillator (default period 26).
Williams %R (default period 26).
Parameters
StochPeriod – Stochastic calculation period.
WprPeriod – Williams %R calculation period.
StopLossPercent – Percent-based stop loss size.
CandleType – Candle type used for indicator calculations.
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>
/// Strategy using RSI and Williams %R for oversold/overbought entries.
/// </summary>
public class AveragedStochWprStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _wprPeriod;
private readonly StrategyParam<DataType> _candleType;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int WprPeriod { get => _wprPeriod.Value; set => _wprPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AveragedStochWprStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_wprPeriod = Param(nameof(WprPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("WPR Period", "Williams %R period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var wpr = new WilliamsR { Length = WprPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, wpr, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal wpr)
{
if (candle.State != CandleStates.Finished)
return;
// Buy: RSI oversold + WPR oversold
if (rsi < 30 && wpr < -80 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Sell: RSI overbought + WPR overbought
else if (rsi > 70 && wpr > -20 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
// Exit
else if (Position > 0 && rsi > 65)
SellMarket();
else if (Position < 0 && rsi < 35)
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, WilliamsR
from StockSharp.Algo.Strategies import Strategy
class averaged_stoch_wpr_strategy(Strategy):
def __init__(self):
super(averaged_stoch_wpr_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._wpr_period = self.Param("WprPeriod", 14) \
.SetDisplay("WPR Period", "Williams %R period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def wpr_period(self):
return self._wpr_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(averaged_stoch_wpr_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
wpr = WilliamsR()
wpr.Length = self.wpr_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, wpr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, rsi, wpr):
if candle.State != CandleStates.Finished:
return
# Buy: RSI oversold + WPR oversold
if rsi < 30 and wpr < -80 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell: RSI overbought + WPR overbought
elif rsi > 70 and wpr > -20 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit
elif self.Position > 0 and rsi > 65:
self.SellMarket()
elif self.Position < 0 and rsi < 35:
self.BuyMarket()
def CreateClone(self):
return averaged_stoch_wpr_strategy()