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

基于R语言自定义分箱绘制股票ROC累积概率密度函数求助

R语言股票ROC分析与自定义分箱CPDF可视化问题

需求:

  • 导入任意股票的每日行情数据,选取历史时段将收盘价转换为每日ROC(变化率)百分比
  • 基于ROC序列创建支持自定义分箱数量/区间(比如22个分箱、区间幅度0.3%)的累积概率密度函数(CPDF),并用直方图或散点图绘制
  • 对同一股票的两个不同时段数据执行上述操作,实现并排可视化

问题:针对SPY编写的代码无法正常运行,原代码如下:

library(quantmod)
library(tidyquant)
library(tidyverse)

# using tidyverse to import a ticker
spy <- tq_get("spy")
spy010422 <- tq_get("spy", get ="stock.prices", from ='2022-01-04', to = '2022-01-24')
str(spy010422)
# getting ROC between prices in the series
spy010422.rtn = ROC(spy010422$close, n = 1, type = c("discrete"), na.pad = TRUE)
str(spy010422.rtn)

# trying to use ggplot and tibble to create an ECDF function
spy010422.rtn %>%
  tibble() %>%
  ggplot() +
  stat_ecdf(aes(.))

# another attempt at running ECDF on the ROC series
spy010422.rtn %>%
  ggplot(spy010422.rtn) +
  stat_ecdf(aes(close))

# trying to set the number of bins and bin size for the ECDF
spy010422.rtn %>%
  mutate(rounded = round(close/.3, 0) *.3,
         bin = min_rank(rounded)) %>%
  ggplot(aes(close, bin)) +
  geom_line()

# next time segment of the ticker spy to compare this to
spy020222 <- tq_get("spy", get ="stock.prices", from ='2022-02-02', to = '2022-02-24')

问题分析与修正方案

原代码的核心问题:

  1. ROC返回的是时间序列对象,转成tibble后列名不明确,ggplot无法正确识别映射变量
  2. 绘制ECDF时变量映射错误,误用了原收盘价列而非ROC值
  3. 自定义分箱逻辑错误,没有基于ROC值计算,且分箱逻辑不符合CPDF的要求
  4. 缺少两个时段数据的并排可视化逻辑

修正后的完整可运行代码

library(quantmod)
library(tidyquant)
library(tidyverse)
library(gridExtra)

# 导入两个时段的SPY行情数据
spy_period1 <- tq_get("SPY", get = "stock.prices", from = '2022-01-04', to = '2022-01-24')
spy_period2 <- tq_get("SPY", get = "stock.prices", from = '2022-02-02', to = '2022-02-24')

# 封装ROC计算函数:生成百分比格式的每日ROC,移除NA值
calculate_roc <- function(data) {
  data %>%
    mutate(roc_pct = ROC(close, n = 1, type = "discrete", na.pad = TRUE) * 100) %>%
    drop_na(roc_pct)
}

spy_roc1 <- calculate_roc(spy_period1)
spy_roc2 <- calculate_roc(spy_period2)

# 封装自定义分箱的CPDF绘图函数
create_cpdf_plot <- function(data, bin_width = 0.3, plot_title = "") {
  # 根据指定区间幅度自动生成分箱边界
  roc_min_max <- range(data$roc_pct)
  bin_breaks <- seq(floor(roc_min_max[1]/bin_width)*bin_width,
                    ceiling(roc_min_max[2]/bin_width)*bin_width,
                    by = bin_width)
  
  # 分箱并计算累积概率
  binned_data <- data %>%
    mutate(bin = cut(roc_pct, breaks = bin_breaks, include.lowest = TRUE)) %>%
    count(bin) %>%
    mutate(cum_prob = cumsum(n)/sum(n),
           # 提取分箱中点作为x轴显示值
           bin_mid = (as.numeric(str_extract(bin, "^\\((.*?),") %>% str_remove_all("\\(|,")) +
                        as.numeric(str_extract(bin, ",(.*?)\\]$") %>% str_remove_all(",|\\]")))/2)
  
  # 绘制CPDF折线+散点图
  ggplot(binned_data, aes(x = bin_mid, y = cum_prob)) +
    geom_line(color = "#2c3e50", linewidth = 1) +
    geom_point(color = "#e74c3c", size = 2) +
    scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
    labs(title = plot_title,
         x = "ROC 日变化率 (%)",
         y = "累积概率") +
    theme_minimal()
}

# 生成两个时段的CPDF图
plot_period1 <- create_cpdf_plot(spy_roc1, bin_width = 0.3, plot_title = "SPY 2022.01.04-2022.01.24")
plot_period2 <- create_cpdf_plot(spy_roc2, bin_width = 0.3, plot_title = "SPY 2022.02.02-2022.02.24")

# 并排展示两个图形
grid.arrange(plot_period1, plot_period2, ncol = 2)

关键修正说明

  • ROC标准化处理:把ROC转换为百分比,封装成函数复用,同时移除无意义的NA值(第一个交易日没有前收盘价,无法计算ROC)
  • 自定义分箱逻辑:根据输入的bin_width自动生成适配数据范围的分箱区间,计算每个分箱的累积概率,并提取分箱中点作为x轴,保证可视化的准确性
  • CPDF可视化优化:用折线+散点的组合展示累积概率变化,y轴转为百分比格式更直观
  • 并排可视化:借助gridExtra包实现两个时段图形的并排展示,方便对比

内容的提问来源于stack exchange,提问作者lvbx9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:45:38