Tushare ID : 459953
1.Tushare接口包简介Tushare是一个免费,开源的python财经数据接口包.拥有丰富的数据内容,如股票、基金、期货、数字货币等行情数据,公司财务、基金经理等基本面数据。目前数据的广度和深度都在不断加大,能够让大众实时获得专业投资者所拥有的数据。
令人惊讶的是,北向资金数据的更新的效率和数据内容质量较好。我再次。由于博主目前积分不够,在获取北向的数据时有限制,所以在代码中加入了停时处理。(运行一次、停30秒)
2.北向资金因子简介北向资金指的是沪港通和深港通买入资金之和,就是通过香港交易所买入内地的股票的资金。 由于A股市场有管制,不允许外资直接参与,我国分别在2014年和2016年开通了沪港通和深港通,形成A股市场和港股市场中的资金互流,因为内地在香港的北面,就形成了北向资金的说法。 由于“北向资金”大都是国外机构投资,而机构一般都有较为雄厚的资金实力、专门的公司研究团与信息搜集团队,在投资上相比普通的散户更专业,也更有优势的多。北向资金因出色稳定的盈利能力与准确的节奏把控而受到市场较高的关注,被市场视为“聪明资金”与风向标。
3.指数衰减法逻辑起点:20日前的北向资金净流入与今日资金净流入相比,有效性会大大降低,因此我们得到一个基本的认知:今日的北向资金净流入比20日之前净流入的更有意义,因此应该会赋予更高的权重,我们在此选取了指数衰减法。
4. 代码实现书接上回,Tushare数据里仅包含北向持股数量的数据,具体资金量的流入和流出问题,还是需要运用不复权的股票价格去计算资金净流入和净流出。
import warnings
import pandas as pd
import numpy as np
# import chinese_calendar
import seaborn as sns
import tushare as ts
import datetime as dt
from dateutil.parser import parse
warnings.filterwarnings('ignore')
sns.set()
#获取使用接口
def get_token():
ts.set_token('xxx')
pro = ts.pro_api()
return pro
#获取北向资金数据
North_capital = pd.Dataframe()
path = "xxx"
files = os.listdir(path)
# 读取北向数据
for file_name in files:
try:
data_day = pd.read_csv(path +"/" +file_name,usecols= [0,1,2,3,4])
data_day["持股数量(万股)"] = data_day["持股数量(股)"]/10000
data_day["交易日期"] = data_day["交易日期"].astype("int") #保证日期的数字类型是INT
del data_day["持股数量(股)"]
del data_day["股票名称"]
North_capital = North_capital.append(data_day)
except:
print(file_name)
#函数:获取2022年1月28日至2022年2月28日的所有股票数据,具体要素如上所述
Stock_Basic_Update("2022/01/28" , "2022/02/28")
#将所有股票数据整理成dataframe
# 读取A股历史行情数据
A_price_data = pd.Dataframe()
path = "~/A股指标行情/"
files = os.listdir(path)
for file_name in files:
data_day = pd.read_csv(path+"/" + file_name , encoding= "gbk",usecols= [0,1,5,22,24,25],names=["代码","交易日期","收盘价","流通股本(万股)","总市值(万元)","流通市值(万元)"],header = 0 )
data_day.fillna(method = "ffill",inplace= True) #同一标的
data_day["交易日期"] = data_day["交易日期"].astype("int")
A_price_data = A_price_data.append(data_day)
A_price_data.dropna(inplace = True) #去除掉异常值
#A_price_data 即为A股行情所有数据
#数据容易出现离散点,采用遍历法对离散点进行处理 效率堪忧!!老铁们求指点
Code_list = list(set(North_capital["代码"].tolist())) # 获取新的代码列表
North_capital_adj = pd.Dataframe()
for code in Code_list:
data_code = pd.Dataframe(North_capital[North_capital["代码"] == code])
data_code = data_code.sort_values(by = ["交易日期"] , ascending= True)
data_code.fillna(method = "ffill" , inplace = True)
#逐日遍历去除异常点
for i in range(1,len(data_code)-1):
data_loc = data_code.iloc[i , 3]
data_loc_bef = data_code.iloc[i-1 , 3]
data_loc_after = data_code.iloc[i+1 , 3]
#异常值的判定条件:当日的数据同时满足大于前后两日数据的20倍 & 当日的数据同时满足小于前后两日数据的0.05倍
conditionA = (abs(data_loc) > 20*abs(data_loc_after)) and (abs(data_loc) > 20*abs(data_loc_bef))
conditionB = (abs(data_loc) < 0.05*abs(data_loc_after)) and (abs(data_loc) < 0.05*abs(data_loc_bef))
if conditionA or conditionB:
data_code.iloc[i ,3] = data_code.iloc[i-1 , 3]
North_capital_adj = North_capital_adj.append(data_code)
#全A数据打上北向资金标签
#全A数据上一节有获取和分析方法
A_price_data_adj = pd.merge(A_price_data_adj , North_capital_adj,how = "left" , on = ["代码","交易日期"])
A_price_data_adj["持股占比(%)"].fillna(0,inplace = True)
A_price_data_adj["持股数量(万股)"].fillna(0,inplace = True)
#计算北向标的的持仓占比
A_price_data_adj = A_price_data_adj.assign( 持股占比 = lambda x:100*x["持股数量(万股)"]/x["流通股本(万股)"] )
A_price_data_adj = A_price_data_adj.assign( 北向持有市值 = lambda x:x["持股数量(万股)"] * x["收盘价"] )
del A_price_data_adj["持股占比(%)"]
A_price_data_adj_north = pd.pivot_table( A_price_data_adj , index = ["交易日期"] , columns=["中信一级行业"] ,values = ["北向持有市值"] , aggfunc= "sum").stack()
#数据切割
A_price_data_adj_north = A_price_data_adj_north.loc[20160629: , :]
#对行业北向资金数据处理,没有交易的日子数据计为np.nan
A_price_data_adj_north.replace(0 , np.nan , inplace= True)
#尔后使用后向填充法填充
A_price_data_adj_north = A_price_data_adj_north.unstack().fillna(method = "ffill" ).stack()
# 边际因子计算
Hold_value = pd.pivot_table(A_price_data_adj_north , index = ["交易日期"] , columns= ["中信一级行业"] , values = ["北向持有市值"])
Hold_Basic = North_basic = (Hold_value - Hold_value.shift(1) ).dropna(axis = 0)
#20日净流入半衰期为5的EWM模型
North_Margin_20_H5 = North_basic.rolling(20).apply(lambda x:pd.Dataframe.ewm(x , halflife=5,axis = 0).mean().iloc[-1])



