# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from sklearn.preprocessing import scale
import statsmodels.api as sm
import widgets
def load_industry_data(fname_list):
    '''
    因为万德写入xlsx的数据的大小限制,数据分散在各个文件中,这里把数据纵向拼接起来并选取所需的192个月
    :param fname_list:
    :return:
    '''
    # 将所有表示交易数据的财务数据表格读入
    data = pd.DataFrame()
    for i in fname_list:
        print 'loading', i
        temp = pd.read_excel(i)
        # 剪掉前两行中文
        temp = temp.iloc[2:, :]
        # 从2000年第一个月开始截取
        temp = temp[temp.Trdmnt >= '2000-01']
        temp = temp[temp.Trdmnt < '2016-01']
        # 拼接到data
        data = pd.concat([data, temp], axis=0)
        # 计算每只股票的市值*收益率以便稍后处理
        data['total_Mr']=data.Msmvttl*data.Mretwd
        # 把月个股流通市值提取出来,用以替代tech里面的ev
        stkcd=widgets.get_selected_Stkcd()
        flow_ev=data[['Stkcd','Trdmnt','Msmvosd']]
        flow_ev=flow_ev.set_index('Stkcd',drop=False)
        flow_ev=flow_ev.ix[stkcd.values]
        flow_ev=flow_ev.set_index(['Trdmnt'],append=True)
        flow_ev=flow_ev.unstack()
        flow_ev=flow_ev['Msmvosd']
        flow_ev=flow_ev.transpose()
        flow_ev.fillna(0,inplace=True)
#        # 将ev标准化
#        ev=pd.DataFrame(scale(ev))
    # 规整index
    data.index = range(data.shape[0])
    # 将股票代码和时间作为Multi_index
    # data=data._index(['Trdmnt','Stkcd'])
    return [data,flow_ev]

def get_ind_return(data):
    '''
    将从xlsx中读取出来按列拼接好的数据进行重组,计算出每个行业每个月的收益率
    :param [DataFrame] data: 从xlsx文件中读取的月份-交易数据
    :return: [DataFrame] ind_ret: 月份*行业 每个行业每个月的收益率
    '''
    # 读入stk_ind_pair.xlsx,用作股票和其所属行业的对照表
    stk_ind = pd.read_excel('E:\\QuantProject2\\temp_data\\stk_ind_pair.xlsx')
    # 把stk_ind里面股票代码数字部分后面的字母去掉
    stk_ind.Stkcd = stk_ind.Stkcd.apply(lambda x: x[:6])
    # 对stk_ind和data进行merge操作,将行业信息插入data
    data = pd.merge(data, stk_ind, on='Stkcd')
    # 按照月份和行业分组
    groups = data.groupby(['Trdmnt', 'ind'])
    # 分组计算每个月每个行业的总市值
    total_Ms = groups['Msmvttl'].sum()
    # 分组计算每个月每个行业按照市值加权的收益率
    total_Mr=groups['total_Mr'].sum()
    # 相除得到每个月每个行业的平均收益率
    ind_ret=total_Mr/total_Ms
    # 将ind_ret的内层level转换为列
    ind_ret=ind_ret.unstack()
    #将ind_ret标准化
    ind_ret=pd.DataFrame(scale(ind_ret),columns=ind_ret.columns)
    return ind_ret

def ind_reg_ret(ind_ret,ret):
    '''
    用行业收益率去回归股票收益率,得到股票在行业因子上的暴露。我们这里只算个暴露,就不关心鲜猪肚了
    :param DataFrame ind_ret: 行业收益率(月份*行业数)
    :param DataFrame ret: 股票收益率(月份*股票数)
    :return:
    '''
    #显著的pvalue阈值定在0.1
    pvalue_threshold=0.1
    ind_loading=np.zeros([ret.shape[1],ind_ret.shape[1]])
    # 依次取出每一只股票的收益率,与行业收益率做多元回归
    for i in range(ret.shape[1]):
        # 取出一个行业来与股票做回归
        for j in range(ind_ret.shape[1]):
            model=sm.OLS(ret.values[:,i],ind_ret.values[:,j]).fit()
            #将回归系数写入暴露矩阵
            ind_loading[i,j]=model.params[0]
        #对于pvalue小于阈值(显著)的因子,将其对应的significant_stocks_list加1
    ind_loading=pd.DataFrame(ind_loading,columns=ind_ret.columns)
    return ind_loading
if __name__ == '__main__':
    # 产生文件名
    path = 'E:\\QuantProject2\\raw_data\\'
    fname_lst = ['E:\\QuantProject2\\raw_data\\TRD_Mnth.xls']
    for i in range(6):
        fname_lst = fname_lst + ['E:\\QuantProject2\\raw_data\\TRD_Mnth' + str(i + 1) + '.xls']
    # 将所有交易数据文件按列拼好
    [data,flow_ev] = load_industry_data(fname_lst)