Мне нужно сгенерировать средневзвешенную доходность некоторого количества финансовых активов, где используемые веса меняются со временем. (Приложение является финансовым, но сама проблема носит весьма общий характер).
Выдержки из моих возвратов и весов следующие:
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
, но до 2015-05-01
.
Разумеется, мой реальный набор данных содержит данные, охватывающие весь диапазон дат в моих весах.
Я совсем не уверен, как подойти к этому, я подумал об использовании 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='│')
Ожидаемые результаты для приведенной выше таблицы будут следующими:
┌──────────────────┬──────────────────┐
│ 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 │
└──────────────────┴──────────────────┘