Fortgeschrittene adaptive Gitter-Strategie
Die fortgeschrittene adaptive Gitter-Strategie verwendet mehrere technische Indikatoren zur Bewertung der Trendrichtung und baut ein dynamisches Gitter von Einstiegsniveaus auf. Die Gittergröße passt sich über ATR an die Volatilität an, und Orders werden platziert, wenn der Preis Gitterniveaus in Trendrichtung berührt. Zu den Risikokontrollen gehören fester Stop-Loss, Take-Profit, Trailing-Stop, zeitbasierter Ausstieg und tägliches Verlustlimit.
Details
- Einstiegskriterien:
- In Trendmärkten: Preis erreicht berechnete Gitterniveaus mit RSI-Bestätigung.
- In Seitwärtsmärkten: überkaufter/überverkaufter RSI löst Gitter-Einstiege aus.
- Long/Short: Beide Seiten.
- Ausstiegskriterien:
- Stop-Loss, Take-Profit, Trailing-Stop, Trendumkehr oder zeitbasierter Ausstieg.
- Stops: Fest und Trailing.
- Standardwerte:
BaseGridSize= 1MaxPositions= 5UseVolatilityGrid= TrueAtrLength= 14AtrMultiplier= 1.5RsiLength= 14RsiOverbought= 70RsiOversold= 30ShortMaLength= 20LongMaLength= 50SuperLongMaLength= 200MacdFastLength= 12MacdSlowLength= 26MacdSignalLength= 9StopLossPercent= 2TakeProfitPercent= 3UseTrailingStop= TrueTrailingStopPercent= 1MaxLossPerDay= 5TimeBasedExit= TrueMaxHoldingPeriod= 48
- Filter:
- Kategorie: Gitter / Trend
- Richtung: Beide
- Indikatoren: ATR, SMA, MACD, RSI, Momentum
- Stops: Ja
- Komplexität: Hoch
- Zeitrahmen: Beliebig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Hoch
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Advanced Adaptive Grid Trading Strategy.
/// Uses RSI extremes and MA trend to enter, with percentage-based stop/TP.
/// </summary>
public class AdvancedAdaptiveGridStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _rsiOverbought;
private readonly StrategyParam<int> _rsiOversold;
private readonly StrategyParam<int> _shortMaLength;
private readonly StrategyParam<int> _longMaLength;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<int> _cooldownBars;
private decimal _entryPrice;
private int _cooldownRemaining;
public DataType CandleType { get => _candleType.Value; set => _candleType.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 int ShortMaLength { get => _shortMaLength.Value; set => _shortMaLength.Value = value; }
public int LongMaLength { get => _longMaLength.Value; set => _longMaLength.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public AdvancedAdaptiveGridStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 70)
.SetDisplay("RSI Overbought", "Overbought level", "Indicators");
_rsiOversold = Param(nameof(RsiOversold), 30)
.SetDisplay("RSI Oversold", "Oversold level", "Indicators");
_shortMaLength = Param(nameof(ShortMaLength), 20)
.SetGreaterThanZero()
.SetDisplay("Short MA", "Short moving average length", "Trend");
_longMaLength = Param(nameof(LongMaLength), 50)
.SetGreaterThanZero()
.SetDisplay("Long MA", "Long moving average length", "Trend");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 3m)
.SetGreaterThanZero()
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_cooldownBars = Param(nameof(CooldownBars), 10)
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var shortMa = new SimpleMovingAverage { Length = ShortMaLength };
var longMa = new SimpleMovingAverage { Length = LongMaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, shortMa, longMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, shortMa);
DrawIndicator(area, longMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal shortMaValue, decimal longMaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var currentPrice = candle.ClosePrice;
var bullish = shortMaValue > longMaValue;
var bearish = shortMaValue < longMaValue;
// Check stop/TP for existing positions
if (Position > 0 && _entryPrice > 0)
{
var stopPrice = _entryPrice * (1 - StopLossPercent / 100m);
var tpPrice = _entryPrice * (1 + TakeProfitPercent / 100m);
if (currentPrice <= stopPrice || currentPrice >= tpPrice)
{
SellMarket(Math.Abs(Position));
_entryPrice = 0;
_cooldownRemaining = CooldownBars;
return;
}
}
else if (Position < 0 && _entryPrice > 0)
{
var stopPrice = _entryPrice * (1 + StopLossPercent / 100m);
var tpPrice = _entryPrice * (1 - TakeProfitPercent / 100m);
if (currentPrice >= stopPrice || currentPrice <= tpPrice)
{
BuyMarket(Math.Abs(Position));
_entryPrice = 0;
_cooldownRemaining = CooldownBars;
return;
}
}
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
return;
}
// Entry logic
if (bullish && rsiValue < RsiOversold && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_entryPrice = currentPrice;
_cooldownRemaining = CooldownBars;
}
else if (bearish && rsiValue > RsiOverbought && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_entryPrice = currentPrice;
_cooldownRemaining = CooldownBars;
}
// Trend reversal exit
else if (Position > 0 && bearish && rsiValue > RsiOverbought)
{
SellMarket(Math.Abs(Position));
_entryPrice = 0;
_cooldownRemaining = CooldownBars;
}
else if (Position < 0 && bullish && rsiValue < RsiOversold)
{
BuyMarket(Math.Abs(Position));
_entryPrice = 0;
_cooldownRemaining = CooldownBars;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class advanced_adaptive_grid_strategy(Strategy):
def __init__(self):
super(advanced_adaptive_grid_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._rsi_overbought = self.Param("RsiOverbought", 70) \
.SetDisplay("RSI Overbought", "Overbought level", "Indicators")
self._rsi_oversold = self.Param("RsiOversold", 30) \
.SetDisplay("RSI Oversold", "Oversold level", "Indicators")
self._short_ma_length = self.Param("ShortMaLength", 20) \
.SetGreaterThanZero() \
.SetDisplay("Short MA", "Short moving average length", "Trend")
self._long_ma_length = self.Param("LongMaLength", 50) \
.SetGreaterThanZero() \
.SetDisplay("Long MA", "Long moving average length", "Trend")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0) \
.SetGreaterThanZero() \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._take_profit_percent = self.Param("TakeProfitPercent", 3.0) \
.SetGreaterThanZero() \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._cooldown_bars = self.Param("CooldownBars", 10) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._entry_price = 0.0
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(advanced_adaptive_grid_strategy, self).OnReseted()
self._entry_price = 0.0
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(advanced_adaptive_grid_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = int(self._rsi_length.Value)
short_ma = SimpleMovingAverage()
short_ma.Length = int(self._short_ma_length.Value)
long_ma = SimpleMovingAverage()
long_ma.Length = int(self._long_ma_length.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, short_ma, long_ma, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, short_ma)
self.DrawIndicator(area, long_ma)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_val, short_ma_val, long_ma_val):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
current_price = float(candle.ClosePrice)
rsi_v = float(rsi_val)
short_v = float(short_ma_val)
long_v = float(long_ma_val)
bullish = short_v > long_v
bearish = short_v < long_v
sl_pct = float(self._stop_loss_percent.Value)
tp_pct = float(self._take_profit_percent.Value)
ob = float(self._rsi_overbought.Value)
os_level = float(self._rsi_oversold.Value)
cooldown = int(self._cooldown_bars.Value)
# Check stop/TP for existing positions
if self.Position > 0 and self._entry_price > 0:
stop_price = self._entry_price * (1.0 - sl_pct / 100.0)
tp_price = self._entry_price * (1.0 + tp_pct / 100.0)
if current_price <= stop_price or current_price >= tp_price:
self.SellMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._cooldown_remaining = cooldown
return
elif self.Position < 0 and self._entry_price > 0:
stop_price = self._entry_price * (1.0 + sl_pct / 100.0)
tp_price = self._entry_price * (1.0 - tp_pct / 100.0)
if current_price >= stop_price or current_price <= tp_price:
self.BuyMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._cooldown_remaining = cooldown
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
return
# Entry logic
if bullish and rsi_v < os_level and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._entry_price = current_price
self._cooldown_remaining = cooldown
elif bearish and rsi_v > ob and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._entry_price = current_price
self._cooldown_remaining = cooldown
# Trend reversal exit
elif self.Position > 0 and bearish and rsi_v > ob:
self.SellMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._cooldown_remaining = cooldown
elif self.Position < 0 and bullish and rsi_v < os_level:
self.BuyMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._cooldown_remaining = cooldown
def CreateClone(self):
return advanced_adaptive_grid_strategy()