Главная
/
Примеры стратегий
Открыть на GitHub
Стратегия OHLC Stochastic
Стратегия следования за импульсом, использующая классический стохастик %K/%D на OHLC-свечах.
Алгоритм реагирует на пересечения в зонах перекупленности/перепроданности и защищает сделки наращиваемым трейлинг-стопом в ценовых шагах.
Подробности
Основная идея : использовать смену импульса, когда %K пересекает %D в экстремальных зонах.
Условия входа :
Лонг :
%K пересекает %D снизу вверх, и хотя бы одна линия находится ниже порога LevelDown.
Если открыта короткая позиция, она закрывается и сразу переворачивается в лонг.
Шорт :
%K пересекает %D сверху вниз, и хотя бы одна линия выше порога LevelUp.
Если открыта длинная позиция, она закрывается и переворачивается в шорт.
Условия выхода :
Срабатывание трейлинг-стопа (использует расстояние TrailingStopSteps и требование улучшения TrailingStepSteps).
Появление противоположного сигнала, запускающего разворот позиции.
Логика трейлинга :
Расстояние и шаг домножаются на PriceStep инструмента для перевода пипсов/шагов в абсолютную цену.
Стоп подтягивается только после того, как цена уйдёт дальше, чем TrailingStopSteps + TrailingStepSteps от входа.
Отдельная обработка трейлинга для длинной и короткой стороны.
Индикаторы :
Направление : Лонг и шорт.
Стопы : Только трейлинг (фиксированных SL/TP нет).
Размер позиции : Используется параметр Volume; при развороте отправляется объём Volume + |Position|.
Параметры по умолчанию :
CandleType = TimeSpan.FromHours(12).TimeFrame()
KPeriod = 5
DPeriod = 3
Slowing = 3
LevelUp = 70
LevelDown = 30
TrailingStopSteps = 5 (ценовых шага)
TrailingStepSteps = 2 (ценовых шага)
Визуализация :
При наличии графиков отображаются свечи, стохастик и сделки.
Рекомендации по использованию
Перед запуском задайте нужный инструмент и таймфрейм.
Подгоняйте TrailingStopSteps под шаг цены инструмента, чтобы соответствовать реальным пипсам.
Метод StartProtection() позволяет добавлять внешние правила управления риском.
Наиболее эффективна на трендовых участках, где стохастик заранее показывает разворот импульса.
Для внутридневных инструментов стоит уменьшать расстояние трейлинга, чтобы избежать преждевременных выходов.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class OhlcStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private decimal? _prevRsi;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public OhlcStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero().SetDisplay("RSI Period", "RSI lookback", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = null;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevRsi = rsiVal; return; }
if (_prevRsi == null) { _prevRsi = rsiVal; return; }
if (_prevRsi.Value < 30m && rsiVal >= 30m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevRsi.Value > 70m && rsiVal <= 70m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevRsi = rsiVal;
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ohlc_stochastic_strategy(Strategy):
def __init__(self):
super(ohlc_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI lookback", "Indicators")
self._prev_rsi = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
def OnReseted(self):
super(ohlc_stochastic_strategy, self).OnReseted()
self._prev_rsi = None
def OnStarted2(self, time):
super(ohlc_stochastic_strategy, self).OnStarted2(time)
self._prev_rsi = None
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self._prev_rsi is None:
self._prev_rsi = rv
return
if self._prev_rsi < 30.0 and rv >= 30.0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_rsi > 70.0 and rv <= 70.0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_rsi = rv
def CreateClone(self):
return ohlc_stochastic_strategy()