You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用dplyr的accumulate函数及rowwise复现R中的数据框/tibble?

用dplyr复现《期权与衍生品》中的保证金账户表格

核心逻辑梳理

首先明确赫尔书中期货保证金账户的结算规则:

  • 初始存入初始保证金($12000),维持保证金为$9000(对应你代码中的contract_value)
  • 每日盈亏 = (当日收盘价 - 前一日收盘价) × 合约乘数(200)
  • 保证金余额 = 前一日余额 + 当日盈亏;若余额低于维持保证金,需追加资金至初始保证金水平
  • 变动保证金 = 初始保证金 - 结算后未追加的余额(仅当余额低于维持保证金时产生)
  • 追加通知(margin_call)为前一日需补缴的变动保证金

正确的accumulate实现(推荐)

这是最高效的矢量化实现,符合dplyr的风格:

library(tidyverse)

initial_deposit <- 12000
maintenance_margin <- 9000
multiplier <- 200
closing_stock_indices <- c(1250,1241,1238.3,1244.6,1241.3,1240.1, 1236.2, 1229.9,
                           1230.8,1225.4,1228.1,1211,1211,1214.3,1216.1,1223,1226.9)

# 构建基础数据
df <- tibble(Day = 0:(length(closing_stock_indices)-1),
             Closing_SI = closing_stock_indices) %>%
  mutate(Daily_change = c(0, diff(Closing_SI) * multiplier))

# 计算保证金账户各项指标
df <- df %>%
  mutate(
    # 递推计算保证金余额
    Margin_balance = accumulate(Daily_change,
                                .init = initial_deposit,
                                ~ {
                                  new_bal <- .x + .y
                                  if (new_bal < maintenance_margin) initial_deposit else new_bal
                                })[-1],
    # 计算变动保证金
    Variation_Margin = ifelse(Margin_balance == initial_deposit,
                              initial_deposit - (lag(Margin_balance) + Daily_change),
                              0),
    Variation_Margin = replace_na(Variation_Margin, 0),
    # 计算追加通知
    margin_call = lag(Variation_Margin, default = 0)
  ) %>%
  # 修正Day0的保证金余额
  mutate(Margin_balance = ifelse(Day == 0, initial_deposit, Margin_balance))

# 查看结果
print(df, n = Inf)

rowwise()替代实现(效率较低)

如果一定要用rowwise(),可以通过逐行重新计算累积序列的方式实现(不推荐用于大数据量):

df_rowwise <- df %>%
  select(Day, Closing_SI, Daily_change) %>%
  rowwise() %>%
  mutate(
    # 逐行计算从初始到当前日的保证金余额,取对应行结果
    Margin_balance = accumulate(c(initial_deposit, Daily_change[Day:(n()-1)]),
                                ~ {
                                  new_bal <- .x + .y
                                  if (new_bal < maintenance_margin) initial_deposit else new_bal
                                })[row_number()]
  ) %>%
  ungroup() %>%
  mutate(
    Variation_Margin = ifelse(Margin_balance == initial_deposit & Day > 0,
                              initial_deposit - (lag(Margin_balance) + Daily_change),
                              0),
    margin_call = lag(Variation_Margin, default = 0)
  )

# 查看结果
print(df_rowwise, n = Inf)

内容的提问来源于stack exchange,提问作者Homer Jay Simpson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:45:34