Могу ли я применить функцию XIRR из библиотеки tvm для каждой строки в моей таблице, где денежные потоки уже находятся в этой строке? - PullRequest
0 голосов
/ 30 декабря 2018

Это мой первый вопрос, поэтому я заранее прошу прощения, если это не совсем заданный вопрос.Я уже искал по всему переполнению стека (& Google), но не смог найти то, что я ищу.Кроме того, я новичок в R и изучаю его самостоятельно на ходу.

Мои проблемы заключаются в следующем: я пытаюсь вычислить внутреннюю норму прибыли для каждой строки в моей таблице, используя функцию 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)

В моем конкретном сценарии у меня есть таблица с периодическими денежными потоками и датами, заполненными в каждой строке для каждого идентификатора.Денежные потоки находятся в столбцах 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.

Возможно ли это, или я должен искать какую-то другую функцию?Спасибо!

РЕДАКТИРОВАТЬ - Дополнительные сведения и ответ о том, почему ответ «равный» не сработал

Мои фактические данные содержат денежные потоки и даты в формате длинной таблицыс более чем 5,5 миллионов строк.Причина, по которой я преобразовал их в «устаревшую» таблицу, заключается в том, что в конечном итоге я пытаюсь создать скользящий ежемесячный расчет IRR.Я подумал, что если бы я построил потоки «Дата» и «Денежный поток» в каждой строке, то я мог бы избежать циклического применения XIRR непосредственно к каждой строке.Создание длинной таблицы, включающей каждую итерацию идентификатора / даты, было бы нереалистичным для этого объема данных (я не думаю).

При использовании предложенного кода денежные потоки и даты объединяются для одного и того жеID, поэтому он не учитывает периоды прокрутки.Я знаю, что это не объяснялось в моем первоначальном вопросе.

Кроме того, у меня есть периоды с отсутствующими денежными потоками, которые показывают NA (так как они мутированы как .numeric).Мне нужен XIRR, чтобы справиться с этим, не выполняя вычисления, когда есть какие-либо NA.Я думаю, что это можно сделать с помощью is.na = TRUE в команде суммирования.

EDIT # 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)

Я получаю предупреждающее сообщение «Предупреждающее сообщение: In bind_rows_ (x, .id): Неравные уровни факторов: принуждениев символ », но расчет точен.

Проблема, с которой я до сих пор сталкиваюсь, заключается в том, насколько медленно это происходит для моего фактического набора данных.Он работает очень долго (6+ часов), но дает правильные результаты.Есть ли способ переписать это, используя параллельную обработку или без строки, что я предполагаю, что это операция цикла и медленная.

1 Ответ

0 голосов
/ 31 декабря 2018

Прежде всего, tbl_df кажется устаревшим, используйте as_tibble или as.tibble.

Я также изменил ваши данные выборки, так как получаю ошибку при применении данных из ID«А».Я определил пример данных следующим образом.

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)))
...