Estratégia da Primeira Vela de 30m do HSI
Esta estratégia captura a máxima e mínima dos primeiros 30 minutos após a abertura da sessão de Hong Kong e opera rompimentos em um gráfico de 5 minutos. Apenas uma operação é permitida por dia.
Detalhes
- Critérios de entrada:
- Comprado: o preço rompe acima da máxima dos primeiros 30 minutos durante a sessão.
- Vendido: o preço cai abaixo da mínima dos primeiros 30 minutos durante a sessão.
- Comprado/Vendido: Ambos os lados.
- Critérios de saída:
- Stop loss no lado oposto do intervalo.
- Take profit a uma distância do tamanho do intervalo multiplicado por
RiskRewarddesde a entrada.
- Stops: Sim.
- Valores padrão:
RiskReward= 1.CandleType= TimeSpan.FromMinutes(5).TimeFrame().
- Filtros:
- Categoria: Rompimento
- Direção: Ambos
- Indicadores: Price action
- Stops: Sim
- Complexidade: Básico
- Período: Intradiário
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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()