问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

量化交易——RSI策略(vectorbt实现)

创作时间:
作者:
@小白创作中心

量化交易——RSI策略(vectorbt实现)

引用
CSDN
1.
https://blog.csdn.net/qq_41072222/article/details/144646756

本文是一篇关于使用vectorbt库实现RSI策略的量化交易教程。文章详细介绍了pandas中drop()和set_index()函数的使用,以及RSI指标的计算步骤和意义。文章通过具体代码示例展示了如何使用vectorbt实现RSI策略,并对回测结果进行了分析。

关于本文所使用数据的说明

由于vbt官方文档提供的入门案例使用的数据是通过其内置的yfinance包获取,在国内无法直接访问,故本文将原数据替换为更容易获取的国内数据。本文使用的数据是通过tushare获取的A股日线行情数据,具体参数如下图所示:

一、pandas常用函数

(1)drop()

函数语法:

DataFrame.drop(
    labels=None, 
    axis=0, 
    index=None,
    columns=None,
    level=None, 
    inplace=False, 
    errors='raise'
)

参数说明:

  • labels:待删除的行名or列名;
  • axis:删除时所参考的轴,0为行,1为列;
  • index:待删除的行名
  • columns:待删除的列名
  • level:多级列表时使用,暂时不作说明
  • inplace:布尔值,默认为False,若为False,则返回的是一个copy;若为True,返回的是删除相应数据后的数据

(1)set_index()

功能:指定数据表中的某列或指定某个数组列表为DataFrame行索引。

函数语法

DataFrame.set_index(keys, *, drop=True, append=False, inplace=False, verify_integrity=False)

参数说明:

  • key:数据表中的某列/列标签列表/数组列表,需要设置为索引的列。
  • drop:删除用作新索引的列,默认为True,删除。
  • append:是否将列附加到现有索引,默认为False,否。
  • inplace:表示当前操作是否对原数据重新,默认为False,否。
  • verify_integrity:检查新索引的副本。否则,请将检查推迟到必要时进行。将其设置为False,将提高该方法的性能,默认为False。

保留到小数点后两位

df.apply(lambda x:round(x,2))

二、RSI策略

(1)RSI计算步骤

  • 确定时间周期:通常设定为14天,但也可以根据需要选择6、12、24等其他周期。
  • 计算涨幅和跌幅:
  • 涨幅:每日收盘价高于前一日收盘价的差额。
  • 跌幅:每日收盘价低于前一日收盘价的差额(取正值)。
  • 计算N日内涨幅之和与跌幅之和:将时间周期内每日的涨幅和跌幅分别累加。
  • 计算RS值:用N日内涨幅之和的平均值除以N日内跌幅之和的平均值。
  • 计算RSI值:将RS值代入RSI公式,得到RSI值。

(2)RSI取值范围及意义

RSI的取值范围在0到100之间,通常以30和70作为超卖和超买的标志线,或以20和80作为超卖和超买的标志线。具体解读如下:

  • 当RSI值超过70或80时,市场处于超买状态,可能会有下跌的趋势。
  • 当RSI值低于30或20时,市场处于超卖状态,可能会有上涨的趋势。
  • 当RSI值在50附近时,代表多空力量均衡。

RSI策略的vectorbt实现方法

第一步:RSI.run()

只需要传入股票每日收盘价,窗口默认为14天。

rsi=vbt.RSI.run(price,window=14)
print('rsi:',rsi.rsi)

特别提示:查看rsi的值请使用rsi.rsi

官方文档详见下图:

第二步:设置买入和卖出条件

rsi值下穿30线时买入,上穿70时卖出。下图为rsi_above和rsi_below函数参数。

#下穿rsi=30线时买入
entries=rsi.rsi_crossed_below(30)
print(entries)
#上穿rsi=70时卖出
exits=rsi.rsi_crossed_above(70)
print(exits)

函数名 说明
rsi_above() 开区间上穿特定值时,返回True,反之返回False
rsi_closed_above() 闭区间上穿特定值时,返回True,反之返回False
rsi_crossed_above() 刚好上穿特定值时,返回True,反之返回False
rsi_below() 开区间下穿特定值时,返回True,反之返回False
rsi_closed_below() 闭区间下穿特定值时,返回True,反之返回False
rsi_crossed_below() 刚好下穿特定值时,返回True,反之返回False

