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.
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")
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")
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)
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).