Megabar Ausbruch (Range & Volumen & RSI)
Megabar Breakout erkennt große Kerzen, die durch hohes Volumen und RSI-Bestätigung gestützt werden. Die Strategie geht bei bullischen Megabars long und bei bärischen short.
Sie multipliziert den durchschnittlichen Range und das Volumen, um Megabars zu finden. Der gleitende Durchschnitt des RSI filtert die Trades.
Details
- Einstiegskriterien: Kerzenkörper und Volumen übersteigen ihre gleitenden Durchschnitte um die angegebenen Multiplikatoren. RSI MA über dem Long-Schwellenwert für Käufe und unter dem Short-Schwellenwert für Verkäufe.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Stop-Loss oder Take-Profit.
- Stops: Ja.
- Standardwerte:
CandleType= TimeSpan.FromMinutes(5)VolumeAveragePeriod= 20VolumeMultiplier= 3RangeAveragePeriod= 20RangeMultiplier= 4RsiPeriod= 14RsiMaPeriod= 14LongRsiThreshold= 50ShortRsiThreshold= 70TakeProfit= 400StopLoss= 300FilterTradeHours= false
- Filter:
- Kategorie: Ausbruch
- Richtung: Beide
- Indikatoren: Volumen, Range, RSI
- Stops: Ja
- Komplexität: Grundlegend
- Zeitrahmen: Intraday
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
using System;
using System.Linq;
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;
public class MegabarBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _avgPeriod;
private readonly StrategyParam<decimal> _multiplier;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _signalCooldownBars;
private readonly StrategyParam<DataType> _candleType;
private RelativeStrengthIndex _rsi;
private readonly List<decimal> _volumes = new();
private readonly List<decimal> _ranges = new();
private int _barsFromSignal;
public int AvgPeriod { get => _avgPeriod.Value; set => _avgPeriod.Value = value; }
public decimal Multiplier { get => _multiplier.Value; set => _multiplier.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SignalCooldownBars { get => _signalCooldownBars.Value; set => _signalCooldownBars.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MegabarBreakoutStrategy()
{
_avgPeriod = Param(nameof(AvgPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Average Period", "Rolling average period", "General");
_multiplier = Param(nameof(Multiplier), 1.8m)
.SetGreaterThanZero()
.SetDisplay("Multiplier", "Volume and range multiplier", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "General");
_signalCooldownBars = Param(nameof(SignalCooldownBars), 8)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown Bars", "Minimum bars between entries", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(10).TimeFrame())
.SetDisplay("Candle Type", "Candles timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_rsi = null;
_volumes.Clear();
_ranges.Clear();
_barsFromSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartProtection(null, null);
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_volumes.Clear();
_ranges.Clear();
_barsFromSignal = SignalCooldownBars;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var vol = candle.TotalVolume;
var range = Math.Abs(candle.ClosePrice - candle.OpenPrice);
_volumes.Add(vol);
_ranges.Add(range);
if (_volumes.Count > AvgPeriod) _volumes.RemoveAt(0);
if (_ranges.Count > AvgPeriod) _ranges.RemoveAt(0);
if (!_rsi.IsFormed || _volumes.Count < AvgPeriod)
return;
var avgVol = _volumes.Average();
var avgRange = _ranges.Average();
var volumeOk = vol > avgVol * Multiplier;
var rangeOk = range > avgRange * Multiplier;
_barsFromSignal++;
if (_barsFromSignal >= SignalCooldownBars && candle.ClosePrice > candle.OpenPrice && volumeOk && rangeOk && rsiValue > 52m && Position <= 0)
{
BuyMarket();
_barsFromSignal = 0;
}
else if (_barsFromSignal >= SignalCooldownBars && candle.ClosePrice < candle.OpenPrice && volumeOk && rangeOk && rsiValue < 48m && Position >= 0)
{
SellMarket();
_barsFromSignal = 0;
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class megabar_breakout_strategy(Strategy):
def __init__(self):
super(megabar_breakout_strategy, self).__init__()
self._avg_period = self.Param("AvgPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("Average Period", "Rolling average period", "General")
self._multiplier = self.Param("Multiplier", 1.8) \
.SetGreaterThanZero() \
.SetDisplay("Multiplier", "Volume and range multiplier", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "RSI period", "General")
self._signal_cooldown_bars = self.Param("SignalCooldownBars", 8) \
.SetGreaterThanZero() \
.SetDisplay("Signal Cooldown Bars", "Minimum bars between entries", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(10))) \
.SetDisplay("Candle Type", "Candles timeframe", "General")
self._volumes = []
self._ranges = []
self._bars_from_signal = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(megabar_breakout_strategy, self).OnReseted()
self._volumes = []
self._ranges = []
self._bars_from_signal = 0
def OnStarted2(self, time):
super(megabar_breakout_strategy, self).OnStarted2(time)
self._volumes = []
self._ranges = []
self._bars_from_signal = self._signal_cooldown_bars.Value
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self._rsi_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._rsi, self.OnProcess).Start()
def OnProcess(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
vol = float(candle.TotalVolume)
rng = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
ap = self._avg_period.Value
self._volumes.append(vol)
self._ranges.append(rng)
if len(self._volumes) > ap:
self._volumes.pop(0)
if len(self._ranges) > ap:
self._ranges.pop(0)
if not self._rsi.IsFormed or len(self._volumes) < ap:
return
avg_vol = sum(self._volumes) / len(self._volumes)
avg_rng = sum(self._ranges) / len(self._ranges)
mult = float(self._multiplier.Value)
volume_ok = vol > avg_vol * mult
range_ok = rng > avg_rng * mult
rv = float(rsi_value)
close = float(candle.ClosePrice)
opn = float(candle.OpenPrice)
self._bars_from_signal += 1
cd = self._signal_cooldown_bars.Value
if self._bars_from_signal >= cd and close > opn and volume_ok and range_ok and rv > 52.0 and self.Position <= 0:
self.BuyMarket()
self._bars_from_signal = 0
elif self._bars_from_signal >= cd and close < opn and volume_ok and range_ok and rv < 48.0 and self.Position >= 0:
self.SellMarket()
self._bars_from_signal = 0
def CreateClone(self):
return megabar_breakout_strategy()