2022-01-14

# -*- coding: utf-8 -*-

"""

Created on Tue Dec  8 14:47:49 2020

"""

# -*- coding: utf-8 -*-

"""

V4:增加了大中小盘风格划分

V5: 改了两个产品名字的代码

V6:更正V4中错误代码;增加重仓股行业对比

v7: 将证券代码作为index,增加了无交易产品的position analysis,20200104新添加无交易产品

新增加可以跑估值表的功能

V7_1:将windclassify修改成之前日度填充的

2021.5.18:估值表产品analyze增加部分字段

【收益互换市值】【收益互换占比】【参考期货可用保证金】【期货名义本金】【期货收益额】【股票敞口】

"""

import os

import re

import math

import datetime

import pandas as pd

import numpy as np

from Factor import *

import warnings

warnings.filterwarnings("ignore")

from dateutil.relativedelta import relativedelta

min_na = 10

# 资金账户和基金名称mapping

chongyang_account_to_name = {'3852147': 'AAAAA'}

chongyang_name_to_account = {value: key for key, value in chongyang_account_to_name.items()}

# chongyang_name_to_account上面的chongyang_account_to_name,key和value交换

HS_account_to_name = {'850502406':'BBBBB'}

HS_name_to_account = {value: key for key, value in HS_account_to_name.items()}

OMS_account_to_name = {'800100012397':'CCCCC'}

OMS_name_to_account = {value: key for key, value in OMS_account_to_name.items()}

IMS_account_to_name = {'0062P0006':'DDDDD'}

IMS_name_to_account = {value: key for key, value in IMS_account_to_name.items()}

# note: 临时加了一个通汇的

onlyposi_account_to_name = {'20200812':'E1111'}

onlyposi_name_to_account = {value: key for key, value in onlyposi_account_to_name.items()}

#2021.1.4新增加无交易产品:

notrans_account_to_name = {'91111111':'F1111'}

notrans_name_to_account = {value: key for key, value in notrans_account_to_name.items()}

'''

Input Class属性:待分析产品名称,分析起止时间,pickle文件地址,原始表格地址,输出结果地址

'''

