Estrategia de Ruptura del Vela de las 2:45 AM
Esta estrategia intradía monitorea la vela de las 2:45 AM y opera rupturas de su máximo o mínimo dentro de las siguientes pocas barras. Cuando el precio supera el máximo de la vela, entra en una posición larga; cuando el precio cae por debajo del mínimo de la vela, abre una posición corta. Las posiciones se cierran al final de la ventana de observación si no ocurre una ruptura opuesta.
Detalles
- Criterios de entrada:
- Largo: El precio rompe por encima del máximo de la vela de las 2:45 AM dentro de las siguientes
LookForwardBarsvelas. - Corto: El precio rompe por debajo del mínimo de la vela de las 2:45 AM dentro de las siguientes
LookForwardBarsvelas.
- Largo: El precio rompe por encima del máximo de la vela de las 2:45 AM dentro de las siguientes
- Largo/Corto: Ambos.
- Criterios de salida:
- Fin de la ventana de observación o ruptura opuesta.
- Stops: Ninguno.
- Valores predeterminados:
TargetHour= 2TargetMinute= 45LookForwardBars= 2CandleType= velas de 45 minutos
- Filtros:
- Categoría: Ruptura basada en tiempo
- Dirección: Ambos
- Indicadores: Ninguno
- Stops: No
- Complejidad: Bajo
- Marco temporal: Intradía
- Estacionalidad: Sí
- 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>
/// Candle 245 Breakout Strategy.
/// Captures reference candle high/low, then trades breakout
/// in the next N bars. Uses EMA as trend filter.
/// </summary>
public class Candle245BreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _refPeriod;
private readonly StrategyParam<int> _lookForwardBars;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _cooldownBars;
private ExponentialMovingAverage _ema;
private decimal _refHigh;
private decimal _refLow;
private int _barsLeft;
private int _barCount;
private int _cooldownRemaining;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RefPeriod
{
get => _refPeriod.Value;
set => _refPeriod.Value = value;
}
public int LookForwardBars
{
get => _lookForwardBars.Value;
set => _lookForwardBars.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
public Candle245BreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_refPeriod = Param(nameof(RefPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Ref Period", "Every N bars capture reference candle", "Trading");
_lookForwardBars = Param(nameof(LookForwardBars), 3)
.SetGreaterThanZero()
.SetDisplay("Look Forward Bars", "Bars to watch for breakout", "Trading");
_emaLength = Param(nameof(EmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA period for trend filter", "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();
_ema = null;
_refHigh = 0;
_refLow = 0;
_barsLeft = 0;
_barCount = 0;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ema, OnProcess)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ema);
DrawOwnTrades(area);
}
}
private void OnProcess(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_ema.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
_barCount++;
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
if (_barsLeft > 0)
_barsLeft--;
return;
}
// Every RefPeriod bars, capture reference candle
if (_barCount % RefPeriod == 0)
{
_refHigh = candle.HighPrice;
_refLow = candle.LowPrice;
_barsLeft = LookForwardBars;
return;
}
if (_barsLeft <= 0)
return;
_barsLeft--;
var price = candle.ClosePrice;
// Breakout above reference high + EMA bullish
if (price > _refHigh && price > emaVal && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Breakout below reference low + EMA bearish
else if (price < _refLow && price < emaVal && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Close position at end of breakout window
if (_barsLeft == 0 && Position != 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
else
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class candle245_breakout_strategy(Strategy):
"""Candle 245 Breakout Strategy."""
def __init__(self):
super(candle245_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._ref_period = self.Param("RefPeriod", 10) \
.SetDisplay("Ref Period", "Every N bars capture reference candle", "Trading")
self._look_forward_bars = self.Param("LookForwardBars", 3) \
.SetDisplay("Look Forward Bars", "Bars to watch for breakout", "Trading")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "EMA period for trend filter", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 10) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._ema = None
self._ref_high = 0.0
self._ref_low = 0.0
self._bars_left = 0
self._bar_count = 0
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(candle245_breakout_strategy, self).OnReseted()
self._ema = None
self._ref_high = 0.0
self._ref_low = 0.0
self._bars_left = 0
self._bar_count = 0
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(candle245_breakout_strategy, self).OnStarted2(time)
self._ema = ExponentialMovingAverage()
self._ema.Length = int(self._ema_length.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
if not self._ema.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
self._bar_count += 1
ref_period = int(self._ref_period.Value)
look_fwd = int(self._look_forward_bars.Value)
cooldown = int(self._cooldown_bars.Value)
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
if self._bars_left > 0:
self._bars_left -= 1
return
if self._bar_count % ref_period == 0:
self._ref_high = float(candle.HighPrice)
self._ref_low = float(candle.LowPrice)
self._bars_left = look_fwd
return
if self._bars_left <= 0:
return
self._bars_left -= 1
price = float(candle.ClosePrice)
ema_v = float(ema_val)
if price > self._ref_high and price > ema_v and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._cooldown_remaining = cooldown
elif price < self._ref_low and price < ema_v and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._cooldown_remaining = cooldown
if self._bars_left == 0 and self.Position != 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
else:
self.BuyMarket(Math.Abs(self.Position))
self._cooldown_remaining = cooldown
def CreateClone(self):
return candle245_breakout_strategy()