楼主: _wallstreetcat_
6782 2

[交易策略] 传统小市值策略(附Python源码) [推广有奖]

  • 0关注
  • 36粉丝

已卖:114份资源

讲师

9%

还不是VIP/贵宾

-

威望
0
论坛币
88 个
通用积分
41.5574
学术水平
14 点
热心指数
13 点
信用等级
13 点
经验
6402 点
帖子
257
精华
0
在线时间
235 小时
注册时间
2017-3-16
最后登录
2024-10-20

楼主
_wallstreetcat_ 企业认证  发表于 2017-3-27 10:53:07 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

前几篇的教程都是关于择时的策略,今天打算写一篇选股的策略——基于市值的选股策略。

了解Alpha策略和Fama_French三因子模型的人都知道,市值因子是一个长期有效的超额收益来源,对股票收益率有一定的解释作用,小市值的股票更容易带来超额收益。这也比较好理解,因为小市值类股票往往表现活跃,容易引发炒作风潮。此外,还有IPO管制的原因(大量排队企业选择借壳),也有市场风险偏好提升的原因(市场恶性循环越来越偏爱小市值)。

现在,开始正式介绍策略部分吧。为方便小伙伴们理解,我们会介绍更详细和具体。

策略逻辑:市值可以带来超额收益策略内容:每月月初买入市值最小的30只股票,持有至下个月月初再调仓资金管理:等权重买入风险控制:无单只股票仓位上限控制、无止盈止损

第一步:获取数据

BigQuant平台具有丰富的金融数据,包括行情数据和财报数据,并且具有便捷、简单的API调用接口。获取数据的代码如下:

  1. # 获取股票代码
  2. instruments = D.instruments()
  3. # 确定起始时间
  4. start_date = '2010-01-01'
  5. # 确定结束时间
  6. end_date = '2017-02-13'
  7. # 获取股票总市值数据,返回DataFrame数据格式
  8. market_cap_data = D.history_data(instruments,start_date,end_date,fields=['market_cap'])
复制代码

在上面的代码中,history_data是我们平台获取数据的一个重要API。fields参数为列表形式,传入的列表即为我们想要获取的数据,该接口有两种返回格式,可以通过groupped_by_instrument进行控制,该参数为True,返回字典格式,该参数为False,返回Pandas的DataFrame格式。

第二步:整理买入股票列表

  1. # 获取交易日历
  2. trading_date = D.history_data(['000300.SHA'],start_date,end_date,
  3.                               fields=['date','open'],
  4.                               groupped_by_instrument=False)
  5. # 将日期型格式转化为字符串格式
  6. trading_date = trading_date['date'].apply(lambda x : x.strftime('%Y-%m-%d'))
  7. # 整理出一个"日期-股票代码"的一个字典
  8. daily_buy_stock = {}
  9. for dt in trading_date:
  10.     # 获取每天总市值最小的30只股票
  11.     daily_buy_stock[dt] = list(market_cap_data[market_cap_data['date']==
  12.                           dt].sort_values('market_cap').instrument)[:30]
复制代码

上面代码的目的是整理出每次调仓需要买入的股票的代码列表。首先,我们需要获得所有的交易日,这里我们以沪深300的交易日历表示,然后我们采取了一个for循环,将每个交易日总市值最小的30只股票代码整理到daily_buy_stock字典,该字典的键名为日期。

第三步:回测主体

  1. # 回测参数设置,initialize函数只运行一次
  2. def initialize(context):
  3.     # 手续费设置
  4.     context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
  5.     # 调仓规则(每月的第一天调仓)
  6.     context.schedule_function(rebalance,date_rule=date_rules.month_start(days_offset=0))
  7.     # 传入 整理好的调仓股票数据
  8.     context.daily_buy_stock = daily_buy_stock

  9. # handle_data函数会每天运行一次
  10. def handle_data(context,data):
  11.     pass

  12. # 换仓函数
  13. def rebalance(context, data):
  14.     # 当前的日期
  15.     date = data.current_dt.strftime('%Y-%m-%d')
  16.     # 根据日期获取调仓需要买入的股票的列表
  17.     stock_to_buy = context.daily_buy_stock[date]
  18.     # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
  19.     stock_hold_now = [equity.symbol for equity in context.portfolio.positions]
  20.     # 继续持有的股票:调仓时,如果买入的股票已经存在于目前的持仓里,那么应继续持有
  21.     no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]
  22.     # 需要卖出的股票
  23.     stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]
  24.   
  25.     # 卖出
  26.     for stock in stock_to_sell:
  27.         # 如果该股票停牌,则没法成交。因此需要用can_trade方法检查下该股票的状态
  28.         # 如果返回真值,则可以正常下单,否则会出错
  29.         # 因为stock是字符串格式,我们用symbol方法将其转化成平台可以接受的形式

  30.         if data.can_trade(context.symbol(stock)):
  31.             # order_target_percent是平台的一个下单接口,表明下单使得该股票的权重为0,
  32.             #   即卖出全部股票,可参考回测文档
  33.             context.order_target_percent(context.symbol(stock), 0)
  34.    
  35.     # 如果当天没有买入的股票,就返回
  36.     if len(stock_to_buy) == 0:
  37.         return

  38.     # 等权重买入
  39.     weight =  1 / len(stock_to_buy)
  40.    
  41.     # 买入
  42.     for  stock in stock_to_buy:
  43.         if data.can_trade(context.symbol(stock)):
  44.             # 下单使得某只股票的持仓权重达到weight,因为
  45.             # weight大于0,因此是等权重买入
  46.             context.order_target_percent(context.symbol(stock), weight)
  47. 第四步:回测接口

  48. # 使用第四版的回测接口,需要传入多个策略参数
  49. m=M.backtest.v4(
  50.     instruments=instruments,
  51.     start_date=start_date,
  52.     end_date=end_date,
  53.     # 必须传入initialize,只在第一天运行
  54.     initialize=initialize,
  55.     #  必须传入handle_data,每个交易日都会运行
  56.     handle_data=handle_data,
  57.     # 买入以开盘价成交
  58.     order_price_field_buy='open',
  59.     # 卖出也以开盘价成交
  60.     order_price_field_sell='open',
  61.     # 策略本金
  62.     capital_base=float("1.0e7"),
  63.     # 比较基准:沪深300
  64.     benchmark='000300.INDX',
  65. )
复制代码

好嘞,策略就完全写好了。我们运行完曲线如下:

1.png

回测结果比较真实,小市值策略在过去几年确实是这样的表现。还记得2014年12月吗?当时大部分的Alpha策略都产生了较大回撤,被称为alpha前所未有的“黑天鹅”,从图上看出那段时间我们的策略相对收益率(绿线)也在回撤。因此,市场没有圣杯,没有哪个策略适合任何市场状况。但总有策略能够保持长期正收益,这才是宽客应该明白和信仰的,当真的遭遇回撤时才能够坚持自我、不惧亏损、等待“春天”的到来。

原文链接地址


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:小市值策略 python2

已有 1 人评分经验 学术水平 热心指数 信用等级 收起 理由
accumulation + 100 + 1 + 1 + 1 精彩帖子

总评分: 经验 + 100  学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

本帖被以下文库推荐

沙发
EddieChiu 发表于 2017-3-28 13:17:21

藤椅
systrader 发表于 2017-3-29 12:14:55
好帖收藏

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群
GMT+8, 2025-12-29 13:45