Estrategia de Ruptura Diaria
Esta estrategia opera rupturas desde la apertura diaria. Al comienzo de cada nuevo día se almacena el precio de apertura. Cuando el precio se aleja de este nivel por un número de puntos definido por el usuario, y la barra anterior está dentro de un rango de tamaño configurable, la estrategia entra en la dirección de la ruptura.
Lógica de entrada
- Si la barra anterior es alcista y el precio sube por encima de la apertura diaria en Break Point puntos, se abre una posición larga.
- Si la barra anterior es bajista y el precio cae por debajo de la apertura diaria en Break Point puntos, se abre una posición corta.
- El tamaño de la barra anterior debe estar entre Last Bar Min y Last Bar Max puntos.
- El nivel de ruptura debe estar dentro del cuerpo de la barra anterior.
Gestión del riesgo
- El Take Profit y Stop Loss opcionales se miden en puntos desde el precio de entrada.
- Se puede activar un trailing stop con los parámetros Trailing Start, Trailing Stop y Trailing Step. Cuando el precio se mueve a favor en Trailing Start puntos, el stop se establece en Trailing Stop puntos desde la entrada y luego sigue con incrementos de Trailing Step.
Parámetros
| Nombre |
Descripción |
| Candle Type |
Marco temporal de las velas procesadas. |
| Break Point |
Distancia desde la apertura diaria para activar una operación (puntos). |
| Last Bar Min |
Tamaño mínimo de la barra anterior (puntos). |
| Last Bar Max |
Tamaño máximo de la barra anterior (puntos). |
| Trailing Start |
Movimiento de precio para iniciar el trailing stop (puntos). |
| Trailing Stop |
Distancia inicial del trailing stop (puntos). |
| Trailing Step |
Paso para mover el trailing stop (puntos). |
| Take Profit |
Distancia de take profit (puntos). |
| Stop Loss |
Distancia de stop loss (puntos). |
Notas
La estrategia opera solo en velas terminadas y utiliza órdenes de mercado para entradas y salidas. Almacena variables internas para los datos de la barra anterior y el nivel del trailing stop.
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>
/// Daily breakout strategy based on the previous bar size and daily open.
/// </summary>
public class DailyBreakpointStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _breakPointPct;
private readonly StrategyParam<decimal> _lastBarMinPct;
private readonly StrategyParam<decimal> _lastBarMaxPct;
private readonly StrategyParam<decimal> _takeProfitPct;
private readonly StrategyParam<decimal> _stopLossPct;
private decimal _prevOpen;
private decimal _prevClose;
private DateTimeOffset _prevTime;
private bool _hasPrev;
private decimal _dayOpen;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal BreakPointPct { get => _breakPointPct.Value; set => _breakPointPct.Value = value; }
public decimal LastBarMinPct { get => _lastBarMinPct.Value; set => _lastBarMinPct.Value = value; }
public decimal LastBarMaxPct { get => _lastBarMaxPct.Value; set => _lastBarMaxPct.Value = value; }
public decimal TakeProfitPct { get => _takeProfitPct.Value; set => _takeProfitPct.Value = value; }
public decimal StopLossPct { get => _stopLossPct.Value; set => _stopLossPct.Value = value; }
public DailyBreakpointStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_breakPointPct = Param(nameof(BreakPointPct), 0.3m)
.SetDisplay("Break Point %", "Breakout offset as % of price", "General");
_lastBarMinPct = Param(nameof(LastBarMinPct), 0.05m)
.SetDisplay("Min Bar %", "Minimal bar size as % of price", "Filter");
_lastBarMaxPct = Param(nameof(LastBarMaxPct), 1.0m)
.SetDisplay("Max Bar %", "Maximum bar size as % of price", "Filter");
_takeProfitPct = Param(nameof(TakeProfitPct), 2m)
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_stopLossPct = Param(nameof(StopLossPct), 1m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = default;
_prevClose = default;
_prevTime = default;
_hasPrev = default;
_dayOpen = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartProtection(
takeProfit: new Unit(TakeProfitPct, UnitTypes.Percent),
stopLoss: new Unit(StopLossPct, UnitTypes.Percent),
isStopTrailing: true,
useMarketOrders: true);
var sub = SubscribeCandles(CandleType);
sub.Bind(Process).Start();
}
private void Process(ICandleMessage c)
{
if (c.State != CandleStates.Finished)
return;
if (!_hasPrev || c.OpenTime.Date != _prevTime.Date)
_dayOpen = c.OpenPrice;
if (Position == 0 && _hasPrev)
{
var price = c.ClosePrice;
var lastSize = Math.Abs(_prevClose - _prevOpen);
var minSize = LastBarMinPct / 100m * price;
var maxSize = LastBarMaxPct / 100m * price;
var offset = BreakPointPct / 100m * price;
var breakBuy = _dayOpen + offset;
var breakSell = _dayOpen - offset;
if (_prevClose > _prevOpen && price - _dayOpen >= offset &&
lastSize >= minSize && lastSize <= maxSize &&
breakBuy >= _prevOpen && breakBuy <= _prevClose)
{
BuyMarket();
}
else if (_prevClose < _prevOpen && _dayOpen - price >= offset &&
lastSize >= minSize && lastSize <= maxSize &&
breakSell <= _prevOpen && breakSell >= _prevClose)
{
SellMarket();
}
}
_prevOpen = c.OpenPrice;
_prevClose = c.ClosePrice;
_prevTime = c.OpenTime;
_hasPrev = true;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class daily_breakpoint_strategy(Strategy):
def __init__(self):
super(daily_breakpoint_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._break_point_pct = self.Param("BreakPointPct", 0.3) \
.SetDisplay("Break Point %", "Breakout offset as % of price", "General")
self._last_bar_min_pct = self.Param("LastBarMinPct", 0.05) \
.SetDisplay("Min Bar %", "Minimal bar size as % of price", "Filter")
self._last_bar_max_pct = self.Param("LastBarMaxPct", 1.0) \
.SetDisplay("Max Bar %", "Maximum bar size as % of price", "Filter")
self._take_profit_pct = self.Param("TakeProfitPct", 2.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._stop_loss_pct = self.Param("StopLossPct", 1.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._prev_open = 0.0
self._prev_close = 0.0
self._prev_time = None
self._has_prev = False
self._day_open = 0.0
@property
def candle_type(self):
return self._candle_type.Value
@property
def break_point_pct(self):
return self._break_point_pct.Value
@property
def last_bar_min_pct(self):
return self._last_bar_min_pct.Value
@property
def last_bar_max_pct(self):
return self._last_bar_max_pct.Value
@property
def take_profit_pct(self):
return self._take_profit_pct.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
def OnReseted(self):
super(daily_breakpoint_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_close = 0.0
self._prev_time = None
self._has_prev = False
self._day_open = 0.0
def OnStarted2(self, time):
super(daily_breakpoint_strategy, self).OnStarted2(time)
self.StartProtection(
takeProfit=Unit(self.take_profit_pct, UnitTypes.Percent),
stopLoss=Unit(self.stop_loss_pct, UnitTypes.Percent),
isStopTrailing=True,
useMarketOrders=True)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process).Start()
def process(self, candle):
if candle.State != CandleStates.Finished:
return
if not self._has_prev or candle.OpenTime.Date != self._prev_time.Date:
self._day_open = float(candle.OpenPrice)
if self.Position == 0 and self._has_prev:
price = float(candle.ClosePrice)
last_size = abs(self._prev_close - self._prev_open)
min_size = float(self.last_bar_min_pct) / 100.0 * price
max_size = float(self.last_bar_max_pct) / 100.0 * price
offset = float(self.break_point_pct) / 100.0 * price
break_buy = self._day_open + offset
break_sell = self._day_open - offset
if (self._prev_close > self._prev_open and price - self._day_open >= offset and
last_size >= min_size and last_size <= max_size and
break_buy >= self._prev_open and break_buy <= self._prev_close):
self.BuyMarket()
elif (self._prev_close < self._prev_open and self._day_open - price >= offset and
last_size >= min_size and last_size <= max_size and
break_sell <= self._prev_open and break_sell >= self._prev_close):
self.SellMarket()
self._prev_open = float(candle.OpenPrice)
self._prev_close = float(candle.ClosePrice)
self._prev_time = candle.OpenTime
self._has_prev = True
def CreateClone(self):
return daily_breakpoint_strategy()