导语:作为策略锦集第二篇,我们以沪深A 股市场出了名的“二八轮动”现象为基础,向大 家介绍经典择时策略:二八轮动策略。 一、策略阐述 在介绍二八轮动策略之前,我们首先来了解一下择时交易,择时交易是指利用某种方法 来判断后市走势,如果判断是上涨,则买入持有;如果判断是下跌,则卖出清仓;如果判断 是震荡,则进行高抛低吸,这样可以获得远远超越简单买入持有策略的收益率,所以择时交 易是收益率最高的一种交易方式。通俗的讲,择时即为选择交易时机,投资者总是希望通过 择时,在上涨前买入,在下跌前卖出。 “二八轮动”现象就是大小盘轮动现象,“二”代表数量占比20%左右的大盘权重股, “八”代表数量占比80%左右的中小盘股票,二八轮动策略就是指在大盘股与小盘股中间不 断切换,轮流持有,在大小盘都看跌的时候,则买入债券或者货币基金。二八轮动策略的本 质是择时,从大小盘指数中选择最佳交易时机。 二八轮动是如何轮动的呢? 择时方法:对比当前交易日收盘数据与二十个交易日前的收盘数据,选择沪深300 指数 和中证500 指数中涨幅较大的一个,于下一个交易日切换为持有该指数 ETF ,若两个指数均 为下跌,则于下个交易日切换为空仓状态。调仓 日为每周第一个交易 日。 以下为策略实现的基本信息: 策略实现难度:1 实现过程中所需要用到的API 函数,ps:通过 MindGo 量化交易平台 API 文档快速掌握: 需要用到的API 函数 功能 run_weekly() 按周定时运行函数 account.positions 获取账户持仓信息 account.cash 获取账户当前资金 history() 获取多只股票多属性的历史行情数据 ----------------------- Page 74----------------------- 二、代码示意图 三、编写释义 本策略的编写难点在于根据信号值来调整持仓。以下是持仓调整逻辑梳理: 第一步:根据信号值,只可能会出现三种情况:分别是空仓、沪深300、中证500,其 中空仓是两者信号值都小于 0,否则持仓为信号值大的那个。 第二步:以目标持仓为导向,根据当前持仓情况作出调仓操作: 目标持仓 当前持仓 操作 空仓 无持仓 无操作 有持仓 卖出持仓 沪深300 无持仓 买入沪深300 沪深300 不操作 中证500 卖出中证500,随后买入沪深300 中证500 无持仓 买入中证500 沪深300 卖出沪深300,买入中证500 中证500 无操作 ----------------------- Page 75----------------------- 四、最终结果 策略回测区间:2014.01.01-2018.01.29 回测资金:100000 回测频率:日级 回测结果:红色曲线为策略收益率曲线,蓝色曲线为对应的基准指数收益率曲线 策略源代码: import pandas as pd import numpy as np #=============================初始化账户=============================== def initialize(account): account.day = 20 #设置数据获取长度为 20 account.security = ['000300.SH','000905.SH']#设沪深300 指数,中证500 指数 account.ETF300 = '510300.OF' #沪深300ETF 基金 account.ETF500 = '510500.OF' # 中证500ETF 基金 run_weekly(trade,date_rule=1) #=============交易函数============ def trade(account,data): #获取信号值 signal=get_signal(account,data) hs300=signal[0] zz500=signal[1] #根据信号值,来调整至相应仓位 #空仓 if hs300 <= 0 and zz500 <= 0: if len(account.positions) > 0: for stock in list(account.positions): order_target(stock, 0) ----------------------- Page 76----------------------- #沪深300 elif hs300 > zz500: if account.ETF500 in list(account.positions): order_target(account.ETF500, 0) if len(account.positions) < 1: order_target_value(account.ETF300, account.cash) # 中证500 elif hs300 < zz500: if account.ETF300 in list(account.positions): order_target(account.ETF300, 0) if len(account.positions) < 1: order_target_value(account.ETF500, account.cash) #======================信号获取函数===================================== def get_signal(account,data): #获取沪深300 与中证500 过去 20 日的收盘价 close=history(account.security, ['close'], 20, '1d', False, 'pre', is_panel=1)['close'] #计算涨跌幅 h=(close.iloc[-1]-close.iloc[0])/close.iloc[0] h300=h['000300.SH'] h500=h['000905.SH'] return h300,h500 ----------------------- Page 77----------------------- |
|