Стратегия Breakdown Level Intraday
Стратегия размещает отложенные ордера на пробой максимумов и минимумов предыдущего дня в заданное время. Открывает длинную позицию при пробое максимума с учётом смещения Delta и короткую при пробое минимума. Управление позицией включает стоп-лосс, тейк-профит, перевод в безубыток и трейлинг-стоп.
Детали
- Условия входа:
- Long: цена пересекает максимум предыдущего дня +
Delta - Short: цена пересекает минимум предыдущего дня −
Delta
- Long: цена пересекает максимум предыдущего дня +
- Направление: Оба
- Условия выхода:
- Срабатывание стоп-лосса или тейк-профита
- Трейлинг-стоп или перевод в безубыток
- Стопы: пункты от цены входа
- Значения по умолчанию:
OrderTime= TimeSpan.ZeroDelta= 6StopLoss= 120TakeProfit= 90NoLoss= 0Trailing= 0Volume= 1m
- Фильтры:
- Категория: Пробой
- Направление: Оба
- Индикаторы: Нет
- Стопы: Да
- Сложность: Базовая
- Таймфрейм: Внутридневной
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Breakout strategy that trades previous high/low levels.
/// Goes long when price breaks above a recent high, short when breaks below recent low.
/// </summary>
public class BreakdownLevelIntradayStrategy : Strategy
{
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<decimal> _takeProfitPct;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _stopPrice;
private decimal _takePrice;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
/// <summary>Lookback period for high/low.</summary>
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
/// <summary>Stop loss percent.</summary>
public decimal StopLossPct { get => _stopLossPct.Value; set => _stopLossPct.Value = value; }
/// <summary>Take profit percent.</summary>
public decimal TakeProfitPct { get => _takeProfitPct.Value; set => _takeProfitPct.Value = value; }
/// <summary>Candle type.</summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BreakdownLevelIntradayStrategy()
{
_lookback = Param(nameof(Lookback), 60)
.SetGreaterThanZero()
.SetDisplay("Lookback", "Number of bars for high/low", "Parameters");
_stopLossPct = Param(nameof(StopLossPct), 0.5m)
.SetDisplay("Stop Loss %", "Stop loss as percent of price", "Risk");
_takeProfitPct = Param(nameof(TakeProfitPct), 1.0m)
.SetDisplay("Take Profit %", "Take profit as percent of price", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_stopPrice = 0m;
_takePrice = 0m;
_prevHigh = 0m;
_prevLow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var highest = new Highest { Length = Lookback };
var lowest = new Lowest { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (_hasPrev)
{
if (Position == 0)
{
// Breakout above previous highest level
if (close > _prevHigh * 1.002m)
{
BuyMarket();
_entryPrice = close;
_stopPrice = close * (1 - StopLossPct / 100m);
_takePrice = close * (1 + TakeProfitPct / 100m);
}
// Breakout below previous lowest level
else if (close < _prevLow * 0.998m)
{
SellMarket();
_entryPrice = close;
_stopPrice = close * (1 + StopLossPct / 100m);
_takePrice = close * (1 - TakeProfitPct / 100m);
}
}
else if (Position > 0)
{
if (close >= _takePrice || close <= _stopPrice)
{
SellMarket(Math.Abs(Position));
}
}
else if (Position < 0)
{
if (close <= _takePrice || close >= _stopPrice)
{
BuyMarket(Math.Abs(Position));
}
}
}
_prevHigh = high;
_prevLow = low;
_hasPrev = true;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class breakdown_level_intraday_strategy(Strategy):
def __init__(self):
super(breakdown_level_intraday_strategy, self).__init__()
self._lookback = self.Param("Lookback", 60)
self._stop_loss_pct = self.Param("StopLossPct", 0.5)
self._take_profit_pct = self.Param("TakeProfitPct", 1.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._entry_price = 0.0
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def Lookback(self):
return self._lookback.Value
@Lookback.setter
def Lookback(self, value):
self._lookback.Value = value
@property
def StopLossPct(self):
return self._stop_loss_pct.Value
@StopLossPct.setter
def StopLossPct(self, value):
self._stop_loss_pct.Value = value
@property
def TakeProfitPct(self):
return self._take_profit_pct.Value
@TakeProfitPct.setter
def TakeProfitPct(self, value):
self._take_profit_pct.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(breakdown_level_intraday_strategy, self).OnStarted2(time)
self._has_prev = False
self._entry_price = 0.0
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
highest = Highest()
highest.Length = self.Lookback
lowest = Lowest()
lowest.Length = self.Lookback
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle, high_val, low_val):
if candle.State != CandleStates.Finished:
return
high = float(high_val)
low = float(low_val)
close = float(candle.ClosePrice)
sl_pct = float(self.StopLossPct)
tp_pct = float(self.TakeProfitPct)
if self._has_prev:
if self.Position == 0:
if close > self._prev_high * 1.002:
self.BuyMarket()
self._entry_price = close
self._stop_price = close * (1.0 - sl_pct / 100.0)
self._take_price = close * (1.0 + tp_pct / 100.0)
elif close < self._prev_low * 0.998:
self.SellMarket()
self._entry_price = close
self._stop_price = close * (1.0 + sl_pct / 100.0)
self._take_price = close * (1.0 - tp_pct / 100.0)
elif self.Position > 0:
if close >= self._take_price or close <= self._stop_price:
self.SellMarket()
elif self.Position < 0:
if close <= self._take_price or close >= self._stop_price:
self.BuyMarket()
self._prev_high = high
self._prev_low = low
self._has_prev = True
def OnReseted(self):
super(breakdown_level_intraday_strategy, self).OnReseted()
self._entry_price = 0.0
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def CreateClone(self):
return breakdown_level_intraday_strategy()