【问题标题】:Need help calculating IRR for different investments at different dates for each investment, in python需要帮助在 python 中为每项投资在不同日期计算不同投资的 IRR
【发布时间】:2021-07-16 05:14:08
【问题描述】:

我需要帮助计算不同投资的 IRR,以及这些投资在不同时间的 IRR。

所以有一个如下所示的数据框:

DATE Investment Flow
2012-05-12 1 -50
2013-09-04 1 100
2014-05-05 1 300
2013-09-04 2 -700
2015-05-12 2 1000
2012-04-04 3 100
2013-05-12 3 -50
2013-09-04 4 -60

还有一个像这样的

DATE Investment Stock
2012-09-05 1 400
2014-05-05 1 600
2014-05-05 2 300
2013-09-04 2 800
2012-09-14 3 1000
2013-09-05 4 6000

因此,我想创建多个数据框,其中包含直到我获得有关股票信息的日期之前的每项投资的流向,最后一行包含该日期的股票。例如,我对投资 1 的股票有 2 个观察结果,所以我应该为投资 1 创建 2 个数据框,如下所示:

DATE Investment Flow + Stock(last row)
2012-05-12 1 -50
2012-09-05 1 400
DATE Investment Flow + Stock(last row)
2012-05-12 1 -50
2013-09-04 1 100
2014-05-05 1 300
2014-05-05 1 600

对于投资 3,假设我对股票只有一个观察结果,应该只有 1 个如下所示的数据框:

DATE Investment Flow + Stock(last row)
2012-04-04 3 100
2012-09-14 3 1000

鉴于我有很多数据,手动创建每个数据框很麻烦,而且我希望此代码在我有新信息时更新 IRR。我想这样做是因为我想在我掌握每项投资的股票信息的每个日期看到 IRR 的演变。有点像投资的内部收益率时间序列。我将使用创建的数据框计算 IRR。

我已尝试为每项投资对我有股票信息的日期进行排名,但循环有问题。

非常感谢

编辑: 根据 Henry Ecker 的要求,这是合并数据库的示例。

         DATE_x       Investment         Flow     DATE_y         Stock
355  2018-08-29            1            1371300 2020-09-30    2904678,03
3076 2016-03-31            2           -4535569 2015-06-30             0
1564 2017-11-28            3            1142227 2014-09-30   10378007,31
3666 2018-02-22            2            1622857 2020-03-31  122203846,09
1394 2017-05-16            3            3116642 2017-12-31             0
472  2013-11-09            3           -4364500 2015-12-31   45789217,93
446  2021-02-23            1             325117 2020-03-31   13176648,97
1641 2018-01-31            3             623695 2015-09-30             0
1297 2017-03-21            3            1146193 2015-09-30    32103654,6
2080 2020-09-15            3             461123 2017-09-30   47763628,79

