我可以将tvm库中的XIRR函数应用于表中每一行中已有现金流的地方吗?

时间:2018-12-30 16:03:38

标签: r xirr

这是我的第一个问题,因此,如果不是一个完美的问题,我谨向您道歉。我已经在Stack Overflow(&Google)上进行了搜索,但是找不到我想要的东西。另外,我是R的新手,我会自己学习。

我的问题是这样的: 我正在尝试使用tvm的XIRR函数计算表中每一行的内部收益率。我能够使XIRR能够为单一现金流量工作。这是我上班的例子。

# This is a sample that works
install.packages("tvm")
library(tvm)

x_CF <- c(-7500, 3000, 5000, 1200, 4000)
x_d <- as.Date(c("2016-01-01", "2016-02-01", "2016-04-15", "2016-08-01", "2017-03-26"))
xirr <- xirr(x_CF, x_d)

在我的特定情况下,我有一个表格,其中每个ID的每一行上都填充有定期现金流量和日期。现金流在cf1,cf2,cf3,cf(n)列中,日期在date1,date2,date3,date(n)列中。现金流和日期数当前为14(n = 14),但可能有所不同(例如36、60等)。这是一个代码,可从我更大的表中填充2行。

# This is just 2 rows of my data table where I manually write the values (the real table is much larger and is dynamically created with code)    

sample_data <-
    matrix(
        c(
            "A",
            "2016-01-31", "2016-02-29", "2016-03-31","2016-04-30","2016-05-31",
            1000, 10, 20, -50, -1025,
            "B",
            "2016-01-31", "2016-02-29", "2016-03-31","2016-04-30", "2016-05-31",
            1000, -50, 20, 10, -1025),
        ncol = 11, byrow = TRUE)

colnames(sample_data) <-
    c("SecId",
      "date1", "date2", "date3", "date4", "date5",
      "cf1", "cf2", "cf3", "cf4", "cf5")

sample_data <- tbl_df(sample_data)

sample_data <-
    sample_data %>% mutate_at(vars(starts_with("cf")),
                              funs(as.integer))
sample_data <-
    sample_data %>% mutate_at(vars(starts_with("date")),
                              funs(as.Date))

我想使用XIRR函数读取cf1:n和date1:​​n。结果应插入另一列(XIRR),计算出的值应为A = 0.1412532和B = 0.1458380。

这是可能的,还是我应该研究其他功能?谢谢!

编辑-其他详细信息和“同行”答案无效的原因

我的实际数据具有长表格式的现金流量和日期,其中有超过550万行。之所以将它们转换为“已弃用”表,是因为我最终想要做的是创建滚动的每月IRR计算。我想出了如果我在每一行上建立了日期和现金流,那么我就可以避免直接将XIRR直接应用于每一行。对于这样大量的数据(我不认为),创建包含ID / Date的每个迭代的长表是不现实的。

使用建议的代码,现金流和日期合并为相同的ID,因此不考虑滚动期间。我知道我的原始问题没有对此进行解释。

此外,我的现金流缺失的期间显示为NA(因为它们被突变为数字)。我需要XIRR通过在有任何NA时不执行计算来处理此问题。我认为可以在summary命令中使用is.na = TRUE进行处理。

编辑#2:找到了部分解决方案

解决了这个问题后,我能够从上面获取XIRR函数以处理示例数据。这是有效的代码,但是要花很长时间才能处理我的实际数据。

calc_xirr <- sample_data %>% rowwise() %>%
do(data.frame(., xirr = tryCatch(xirr(unlist(.[7:11]), unlist(.[2:6]),lower=0,upper=1),
                                 error = function(e) {NA}))) %>%
select(SecId, xirr)

我收到一条警告消息“警告消息:在bind_rows_(x,.id)中:不相等的因子水平:强制转换为字符”,但是计算准确。

我仍然遇到的问题是,这对我的实际数据集有多慢。  它可以运行很长时间(超过6小时),但确实会产生正确的结果。有什么方法可以使用并行处理来重写它,也可以不逐行重写,我认为这是循环操作并且很慢。

1 个答案:

答案 0 :(得分:0)

首先,tbl_df似乎已被弃用,请改用as_tibbleas.tibble

我还更改了您的示例数据,因为从ID“ A”应用数据时遇到错误。 我将样本数据定义如下。

sample_data <-
  matrix(
    c(
      "A",
      "2016-01-01",
      "2016-02-01",
      "2016-04-15",
      "2016-08-01",
      "2017-03-26",
      -7500,
      3000,
      5000,
      1200,
      4000,
      "B",
      "2016-01-01",
      "2016-02-01",
      "2016-04-15",
      "2016-08-01",
      "2017-03-26",
      -7500,
      3000,
      5000,
      1200,
      4000
    ),
    ncol = 11,
    byrow = TRUE
  )

colnames(sample_data) <-
  c("ID",
    "date1",
    "date2",
    "date3",
    "date4",
    "date5",
    "cf1",
    "cf2",
    "cf3",
    "cf4",
    "cf5")

我将代码分为两部分。第一部分是整理数据,第二部分是创建所需的值。

sample_data <- tbl_df(sample_data)

sample_data <-
  sample_data %>% mutate_at(vars(starts_with("cf")),
                            funs(as.numeric),
                            vars(starts_with("date")),
                            funs(as.Date))
sample_data_dates <-
  sample_data %>% select(starts_with("date"), ID) %>% gather(key, date, -ID) %>% mutate(index = gsub("date", "", key))
sample_data_cashflows <-
  sample_data %>% select(starts_with("cf"), ID) %>% gather(key, cashflow,-ID) %>% mutate(index = gsub("cf", "", key))

sample_data <-
  inner_join(
    sample_data_dates %>% select(-key),
    sample_data_cashflows %>% select(-key),
    by = c("ID", "index")
  ) %>% select(-index)

此后,您将获得一个包含列名称ID,日期和现金流量的表。 然后,您可以通过以下代码简单地从函数xirr计算结果值:

sample_data %>% group_by(ID) %>% summarise(xirr(cashflow,as.Date(date)))