问题描述
请为我编写一个RSI交易策略,当RSI指标进入超卖区(例如低于30)时买入,进入超买区(例如高于70)时卖出。
解决方案
这是一个基于PTrade API实现的经典RSI(相对强弱指标)均值回归策略。
策略逻辑
- 买入条件:当RSI指标低于30(超卖区)时,认为股价可能反弹,执行买入。
- 卖出条件:当RSI指标高于70(超买区)时,认为股价可能回调,清仓卖出。
- 资金管理:买入时使用当前所有可用资金(全仓),卖出时清空该股票持仓。
策略代码
def initialize(context):
"""
初始化函数,设置股票池和全局变量
"""
# 设置我们要操作的股票,这里以恒生电子为例
g.security = ['600570.SS']
# 设置股票池
set_universe(g.security)
# 设定RSI参数
g.rsi_period = 14 # RSI计算周期,通常为14
g.buy_threshold = 30 # 超卖阈值,低于此值买入
g.sell_threshold = 70 # 超买阈值,高于此值卖出
def handle_data(context, data):
"""
盘中运行函数,每个单位时间(如每天)运行一次
"""
# 遍历股票池中的每一只股票
for stock in g.security:
# 如果股票停牌,则跳过
if data[stock].is_open == 0:
continue
# 1. 获取历史收盘价数据
# 获取过去100个交易日的数据,确保有足够的数据计算RSI
# 注意:get_history返回的是DataFrame,我们需要.values转为numpy数组
h = get_history(100, '1d', 'close', security_list=stock)
# 检查数据长度是否足够,防止新股数据不足导致报错
if len(h) < g.rsi_period + 1:
continue
close_prices = h['close'].values
# 2. 计算RSI指标
# PTrade内置了get_RSI函数,直接调用即可
# get_RSI返回的是一个numpy数组,包含时间序列上的RSI值
rsi_values = get_RSI(close_prices, n=g.rsi_period)
# 获取最新的RSI值(数组的最后一个元素)
if rsi_values is None or len(rsi_values) == 0:
continue
current_rsi = rsi_values[-1]
# 获取当前持仓和资金情况
position = get_position(stock)
cash = context.portfolio.cash
# 3. 交易逻辑判断
# 信号:RSI < 30 (超卖),且当前有资金 -> 买入
if current_rsi < g.buy_threshold:
if cash > 0:
# 用所有现金买入
order_value(stock, cash)
log.info("买入 %s, 当前RSI: %.2f, 触发超卖买入信号" % (stock, current_rsi))
# 信号:RSI > 70 (超买),且当前有持仓 -> 卖出
elif current_rsi > g.sell_threshold:
if position.amount > 0:
# 卖出所有持仓
order_target(stock, 0)
log.info("卖出 %s, 当前RSI: %.2f, 触发超买卖出信号" % (stock, current_rsi))
代码关键点说明
-
get_history的使用:- RSI计算需要一定长度的历史数据。虽然RSI周期是14,但为了计算的平滑和准确性,建议获取更多的数据点(代码中获取了100条)。
get_history获取的数据是DataFrame格式,计算指标时通常需要使用.values转换为numpy数组。
-
get_RSI函数:- 这是PTrade内置的技术指标计算函数,无需手动编写RSI公式。
- 它接受价格序列和周期参数
n,返回计算好的RSI序列。
-
交易执行:
order_value(stock, cash):按金额下单,这里示例为全仓买入。order_target(stock, 0):调整持仓到目标数量,设置为0即为清仓卖出。
-
兼容性:
- 代码遵循Python 3.5语法规范(如使用
%进行字符串格式化),完全兼容PTrade环境。
- 代码遵循Python 3.5语法规范(如使用
如何回测
在PTrade客户端中,新建一个策略,将上述代码复制进去,设置回测频率为“日线”,选择好回测时间段(例如过去一年),即可开始回测。