ColorMETRO WPR-Strategie
Diese Strategie verwendet den ColorMETRO Williams %R-Indikator, der schnelle und langsame Treppenlinien um den Williams %R-Oszillator aufbaut. Die schnelle Linie reagiert schnell auf Preisänderungen, während die langsame Linie das Rauschen glättet. Handelsentscheidungen werden getroffen, wenn sich diese Linien kreuzen, was auf potenzielle Impulswechsel hinweist. Wenn die schnelle Linie unter die langsame fällt, geht die Strategie davon aus, dass der Markt überverkauft ist und eröffnet eine Long-Position. Wenn die schnelle Linie über die langsame steigt, wird eine Short-Position eröffnet. Bestehende Positionen werden geschlossen, wenn die entgegengesetzte Bedingung erkannt wird.
Das Risikomanagement erfolgt über prozentbasierte Take-Profit- und Stop-Loss-Levels. Dies ermöglicht es der Strategie, sich an die Preisniveaus verschiedener Instrumente anzupassen. Der Standard-Kerzen-Zeitrahmen beträgt acht Stunden, was hilft, die Intraday-Volatilität herauszufiltern und sich auf mittelfristige Trends zu konzentrieren. Die Logik funktioniert auf beiden Seiten des Marktes und ermöglicht Long- und Short-Operationen.
Details
- Einstiegskriterien:
- Long:
Schnelle Liniekreuzt unter dieLangsame Linie. - Short:
Schnelle Liniekreuzt über dieLangsame Linie.
- Long:
- Long/Short: Beide Seiten.
- Ausstiegskriterien:
- Long:
Schnelle Liniesteigt über dieLangsame Linie. - Short:
Schnelle Liniefällt unter dieLangsame Linie.
- Long:
- Stops: Ja, prozentbasierter Take-Profit und Stop-Loss.
- Standardwerte:
WprPeriod= 7.FastStep= 5.SlowStep= 15.TakeProfitPercent= 4.StopLossPercent= 2.CandleType= 8-Stunden-Kerzen.
- Filter:
- Kategorie: Trendfolge.
- Richtung: Beide.
- Indikatoren: Einzeln (basierend auf Williams %R).
- Stops: Ja.
- Komplexität: Mittel.
- Zeitrahmen: Mittelfristig.
- Saisonalität: Nein.
- Neuronale Netze: Nein.
- Divergenz: Nein.
- Risikolevel: Mittel.
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 ColorMETRO Williams %R indicator.
/// It trades when the fast step line crosses the slow step line.
/// </summary>
public class ColorMetroWprStrategy : Strategy
{
private readonly StrategyParam<int> _wprPeriod;
private readonly StrategyParam<int> _fastStep;
private readonly StrategyParam<int> _slowStep;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
// Indicator instance
private WilliamsR _wpr;
// Previous state for step calculations
private decimal _fMinPrev;
private decimal _fMaxPrev;
private decimal _sMinPrev;
private decimal _sMaxPrev;
private int _fTrend;
private int _sTrend;
// Previous and current step values
private decimal _prevMPlus;
private decimal _prevMMinus;
private decimal _currMPlus;
private decimal _currMMinus;
private bool _isFirstValue;
/// <summary>
/// Period for Williams %R.
/// </summary>
public int WprPeriod
{
get => _wprPeriod.Value;
set => _wprPeriod.Value = value;
}
/// <summary>
/// Step size for the fast line.
/// </summary>
public int FastStep
{
get => _fastStep.Value;
set => _fastStep.Value = value;
}
/// <summary>
/// Step size for the slow line.
/// </summary>
public int SlowStep
{
get => _slowStep.Value;
set => _slowStep.Value = value;
}
/// <summary>
/// Take profit in percent.
/// </summary>
public decimal TakeProfitPercent
{
get => _takeProfitPercent.Value;
set => _takeProfitPercent.Value = value;
}
/// <summary>
/// Stop loss in percent.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Type of candles used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="ColorMetroWprStrategy"/>.
/// </summary>
public ColorMetroWprStrategy()
{
_wprPeriod = Param(nameof(WprPeriod), 7)
.SetDisplay("Williams %R Period", "Period for Williams %R", "Indicators")
.SetOptimize(5, 15, 1);
_fastStep = Param(nameof(FastStep), 5)
.SetDisplay("Fast Step", "Step size for fast line", "Indicators")
.SetOptimize(3, 10, 1);
_slowStep = Param(nameof(SlowStep), 15)
.SetDisplay("Slow Step", "Step size for slow line", "Indicators")
.SetOptimize(10, 20, 1);
_takeProfitPercent = Param(nameof(TakeProfitPercent), 4m)
.SetDisplay("Take Profit (%)", "Take profit as percentage", "Risk parameters")
.SetOptimize(2m, 6m, 1m);
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetDisplay("Stop Loss (%)", "Stop loss as percentage", "Risk parameters")
.SetOptimize(1m, 4m, 1m);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fMinPrev = decimal.MaxValue;
_fMaxPrev = decimal.MinValue;
_sMinPrev = decimal.MaxValue;
_sMaxPrev = decimal.MinValue;
_fTrend = 0;
_sTrend = 0;
_prevMPlus = 0m;
_prevMMinus = 0m;
_currMPlus = 0m;
_currMMinus = 0m;
_isFirstValue = true;
_wpr = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wpr = new WilliamsR { Length = WprPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_wpr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _wpr);
DrawOwnTrades(area);
}
StartProtection(
new Unit(TakeProfitPercent, UnitTypes.Percent),
new Unit(StopLossPercent, UnitTypes.Percent));
}
private void ProcessCandle(ICandleMessage candle, decimal wprValue)
{
// Use only finished candles
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var wpr = wprValue + 100m;
var fmax0 = wpr + 2m * FastStep;
var fmin0 = wpr - 2m * FastStep;
if (wpr > _fMaxPrev)
_fTrend = 1;
if (wpr < _fMinPrev)
_fTrend = -1;
if (_fTrend > 0 && fmin0 < _fMinPrev)
fmin0 = _fMinPrev;
if (_fTrend < 0 && fmax0 > _fMaxPrev)
fmax0 = _fMaxPrev;
var smax0 = wpr + 2m * SlowStep;
var smin0 = wpr - 2m * SlowStep;
if (wpr > _sMaxPrev)
_sTrend = 1;
if (wpr < _sMinPrev)
_sTrend = -1;
if (_sTrend > 0 && smin0 < _sMinPrev)
smin0 = _sMinPrev;
if (_sTrend < 0 && smax0 > _sMaxPrev)
smax0 = _sMaxPrev;
var mPlus = _fTrend > 0 ? fmin0 + FastStep : fmax0 - FastStep;
var mMinus = _sTrend > 0 ? smin0 + SlowStep : smax0 - SlowStep;
_fMinPrev = fmin0;
_fMaxPrev = fmax0;
_sMinPrev = smin0;
_sMaxPrev = smax0;
if (_isFirstValue)
{
_prevMPlus = mPlus;
_prevMMinus = mMinus;
_currMPlus = mPlus;
_currMMinus = mMinus;
_isFirstValue = false;
return;
}
_prevMPlus = _currMPlus;
_prevMMinus = _currMMinus;
_currMPlus = mPlus;
_currMMinus = mMinus;
var prevFastAboveSlow = _prevMPlus > _prevMMinus;
var prevFastBelowSlow = _prevMPlus < _prevMMinus;
if (prevFastAboveSlow)
{
if (Position < 0)
BuyMarket();
if (_currMPlus <= _currMMinus && Position <= 0)
BuyMarket();
}
else if (prevFastBelowSlow)
{
if (Position > 0)
SellMarket();
if (_currMPlus >= _currMMinus && Position >= 0)
SellMarket();
}
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import WilliamsR
from StockSharp.Algo.Strategies import Strategy
class color_metro_wpr_strategy(Strategy):
def __init__(self):
super(color_metro_wpr_strategy, self).__init__()
self._wpr_period = self.Param("WprPeriod", 7) \
.SetDisplay("Williams %R Period", "Period for Williams %R", "Indicators")
self._fast_step = self.Param("FastStep", 5) \
.SetDisplay("Fast Step", "Step size for fast line", "Indicators")
self._slow_step = self.Param("SlowStep", 15) \
.SetDisplay("Slow Step", "Step size for slow line", "Indicators")
self._take_profit_percent = self.Param("TakeProfitPercent", 4.0) \
.SetDisplay("Take Profit (%)", "Take profit as percentage", "Risk parameters")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0) \
.SetDisplay("Stop Loss (%)", "Stop loss as percentage", "Risk parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._wpr = None
self._f_min_prev = 999999.0
self._f_max_prev = -999999.0
self._s_min_prev = 999999.0
self._s_max_prev = -999999.0
self._f_trend = 0
self._s_trend = 0
self._prev_m_plus = 0.0
self._prev_m_minus = 0.0
self._curr_m_plus = 0.0
self._curr_m_minus = 0.0
self._is_first_value = True
@property
def wpr_period(self):
return self._wpr_period.Value
@property
def fast_step(self):
return self._fast_step.Value
@property
def slow_step(self):
return self._slow_step.Value
@property
def take_profit_percent(self):
return self._take_profit_percent.Value
@property
def stop_loss_percent(self):
return self._stop_loss_percent.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_metro_wpr_strategy, self).OnReseted()
self._f_min_prev = 999999.0
self._f_max_prev = -999999.0
self._s_min_prev = 999999.0
self._s_max_prev = -999999.0
self._f_trend = 0
self._s_trend = 0
self._prev_m_plus = 0.0
self._prev_m_minus = 0.0
self._curr_m_plus = 0.0
self._curr_m_minus = 0.0
self._is_first_value = True
self._wpr = None
def OnStarted2(self, time):
super(color_metro_wpr_strategy, self).OnStarted2(time)
self._wpr = WilliamsR()
self._wpr.Length = self.wpr_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._wpr, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._wpr)
self.DrawOwnTrades(area)
self.StartProtection(
takeProfit=Unit(float(self.take_profit_percent), UnitTypes.Percent),
stopLoss=Unit(float(self.stop_loss_percent), UnitTypes.Percent))
def process_candle(self, candle, wpr_value):
if candle.State != CandleStates.Finished:
return
wpr = float(wpr_value) + 100.0
fs = float(self.fast_step)
ss = float(self.slow_step)
fmax0 = wpr + 2.0 * fs
fmin0 = wpr - 2.0 * fs
if wpr > self._f_max_prev:
self._f_trend = 1
if wpr < self._f_min_prev:
self._f_trend = -1
if self._f_trend > 0 and fmin0 < self._f_min_prev:
fmin0 = self._f_min_prev
if self._f_trend < 0 and fmax0 > self._f_max_prev:
fmax0 = self._f_max_prev
smax0 = wpr + 2.0 * ss
smin0 = wpr - 2.0 * ss
if wpr > self._s_max_prev:
self._s_trend = 1
if wpr < self._s_min_prev:
self._s_trend = -1
if self._s_trend > 0 and smin0 < self._s_min_prev:
smin0 = self._s_min_prev
if self._s_trend < 0 and smax0 > self._s_max_prev:
smax0 = self._s_max_prev
m_plus = fmin0 + fs if self._f_trend > 0 else fmax0 - fs
m_minus = smin0 + ss if self._s_trend > 0 else smax0 - ss
self._f_min_prev = fmin0
self._f_max_prev = fmax0
self._s_min_prev = smin0
self._s_max_prev = smax0
if self._is_first_value:
self._prev_m_plus = m_plus
self._prev_m_minus = m_minus
self._curr_m_plus = m_plus
self._curr_m_minus = m_minus
self._is_first_value = False
return
self._prev_m_plus = self._curr_m_plus
self._prev_m_minus = self._curr_m_minus
self._curr_m_plus = m_plus
self._curr_m_minus = m_minus
prev_fast_above_slow = self._prev_m_plus > self._prev_m_minus
prev_fast_below_slow = self._prev_m_plus < self._prev_m_minus
if prev_fast_above_slow:
if self.Position < 0:
self.BuyMarket()
if self._curr_m_plus <= self._curr_m_minus and self.Position <= 0:
self.BuyMarket()
elif prev_fast_below_slow:
if self.Position > 0:
self.SellMarket()
if self._curr_m_plus >= self._curr_m_minus and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return color_metro_wpr_strategy()