Стратегия Highs Lows
Стратегия торгует на основе средних точек свечей относительно диапазона максимумов и минимумов.
Покупает, когда средняя текущей свечи ниже среднего между максимумом и минимумом, и нормализованное расстояние меньше LowThreshold. Закрывает длинную позицию, когда средняя выше этого значения и нормализованное расстояние превышает HighThreshold.
Детали
- Критерии входа: Средняя свечи ниже диапазона и нормализованное расстояние ниже LowThreshold.
- Длинные/короткие: только длинные.
- Критерии выхода: Средняя выше диапазона и нормализованное расстояние выше HighThreshold.
- Стопы: нет.
- Значения по умолчанию:
Range= 100LowThreshold= 15mHighThreshold= 85mCandleType= TimeSpan.FromMinutes(240)
- Фильтры:
- Категория: Диапазон
- Направление: Длинные
- Индикаторы: Highest, Lowest
- Стопы: Нет
- Сложность: Базовая
- Таймфрейм: Внутридневной (240m)
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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>
/// Highs Lows strategy.
/// Tracks the highest high and lowest low of the last Range candles. The candle midpoint is compared with the average of
/// these extremes, and their distance is normalized by half the range (0 at the average, 100 at an extreme). A long opens when the midpoint is
/// below the average and the normalized distance is below LowThreshold, and closes when the midpoint is above the average
/// and the normalized distance is above HighThreshold.
/// </summary>
public class HighsLowsStrategy : Strategy
{
private readonly StrategyParam<int> _range;
private readonly StrategyParam<decimal> _lowThreshold;
private readonly StrategyParam<decimal> _highThreshold;
private readonly StrategyParam<DataType> _candleType;
private Highest _highest;
private Lowest _lowest;
/// <summary>
/// Number of candles for the highest and lowest values.
/// </summary>
public int Range
{
get => _range.Value;
set => _range.Value = value;
}
/// <summary>
/// Normalized distance below which a long opens.
/// </summary>
public decimal LowThreshold
{
get => _lowThreshold.Value;
set => _lowThreshold.Value = value;
}
/// <summary>
/// Normalized distance above which the long closes.
/// </summary>
public decimal HighThreshold
{
get => _highThreshold.Value;
set => _highThreshold.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HighsLowsStrategy()
{
_range = Param(nameof(Range), 100)
.SetGreaterThanZero()
.SetDisplay("Range", "Number of candles for highest and lowest values", "Indicators");
_lowThreshold = Param(nameof(LowThreshold), 15m)
.SetDisplay("Low Threshold", "Normalized distance below which a long opens", "Signals");
_highThreshold = Param(nameof(HighThreshold), 85m)
.SetDisplay("High Threshold", "Normalized distance above which the long closes", "Signals");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(240).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();
_highest = null;
_lowest = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_highest = new Highest { Length = Range };
_lowest = new Lowest { Length = Range };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _highest);
DrawIndicator(area, _lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var highest = _highest.Process(candle.HighPrice, candle.OpenTime, true).ToDecimal();
var lowest = _lowest.Process(candle.LowPrice, candle.OpenTime, true).ToDecimal();
if (!_highest.IsFormed || !_lowest.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var width = highest - lowest;
if (width <= 0)
return;
var midpoint = (candle.HighPrice + candle.LowPrice) / 2;
var average = (highest + lowest) / 2;
// Distance from the average as a percentage of the half range: 0 at the average, 100 at an extreme.
var distance = Math.Abs(midpoint - average) / (width / 2) * 100m;
if (Position <= 0 && midpoint < average && distance < LowThreshold)
BuyMarket(Volume + Math.Abs(Position));
else if (Position > 0 && midpoint > average && distance > HighThreshold)
SellMarket(Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class highs_lows_strategy(Strategy):
"""
Highs Lows strategy.
Tracks the highest high and lowest low of the last Range candles. The candle midpoint is compared with the average of
these extremes, and their distance is normalized by half the range (0 at the average, 100 at an extreme). A long opens when the midpoint is
below the average and the normalized distance is below LowThreshold, and closes when the midpoint is above the average
and the normalized distance is above HighThreshold.
"""
def __init__(self):
super(highs_lows_strategy, self).__init__()
self._range = self.Param("Range", 100).SetGreaterThanZero().SetDisplay("Range", "Number of candles for highest and lowest values", "Indicators")
self._low_threshold = self.Param("LowThreshold", 15.0).SetDisplay("Low Threshold", "Normalized distance below which a long opens", "Signals")
self._high_threshold = self.Param("HighThreshold", 85.0).SetDisplay("High Threshold", "Normalized distance above which the long closes", "Signals")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(240))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._highest = None
self._lowest = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(highs_lows_strategy, self).OnReseted()
self._highest = None
self._lowest = None
def OnStarted2(self, time):
super(highs_lows_strategy, self).OnStarted2(time)
self._highest = Highest()
self._highest.Length = self._range.Value
self._lowest = Lowest()
self._lowest.Length = self._range.Value
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.DrawIndicator(area, self._highest)
self.DrawIndicator(area, self._lowest)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
highest = process_float(self._highest, candle.HighPrice, candle.OpenTime, True).GetValue[Decimal](None)
lowest = process_float(self._lowest, candle.LowPrice, candle.OpenTime, True).GetValue[Decimal](None)
if not self._highest.IsFormed or not self._lowest.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
width = highest - lowest
if width <= 0:
return
midpoint = (candle.HighPrice + candle.LowPrice) / Decimal(2)
average = (highest + lowest) / Decimal(2)
# Distance from the average as a percentage of the half range: 0 at the average, 100 at an extreme.
distance = abs(midpoint - average) / (width / Decimal(2)) * Decimal(100)
if self.Position <= 0 and midpoint < average and distance < Decimal(self._low_threshold.Value):
self.BuyMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and midpoint > average and distance > Decimal(self._high_threshold.Value):
self.SellMarket(self.Position)
def CreateClone(self):
return highs_lows_strategy()