class Position_ANLS():

    # 基金名称与资金账号互查

    def __init__(self,name='',start_date='',end_date='',

                pickle_path='',rawdata_path='',output_path='',exchange_path='',

                data_freq =''):

        '''

        input:

            rawdata_path: 存放标准格式对账单的地址

            output_path: 存放positionANAS结果的地址

            start_date: 从这一天开始分析

            end_date: 到这一天结束

            data_freq: 原始数据频率。DWM

        '''

        self.account_name = name

        self.start_date = start_date

        self.end_date = end_date

        self.pickle_path = pickle_path

        self.rawdata_path = rawdata_path

        self.output_path = output_path

        self.exchange_dir=exchange_path

        self.wind_classify = pd.read_pickle(self.pickle_path + '股票/wind_classify.plk')

        self.index_member = pd.read_pickle(self.pickle_path  + 'Index/ST_indexmember.plk').reset_index().drop_duplicates().set_index(['indexcode', 'indexupdate'])

        self.ST_indexmember_fill = pd.read_pickle(self.pickle_path + 'Index/ST_indexmember_dailyfill.plk').set_index('indexupdate')

        self.indus_nav = self.cal_indus_nav()

        self.data_freq = data_freq

        self.A_style = pd.read_pickle(self.pickle_path + '股票/A_style.plk').reset_index()


        # =====================================================================

        # 调整合并数据,计算

        # =====================================================================

        # 这里将history的证券名称改为证券代码 

    # 2020.9.6

    def single_stock_monitor(self, pre_adj_price_track, adj_price_track, position_track, name_track):

        '''

        使用股票(前)复权收盘价追踪、仓位追踪、证券信息追踪四个dataframe,整理基金重仓股分析

        input:

            pre_adj_price_track: 股票前复权收盘价追踪

            adj_price_track: 股票复权收盘价追踪

            position_track: 股票仓位追踪

            name_track: 证券信息追踪。包含证券代码、证券名称、所属行业

            注意!!name_track just for mapping

            name_track's dimension can be different from than the other 3 tracks

        '''

        # 使用两次的收盘价计算收益率。不能使用股票收益率追踪计算,因为里面是单日收益率

        # 四个dataframe进行去重(Column names 防止重复)

        '''name_track = result[证券信息追踪],在第289行左右应该已经进行名称代码一起去重了,以防万一可以对index

        再次去重'''


        # 更改set_index


        return_track = (adj_price_track-pre_adj_price_track)/pre_adj_price_track

        columns_name = ['证券代码', '所属申万行业名称', '所属申万行业代码',

                        '首次出现日期', '最后出现日期', '持有天数', '期间交易日天数',

                        '个股持有期涨跌幅', '个股区间涨跌幅', '个股收益归因',

                        '所属申万行业持有期涨跌幅', '所属申万行业区间涨跌幅']

        ### 证券代码、证券名称、所属申万行业名称、所属申万行业代码

        # 这里是对特殊的debug处理:

        name_columns = name_track.columns.tolist()

        if '日期' in name_columns:

            del name_track['日期']


        '''name_track = result[证券信息追踪],在第289行左右应该已经去重了,以防万一可以对证券代码

        再次去重''' 

        name_track2 = name_track.copy()

        name_track2 = name_track2.groupby(name_track2['证券代码']).first()

        name_track2 = name_track2.reset_index()

        result = name_track2.copy().set_index('证券代码')


        ### 首次出现日期、最后出现日期、持有天数

        duration = position_track.copy() #股票参考仓位先复制过来

        duration.replace(0, np.nan, inplace = True) #把值为0的仓位变成np.nan

        duration[~duration.isnull()] = 1 #把非na的部分全部换成1

        duration = duration.cumsum(skipna = True) #可以计算累计持有天数

        # 对于每只股票,计算首次出现日期

        ss_start_time = pd.DataFrame(duration.idxmin(axis = 0)).rename(columns = {0:'首次出现日期'})

        # 对于每只股票,计算最后出现日期

        ss_end_time = pd.DataFrame(duration.idxmax(axis = 0)).rename(columns = {0:'最后出现日期'})

        # 对于每只股票,计算持有天数

        ss_duration = pd.DataFrame(duration.max(axis = 0)).rename(columns = {0:'持有天数'})

        result = pd.concat([result, ss_start_time, ss_end_time, ss_duration], axis=1)


        ### 计算从首次出现日期~最后交易日期期间的交易日天数

        duration = position_track.copy() #股票参考仓位先复制过来

        duration.replace(0, np.nan, inplace = True)#把值为0的仓位变成np.nan

        duration[~duration.isnull()] = 1#把非na的部分全部换成1

        # 两边fill na

        duration1 = duration.fillna(method = 'bfill').fillna(0)

        duration2 = duration.fillna(method = 'ffill').fillna(0)

        duration = duration1 * duration2 # 只有区间的数字是1

        duration = duration.cumsum(skipna = True)

        inter_tradeday = duration.fillna(method = 'ffill').iloc[-1:, ].T

        # 交易日天数+1

        inter_tradeday = inter_tradeday

        inter_tradeday.columns = ['期间交易日天数']

        result = pd.concat([result, inter_tradeday], axis=1)


        ### 个股持有期、区间涨跌幅

        ss_cumreturn = ((return_track+1).cumprod()-1).fillna(method = 'ffill').iloc[-1:, ].T

        ss_cumreturn.columns = ['个股持有期涨跌幅']

        tmp_end = adj_price_track.sort_index().fillna(method = 'ffill').iloc[-1,]

        tmp_start = pre_adj_price_track.sort_index().fillna(method = 'bfill').iloc[0,]

        ss_cntreturn = pd.DataFrame((tmp_end-tmp_start)/tmp_start).rename(columns = {0:'个股区间涨跌幅'}) # 得到个股区间最后价格和最初价格

        ss_cntreturn.columns = ['个股区间涨跌幅']

        result = pd.concat([result, ss_cumreturn, ss_cntreturn], axis=1)

        result.loc[result['期间交易日天数']-result['持有天数']<=min_na, '个股持有期涨跌幅'] = result.loc[result['期间交易日天数']-result['持有天数']<=min_na, '个股区间涨跌幅']


        ### 个股收益归因

        ss_cumreturm_posi = return_track.mul(position_track)

        ss_cumreturm_posi = ((ss_cumreturm_posi+1).cumprod()-1).fillna(method = 'ffill').iloc[-1:, ].T

        ss_cumreturm_posi.columns = ['个股收益归因']

        ### 所属申万行业持有期涨跌幅

        # 注意:时间不要太早。之前申万指数,一个行业会对应两个指数,现在有一个停更。如,机械设备同时对应801070和801890

        # 申万指数

        indus_return = self.indus_nav.reset_index().set_index(['trade_date', 'name'])[['sw_close']].unstack()['sw_close'] # 不能用8xxx打头的代码锁,因为港股股票的代码不同;只能直接用行业的名称锁

        indus_return = (indus_return-indus_return.shift(1)) / indus_return.shift(1)

        indus_return = pd.DataFrame(index = return_track.index).join(indus_return, how = 'left')

        indus_return = indus_return.T.sort_index().T # 按照顺序排列列名

        # 这一步返回一个矩阵,删掉了column、index,行为(0-n)天数, 28个申万行业

        indus_return = np.array(indus_return) # 矩阵:天数*28行业涨跌幅


        duration = position_track.copy()

        duration.replace(0, np.nan, inplace = True)

        duration[~duration.isnull()]=1

        # Na变为0

        duration.fillna(0, inplace = True)

        #将duration transpose后,reindex as 代码

        #duration = np.array(duration.T.reindex(name_track['证券名称'])) # 矩阵:股票数量*天数

        # debug:储存矩阵:股票*日期

        durationT = duration.T.reindex(name_track2['证券代码'])

        # 矩阵index,columns均为0

        duration = np.array(duration.T.reindex(name_track2['证券代码']))


        #ss_indus = name_track[['证券名称', '所属申万行业']].set_index(['证券名称', '所属申万行业'])

        ss_indus = name_track2[['证券代码', '所属申万行业']].set_index(['证券代码', '所属申万行业'])

        ss_indus['type'] = 1

        ss_indus = ss_indus.unstack(fill_value = np.nan)['type']

        ss_indus = ss_indus.T.reindex(sw1_to_name.values()).fillna(np.nan).sort_index().T

        ss_indus = np.array(ss_indus) # 矩阵:股票数量*28各行业


        indus_cumreturn = np.dot(duration, indus_return)

        indus_cumreturn = np.multiply(indus_cumreturn, ss_indus)

        #indus_cumreturn = pd.DataFrame(indus_cumreturn, index = name_track['证券名称'], columns = sorted(sw1_to_name.values()))

        indus_cumreturn = pd.DataFrame(indus_cumreturn, index = name_track2['证券代码'], columns = sorted(sw1_to_name.values()))

        indus_cumreturn = pd.DataFrame(indus_cumreturn.stack())

        indus_cumreturn.columns = ['所属申万行业持有期涨跌幅']

        indus_cumreturn = indus_cumreturn[~indus_cumreturn['所属申万行业持有期涨跌幅'].isnull()].reset_index()[['证券代码', '所属申万行业持有期涨跌幅']].set_index('证券代码')


        ### 所属申万行业区间涨跌幅

        duration = position_track.copy()

        duration.replace(0, np.nan, inplace = True)

        duration[~duration.isnull()]=1

        duration1 = duration.fillna(method = 'bfill').fillna(0)

        duration2 = duration.fillna(method = 'ffill').fillna(0)

        duration = duration1 * duration2 # 只有区间的数字是1

        duration = np.array(duration.T.reindex(name_track2['证券代码']))



        indus_cntreturn = np.dot(duration, indus_return)

        indus_cntreturn = np.multiply(indus_cntreturn, ss_indus)

        indus_cntreturn = pd.DataFrame(indus_cntreturn, index = name_track2['证券代码'], columns = sorted(sw1_to_name.values()))

        indus_cntreturn = pd.DataFrame(indus_cntreturn.stack())

        indus_cntreturn.columns = ['所属申万行业区间涨跌幅']

        indus_cntreturn = indus_cntreturn[~indus_cntreturn['所属申万行业区间涨跌幅'].isnull()].reset_index()[['证券代码', '所属申万行业区间涨跌幅']].set_index('证券代码')

        ### 合并

        result = pd.concat([result, ss_cumreturm_posi, indus_cumreturn, indus_cntreturn], axis=1)



        result.columns = columns_name

        result['持有天数'].fillna(0, inplace = True)

        #这一步,只保留持有天数>0的重仓股

        result = result[result['持有天数']>0]

        return result


    def position_ANLS(self,balance,position,transaction):

        '''

        position anlysis

        :param balance: DataFrame balance sheet

        :param position: DataFrame position sheet

        :param transaction: DataFrame transaction sheet

        :return: dict, 7 DataFrame, result of position anlysis

        input:

            标准化对账单后,某一日某一只基金的balance, position, transaction

        output:

            dict:

                keys: 持仓综合信息追踪,持仓风格追踪,港股配置需求,股票参考仓位追踪,股票市值分布,股票市值追踪,股票收益率追踪,股票收盘价追踪,股票前复权收盘价追踪,股票复权收盘价追踪,股票数量追踪,行业配置追踪,证券信息追踪

        '''

        # 2020.9.6

        if len(balance) == 0:

            return {'持仓综合信息追踪' : None, '行业配置需求' : None, '港股配置需求' : None,

                    '股票参考仓位追踪' : None, '股票收盘价追踪' : None,'股票前复权收盘价追踪' : None,

                    '股票复权收盘价追踪' : None, '股票数量追踪' : None,

                    '股票市值追踪' : None, '股票市值分布' : None, '股票收益率追踪' : None,

                    '持仓风格追踪': None, '证券信息追踪' : None}

        date = pd.to_datetime(str(balance['日期'].iloc[0]))

        date,H_date,A_predate,H_predate,H_exchange_date,H_exchangepredate = self.get_predate_samefreq(date)


        summary = pd.DataFrame(columns=['资金余额','证券市值','实际帐户总资产',"实际账户净资产",

                                        'A股股票市值','H股股票市值','A股股票仓位',

                                        'H股股票仓位','债券市值','债券仓位',

                                        '基金市值','基金仓位','A股股票只数',

                                        'H股股票只数','前五大股票集中度','前十大股票集中度',

                                        'A股行业数量','H股行业数量','前三大行业集中度','前五大行业集中度',

                                        'A股pe_ttm','H股pe_ttm','A股pe_ttm_平权','H股pe_ttm_平权','A股pb','H股pb',

                                        'A股pb_平权','H股pb_平权','A股股息率','H股股息率','A股净利润增速_加权','A股净利润增速_平权',

                                        'H股净利润增速_加权','H股净利润增速_平权','成交额A股','成交额H股','行业轮动',

                                        '股票市值','股票仓位', '成交额'], index = [date])   

