Estrategia de la Primera Vela de 30m del HSI
Esta estrategia captura el máximo y mínimo de los primeros 30 minutos tras la apertura de la sesión de Hong Kong y opera rupturas en un gráfico de 5 minutos. Solo se permite una operación por día.
Detalles
- Criterios de entrada:
- Largo: el precio rompe por encima del máximo de los primeros 30 minutos durante la sesión.
- Corto: el precio cae por debajo del mínimo de los primeros 30 minutos durante la sesión.
- Largo/Corto: Ambos lados.
- Criterios de salida:
- Stop loss en el lado opuesto del rango.
- Take profit a una distancia del tamaño del rango multiplicado por
RiskRewarddesde la entrada.
- Stops: Sí.
- Valores predeterminados:
RiskReward= 1.CandleType= TimeSpan.FromMinutes(5).TimeFrame().
- Filtros:
- Categoría: Ruptura
- Dirección: Ambos
- Indicadores: Price action
- Stops: Sí
- Complejidad: Básico
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// HSI First 30m Candle strategy.
/// Records the high and low of the first 30 minutes after the Hong Kong session opens (09:30 HKT, 01:30 UTC). During the rest of
/// the session a close above that high goes long and a close below that low goes short, at most one trade per day. The stop sits
/// at the opposite side of the range and the target at the range size multiplied by RiskReward from the entry.
/// </summary>
public class HsiFirst30mCandleStrategy : Strategy
{
private static readonly TimeSpan _sessionOpen = new(1, 30, 0);
private static readonly TimeSpan _rangeEnd = new(2, 0, 0);
private static readonly TimeSpan _sessionClose = new(8, 0, 0);
private readonly StrategyParam<decimal> _riskReward;
private readonly StrategyParam<DataType> _candleType;
private DateTime _currentDay;
private decimal? _rangeHigh;
private decimal? _rangeLow;
private bool _tradedToday;
private decimal _stopPrice;
private decimal _takePrice;
/// <summary>
/// Target distance as a multiple of the range size.
/// </summary>
public decimal RiskReward
{
get => _riskReward.Value;
set => _riskReward.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HsiFirst30mCandleStrategy()
{
_riskReward = Param(nameof(RiskReward), 1m)
.SetGreaterThanZero()
.SetDisplay("Risk Reward", "Target distance as a multiple of the range size", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
ResetState();
}
private void ResetState()
{
_currentDay = default;
_rangeHigh = null;
_rangeLow = null;
_tradedToday = false;
_stopPrice = 0m;
_takePrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var openTime = candle.OpenTime;
var day = openTime.Date;
var timeOfDay = openTime.TimeOfDay;
if (day != _currentDay)
{
_currentDay = day;
_rangeHigh = null;
_rangeLow = null;
_tradedToday = false;
}
if (timeOfDay >= _sessionOpen && timeOfDay < _rangeEnd)
{
_rangeHigh = _rangeHigh is decimal h ? Math.Max(h, candle.HighPrice) : candle.HighPrice;
_rangeLow = _rangeLow is decimal l ? Math.Min(l, candle.LowPrice) : candle.LowPrice;
return;
}
if (Position > 0)
{
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
SellMarket(Position);
return;
}
if (Position < 0)
{
if (candle.HighPrice >= _stopPrice || candle.LowPrice <= _takePrice)
BuyMarket(-Position);
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_tradedToday || timeOfDay < _rangeEnd || timeOfDay >= _sessionClose)
return;
if (_rangeHigh is not decimal high || _rangeLow is not decimal low)
return;
var range = high - low;
if (range <= 0)
return;
var close = candle.ClosePrice;
if (close > high)
{
BuyMarket(Volume);
_stopPrice = low;
_takePrice = close + range * RiskReward;
_tradedToday = true;
}
else if (close < low)
{
SellMarket(Volume);
_stopPrice = high;
_takePrice = close - range * RiskReward;
_tradedToday = true;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
# Minutes after midnight UTC.
SESSION_OPEN = 90.0
RANGE_END = 120.0
SESSION_CLOSE = 480.0
class hsi_first_30m_candle_strategy(Strategy):
"""
HSI First 30m Candle strategy.
Records the high and low of the first 30 minutes after the Hong Kong session opens (09:30 HKT, 01:30 UTC). During the rest of
the session a close above that high goes long and a close below that low goes short, at most one trade per day. The stop sits
at the opposite side of the range and the target at the range size multiplied by RiskReward from the entry.
"""
def __init__(self):
super(hsi_first_30m_candle_strategy, self).__init__()
self._risk_reward = self.Param("RiskReward", 1.0).SetGreaterThanZero().SetDisplay("Risk Reward", "Target distance as a multiple of the range size", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._current_day = None
self._range_high = None
self._range_low = None
self._traded_today = False
self._stop_price = 0.0
self._take_price = 0.0
def OnReseted(self):
super(hsi_first_30m_candle_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(hsi_first_30m_candle_strategy, self).OnStarted2(time)
self._reset_state()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
open_time = candle.OpenTime
day = open_time.Date
time_of_day = open_time.TimeOfDay.TotalMinutes
if self._current_day is None or day != self._current_day:
self._current_day = day
self._range_high = None
self._range_low = None
self._traded_today = False
high_price = float(candle.HighPrice)
low_price = float(candle.LowPrice)
if time_of_day >= SESSION_OPEN and time_of_day < RANGE_END:
self._range_high = high_price if self._range_high is None else max(self._range_high, high_price)
self._range_low = low_price if self._range_low is None else min(self._range_low, low_price)
return
if self.Position > 0:
if low_price <= self._stop_price or high_price >= self._take_price:
self.SellMarket(self.Position)
return
if self.Position < 0:
if high_price >= self._stop_price or low_price <= self._take_price:
self.BuyMarket(-self.Position)
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self._traded_today or time_of_day < RANGE_END or time_of_day >= SESSION_CLOSE:
return
if self._range_high is None or self._range_low is None:
return
high = self._range_high
low = self._range_low
rng = high - low
if rng <= 0:
return
close = float(candle.ClosePrice)
rr = float(self._risk_reward.Value)
if close > high:
self.BuyMarket(self.Volume)
self._stop_price = low
self._take_price = close + rng * rr
self._traded_today = True
elif close < low:
self.SellMarket(self.Volume)
self._stop_price = high
self._take_price = close - rng * rr
self._traded_today = True
def CreateClone(self):
return hsi_first_30m_candle_strategy()