2時45分ローソク足ブレイクアウト戦略
このイントラデイ戦略は、午前2時45分のローソク足を監視し、次の数本のバー内でその高値または安値のブレイクアウトを取引します。価格がローソク足の高値を超えるとロングポジションに入り、価格がローソク足の安値を下回るとショートポジションを開きます。観察ウィンドウの終わりまでに反対方向のブレイクアウトが発生しない場合、ポジションは決済されます。
詳細
- エントリー条件:
- ロング: 次の
LookForwardBars本のローソク足内で価格が2時45分ローソク足の高値を上抜け。 - ショート: 次の
LookForwardBars本のローソク足内で価格が2時45分ローソク足の安値を下抜け。
- ロング: 次の
- ロング/ショート: 両方。
- エグジット条件:
- 観察ウィンドウの終了または反対方向のブレイクアウト。
- ストップ: なし。
- デフォルト値:
TargetHour= 2TargetMinute= 45LookForwardBars= 2CandleType= 45分足
- フィルター:
- カテゴリ: 時間ベースのブレイクアウト
- 方向: 両方
- インジケーター: なし
- ストップ: いいえ
- 複雑さ: 低
- 時間軸: イントラデイ
- 季節性: はい
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Candle 2:45 Breakout Strategy.
/// The candle covering TargetHour:TargetMinute (UTC) sets the reference high and low. During the next LookForwardBars candles a
/// close above the high goes long and a close below the low goes short, reversing an opposite position. Any position is
/// closed when the observation window ends.
/// </summary>
public class Candle245BreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _targetHour;
private readonly StrategyParam<int> _targetMinute;
private readonly StrategyParam<int> _lookForwardBars;
private readonly StrategyParam<DataType> _candleType;
private decimal? _refHigh;
private decimal? _refLow;
private int _barsLeft;
/// <summary>
/// Hour of the reference candle (UTC).
/// </summary>
public int TargetHour
{
get => _targetHour.Value;
set => _targetHour.Value = value;
}
/// <summary>
/// Minute of the reference candle.
/// </summary>
public int TargetMinute
{
get => _targetMinute.Value;
set => _targetMinute.Value = value;
}
/// <summary>
/// Candles after the reference candle during which breakouts are traded.
/// </summary>
public int LookForwardBars
{
get => _lookForwardBars.Value;
set => _lookForwardBars.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public Candle245BreakoutStrategy()
{
_targetHour = Param(nameof(TargetHour), 2)
.SetRange(0, 23)
.SetDisplay("Target Hour", "Hour of the reference candle (UTC)", "Session");
_targetMinute = Param(nameof(TargetMinute), 45)
.SetRange(0, 59)
.SetDisplay("Target Minute", "Minute of the reference candle", "Session");
_lookForwardBars = Param(nameof(LookForwardBars), 2)
.SetGreaterThanZero()
.SetDisplay("Look Forward Bars", "Candles after the reference candle during which breakouts are traded", "Trading");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(45).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_refHigh = null;
_refLow = null;
_barsLeft = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_refHigh = null;
_refLow = null;
_barsLeft = 0;
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;
// With frames that do not start exactly at the target time, the candle covering it is the reference.
var target = candle.OpenTime.Date + new TimeSpan(TargetHour, TargetMinute, 0);
var frame = CandleType.Arg is TimeSpan tf ? tf : TimeSpan.Zero;
var isReference = candle.OpenTime == target || (candle.OpenTime < target && target < candle.OpenTime + frame);
if (isReference)
{
_refHigh = candle.HighPrice;
_refLow = candle.LowPrice;
_barsLeft = LookForwardBars;
return;
}
if (_barsLeft <= 0 || _refHigh is not decimal high || _refLow is not decimal low)
return;
_barsLeft--;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_barsLeft == 0)
{
// The observation window ends with this candle.
if (Position > 0)
SellMarket(Position);
else if (Position < 0)
BuyMarket(-Position);
return;
}
var close = candle.ClosePrice;
if (close > high && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (close < low && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
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
class candle245_breakout_strategy(Strategy):
"""
Candle 2:45 Breakout Strategy.
The candle covering TargetHour:TargetMinute (UTC) sets the reference high and low. During the next LookForwardBars candles a
close above the high goes long and a close below the low goes short, reversing an opposite position. Any position is
closed when the observation window ends.
"""
def __init__(self):
super(candle245_breakout_strategy, self).__init__()
self._target_hour = self.Param("TargetHour", 2).SetRange(0, 23).SetDisplay("Target Hour", "Hour of the reference candle (UTC)", "Session")
self._target_minute = self.Param("TargetMinute", 45).SetRange(0, 59).SetDisplay("Target Minute", "Minute of the reference candle", "Session")
self._look_forward_bars = self.Param("LookForwardBars", 2).SetGreaterThanZero().SetDisplay("Look Forward Bars", "Candles after the reference candle during which breakouts are traded", "Trading")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(45))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._ref_high = None
self._ref_low = None
self._bars_left = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(candle245_breakout_strategy, self).OnReseted()
self._ref_high = None
self._ref_low = None
self._bars_left = 0
def OnStarted2(self, time):
super(candle245_breakout_strategy, self).OnStarted2(time)
self._ref_high = None
self._ref_low = None
self._bars_left = 0
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
# With frames that do not start exactly at the target time, the candle covering it is the reference.
open_time = candle.OpenTime
target = open_time.Date.Add(TimeSpan(self._target_hour.Value, self._target_minute.Value, 0))
arg = self.candle_type.Arg
frame = arg if isinstance(arg, TimeSpan) else TimeSpan.Zero
is_reference = open_time == target or (open_time < target and target < open_time.Add(frame))
if is_reference:
self._ref_high = float(candle.HighPrice)
self._ref_low = float(candle.LowPrice)
self._bars_left = self._look_forward_bars.Value
return
if self._bars_left <= 0 or self._ref_high is None or self._ref_low is None:
return
self._bars_left -= 1
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self._bars_left == 0:
# The observation window ends with this candle.
if self.Position > 0:
self.SellMarket(self.Position)
elif self.Position < 0:
self.BuyMarket(-self.Position)
return
close = float(candle.ClosePrice)
if close > self._ref_high and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif close < self._ref_low and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return candle245_breakout_strategy()