# 2021.5.28

        if self.formtype in ['GuoJun', 'ZhaoShang']:

            summary['股票敞口'] = balance['股票敞口'].values

            summary['参考期货可用保证金'] = balance['参考期货可用保证金'].values

            summary['期货名义本金'] = balance['期货名义本金'].values

            summary['期货收益额'] = balance['期货收益额'].values

            summary['收益互换市值'] = balance['收益互换市值'].values

            summary['收益互换占比'] = balance['收益互换市值'].values/balance['净资产'].values

        summary['资金余额'] = balance['资金余额'].sum()

        balance['H股市值RMB(结算买入)'] = balance['H股市值']*balance['结算买入汇率']

        summary['证券市值'] = balance['证券市值'].values

        summary['实际帐户总资产'] = balance['资产总值'].values

        summary["实际账户净资产"] = balance["净资产"].values if "净资产" in balance.columns else np.nan

        summary['A股股票市值'] = balance['A股市值'].values

        summary['H股股票市值'] = balance['H股市值RMB(结算买入)'].values

        summary['债券市值'] = balance['债券市值'].values

        summary['基金市值'] = balance['基金市值'].values

# 估值表可以看到负债信息,计算仓位的时候用净资产

        if self.formtype in ['重阳对账单', 'HS', 'OMS', 'IMS', '对账单_只有持仓', '无交易产品']:

            demoninator = summary['实际帐户总资产']

        elif self.formtype in ['GuoJun', 'ZhaoShang',"海通证券","国泰君安","中信证券"]:

            demoninator = balance['净资产'].values

        summary['A股股票仓位'] = summary['A股股票市值'] / demoninator

        summary['H股股票仓位'] = summary['H股股票市值'] / demoninator

        summary['债券仓位'] = summary['债券市值'] / demoninator

        summary['基金仓位'] = summary['基金市值'] / demoninator

        summary['A股股票只数'] = len(position[position['证券类型'] == 'A股'])

        summary['H股股票只数'] = len(position[position['证券类型'] == 'H股'])

        stock_position = position[(position['证券类型'] == 'A股') | (position['证券类型'] == 'H股')]

        stock_position['持仓市值RMB(结算买入)'] = stock_position['持仓市值'] * stock_position['结算买入汇率'].fillna(1)

        stock_position = stock_position.sort_values(by = '持仓市值RMB(结算买入)', ascending = False)

        summary['前五大股票集中度'] = stock_position.iloc[0:5]['持仓市值RMB(结算买入)'].sum() / summary['实际帐户总资产']

        summary['前十大股票集中度'] = stock_position.iloc[0:10]['持仓市值RMB(结算买入)'].sum() / summary['实际帐户总资产']

        summary['A股行业数量'] = len(position[position['证券类型'] == 'A股'].groupby(['所属申万行业']).size())

        summary['H股行业数量'] = len(position[position['证券类型'] == 'H股'].groupby(['所属申万行业']).size())

        summary['股票市值'] = summary['A股股票市值'] + summary['H股股票市值']

        summary['股票仓位'] = summary['A股股票仓位'] + summary['H股股票仓位']


        A_industry_cap_tmp = stock_position[position['证券类型'] == 'A股'].groupby('所属申万行业')['持仓市值RMB(结算买入)'].sum()

        H_industry_cap_tmp = stock_position[position['证券类型'] == 'H股'].groupby('所属申万行业')['持仓市值RMB(结算买入)'].sum()

        A_industry_cap = pd.DataFrame(index=[value for key,value in sw1_to_name.items()])       

        A_industry_cap = A_industry_cap.join(A_industry_cap_tmp).fillna(0)

        H_industry_cap = pd.DataFrame(index=[value for key,value in HKSW_to_name.items()])       

        H_industry_cap = H_industry_cap.join(H_industry_cap_tmp).fillna(0)


        industry_cap = pd.concat([A_industry_cap,H_industry_cap],axis=1,sort=True).fillna(0).sum(axis=1).sort_values(ascending=False)

        try:

            A_pepbdividend = A_market[['pe_ttm','pb']].loc[date].loc[position[position['证券类型'] == 'A股']['证券代码']]


        except:

            A_pepbdividend = pd.DataFrame(position[position['证券类型'] == 'A股']['证券代码'])

            A_market_tmp = A_market[['pe_ttm','pb']].loc[date]

            A_pepbdividend['pe_ttm'] = A_pepbdividend['证券代码'].apply(lambda x:A_market_tmp['pe_ttm'].loc[x] if x in A_market_tmp.index.drop_duplicates().to_list() else None)

            A_pepbdividend['pb'] = A_pepbdividend['证券代码'].apply(lambda x:A_market_tmp['pb'].loc[x] if x in A_market_tmp.index.drop_duplicates().to_list() else None)

        A_pepbdividend['股息率'] = np.nan

        A_pepbdividend['net_profit_qoq'] = np.nan

        A_pepbdividend['cap'] = stock_position[stock_position['证券类型'] == 'A股']['持仓市值'].to_list()


        H_pepbdividend = H_market[['pe_ttm','pb']].loc[date].loc[stock_position[stock_position['证券类型'] == 'H股']['证券代码']]

        H_pepbdividend['股息率'] = np.nan

        H_pepbdividend['net_profit_qoq'] = np.nan 

        H_pepbdividend['cap'] = stock_position[stock_position['证券类型'] == 'H股']['持仓市值RMB(结算买入)'].to_list()



        summary['前三大行业集中度'] = industry_cap.iloc[0:3].sum() / summary['实际帐户总资产']

        summary['前五大行业集中度'] = industry_cap.iloc[0:5].sum() / summary['实际帐户总资产']

        summary['A股pe_ttm'] = (A_pepbdividend['pe_ttm'] * A_pepbdividend['cap']).sum() / A_pepbdividend['cap'].sum()

        summary['A股pe_ttm'] = summary['A股pe_ttm'].replace(0,np.nan)

        summary['A股pe_ttm_平权'] = A_pepbdividend['pe_ttm'].mean()

        summary['A股pb'] = (A_pepbdividend['pb'] * A_pepbdividend['cap']).sum() / A_pepbdividend['cap'].sum()

        summary['A股pb'] = summary['A股pb'].replace(0,np.nan).values

        summary['A股pb_平权'] = A_pepbdividend['pb'].mean()

        summary['A股股息率'] = (A_pepbdividend['股息率'] * A_pepbdividend['cap']).sum() / A_pepbdividend['cap'].sum()

        summary['A股股息率'] = summary['A股股息率'].replace(0,np.nan)


        summary['H股pe_ttm'] = (H_pepbdividend['pe_ttm'] * H_pepbdividend['cap']).sum() / H_pepbdividend['cap'].sum()

        summary['H股pe_ttm_平权'] = H_pepbdividend['pe_ttm'].mean()

        summary['H股pe_ttm'] = summary['H股pe_ttm'].replace(0,np.nan)

        summary['H股pb'] = (H_pepbdividend['pb'] * H_pepbdividend['cap']).sum() / H_pepbdividend['cap'].sum()

        summary['H股pb_平权'] = H_pepbdividend['pb'].mean()

        summary['H股股息率'] = (H_pepbdividend['股息率'] * H_pepbdividend['cap']).sum() / H_pepbdividend['cap'].sum()

        summary['H股股息率'] = summary['H股股息率'].replace(0,np.nan)

        summary['A股净利润增速_加权'] = (A_pepbdividend['net_profit_qoq'] * A_pepbdividend['cap']).sum() / A_pepbdividend['cap'].sum()

        summary['A股净利润增速_平权'] = A_pepbdividend['net_profit_qoq'].mean()


        summary['H股净利润增速_加权'] = (H_pepbdividend['net_profit_qoq'] * H_pepbdividend['cap']).sum() / H_pepbdividend['cap'].sum()

        summary['H股净利润增速_平权'] = H_pepbdividend['net_profit_qoq'].mean()     

        buy = transaction[transaction['交易类型'] == '买入']

        sell = transaction[transaction['交易类型'] == '卖出']

        summary['成交额A股'] = buy[buy['证券类型'] == 'A股']['成交金额'].sum() + sell[sell['证券类型'] == 'A股']['成交金额'].sum()

        summary['成交额H股'] = buy[buy['证券类型'] == 'H股']['成交金额'].sum() + sell[sell['证券类型'] == 'H股']['成交金额'].sum()*balance['结算买入汇率'].values

        summary['成交额'] = summary['成交额A股'] + summary['成交额H股']


        indus_config = pd.DataFrame((industry_cap / summary['实际帐户总资产'].sum())).T

        indus_config.index = [date]

        H_indus_config = pd.DataFrame((H_industry_cap / summary['实际帐户总资产'].sum())).T

        H_indus_config.index = [date]


        track = stock_position

