[Practice] 使用相对强弱指数的算法交易策略

1. 算法交易

读书的时候上过一门算法交易的课程,讲的就是如何使用各种算法进行股票以及期货(指)的投资。投资算法五花八门,在真实的交易中一般需要参考各种因素选择一种或多种投资策略进行交易。然而这还远远不够,记得那门课的教授当时说过"In Chinese stock market, monkey would earn more than a professional trader(在中国股票市场,猴子有可能比专业交易员赚的还多哦),所以说,本文仅供娱乐,无任何投资参考价值。
在本文中,我使用搜狐的接口获取一定时间内特定股票的数据,API地址,源代码地址: https://github.com/missweetcxx/algo_trading

2. 相对强弱指数

相对强弱指数(Relative Strength Index,以下简称RSI)最初由经济学家J.Welles Wilder在上世纪七十年代提出。作为计量超买超卖状况的“警示符”,RSI在证券投资领域十分常用,下面就和大家介绍一下RSI。
RSI主要衡量某股(指)了近期涨幅与跌幅的比例,它的计算公式如下:

RSI = 100 - 100/(1+RS)
其中,RS = 近n天收盘价上涨的指数移动平均/近n天收盘价下跌的指数移动平均

由于指数移动平均的计算比较麻烦,而采用简单移动平均(SMA)方法的卡特勒相对强弱指数(Culter's RSI)由于计算结果与其差别并不显著,所以我们采用后者来进行分析,即 RS = SMA(up_trend)/SMA(down_trend)

举个栗子吧,某股票在14天内的价格趋势如下:


1.首先将上涨的数据累加再除天数14,得到16/14=1.143;
2.再将下跌的数据累加除以天数14,得到23/14=1.643;
3.那么,RS=1.143/1.1643=0.696,
4.RSI = 100 - 100/(1+0.696)=41.038。

所以这14天的相对强弱指数就是41.038。

上代码(price_list为所选区间内的收盘价集合):

rise_sum, down_sum = 0, 0
for i in range(len(price_list) - 1):
    balance = price_list[i + 1] - price_list[i]
    if balance > 0:
        rise_sum += balance
    else:
        down_sum -= balance
if (rise_sum + down_sum) != 0:
    rsi = 100 * rise_sum / (rise_sum + down_sum)
else:
    rsi = 50    # 防止除数为零
3. 交易策略

J.Welles Wilder采用14天RSI提出以下交易策略:当RSI低于30时,该股票处于“超卖状态”,此时是买入的好时机;而当RSI高于70时,该股处于“超买状态”,此时应当酌情卖出。
根据这一交易策略,我直接将沪指(000001.SS)这只股票作为实验对象,交易跨度为2018年2月23日的前100个交易日至2018年2月23日,当其14日RSI高于70时卖出100股,低于30时买入100股(均以收盘价为准),在不考虑手续费以及平仓的情况下,我的收益是1498元。

我打算改进一下我的交易策略,首先在牛市和熊市中,应该使用不同的交易策略;其次,70和30的界限太过单一,我觉得可以根据RSI的值确定买入以及卖出的量,比如30买入100股,20买入150股,40买入50股...

首先,该如何确定是牛市还是熊市呢,网上众说纷纭,而我的策略是得出14日以及200日沪指的简单移动平均(SMA),若SMA(5)>SMA(200)则是牛市,反之则是熊市,可能有些不太精准,暂且这样吧。

其次,要定下卖出(买入)的量与RSI的公式:
volume = int((RSI-50)/20) * basic_volume * alpha
其中basic_volume是用户输入的基本交易单位(这里我输入100),alpha是市场系数,暂且定为熊市卖0.9买1,牛市卖1买0.9,贴代码(其中MarketStatus即为牛熊市):

def rsi_strategy_executor(date, volume):
    market_status = StockMarket.market_status(date)
    rsi = StockIndex.rsi(date)
    grades = int((rsi - 50) / 10)/2
    if market_status == MarketStatus.BEAR:
        if grades >= 0:
            TradeUtil.sell(volume * grades * 0.9, date)
        else:
            TradeUtil.buy(volume * grades, date)
    elif market_status == MarketStatus.BULL:
        if grades >= 0:
            TradeUtil.sell(volume * grades, date)
        else:
            TradeUtil.buy(volume * grades * 0.9, date)

再次计算发现收益为2562,居然赚了,简直不敢相信。

4. 开挂的RSI2

2008年11月,恰逢经济危机,而正在此时Larry Connors提出了RSI2的观点,并通过历史数据验证RSI2比RSI更加有效,并且更加适用于高频交易。Larry Connors的交易策略主要为以下四步:

  1. 确定牛熊市
    在这里,Larry Connors将价格高于SMA(200)的时刻判断为牛市,低于SMA(200)的时刻判断为熊市,这里似乎不应称为牛熊市,但我也想不出其它更贴切的词了。

  2. 确定买入、卖出时机
    Connors认为RSI在[0,10]的区间是非常好的买入机会,且越低收益越大;而[90,100]的区间则应当沽空,且越高持仓的风险越大。

  3. 收盘价 or 开盘价?
    对于股市中的算法交易,一般由两种操作方式,在收盘前买入/卖出,或是在开盘后集合竞价后买入/卖出,这两种方式更有利弊,在这里我选择第一种操作方式,且不考虑交易确认的时间。

  4. 设定’退出点‘
    股市有风险,入市需谨慎。设定’退出点‘才能有效把控风险,从而止损。Connors认为当股价高于SMA(5)时多头看跌,应及时停止买入,而当股价低于SMA(5)时空头看跌,及时停止卖出。

根据Connors的RSI2交易策略,我尝试着对100天的沪指进行了模拟交易,其中我还是根据RSI2的值以及市场形势定了购买量。牛市alpha为1,熊市alpha为0.9。
volume = ((RSI2 - 90) / 10 + 1)* basic_volume * alpha

贴代码,其中MarketCondition即为上述‘退出点’:

def rsi2_strategy_executor(date, volume):
    market_status = StockMarket.connors_market_status(date)
    exit_point = StockMarket.connors_exit_condition(date)
    rsi_2 = StockIndex.rsi_2(date)

    if rsi_2 > 90 and exit_point != MarketCondition.LONG:
        alpha = 0.9 if market_status == MarketStatus.BULL else 1
        grade = (rsi_2 - 90) / 10 + 1
        TradeUtil.sell(volume * grade * alpha, date)
    elif rsi_2 < 10 and exit_point != MarketCondition.SHORT:
        alpha = 1 if market_status == MarketStatus.BULL else 0.9
        grade = (10 - rsi_2) / 10 + 1
        TradeUtil.buy(volume * grade * alpha, date)

很无奈地发现,居然没有赚。不知道是不是因为界限设的太高,调整了一下代码继续操作,当RSI2在[80,90)以及(10,20]间时买入/卖出量呈线性增长,RSI2高于90或低于10时则呈指数增长:

def rsi2_strategy_executor(date, volume):
    market_status = StockMarket.connors_market_status(date)
    exit_point = StockMarket.connors_exit_condition(date)
    rsi_2 = StockIndex.rsi_2(date)

    if rsi_2 > 80 and exit_point != MarketCondition.LONG:
        alpha = 0.8 if market_status == MarketStatus.BULL else 1
        grade = (rsi_2 - 80) / 10 if rsi_2 < 90 else pow((rsi_2 - 80) / 10, 2)
        TradeUtil.sell(volume * grade * alpha, date)
    elif rsi_2 < 20 and exit_point != MarketCondition.SHORT:
        alpha = 1 if market_status == MarketStatus.BULL else 0.8
        grade = (20 - rsi_2) / 10 if rsi_2 > 10 else pow((20 - rsi_2) / 10, 2)
        TradeUtil.buy(volume * grade * alpha, date)

赚了,但比银行利率还少,问题出在哪里,我也不知道。

参考资料
  1. How I Trade With Only 2-Period RSI, by Galen Woods
  2. RSI2, from www.stockcharts.com
  3. Testing the RSI 2 Trading Strategy On US Stocks, by JB Marwood
  4. Connors 2-Period RSI Update For 2014, by Jeff Swanson
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348