# -*- 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