# 2020.9.9

        track = track[track['持仓市值RMB(结算买入)']>0]



        try:

            track['close'] = A_nav.loc[date]['close'].loc[track['证券代码']].fillna(value=H_nav.loc[H_date]['close'].loc[track['证券代码']]).to_list()

            track['adj_close'] = A_nav.loc[date]['adj_close'].loc[track['证券代码']].fillna(value=H_nav.loc[H_date]['adj_close'].loc[track['证券代码']]).to_list()

            track['pre_adj_close'] = A_nav.loc[A_predate]['adj_close'].loc[track['证券代码']].fillna(value=H_nav.loc[H_predate]['adj_close'].loc[track['证券代码']]).to_list()

# 2020.9.9

        except:

            try:

                track['close'] = A_nav.loc[date]['close'].loc[track['证券代码']].to_list()

                track['adj_close'] = A_nav.loc[date]['adj_close'].loc[track['证券代码']].to_list()

                track['pre_adj_close'] = A_nav.loc[A_predate]['adj_close'].loc[track['证券代码']].to_list()

            except:

                try:

                    track['close'] = H_nav.loc[H_date]['close'].loc[track['证券代码']].to_list()

                    track['adj_close'] = H_nav.loc[H_date]['adj_close'].loc[track['证券代码']].to_list()

                    track['pre_adj_close'] = H_nav.loc[H_predate]['adj_close'].loc[track['证券代码']].to_list()

                except:

                    if len(track) == 1:

                        track['close'] = None

                        track['adj_close'] = None

                        track['pre_adj_close'] = None

#                        track['returns'] = None

                    else:

                        track['close'] = track['证券代码'].apply(lambda x:A_nav.loc[date]['close'].loc[x] if x in A_nav.loc[date]['close'].index.drop_duplicates().to_list() else H_nav.loc[H_date]['close'].loc[x] if x in H_nav.loc[H_date]['close'].index.drop_duplicates().to_list() else None)

                        track['adj_close'] = track['证券代码'].apply(lambda x:A_nav.loc[date]['adj_close'].loc[x] if x in A_nav.loc[date]['adj_close'].index.drop_duplicates().to_list() else H_nav.loc[H_date]['adj_close'].loc[x] if x in H_nav.loc[date]['adj_close'].index.drop_duplicates().to_list() else None)

                        track['pre_adj_close'] = track['证券代码'].apply(lambda x:A_nav.loc[A_predate]['adj_close'].loc[x] if x in A_nav.loc[A_predate]['adj_close'].index.drop_duplicates().to_list() else H_nav.loc[H_predate]['adj_close'].loc[x] if x in H_nav.loc[H_predate]['adj_close'].index.drop_duplicates().to_list() else None)

        # 2020.9.6

        # 如果是新股,可能会提取不到close等信息。标准化对账单中的收盘价都是ipo价格,可以直接填充。

        track['close'].fillna(track['收盘价'], inplace = True)

        track['adj_close'].fillna(track['收盘价'], inplace = True)

        track['pre_adj_close'].fillna(track['前收盘价'], inplace = True)

        # 2020.9.6     

        name_track = position[['日期', '证券代码','证券名称','证券类型', '所属申万行业', '所属申万行业代码']]

        A_name_track = name_track[name_track['证券类型']=='A股']

        H_name_track = name_track[name_track['证券类型']=='H股']

        H_name_track['证券名称'] = H_name_track['证券名称'] + '(HK)'

        # 2020.9.6

        name_track = pd.concat([A_name_track,H_name_track]).set_index('日期')

        del name_track['证券类型']


        position_track = pd.DataFrame(track['持仓市值RMB(结算买入)'] / summary['实际帐户总资产'].sum()).T

        position_track.columns = track['证券代码']

        position_track.index = [date]


        price_track = pd.DataFrame(track['close']).T

        price_track.columns = track['证券代码']

        price_track.index = [date]


        adj_price_track = pd.DataFrame(track['adj_close']).T

        adj_price_track.columns = track['证券代码']

        adj_price_track.index = [date]


        pre_adj_price_track = pd.DataFrame(track['pre_adj_close']).T

        pre_adj_price_track.columns = track['证券代码']

        pre_adj_price_track.index = [date]

        volume_track = pd.DataFrame(track['持仓数量']).T

        volume_track.columns = track['证券代码']

        volume_track.index = [date]

