Stochastic Automated 策略
该策略在选定的K线周期上使用 Stochastic 振荡器。当 %K 与 %D 进入极端区域并发生交叉时触发交易。每笔交易都设置固定的止盈和止损,并使用移动止损来锁定利润。
逻辑
- 入场
- 做多:
- 两根K线之前,%K 与 %D 都低于
OverSold。 - 两根K线之前 %D 在 %K 之上,而一根K线之前在 %K 之下。
- %D 正在上升。
- 两根K线之前,%K 与 %D 都低于
- 做空:
- 两根K线之前,%K 与 %D 都高于
OverBought。 - 两根K线之前 %D 在 %K 之下,而一根K线之前在 %K 之上。
- %D 正在下降。
- 两根K线之前,%K 与 %D 都高于
- 做多:
- 出场
- 当 Stochastic 脱离极端区域或 %D 反转时平仓。
- 如果价格回撤超过
TrailingStop,移动止损将退出头寸。 - 每笔交易都应用全局
TakeProfit与StopLoss。
参数
| 名称 | 说明 |
|---|---|
CandleType |
Stochastic 计算所用的K线周期。 |
KPeriod |
%K 的回溯周期。 |
DPeriod |
%D 的平滑周期。 |
Slowing |
%K 的附加平滑。 |
OverBought |
超买阈值。 |
OverSold |
超卖阈值。 |
TakeProfit |
入场到止盈的距离(价格单位)。 |
StopLoss |
入场到止损的距离(价格单位)。 |
TrailingStop |
移动止损的距离(价格单位)。 |
指标
StochasticOscillator
备注
- 代码注释为英文。
- 暂无 Python 版本。
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>
/// Stochastic oscillator based strategy.
/// Buys on K/D crossover in oversold, sells on crossover in overbought.
/// </summary>
public class StochasticAutomatedStrategy : Strategy
{
private readonly StrategyParam<int> _kPeriod;
private readonly StrategyParam<int> _dPeriod;
private readonly StrategyParam<decimal> _overBought;
private readonly StrategyParam<decimal> _overSold;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevK;
private decimal? _prevD;
public int KPeriod { get => _kPeriod.Value; set => _kPeriod.Value = value; }
public int DPeriod { get => _dPeriod.Value; set => _dPeriod.Value = value; }
public decimal OverBought { get => _overBought.Value; set => _overBought.Value = value; }
public decimal OverSold { get => _overSold.Value; set => _overSold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public StochasticAutomatedStrategy()
{
_kPeriod = Param(nameof(KPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("%K Period", "Stochastic %K period", "Stochastic");
_dPeriod = Param(nameof(DPeriod), 3)
.SetGreaterThanZero()
.SetDisplay("%D Period", "Stochastic %D period", "Stochastic");
_overBought = Param(nameof(OverBought), 80m)
.SetDisplay("Overbought", "Overbought threshold", "Stochastic");
_overSold = Param(nameof(OverSold), 20m)
.SetDisplay("Oversold", "Oversold threshold", "Stochastic");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Time frame", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevK = _prevD = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var stochastic = new StochasticOscillator();
stochastic.K.Length = KPeriod;
stochastic.D.Length = DPeriod;
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(stochastic, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, stochastic);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var stoch = (IStochasticOscillatorValue)stochValue;
if (stoch.K is not decimal k || stoch.D is not decimal d)
return;
if (_prevK is decimal pk && _prevD is decimal pd)
{
// Buy: K crosses above D in oversold zone
if (pk <= pd && k > d && pd < OverSold && Position <= 0)
BuyMarket();
// Sell: K crosses below D in overbought zone
if (pk >= pd && k < d && pd > OverBought && Position >= 0)
SellMarket();
}
_prevK = k;
_prevD = d;
}
}
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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class stochastic_automated_strategy(Strategy):
def __init__(self):
super(stochastic_automated_strategy, self).__init__()
self._k_period = self.Param("KPeriod", 14) \
.SetDisplay("%K Period", "Stochastic %K period", "Stochastic")
self._d_period = self.Param("DPeriod", 3) \
.SetDisplay("%D Period", "Stochastic %D period", "Stochastic")
self._over_bought = self.Param("OverBought", 80.0) \
.SetDisplay("Overbought", "Overbought threshold", "Stochastic")
self._over_sold = self.Param("OverSold", 20.0) \
.SetDisplay("Oversold", "Oversold threshold", "Stochastic")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Time frame", "General")
self._prev_k = None
self._prev_d = None
@property
def k_period(self):
return self._k_period.Value
@property
def d_period(self):
return self._d_period.Value
@property
def over_bought(self):
return self._over_bought.Value
@property
def over_sold(self):
return self._over_sold.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(stochastic_automated_strategy, self).OnReseted()
self._prev_k = None
self._prev_d = None
def OnStarted2(self, time):
super(stochastic_automated_strategy, self).OnStarted2(time)
stochastic = StochasticOscillator()
stochastic.K.Length = self.k_period
stochastic.D.Length = self.d_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(stochastic, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, stochastic)
self.DrawOwnTrades(area)
def process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k = stoch_value.K
d = stoch_value.D
if k is None or d is None:
return
k = float(k)
d = float(d)
if self._prev_k is not None and self._prev_d is not None:
ob = float(self.over_bought)
os_val = float(self.over_sold)
# Buy: K crosses above D in oversold zone
if self._prev_k <= self._prev_d and k > d and self._prev_d < os_val and self.Position <= 0:
self.BuyMarket()
# Sell: K crosses below D in overbought zone
if self._prev_k >= self._prev_d and k < d and self._prev_d > ob and self.Position >= 0:
self.SellMarket()
self._prev_k = k
self._prev_d = d
def CreateClone(self):
return stochastic_automated_strategy()