Die Bias-Ratio-Strategie handelt Ausbrüche basierend auf der Preisabweichung von langfristigen gleitenden Durchschnitten. Sie vergleicht den Schlusskurs sowohl mit einem exponentiellen gleitenden Durchschnitt (EMA) als auch mit einem einfachen gleitenden Durchschnitt (SMA). Eine Long-Position wird eröffnet, wenn der Preis die EMA um ein bestimmtes Verhältnis übersteigt, und eine Short-Position, wenn der Preis um dasselbe Verhältnis unter die SMA fällt.
Details
Einstiegskriterien:
close / EMA >= 1 + BiasThreshold → Long einsteigen.
close / SMA <= 1 - BiasThreshold → Short einsteigen.
Long/Short: Beide Richtungen.
Ausstiegskriterien:
Das entgegengesetzte Signal schließt und kehrt Positionen um.
Stops: Keine.
Standardwerte:
MaPeriod = 200
BiasThreshold = 0.025
Filter:
Kategorie: Trendfolge
Richtung: Long & Short
Indikatoren: EMA, SMA
Stops: Nein
Komplexität: Niedrig
Zeitrahmen: Beliebig
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>
/// Bias Ratio Strategy - trades when price deviates from moving averages by a threshold.
/// </summary>
public class BiasRatioStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<decimal> _biasThreshold;
private decimal _prevBiasEma;
private decimal _prevBiasSma;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public decimal BiasThreshold { get => _biasThreshold.Value; set => _biasThreshold.Value = value; }
public BiasRatioStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_maPeriod = Param(nameof(MaPeriod), 200)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period", "Indicators");
_biasThreshold = Param(nameof(BiasThreshold), 0.015m)
.SetDisplay("Bias Threshold", "Price deviation ratio from MA", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevBiasEma = 0m;
_prevBiasSma = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = MaPeriod };
var sma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (emaValue <= 0 || smaValue <= 0)
return;
var biasEma = candle.ClosePrice / emaValue - 1m;
var biasSma = candle.ClosePrice / smaValue - 1m;
// Long: price crosses above threshold from EMA
var longSignal = _prevBiasEma <= BiasThreshold && biasEma > BiasThreshold;
// Short: price crosses below negative threshold from SMA
var shortSignal = _prevBiasSma >= -BiasThreshold && biasSma < -BiasThreshold;
if (longSignal && Position <= 0)
{
BuyMarket();
}
else if (shortSignal && Position >= 0)
{
SellMarket();
}
_prevBiasEma = biasEma;
_prevBiasSma = biasSma;
}
}
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 ExponentialMovingAverage, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bias_ratio_strategy(Strategy):
def __init__(self):
super(bias_ratio_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._ma_period = self.Param("MaPeriod", 200) \
.SetGreaterThanZero() \
.SetDisplay("MA Period", "Moving average period", "Indicators")
self._bias_threshold = self.Param("BiasThreshold", 0.015) \
.SetDisplay("Bias Threshold", "Price deviation ratio from MA", "Trading")
self._prev_bias_ema = 0.0
self._prev_bias_sma = 0.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(bias_ratio_strategy, self).OnReseted()
self._prev_bias_ema = 0.0
self._prev_bias_sma = 0.0
def OnStarted2(self, time):
super(bias_ratio_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self._ma_period.Value
sma = SimpleMovingAverage()
sma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, sma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, ema_val, sma_val):
if candle.State != CandleStates.Finished:
return
ema_v = float(ema_val)
sma_v = float(sma_val)
if ema_v <= 0 or sma_v <= 0:
return
close = float(candle.ClosePrice)
bias_ema = close / ema_v - 1.0
bias_sma = close / sma_v - 1.0
threshold = float(self._bias_threshold.Value)
long_signal = self._prev_bias_ema <= threshold and bias_ema > threshold
short_signal = self._prev_bias_sma >= -threshold and bias_sma < -threshold
if long_signal and self.Position <= 0:
self.BuyMarket()
elif short_signal and self.Position >= 0:
self.SellMarket()
self._prev_bias_ema = bias_ema
self._prev_bias_sma = bias_sma
def CreateClone(self):
return bias_ratio_strategy()