# 2020.9.9     

        returns_track = pd.DataFrame(track['adj_close']/track['pre_adj_close']-1).T

        returns_track.columns = track['证券代码']

        returns_track.index = [date]


        #个股持仓市值track

        marketval_track = pd.DataFrame(track['持仓市值RMB(结算买入)']).T

        marketval_track.columns = track['证券代码']

        marketval_track.index = [date]     

        try:

            try:

                track['circulating_market_cap'] = A_market.loc[date]['circulating_market_cap'].loc[track['证券代码']].fillna(value=H_market.loc[date]['circulating_market_cap'].loc[track['证券代码']]).to_list()

            except:

                #不用全港股的情况!!!!

                track['circulating_market_cap'] = A_market.loc[date]['circulating_market_cap'].loc[track['证券代码']].to_list()

            #市值:万元

            cap_dist = track[['持仓市值RMB(结算买入)','circulating_market_cap']].dropna()

            cap_dist['type'] = cap_dist['circulating_market_cap'].apply(lambda x: (x>1e6)+(x>3e6)+(x>5e6)+(x>1e7))

            cap_dist = cap_dist['持仓市值RMB(结算买入)'].groupby(cap_dist['type']).sum()

            cap_dist = pd.DataFrame(cap_dist / (summary['A股股票市值']+summary['H股股票市值']).sum()).T

            cap_dist = pd.concat([cap_dist,pd.DataFrame(columns=[0,1,2,3,4])])

            cap_dist = cap_dist.fillna(0)

            cap_dist.columns = ['<100亿','100亿','300亿','500亿','1000亿']

            cap_dist.index = [date]

        except:

            cap_dist = pd.DataFrame(columns = ['<100亿','100亿','300亿','500亿','1000亿'],index=[date])

        return {'持仓综合信息追踪' : summary, '行业配置需求' : indus_config, '港股配置需求' : H_indus_config,

                '股票参考仓位追踪' : position_track, '股票收盘价追踪' : price_track,

                '股票前复权收盘价追踪' : pre_adj_price_track, '股票复权收盘价追踪' : adj_price_track,

                '股票数量追踪' : volume_track,'股票市值追踪' : marketval_track, '股票市值分布' : cap_dist,

                '股票收益率追踪' : returns_track, '证券信息追踪' : name_track}


    def _position_classify(self,position):

        '''

        Parameters

        ----------

        position : DataFrame: 增量的个股仓位数据

        Returns

        -------

        output:Dataframe: 九大类风格的仓位数据

        '''

        A_style = self.A_style.copy()

        all_output = pd.DataFrame()

        for i in range(len(position)):

            position_single = pd.DataFrame(position.iloc[i]).T

            result = pd.DataFrame(index = pd.MultiIndex.from_product([list(position_single.index.values),

                                                                      list(position_single.columns.values)])).reset_index()

            result.columns = ['trade_date','code']

            result['year'] = result['trade_date'].map(lambda x: str(x.year))

            A_style['year'] = A_style['year'].astype(str)

            #补充Astyle里面没有的年份

            if str(result['year'].iloc[0]) not in A_style['year'].drop_duplicates().to_list():

                result['year'] = result['year'].apply(lambda x:max(A_style['year'].to_list()))

