Search code examples
rpackagextsquantmod

setOldClass("xts") causing problems in a custom R package


I wrote an R package which contains an S4 class which uses xts objects. It's my understanding that I need to include the line

setOldClass("xts")
stock.returns <- setClass(
    Class = "stock.returns",
    slots = c(xts_returns = "xts", timeframe = "timeframe", currency = "character"),
    prototype = prototype(xts_returns = xts::xts(, order.by = c(lubridate::today())), timeframe = timeframe(), currency = "Local")
)

at the top of my class definition script. Problems occur when I use my package to create my object. It works, but I occasionally get this warning repeated several times:

Found more than one class "xts" in cache; using the first, from namespace 'quantmod'

How can I force my class to use the correct xts package instead of defaulting to the quantmod package? Failing this, how do I at least stop the warnings?

I note this conversation between Hadley Wickham and another, on the same topic: http://r.789695.n4.nabble.com/setOldClass-quot-xts-quot-td4714332.html. It went nowhere.

EDIT: My NAMESPACE file is

# Generated by roxygen2: do not edit by hand

export("%>%")
export(EOMonth)
export(EOWeek)
export(VaR.cree)
export(date_to_sql_string)
export(df_to_xts)
export(ewma)
export(factor_model_maker)
export(flatten_xts)
export(get_USD_fx)
export(get_benchmark_index)
export(get_benchmark_xts_returns)
export(get_bond_index)
export(get_currency_index)
export(get_end_date)
export(get_financial_history)
export(get_financial_history_and_make_it_monthly)
export(get_frequency)
export(get_fund_performance)
export(get_fx_USD_history)
export(get_fx_cross)
export(get_index_snapshot)
export(get_metrics_history)
export(get_portfolio)
export(get_price_history)
export(get_shock_results)
export(get_shock_results.yield_version)
export(get_spc_xts_raw_total_returns)
export(get_spc_xts_returns)
export(get_start_date)
export(get_table_from_sql_CISMPRDSVR)
export(get_test_date)
export(get_ticker_xts_return_index)
export(get_ticker_xts_t_data_fs_eps)
export(get_watchlist)
export(get_yield_index)
export(market_capture_ratio)
export(previous_business_date_if_weekend)
export(price_plot)
export(rel_plot)
export(return_over_horizon)
export(rolling_correlation)
export(run_sql_in_CISMPRDSVR)
export(scenario_analysis)
export(show_regression)
export(single_experiment_summary)
export(stock.returns)
export(timeframe)
export(update_fund_performance_from_spreadsheet)
export(write.zoo)
export(xts_add_average_series)
export(xts_price_from_returns)
export(xts_returns)
exportClasses(timeframe)

And my DESCRIPTION file is:

Package: cree
Title: CI Risk Engine, Eh?
Version: 0.0.0.9000
Authors@R: person("Mr", "lebelinoz", email = "lebelinoz@mycompany.com", role = c("aut", "cre"))
Description: All the in-house risk tools built in R.
Depends: R (>= 3.3.1)
License: Proprietary. Do not distribute outside My Company Limited.
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.0.1
Imports:
    tidyverse,
    lubridate,
    quantmod,
    xts,
    zoo,
    RODBC,
    PerformanceAnalytics
Collate: 
    'Functions.R'
    'Sql_Wrapper.R'
    'StockPlot.R'
    'VaR.cree.R'
    'ewma.R'
    'timeframe.R'
    'stock.returns.R'
    'factor_model_maker.R'
    'get_benchmark_index.R'
    'get_bond_index.R'
    'get_currency_index.R'
    'get_financial_history.R'
    'get_fx_.R'
    'get_metrics_history.R'
    'get_portfolio.R'
    'get_price_history.R'
    'get_shock_results.R'
    'get_shock_results.yield_version.R'
    'get_yield_index.R'
    'market_capture_ratio.R'
    'return_over_horizon.R'
    'scenario_analysis.R'
    'show_regression.R'
    'show_regression_between_xts.R'
    'single_experiment_summary.R'
    'update_fund_performance_from_spreadsheet.R'

Solution

  • The problem is that your NAMESPACE file does not include any imports. Specifying Imports in the DESCRIPTION file only indicates that your package imports stuff from the listed packages. You must also explicitly import specific functions in the NAMESPACE file.

    Using a skeleton package, I can replicate the messages using the following commands:

    library(quantmod)
    stock_returns = anRpackage::stock.returns()@xts_returns
    economic.factor.model <- setClass("economic.factor.model",
        slots = c(stock_returns = "xts", factor_premiums = "xts"))
    

    But I don't get any messages if I import quantmod, xts, and zoo. My package contains only the following files:

    > ls -l anRpackage/*
    -rw-rw-r-- 1 josh josh  311 Jun 21 05:35 anRpackage/DESCRIPTION
    -rw-rw-r-- 1 josh josh   75 Jun 21 05:55 anRpackage/NAMESPACE
    
    anRpackage/man:
    total 4
    -rw-rw-r-- 1 josh josh 713 Jun 21 05:38 anRpackage-package.Rd
    
    anRpackage/R:
    total 4
    -rw-rw-r-- 1 josh josh 364 Jun 21 05:40 file.R
    

    The contents of DESCRIPTION are:

    Package: anRpackage
    Type: Package
    Title: What the package does (short line)
    Version: 1.0
    Date: 2017-06-21
    Author: Who wrote it
    Maintainer: Who to complain to <yourfault@somewhere.net>
    Description: More about what it does (maybe more than one line)
    License: What license is it under?
    Imports: quantmod, xts, zoo
    

    The contents of NAMESPACE are below. Note that I simply import everything from the 3 listed packages for testing purposes. It's better practice to selectively import only the functions you use. If you have no import() commands in your NAMESPACE file, you can use R CMD check to tell you what functions need to be imported from each package.

    Lesson learned: R CMD check is useful even if you don't intend to submit your package to CRAN. ;-)

    exportPattern("^[[:alpha:]]+")
    import(quantmod)
    import(xts)
    import(zoo)
    

    The contents of R/file.R are:

    setOldClass("xts")
    stock.returns <- setClass(
        Class = "stock.returns",
        slots = c(xts_returns = "xts",
                  timeframe = "character",
                  currency = "character"),
        prototype = prototype(xts_returns = xts::xts(, order.by = Sys.Date()),
                              timeframe = "timeframe()",
                              currency = "Local")
    )
    

    And the contents of man/anRpackage-package.Rd are:

    \name{anRpackage-package}
    \alias{anRpackage-package}
    \alias{anRpackage}
    \docType{package}
    \title{
    \packageTitle{anRpackage}
    }
    \description{
    \packageDescription{anRpackage}
    }
    \details{
    
    The DESCRIPTION file:
    \packageDESCRIPTION{anRpackage}
    \packageIndices{anRpackage}
    ~~ An overview of how to use the package, including the most important ~~
    ~~ functions ~~
    }
    \author{
    \packageAuthor{anRpackage}
    
    Maintainer: \packageMaintainer{anRpackage}
    }
    \references{
    ~~ Literature or other references for background information ~~
    }
    \keyword{ package }
    \seealso{
    ~~ Optional links to other man pages, e.g. ~~
    ~~ \code{\link[<pkg>:<pkg>-package]{<pkg>}} ~~
    }
    \examples{
    #~~ simple examples of the most important functions ~~
    }