权重随时间变化的时间序列加权平均值

时间:2019-01-07 16:32:23

标签: python pandas dataframe time-series weighted-average

我需要生成一些金融资产收益的加权平均值,其中所使用的权重会随着时间而变化。 (该应用程序是财务应用程序,但问题本身是非常普遍的问题。)

我的收益和权重摘要如下:

returns_df:一段时间内的资产退还

┌──────────────────┬───────────┬───────────┬───────────┐
│     DateTime     │  Asset 1  │  Asset 2  │  Asset 3  │
├──────────────────┼───────────┼───────────┼───────────┤
│ 2015-04-09 07:00 │ -0.000959 │ -0.000207 │ -0.000233 │
│ 2015-04-09 08:00 │ -0.004003 │  0.000169 │  0.001221 │
│ 2015-04-09 09:00 │ -0.000700 │ -0.000070 │ -0.000096 │
│ 2015-04-09 10:00 │ -0.000812 │ -0.000289 │  0.000177 │
│ 2015-04-09 11:00 │ -0.000030 │ -0.000168 │ -0.000315 │
└──────────────────┴───────────┴───────────┴───────────┘

weights_df:资产在一段时间内的权重

┌──────────────────┬─────────┬─────────┬─────────┐
│ Start of weights │ Asset 1 │ Asset 2 │ Asset 3 │
├──────────────────┼─────────┼─────────┼─────────┤
│ 2015-03-01       │       1 │       0 │       0 │
│ 2015-04-01       │   0.023 │  0.8733 │  0.1037 │
│ 2015-05-01       │       1 │       0 │       0 │
│ 2015-06-01       │  0.0477 │  0.8278 │  0.1245 │
└──────────────────┴─────────┴─────────┴─────────┘

例如,第一个表中的返回值将全部用{0.023; 0.8733; 0.103}加权,因为它们都在之后 2015-04-01而在之前 {{ 1}}。

当然,我的真实数据集的返回值涵盖了整个日期范围。

我完全不确定如何解决这个问题,我想到使用2015-05-01,但是鉴于groupby()的形状与weights_df并不相同,因此似乎工作。

returns_df

上表的预期结果如下:

┌──────────────────┬──────────────────┐
│     DateTime     │ Weighted average │
├──────────────────┼──────────────────┤
│ 2015-04-09 07:00 │        -0.000227 │
│ 2015-04-09 08:00 │         0.000182 │
│ 2015-04-09 09:00 │        -0.000087 │
│ 2015-04-09 10:00 │        -0.000253 │
│ 2015-04-09 11:00 │        -0.000180 │
└──────────────────┴──────────────────┘

1 个答案:

答案 0 :(得分:2)

这是pd.merge_asof来链接两者,然后是numpy.average

import pandas as pd
import numpy as np

## Fix whitespace in sample data
#returns_df.index.name = 'DateTime'
#returns_df.columns = ['Asset1', 'Asset2', 'Asset3']
#weights_df.index.name= 'Start of weights'
#weights_df.columns = ['Asset1', 'Asset2', 'Asset3']

df = pd.merge_asof(returns_df, weights_df,
                   left_index=True, right_index=True, 
                   direction='backward',
                   suffixes=['', '_weight'])

cols = ['Asset1', 'Asset2', 'Asset3']
returns_df['weighted_average'] = np.average(df[cols], weights=df[[col + '_weight' for col in cols]], axis=1)

输出:returns_df

                       Asset1    Asset2    Asset3  weighted_average
DateTime                                                           
2015-04-09 07:00:00 -0.000959 -0.000207 -0.000233         -0.000227
2015-04-09 08:00:00 -0.004003  0.000169  0.001221          0.000182
2015-04-09 09:00:00 -0.000700 -0.000070 -0.000096         -0.000087
2015-04-09 10:00:00 -0.000812 -0.000289  0.000177         -0.000253
2015-04-09 11:00:00 -0.000030 -0.000168 -0.000315         -0.000180

为说明起见,这是合并产生的DataFrame。逻辑会选择weights_df中最接近日期returns_df中最接近的日期作为合并条件:

                       Asset1    Asset2    Asset3  Asset1_weight  Asset2_weight  Asset3_weight
DateTime                                                                                      
2015-04-09 07:00:00 -0.000959 -0.000207 -0.000233          0.023         0.8733         0.1037
2015-04-09 08:00:00 -0.004003  0.000169  0.001221          0.023         0.8733         0.1037
2015-04-09 09:00:00 -0.000700 -0.000070 -0.000096          0.023         0.8733         0.1037
2015-04-09 10:00:00 -0.000812 -0.000289  0.000177          0.023         0.8733         0.1037
2015-04-09 11:00:00 -0.000030 -0.000168 -0.000315          0.023         0.8733         0.1037