Start
/
Strategie-Beispiele
Auf GitHub ansehen
Sitzungs-Ordersentiment-Strategie
Übersicht
Diese Strategie handelt basierend auf dem Ungleichgewicht zwischen Kauf- und Verkaufsaufträgen im Orderbuch. Sie misst Verhältnisse von Auftragsanzahlen und Gesamtvolumina für beide Seiten des Buches und eröffnet eine Position, wenn die Dominanz einer Seite konfigurierbare Schwellenwerte überschreitet. Der Handel ist nur während eines bestimmten Zeitfensters erlaubt.
Nach dem Öffnen einer Position werden die Schwellenwerte reduziert, um die gegenüberliegende Seite zu überwachen. Wenn die gegenüberliegende Seite über diese reduzierten Schwellenwerte wächst, wird die Position geschlossen. Stop-Loss und Take-Profit werden ebenfalls in absoluten Preispunkten angewendet.
Handelsregeln
Long-Einstieg : Kaufen wenn
BUY volume / SELL volume >= DiffVolumesEx und BUY orders / SELL orders >= DiffTradersEx
Eine der Seiten erfüllt MinTraders und MinVolume
Die aktuelle Zeit besteht CheckTradingTime
Short-Einstieg : Verkaufen, wenn die obige Logik spiegelbildlich für die Verkaufsseite gilt.
Ausstieg :
Long schließen wenn SELL volume / BUY volume > 1 / DiffVolumes oder SELL orders / BUY orders > 1 / DiffTraders
Short schließen wenn SELL volume / BUY volume < DiffVolumes oder SELL orders / BUY orders < DiffTraders
Alle Positionen außerhalb der Handelszeiten schließen
Stops : Verwendet Stop Loss und Take Profit in Preispunkten.
Parameter
MinVolume – minimales Gesamtvolumen auf einer Seite des Buches (Standard: 20000)
MinTraders – Mindestanzahl von Aufträgen auf einer Seite (Standard: 1000)
DiffVolumesEx – Volumenverhältnis für den Einstieg (Standard: 2.0)
DiffTradersEx – Auftragsanzahlverhältnis für den Einstieg (Standard: 1.5)
MinDiffVolumesEx – Volumenverhältnis nach Positionseröffnung (Standard: 1.5)
MinDiffTradersEx – Auftragsanzahlverhältnis nach Positionseröffnung (Standard: 1.3)
SleepMinutes – Verzögerung zwischen Orderbuchprüfungen in Minuten (Standard: 5)
TpPips – Take-Profit in Preispunkten (Standard: 500)
SlPips – Stop-Loss in Preispunkten (Standard: 500)
Hinweise
Die Strategie enthält keine Python-Version.
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 trading on volume sentiment using candle data.
/// Compares bullish vs bearish volume over a lookback period.
/// </summary>
public class SessionOrderSentimentStrategy : Strategy
{
private readonly StrategyParam<decimal> _volumeRatio;
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<DataType> _candleType;
private readonly List<(decimal vol, bool isBull)> _volumeHistory = new();
private decimal _entryPrice;
/// <summary>
/// Volume ratio required for entry.
/// </summary>
public decimal VolumeRatio
{
get => _volumeRatio.Value;
set => _volumeRatio.Value = value;
}
/// <summary>
/// Lookback period in candles.
/// </summary>
public int Lookback
{
get => _lookback.Value;
set => _lookback.Value = value;
}
/// <summary>
/// Stop loss percentage.
/// </summary>
public decimal StopLossPct
{
get => _stopLossPct.Value;
set => _stopLossPct.Value = value;
}
/// <summary>
/// Candle type for processing.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="SessionOrderSentimentStrategy"/>.
/// </summary>
public SessionOrderSentimentStrategy()
{
_volumeRatio = Param(nameof(VolumeRatio), 1.5m)
.SetDisplay("Volume Ratio", "Bull/bear volume ratio for entry", "General")
.SetGreaterThanZero();
_lookback = Param(nameof(Lookback), 10)
.SetDisplay("Lookback", "Number of candles to look back", "General")
.SetGreaterThanZero();
_stopLossPct = Param(nameof(StopLossPct), 1m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
.SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var isBull = candle.ClosePrice >= candle.OpenPrice;
_volumeHistory.Add((candle.TotalVolume, isBull));
if (_volumeHistory.Count > Lookback)
_volumeHistory.RemoveAt(0);
if (_volumeHistory.Count < Lookback)
return;
var bullVolume = 0m;
var bearVolume = 0m;
foreach (var (vol, bull) in _volumeHistory)
{
if (bull)
bullVolume += vol;
else
bearVolume += vol;
}
if (bearVolume == 0) bearVolume = 1;
if (bullVolume == 0) bullVolume = 1;
var bullBearRatio = bullVolume / bearVolume;
var bearBullRatio = bearVolume / bullVolume;
var close = candle.ClosePrice;
// Check stop loss
if (Position > 0 && close <= _entryPrice * (1m - StopLossPct / 100m))
{
SellMarket();
return;
}
if (Position < 0 && close >= _entryPrice * (1m + StopLossPct / 100m))
{
BuyMarket();
return;
}
// Bullish sentiment
if (bullBearRatio >= VolumeRatio)
{
if (Position < 0)
{
BuyMarket();
}
if (Position <= 0)
{
_entryPrice = close;
BuyMarket();
}
}
// Bearish sentiment
else if (bearBullRatio >= VolumeRatio)
{
if (Position > 0)
{
SellMarket();
}
if (Position >= 0)
{
_entryPrice = close;
SellMarket();
}
}
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_volumeHistory.Clear();
_entryPrice = 0m;
}
}
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.Strategies import Strategy
class session_order_sentiment_strategy(Strategy):
def __init__(self):
super(session_order_sentiment_strategy, self).__init__()
self._volume_ratio = self.Param("VolumeRatio", 1.5) \
.SetDisplay("Volume Ratio", "Bull/bear volume ratio for entry", "General")
self._lookback = self.Param("Lookback", 10) \
.SetDisplay("Lookback", "Number of candles to look back", "General")
self._stop_loss_pct = self.Param("StopLossPct", 1.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._volume_history = []
self._entry_price = 0.0
@property
def volume_ratio(self):
return self._volume_ratio.Value
@property
def lookback(self):
return self._lookback.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(session_order_sentiment_strategy, self).OnReseted()
self._volume_history = []
self._entry_price = 0.0
def OnStarted2(self, time):
super(session_order_sentiment_strategy, self).OnStarted2(time)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
is_bull = float(candle.ClosePrice) >= float(candle.OpenPrice)
vol = float(candle.TotalVolume)
lb = int(self.lookback)
self._volume_history.append((vol, is_bull))
if len(self._volume_history) > lb:
self._volume_history.pop(0)
if len(self._volume_history) < lb:
return
bull_volume = 0.0
bear_volume = 0.0
for v, b in self._volume_history:
if b:
bull_volume += v
else:
bear_volume += v
if bear_volume == 0:
bear_volume = 1.0
if bull_volume == 0:
bull_volume = 1.0
bull_bear_ratio = bull_volume / bear_volume
bear_bull_ratio = bear_volume / bull_volume
close = float(candle.ClosePrice)
sl = float(self.stop_loss_pct)
vr = float(self.volume_ratio)
# Check stop loss
if self.Position > 0 and close <= self._entry_price * (1.0 - sl / 100.0):
self.SellMarket()
return
if self.Position < 0 and close >= self._entry_price * (1.0 + sl / 100.0):
self.BuyMarket()
return
# Bullish sentiment
if bull_bear_ratio >= vr:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self._entry_price = close
self.BuyMarket()
# Bearish sentiment
elif bear_bull_ratio >= vr:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self._entry_price = close
self.SellMarket()
def CreateClone(self):
return session_order_sentiment_strategy()