Übergeordnete Session Sweep-Alarm-Strategie
Diese Strategie überwacht tägliche Sessions und erkennt, wenn die aktuelle Session das Hoch oder Tief der vorherigen Session überstreicht. Wenn ein Sweep auftritt und die Kerze zurück in die vorherige Range schließt, wird ein Trade in die entgegengesetzte Richtung mit einem konfigurierbaren Chance-Risiko-Verhältnis eröffnet.
Details
- Einstiegskriterien: Sweep des Hochs/Tiefs der vorherigen Session mit optionalem Kerzenschluss-Filter.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Stop am Session-Extremum oder Ziel basierend auf dem Chance-Risiko-Verhältnis.
- Stops: Ja.
- Standardwerte:
MinRiskReward= 1UseCandleFilter= trueCandleType= TimeSpan.FromMinutes(15)
- Filter:
- Kategorie: Price Action
- Richtung: Beide
- Indikatoren: Keine
- Stops: Ja
- Komplexität: Mittel
- 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 Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Detects sweeps of the previous session's range and trades in the opposite direction.
/// </summary>
public class ParentSessionSweepsAlertStrategy : Strategy
{
private readonly StrategyParam<decimal> _minRiskReward;
private readonly StrategyParam<bool> _useCandleFilter;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevHigh;
private decimal? _prevLow;
private decimal _sessionHigh;
private decimal _sessionLow;
private DateTimeOffset _currentSessionDate;
private decimal? _stopPrice;
private decimal? _targetPrice;
private bool _isLong;
/// <summary>
/// Minimum risk reward ratio.
/// </summary>
public decimal MinRiskReward
{
get => _minRiskReward.Value;
set => _minRiskReward.Value = value;
}
/// <summary>
/// Require candle close back inside previous range after sweep.
/// </summary>
public bool UseCandleFilter
{
get => _useCandleFilter.Value;
set => _useCandleFilter.Value = value;
}
/// <summary>
/// Candle type for processing.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="ParentSessionSweepsAlertStrategy"/>.
/// </summary>
public ParentSessionSweepsAlertStrategy()
{
_minRiskReward = Param(nameof(MinRiskReward), 1m)
.SetDisplay("Min RR", "Minimum risk reward ratio", "General")
;
_useCandleFilter = Param(nameof(UseCandleFilter), true)
.SetDisplay("Use Candle Filter", "Require candle close inside range", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for processing", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = null;
_prevLow = null;
_sessionHigh = 0m;
_sessionLow = 0m;
_currentSessionDate = default;
_stopPrice = null;
_targetPrice = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var date = candle.OpenTime.Date;
if (_currentSessionDate != date)
{
_prevHigh = _sessionHigh != 0m ? _sessionHigh : _prevHigh;
_prevLow = _sessionLow != 0m ? _sessionLow : _prevLow;
_sessionHigh = candle.HighPrice;
_sessionLow = candle.LowPrice;
_currentSessionDate = date;
return;
}
_sessionHigh = Math.Max(_sessionHigh, candle.HighPrice);
_sessionLow = Math.Min(_sessionLow, candle.LowPrice);
if (Position == 0 && _prevHigh is decimal ph && _prevLow is decimal pl)
{
if (candle.HighPrice > ph && (!UseCandleFilter || candle.ClosePrice < ph))
{
EnterShort(candle);
}
else if (candle.LowPrice < pl && (!UseCandleFilter || candle.ClosePrice > pl))
{
EnterLong(candle);
}
}
else if (Position != 0 && _stopPrice is decimal stop && _targetPrice is decimal target)
{
if (_isLong)
{
if (candle.LowPrice <= stop || candle.HighPrice >= target)
{
SellMarket();
_stopPrice = null;
_targetPrice = null;
}
}
else
{
if (candle.HighPrice >= stop || candle.LowPrice <= target)
{
BuyMarket();
_stopPrice = null;
_targetPrice = null;
}
}
}
}
private void EnterLong(ICandleMessage candle)
{
var entry = candle.ClosePrice;
var stop = candle.LowPrice;
var risk = entry - stop;
var target = entry + risk * MinRiskReward;
BuyMarket();
_isLong = true;
_stopPrice = stop;
_targetPrice = target;
LogInfo($"Bullish setup at {candle.OpenTime:O}. Entry={entry}, Stop={stop}, Target={target}");
}
private void EnterShort(ICandleMessage candle)
{
var entry = candle.ClosePrice;
var stop = candle.HighPrice;
var risk = stop - entry;
var target = entry - risk * MinRiskReward;
SellMarket();
_isLong = false;
_stopPrice = stop;
_targetPrice = target;
LogInfo($"Bearish setup at {candle.OpenTime:O}. Entry={entry}, Stop={stop}, Target={target}");
}
}
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.Strategies import Strategy
class parent_session_sweeps_alert_strategy(Strategy):
def __init__(self):
super(parent_session_sweeps_alert_strategy, self).__init__()
self._min_risk_reward = self.Param("MinRiskReward", 1.0)
self._use_candle_filter = self.Param("UseCandleFilter", True)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15)))
self._prev_high = None
self._prev_low = None
self._session_high = 0.0
self._session_low = 0.0
self._current_session_date = None
self._stop_price = None
self._target_price = None
self._is_long = False
@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(parent_session_sweeps_alert_strategy, self).OnReseted()
self._prev_high = None
self._prev_low = None
self._session_high = 0.0
self._session_low = 0.0
self._current_session_date = None
self._stop_price = None
self._target_price = None
def OnStarted2(self, time):
super(parent_session_sweeps_alert_strategy, self).OnStarted2(time)
self._prev_high = None
self._prev_low = None
self._session_high = 0.0
self._session_low = 0.0
self._current_session_date = None
self._stop_price = None
self._target_price = None
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.OnProcess).Start()
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
date = candle.OpenTime.Date
if self._current_session_date is None or self._current_session_date != date:
if self._session_high != 0.0:
self._prev_high = self._session_high
self._prev_low = self._session_low
self._session_high = high
self._session_low = low
self._current_session_date = date
return
self._session_high = max(self._session_high, high)
self._session_low = min(self._session_low, low)
if self.Position == 0 and self._prev_high is not None and self._prev_low is not None:
ph = self._prev_high
pl = self._prev_low
use_filter = self._use_candle_filter.Value
if high > ph and (not use_filter or close < ph):
entry = close
stop = high
risk = stop - entry
if risk > 0:
rr = float(self._min_risk_reward.Value)
target = entry - risk * rr
self.SellMarket()
self._is_long = False
self._stop_price = stop
self._target_price = target
elif low < pl and (not use_filter or close > pl):
entry = close
stop = low
risk = entry - stop
if risk > 0:
rr = float(self._min_risk_reward.Value)
target = entry + risk * rr
self.BuyMarket()
self._is_long = True
self._stop_price = stop
self._target_price = target
elif self.Position != 0 and self._stop_price is not None and self._target_price is not None:
if self._is_long:
if low <= self._stop_price or high >= self._target_price:
self.SellMarket()
self._stop_price = None
self._target_price = None
else:
if high >= self._stop_price or low <= self._target_price:
self.BuyMarket()
self._stop_price = None
self._target_price = None
def CreateClone(self):
return parent_session_sweeps_alert_strategy()