在 GitHub 上查看
RSI水平策略
概述
RSI水平策略 是 MetaTrader 5 "RSI Levels" 智能交易顾问的直接移植版本。策略在指定周期上监控单一品种,当相对强弱指数(RSI)穿越可配置的超买和超卖阈值时采取行动。系统假设当RSI进入极值区域后价格会回归均值:当指标跌破超卖水平时开多,当指标升破超买水平时开空。任意时刻只允许持有一个方向的仓位,新的信号会先平掉相反持仓再入场。
交易逻辑
- RSI计算 – 使用可配置周期在工作时间框上计算RSI,只在K线收盘后评估信号。
- 做多条件 – 当前RSI收在超卖线以下、上一笔RSI在超卖线上方时触发。如果存在空单则立即平仓,否则按风险模型开多。
- 做空条件 – 当前RSI收在超买线上方、上一笔RSI在超买线下方时触发。如持有多单则先平仓,再按风险模型开空。
- 止损 – 按配置的点数距离在入场价附近设置固定止损;当该参数为零时表示禁用止损。
- 止盈 – 按配置的点数距离在入场价附近设置固定止盈;为零时表示禁用止盈。
- 仓位管理 – 任何仓位平仓后都会重置内部状态,确保下一次信号在干净环境下执行。
仓位管理
仓位大小由“单笔风险百分比”参数决定。算法取组合权益乘以风险百分比得到风险资金,再除以止损距离的货币价值(止损点数 × 最小价格变动价值)。结果向下取整到可交易的手数步长,并受到品种最小/最大手数限制。如果缺少 PriceStep 或 StepPrice 等关键信息,策略会记录警告并退回到最小手数。
参数
| 参数 |
默认值 |
说明 |
CandleType |
1小时周期 |
用于订阅K线并计算RSI的时间框。 |
RsiPeriod |
14 |
RSI指标的周期长度。 |
OverboughtLevel |
70 |
定义超买区域的RSI阈值。 |
OversoldLevel |
30 |
定义超卖区域的RSI阈值。 |
RiskPercent |
2 |
每笔交易风险占权益的百分比。 |
StopLossPoints |
500 |
以点数表示的止损距离,设为0可禁用。 |
TakeProfitPoints |
1000 |
以点数表示的止盈距离,设为0可禁用。 |
实践提示
- 请确保品种已经配置
PriceStep、StepPrice、MinVolume 和 VolumeStep,否则风险头寸计算会退回到保守的最小手数。
- 策略通过
SubscribeCandles 和 Bind 获取指标数值,无需手动访问历史数据,符合高阶API规范。
- 止损与止盈基于收盘K线判断,跳空或滑点可能导致实际成交价偏离设定价。
- 建议在M15、H1或H4等较稳定周期上运行。如使用更低周期,需额外过滤噪声。
使用方法
- 将策略附加到目标证券和组合。
- 根据品种波动性调整RSI阈值及风险参数。
- 启动策略,并关注日志中关于缺失品种信息的警告。
- 根据回测或实盘结果微调止损、止盈或阈值设置。
该StockSharp实现完整复现了原始MetaTrader逻辑,并通过标准策略参数开放了所有核心配置。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// RSI Levels strategy: RSI oversold/overbought mean reversion.
/// Buys when RSI < 35. Sells when RSI > 65.
/// </summary>
public class RsiLevelsStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public RsiLevelsStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
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 rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (rsi < 30m && Position <= 0)
{
BuyMarket();
}
else if (rsi > 70m && Position >= 0)
{
SellMarket();
}
}
}
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 rsi_levels_strategy(Strategy):
def __init__(self):
super(rsi_levels_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._rsi = None
@property
def rsi_period(self):
return self._rsi_period.Value
def OnReseted(self):
super(rsi_levels_strategy, self).OnReseted()
self._rsi = None
def OnStarted2(self, time):
super(rsi_levels_strategy, self).OnStarted2(time)
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromHours(1)))
subscription.Bind(self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._rsi.IsFormed:
return
rsi = float(rsi_value)
if rsi < 30.0 and self.Position <= 0:
self.BuyMarket()
elif rsi > 70.0 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return rsi_levels_strategy()