【全新量化入门系列8】综合之前所学写一个策略

作者: 量化君
检测时间到!进来测测你能写出几个策略~

本文是量化交易零基础入门教程中的一篇,点击文末阅读原文可查看该系列详情。

摘要

· 灵感细化

· 逐步实现策略

· 调整与改进策略

· 自测与自学

前言

通过前文基础知识的学习,本文将引导读者运用所学写成一个策略。如果发现某些知识忘了很正常,回头再看就行,用到什么去学什么,学习的效率更高。

灵感细化

之前也提到过策略灵感的来源多种多样,可能是通过阅读、通过与人交流、或是通过自己感悟与研究等等。灵感最初可能只是模糊的感觉或疑问,比如“感觉低市盈率的股票好像长期收益更好”、“当股价一旦超过整百的时候会不会更容易继续涨一段”、“这个股票和那个股票的股价数据看起来好像符合某种统计规律”等等。

验证灵感的一个基本方法是把灵感细化,写成策略做回测。

现在你听说了这样一件事,小市值股票过去很长一段时间内收益特别好,但最近不太行了。你觉得这件事比较有价值,想要写成策略来回测验证下。

请思考下,应该写一个什么样的策略来验证这件事呢?

为了验证灵感,我们把灵感细化成内容如下的这样一个策略。

每天找出市值排名最小的前10只股票作为要买入的股票。 若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。 买入要买入的股票,买入金额为当前可用资金的10分之一。

考虑到不一定要选10个股票,股票数量应该是个可以方便调节的变量,因此策略内容改成如下这样更好。

设定好要交易的股票数量stocksnum  每天找出市值排名最小的前stocksnum只股票作为要买入的股票。 若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。 买入要买入的股票,买入金额为当前可用资金的stocksnum分之一。

逐步实现

因为最终目的是要写成代码交给计算机回测,因此要逐步把文字的意思用代码实现,首先要把这个策略放到之前讲过的初始化与周期循环的策略框架中,如下:

def initialize(context):  run_daily(period,time='every_bar')  # 代码:设定好要交易的股票数量stocksnumdef period(context):  # 代码:找出市值排名最小的前stocksnum只股票作为要买入的股票  # 代码:若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。  # 代码:买入要买入的股票,买入金额为可用资金的stocksnum分之一

接下来,你只需要逐步的把策略的全部内容用代码实现出来,技巧是把复杂的内容拆分成多个简单的内容,逐步实现,对于不确定的东西print打印出来看看。往下读之前,建议自己独立实现下试试,基本都是用讲过的内容。遇到困难可以看下我下面给出的提示,所有提示后面会给出参考代码。

[这句非常简单,需要注意的是要用到之前讲过的全局变量。]

[首先使用获取指数成分股方法可以获取上证指数和深证综指的成分股,两者加起来就是当前全市场股票的股票列表,用加号可以连接两个list。然后,使用获取财务数据的方法找出当前全市场股票中市值最小的前stocksnum个的股票代码。]

[使用context数据获取当前持仓情况,用for循环语句与if判断语句判断股票是否在当前持仓中,用in判断是否一个元素在某list中,用下单API实现卖出操作。]

[使用context数据获取当前可用资金总量,用for循环与下单API实现买入每个要买入的股票。]

参考代码:

def initialize(context):  run_daily(period,time='every_bar')  # 设定好要交易的股票数量stocksnum  g.stocksnum = 10def period(context):  # 代码:找出市值排名最小的前stocksnum只股票作为要买入的股票  # 获取上证指数和深证综指的成分股代码并连接,即为全A股市场所有股票的股票代码  # 用加号可以连接两个list  scu =get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE')  # 选出在scu内的市值排名最小的前stocksnum只股票  q=query(valuation.code        ).filter(          valuation.code.in_(scu)        ).order_by(          valuation.market_cap.asc()        ).limit(g.stocksnum)  df = get_fundamentals(q)  # 选取股票代码并转为list  buylist=list(df['code'])# 代码:若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。  # 对于每个当下持有的股票进行判断:现在是否已经不在buylist里,如果是则卖出  for stock in context.portfolio.positions:    if stock not in buylist: #如果stock不在buylist      order_target(stock, 0) #调整stock的持仓为0,即卖出  # 代码:买入要买入的股票,买入金额为可用资金的stocksnum分之一  # 将资金分成g.stocksnum份  position_per_stk = context.portfolio.cash/g.stocksnum  # 用position_per_stk大小的g.stocksnum份资金去买buylist中的股票  for stock in buylist:    order_value(stock, position_per_stk)

调整与改进

至此这已经是一个完整可运行的策略了,你可以试试看,回测结果应该已经可以一定程度上验证灵感了。不过虽然策略完成,我们却发现现在策略是每天进行一次选股并交易,我们觉得这太频繁了,希望能实现通过一个变量period控制操作的周期,即每period天进行一次选股并交易。

依然建议先试着自己做下,提示如下,后面是参考代码。

参考代码:

def initialize(context):  run_daily(period,time='every_bar')  # 设定好要交易的股票数量  g.stocksnum = 7  # 设定交易周期  g.period = 13  # 记录策略进行天数  g.days = 0def period(context):  # 判断策略进行天数是否能被轮动频率整除余1  if g.days % g.period == 0:# 代码:找出市值排名最小的前stocksnum只股票作为要买入的股票    # 获取上证指数和深证综指的成分股代码并连接,即为全A股市场所有股票的股票代码    # 用加号可以连接两个list    scu = get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE')    # 选出在scu内的市值排名最小的前stocksnum只股票    q=query(valuation.code          ).filter(            valuation.code.in_(scu)          ).order_by(             valuation.market_cap.asc()          ).limit(g.stocksnum)    df = get_fundamentals(q)# 选取股票代码并转为list    buylist=list(df['code'])    # 代码:若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。    # 对于每个当下持有的股票进行判断:现在是否已经不在buylist里,如果是则卖出    for stock in context.portfolio.positions:      if stock not in buylist: #如果stock不在buylist        order_target(stock, 0) #调整stock的持仓为0,即卖出# 代码:买入要买入的股票,买入金额为可用资金的stocksnum分之一    # 将资金分成g.stocksnum份    position_per_stk = context.portfolio.cash/g.stocksnum    # 用position_per_stk大小的g.stocksnum份资金去买buylist中的股票    for stock in buylist:      order_value(stock, position_per_stk)  # 策略进行天数增加1      g.days = g.days + 1

回测结果

策略初步写完,把g.period设为13,g.stocksnum设为7,初始资金设为100000,频率为天,回测起止日期为20150101-20180627,然后进行回测,回测结果如下:

可见15年到16年该策略表现确实不错,随后17年至今则表现平平。

自测与自学

-END

JoinQuant-TWist

-------------------------------------

如果您有优质的、符合见闻调性的原创文章,欢迎以个人的名义投稿入驻华尔街见闻名家专栏。

投稿方式 :请将个人简介以及代表作品发送至 zhuanlan@wallstreetcn.com ,并附上电话和微信以便做进一步沟通,在主题中标明: 申请入驻见闻专栏 + 投稿人名字

参与评论
收藏
qrcode
相关资讯
参与评论