Color Schaff WPR Trend Cycle Strategy
This strategy implements the Color Schaff WPR Trend Cycle expert from MetaTrader. It uses the Schaff Trend Cycle calculated from fast and slow Williams %R values to detect market turns.
The algorithm works on finished candles only. When the indicator value crosses above the upper level, the strategy opens a long position and closes any existing short position. When the value crosses below the lower level, it opens a short position and closes any existing long position.
Parameters
- Fast WPR – period for the fast Williams %R calculation.
- Slow WPR – period for the slow Williams %R calculation.
- Cycle – cycle length used in the Schaff Trend calculation.
- High Level – upper trigger level for long entries.
- Low Level – lower trigger level for short entries.
- Candle Type – timeframe of candles for indicator evaluation.
Links
- Original MQL source:
MQL/13489/mql5/Experts/exp_colorschaffwprtrendcycle.mq5 - Indicator:
MQL/13489/mql5/Indicators/colorschaffwprtrendcycle.mq5
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on the Schaff Trend Cycle calculated from WPR.
/// </summary>
public class ColorSchaffWprTrendCycleStrategy : Strategy
{
private readonly StrategyParam<int> _fastWpr;
private readonly StrategyParam<int> _slowWpr;
private readonly StrategyParam<int> _cycle;
private readonly StrategyParam<int> _highLevel;
private readonly StrategyParam<int> _lowLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevStc;
public int FastWpr { get => _fastWpr.Value; set => _fastWpr.Value = value; }
public int SlowWpr { get => _slowWpr.Value; set => _slowWpr.Value = value; }
public int Cycle { get => _cycle.Value; set => _cycle.Value = value; }
public int HighLevel { get => _highLevel.Value; set => _highLevel.Value = value; }
public int LowLevel { get => _lowLevel.Value; set => _lowLevel.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorSchaffWprTrendCycleStrategy()
{
_fastWpr = Param(nameof(FastWpr), 23)
.SetDisplay("Fast WPR", "Fast Williams %R period", "Indicator");
_slowWpr = Param(nameof(SlowWpr), 50)
.SetDisplay("Slow WPR", "Slow Williams %R period", "Indicator");
_cycle = Param(nameof(Cycle), 10)
.SetDisplay("Cycle", "Cycle length", "Indicator");
_highLevel = Param(nameof(HighLevel), 60)
.SetDisplay("High Level", "Upper trigger level", "Indicator");
_lowLevel = Param(nameof(LowLevel), -60)
.SetDisplay("Low Level", "Lower trigger level", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevStc = 0m;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Schaff trend cycle indicator using WPR values
var stc = new SchaffTrendCycle
{
Length = Cycle
};
stc.Macd.Macd.ShortMa.Length = FastWpr;
stc.Macd.Macd.LongMa.Length = SlowWpr;
var subscription = SubscribeCandles(CandleType);
subscription.Bind(stc, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal stcValue)
{
if (candle.State != CandleStates.Finished)
return;
var prev = _prevStc;
_prevStc = stcValue;
// Generate buy signal when STC crosses above HighLevel
var crossUp = prev <= HighLevel && stcValue > HighLevel;
// Generate sell signal when STC crosses below LowLevel
var crossDown = prev >= LowLevel && stcValue < LowLevel;
if (crossUp)
{
if (Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
}
else if (crossDown)
{
if (Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import Math, TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SchaffTrendCycle
from StockSharp.Algo.Strategies import Strategy
class color_schaff_wpr_trend_cycle_strategy(Strategy):
def __init__(self):
super(color_schaff_wpr_trend_cycle_strategy, self).__init__()
self._fast_wpr = self.Param("FastWpr", 23) \
.SetDisplay("Fast WPR", "Fast Williams %R period", "Indicator")
self._slow_wpr = self.Param("SlowWpr", 50) \
.SetDisplay("Slow WPR", "Slow Williams %R period", "Indicator")
self._cycle = self.Param("Cycle", 10) \
.SetDisplay("Cycle", "Cycle length", "Indicator")
self._high_level = self.Param("HighLevel", 60) \
.SetDisplay("High Level", "Upper trigger level", "Indicator")
self._low_level = self.Param("LowLevel", -60) \
.SetDisplay("Low Level", "Lower trigger level", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_stc = 0.0
@property
def FastWpr(self):
return self._fast_wpr.Value
@FastWpr.setter
def FastWpr(self, value):
self._fast_wpr.Value = value
@property
def SlowWpr(self):
return self._slow_wpr.Value
@SlowWpr.setter
def SlowWpr(self, value):
self._slow_wpr.Value = value
@property
def Cycle(self):
return self._cycle.Value
@Cycle.setter
def Cycle(self, value):
self._cycle.Value = value
@property
def HighLevel(self):
return self._high_level.Value
@HighLevel.setter
def HighLevel(self, value):
self._high_level.Value = value
@property
def LowLevel(self):
return self._low_level.Value
@LowLevel.setter
def LowLevel(self, value):
self._low_level.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(color_schaff_wpr_trend_cycle_strategy, self).OnStarted2(time)
stc = SchaffTrendCycle()
stc.Length = self.Cycle
stc.Macd.Macd.ShortMa.Length = self.FastWpr
stc.Macd.Macd.LongMa.Length = self.SlowWpr
self.SubscribeCandles(self.CandleType) \
.Bind(stc, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, stc_value):
if candle.State != CandleStates.Finished:
return
stc_val = float(stc_value)
prev = self._prev_stc
self._prev_stc = stc_val
high = float(self.HighLevel)
low = float(self.LowLevel)
cross_up = prev <= high and stc_val > high
cross_down = prev >= low and stc_val < low
if cross_up:
if self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down:
if self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def OnReseted(self):
super(color_schaff_wpr_trend_cycle_strategy, self).OnReseted()
self._prev_stc = 0.0
def CreateClone(self):
return color_schaff_wpr_trend_cycle_strategy()