RSI 专家策略
概述
RSI 专家策略 利用相对强弱指数 (RSI) 进行交易。当 RSI 穿越预设的超买或超卖水平时,策略在突破方向上开仓。
逻辑
- 对每根 K 线计算 RSI。
- 当 RSI 上穿 超卖水平时,开多单。
- 当 RSI 下穿 超买水平时,开空单。
- 在开新仓位前先关闭相反仓位。
- 可选的止盈、止损和跟踪止损保护可以启用。
该策略只处理已完成的 K 线,并使用 StockSharp 的高级 API 进行指标绑定。
参数
| 名称 | 说明 | 默认值 |
|---|---|---|
RsiPeriod |
RSI 计算周期 | 14 |
LevelUp |
触发做空的超买水平 | 70 |
LevelDown |
触发做多的超卖水平 | 30 |
TakeProfitPercent |
止盈百分比,0 表示禁用 |
0 |
StopLossPercent |
止损百分比,0 表示禁用 |
0 |
TrailingStopPercent |
跟踪止损百分比,0 表示禁用 |
0 |
CandleType |
用于计算的 K 线周期 | 1 分钟 |
说明
当 TrailingStopPercent 大于零时,策略使用 StartProtection 的内置机制,将止损转换为跟踪止损并自动跟随价格。
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>
/// RSI based strategy with overbought and oversold level cross signals.
/// Opens long when RSI crosses above oversold level, short when crosses below overbought level.
/// </summary>
public class RsiExpertStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _levelUp;
private readonly StrategyParam<decimal> _levelDown;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevRsi;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal LevelUp { get => _levelUp.Value; set => _levelUp.Value = value; }
public decimal LevelDown { get => _levelDown.Value; set => _levelDown.Value = value; }
public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RsiExpertStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Length of the RSI indicator", "Indicators");
_levelUp = Param(nameof(LevelUp), 70m)
.SetDisplay("RSI Overbought", "Upper RSI level triggering a short", "Indicators");
_levelDown = Param(nameof(LevelDown), 30m)
.SetDisplay("RSI Oversold", "Lower RSI level triggering a long", "Indicators");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 3m)
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).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();
_prevRsi = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(TakeProfitPercent, UnitTypes.Percent),
stopLoss: new Unit(StopLossPercent, UnitTypes.Percent),
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0m)
{
_prevRsi = rsiValue;
return;
}
var crossUp = _prevRsi < LevelDown && rsiValue > LevelDown;
var crossDown = _prevRsi > LevelUp && rsiValue < LevelUp;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevRsi = rsiValue;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class rsi_expert_strategy(Strategy):
def __init__(self):
super(rsi_expert_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Length of the RSI indicator", "Indicators")
self._level_up = self.Param("LevelUp", 70.0) \
.SetDisplay("RSI Overbought", "Upper RSI level triggering a short", "Indicators")
self._level_down = self.Param("LevelDown", 30.0) \
.SetDisplay("RSI Oversold", "Lower RSI level triggering a long", "Indicators")
self._take_profit_percent = self.Param("TakeProfitPercent", 3.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_rsi = 0.0
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def LevelUp(self):
return self._level_up.Value
@LevelUp.setter
def LevelUp(self, value):
self._level_up.Value = value
@property
def LevelDown(self):
return self._level_down.Value
@LevelDown.setter
def LevelDown(self, value):
self._level_down.Value = value
@property
def TakeProfitPercent(self):
return self._take_profit_percent.Value
@TakeProfitPercent.setter
def TakeProfitPercent(self, value):
self._take_profit_percent.Value = value
@property
def StopLossPercent(self):
return self._stop_loss_percent.Value
@StopLossPercent.setter
def StopLossPercent(self, value):
self._stop_loss_percent.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(rsi_expert_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(rsi, self.ProcessCandle) \
.Start()
self.StartProtection(
takeProfit=Unit(float(self.TakeProfitPercent), UnitTypes.Percent),
stopLoss=Unit(float(self.StopLossPercent), UnitTypes.Percent),
useMarketOrders=True
)
def ProcessCandle(self, candle, rsi_val):
if candle.State != CandleStates.Finished:
return
rsi_f = float(rsi_val)
if self._prev_rsi == 0.0:
self._prev_rsi = rsi_f
return
level_up = float(self.LevelUp)
level_down = float(self.LevelDown)
cross_up = self._prev_rsi < level_down and rsi_f > level_down
cross_down = self._prev_rsi > level_up and rsi_f < level_up
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_rsi = rsi_f
def OnReseted(self):
super(rsi_expert_strategy, self).OnReseted()
self._prev_rsi = 0.0
def CreateClone(self):
return rsi_expert_strategy()