权重随时间变化的时间序列的加权平均值
Weighted average of time-series with changing weights over time
我需要生成一些金融资产的 returns 的加权平均值,其中使用的权重随时间变化。 (应用程序是金融的,但问题本身是一个非常普遍的问题)。
我的returns节选和权重如下:
returns_df
:Returns 随着时间推移的资产
┌──────────────────┬──────────┬────────────┬────── ──────┐
│ 日期时间 │ 资产 1 │ 资产 2 │ 资产 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
:随时间变化的资产权重
┌──────────────────┬────────┬──────────┬────────┐
│ 权重开始 │ 资产 1 │ 资产 2 │ 资产 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 │
└──────────────────┴────────┴────────┴────────┘
例如,第一个 table 中的 returns 将全部由 {0.023; 0.8733; 0.103}
加权,因为它们都落在 之后 2015-04-01
但 在 2015-05-01
.
之前
当然,我的真实数据集 returns 涵盖了我权重中的整个日期范围。
我完全不确定如何处理这个问题,我想过使用 groupby()
但考虑到 weights_df
的形状与 returns_df
不同,所以不好像没用。
import numpy as np
import pandas as pd
from io import StringIO
# alternatively try `import StringIO`
returns_datatext = StringIO("""
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
""")
returns_df = pd.read_table(returns_datatext, index_col=[0], parse_dates=True, sep='│')
weights_datatext = StringIO("""
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
""")
weights_df = pd.read_table(weights_datatext, index_col=[0], parse_dates=True, sep='│')
上述 table 的预期结果如下:
┌──────────────────┬──────────────────┐
│ 日期时间 │ 加权平均值 │
├──────────────────┼──────────────────┤
│ 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 │
└──────────────────┴──────────────────┘
这是pd.merge_asof
到link这两个,然后是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
我需要生成一些金融资产的 returns 的加权平均值,其中使用的权重随时间变化。 (应用程序是金融的,但问题本身是一个非常普遍的问题)。
我的returns节选和权重如下:
returns_df
:Returns 随着时间推移的资产
┌──────────────────┬──────────┬────────────┬────── ──────┐ │ 日期时间 │ 资产 1 │ 资产 2 │ 资产 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
:随时间变化的资产权重
┌──────────────────┬────────┬──────────┬────────┐ │ 权重开始 │ 资产 1 │ 资产 2 │ 资产 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 │ └──────────────────┴────────┴────────┴────────┘
例如,第一个 table 中的 returns 将全部由 {0.023; 0.8733; 0.103}
加权,因为它们都落在 之后 2015-04-01
但 在 2015-05-01
.
当然,我的真实数据集 returns 涵盖了我权重中的整个日期范围。
我完全不确定如何处理这个问题,我想过使用 groupby()
但考虑到 weights_df
的形状与 returns_df
不同,所以不好像没用。
import numpy as np
import pandas as pd
from io import StringIO
# alternatively try `import StringIO`
returns_datatext = StringIO("""
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
""")
returns_df = pd.read_table(returns_datatext, index_col=[0], parse_dates=True, sep='│')
weights_datatext = StringIO("""
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
""")
weights_df = pd.read_table(weights_datatext, index_col=[0], parse_dates=True, sep='│')
上述 table 的预期结果如下:
┌──────────────────┬──────────────────┐ │ 日期时间 │ 加权平均值 │ ├──────────────────┼──────────────────┤ │ 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 │ └──────────────────┴──────────────────┘
这是pd.merge_asof
到link这两个,然后是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