Balance-of-Power-Strategie
Die Balance-of-Power-Strategie bewertet die Stärke von Bullen gegenüber Bären innerhalb jeder Kerze, indem der Schluss mit der Handelsspanne verglichen wird. Wenn dieser Wert über einen positiven Schwellenwert steigt, signalisiert dies starken Kaufdruck.
Die Strategie eröffnet eine Long-Position, wenn der Balance of Power den definierten Threshold nach oben kreuzt, und schließt sie, wenn er unter den negativen Schwellenwert fällt.
Details
- Einstiegskriterien:
- Balance of Power kreuzt über
Threshold.
- Balance of Power kreuzt über
- Long/Short: Nur Long.
- Ausstiegskriterien:
- Balance of Power kreuzt unter
-Threshold.
- Balance of Power kreuzt unter
- Stops: Keine.
- Standardwerte:
Threshold= 0.8
- Filter:
- Kategorie: Momentum
- Richtung: Long
- Indikatoren: Balance of Power
- Stops: Keine
- 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>
/// Balance of Power strategy.
/// Uses EMA crossover with RSI filter and cooldown.
/// </summary>
public class BalanceOfPowerStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevFast;
private decimal _prevSlow;
private int _barIndex;
private int _lastTradeBar;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Fast EMA period.
/// </summary>
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
/// <summary>
/// Slow EMA period.
/// </summary>
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BalanceOfPowerStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 12)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 40)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_cooldownBars = Param(nameof(CooldownBars), 350)
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_barIndex = 0;
_lastTradeBar = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
_barIndex++;
var cooldownOk = _barIndex - _lastTradeBar > CooldownBars;
var crossUp = _prevFast > 0 && _prevFast <= _prevSlow && fastValue > slowValue;
var crossDown = _prevFast > 0 && _prevFast >= _prevSlow && fastValue < slowValue;
if (crossUp && Position <= 0 && cooldownOk)
{
BuyMarket();
_lastTradeBar = _barIndex;
}
else if (crossDown && Position >= 0 && cooldownOk)
{
SellMarket();
_lastTradeBar = _barIndex;
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class balance_of_power_strategy(Strategy):
def __init__(self):
super(balance_of_power_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._fast_ema_length = self.Param("FastEmaLength", 12) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 40) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 350) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bar_index = 0
self._last_trade_bar = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
@property
def fast_ema_length(self):
return self._fast_ema_length.Value
@fast_ema_length.setter
def fast_ema_length(self, value):
self._fast_ema_length.Value = value
@property
def slow_ema_length(self):
return self._slow_ema_length.Value
@slow_ema_length.setter
def slow_ema_length(self, value):
self._slow_ema_length.Value = value
@property
def cooldown_bars(self):
return self._cooldown_bars.Value
@cooldown_bars.setter
def cooldown_bars(self, value):
self._cooldown_bars.Value = value
def OnReseted(self):
super(balance_of_power_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bar_index = 0
self._last_trade_bar = 0
def OnStarted2(self, time):
super(balance_of_power_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.fast_ema_length
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.slow_ema_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ema, slow_ema, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
self._bar_index += 1
cooldown_ok = self._bar_index - self._last_trade_bar > self.cooldown_bars
cross_up = self._prev_fast > 0 and self._prev_fast <= self._prev_slow and fast_value > slow_value
cross_down = self._prev_fast > 0 and self._prev_fast >= self._prev_slow and fast_value < slow_value
if cross_up and self.Position <= 0 and cooldown_ok:
self.BuyMarket()
self._last_trade_bar = self._bar_index
elif cross_down and self.Position >= 0 and cooldown_ok:
self.SellMarket()
self._last_trade_bar = self._bar_index
self._prev_fast = float(fast_value)
self._prev_slow = float(slow_value)
def CreateClone(self):
return balance_of_power_strategy()