├── README.md ├── factor_exposure.py ├── data.py ├── Part3.py ├── utility.py ├── UIconnect.py ├── style_factor.py ├── regression.py ├── Part2.py ├── Part1.py └── Part4.py /README.md: -------------------------------------------------------------------------------- 1 | # Barra_CNE5 2 | Provide risk forecasts by Barra China Equity Model 3 | 4 | ## Code Usage 5 | 6 | 1. `data.py` Extract data from Wind database. 7 | 8 | 2. `style_factor.py` Build style factors. 9 | 10 | 3. `factor_exposure.py` Prepare factor exposures data for regression: truncate, winsorize and normalize style factors, build industry factors.Return a dataframe with hierarchy index (datetime, code) and columns containing: industry factors, 10 style factors, daily return and weight. 11 | 12 | 4. `regression.py` Calculate factor returns by weighted linear regression. Predict risk by factor returns. 13 | 14 | 5. `utility.py` Some utility functions. 15 | -------------------------------------------------------------------------------- /factor_exposure.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from utility import * 4 | from WindPy import * 5 | from style_factor import StyleFactor 6 | 7 | 8 | path = r'D:\citics\Barra\data\\' 9 | data = pd.read_csv(path + 'dataall.csv') 10 | 11 | ####pre NA processing 优先股缺失并非来源于数据缺失,所以用0填补。 12 | data.wgsd_pfd_stk.fillna(0, inplace = True) 13 | 14 | ###返回style factor exposure 15 | style_factors = factors(data) 16 | style_factors.to_csv(path + 'StyleFactors.csv', index = False) 17 | 18 | ####删除任意因子暴露存在NA的行,删除当日停牌的股票 19 | style_factors.dropna(inplace = True, axis = 0) 20 | style_factors.drop(style_factors[style_factors.volume == 0].index.tolist(), inplace = True) 21 | style_factors.drop(['volume'],axis = 1,inplace = True) 22 | style_factors.index = np.arange(len(style_factors)) 23 | 24 | ###用以下两种方法都可以获取industry factor exposure 25 | """ 26 | w.start() 27 | beginDate = '2012-12-25' 28 | endDate = '2018-07-01' 29 | stockSector = w.wset("sectorconstituent","date="+endDate+";sector=全部A股") 30 | dates,codes,names = stockSector.Data 31 | joincodes = ','.join(codes) 32 | ind = w.wss(joincodes,'industry_gicscode','industryType=1') 33 | industrycode= ind.Data[0] 34 | inddata = pd.DataFrame({'industry_gicscode':industrycode}, index = ind.Codes) 35 | """ 36 | 37 | IND = pd.read_csv(path + 'industry.csv') 38 | IND = IND[~IND.iloc[:,3].isnull()] 39 | industrycode = [str(int(x)) for x in IND.iloc[:,3]] 40 | inddata = pd.DataFrame({'industry_gicscode':industrycode}, index = IND.iloc[:,0]) 41 | industry_data = industry(inddata) 42 | 43 | 44 | ####对style factors truncate, winsorize, normalize后将数据合并。 45 | trade_data = data.loc[:,['datetime', 'code']] 46 | trade_data['return'] = data.loc[:,'pct_chg'] 47 | trade_data['weight'] = data.loc[:,'mkt_cap_ard'] 48 | datetime = sorted(style_factors.datetime.unique()) 49 | dfs = pd.DataFrame() 50 | for each in datetime: 51 | time = style_factors[style_factors.datetime == each] 52 | pre_data = preparing(time) 53 | style_data = styles(pre_data) 54 | factor_data = pd.merge(style_data, industry_data.iloc[:,1:], left_on = 'code', right_index = True,how = 'left') 55 | df = pd.merge(factor_data, trade_data, left_on = ['datetime','code'],right_on =['datetime','code'], how = 'inner') 56 | df.dropna(inplace = True) 57 | df.weight = df.loc[:,'weight'] / sum(df.loc[:,'weight']) 58 | dfs = dfs.append(df) 59 | print(each) 60 | 61 | dfs.index = np.arange(len(dfs)) 62 | dfs.to_csv(path+'FactorExposure.csv', index = False) 63 | 64 | -------------------------------------------------------------------------------- /data.py: -------------------------------------------------------------------------------- 1 | from WindPy import * 2 | import datetime 3 | import pandas as pd 4 | import numpy as np 5 | 6 | market_cols1 = ['mkt_cap_ard','risk_beta120','pb','pe_est_ftm','ocfps_ttm', #财务数据 7 | 'pe_ttm','west_netprofit_CAGR','west_netprofit_YOY', 8 | 'risk_exstdev252','risk_residvol252','share_totala', 9 | 'wgsd_pfd_stk','wgsd_debt_lt','wgsd_liabs', 10 | 'wgsd_assets','wgsd_com_eq_par'] 11 | market_cols2 = ['pct_chg', 'volume','close'] #交易数据 12 | beginDate = '2012-12-29' 13 | endDate = '2018-07-01' 14 | path = r'D:\citics\Barra\data\\' # 结果储存路径 15 | 16 | #today = datetime.date.today().strftime('%Y-%m-%d') 17 | #endDate = (datetime.date.today()-datetime.timedelta(days=1)).strftime('%Y-%m-%d') 18 | w.start() 19 | def GetMarketInfo(code,cols1,cols2): 20 | global beginDate 21 | ipoDate = w.wss(code,'ipo_date').Data[0][0].strftime('%Y-%m-%d') 22 | if ipoDate > beginDate: 23 | begin = ipoDate 24 | else: 25 | begin = beginDate 26 | dailyQuota1 = w.wsd(code,','.join(cols1),begin,endDate,"industryType=1;ruleType=9;currencyType=;rptType=1;Fill=Previous") 27 | df1 = pd.DataFrame(dict(zip(cols1,dailyQuota1.Data)),index=dailyQuota1.Times) 28 | dailyQuota2 = w.wsd(code,','.join(cols2),begin,endDate,"") 29 | df2 = pd.DataFrame(dict(zip(cols2,dailyQuota2.Data)),index=dailyQuota2.Times) 30 | df = pd.merge(df1,df2, left_index = True, right_index = True) 31 | [riskfree] = w.wsd("TB1Y.WI", "close", begin, endDate, "Fill=Previous").Data 32 | rf =(np.array(riskfree)/100 + 1)**(1/252)-1 33 | df['rf'] = rf 34 | return df 35 | def Align(code,df): 36 | df.reset_index(inplace=True) 37 | df.rename(columns={'index':'datetime'},inplace=True) 38 | df['code'] = code; 39 | df.set_index(['datetime','code'],inplace=True) 40 | try: 41 | df['pct_chg'] /= 100 42 | except: 43 | print('无pct_chg字段') 44 | return df 45 | def Concat(codes,cols1,cols2): 46 | dfs = pd.DataFrame() 47 | for code in codes: 48 | print('开始下载%s数据'%code) 49 | try: 50 | df_temp = GetMarketInfo(code,cols1,cols2) 51 | df_temp = Align(code,df_temp) 52 | dfs = dfs.append(df_temp) 53 | dfs.to_pickle(path+r'test.pkl') 54 | except: 55 | print('quota exceeded.') 56 | break 57 | return dfs 58 | # 通过wset取截止日全部A股代码,ESTU 59 | stockSector = w.wset("sectorconstituent","date="+endDate+";sector=全部A股") 60 | dates,codes,names = stockSector.Data 61 | #股票数据 62 | dfs = Concat(codes,market_cols1,market_cols2) 63 | dfs.to_csv(path + r'stock.csv') 64 | w.stop() 65 | -------------------------------------------------------------------------------- /Part3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'D:\citics\Barra\code\Part3.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(1311, 810) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 18 | self.label_5.setGeometry(QtCore.QRect(540, 40, 181, 91)) 19 | font = QtGui.QFont() 20 | font.setPointSize(20) 21 | font.setBold(True) 22 | font.setWeight(75) 23 | self.label_5.setFont(font) 24 | self.label_5.setObjectName("label_5") 25 | self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) 26 | self.verticalLayoutWidget.setGeometry(QtCore.QRect(440, 290, 351, 201)) 27 | self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") 28 | self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) 29 | self.verticalLayout.setContentsMargins(0, 0, 0, 0) 30 | self.verticalLayout.setObjectName("verticalLayout") 31 | self.progressBar = QtWidgets.QProgressBar(self.verticalLayoutWidget) 32 | font = QtGui.QFont() 33 | font.setPointSize(12) 34 | self.progressBar.setFont(font) 35 | self.progressBar.setProperty("value", 24) 36 | self.progressBar.setObjectName("progressBar") 37 | self.verticalLayout.addWidget(self.progressBar) 38 | self.push_button = QtWidgets.QPushButton(self.verticalLayoutWidget) 39 | font = QtGui.QFont() 40 | font.setPointSize(12) 41 | self.push_button.setFont(font) 42 | self.push_button.setObjectName("push_button") 43 | self.verticalLayout.addWidget(self.push_button) 44 | self.label = QtWidgets.QLabel(self.centralwidget) 45 | self.label.setGeometry(QtCore.QRect(450, 480, 349, 128)) 46 | self.label.setObjectName("label") 47 | MainWindow.setCentralWidget(self.centralwidget) 48 | self.menubar = QtWidgets.QMenuBar(MainWindow) 49 | self.menubar.setGeometry(QtCore.QRect(0, 0, 1311, 26)) 50 | self.menubar.setObjectName("menubar") 51 | MainWindow.setMenuBar(self.menubar) 52 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 53 | self.statusbar.setObjectName("statusbar") 54 | MainWindow.setStatusBar(self.statusbar) 55 | 56 | self.retranslateUi(MainWindow) 57 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 58 | 59 | def retranslateUi(self, MainWindow): 60 | _translate = QtCore.QCoreApplication.translate 61 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 62 | self.label_5.setText(_translate("MainWindow", "因子库更新")) 63 | self.push_button.setText(_translate("MainWindow", "开始更新")) 64 | self.label.setText(_translate("MainWindow", "(根据日数据更新每日因子暴露和因子收益)")) 65 | 66 | -------------------------------------------------------------------------------- /utility.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import scipy.optimize as sc_opt 4 | 5 | 6 | 7 | def halflife(half_life = 63, length = 252): 8 | t = np.arange(length) 9 | w = 2 **(t/half_life) / sum(2 ** (t/half_life)) 10 | return(w) 11 | 12 | 13 | def winsorize(a, limit = 3): 14 | mean = np.mean(a) 15 | std = np.std(a) 16 | a_new = a.copy() 17 | a_new[a < mean - std * limit] = mean - std*limit 18 | a_new[a > mean + std * limit] = mean + std*limit 19 | return a 20 | 21 | def normalize(a): 22 | mean = np.mean(a) 23 | std = np.std(a) 24 | a_new = (a - mean)/std 25 | return a_new 26 | 27 | def orthogonalize(target_variable, reference_variable, regression_weight): 28 | orthogonalized_target_variable = target_variable - (target_variable * reference_variable).sum()/(reference_variable**2).sum() * reference_variable 29 | return orthogonalized_target_variable 30 | 31 | 32 | def non_linear_size(size_exposure, market_cap_on_current_day): 33 | 34 | cubed_size = np.power(size_exposure, 3) 35 | 36 | cubed = normalize(winsorize(cubed_size)) 37 | 38 | size = normalize(winsorize(size_exposure)) 39 | 40 | # orthogonalized_size = orthogonalize(target_variable = cubed_size, reference_variable = size_exposure, 41 | # regression_weight = np.sqrt(market_cap_on_current_day)/(np.sqrt(market_cap_on_current_day).sum())) 42 | 43 | orthogonalized_size = orthogonalize(target_variable = cubed, reference_variable = size, 44 | regression_weight = np.sqrt(market_cap_on_current_day)/(np.sqrt(market_cap_on_current_day).sum())) 45 | 46 | return orthogonalized_size 47 | 48 | 49 | def truncate(data, column, limit = 5): 50 | data = data[np.isfinite(data.iloc[:,column])] 51 | mean = np.mean(data.iloc[:,column]) 52 | std = np.std(data.iloc[:,column]) 53 | idx = (data.iloc[:,column] > (mean - std * limit)) & (data.iloc[:,column] < (mean + std * limit)) 54 | data_new = data[idx] 55 | return data_new 56 | 57 | 58 | 59 | 60 | def preparing(data, truncate_limit = 5, winsorize_limit = 3): 61 | ncols = data.shape[1] 62 | for i in np.arange(2, ncols): 63 | data = truncate(data, i) 64 | data.iloc[:,i] = winsorize(data.iloc[:,i], winsorize_limit) 65 | data.iloc[:,i] = normalize(data.iloc[:,i]) 66 | return data 67 | 68 | 69 | 70 | 71 | def industry(data): 72 | industry = data.iloc[:,0].unique() 73 | for each in industry: 74 | data[each] = 0 75 | data.loc[data.iloc[:,0]== each, each] = 1 76 | return data 77 | 78 | def styles(data): 79 | result = data.iloc[:,:2] 80 | result['Beta'] = data.BETA 81 | result['Momentum'] = data.RSTR 82 | result['Size'] = data.LNCAP 83 | result['RV'] = 0.74*data.DASTD + 0.16*data.CMRA + 0.1*data.HSIGMA 84 | result['NLS'] = data.NLSIZE 85 | result['BTP'] = data.BTOP 86 | result['Liquidity'] = 0.35*data.STOM + 0.35*data.STOQ + 0.3*data.STOA 87 | result['EY'] = 0.68*data.EPFWD + 0.21* data.CETOP + 0.11*data.ETOP 88 | result['Growth'] = 0.18*data.EGRLF + 0.11*data.EGRSF 89 | result['Leverage'] = 0.38*data.MLEV + 0.35* data.DTOA + 0.27 * data.BLEV 90 | return result 91 | 92 | def dealna(data): 93 | data.dropna(inplace = True) 94 | tradeday = data.datetime.unique() 95 | nday = len(tradeday) 96 | data_count = data.code.value_counts() 97 | complete = data_count[data_count == nday].index.values 98 | ind = data.code.isin(complete) 99 | data = data[ind] 100 | data.index = np.arange(len(data)) 101 | return data -------------------------------------------------------------------------------- /UIconnect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Aug 18 07:01:33 2018 4 | 5 | @author: YTZzz 6 | """ 7 | from final import * 8 | from PyQt5 import QtWidgets 9 | from PyQt5.QtGui import * 10 | from PyQt5.QtWidgets import * 11 | from PyQt5.QtCore import * 12 | import Part1 13 | import Part2 14 | import Part3 15 | import Part4 16 | import pandas as pd 17 | import numpy as np 18 | 19 | 20 | path = 'D:\\citics\\Barra\\data\\' 21 | 22 | Exposure = pd.read_csv(path + 'FactorExposure.csv',encoding='utf-8_sig') 23 | FactorReturn = pd.read_csv(path + 'FactorReturn.csv', index_col = 0) 24 | raw = pd.read_csv(path + 'dataall.csv') 25 | #Specific =pd.read_csv(path+'specific_risk.csv') 26 | #tvalue = pd.read_csv(path + 'tvalue.csv',index_col = 0) 27 | #VIF = pd.read_csv(path + 'VIF.csv',inb 28 | 29 | 30 | 31 | class mywindow(QtWidgets.QMainWindow): 32 | def __init__(self): 33 | super(mywindow,self).__init__() 34 | 35 | self.firstUi = Part1.Ui_MainWindow() 36 | self.secondUi = Part2.Ui_MainWindow() 37 | self.thirdUi = Part3.Ui_MainWindow() 38 | self.fourthUi = Part4.Ui_MainWindow() 39 | 40 | tabWidget=QTabWidget(self) 41 | 42 | w3 = QMainWindow() 43 | self.thirdUi.setupUi(w3) 44 | w1 = QMainWindow() 45 | self.firstUi.setupUi(w1) 46 | w2 = QMainWindow() 47 | self.secondUi.setupUi(w2) 48 | w4 = QMainWindow() 49 | self.fourthUi.setupUi(w4) 50 | 51 | tabWidget.addTab(w3,"因子更新") 52 | tabWidget.addTab(w1,"因子收益归因") 53 | tabWidget.addTab(w2,"因子风险预测") 54 | tabWidget.addTab(w4,"有效因子筛选") 55 | 56 | tabWidget.resize(1311, 810) 57 | 58 | self.firstUi.push_button.clicked.connect(self.Attribution) 59 | self.secondUi.push_button.clicked.connect(self.RiskForecast) 60 | self.fourthUi.push_button.clicked.connect(self.EffectiveFactor) 61 | 62 | def Attribution(self): 63 | factorName= self.firstUi.factor_box.currentText() 64 | startdate = self.firstUi.calendar_start.selectedDate().toPyDate() 65 | enddate = self.firstUi.calendar_end.selectedDate().toPyDate() 66 | pofo = self.firstUi.portfolio_box.toPlainText() 67 | portfolio_return = portfolio_dcp(pofo, [factorName], Exposure, FactorReturn,str(startdate), str(enddate)) 68 | print(portfolio_return) 69 | Hheader = portfolio_return.columns.tolist() 70 | Vheader = portfolio_return.index.tolist() 71 | print(Hheader) 72 | n = portfolio_return.shape[0] 73 | m = portfolio_return.shape[1] 74 | self.firstUi.resulttable.setRowCount(n) 75 | self.firstUi.resulttable.setColumnCount(m) 76 | self.firstUi.resulttable.setHorizontalHeaderLabels(Hheader) 77 | self.firstUi.resulttable.setVerticalHeaderLabels(Vheader) 78 | for i in range(n): 79 | for j in range(m): 80 | self.firstUi.resulttable.setItem(i, j, QtWidgets.QTableWidgetItem(str(portfolio_return.iloc[i,j]))) 81 | self.firstUi.resulttable.setColumnWidth(j,200) 82 | self.firstUi.label_pic.setPixmap(QPixmap('D:\\citics\\Barra\\code\\' +'factor_attribution.png')) 83 | self.firstUi.label_pic.setScaledContents(True) 84 | 85 | def RiskForecast(self): 86 | 87 | factorName= self.secondUi.factor_box.currentText() 88 | startdate = self.secondUi.calendar_start.selectedDate().toPyDate() 89 | enddate = self.secondUi.calendar_end.selectedDate().toPyDate() 90 | Thalf = int(self.secondUi.halflife_box.toPlainText()) 91 | cmp = risk_validate(FactorReturn, factorName,str(startdate), str(enddate), TF= Thalf) 92 | self.secondUi.label_pic.setPixmap(QPixmap('D:\\citics\\Barra\\code\\' +'risk_forecast.png')) 93 | self.secondUi.label_pic.setScaledContents(True) 94 | 95 | def EffectiveFactor(self): 96 | factorName= self.fourthUi.factor_box.currentText() 97 | startdate = self.fourthUi.calendar_start.selectedDate().toPyDate() 98 | enddate = self.fourthUi.calendar_end.selectedDate().toPyDate() 99 | index = self.fourthUi.index_box.toPlainText() 100 | riskfree = float(self.fourthUi.rf_box.toPlainText()) 101 | ngroup = int(self.fourthUi.number_box.toPlainText()) 102 | group = groupvalidate(Exposure, raw,factorName, str(startdate), str(enddate), riskfree, index, ngroup) 103 | group = group.stack().unstack(0) 104 | print(group) 105 | Hheader = group.columns.tolist() 106 | Vheader = group.index.tolist() 107 | Hheader = [str(x) for x in Hheader] 108 | Vheader 109 | print(Hheader) 110 | n = group.shape[0] 111 | m = group.shape[1] 112 | self.fourthUi.resulttable.setRowCount(n) 113 | self.fourthUi.resulttable.setColumnCount(m) 114 | self.fourthUi.resulttable.setHorizontalHeaderLabels(Hheader) 115 | self.fourthUi.resulttable.setVerticalHeaderLabels(Vheader) 116 | for i in range(n): 117 | for j in range(m): 118 | self.fourthUi.resulttable.setItem(i, j, QtWidgets.QTableWidgetItem(str(group.iloc[i,j]))) 119 | self.fourthUi.resulttable.setColumnWidth(j,80) 120 | 121 | 122 | 123 | if __name__=="__main__": 124 | import sys 125 | 126 | app=QtWidgets.QApplication(sys.argv) 127 | myshow=mywindow() 128 | myshow.show() 129 | sys.exit(app.exec_()) 130 | 131 | -------------------------------------------------------------------------------- /style_factor.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from utility import * 4 | 5 | class StyleFactor(object): 6 | 7 | def __init__(self, data): 8 | self.data = data 9 | self.date = list(data.datetime) 10 | self.length = len(data) 11 | 12 | def RSTR(self, T = 504, L = 21, half_life = 126): 13 | rstr = np.tile(np.nan, self.length) 14 | for t in np.arange(T + L, self.length+1): 15 | rt = self.data.pct_chg.iloc[(t-T-L):(t-L)].copy() 16 | rft = self.data.rf.iloc[(t-T-L):(t-L)].copy() 17 | rstr[t-1] = sum((np.log(1+rt)-np.log(1+rft)) * halflife(half_life, length = T)) 18 | return rstr 19 | 20 | def DASTD(self, half_life = 42,T = 252): 21 | w = halflife(half_life, length = T) 22 | dastd = np.tile(np.nan, self.length) 23 | for t in np.arange(T, self.length): 24 | re = self.data.pct_chg[t- T:t] 25 | r_avg = sum(w * re) 26 | dastd[t] = sum(w * (re - r_avg)**2) 27 | return dastd 28 | 29 | def CMRA(self, period = 12): 30 | cmra = np.tile(np.nan, self.length) 31 | for k in np.arange(period*21, self.length): 32 | r = [] 33 | for i in range(period): 34 | r_month = np.prod(self.data.pct_chg[k-(i+1)*21:k-i*21]+1)-1 35 | rf_month = np.prod(self.data.rf[k-(i+1)*21:k-i*21]+1)-1 36 | r.append(np.log(1+r_month) - np.log(1+rf_month)) 37 | Z = np.cumsum(r) 38 | cmra[k] = np.log(1+max(Z)) - np.log(1+min(Z)) 39 | return cmra 40 | 41 | def NLSIZE(self): 42 | tradeday = self.data.datetime.unique() 43 | nlsize = np.tile(np.nan, self.length) 44 | for each in tradeday: 45 | ind = self.data.datetime == each 46 | cap = self.data.mkt_cap_ard[ind] 47 | if (all(cap.isnull())): 48 | print(each) 49 | else: 50 | lncap = np.log(cap) 51 | nlsize[ind] = non_linear_size(lncap, cap) 52 | print(each) 53 | return nlsize 54 | 55 | def BTOP(self): 56 | btop = 1 / self.data.pb 57 | return btop 58 | 59 | def STOM(self, t = 21): 60 | stom = np.tile(np.nan, self.length) 61 | for k in np.arange(t, self.length): 62 | turnover = sum(self.data.volume[k-t:k]/self.data.share_totala[k-t:k]) 63 | if turnover == 0: 64 | stom[k] = np.nan 65 | else: 66 | stom[k] = np.log(turnover) 67 | return stom 68 | 69 | def STOQ(self, stom, t=21, T=3): 70 | stoq = np.tile(np.nan, self.length) 71 | for k in np.arange(T*t, self.length): 72 | idx = k - np.arange(T) *t 73 | stoq[k] = np.log(np.nanmean(np.exp(stom.iloc[idx]))) 74 | return stoq 75 | 76 | def STOA(self, stom, t=21, T =12): 77 | stoa = np.tile(np.nan, self.length) 78 | for k in np.arange(T*t, self.length): 79 | idx = k - np.arange(T) *t 80 | stoa[k] = np.log(np.nanmean(np.exp(stom.iloc[idx]))) 81 | return stoa 82 | 83 | def EPFWD(self): 84 | epfwd = 1 / self.data.pe_est_ftm 85 | return epfwd 86 | 87 | def CETOP(self): 88 | cetop = self.data.ocfps_ttm / self.data.close 89 | return cetop 90 | 91 | def ETOP(self): 92 | etop = 1/self.data.pe_ttm 93 | return etop 94 | 95 | def EGRO(self,period): 96 | year = [x[:4] for x in self.data.datetime] 97 | time = [int(x) for x in year] 98 | eps = self.data.eps_basic 99 | n = len(year) 100 | egro = np.tile(np.nan, n) 101 | for i in np.arange(period, n): 102 | x = time[i-period:i] 103 | y = eps[i-period:i] 104 | x_avg = np.mean(x) 105 | y_avg = np.mean(y) 106 | beta = sum((x - x_avg) * (y - y_avg))/sum((x - x_avg) **2) 107 | egro[i] = beta/x_avg 108 | return egro 109 | 110 | def MLEV(self): 111 | ME = self.data.close.shift(1) * self.data.share_totala.shift(1) 112 | PE = self.data.wgsd_pfd_stk 113 | LD = self.data.wgsd_debt_lt 114 | mlev = (ME+PE+LD)/ME 115 | return mlev 116 | 117 | def DTOA(self): 118 | TD= self.data.wgsd_liabs 119 | TA= self.data.wgsd_assets 120 | dtoa = TD/TA 121 | return dtoa 122 | 123 | def BLEV(self): 124 | PE = self.data.wgsd_pfd_stk 125 | LD = self.data.wgsd_debt_lt 126 | BE = self.data.wgsd_com_eq_par 127 | blev = (BE+PE+LD) / BE 128 | return blev 129 | 130 | def factors(raw_data): 131 | codes = raw_data.code.unique( ) 132 | dfs = pd.DataFrame() 133 | for each in codes: 134 | temp = raw_data[raw_data.code == each] 135 | factor = StyleFactor(temp) 136 | exposure = temp[['datetime', 'code','volume']] 137 | exposure['MARCAP'] = temp.mkt_cap_ard.copy() 138 | exposure['LNCAP'] = np.log(temp.mkt_cap_ard) 139 | exposure['BETA'] = temp.risk_beta120.copy() 140 | exposure['RSTR'] = factor.RSTR() 141 | exposure['DASTD'] = factor.DASTD() 142 | exposure['CMRA'] = factor.CMRA() 143 | exposure['HSIGMA'] = temp.risk_residvol252.copy() 144 | exposure['BTOP'] = 1/temp.pb 145 | exposure['STOM'] = factor.STOM() 146 | exposure['STOQ'] = factor.STOQ(exposure.STOM) 147 | exposure['STOA'] = factor.STOA(exposure.STOM) 148 | exposure['EPFWD'] = factor.EPFWD() 149 | exposure['CETOP'] = factor.CETOP() 150 | exposure['ETOP'] = factor.ETOP() 151 | exposure['EGRLF'] = temp.west_netprofit_CAGR.copy() 152 | exposure['EGRSF'] = temp.west_netprofit_YOY.copy() 153 | exposure['MLEV'] = factor.MLEV() 154 | exposure['DTOA'] = factor.DTOA() 155 | exposure['BLEV'] = factor.BLEV() 156 | dfs = dfs.append(exposure) 157 | print(each) 158 | factor2 = StyleFactor(raw_data) 159 | dfs['NLSIZE'] = factor2.NLSIZE() 160 | return(dfs) -------------------------------------------------------------------------------- /regression.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from sklearn import linear_model 4 | from statsmodels.stats.outliers_influence import variance_inflation_factor 5 | import statsmodels.api as sm 6 | from utility import * 7 | path = u'D:\citics\Barra\data\\' 8 | 9 | 10 | dfs = pd.read_csv(path + 'FactorExposure.csv') 11 | raw = pd.read_csv(path + 'dataall.csv') 12 | 13 | 14 | 15 | ####通过加权回归计算因子收益率 16 | #####同时返回t值,VIF 17 | def regress(test): 18 | X = test.iloc[:,2:-2] 19 | y = np.array(test.loc[:,'return']) 20 | w = np.array(test.loc[:,'weight']) 21 | wls_model = sm.WLS(y,X, weights= w) 22 | result = wls_model.fit() 23 | factor_return = result.params 24 | f = pd.DataFrame(dict(factor_return), index =test.datetime.unique(),columns = factor_return.index) 25 | resid = result.resid 26 | pred = pd.DataFrame({'residual':resid,'code':test.code,'weight':test.weight}) 27 | t = result.tvalues 28 | vif = [variance_inflation_factor(np.array(X), i) for i in range(X.shape[1])] 29 | vif = dict(zip(X.columns, vif)) 30 | return(f, pred,t, vif) 31 | 32 | def cov_pair(ft, fk): 33 | T = len(ft) 34 | half = T/2 35 | w = halflife(half_life = half, length = T) 36 | cov = sum(w*(ft - np.mean(ft)) * (fk - np.mean(fk))) 37 | return cov 38 | 39 | def cov_mat(df,date,T = 90, delta = 0): 40 | try: 41 | loca = np.where(df.index.values == date)[0][0] 42 | mat = pd.DataFrame(index= df.columns, columns = df.columns) 43 | col = df.columns 44 | for fact1 in col: 45 | for fact2 in col: 46 | ft = np.array(df[fact1].iloc[(loca-T):loca]) 47 | fk = np.array(df[fact2].iloc[(loca - T - delta):(loca - delta)]) 48 | mat.loc[fact1,fact2] = cov_pair(ft, fk) 49 | except: 50 | print('Index out-of-bounds' ) 51 | return mat 52 | 53 | 54 | 55 | ####因子风险和现实风险比较 56 | def forecast_risk(df, T= 90): 57 | risk = pd.DataFrame(index = df.index, columns = df.columns) 58 | for i in np.arange(T,len(df)): 59 | for each in df.columns: 60 | risk[each].iloc[i] = cov_pair(df[each].iloc[(i-T):i], df[each].iloc[(i-T):i]) 61 | return risk 62 | 63 | def realized_risk(df, T = 126): 64 | risk = pd.DataFrame(index = df.index, columns = df.columns) 65 | for each in df.columns: 66 | risk[each] = df[each].rolling(window = T).var() 67 | return risk 68 | 69 | 70 | ############以下是specific risk的计算 71 | #####计算St 72 | def avg_risk(df): 73 | tradeday = df.datetime.unique() 74 | S =[] 75 | for each in tradeday: 76 | temp = df[df.datetime == each] 77 | abs_return = abs(temp['residual']) 78 | avg_return = sum(abs_return * temp.weight) 79 | S.append(avg_return) 80 | St = pd.Series(S, index = tradeday) 81 | return St 82 | 83 | ####计算Shat 84 | def avg_risk_predict(S, T = 30, a = 6): ##T是 回归的回溯时长;a value of weight 85 | E = a*S.shift(1) + a * (1-a) *S.shift(2) + a*(1-a)**2 * S.shift(3) 86 | S_hat = pd.Series(index = S.index) 87 | for i in np.arange(3+T, len(E)): 88 | y = S[(i-T):i] 89 | x = E[(i-T):i] 90 | ols_model = sm.OLS(y, x) 91 | result = ols_model.fit() 92 | S_hat[i:(i+1)] =result.predict(S[i:(i+1)]) 93 | return(S_hat) 94 | 95 | def adjustment_data(predict_data,factor, raw, a = 0.6): 96 | code = predict_data.code.unique() 97 | dfs = pd.DataFrame() 98 | for each in code: 99 | df = predict_data[predict_data.code == each].copy() 100 | raw_data = raw[raw.code == each].copy() 101 | r = abs(raw_data.pct_chg) 102 | raw_data['EWA'] = a*r.shift(1) + a * (1-a) *r.shift(2) + a*(1-a)**2 * r.shift(3) 103 | raw_data['return_lag'] = raw_data.pct_chg.shift(1) 104 | df = pd.merge(df, raw_data[['datetime','code','pct_chg','risk_residvol252','EWA','return_lag']], on = ['datetime','code'], how = 'inner') 105 | dfs = dfs.append(df) 106 | predict_data = pd.merge(dfs, factor.iloc[:,:-2], on = ['datetime','code'],how = 'inner' ) 107 | S_avg = avg_risk(predict_data) 108 | S_avg = pd.DataFrame(S_avg) 109 | S_avg.columns = ['S'] 110 | predict_data = pd.merge(predict_data, S_avg, left_on = 'datetime', right_index = True) 111 | predict_data['V'] = (abs(predict_data.residual) - predict_data.S)/ predict_data.S 112 | predict_data.drop(['S','residual','pct_chg'], axis = 1, inplace =True) 113 | predict_data.rename(columns = {'risk_residvol252': 'sigma'}, inplace = True) 114 | predict_data = predict_data.sort_values(by = ['datetime','code'], axis =0, ascending = True) 115 | return predict_data 116 | 117 | ####计算Vhat 目前还确少峰度修正k 118 | def adjustment(predict_data): 119 | predict_data.dropna(inplace = True) 120 | tradeday = predict_data.datetime.unique() 121 | V_hat = pd.DataFrame() 122 | for i in np.arange((len(tradeday)-1)): 123 | df = predict_data[predict_data.datetime == tradeday[i]].copy() 124 | dfnext = predict_data[predict_data.datetime == tradeday[i+1]].copy() 125 | V = df['V'] 126 | Z = df.iloc[:,2:-3].copy() 127 | Znext = dfnext.iloc[:,2:-3].copy() 128 | ols_model = sm.OLS(V, Z) 129 | result = ols_model.fit() 130 | V_pred = result.predict(Znext) 131 | V_pred = pd.DataFrame({'datetime':tradeday[i+1], 'code':dfnext.code,'Vhat':V_pred}, columns =['datetime','code','Vhat']) 132 | V_hat = V_hat.append(V_pred) 133 | print(tradeday[i]) 134 | V_hat.loc[V_hat.Vhat <-1,'Vhat'] = -1 135 | return V_hat 136 | 137 | 138 | a = adjustment_data(predict_data, dfs, raw) 139 | V = adjustment(a) 140 | Shat = avg_risk_predict(avg_risk(predict_data)) 141 | Shat = pd.DataFrame(Shat,columns = ['Shat']) 142 | specific_risk = pd.merge(V,Shat, left_on = 'datetime', right_index = True) 143 | specific_risk.dropna(inplace = True) 144 | specific_risk['sigma'] = specific_risk.Shat*(1 + specific_risk.Vhat) 145 | specific_risk.index = np.arange(len(specific_risk)) 146 | #specific_risk['datetime'].value_counts() 147 | specific_risk.to_csv(path + 'specific_risk.csv') 148 | return_matrix.to_csv(path + 'FactorReturn.csv') 149 | Frisk = forecast_risk(return_matrix) 150 | Rrisk = realized_risk(return_matrix) 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /Part2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'D:\citics\Barra\code\Part2.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(1311, 846) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 18 | self.label_5.setGeometry(QtCore.QRect(560, 20, 161, 91)) 19 | font = QtGui.QFont() 20 | font.setPointSize(20) 21 | font.setBold(True) 22 | font.setWeight(75) 23 | self.label_5.setFont(font) 24 | self.label_5.setObjectName("label_5") 25 | self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) 26 | self.verticalLayoutWidget.setGeometry(QtCore.QRect(40, 190, 351, 535)) 27 | self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") 28 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) 29 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) 30 | self.verticalLayout_2.setObjectName("verticalLayout_2") 31 | self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget) 32 | font = QtGui.QFont() 33 | font.setPointSize(12) 34 | font.setBold(True) 35 | font.setWeight(75) 36 | self.label_4.setFont(font) 37 | self.label_4.setObjectName("label_4") 38 | self.verticalLayout_2.addWidget(self.label_4) 39 | self.calendar_start = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 40 | font = QtGui.QFont() 41 | font.setPointSize(9) 42 | self.calendar_start.setFont(font) 43 | self.calendar_start.setObjectName("calendar_start") 44 | self.verticalLayout_2.addWidget(self.calendar_start) 45 | self.label_6 = QtWidgets.QLabel(self.verticalLayoutWidget) 46 | font = QtGui.QFont() 47 | font.setPointSize(12) 48 | font.setBold(True) 49 | font.setWeight(75) 50 | self.label_6.setFont(font) 51 | self.label_6.setObjectName("label_6") 52 | self.verticalLayout_2.addWidget(self.label_6) 53 | self.calendar_end = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 54 | font = QtGui.QFont() 55 | font.setPointSize(9) 56 | self.calendar_end.setFont(font) 57 | self.calendar_end.setObjectName("calendar_end") 58 | self.verticalLayout_2.addWidget(self.calendar_end) 59 | self.verticalLayoutWidget_3 = QtWidgets.QWidget(self.centralwidget) 60 | self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(440, 250, 122, 80)) 61 | self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3") 62 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3) 63 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) 64 | self.verticalLayout_4.setObjectName("verticalLayout_4") 65 | self.label_8 = QtWidgets.QLabel(self.verticalLayoutWidget_3) 66 | font = QtGui.QFont() 67 | font.setPointSize(12) 68 | font.setBold(True) 69 | font.setWeight(75) 70 | self.label_8.setFont(font) 71 | self.label_8.setObjectName("label_8") 72 | self.verticalLayout_4.addWidget(self.label_8) 73 | self.factor_box = QtWidgets.QComboBox(self.verticalLayoutWidget_3) 74 | font = QtGui.QFont() 75 | font.setPointSize(12) 76 | self.factor_box.setFont(font) 77 | self.factor_box.setObjectName("factor_box") 78 | self.factor_box.addItem("") 79 | self.factor_box.addItem("") 80 | self.factor_box.addItem("") 81 | self.factor_box.addItem("") 82 | self.factor_box.addItem("") 83 | self.factor_box.addItem("") 84 | self.factor_box.addItem("") 85 | self.factor_box.addItem("") 86 | self.factor_box.addItem("") 87 | self.factor_box.addItem("") 88 | self.verticalLayout_4.addWidget(self.factor_box) 89 | self.push_button = QtWidgets.QPushButton(self.centralwidget) 90 | self.push_button.setGeometry(QtCore.QRect(430, 620, 131, 41)) 91 | font = QtGui.QFont() 92 | font.setPointSize(10) 93 | self.push_button.setFont(font) 94 | self.push_button.setObjectName("push_button") 95 | self.label_pic = QtWidgets.QLabel(self.centralwidget) 96 | self.label_pic.setGeometry(QtCore.QRect(620, 280, 661, 391)) 97 | self.label_pic.setText("") 98 | self.label_pic.setObjectName("label_pic") 99 | self.label_9 = QtWidgets.QLabel(self.centralwidget) 100 | self.label_9.setGeometry(QtCore.QRect(840, 170, 331, 91)) 101 | font = QtGui.QFont() 102 | font.setPointSize(14) 103 | font.setBold(True) 104 | font.setWeight(75) 105 | self.label_9.setFont(font) 106 | self.label_9.setObjectName("label_9") 107 | self.halflife_box = QtWidgets.QTextEdit(self.centralwidget) 108 | self.halflife_box.setGeometry(QtCore.QRect(430, 470, 158, 41)) 109 | font = QtGui.QFont() 110 | font.setPointSize(12) 111 | self.halflife_box.setFont(font) 112 | self.halflife_box.setObjectName("halflife_box") 113 | self.label_10 = QtWidgets.QLabel(self.centralwidget) 114 | self.label_10.setGeometry(QtCore.QRect(430, 419, 158, 41)) 115 | font = QtGui.QFont() 116 | font.setPointSize(12) 117 | font.setBold(True) 118 | font.setWeight(75) 119 | self.label_10.setFont(font) 120 | self.label_10.setObjectName("label_10") 121 | MainWindow.setCentralWidget(self.centralwidget) 122 | self.menubar = QtWidgets.QMenuBar(MainWindow) 123 | self.menubar.setGeometry(QtCore.QRect(0, 0, 1311, 26)) 124 | self.menubar.setObjectName("menubar") 125 | MainWindow.setMenuBar(self.menubar) 126 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 127 | self.statusbar.setObjectName("statusbar") 128 | MainWindow.setStatusBar(self.statusbar) 129 | 130 | self.retranslateUi(MainWindow) 131 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 132 | 133 | def retranslateUi(self, MainWindow): 134 | _translate = QtCore.QCoreApplication.translate 135 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 136 | self.label_5.setText(_translate("MainWindow", "风险预测")) 137 | self.label_4.setText(_translate("MainWindow", "起始日")) 138 | self.label_6.setText(_translate("MainWindow", "截止日")) 139 | self.label_8.setText(_translate("MainWindow", "因子")) 140 | self.factor_box.setItemText(0, _translate("MainWindow", "Size")) 141 | self.factor_box.setItemText(1, _translate("MainWindow", "Beta")) 142 | self.factor_box.setItemText(2, _translate("MainWindow", "BTP")) 143 | self.factor_box.setItemText(3, _translate("MainWindow", "NLS")) 144 | self.factor_box.setItemText(4, _translate("MainWindow", "EY")) 145 | self.factor_box.setItemText(5, _translate("MainWindow", "Liquidity")) 146 | self.factor_box.setItemText(6, _translate("MainWindow", "Momentum")) 147 | self.factor_box.setItemText(7, _translate("MainWindow", "RV")) 148 | self.factor_box.setItemText(8, _translate("MainWindow", "Growth")) 149 | self.factor_box.setItemText(9, _translate("MainWindow", "Leverage")) 150 | self.push_button.setText(_translate("MainWindow", "导入")) 151 | self.label_9.setText(_translate("MainWindow", "因子风险预测效果")) 152 | self.label_10.setText(_translate("MainWindow", "预测半衰期")) 153 | 154 | -------------------------------------------------------------------------------- /Part1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'D:\citics\Barra\code\Part1.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(1311, 807) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 18 | self.label_5.setGeometry(QtCore.QRect(510, 20, 381, 91)) 19 | font = QtGui.QFont() 20 | font.setPointSize(20) 21 | font.setBold(True) 22 | font.setWeight(75) 23 | self.label_5.setFont(font) 24 | self.label_5.setObjectName("label_5") 25 | self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) 26 | self.verticalLayoutWidget.setGeometry(QtCore.QRect(40, 190, 351, 535)) 27 | self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") 28 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) 29 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) 30 | self.verticalLayout_2.setObjectName("verticalLayout_2") 31 | self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget) 32 | font = QtGui.QFont() 33 | font.setPointSize(12) 34 | font.setBold(True) 35 | font.setWeight(75) 36 | self.label_4.setFont(font) 37 | self.label_4.setObjectName("label_4") 38 | self.verticalLayout_2.addWidget(self.label_4) 39 | self.calendar_start = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 40 | font = QtGui.QFont() 41 | font.setPointSize(9) 42 | self.calendar_start.setFont(font) 43 | self.calendar_start.setObjectName("calendar_start") 44 | self.verticalLayout_2.addWidget(self.calendar_start) 45 | self.label_6 = QtWidgets.QLabel(self.verticalLayoutWidget) 46 | font = QtGui.QFont() 47 | font.setPointSize(12) 48 | font.setBold(True) 49 | font.setWeight(75) 50 | self.label_6.setFont(font) 51 | self.label_6.setObjectName("label_6") 52 | self.verticalLayout_2.addWidget(self.label_6) 53 | self.calendar_end = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 54 | font = QtGui.QFont() 55 | font.setPointSize(9) 56 | self.calendar_end.setFont(font) 57 | self.calendar_end.setObjectName("calendar_end") 58 | self.verticalLayout_2.addWidget(self.calendar_end) 59 | self.portfolio_box = QtWidgets.QTextEdit(self.centralwidget) 60 | self.portfolio_box.setGeometry(QtCore.QRect(430, 470, 158, 41)) 61 | font = QtGui.QFont() 62 | font.setPointSize(12) 63 | self.portfolio_box.setFont(font) 64 | self.portfolio_box.setObjectName("portfolio_box") 65 | self.label_7 = QtWidgets.QLabel(self.centralwidget) 66 | self.label_7.setGeometry(QtCore.QRect(430, 419, 158, 41)) 67 | font = QtGui.QFont() 68 | font.setPointSize(12) 69 | font.setBold(True) 70 | font.setWeight(75) 71 | self.label_7.setFont(font) 72 | self.label_7.setObjectName("label_7") 73 | self.verticalLayoutWidget_3 = QtWidgets.QWidget(self.centralwidget) 74 | self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(430, 250, 122, 80)) 75 | self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3") 76 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3) 77 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) 78 | self.verticalLayout_4.setObjectName("verticalLayout_4") 79 | self.label_8 = QtWidgets.QLabel(self.verticalLayoutWidget_3) 80 | font = QtGui.QFont() 81 | font.setPointSize(12) 82 | font.setBold(True) 83 | font.setWeight(75) 84 | self.label_8.setFont(font) 85 | self.label_8.setObjectName("label_8") 86 | self.verticalLayout_4.addWidget(self.label_8) 87 | self.factor_box = QtWidgets.QComboBox(self.verticalLayoutWidget_3) 88 | font = QtGui.QFont() 89 | font.setPointSize(12) 90 | self.factor_box.setFont(font) 91 | self.factor_box.setObjectName("factor_box") 92 | self.factor_box.addItem("") 93 | self.factor_box.addItem("") 94 | self.factor_box.addItem("") 95 | self.factor_box.addItem("") 96 | self.factor_box.addItem("") 97 | self.factor_box.addItem("") 98 | self.factor_box.addItem("") 99 | self.factor_box.addItem("") 100 | self.factor_box.addItem("") 101 | self.factor_box.addItem("") 102 | self.verticalLayout_4.addWidget(self.factor_box) 103 | self.push_button = QtWidgets.QPushButton(self.centralwidget) 104 | self.push_button.setGeometry(QtCore.QRect(430, 580, 131, 41)) 105 | font = QtGui.QFont() 106 | font.setPointSize(10) 107 | self.push_button.setFont(font) 108 | self.push_button.setObjectName("push_button") 109 | self.label_pic = QtWidgets.QLabel(self.centralwidget) 110 | self.label_pic.setGeometry(QtCore.QRect(650, 410, 601, 311)) 111 | self.label_pic.setText("") 112 | self.label_pic.setObjectName("label_pic") 113 | self.label_9 = QtWidgets.QLabel(self.centralwidget) 114 | self.label_9.setGeometry(QtCore.QRect(820, 160, 301, 51)) 115 | font = QtGui.QFont() 116 | font.setPointSize(14) 117 | font.setBold(True) 118 | font.setWeight(75) 119 | self.label_9.setFont(font) 120 | self.label_9.setObjectName("label_9") 121 | self.resulttable = QtWidgets.QTableWidget(self.centralwidget) 122 | self.resulttable.setGeometry(QtCore.QRect(660, 240, 601, 131)) 123 | self.resulttable.setObjectName("resulttable") 124 | self.resulttable.setColumnCount(0) 125 | self.resulttable.setRowCount(0) 126 | MainWindow.setCentralWidget(self.centralwidget) 127 | self.menubar = QtWidgets.QMenuBar(MainWindow) 128 | self.menubar.setGeometry(QtCore.QRect(0, 0, 1311, 26)) 129 | self.menubar.setObjectName("menubar") 130 | MainWindow.setMenuBar(self.menubar) 131 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 132 | self.statusbar.setObjectName("statusbar") 133 | MainWindow.setStatusBar(self.statusbar) 134 | 135 | self.retranslateUi(MainWindow) 136 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 137 | 138 | def retranslateUi(self, MainWindow): 139 | _translate = QtCore.QCoreApplication.translate 140 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 141 | self.label_5.setText(_translate("MainWindow", "投资组合收益分解")) 142 | self.label_4.setText(_translate("MainWindow", "起始日")) 143 | self.label_6.setText(_translate("MainWindow", "截止日")) 144 | self.label_7.setText(_translate("MainWindow", "投资组合")) 145 | self.label_8.setText(_translate("MainWindow", "因子")) 146 | self.factor_box.setItemText(0, _translate("MainWindow", "Size")) 147 | self.factor_box.setItemText(1, _translate("MainWindow", "Beta")) 148 | self.factor_box.setItemText(2, _translate("MainWindow", "BTP")) 149 | self.factor_box.setItemText(3, _translate("MainWindow", "NLS")) 150 | self.factor_box.setItemText(4, _translate("MainWindow", "EY")) 151 | self.factor_box.setItemText(5, _translate("MainWindow", "Liquidity")) 152 | self.factor_box.setItemText(6, _translate("MainWindow", "Momentum")) 153 | self.factor_box.setItemText(7, _translate("MainWindow", "RV")) 154 | self.factor_box.setItemText(8, _translate("MainWindow", "Growth")) 155 | self.factor_box.setItemText(9, _translate("MainWindow", "Leverage")) 156 | self.push_button.setText(_translate("MainWindow", "导入")) 157 | self.label_9.setText(_translate("MainWindow", "因子收益分解与风险敞口")) 158 | 159 | -------------------------------------------------------------------------------- /Part4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'D:\citics\Barra\code\Part4.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(1311, 846) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 18 | self.label_5.setGeometry(QtCore.QRect(510, 20, 381, 91)) 19 | font = QtGui.QFont() 20 | font.setPointSize(20) 21 | font.setBold(True) 22 | font.setWeight(75) 23 | self.label_5.setFont(font) 24 | self.label_5.setObjectName("label_5") 25 | self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) 26 | self.verticalLayoutWidget.setGeometry(QtCore.QRect(40, 190, 351, 535)) 27 | self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") 28 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) 29 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) 30 | self.verticalLayout_2.setObjectName("verticalLayout_2") 31 | self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget) 32 | font = QtGui.QFont() 33 | font.setPointSize(12) 34 | font.setBold(True) 35 | font.setWeight(75) 36 | self.label_4.setFont(font) 37 | self.label_4.setObjectName("label_4") 38 | self.verticalLayout_2.addWidget(self.label_4) 39 | self.calendar_start = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 40 | font = QtGui.QFont() 41 | font.setPointSize(9) 42 | self.calendar_start.setFont(font) 43 | self.calendar_start.setObjectName("calendar_start") 44 | self.verticalLayout_2.addWidget(self.calendar_start) 45 | self.label_6 = QtWidgets.QLabel(self.verticalLayoutWidget) 46 | font = QtGui.QFont() 47 | font.setPointSize(12) 48 | font.setBold(True) 49 | font.setWeight(75) 50 | self.label_6.setFont(font) 51 | self.label_6.setObjectName("label_6") 52 | self.verticalLayout_2.addWidget(self.label_6) 53 | self.calendar_end = QtWidgets.QCalendarWidget(self.verticalLayoutWidget) 54 | font = QtGui.QFont() 55 | font.setPointSize(9) 56 | self.calendar_end.setFont(font) 57 | self.calendar_end.setObjectName("calendar_end") 58 | self.verticalLayout_2.addWidget(self.calendar_end) 59 | self.verticalLayoutWidget_3 = QtWidgets.QWidget(self.centralwidget) 60 | self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(440, 250, 122, 80)) 61 | self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3") 62 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3) 63 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) 64 | self.verticalLayout_4.setObjectName("verticalLayout_4") 65 | self.label_8 = QtWidgets.QLabel(self.verticalLayoutWidget_3) 66 | font = QtGui.QFont() 67 | font.setPointSize(12) 68 | font.setBold(True) 69 | font.setWeight(75) 70 | self.label_8.setFont(font) 71 | self.label_8.setObjectName("label_8") 72 | self.verticalLayout_4.addWidget(self.label_8) 73 | self.factor_box = QtWidgets.QComboBox(self.verticalLayoutWidget_3) 74 | font = QtGui.QFont() 75 | font.setPointSize(12) 76 | self.factor_box.setFont(font) 77 | self.factor_box.setObjectName("factor_box") 78 | self.factor_box.addItem("") 79 | self.factor_box.addItem("") 80 | self.factor_box.addItem("") 81 | self.factor_box.addItem("") 82 | self.factor_box.addItem("") 83 | self.factor_box.addItem("") 84 | self.factor_box.addItem("") 85 | self.factor_box.addItem("") 86 | self.factor_box.addItem("") 87 | self.factor_box.addItem("") 88 | self.verticalLayout_4.addWidget(self.factor_box) 89 | self.push_button = QtWidgets.QPushButton(self.centralwidget) 90 | self.push_button.setGeometry(QtCore.QRect(1140, 290, 131, 41)) 91 | font = QtGui.QFont() 92 | font.setPointSize(10) 93 | self.push_button.setFont(font) 94 | self.push_button.setObjectName("push_button") 95 | self.label_9 = QtWidgets.QLabel(self.centralwidget) 96 | self.label_9.setGeometry(QtCore.QRect(780, 370, 211, 91)) 97 | font = QtGui.QFont() 98 | font.setPointSize(14) 99 | font.setBold(True) 100 | font.setWeight(75) 101 | self.label_9.setFont(font) 102 | self.label_9.setObjectName("label_9") 103 | self.rf_box = QtWidgets.QTextEdit(self.centralwidget) 104 | self.rf_box.setGeometry(QtCore.QRect(590, 291, 158, 41)) 105 | font = QtGui.QFont() 106 | font.setPointSize(12) 107 | self.rf_box.setFont(font) 108 | self.rf_box.setObjectName("rf_box") 109 | self.label_10 = QtWidgets.QLabel(self.centralwidget) 110 | self.label_10.setGeometry(QtCore.QRect(590, 240, 158, 41)) 111 | font = QtGui.QFont() 112 | font.setPointSize(12) 113 | font.setBold(True) 114 | font.setWeight(75) 115 | self.label_10.setFont(font) 116 | self.label_10.setObjectName("label_10") 117 | self.index_box = QtWidgets.QTextEdit(self.centralwidget) 118 | self.index_box.setGeometry(QtCore.QRect(770, 290, 158, 41)) 119 | font = QtGui.QFont() 120 | font.setPointSize(12) 121 | self.index_box.setFont(font) 122 | self.index_box.setObjectName("index_box") 123 | self.label_11 = QtWidgets.QLabel(self.centralwidget) 124 | self.label_11.setGeometry(QtCore.QRect(770, 239, 158, 41)) 125 | font = QtGui.QFont() 126 | font.setPointSize(12) 127 | font.setBold(True) 128 | font.setWeight(75) 129 | self.label_11.setFont(font) 130 | self.label_11.setObjectName("label_11") 131 | self.resulttable = QtWidgets.QTableWidget(self.centralwidget) 132 | self.resulttable.setGeometry(QtCore.QRect(470, 470, 811, 281)) 133 | self.resulttable.setObjectName("resulttable") 134 | self.resulttable.setColumnCount(0) 135 | self.resulttable.setRowCount(0) 136 | self.number_box = QtWidgets.QTextEdit(self.centralwidget) 137 | self.number_box.setGeometry(QtCore.QRect(960, 290, 158, 41)) 138 | font = QtGui.QFont() 139 | font.setPointSize(12) 140 | self.number_box.setFont(font) 141 | self.number_box.setObjectName("number_box") 142 | self.label_12 = QtWidgets.QLabel(self.centralwidget) 143 | self.label_12.setGeometry(QtCore.QRect(960, 240, 158, 41)) 144 | font = QtGui.QFont() 145 | font.setPointSize(12) 146 | font.setBold(True) 147 | font.setWeight(75) 148 | self.label_12.setFont(font) 149 | self.label_12.setObjectName("label_12") 150 | MainWindow.setCentralWidget(self.centralwidget) 151 | self.menubar = QtWidgets.QMenuBar(MainWindow) 152 | self.menubar.setGeometry(QtCore.QRect(0, 0, 1311, 26)) 153 | self.menubar.setObjectName("menubar") 154 | MainWindow.setMenuBar(self.menubar) 155 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 156 | self.statusbar.setObjectName("statusbar") 157 | MainWindow.setStatusBar(self.statusbar) 158 | 159 | self.retranslateUi(MainWindow) 160 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 161 | 162 | def retranslateUi(self, MainWindow): 163 | _translate = QtCore.QCoreApplication.translate 164 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 165 | self.label_5.setText(_translate("MainWindow", "有效因子筛选")) 166 | self.label_4.setText(_translate("MainWindow", "起始日")) 167 | self.label_6.setText(_translate("MainWindow", "截止日")) 168 | self.label_8.setText(_translate("MainWindow", "因子")) 169 | self.factor_box.setItemText(0, _translate("MainWindow", "Size")) 170 | self.factor_box.setItemText(1, _translate("MainWindow", "Beta")) 171 | self.factor_box.setItemText(2, _translate("MainWindow", "BTP")) 172 | self.factor_box.setItemText(3, _translate("MainWindow", "NLS")) 173 | self.factor_box.setItemText(4, _translate("MainWindow", "EY")) 174 | self.factor_box.setItemText(5, _translate("MainWindow", "Liquidity")) 175 | self.factor_box.setItemText(6, _translate("MainWindow", "Momentum")) 176 | self.factor_box.setItemText(7, _translate("MainWindow", "RV")) 177 | self.factor_box.setItemText(8, _translate("MainWindow", "Growth")) 178 | self.factor_box.setItemText(9, _translate("MainWindow", "Leverage")) 179 | self.push_button.setText(_translate("MainWindow", "导入")) 180 | self.label_9.setText(_translate("MainWindow", "因子分组收益比较")) 181 | self.label_10.setText(_translate("MainWindow", "无风险利率")) 182 | self.label_11.setText(_translate("MainWindow", "同期股指比较")) 183 | self.label_12.setText(_translate("MainWindow", "分组数")) 184 | 185 | --------------------------------------------------------------------------------