Search code examples
roptimizationstatisticsdistributionmle

fitdistr from MASS library gives warnings when fitting t-distribution


I'm trying to reproduce the following example from David Ruppert's "Statistics and Data Analysis for Financial Engineering", which fits Students t-distribution to historical risk free rate:

library(MASS)
data(Capm, package = "Ecdat")
x <-  Capm$rf
fitt <- fitdistr(x,"t", start = list(m=mean(x),s=sd(x)), df=3)
as.numeric(fitt$estimate)
0.437310595161651 0.152205764779349

The output is accompanied by the following Warnings message:

Warning message:

In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs producedWarning message:
In log(s): NaNs produced

It appears from the R's help file that MASS::fitdistr uses maximum-likelihood for finding optimal parameters. However, when I do optimization manually (same book), all goes smoothly and there is no warnings:

library(fGarch)
loglik_t <- function(beta) {sum( - dt((x - beta[1]) / beta[2],
                                      beta[3], log = TRUE) + log(beta[2]) )}

start <- c(mean(x), sd(x), 5)
lower <- c(-1, 0.001, 1)
fit_t <- optim(start, loglik_t, hessian = T, method = "L-BFGS-B", lower = lower)
fit_t$par
0.44232633269102 0.163306955396773 4.12343777572566

The fitted parameters are within acceptable standard errors, and, in addition to mean and sd I have gotten df.

Can somebody advise me please:

  1. Why MASS::fitdistr produces warnings whereas optimization via fGarch::optim succeeds without a warning?
  2. Why there is no df in MASS::fitdistr output?
  3. Is there a way to run MASS:fitdistr on this data without a warning and get df?

Disclaimer:

a similar question was asked couple of times without an answer here and here


Solution

  • You are not passing the lower argument to the function fitdistr which leads it to make a search in positive and negative domain. By passing the lower argument to function

    fitt <- fitdistr(x,"t", start = list(m=mean(x),s=sd(x)), df=3, lower=c(-1, 0.001))
    

    you get no NaNs -as you did in your manual optimisation.

    EDIT:

    fitt <- fitdistr(x,"t", start = list(m=mean(x),s=sd(x),df=3),lower=c(-1, 0.001,1))
    

    returns non-integer degrees of freedom result. However, I guess, the rounded value of it, which is round(fitt$estimate['df'],0) can be used for fitted degrees of freedom parameter.