# 风格的pickle有问题

            result['year'] = result['year'].astype(str)

            result.to_excel('result0.xlsx')

            result = pd.merge(result,A_style,on=['year','code'],how = 'left').set_index(['trade_date','code'])

            result.to_excel('result1.xlsx')

            del result['year']

            result = result.dropna(how='all').astype('int')

            if result.shape[0]:

                result['成长型'] = result['大盘成长型']+result['中盘成长型']+result['小盘成长型']

                result['均衡型'] = result['大盘均衡型']+result['中盘均衡型']+result['小盘均衡型']

                result['价值型'] = result['大盘价值型']+result['中盘价值型']+result['小盘价值型']

                result = result[['成长型', '均衡型', '价值型']].reset_index()

                result = result.melt(id_vars = ['trade_date', 'code'], var_name = ['风格'])   

                result = result[result['value']==1]

                del result['value']

                #开始判断大中小盘,注意这里的trade_date multiple

                result.to_excel('result2.xlsx')

                date = result['trade_date'].iloc[0]

                hushen300 = self.ST_indexmember_fill[self.ST_indexmember_fill['indexname'] == '沪深300'].loc[date]['code'].tolist()

                zhongzheng500 = self.ST_indexmember_fill[self.ST_indexmember_fill['indexname'] == '中证500'].loc[date]['code'].tolist()

                result['市值'] = result['code'].apply(lambda x: '大盘' if x in hushen300 else ('中盘' if x in zhongzheng500 else '小盘'))

                result['真实风格'] = result['市值']+result['风格']

                result['仓位'] = result['code'].apply(lambda x: float(position_single[x].values)) #float(position_single[x].values)

                #汇总成九个字段表

                result2 = result.groupby('真实风格')['仓位'].sum()

                total = result2.sum()

                output = pd.DataFrame(result2/total)

                index = ['小盘价值型', '小盘均衡型', '小盘成长型', '中盘价值型', '中盘均衡型', '中盘成长型', '大盘价值型', '大盘均衡型', '大盘成长型']

                output = output.reindex(index).T

                output.index = pd.Series(date,name = 'trade_date')

                output = output.fillna(value = 0)

                output['大盘'] = output['大盘价值型'] + output['大盘均衡型'] + output['大盘成长型']

                output['中盘'] = output['中盘价值型'] + output['中盘均衡型'] + output['中盘成长型']

                output['小盘'] = output['小盘价值型'] + output['小盘均衡型'] + output['小盘成长型']

            else:

                output = pd.DataFrame()

            all_output = pd.concat([all_output, output])

        return all_output


    def _position_track(self,result,name_list):

        '''

        仓位追踪

        '''

        mv_indT10 = (result['行业配置需求'][-1:].T/result['持仓综合信息追踪']['股票仓位'][-1:].values[0]) * result['持仓综合信息追踪']['股票市值'][-1:].values[0]

        #绝对仓位

        weight_indT10 = result['行业配置需求'][-1:].T

        indT10 = pd.concat([mv_indT10,weight_indT10],axis=1,ignore_index=False)

        indT10.columns = ['市值','仓位']

        indT10 = indT10.sort_values(by='市值',ascending = False)

        #差一列个股数量


        #Add_xw 十大重仓个股。期末,更新日当天的十大重仓股

        weight_stockT10 = result['股票参考仓位追踪'][-1:].T.dropna()

        mk_stockT10 = result['股票市值追踪'][-1:].T.dropna()

        quant_stockT10 = result['股票数量追踪'][-1:].T.dropna()

        stockT10 = pd.concat([mk_stockT10,weight_stockT10,quant_stockT10],axis=1,ignore_index=False)

        stockT10.columns = ['市值','仓位','持有数量']

        stockT10 = stockT10.sort_values(by='市值',ascending = False)


        # 问题:这里选择major_holding的思路和上面StockT10的结果可能不同

        max_weight = result['股票参考仓位追踪'].mean().sort_values(ascending=False).head(5)

        max_time = result['股票参考仓位追踪'].count().sort_values(ascending=False).head(5)

        major_holding = pd.concat([max_time,max_weight],axis=1).sort_values([0,1],ascending=False)

        # 有个股票平均权重大,但是持有天数不是很大,通过下面这一步,填充这些股票的持有天数

        major_holding['time'] = result['股票参考仓位追踪'].count().sort_values(ascending=False).loc[major_holding.index]

        major_holding['time_rank'] = major_holding['time'].rank(method='first',ascending=False)

        major_holding['weight'] = result['股票参考仓位追踪'].mean().sort_values(ascending=False).loc[major_holding.index]

        major_holding['weight_rank'] = major_holding['weight'].rank(method='first',ascending=False)

        major_holding_dict = {}  #key:mojor_holding股票的名字;value:对应的df

        # 生成字典major_holding_dict过程

        for i in major_holding.index:

            major_holding_track = pd.concat([result['股票数量追踪'][i],result['股票参考仓位追踪'][i],result['股票收盘价追踪'][i],result['股票收益率追踪'][i]],axis=1)

            major_holding_track.columns = ['数量','仓位','收盘价','累计收益额']



            code_temp = name_list[name_list['证券名称']==i].index[0]

            # 这只股票的数量,仓位,收盘价,累计收益额都是已知的

            # 下面步骤的目的是生成持有天数,平均仓位,累计收益三列

            if '.SH' in code_temp or '.SZ' in code_temp:

                try:

                    major_holding_track['收盘价'] = A_nav['close'].loc[major_holding_track.index].unstack()[code_temp]

                    major_holding_track['累计收益额'] = A_return_data['returns'].loc[major_holding_track.index].unstack()[code_temp]

                except:

                    major_holding_track['收盘价'] = None

                    major_holding_track['累计收益额'] = 0

            elif '.HK' in code_temp:

                try:

                    major_holding_track['收盘价'] = H_nav['close'].loc[major_holding_track.index].unstack()[code_temp]

                    major_holding_track['累计收益额'] = H_return_data['returns'].loc[major_holding_track.index].unstack()[code_temp]

                except:

                    if major_holding_track.index > pd.to_datetime('20161205'):

                        date,H_date,A_predate,H_predate,H_exchange_date,H_exchangepredate = self.get_predate_samefreq(major_holding_track.index)

                    else:

                        H_date = major_holding_track.index

                    major_holding_track['收盘价'] = H_nav['close'].loc[H_date][code_temp]

                    major_holding_track['累计收益额'] = H_return_data['returns'].loc[H_date][code_temp]


            major_holding_track['累计收益额'] = (result['持仓综合信息追踪']['实际帐户总资产'].loc[major_holding_track.index] * major_holding_track['仓位']).shift() * major_holding_track['累计收益额']

            major_holding_track['累计收益额'] = major_holding_track['累计收益额'].cumsum()

            # 定义cuminc和close_price的目的是把累计收益额和收盘价移动到第一二列

            cuminc= major_holding_track['累计收益额']

            close_price = major_holding_track['收盘价']

            major_holding_track =  major_holding_track.drop('收盘价', axis=1)

            major_holding_track =  major_holding_track.drop('累计收益额', axis=1)

            major_holding_track.insert(0, '收盘价', close_price)

            major_holding_track.insert(0, '累计收益额', cuminc)           

            major_holding_track = pd.concat([major_holding_track,pd.DataFrame(columns=['','持有天数','平均仓位','累计收益'])],axis=1)

            major_holding_track['持有天数'].iloc[0] = major_holding['time'].loc[i]

            major_holding_track['平均仓位'].iloc[0] = major_holding['weight'].loc[i]

            # 累计收益,是当天的累计收益额,也就是累计收益额的最后一个

            try:

                major_holding_track['累计收益'].iloc[0] = major_holding_track['累计收益额'].dropna().iloc[-1]

            except:

                major_holding_track['累计收益'].iloc[0] = 0

            sheet_name = '%s_T&W_%d&%d'%(i,major_holding.loc[i]['time_rank'],major_holding.loc[i]['weight_rank'])

            major_holding_dict[sheet_name] = major_holding_track


        # Add_xw, 换手率及行业轮动率页面

        # 不可以只用更新的信息

        # change

        result['持仓综合信息追踪']['日期'] = result['持仓综合信息追踪'].index.values

        # 日期里面只包含年和月

        result['持仓综合信息追踪']['日期'] = result['持仓综合信息追踪']['日期'].apply(lambda x:datetime.datetime.strftime(x,'%Y-%m'))

        # 分子是每个月的成交总额

        # 分母是这一个月的股票平均持有市值

        turnover_stock = 12*(result['持仓综合信息追踪']['成交额'].groupby(result['持仓综合信息追踪']['日期']).sum()/result['持仓综合信息追踪']['股票市值'].groupby(result['持仓综合信息追踪']['日期']).mean())

        # 一个月的行业轮动求和

        turnover_industry = 12*result['持仓综合信息追踪']['行业轮动'].groupby(result['持仓综合信息追踪']['日期']).sum()

        # 平均股票仓位

        stock_weight = result['持仓综合信息追踪']['股票仓位'].groupby(result['持仓综合信息追踪']['日期']).mean()

        turnover = pd.concat([stock_weight,turnover_stock,turnover_industry],axis=1,ignore_index=False)

        turnover.columns = ['股票仓位','换手率','行业轮动率']

        result['持仓综合信息追踪'] = result['持仓综合信息追踪'].drop(columns=['股票市值','股票仓位', '成交额','日期'])

        # 问题:丢掉了四列

        return result,turnover,indT10,stockT10,major_holding_dict




    # 频率判断函数

    def get_freq(self, date_list):

        date_range = pd.to_datetime(date_list[-1])-pd.to_datetime(date_list[0])

        size = pd.to_timedelta(len(date_list),'D')

        # 日度数据

        if date_range/size < 2:

            return '日度'

        # 周度月度数据

        else:

            return '非日度'


    def cal_data(self,path,stock_type):

        start_time = pd.to_datetime(self.start_date)

        end_time = pd.to_datetime(self.end_date)

        industry = pd.read_pickle(path + '股票/' + stock_type + '_industry.plk')

        industry = industry[start_time:end_time]

        market = pd.read_pickle(path + '股票/'+ stock_type + '_market_data.plk')

        market = market.dropna(how='all')[start_time:end_time]

        nav = pd.read_pickle(path + '股票/' + stock_type + '_nav_data.plk')

        nav = nav.dropna(how='all')[start_time-datetime.timedelta(days=10):end_time]

        # 2020.9.6:

        nav['adj_close'] = nav['close']*nav['adj_factor']

        fundamental = pd.read_pickle(path + '股票/' + stock_type + '_fundamental_data.plk')

        fundamental = fundamental.dropna(how='all')[start_time:end_time]

        return_df = self._cal_returns(nav)

        return return_df,industry,market,nav


    def _cal_net_profit(self,fundamental,stock_type):

        '''

        处理净利润,缺失值用过去四季度滚动平均代替

        公式待更新

        '''

        df = fundamental.copy()

        if stock_type == 'A':

            is_report = df['net_profit'].unstack().diff().fillna(0).astype(bool).replace(False,np.nan)

            net_profit = is_report * pd.DataFrame(df['net_profit'].unstack())

        elif stock_type == 'HK':

            is_report = df['NET_PROFIT_CS'].unstack().diff().fillna(0).astype(bool).replace(False,np.nan)

            net_profit = is_report * pd.DataFrame(df['NET_PROFIT_CS'].unstack())

        net_profit_1 = net_profit.fillna(method='ffill').shift() * is_report

        net_profit_2 = net_profit_1.fillna(method='ffill').shift() * is_report

        net_profit_3 = net_profit_2.fillna(method='ffill').shift() * is_report

        net_profit_4 = net_profit_3.fillna(method='ffill').shift() * is_report


        net_profit_qoq = (net_profit - net_profit_1) / abs(net_profit_1)

        net_profit_qoq_1 = (net_profit_1 - net_profit_2) / abs(net_profit_2)

        net_profit_qoq_2 = (net_profit_2 - net_profit_3) / abs(net_profit_3)

        net_profit_qoq_3 = (net_profit_3 - net_profit_4) / abs(net_profit_4)


        net_profit_qoq_mean = ((net_profit_qoq+net_profit_qoq_1+net_profit_qoq_2+net_profit_qoq_3) / 4).fillna(method='ffill')

        net_profit_qoq = net_profit_qoq.fillna(net_profit_qoq_mean)

        result = pd.DataFrame(net_profit_qoq.stack(),columns=['net_profit_qoq'])

        return result


    def _cal_dividend_yield(self,fundamental,market,stock_type):

        '''

        get dividend yield

        '''

        df = fundamental.copy()

        if stock_type == 'A':

            df = df.join(market)

            tmp = (df['dividend_payable'].values.T / df['circulating_market_cap'].values / 10000).T

            tmp = pd.DataFrame(tmp,columns=['dividend_yield'],index=df.index)

        elif stock_type == 'HK':

            market = market.copy().reset_index()

            market = market[market['code'].isin(HK_stock_list['S_INFO_WINDCODE'])]

            market = market.set_index(['trade_date','code'])

            df.index.names=['trade_date','code']

            df = df.join(market)

            tmp = (df['TOT_DIV_PAID'].values.T / df['circulating_market_cap'].values / 10000).T

            tmp = pd.DataFrame(tmp,columns=['dividend_yield'],index=df.index)

        return tmp


    def _cal_returns(self,nav):

        '''

        get adj_stock_returns

        '''

        df = nav.copy()

        df['close'] = df['close'] * df['adj_factor']       

        tmp = pd.DataFrame(df['close'].unstack().pct_change().stack(),columns=['returns'])

        return tmp


    def cal_indus_nav(self)->pd.DataFrame:

        '''

        初始化申万行业指数plk

        '''

        indus_nav = pd.read_pickle(self.pickle_path+'Index/STIND_index.plk')

        indus_nav = indus_nav[(indus_nav.index.get_level_values(1)>=pd.to_datetime(self.start_date)-datetime.timedelta(days = 10)) & (indus_nav.index.get_level_values(1)<=pd.to_datetime(self.end_date))]

        indus_nav.reset_index(inplace = True)

        indus_nav['code'] = indus_nav['code'].apply(lambda x: x[:-3])

        indus_nav['name'] = indus_nav['name'].apply(lambda x: x[:-4])

        indus_nav.set_index(['trade_date', 'code'], inplace = True)

        return indus_nav[['sw_close', 'name']]




    def get_comp_name(self,code_list):

        '''

        待改进,可以对接pickle,对接后可以不import Factor

        '''

        query ='''

              SELECT S_INFO_WINDCODE,S_INFO_NAME

              FROM WINDCUSTOMCODE WHERE S_INFO_WINDCODE =

              '''

        for i in code_list:

            if i == code_list[0]:

                query += "'%s'"%code_list[0]

            else:

                query += " or S_INFO_WINDCODE = '%s'"%i

        result = Read_sql_Oracle(query)

        result['S_INFO_NAME'] = result['S_INFO_WINDCODE'].apply(lambda x: {7:'(HK)',9:''}[len(x)])+result['S_INFO_NAME']

        result = result.set_index('S_INFO_WINDCODE')

        return result

    def get_exchange(self):

        '''

        获取汇率数据

        '''

        settle_rate = pd.read_excel(self.exchange_dir + '结算汇兑比率.xlsx').iloc[:,0:-1].set_index('适用日期')

        refer_rate = pd.read_excel(self.exchange_dir + '历史参考汇率.xlsx').iloc[:,0:-1].set_index('适用日期')

        rate = settle_rate.join(refer_rate).reset_index()

        rate = settle_rate.join(refer_rate).reset_index()

        rate.columns = ['日期','买入结算','卖出结算','参考买入','参考卖出']

        rate['日期'] = pd.to_datetime(rate['日期'])

        rate = rate.set_index('日期').sort_index()

        return rate


