如何更高效优雅地计算含现金流的投资账户余额?
带现金流的投资账户滚动余额高效计算方法
我有一个投资账户的收益序列,账户有初始资金,期间可能存在存入和取出操作,需要生成账户的滚动余额。当无中间现金流时,使用cumprod可以轻松实现,但存在中间现金流时只能使用for()循环,感觉这种方法速度较慢,是否有更高效的实现方式?
set.seed(100) return <- c(0,rnorm(5,.05,.02)) cash_flow <- c(100,0,0,-5,0,0) account <- data.frame(cash_flow,return) # 无中间现金流时的简单实现(忽略现金流列) balance <- account$cash_flow[1] * cumprod(1+account$return) cbind(account,balance) #> cash_flow return balance #> 1 100 0.00000000 100.0000 #> 2 0 0.03995615 103.9956 #> 3 0 0.05263062 109.4690 #> 4 -5 0.04842166 114.7696 #> 5 0 0.06773570 122.5436 #> 6 0 0.05233943 128.9575 # 持有期间有取现操作时的循环实现 balance[1] <- account$cash_flow[1] for (n in 2:6){ balance[n] <- (balance[n-1] * (1+account$return[n]) + account$cash_flow[n]) } cbind(account,balance) #> cash_flow return balance #> 1 100 0.00000000 100.0000 #> 2 0 0.03995615 103.9956 #> 3 0 0.05263062 109.4690 #> 4 -5 0.04842166 109.7696 #> 5 0 0.06773570 117.2050 #> 6 0 0.05233943 123.3394
不同实现方案的速度对比
测试了三种实现方式:原生R循环、Reduce()函数、C语言扩展,结果显示C语言实现比原生R循环快34%,Reduce()方法反而更慢。
实现代码:
CB_R <- function(returns,cash_flow,num_rows){ balance <- cash_flow[1] for (n in 2:num_rows){ balance[n] <- (balance[n-1] * (1+returns[n]) + cash_flow[n]) } return(balance) } CB_R2 <- function(returns,cash_flow,num_rows){ return( Reduce( f = \(x, i) x * (1 + returns[i]) + cash_flow[i], x = 2:num_rows, init = cash_flow[1], acc = TRUE) ) } cppFunction(' NumericVector CB_C(NumericVector Returns, NumericVector cashFlow, int num_rows) { NumericVector balance(num_rows); balance[0] = cashFlow[0]; for(int i = 1; i < num_rows; i++){ balance[i] = (balance[i-1] * (1+Returns[i]) + cashFlow[i]); } return balance; }') bench::mark( CB_R(account$return,account$cash_flow,nrow(account)), CB_R2(account$return,account$cash_flow,nrow(account)), CB_C(account$return,account$cash_flow,nrow(account)) ) #> # A tibble: 3 × 6 #> expression min median `itr/sec` mem_alloc `gc/sec` #> <bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> #> 1 CB_R(account$return, account$cash_… 5.8µs 6.4µs 144957. 85.87KB 29.0 #> 2 CB_R2(account$return, account$cash… 13.1µs 14.7µs 64339. 0B 25.7 #> 3 CB_C(account$return, account$cash_… 3.7µs 4.2µs 196991. 2.49KB 39.4
内容的提问来源于stack exchange,提问作者Art
相关产品推荐
相关产品推荐

