【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型之python实现

【更新日志】
8/6/2020 对代码中计算择时与择股收益公式的错误进行了修正,并将数据结构框架补充在了附录中


1. 引言

在上文中,我们已经介绍了Brinson归因模型的基本思想和基本方法。在这篇文章中,就让我们动起手来实现这一方法吧!

在Brinson多期归因模型实现的过程中,本文使用模块化方法,将整个实现过程划分为如下五个功能板块:
Module 1: 基准数据读取模块(功能函数:benchmark_load)
Module 2: 持仓数据读取模块(功能函数:positions_load)
Module 3: 持仓收益与基准计算模块(功能函数:w_r_calculation)
Module 4: Brinson多期归因模型核心算法(功能函数:Brinson_Multiple)
Module 5: 主函数模块

注1:由于每个人数据都不一样,因此读者可以仅参考自己认为有用的模块(比如Brinson模型的核心算法)。

注2:由于本人自己的持仓数据比较敏感,在此仅展示代码实现框架。读者可以将自己的数据稍作处理后套用与本模板。


2. Brinson多期归因模型的Python实现

2.1 基准数据读取模块

# 0. 导入pandas库
import pandas as pd

# 1. 基准数据读取函数
'''
· 函数功能:读取基准数据
· 输入变量:基准数据存储的地址路径,格式为str
· 输出变量:基准的权重矩阵和收益矩阵,格式为DataFrame的list
· 数据样式介绍:
	1) 基准的权重存储于某xlsx或xls文件中,共有两个sheets,分别命名为"Weights"和"Return";
	2) 数据的第一列为交易日日期,列名为“日期”,其列格式为“datatime64”;
	3) 数据表头为各行业名称。
'''
def benchmark_load(benchmark_path):
    benchmark_weights = pd.read_excel(benchmark_path, sheet_name='Weights', index_col='日期')
    benchmark_returns = pd.read_excel(benchmark_path, sheet_name='Return', index_col='日期')
    return [benchmark_weights, benchmark_returns]

:除本地导入基准数据外,可以通过API接口直接获取基准数据,如wind数据库、tushare数据库等

2.2 持仓数据读取模块

# 2. 读取持仓数据
'''
· 函数功能:读取持仓数据
· 输入变量:持仓数据存储的地址路径,格式为str
· 输出变量:标准持仓数据,格式为DataFrame,columns为数据名称,index为对应股票的持仓日期
· 数据样式介绍:
	1) 全部的持仓数据,包括:持仓股票代码,股票所属行业,持仓日期、市值、当日卖出金额、当日买入金额等;
	2) 数据表头为各数据名称;
	3) 原始数据可以不按照交易日先后顺序排列。
'''
def positions_load(positions_path):
    pf_data= pd.read_excel(positions_path)
    pf_data.drop_duplicates()  # 数据去重
    pf_data = pf_data[['持仓日期', '市值', '行业', '当日卖出金额', '当日买入金额']]  # 选定需要使用的列
    pf_data['持仓日期'] = pf_data['持仓日期'].astype('datetime64')  # 转化日期格式
    return pf_data

2.3 持仓收益与基准计算模块

# 3. calculate the weights and the returns of the portfolio
'''
· 函数功能:计算所持仓位的权重和收益矩阵
· 输入变量:
	1) trading_dates:从基准值提取的交易日信息,格式为list
	2)  sectors: 从基准中提取行业名称(本码为申万一级),格式为list
	3) pf_data:使用读取函数读取到的数据
· 输出变量:持仓的权重矩阵和收益矩阵,格式为DataFrame的list
'''
def w_r_calculation(trading_dates, sectors, pf_data):
    # sectors: 从基准中提取行业名称(申万一级)
    # trading_dates 从基准值提取交易日信息
	
	# Part 1: 初始化一些存储用的中间变量
    pf_weights = pd.DataFrame(0, columns=sectors, index=td_dates).astype('float') # 存储持仓权重
  • 42
    点赞
  • 216
    收藏
    觉得还不错? 一键收藏
  • 38
    评论
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值