导读:近期朋友私信想了解关于“量化投资”的股票知识,下面小编就通过“多因子选股(股票)”来讲解这一股票知识内容,下面就来进行简要的介绍,1.# coding=utf-82.from__future__ im
本文有2792个文字,大小约为9KB,预计阅读时间7分钟1.# coding=utf-8
2.from__future__ importprint_function,absolute_import,unicode_literals
3.
4.importnumpy asnp
5.fromgm.api import*
6.frompandas importDataFrame
7.
8.'''
9.本策略每隔1个月定时触发,根据Fama-French三因子模型对每只股票进行回归,得到其alpha值。
10.假设Fama-French三因子模型可以完全解释市场,则alpha为负表明市场低估该股,因此应该买入。
11.策略思路:
12.计算市场收益率、个股的账面市值比和市值,并对后两个进行了分类,
13.根据分类得到的组合分别计算其市值加权收益率、SMB和HML.
14.对各个股票进行回归(假设无风险收益率等于0)得到alpha值.
15.选取alpha值小于0并为最小的10只股票进入标的池
16.平掉不在标的池的股票并等权买入在标的池的股票
17.回测数据:SHSE.000300的成份股
18.回测时间:2017-07-01 08:00:00到2017-10-01 16:00:00
19.'''
20.
21.
22.definit(context):
23.# 每月第一个交易日的09:40 定时执行algo任务
24.schedule(schedule_func=algo,date_rule='1m',time_rule='09:40:00')
25.print(order_target_percent(symbol='SHSE.600000',percent=0.5,order_type=OrderType_Market,
26.position_side=PositionSide_Long))
27.# 数据滑窗
28.context.date =20
29.# 设置开仓的最大资金量
30.context.ratio =0.8
31.# 账面市值比的大/中/小分类
32.context.BM_BIG =3.0
33.context.BM_MID =2.0
34.context.BM_SMA =1.0
35.# 市值大/小分类
36.context.MV_BIG =2.0
37.context.MV_SMA =1.0
38.
39.
40.# 计算市值加权的收益率,MV为市值的分类,BM为账目市值比的分类
41.defmarket_value_weighted(stocks,MV,BM):
42.select =stocks[(stocks.NEGOTIABLEMV ==MV)&(stocks.BM ==BM)]
43.market_value =select['mv'].values
44.mv_total =np.sum(market_value)
45.mv_weighted =[mv /mv_total formv inmarket_value]
46.stock_return =select['return'].values
47.# 返回市值加权的收益率的和
48.return_total =[]
49.fori inrange(len(mv_weighted)):
50.return_total.append(mv_weighted[i]*stock_return[i])
51.return_total =np.sum(return_total)
52.returnreturn_total
53.
54.
55.defalgo(context):
56.# 获取上一个交易日的日期
57.last_day =get_previous_trading_date(exchange='SHSE',date=context.now)
58.# 获取沪深300成份股
59.context.stock300 =get_history_constituents(index='SHSE.000300',start_date=last_day,
60.end_date=last_day)[0]['constituents'].keys()
61.# 获取当天有交易的股票
62.not_suspended =get_history_instruments(symbols=context.stock300,start_date=last_day,end_date=last_day)
63.not_suspended =[item['symbol']foritem innot_suspended ifnotitem['is_suspended']]
64.fin =get_fundamentals(table='tq_sk_finindic',symbols=not_suspended,start_date=last_day,end_date=last_day,
65.fields='PB,NEGOTIABLEMV',df=True)
66.
67.# 计算账面市值比,为P/B的倒数
68.fin['PB']=(fin['PB']**-1)
69.# 计算市值的50%的分位点,用于后面的分类
70.size_gate =fin['NEGOTIABLEMV'].quantile(0.50)
71.# 计算账面市值比的30%和70%分位点,用于后面的分类
72.bm_gate =[fin['PB'].quantile(0.30),fin['PB'].quantile(0.70)]
73.fin.index =fin.symbol
74.x_return =[]
75.# 对未停牌的股票进行处理
76.forsymbol innot_suspended:
77.# 计算收益率
78.close =history_n(symbol=symbol,frequency='1d',count=context.date +1,end_time=last_day,fields='close',
79.skip_suspended=True,fill_missing='Last',adjust=ADJUST_PREV,df=True)['close'].values
80.stock_return =close[-1]/close[0]-1
81.pb =fin['PB'][symbol]
82.market_value =fin['NEGOTIABLEMV'][symbol]
83.# 获取[股票代码. 股票收益率, 账面市值比的分类, 市值的分类, 流通市值]
84.ifpb <bm_gate[0]:
85.ifmarket_value <size_gate:
86.label =[symbol,stock_return,context.BM_SMA,context.MV_SMA,market_value]
87.else:
88.label =[symbol,stock_return,context.BM_SMA,context.MV_BIG,market_value]
89.elifpb <bm_gate[1]:
90.ifmarket_value <size_gate:
91.label =[symbol,stock_return,context.BM_MID,context.MV_SMA,market_value]
92.else:
93.label =[symbol,stock_return,context.BM_MID,context.MV_BIG,market_value]
94.elifmarket_value <size_gate:
95.label =[symbol,stock_return,context.BM_BIG,context.MV_SMA,market_value]
96.else:
97.label =[symbol,stock_return,context.BM_BIG,context.MV_BIG,market_value]
98.iflen(x_return)==0:
99.x_return =label
100.else:
101.x_return =np.vstack([x_return,label])
102.
103.stocks =DataFrame(data=x_return,columns=['symbol','return','BM','NEGOTIABLEMV','mv'])
104.stocks.index =stocks.symbol
105.columns =['return','BM','NEGOTIABLEMV','mv']
106.forcolumn incolumns:
107.stocks[column]=stocks[column].astype(np.float64)
108.# 计算SMB.HML和市场收益率
109.# 获取小市值组合的市值加权组合收益率
110.smb_s =(market_value_weighted(stocks,context.MV_SMA,context.BM_SMA)+
111.market_value_weighted(stocks,context.MV_SMA,context.BM_MID)+
112.market_value_weighted(stocks,context.MV_SMA,context.BM_BIG))/3
113.
114.# 获取大市值组合的市值加权组合收益率
115.smb_b =(market_value_weighted(stocks,context.MV_BIG,context.BM_SMA)+
116.market_value_weighted(stocks,context.MV_BIG,context.BM_MID)+
117.market_value_weighted(stocks,context.MV_BIG,context.BM_BIG))/3
118.
119.smb =smb_s -smb_b
120.# 获取大账面市值比组合的市值加权组合收益率
121.hml_b =(market_value_weighted(stocks,context.MV_SMA,3)+
122.market_value_weighted(stocks,context.MV_BIG,context.BM_BIG))/2
123.# 获取小账面市值比组合的市值加权组合收益率
124.hml_s =(market_value_weighted(stocks,context.MV_SMA,context.BM_SMA)+
125.market_value_weighted(stocks,context.MV_BIG,context.BM_SMA))/2
126.
127.hml =hml_b -hml_s
128.close =history_n(symbol='SHSE.000300',frequency='1d',count=context.date +1,
129.end_time=last_day,fields='close',skip_suspended=True,
130.fill_missing='Last',adjust=ADJUST_PREV,df=True)['close'].values
131.market_return =close[-1]/close[0]-1
132.coff_pool =[]
133.# 对每只股票进行回归获取其alpha值
134.forstock instocks.index:
135.x_value =np.array([[market_return],[smb],[hml],[1.0]])
136.y_value =np.array([stocks['return'][stock]])
137.# OLS估计系数
138.coff =np.linalg.lstsq(x_value.T,y_value)[0][3]
139.coff_pool.append(coff)
140.
141.# 获取alpha最小并且小于0的10只的股票进行操作(若少于10只则全部买入)
142.stocks['alpha']=coff_pool
143.stocks =stocks[stocks.alpha <0].sort_values(by='alpha').head(10)
144.
145.symbols_pool =stocks.index.tolist()
146.positions =context.account().positions()
147.
148.# 平不在标的池的股票
149.forposition inpositions:
150.symbol =position['symbol']
151.ifsymbol notinsymbols_pool:
152.order_target_percent(symbol=symbol,percent=0,order_type=OrderType_Market,
153.position_side=PositionSide_Long)
154.print('市价单平不在标的池的',symbol)
155.
156.# 获取股票的权重
157.percent =context.ratio /len(symbols_pool)
158.# 买在标的池中的股票
159.forsymbol insymbols_pool:
160.order_target_percent(symbol=symbol,percent=percent,order_type=OrderType_Market,
161.position_side=PositionSide_Long)
162.print(symbol,'以市价单调多仓到仓位',percent)
163.
164.
165.if__name__ =='__main__':
166.'''
167.strategy_id策略ID,由系统生成
168.filename文件名,请与本文件名保持一致
169.mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
170.token绑定计算机的ID,可在系统设置-密钥管理中生成
171.backtest_start_time回测开始时间
172.backtest_end_time回测结束时间
173.backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
174.backtest_initial_cash回测初始资金
175.backtest_commission_ratio回测佣金比例
176.backtest_slippage_ratio回测滑点比例
177.'''
178.run(strategy_id='strategy_id',
179.filename='main.py',
180.mode=MODE_BACKTEST,
181.token='token_id',
182.backtest_start_time='2017-07-01 08:00:00',
183.backtest_end_time='2017-10-01 16:00:00',
184.backtest_adjust=ADJUST_PREV,
185.backtest_initial_cash=10000000,
186.backtest_commission_ratio=0.0001,
187.backtest_slippage_ratio=0.0001)