# 2020.9.9 调整了计算日期的函数

    def get_predate(self,date):

        '''

        如果date是交易日,predate是前一个交易日

        如果date不是交易日,将替换为最近的一个交易日

        '''

        A_tradeday_list = A_nav.index.get_level_values(0).drop_duplicates().to_list()

        H_tradeday_list = H_nav.index.get_level_values(0).drop_duplicates().to_list()

        exchange_list = exchange_rate.index.to_list()

        A_tradeday_list.sort()

        H_tradeday_list.sort()

        exchange_list.sort()

        if date in A_tradeday_list:

            A_date = date

            A_index = max(A_tradeday_list.index(date)-1,0)

            A_predate = A_tradeday_list[A_index]

        else: 

            temp = A_nav.index.get_level_values(0).drop_duplicates().to_list()

            temp = list(set(temp))

            temp.sort()

            A_date = list(filter(lambda x:x <= date,temp))[-1]

            A_predate = A_date


        if date in H_tradeday_list:

            H_date = date

            H_index = max(H_tradeday_list.index(date)-1,0)

            H_predate = H_tradeday_list[H_index]

            # print('situation1')

            # print(H_tradeday_list[-3:])

        else:

            # print('situation2')

            temp = H_nav.index.get_level_values(0).drop_duplicates().to_list()

            temp = list(set(temp))

            temp.sort()

            # print(temp[-3:])

            H_date = list(filter(lambda x:x <= date,temp))[-1]

            H_predate = H_date


        if date in exchange_list:

            H_exchange_index = max(exchange_list.index(H_date)-1,0)

            H_exchangepredate = exchange_list[H_exchange_index]

            H_exchange_date = date

        elif date >= pd.to_datetime('20161205'):

            temp = list(set(exchange_rate.index.to_list()))

            temp.sort()

            H_exchange_date = list(filter(lambda x:x <= date, temp))[-1]

            H_exchangepredate = H_exchange_date 

        else:

            H_exchangepredate = H_exchange_date = pd.to_datetime('20161205')

        return A_date,H_date,A_predate,H_predate,H_exchange_date,H_exchangepredate


