ホーム
/
戦略のサンプル
GitHub で見る
OHLC Stochastic Strategy
Momentum-following strategy that uses the classic %K/%D stochastic oscillator on OHLC candles.
The algorithm reacts to crossovers in oversold/overbought zones and protects open trades with a configurable trailing stop measured in price steps.
Details
Core Idea : exploit the shift in momentum when stochastic %K crosses %D at extreme levels.
Entry Criteria :
Long :
%K crosses above %D and at least one of the lines is below the LevelDown threshold.
If a short position exists it is closed and reversed to long.
Short :
%K crosses below %D and at least one of the lines is above the LevelUp threshold.
If a long position exists it is closed and reversed to short.
Exit Criteria :
Trailing stop is hit (based on TrailingStopSteps distance and TrailingStepSteps improvement requirement).
Opposite entry signal appears, triggering a reversal.
Trailing Logic :
Distance and step are multiplied by the security PriceStep to convert pips/steps into absolute prices.
Stop only advances after the trade moves beyond TrailingStopSteps + TrailingStepSteps from the entry price.
Separate trailing logic for long and short sides.
Indicators :
Long/Short : Both.
Stops : Trailing stop only (no fixed SL/TP orders).
Position Sizing : Uses the strategy Volume parameter; reversals send Volume + |Position| to flip direction.
Default Parameters :
CandleType = TimeSpan.FromHours(12).TimeFrame()
KPeriod = 5
DPeriod = 3
Slowing = 3
LevelUp = 70
LevelDown = 30
TrailingStopSteps = 5 (price steps)
TrailingStepSteps = 2 (price steps)
Visualization :
Draws OHLC candles, stochastic indicator, and trade markers when charts are available.
Usage Notes
Configure the underlying security and timeframe before starting the strategy.
Adjust TrailingStopSteps according to the instrument tick size to reflect real pip distances.
The strategy calls StartProtection() so additional risk rules can be attached externally.
Works best on trending regimes where stochastic reversals lead price.
For intraday products lower timeframes may require reducing trailing distances to avoid premature exits.
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()