计算具有条件的两个特定行之间的行

counting rows between two specific rows with a condition

df <- structure(list(inv = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"), ass = c("x", "x", "x", "x", "x"), datetime = c("2010-01-01", 
"2010-01-02", "2010-01-03", "2010-01-08", "2010-01-19"), portfolio = c(10, 
0, 5, 2, 0)), operation = c(10, -10, 5, -3, -2), class = "data.frame", row.names = c(NA, -5L))

所以我有 4000 个拥有 6000 不同资产的投资者,对于每个投资者,我有两个不同变量的交易操作:操作告诉我他是否 buying/selling;投资组合告诉我他在投资组合中有多少。

我想做的是计算一个头寸在投资组合中保持开放的天数,所以我想计算投资组合回到零的那一天和投资组合去的那一天之间的差异正面(不可能获得负面投资组合)。

所以在上面的数据集中我会算 row2 - row1 ==> 2010-01-02 - 2010-01-01row 5 - row 3 ==> 2010-01-19 - 2010-01-03 等等...

我想对数据集中所有我发现 portfolio > 0.

的所有行的所有投资者和资产进行此计算

所以我的数据集将有一个名为 duration 的列,在这种情况下,它等于 c(0,1,0,5,16)(所以我当然还必须计算 raw1 - raw1raw3 - raw3) 因此我的问题是每次 portfolio 回到零时重新开始计数。

library(dplyr)

df %>% 
  mutate(datetime = as.Date(datetime, "%Y-%m-%d")) %>% 
  group_by(investor, asset) %>% 
  arrange(datetime) %>% 
  mutate(grp.pos = cumsum(lag(portfolio, default = 1) == 0)) %>%
  group_by(investor, asset, grp.pos) %>% 
  mutate(`Open (#days)` = datetime - datetime[1])

#> # A tibble: 5 x 6
#> # Groups:   investor, asset, grp.pos [2]
#>   investor asset datetime   portfolio grp.pos `Open (#days)`
#>   <chr>    <chr> <date>         <dbl>   <int> <drtn>        
#> 1 INV_1    x     2010-01-01        10       0  0 days       
#> 2 INV_1    x     2010-01-02         0       0  1 days       
#> 3 INV_1    x     2010-01-03         5       1  0 days       
#> 4 INV_1    x     2010-01-08         2       1  5 days       
#> 5 INV_1    x     2010-01-19         0       1 16 days

数据:

df <- structure(list(investor = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"), 
                     asset = c("x", "x", "x", "x", "x"), 
                     datetime = c("2010-01-01", "2010-01-02", "2010-01-03", 
                                  "2010-01-08", "2010-01-19"), 
                     portfolio = c(10, 0, 5, 2, 0)), 
                     operation = c(10, -10, 5, -3, -2), 
                class = "data.frame", row.names = c(NA, -5L))

这是我们可以做到的方法,如果需要,可以扩展 ass

首先我们按 inv 分组以用于原始数据集。然后将datetime转换为日期格式,方便计算(这里使用ymd()函数)。

下一步可以用不同的方式完成:

主要思想是将组的最后一行 0 指示的列 portfolio 分组。为此,我们以降序形式排列 datetime,以便轻松应用分组 ID 和 cumsum == 0.

重新排列后 datetime 我们可以按预期从第一个开始计算最后一个:

library(dplyr)
library(lubridate)

df %>% 
  group_by(inv) %>% 
  mutate(datetime = ymd(datetime)) %>% 
  arrange(desc(datetime)) %>% 
  group_by(position_Group = cumsum(portfolio==0)) %>% 
  arrange(datetime) %>% 
  mutate(position_open = last(datetime)-first(datetime)) %>% 
  ungroup()
  inv   ass   datetime   portfolio operation id_Group position_open
  <chr> <chr> <date>         <dbl>     <dbl>    <int> <drtn>       
1 INV_1 x     2010-01-01        10        10        2  1 days      
2 INV_1 x     2010-01-02         0       -10        2  1 days      
3 INV_1 x     2010-01-03         5         5        1 16 days      
4 INV_1 x     2010-01-08         2        -3        1 16 days      
5 INV_1 x     2010-01-19         0        -2        1 16 days