• 在 R 中估计 GARCH 参数存在的问题(续)


    在 R 中估计 GARCH 参数存在的问题(续)

    本文承接《在 R 中估计 GARCH 参数存在的问题》

    链接:https://www.cnblogs.com/xuruilong100/p/9986088.html

    在之前的博客《在 R 中估计 GARCH 参数存在的问题》中,Curtis Miller 讨论了 fGarch 包和 tseries 包估计 GARCH(1, 1) 模型参数的稳定性问题,结果不容乐观。本文承接之前的博客,继续讨论估计参数的稳定性,这次使用的是前文中提到,但没有详尽测试的 rugarch 包。

    rugarch 包的使用

    rugarch 包中负责估计 GARCH 模型参数的最主要函数是 ugarchfit,不过在调用该函数值前要用函数 ugarchspec 创建一个特殊对象,用来固定 GARCH 模型的阶数。

    srs = ...
    
    garch_mod = ugarchspec(
        variance.model = list(
            garchOrder = c(1, 1)),
        mean.model = list(
            armaOrder = c(0, 0),
            include.mean = FALSE))
    
    g <- ugarchfit(spec = garch_mod, data = srs)
    

    需要注意的是 g 是一个 S4 类。

    简单实验

    首先用 1000 个模拟样本,

    library(rugarch)
    library(ggplot2)
    library(fGarch)
    
    set.seed(110117)
    
    x <- garchSim(
        garchSpec(
            model = list(
                "alpha" = 0.2, "beta" = 0.2, "omega" = 0.2)),
        n.start = 1000,
        n = 1000)
    
    plot(x)
    

    garch_spec = ugarchspec(
        variance.model = list(garchOrder = c(1, 1)),
        mean.model = list(
            armaOrder = c(0, 0), include.mean = FALSE))
    
    g_all <- ugarchfit(
        spec = garch_spec, data = x)
    
    g_50p <- ugarchfit(
        spec = garch_spec, data = x[1:500])
    
    g_20p <- ugarchfit(
        spec = garch_spec, data = x[1:200])
    

    结果同样不容乐观,

    coef(g_all)
    #        omega       alpha1        beta1 
    # 2.473776e-04 9.738059e-05 9.989026e-01
    
    coef(g_50p)
    #        omega       alpha1        beta1 
    # 2.312677e-04 4.453120e-10 9.989998e-01 
    
    coef(g_20p)
    #      omega     alpha1      beta1 
    # 0.03370291 0.09823614 0.79988068
    

    再用 10000 个模拟样本试试,如果使用日线级别的数据的话,这相当于 40 年长度的数据量,

    set.seed(110117)
    
    x <- garchSim(
        garchSpec(
            model = list(
                "alpha" = 0.2, "beta" = 0.2, "omega" = 0.2)),
        n.start = 1000, n = 10000)
    
    plot(x)
    
    g_all <- ugarchfit(
        spec = garch_spec, data = x)
    
    g_50p <- ugarchfit(
        spec = garch_spec, data = x[1:5000])
    
    g_20p <- ugarchfit(
        spec = garch_spec, data = x[1:2000])
    

    coef(g_all)
    #     omega    alpha1     beta1 
    # 0.1955762 0.1924522 0.1967614 
    
    coef(g_50p)
    #     omega    alpha1     beta1 
    # 0.2003755 0.1919633 0.1650453
    
    coef(g_20p)
    #        omega       alpha1        beta1 
    # 1.368689e-03 6.757177e-09 9.951920e-01
    

    看来数据量极端大的时候,估计才可能是合理的、稳定的。

    rugarch 参数估计的行为

    首先使用 1000 个模拟样本做连续估计,样本数从 500 升至 1000。

    library(doParallel)
    
    cl <- makeCluster(detectCores() - 1)
    registerDoParallel(cl)
    
    set.seed(110117)
    
    x <- garchSim(
        garchSpec(
            model = list(alpha = 0.2, beta = 0.2, omega = 0.2)),
        n.start = 1000, n = 1000)
    
    params <- foreach(
        t = 500:1000,
        .combine = rbind,
        .packages = c("rugarch")) %dopar%
        {
            getFitDataRugarch(x[1:t])
        }
    
    rownames(params) <- 500:1000
    
    params_df <- as.data.frame(params)
    params_df$t <- as.numeric(rownames(params))
    
    ggplot(params_df) +
        geom_line(
            aes(x = t, y = beta1)) +
        geom_hline(
            yintercept = 0.2, color = "blue") +
        geom_ribbon(
            aes(x = t,
                ymin = beta1 - 2 * beta1.se,
                ymax = beta1 + 2 * beta1.se),
            color = "grey", alpha = 0.5) +
        ylab(expression(hat(beta))) +
        scale_y_continuous(
            breaks = c(0, 0.2, 0.25, 0.5, 1)) +
        coord_cartesian(ylim = c(0, 1))
    

    几乎所有关于 (eta) 的估计都非常肯定的被认为是 1!这个结果相较于 fGarch 包来说,更加糟糕。

    让我们看看其他参数的行为。

    library(reshape2)
    library(plyr)
    library(dplyr)
    
    param_reshape <- function(p)
    {
        p <- as.data.frame(p)
        p$t <- as.integer(rownames(p))
    
        pnew <- melt(p, id.vars = "t", variable.name = "parameter")
    
        pnew$parameter <- as.character(pnew$parameter)
        pnew.se <- pnew[grepl("*.se", pnew$parameter), ]
        pnew.se$parameter <- sub(".se", "", pnew.se$parameter)
        names(pnew.se)[3] <- "se"
        pnew <- pnew[!grepl("*.se", pnew$parameter), ]
    
        return(
            join(
                pnew, pnew.se,
                by = c("t", "parameter"),
                type = "inner"))
    }
    
    ggp <- ggplot(
        param_reshape(params),
        aes(x = t, y = value)) +
        geom_line() +
        geom_ribbon(
            aes(ymin = value - 2 * se,
                ymax = value + 2 * se),
            color = "grey",
            alpha = 0.5) +
        geom_hline(yintercept = 0.2, color = "blue") +
        scale_y_continuous(
            breaks = c(0, 0.2, 0.25, 0.5, 0.75, 1)) +
        coord_cartesian(ylim = c(0, 1)) +
        facet_grid(. ~ parameter)
    
    print(ggp + ggtitle("solnp Optimization"))
    

    这种现象不仅限于 (eta)(omega)(alpha) 也表现出极端不良行为。

    极端大样本

    下面将样本总数扩充至 10000,连续估计的样本数从 5000 升至 10000,情况有会怎么样?

    set.seed(110117)
    
    x <- garchSim(
        garchSpec(
            model = list(alpha = 0.2, beta = 0.2, omega = 0.2)),
        n.start = 1000, n = 10000)
    
    params10k <- foreach(
        t = seq(5000, 10000, 100),
        .combine = rbind,
        .packages = c("rugarch")) %dopar%
        {
            getFitDataRugarch(x[1:t])
        }
    
    rownames(params10k) <- seq(5000, 10000, 100)
    
    params10k_df <- as.data.frame(params10k)
    params10k_df$t <- as.numeric(rownames(params10k))
    
    ggplot(params10k_df) +
        geom_line(
            aes(x = t, y = beta1)) +
        geom_hline(
            yintercept = 0.2, color = "blue") +
        geom_ribbon(
            aes(x = t,
                ymin = beta1 - 2 * beta1.se,
                ymax = beta1 + 2 * beta1.se),
            color = "grey", alpha = 0.5) +
        ylab(expression(hat(beta))) +
        scale_y_continuous(
            breaks = c(0, 0.2, 0.25, 0.5, 1)) +
        coord_cartesian(ylim = c(0, 1))
    

    结果堪称完美!之前的猜测是对的,样本要极端大才能保证估计的质量。

    其他参数的行为。

    ggp10k <- ggplot(
        param_reshape(params10k),
        aes(x = t, y = value)) +
        geom_line() +
        geom_ribbon(
            aes(ymin = value - 2 * se,
                ymax = value + 2 * se),
            color = "grey",
            alpha = 0.5) +
        geom_hline(yintercept = 0.2, color = "blue") +
        scale_y_continuous(
            breaks = c(0, 0.2, 0.25, 0.5, 0.75, 1)) +
        coord_cartesian(ylim = c(0, 1)) +
        facet_grid(. ~ parameter)
    
    print(ggp10k + ggtitle("solnp Optimization"))
    

    相较于 (eta)(omega)(alpha) 的估计值更加稳定,这一节论和之前文章中的结论大体一致,参数估计的不稳定性集中体现在 (eta) 身上。

    结论

    在一般大小样本量的情况下,rugarchfGarch 的表现都不好,即使改变函数的最优化算法(相关代码未贴出)也于事无补。不过当样本量极端大时,rugarch 的稳定性大幅改善,这似乎印证了机器学习中的一个常见观点,即大样本 + 简单算法胜过小样本 + 复杂算法

    为了解决非大样本情况下估计的稳定性问题,有必要找到一种 bootstrap 方法,人为扩充现实问题中有限的样本量;或者借鉴机器学习的思路,对参数施加正则化约束。

  • 相关阅读:
    TIMESTAMP类型字段在SQL Server和MySQL中的含义和使用
    Redis阻塞诊断基础
    MySQL分区表
    Redis 主从复制
    Redis安全以及备份还原
    Redis物理文件结构
    Redis的Errorlog或者启动日志(错误日志)的配置
    Redis 编译安装
    MySQL自增列锁模式 innodb_autoinc_lock_mode不同参数下性能测试
    SQL Server并发操作单个表时发生在page页面级的死锁
  • 原文地址:https://www.cnblogs.com/xuruilong100/p/10087995.html
Copyright © 2020-2023  润新知