rplot

plotting daily time series using ts.plot


I am trying to use ts.plot for plotting a daily time series. Since the default tick labels are not particularly meaningful, I am trying to suppress the x-axis first and then add a custom axis later:

library(quantmod)
getSymbols("MSFT", src = "yahoo", from = "2023-01-01", to = "2023-12-31")
msft_prices <- as.numeric(Cl(MSFT))
ts_msft <- ts(msft_prices, frequency = 365, start = c(2023, 1))
plot.ts(ts_msft, ylab = "stock price", xlab = "days", xaxt = "n")
date_labels <- seq(as.Date("2023-01-01"), by = "1 month", length.out = 12)
x_indices <- seq(1, length(ts_msft), length.out = length(date_labels))
axis(1, at = x_indices, labels = format(date_labels, "%b %d"), las = 2)

Unfortunately, the new x-axis is not printed. Does anyone see why that is? Thanks a million.


Solution

  • 1) autoplot.zoo it would be easier to use autoplot.zoo which uses ggplot2

    library(ggplot2)
    library(quantmod)
    
    getSymbols("MSFT", src = "yahoo", from = "2023-01-01", to = "2023-12-31")
    autoplot(Cl(MSFT)) +
      scale_x_date(date_breaks = "1 month", date_labels = "%b %d")
    

    (continued after graph) screenshot

    2) plot.xts Note that quantmod depends on zoo and xts so this does not use any more packages than are already being used in the question.

    library(quantmod)
    
    getSymbols("MSFT", src = "yahoo", from = "2023-01-01", to = "2023-12-31")
    plot(Cl(MSFT), format.labels = "%b %d")
    

    (continued after graph) screenshot

    3) ts ts does not work well with daily data. Note that there are not 365 days in MSFT. It does not even start on January 1st and end on December 31st. Weekends and holidays are missing. If you really want to use ts you are going to have to kludge it since ts is meant for regularly spaced series and MSFT is irregularly spaced.

    To do so we can represent the series as a ts series, tt, with times 1, 2, 3, ..., nrow(MSFT) and have an auxilliary vector of Date class giving the date corresponding to each index in tt. Then find the indexes of the start of each month, ix, use plot.ts suppressing the X axis and use axis to display it.

    # inputs
    dates <- time(MSFT)
    tt <- ts(Cl(MSFT))
    
    plot(tt, xaxt = "n")
    ix <- tapply(time(tt), format(dates, "%Y-%m"), min)
    axis(1, ix, format(dates[ix], "%b %d"), las = 2)
    

    (continued after graph) screenshot

    Another way to kludge it is to have NA's in the ts object to ensure regular spacing and then use the internal numeric value of dates which is the number of days since the UNIX Epoch (January 1, 1970).  That is we assume the input is the following where we are only using zoo and xts to form tt2 but from that point on only tt2 is used. We can then form tt and dates as shown above and proceed as we do there.

    library(quantmod)
    tt2 <- as.ts(as.zoo(Cl(MSFT))) # input
    
    ok <- !is.na(tt2)    
    tt <- ts(tt2[ok])
    dates <- .Date(time(tt2)[ok])
    
    # now use previous code with tt and dates
    

    Yet another way to kludge it is to use tt2 with the NA's but then the NA's will cause breaks in the lines. We can fix that by using linear interpolation to fill them in with approx but it is messy and takes us far way from the simple approaches in (1) and (2).