布林带多头策略
该策略在价格收于布林带下轨且 RSI 进入超卖区时买入,当价格回到中轨时平仓。
细节
- 入场条件:
- 价格收于布林带下轨。
- RSI 低于超卖水平。
- 多空方向:仅做多。
- 出场条件:
- 价格收于或高于布林带中轨。
- 止损:无。
- 默认值:
BbLength= 10BbDeviation= 2RsiLength= 14RsiOversold= 30
- 筛选:
- 类型:均值回归
- 方向:多头
- 指标:布林带、RSI
- 止损:否
- 复杂度:低
- 时间框架:任意
- 季节性:否
- 神经网络:否
- 背离:否
- 风险等级:中
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>
/// Bollinger Bands Long strategy.
/// Long only: buys when the close is below the lower Bollinger band and RSI is below RsiOversold, and closes the long once the close
/// is at or above the middle band.
/// </summary>
public class BollingerBandsLongStrategy : Strategy
{
private readonly StrategyParam<int> _bbLength;
private readonly StrategyParam<decimal> _bbDeviation;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Bollinger period.
/// </summary>
public int BbLength
{
get => _bbLength.Value;
set => _bbLength.Value = value;
}
/// <summary>
/// Bollinger standard deviation multiplier.
/// </summary>
public decimal BbDeviation
{
get => _bbDeviation.Value;
set => _bbDeviation.Value = value;
}
/// <summary>
/// RSI period.
/// </summary>
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
/// <summary>
/// RSI oversold level.
/// </summary>
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BollingerBandsLongStrategy()
{
_bbLength = Param(nameof(BbLength), 10)
.SetGreaterThanZero()
.SetDisplay("BB Length", "Bollinger period", "Bollinger");
_bbDeviation = Param(nameof(BbDeviation), 2m)
.SetGreaterThanZero()
.SetDisplay("BB Deviation", "Bollinger standard deviation multiplier", "Bollinger");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "RSI");
_rsiOversold = Param(nameof(RsiOversold), 30m)
.SetDisplay("RSI Oversold", "RSI oversold level", "RSI");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).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 OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bollinger = new BollingerBands { Length = BbLength, Width = BbDeviation };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bollinger, rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
var oscillators = CreateChartArea();
if (oscillators != null)
{
DrawIndicator(oscillators, rsi);
}
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bollingerValue, IIndicatorValue rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!bollingerValue.IsFormed || !rsiValue.IsFormed)
return;
var bands = (BollingerBandsValue)bollingerValue;
if (bands.LowBand is not decimal lower || bands.MovingAverage is not decimal middle)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var rsi = rsiValue.GetValue<decimal>();
if (Position == 0 && close < lower && rsi < RsiOversold)
BuyMarket(Volume);
else if (Position > 0 && close >= middle)
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 BollingerBands, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class bollinger_bands_long_strategy(Strategy):
"""
Bollinger Bands Long strategy.
Long only: buys when the close is below the lower Bollinger band and RSI is below RsiOversold, and closes the long once the close
is at or above the middle band.
"""
def __init__(self):
super(bollinger_bands_long_strategy, self).__init__()
self._bb_length = self.Param("BbLength", 10).SetGreaterThanZero().SetDisplay("BB Length", "Bollinger period", "Bollinger")
self._bb_deviation = self.Param("BbDeviation", 2.0).SetGreaterThanZero().SetDisplay("BB Deviation", "Bollinger standard deviation multiplier", "Bollinger")
self._rsi_length = self.Param("RsiLength", 14).SetGreaterThanZero().SetDisplay("RSI Length", "RSI period", "RSI")
self._rsi_oversold = self.Param("RsiOversold", 30.0).SetDisplay("RSI Oversold", "RSI oversold level", "RSI")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(bollinger_bands_long_strategy, self).OnStarted2(time)
bollinger = BollingerBands()
bollinger.Length = self._bb_length.Value
bollinger.Width = Decimal(self._bb_deviation.Value)
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bollinger, rsi, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bollinger)
self.DrawOwnTrades(area)
oscillators = self.CreateChartArea()
if oscillators is not None:
self.DrawIndicator(oscillators, rsi)
def _process_candle(self, candle, bollinger_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not bollinger_value.IsFormed or not rsi_value.IsFormed:
return
lower = bollinger_value.LowBand
middle = bollinger_value.MovingAverage
if lower is None or middle is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
rsi = rsi_value.GetValue[Decimal](None)
if self.Position == 0 and close < lower and rsi < Decimal(self._rsi_oversold.Value):
self.BuyMarket(self.Volume)
elif self.Position > 0 and close >= middle:
self.SellMarket(self.Position)
def CreateClone(self):
return bollinger_bands_long_strategy()