【问题讨论】:

    标签: python pandas loops date irr


    【解决方案1】:

    解决此问题的一种方法是加入流程和观察以获取关联,然后按观察日期和投资 ID 分组以获取我们感兴趣的每个组。

    process_df 函数用于仅过滤掉观察日期之前的日期 (DATE_y)。

    从第一行获取值投资、观察日期 (DATE_y) 和股票值,因为它们在组中都是相同的,并将其附加到表的末尾。然后只需清理所有内容,删除多余的列(Stock 和 DATE_y),重置索引,然后重命名列以反映您想要的输出。

    import pandas as pd
    
    flows = pd.DataFrame({'DATE': {0: '2012-05-12', 1: '2013-09-04',
                                   2: '2014-05-05', 3: '2013-09-04',
                                   4: '2015-05-12', 5: '2012-04-04',
                                   6: '2013-05-12', 7: '2013-09-04',
                                   8: '2020-05-12', 9: '2016-07-12'},
                          'Investment': {0: 1, 1: 1, 2: 1, 3: 2,
                                         4: 2, 5: 3, 6: 3, 7: 4,
                                         8: 5, 9: 7},
                          'Flow': {0: -50, 1: 100, 2: 300, 3: -700,
                                   4: 1000, 5: 100, 6: -50, 7: -60,
                                   8: 100, 9: 800}})
    flows['DATE'] = flows['DATE'].astype('datetime64[ns]')
    
    observations = pd.DataFrame({'DATE': {0: '2012-09-05', 1: '2014-05-05',
                                          2: '2014-05-05', 3: '2013-09-04',
                                          4: '2012-09-14', 5: '2013-09-05',
                                          6: '2014-05-14', 7: '2015-12-14'},
                                 'Investment': {0: 1, 1: 1, 2: 2,
                                                3: 2, 4: 3, 5: 4,
                                                6: 5, 7: 6},
                                 'Stock': {0: 400, 1: 600, 2: 300,
                                           3: 800, 4: 1000, 5: 6000,
                                           6: 0, 7: 15}})
    observations['DATE'] = observations['DATE'].astype('datetime64[ns]')
    
    
    def process_df(df):
        out = df[df['DATE_x'] <= df['DATE_y']]  # Filter Out Out of Bound Dates
        if out.empty:
            # Handle Case Where Observation but No flows
            return df[['DATE_y', 'Investment', 'Stock']] \
                .reset_index(drop=True) \
                .rename(columns={'DATE_y': 'DATE', 'Stock': 'Flow + Stock(last row)'})
        return out.drop(['DATE_y', 'Stock'], axis=1) \
            .append(out[['Investment', 'DATE_y', 'Stock']]
                    .iloc[0]
                    .rename({'DATE_y': 'DATE_x', 'Stock': 'Flow'})) \
            .reset_index(drop=True) \
            .rename(columns={'DATE_x': 'DATE', 'Flow': 'Flow + Stock(last row)'})
    
    
    merged = pd.merge(flows, observations, on='Investment', how='right')
    
    dfs = [process_df(group) for _, group in merged.groupby(['Investment', 'DATE_y'])]
    
    # For Display
    for i, new_df in enumerate(dfs):
        print(f'DataFrame {i+1}')
        print(new_df)
        print()
    

    dfs 是一个包含各个 DataFrame 的列表。

    输出:

    DataFrame 1
            DATE  Investment  Flow + Stock(last row)
    0 2012-05-12           1                   -50.0
    1 2012-09-05           1                   400.0
    
    DataFrame 2
            DATE  Investment  Flow + Stock(last row)
    0 2012-05-12           1                   -50.0
    1 2013-09-04           1                   100.0
    2 2014-05-05           1                   300.0
    3 2014-05-05           1                   600.0
    
    DataFrame 3
            DATE  Investment  Flow + Stock(last row)
    0 2013-09-04           2                  -700.0
    1 2013-09-04           2                   800.0
    
    DataFrame 4
            DATE  Investment  Flow + Stock(last row)
    0 2013-09-04           2                  -700.0
    1 2014-05-05           2                   300.0
    
    DataFrame 5
            DATE  Investment  Flow + Stock(last row)
    0 2012-04-04           3                   100.0
    1 2012-09-14           3                  1000.0
    
    DataFrame 6
            DATE  Investment  Flow + Stock(last row)
    0 2013-09-04           4                   -60.0
    1 2013-09-05           4                  6000.0
    
    DataFrame 7
            DATE  Investment  Flow + Stock(last row)
    0 2014-05-14           5                       0
    
    DataFrame 8
            DATE  Investment  Flow + Stock(last row)
    0 2015-12-14           6                      15
    

    编辑注释:

    • 我最初的实现做了一个错误的假设,即所有观察都至少有一个流。我猜测您希望如何接收有关没有流关联的观察的信息,并选择返回一个 DataFrame,它仍然具有包含股票信息但没有流的最后一行。如果您更喜欢空的 DataFrame,请直接返回。
        if out.empty:
            # Handle Case Where Observation but No flows
            return out
    
    • 我在示例数据中添加了 3 个额外的测试用例。
      1. 有流,但观察后出现
      2. 没有给定投资 ID 的流量
      3. 有流动但没有观察。
        • 鉴于您生成的 DataFrame 是基于观察结果,我选择使用“右”连接排除观察结果不匹配的流。

    【讨论】:

    • 当代码到达“dfs = [process_df(group) for _, group in mapped.groupby(['Investment', 'DATE_y'])]"。你知道会发生什么吗?
    • 它没有用。我仍然得到同样的错误。我查看了合并的数据框,似乎有一些 DATE_y 观察结果显示“NaT”。但是,如果我查看包含每项投资的股票信息的观察数据框,就会发现该信息存在。您知道某些投资的日期没有很好地合并会发生什么吗?
    • Inner 不起作用,但我不再有 NaT 值了。
    • 您能否更新您的问题以包含导致问题的部分数据,以便我可以测试和修改我的结果?
    • 我已经更新了我的解决方案。我做出了错误的假设,即所有观察在观察之前都会有至少一个流,因此,当您使用 .iloc[0] 时,没有数据。您必须将您的加入设置为“正确”才能按预期运行。
    猜你喜欢
    • 2021-10-06
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 2021-04-22
    • 2011-09-27
    • 2014-01-07
    • 2021-06-02
    • 1970-01-01
    相关资源
    最近更新 更多