---
title: "Business-Day Scaling"
author: "Dave Mills"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Business-Day Scaling}
  %\VignetteEngine{knitr::rmarkdown}
  %\usepackage[utf8]{inputenc}
---

```{r message=F, warning=F, results='hide', echo=F}
library(ggplot2)
library(scales)
library(bdscale)
```

When graphing financial data, I prefer a continuous axis scale where weekends and holidays don't exist. Did the price remain unchanged for three days, or am I looking at labor-day weekend? 

## Create sample data

Load past NYSE trading dates, taken from Yahoo's S&P prices:

```{r}
data(nyse)
```

Then create some fake prices, put them into a `data.frame` alongside the dates:

```{r}
set.seed(12345)
df <- data.frame(date=nyse, price=cumsum(rnorm(length(nyse))) + 100)
df <- subset(df, as.Date('2014-08-01') <= date & date <= as.Date('2014-10-08'))
```

```{r, echo=FALSE, results='asis'}
knitr::kable(tail(df, 5))
```

## Plot on a standard calendar-day axis:

Create a plot:

```{r}
plot <- ggplot(df, aes(x=date, y=price)) + geom_step() + 
  theme(axis.title.x=element_blank(), axis.title.y=element_blank())
```

Note the large gap at the beginning of September, because Labor Day was on the 1st:

```{r, fig.width=7}
plot + ggtitle('calendar dates')
```

## Plot on a business-day axis:

Plotting against `scale_x_bd` instead removes weekends and holidays from the graph:

```{r, fig.width=7}
plot + scale_x_bd(business.dates=nyse, labels=date_format("%b '%y")) + 
  ggtitle('business dates, month breaks')
```

## Increasing density of breaks

In the previous chart, the major breaks are pretty far apart.

The package determined that breaks on the first trading day of each **month** gives me the largest number of breaks weakly less than maximum. I didn't specify a max, so it defaulted to `5`. 

If I tell it to use more, it can put breaks on the first day of each **week**:

```{r, fig.width=7}
plot + scale_x_bd(business.dates=nyse, max.major.breaks=10, labels=date_format('%d %b')) + 
  ggtitle('business dates, week breaks')
```

## Translating into business-day space

Say I wanted to put vertical lines on option expiration dates.

Calling `as.numeric(...)` on my dates translates them into the the number of calendar days after unix epoch, which is what `scale_x_date(...)` uses (see `scales:::from_date`):

```{r, fig.width=7}
options <- as.Date(c('2014-08-15', '2014-09-19'))

plot + 
  geom_vline(xintercept=as.numeric(options), size=2, alpha=0.25) + 
  ggtitle('calendar dates, option expiry')
```

This doesn't work for business-day space because the x-axis now represents the number of business days after the first date in your `business.dates` vector:

|             | `scale_x_date`                           | `scale_x_bd`                               
|-------------|------------------------------------------|--------------------------------------------|
| origin      | unix epoch: `1970-01-01`                 | first date in your `business.dates` vector |
| axis values | number of **calendar days** after origin | number of **business days** after origin   |
| conversion  | `as.numeric(...)`                        | `bd2t(..., business.dates)`                |

Instead, use the `bdscale::bd2t(...)` function to translate into business-day space:

```{r, fig.width=7}
plot + 
  geom_vline(xintercept=bd2t(options, business.dates=nyse), size=2, alpha=0.25) + 
  scale_x_bd(business.dates=nyse) +
  ggtitle('business dates, option expiry')
```
