Knux Multi-Indikator-Strategie
Diese Strategie kombiniert Trendstärke-Indikatoren und Momentum-Oszillatoren, um Ausbrüche zu handeln. Sie wartet auf einen bullischen oder bärischen Crossover zweier gleitender Durchschnitte, während der Average Directional Index (ADX) einen starken Trend signalisiert. Der Relative Vigor Index (RVI), der Commodity Channel Index (CCI) und Williams %R dienen als Filter, um sicherzustellen, dass das Momentum die Bewegung bestätigt und der Markt nicht überdehnt ist.
Das System kann sowohl Long- als auch Short-Positionen eröffnen. Es hält die Position, bis ein entgegengesetztes Signal erscheint, und verwendet keinen dedizierten Stop-Loss. Alle Parameter wie Indikatorperioden und Schwellenwerte sind konfigurierbar.
Details
- Einstiegskriterien:
- Long: Schneller SMA kreuzt oberhalb des langsamen SMA,
ADX > AdxLevel, RVI steigend, CCI < -CciLevel, und WPR <= -100 + WprBuyRange.
- Short: Schneller SMA kreuzt unterhalb des langsamen SMA,
ADX > AdxLevel, RVI fallend, CCI > CciLevel, und WPR >= -WprSellRange.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Entgegengesetztes Signal (Crossover in die andere Richtung).
- Stops: Kein expliziter Stop-Loss.
- Standardwerte:
FastMaLength = 5
SlowMaLength = 20
AdxPeriod = 14
AdxLevel = 15
RviPeriod = 20
CciPeriod = 40
CciLevel = 150
WprPeriod = 60
WprBuyRange = 15
WprSellRange = 15
- Filter:
- Kategorie: Trendfolge
- Richtung: Beide
- Indikatoren: Mehrere
- Stops: Keine
- Komplexität: Mittel
- Zeitrahmen: Kurzfristig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// Knux multi-indicator strategy.
/// Combines CCI, Williams %R and a moving average crossover for entry signals.
/// </summary>
public class KnuxStrategy : Strategy
{
private readonly StrategyParam<int> _fastMaLength;
private readonly StrategyParam<int> _slowMaLength;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _wprPeriod;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _slowMa;
private CommodityChannelIndex _cci;
private WilliamsR _wpr;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isInitialized;
public int FastMaLength { get => _fastMaLength.Value; set => _fastMaLength.Value = value; }
public int SlowMaLength { get => _slowMaLength.Value; set => _slowMaLength.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public int WprPeriod { get => _wprPeriod.Value; set => _wprPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public KnuxStrategy()
{
_fastMaLength = Param(nameof(FastMaLength), 5)
.SetGreaterThanZero()
.SetDisplay("Fast MA Length", "Period of fast moving average", "General");
_slowMaLength = Param(nameof(SlowMaLength), 20)
.SetGreaterThanZero()
.SetDisplay("Slow MA Length", "Period of slow moving average", "General");
_cciPeriod = Param(nameof(CciPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI calculation period", "General");
_wprPeriod = Param(nameof(WprPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("WPR Period", "Williams %R period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();
_prevFast = _prevSlow = 0m;
_isInitialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastMa = new SimpleMovingAverage { Length = FastMaLength };
_slowMa = new SimpleMovingAverage { Length = SlowMaLength };
_cci = new CommodityChannelIndex { Length = CciPeriod };
_wpr = new WilliamsR { Length = WprPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, _slowMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast)
{
if (candle.State != CandleStates.Finished)
return;
var slowResult = _slowMa.Process(candle.ClosePrice, candle.OpenTime, true);
var cciResult = _cci.Process(candle);
var wprResult = _wpr.Process(candle);
if (!slowResult.IsFormed)
{
_prevFast = fast;
return;
}
var slow = slowResult.ToDecimal();
if (!_isInitialized)
{
_prevFast = fast;
_prevSlow = slow;
_isInitialized = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
if (cciResult.IsFormed && wprResult.IsFormed)
{
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
else
{
// Fallback without CCI/WPR
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prevFast = fast;
_prevSlow = slow;
}
}
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, CommodityChannelIndex, WilliamsR, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class knux_strategy(Strategy):
"""
Knux multi-indicator: SMA crossover with CCI and Williams %R confirmation.
"""
def __init__(self):
super(knux_strategy, self).__init__()
self._fast_ma_length = self.Param("FastMaLength", 5) \
.SetDisplay("Fast MA Length", "Period of fast MA", "General")
self._slow_ma_length = self.Param("SlowMaLength", 20) \
.SetDisplay("Slow MA Length", "Period of slow MA", "General")
self._cci_period = self.Param("CciPeriod", 20) \
.SetDisplay("CCI Period", "CCI calculation period", "General")
self._wpr_period = self.Param("WprPeriod", 14) \
.SetDisplay("WPR Period", "Williams %R period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._slow_ma = None
self._cci = None
self._wpr = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_initialized = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(knux_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_initialized = False
def OnStarted2(self, time):
super(knux_strategy, self).OnStarted2(time)
fast_ma = SimpleMovingAverage()
fast_ma.Length = self._fast_ma_length.Value
self._slow_ma = SimpleMovingAverage()
self._slow_ma.Length = self._slow_ma_length.Value
self._cci = CommodityChannelIndex()
self._cci.Length = self._cci_period.Value
self._wpr = WilliamsR()
self._wpr.Length = self._wpr_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, self._slow_ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_val):
if candle.State != CandleStates.Finished:
return
fast = float(fast_val)
slow_result = process_float(self._slow_ma, candle.ClosePrice, candle.OpenTime, True)
cci_inp = CandleIndicatorValue(self._cci, candle)
self._cci.Process(cci_inp)
wpr_inp = CandleIndicatorValue(self._wpr, candle)
self._wpr.Process(wpr_inp)
if not slow_result.IsFormed:
self._prev_fast = fast
return
slow = float(slow_result)
if not self._is_initialized:
self._prev_fast = fast
self._prev_slow = slow
self._is_initialized = True
return
cross_up = self._prev_fast <= self._prev_slow and fast > slow
cross_down = self._prev_fast >= self._prev_slow and fast < slow
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return knux_strategy()