# 2020.9.9 

    def get_preweek(self,date):

        '''

        当前日期date减去一周,并转换为交易日

        '''

        last_week = pd.to_datetime(date)-relativedelta(days=7)

        A_date, H_date, A_predate, H_predate, H_exchangedate, H_exchangepredate = self.get_predate(last_week)

        return A_date, H_date, A_predate, H_predate, H_exchangedate, H_exchangepredate


# 2021.7.15 

    def get_premonth(self,date):

        '''

        当前日期date减去一月,并转换为交易日

        '''

        last_week = pd.to_datetime(date)-relativedelta(days=30)

        A_date, H_date, A_predate, H_predate, H_exchangedate, H_exchangepredate = self.get_predate(last_week)

        return A_date, H_date, A_predate, H_predate, H_exchangedate, H_exchangepredate


# 2020.9.9

    def get_predate_samefreq(self,date):

        '''

        如果date是交易日,predate是前一个交易日。但是predate提前的程度和原始数据一样,即predate必须在原始数据中出现。

        要求输入的原始excel文件的日期必须是准确的。

        如果date不是交易日,将替换为前一个交易日。“前”的频率和原始数据频率一样

        '''

        A_tradeday_list = A_nav.index.get_level_values(0).drop_duplicates().to_list()

        H_tradeday_list = H_nav.index.get_level_values(0).drop_duplicates().to_list()

        exchange_list = exchange_rate.index.to_list()

        A_tradeday_list = list(set(self.filetradeday_list) & set(A_tradeday_list))

        H_tradeday_list = list(set(self.filetradeday_list) & set(H_tradeday_list))

        exchange_list = list(set(self.filetradeday_list) & set(exchange_rate.index.to_list()))

        A_tradeday_list.sort()

        H_tradeday_list.sort()

        exchange_list.sort()


        if date in A_tradeday_list:

            A_date = date

            A_index = A_tradeday_list.index(date)-1

            if A_index<0:

                if self.data_freq == 'D':

                    A_predate,__,__,__,__,__ = self.get_predate(date)

                elif self.data_freq == 'W':

                    A_predate,__,__,__,__,__ = self.get_preweek(date)

                elif self.data_freq == 'M':  #20210715增加月频

                    A_predate,__,__,__,__,__ = self.get_premonth(date)

            else:

                A_predate = A_tradeday_list[A_index]

        elif len(list(filter(lambda x:x <= date,A_tradeday_list))):

            A_date = list(filter(lambda x:x <= date,A_tradeday_list))[-1]

            A_predate = A_date

        else:

            if self.data_freq == 'D':

                A_date,__,A_predate,__,__,__ = self.get_predate(date)

            elif self.data_freq == 'W':

                A_date,__,A_predate,__,__,__ = self.get_preweek(date)

            elif self.data_freq == 'M':  #20210715增加月频

                A_date,__,A_predate,__,__,__ = self.get_premonth(date)

        if date in H_tradeday_list:

            H_date = date

            H_index = H_tradeday_list.index(date)-1

            if H_index<0:

                if self.data_freq == 'D':

                    H_predate,__,__,__,__,__ = self.get_predate(date)

                elif self.data_freq == 'W':

                    H_predate,__,__,__,__,__ = self.get_preweek(date)

                elif self.data_freq == 'M':  #20210715增加月频

                    H_predate,__,__,__,__,__ = self.get_premonth(date)

            else:

                H_predate = H_tradeday_list[H_index]

        elif len(list(filter(lambda x:x <= date,H_tradeday_list))):

            H_date = list(filter(lambda x:x <= date,H_tradeday_list))[-1]

            H_predate = H_date

        else:

            if self.data_freq == 'D':

                __,H_date,__,H_predate,__,__ = self.get_predate(date)

            elif self.data_freq == 'W':

                __,H_date,__,H_predate,__,__ = self.get_preweek(date)

            elif self.data_freq == 'M':  #20210715增加月频

                __,H_date,__,H_predate,__,__ = self.get_premonth(date)

        if date in exchange_list:

            H_exchange_index = exchange_list.index(H_date)-1

            H_exchange_date = date

            if H_exchange_index<0:

                if self.data_freq == 'D':

                    H_exchangepredate,__,__,__,__, __ = self.get_predate(date)

                elif self.data_freq == 'W':

                    H_exchangepredate,__,__,__,__, __ = self.get_preweek(date)

                elif self.data_freq == 'M':  #20210715增加月频

                    H_exchangepredate,__,__,__,__, __ = self.get_premonth(date)

            else:

                H_exchangepredate = exchange_list[H_exchange_index]

                H_exchange_date = date

        elif len(list(filter(lambda x:x <= H_date,exchange_list))):

            H_exchange_date = list(filter(lambda x:x <= H_date,exchange_list))[-1]

            H_exchange_date = H_exchangepredate = H_exchange_date 

        else:

            if self.data_freq == 'D':

                __,__,__,__,H_exchange_date, H_exchangepredate = self.get_predate(date)

            elif self.data_freq == 'W':

                __,__,__,__,H_exchange_date, H_exchangepredate = self.get_preweek(date)

            elif self.data_freq == 'M':  #20210715增加月频

                __,__,__,__,H_exchange_date, H_exchangepredate = self.get_premonth(date)

        return A_date,H_date,A_predate,H_predate,H_exchange_date,H_exchangepredate

你可能感兴趣的:(2022-01-14)