Estrategia de Zonas SMC de Bloques de Órdenes
La estrategia identifica máximos y mínimos de swing para definir zonas premium y de descuento. Una media móvil simple actúa como filtro de tendencia y los bloques de órdenes recientes confirman las entradas. Las operaciones se ejecutan cuando el precio se mueve de una zona hacia el equilibrio con la confirmación del bloque de órdenes, usando un stop loss porcentual para protección.
Detalles
- Criterios de entrada:
- Cierre por debajo del equilibrio pero por encima de la zona de descuento y SMA para operaciones largas.
- Cierre por encima del equilibrio pero por debajo de la zona premium y SMA para operaciones cortas.
- El precio debe tocar el nivel del bloque de órdenes respectivo.
- Largo/Corto: Largo, corto o ambos, configurable.
- Criterios de salida: Señal opuesta o stop loss.
- Stops: Stop loss porcentual.
- Valores predeterminados:
SwingHighLength= 8SwingLowLength= 8SmaLength= 50OrderBlockLength= 20StopLossPercent= 2
- Filtros:
- Categoría: Tendencia y SMC
- Dirección: Definido por el usuario
- Indicadores: SMA, Highest, Lowest
- Stops: Sí
- Complejidad: Medio
- Marco temporal: Cualquiera
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// SMC Order Block Zones Strategy.
/// Uses BB as order block zones and SMA as equilibrium.
/// Buys in discount zone (below SMA near lower BB).
/// Sells in premium zone (above SMA near upper BB).
/// </summary>
public class SmcOrderBlockZonesStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<int> _bbLength;
private readonly StrategyParam<int> _cooldownBars;
private SimpleMovingAverage _sma;
private BollingerBands _bb;
private int _cooldownRemaining;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
public int BbLength
{
get => _bbLength.Value;
set => _bbLength.Value = value;
}
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
public SmcOrderBlockZonesStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_smaLength = Param(nameof(SmaLength), 50)
.SetGreaterThanZero()
.SetDisplay("SMA Length", "Equilibrium SMA period", "Indicators");
_bbLength = Param(nameof(BbLength), 20)
.SetGreaterThanZero()
.SetDisplay("BB Length", "Bollinger Bands period", "Indicators");
_cooldownBars = Param(nameof(CooldownBars), 10)
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_sma = null;
_bb = null;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_sma = new SimpleMovingAverage { Length = SmaLength };
_bb = new BollingerBands { Length = BbLength, Width = 2m };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(_sma, _bb, OnProcess)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _sma);
DrawIndicator(area, _bb);
DrawOwnTrades(area);
}
}
private void OnProcess(ICandleMessage candle, IIndicatorValue smaValue, IIndicatorValue bbValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_sma.IsFormed || !_bb.IsFormed)
return;
if (smaValue.IsEmpty || bbValue.IsEmpty)
return;
var sma = smaValue.ToDecimal();
var bb = (BollingerBandsValue)bbValue;
if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
return;
}
var price = candle.ClosePrice;
var equilibrium = sma;
// Discount zone: below SMA, near lower BB -> buy
if (price < equilibrium && price <= lower && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Premium zone: above SMA, near upper BB -> sell
else if (price > equilibrium && price >= upper && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Exit long: price returns above equilibrium
else if (Position > 0 && price > equilibrium)
{
SellMarket(Math.Abs(Position));
_cooldownRemaining = CooldownBars;
}
// Exit short: price returns below equilibrium
else if (Position < 0 && price < equilibrium)
{
BuyMarket(Math.Abs(Position));
_cooldownRemaining = CooldownBars;
}
}
}
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.Indicators import SimpleMovingAverage, BollingerBands, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class smc_order_block_zones_strategy(Strategy):
"""SMC Order Block Zones Strategy."""
def __init__(self):
super(smc_order_block_zones_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._sma_length = self.Param("SmaLength", 50) \
.SetDisplay("SMA Length", "Equilibrium SMA period", "Indicators")
self._bb_length = self.Param("BbLength", 20) \
.SetDisplay("BB Length", "Bollinger Bands period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 10) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._sma = None
self._bb = None
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(smc_order_block_zones_strategy, self).OnReseted()
self._sma = None
self._bb = None
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(smc_order_block_zones_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = int(self._sma_length.Value)
self._bb = BollingerBands()
self._bb.Length = int(self._bb_length.Value)
self._bb.Width = 2.0
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(self._sma, self._bb, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._sma)
self.DrawIndicator(area, self._bb)
self.DrawOwnTrades(area)
def _on_process(self, candle, sma_value, bb_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed or not self._bb.IsFormed:
return
if sma_value.IsEmpty or bb_value.IsEmpty:
return
if bb_value.UpBand is None or bb_value.LowBand is None:
return
sma_val = float(IndicatorHelper.ToDecimal(sma_value))
upper = float(bb_value.UpBand)
lower = float(bb_value.LowBand)
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
return
price = float(candle.ClosePrice)
equilibrium = sma_val
cooldown = int(self._cooldown_bars.Value)
if price < equilibrium and price <= lower and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._cooldown_remaining = cooldown
elif price > equilibrium and price >= upper and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._cooldown_remaining = cooldown
elif self.Position > 0 and price > equilibrium:
self.SellMarket(Math.Abs(self.Position))
self._cooldown_remaining = cooldown
elif self.Position < 0 and price < equilibrium:
self.BuyMarket(Math.Abs(self.Position))
self._cooldown_remaining = cooldown
def CreateClone(self):
return smc_order_block_zones_strategy()