1. 程式人生 > >單因子 & 多因子策略(基於JoinQuant)

單因子 & 多因子策略(基於JoinQuant)

## step1:匯入所需的庫import pandas as pdfrom pandas import Series, DataFrameimport numpy as npimport statsmodels.api as smimport scipy.stats as scsimport 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_returndef 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))