第三步:模拟投资【vbt.Portfolio.from_signals()】

该函数通过买入和卖出信号来模拟投资。代码如下:

pf=vbt.Portfolio.from_signals(price,entries=entries,exits=exits,init_cash=10000)

该函数的参数详情如下:

Portfolio.from_signals(
    close,
    entries=None,
    exits=None,
    short_entries=None,
    short_exits=None,
    signal_func_nb=no_signal_func_nb,
    signal_args=(),
    size=None,
    size_type=None,
    price=None,
    fees=None,
    fixed_fees=None,
    slippage=None,
    min_size=None,
    max_size=None,
    size_granularity=None,
    reject_prob=None,
    lock_cash=None,
    allow_partial=None,
    raise_reject=None,
    log=None,
    accumulate=None,
    upon_long_conflict=None,
    upon_short_conflict=None,
    upon_dir_conflict=None,
    upon_opposite_entry=None,
    direction=None,
    val_price=None,
    open=None,
    high=None,
    low=None,
    sl_stop=None,
    sl_trail=None,
    tp_stop=None,
    stop_entry_price=None,
    stop_exit_price=None,
    upon_stop_exit=None,
    upon_stop_update=None,
    adjust_sl_func_nb=no_adjust_sl_func_nb,
    adjust_sl_args=(),
    adjust_tp_func_nb=no_adjust_tp_func_nb,
    adjust_tp_args=(),
    use_stops=None,
    init_cash=None,
    cash_sharing=None,
    call_seq=None,
    ffill_val_price=None,
    update_value=None,
    max_orders=None,
    max_logs=None,
    seed=None,
    group_by=None,
    broadcast_named_args=None,
    broadcast_kwargs=None,
    template_mapping=None,
    wrapper_kwargs=None,
    freq=None,
    attach_call_seq=None,
    **kwargs
)

第四步:查看回测结果

print(pf.stats().apply(lambda x:round(x,2)))

运行结果:

Start                         20230804.00
End                           20241220.00
Period                             335.00
Start Value                      10000.00
End Value                        10041.23
Total Return [%]                     0.41
Benchmark Return [%]                -5.53
Max Gross Exposure [%]             100.00
Total Fees Paid                      0.00
Max Drawdown [%]                    21.89
Max Drawdown Duration              313.00
Total Trades                         5.00
Total Closed Trades                  5.00
Total Open Trades                    0.00
Open Trade PnL                       0.00
Win Rate [%]                        60.00
Best Trade [%]                      13.20
Worst Trade [%]                    -14.94
Avg Winning Trade [%]                7.12
Avg Losing Trade [%]                -9.31
Avg Winning Trade Duration          25.67
Avg Losing Trade Duration           77.00
Profit Factor                        1.02
Expectancy                           8.25
dtype: float64

第五步:画图

pf.plot().show()

运行结果:



完整代码

import vectorbt as vbt
import pandas as pd
pd=pd.read_csv("stock_data/000001.SZ.csv",names=['index','trade_date','open','close','low','high','vol','x','macd','dif','dea'])
#删除index列
pd=pd.drop(columns='index')
#pd.index=pd['trade_date']
#设置trade_date列为行索引
pd=pd.set_index('trade_date')
price=pd['close']#每日收盘价
#设计RSI策略
'''
窗口:14天
超卖:30
超买:70
'''
rsi=vbt.RSI.run(price,window=14)
print('rsi:',rsi.rsi)
#下穿rsi=30线时买入
entries=rsi.rsi_crossed_below(30)
print(entries)
#上穿rsi=70时卖出
exits=rsi.rsi_crossed_above(70)
print(exits)
#回测
pf=vbt.Portfolio.from_signals(price,entries=entries,exits=exits,init_cash=10000)
#
print(pf.stats().apply(lambda x:round(x,2)))
print(pf.total_return)
pf.plot().show()

参考文献

  • pandas drop()函数详解
  • tushare官网
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号