# 单因子 &amp; 多因子策略（基于JoinQuant）

23 篇文章 1 订阅
3 篇文章 0 订阅
一份朴实的声明。。。

1. 基于joinquant，大部分代码是原作者所写，俺只是改写、补充。。。
2. 源码见：https://www.joinquant.com/post/775

3. 基于因子打分，不是因子回归
（思路：单因子打分，分值赋权个股形成单因子组合，再等权加权单因子组合，变为多因子策略）
----------------------------------------------------------------------------------------

## step1：导入所需的库
import pandas as pdfrom pandas
import Series, DataFrame
import numpy as npimport statsmodels.api as sm
import scipy.stats as scs
import matplotlib.pyplot as plt
## step2：三个函数
# 函数1：获取因子
factors = ['B/M','EPS','PEG','ROE','ROA','GP/R','P/R','L/A','FAP','CMV']
#月初取出因子数值
def get_factors(fdate,factors):
stock_set = get_index_stocks('000001.XSHG',fdate)
q = query( valuation.code, balance.total_owner_equities/valuation.market_cap/100000000, income.basic_eps, valuation.pe_ratio, income.net_profit/balance.total_owner_equities, income.net_profit/balance.total_assets, income.total_profit/income.operating_revenue, income.net_profit/income.operating_revenue, balance.total_liability/balance.total_assets, balance.fixed_assets/balance.total_assets, valuation.circulating_market_cap ).filter( valuation.code.in_(stock_set), valuation.circulating_market_cap )
fdf = get_fundamentals(q, date=fdate)
fdf.index = fdf['code']
fdf.columns = ['code'] + factors
return fdf.iloc[:,-10:]
# 函数2和3：计算因子及benchmark的月收益
def caculate_port_monthly_return(port,startdate,enddate,nextdate,CMV):
close1 = get_price(port, startdate, enddate, 'daily', ['close']) #面板数据 <class 'pandas.core.panel.Panel'>
close2 = get_price(port, enddate, nextdate, 'daily',['close']) #面板数据 <class 'pandas.core.panel.Panel'>
weighted_m_return = ((close2['close'].ix[0,:]/close1['close'].ix[0,:]-1)).mean() #等权加权
return weighted_m_return
def caculate_benchmark_monthly_return(startdate,enddate,nextdate):
close1 = get_price(['000300.XSHG'],startdate,enddate,'daily',['close'])['close']
close2 = get_price(['000300.XSHG'],enddate, nextdate, 'daily',['close'])['close']
benchmark_return = (close2.ix[0,:]/close1.ix[0,:]-1).sum()
print close1
return benchmark_return
## step3：核心策略
factors = ['B/M','EPS','PEG','ROE','ROA','GP/R','P/R','L/A','FAP','CMV']#因为研究模块取fundmental数据默认date为研究日期的前一天。所以要自备时间序列。按月取
year = ['2011','2012','2013','2014','2015','2016','2017']
month = ['01','02','03','04','05','06','07','08','09','10','11','12']
result = {}
for i in range(7*12):
startdate = year[i/12] + '-' + month[i%12] + '-01'
try:
enddate = year[(i+1)/12] + '-' + month[(i+1)%12] + '-01'
except IndexError:
enddate = '2018-01-01'
try:
nextdate = year[(i+2)/12] + '-' + month[(i+2)%12] + '-01'
except IndexError:
if enddate == '2018-01-01':
nextdate = '2018-02-01'
else:
nextdate = '2018-01-01'
#print 'time %s'%startdate
fdf = get_factors(startdate,factors)
CMV = fdf['CMV'] #5个组合，10个因子
df = DataFrame(np.zeros(6*10).reshape(6,10),index = ['port1','port2','port3','port4','port5','benchmark'],columns = factors)
for fac in factors:
score = fdf[fac].order()
port1 = list(score.index)[: len(score)/5]
port2 = list(score.index)[ len(score)/5+1: 2*len(score)/5]
port3 = list(score.index)[ 2*len(score)/5+1: -2*len(score)/5]
port4 = list(score.index)[ -2*len(score)/5+1: -len(score)/5]
port5 = list(score.index)[ -len(score)/5+1: ]
df.ix['port1',fac] = caculate_port_monthly_return(port1,startdate,enddate,nextdate,CMV)
df.ix['port2',fac] = caculate_port_monthly_return(port2,startdate,enddate,nextdate,CMV)
df.ix['port3',fac] = caculate_port_monthly_return(port3,startdate,enddate,nextdate,CMV)
df.ix['port4',fac] = caculate_port_monthly_return(port4,startdate,enddate,nextdate,CMV)
df.ix['port5',fac] = caculate_port_monthly_return(port5,startdate,enddate,nextdate,CMV)
df.ix['benchmark',fac] = caculate_benchmark_monthly_return(startdate,enddate,nextdate)
#print 'factor %s'%fac
result[i+1]=dfmonthly_return = pd.Panel(result)
## step4：模型评价
total_return = {}
annual_return = {}
excess_return = {}
annual_volatility={}
sharpe={}
information_ratio={}
win_prob = {}
drawdown={}
tr={}
for fac in factors:
monthly = monthly_return[:,:,fac]
total_return[fac] = (monthly+1).T.cumprod().iloc[-1,:]-1
annual_return[fac] = (total_return[fac]+1)**(1./6)-1
excess_return[fac] = annual_return[fac]*0.7- annual_return[fac][-1]
annual_volatility[fac]=monthly.T.std()
sharpe[fac]=(annual_return[fac]-0.04)/annual_volatility[fac]
information_ratio[fac]=(annual_return[fac]-annual_return[fac][-1])/annual_volatility[fac]
drawdown[fac]=monthly.T.min()
win_excess = monthly.iloc[0,:]*0.7-monthly.iloc[-1,:]
win_prob[fac]=win_excess[win_excess>0].count()/float(len(win_excess))
### step5：Smart Beta指数的编制 #把一个三维的panel按因子降维，即对因子求平均，使因子这一维度消失掉 # 也即将因子类子指数等权加权，编制成指数 columns= ['port1','port2','port3','port4','port5','benchmark'] avg_data= DataFrame(np.zeros(85*6).reshape(85,6),columns= ['port1','port2','port3','port4','port5','benchmark']) for i in columns: avg_data[i]=pd.DataFrame((monthly_return[:,i,:]).mean()) #(monthly_return[:,2,:]).mean() #avg_data avg_total_return=(avg_data+1).cumprod().iloc[-1,:]-1 avg_annual_return= (avg_total_return+1)**(1./6)-1 avg_excess_return= avg_annual_return*0.7- avg_annual_return[-1] avg_annual_volatility=avg_data.std() avg_information_ratio=avg_excess_return/avg_annual_volatility avg_sharpe=(avg_annual_return-0.04)/avg_annual_volatility avg_drawdown=avg_data.min() avg_win_excess = avg_data.T.iloc[5,:]*0.7-avg_data.T.iloc[-1,:] avg_win_prob=avg_win_excess[avg_win_excess>0].count()/float(len(avg_win_excess)) avg_win_prob plt.figure(figsize =(8,4)) plt.plot((avg_data+1).cumprod().ix[:,0], 'r',label = '%s'%fac ,alpha=0.5) plt.plot((monthly.ix[-1,:].T+1).cumprod(), 'blue',label = '沪深300指数',alpha=0.5) plt.xlabel('净值曲线') plt.legend(loc='upper left',ncol=2)

• 0
点赞
• 6
收藏
• 打赏
• 0
评论
11-17
12-29 846
05-31 3847
09-02 3039
08-07 628
03-18 1万+
06-26 4万+

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

©️2022 CSDN 皮肤主题：游动-白 设计师：我叫白小胖

Xionglingchu

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。