先物エングルフィングローソク足サイズ戦略
選択した時間帯内でローソク足のレンジがティック閾値を超えると、1日に1回取引します。方向はローソク足の実体に従い、テイクプロフィットとストップロスで決済します。
詳細
- エントリー条件: 取引セッション内のローソク足レンジ(ティック数)。
- ロング/ショート: 両方。
- エグジット条件: テイクプロフィットまたはストップロス。
- ストップ: テイクプロフィットとストップロス。
- デフォルト値:
CandleType= 1 minuteCandleSizeThresholdTicks= 25TakeProfitTicks= 50StopLossTicks= 40StartHour= 7StartMinute= 0EndHour= 9EndMinute= 15
- フィルター:
- カテゴリ: パターン
- 方向: 両方
- インジケーター: Candlestick
- Stops: はい
- 複雑さ: 初心者
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Futures Engulfing Candle Size strategy.
/// Inside the StartHour:StartMinute..EndHour:EndMinute window (candle open time, UTC) the first candle whose high-low range reaches
/// CandleSizeThresholdTicks price steps opens one trade for the day in the direction of its body. The trade exits through a
/// take profit of TakeProfitTicks and a stop loss of StopLossTicks price steps.
/// </summary>
public class FuturesEngulfingCandleSizeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _candleSizeThresholdTicks;
private readonly StrategyParam<int> _takeProfitTicks;
private readonly StrategyParam<int> _stopLossTicks;
private readonly StrategyParam<int> _startHour;
private readonly StrategyParam<int> _startMinute;
private readonly StrategyParam<int> _endHour;
private readonly StrategyParam<int> _endMinute;
private DateTime _lastTradeDay;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Minimum candle range in price steps.
/// </summary>
public int CandleSizeThresholdTicks
{
get => _candleSizeThresholdTicks.Value;
set => _candleSizeThresholdTicks.Value = value;
}
/// <summary>
/// Take profit in price steps.
/// </summary>
public int TakeProfitTicks
{
get => _takeProfitTicks.Value;
set => _takeProfitTicks.Value = value;
}
/// <summary>
/// Stop loss in price steps.
/// </summary>
public int StopLossTicks
{
get => _stopLossTicks.Value;
set => _stopLossTicks.Value = value;
}
/// <summary>
/// Session start hour (UTC).
/// </summary>
public int StartHour
{
get => _startHour.Value;
set => _startHour.Value = value;
}
/// <summary>
/// Session start minute.
/// </summary>
public int StartMinute
{
get => _startMinute.Value;
set => _startMinute.Value = value;
}
/// <summary>
/// Session end hour (UTC).
/// </summary>
public int EndHour
{
get => _endHour.Value;
set => _endHour.Value = value;
}
/// <summary>
/// Session end minute.
/// </summary>
public int EndMinute
{
get => _endMinute.Value;
set => _endMinute.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public FuturesEngulfingCandleSizeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_candleSizeThresholdTicks = Param(nameof(CandleSizeThresholdTicks), 25)
.SetGreaterThanZero()
.SetDisplay("Candle Size Ticks", "Minimum candle range in price steps", "Signal");
_takeProfitTicks = Param(nameof(TakeProfitTicks), 50)
.SetNotNegative()
.SetDisplay("Take Profit Ticks", "Take profit in price steps", "Risk");
_stopLossTicks = Param(nameof(StopLossTicks), 40)
.SetNotNegative()
.SetDisplay("Stop Loss Ticks", "Stop loss in price steps", "Risk");
_startHour = Param(nameof(StartHour), 7)
.SetRange(0, 23)
.SetDisplay("Start Hour", "Session start hour (UTC)", "Session");
_startMinute = Param(nameof(StartMinute), 0)
.SetRange(0, 59)
.SetDisplay("Start Minute", "Session start minute", "Session");
_endHour = Param(nameof(EndHour), 9)
.SetRange(0, 23)
.SetDisplay("End Hour", "Session end hour (UTC)", "Session");
_endMinute = Param(nameof(EndMinute), 15)
.SetRange(0, 59)
.SetDisplay("End Minute", "Session end minute", "Session");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_lastTradeDay = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_lastTradeDay = default;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var step = Security?.PriceStep ?? 1m;
StartProtection(
new Unit(TakeProfitTicks * step, UnitTypes.Absolute),
new Unit(StopLossTicks * step, UnitTypes.Absolute),
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var time = candle.OpenTime;
var day = time.Date;
if (_lastTradeDay == day || Position != 0)
return;
var minutes = time.Hour * 60 + time.Minute;
if (minutes < StartHour * 60 + StartMinute || minutes > EndHour * 60 + EndMinute)
return;
var step = Security?.PriceStep ?? 1m;
if (step <= 0)
step = 1m;
if ((candle.HighPrice - candle.LowPrice) / step < CandleSizeThresholdTicks)
return;
if (candle.ClosePrice > candle.OpenPrice)
{
BuyMarket();
_lastTradeDay = day;
}
else if (candle.ClosePrice < candle.OpenPrice)
{
SellMarket();
_lastTradeDay = day;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class futures_engulfing_candle_size_strategy(Strategy):
"""
Futures Engulfing Candle Size strategy.
Inside the StartHour:StartMinute..EndHour:EndMinute window (candle open time, UTC) the first candle whose high-low range reaches
CandleSizeThresholdTicks price steps opens one trade for the day in the direction of its body. The trade exits through a
take profit of TakeProfitTicks and a stop loss of StopLossTicks price steps.
"""
def __init__(self):
super(futures_engulfing_candle_size_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._candle_size_threshold_ticks = self.Param("CandleSizeThresholdTicks", 25).SetGreaterThanZero().SetDisplay("Candle Size Ticks", "Minimum candle range in price steps", "Signal")
self._take_profit_ticks = self.Param("TakeProfitTicks", 50).SetNotNegative().SetDisplay("Take Profit Ticks", "Take profit in price steps", "Risk")
self._stop_loss_ticks = self.Param("StopLossTicks", 40).SetNotNegative().SetDisplay("Stop Loss Ticks", "Stop loss in price steps", "Risk")
self._start_hour = self.Param("StartHour", 7).SetRange(0, 23).SetDisplay("Start Hour", "Session start hour (UTC)", "Session")
self._start_minute = self.Param("StartMinute", 0).SetRange(0, 59).SetDisplay("Start Minute", "Session start minute", "Session")
self._end_hour = self.Param("EndHour", 9).SetRange(0, 23).SetDisplay("End Hour", "Session end hour (UTC)", "Session")
self._end_minute = self.Param("EndMinute", 15).SetRange(0, 59).SetDisplay("End Minute", "Session end minute", "Session")
self._last_trade_day = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(futures_engulfing_candle_size_strategy, self).OnReseted()
self._last_trade_day = None
def _price_step(self):
step = self.Security.PriceStep if self.Security is not None and self.Security.PriceStep is not None else None
step = float(step) if step is not None else 1.0
return step if step > 0 else 1.0
def OnStarted2(self, time):
super(futures_engulfing_candle_size_strategy, self).OnStarted2(time)
self._last_trade_day = None
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
step = self._price_step()
self.StartProtection(
Unit(Decimal(self._take_profit_ticks.Value * step), UnitTypes.Absolute),
Unit(Decimal(self._stop_loss_ticks.Value * step), UnitTypes.Absolute),
useMarketOrders=True)
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
if not self.IsFormedAndOnlineAndAllowTrading():
return
time = candle.OpenTime
day = time.Date
if self._last_trade_day == day or self.Position != 0:
return
minutes = time.Hour * 60 + time.Minute
start = self._start_hour.Value * 60 + self._start_minute.Value
end = self._end_hour.Value * 60 + self._end_minute.Value
if minutes < start or minutes > end:
return
if (float(candle.HighPrice) - float(candle.LowPrice)) / self._price_step() < self._candle_size_threshold_ticks.Value:
return
if candle.ClosePrice > candle.OpenPrice:
self.BuyMarket()
self._last_trade_day = day
elif candle.ClosePrice < candle.OpenPrice:
self.SellMarket()
self._last_trade_day = day
def CreateClone(self):
return futures_engulfing_candle_size_strategy()