[R] xts形式のデータをプロットした時に困ること

MQL4 には一度も触れずに xts の話ばかりですが、まだ続けます。
実際、私なんかのレベルでは MQL4 について今さら書くようなことは無いんですよね・・・。
大抵のことはネットで検索すれば答えが見つかりますから。
R に関してもネットの情報量は膨大なのですが、意外と私の知りたいことはいくら検索してもなぜか見つからなかったりします。
やっぱり R でファイナンスデータの時系列分析をしている人は少数派という噂は本当なんですかね？
システムトレードを勉強していて R を知ったクチなので実感ありませんが。
そんなわけなので、今回も R 初心者の MT4 ユーザー（つまり私のこと）のためのネタです。

先にお断りしておきますが、各種仕様や機能についてどれが xts 固有のものでどれが zoo のものなのか、あるいはその他のものなのか、私はきちんとした区別ができておりません。
目に余る誤記述があるようでしたらご指摘頂けますと幸いです。

さて、R に取り込んだヒストリカルデータを xts 形式に変換するとデータを操作する際に日時での指定ができるようになるし、前回のように複数通貨ペアのデータを結合した時には自動でタイミングを揃えてくれるし、各種便利関数も使えるようになるしで、メリットはたくさんあるのですが、ちょっと困ったこともあります。

今回はプロットに関して書いてみます。

使用するデータ USDJPY60.xts は今年1月の某国内業者のドル円1時間足データで下記のような内容です。

```
> head(USDJPY60.xts,5)
                       Open    High     Low   Close
2014-01-02 00:00:00 105.239 105.387 105.219 105.362
2014-01-02 01:00:00 105.360 105.400 105.269 105.329
2014-01-02 02:00:00 105.330 105.332 105.243 105.315
2014-01-02 03:00:00 105.314 105.328 105.270 105.298
2014-01-02 04:00:00 105.301 105.322 105.235 105.239
```
まずはこれを普通にプロットしてみます。

```r:R
plot(USDJPY60.xts$Close, minor.ticks=FALSE, type="l",
     main="USDJPY60$Close", ylab="price")
```

ちなみに minor.ticks=FALSE しておかないと x 軸に1時間毎に目盛りが並んで目障りです。
すると・・・

![uj60_1.png](https://qiita-image-store.s3.amazonaws.com/0/43819/29a3fd11-3a81-b00f-1934-9bed5c63ca2e.png)

は？なんですかこれ・・・？

どうやらデータが存在しない週末までプロットされているようです。
いろいろ調べてみましたが、どうもこれは POSIXct（あるいは POSIXlt）属性のデータをプロットした時の仕様のようで、データがあろうがなかろうがそこに時間は存在する、ということらしく、インデックスすら存在しないのに律儀にプロットされてしまいます。

ちょっと寄り道になりますけど、これを手軽に回避する手段として quantmod パッケージを導入して、

```r:R
chartSeries(USDJPY60.xts$Close, minor.ticks=FALSE, type="l",
            theme = chartTheme("white", up.col="black"))
```

![uj60_2.png](https://qiita-image-store.s3.amazonaws.com/0/43819/c44dcf5f-143f-21b8-6497-cb1f8bddc5c4.png)

という手もあるのですが、これはこれで困ったことがあります。
この関数、存在しないインデックスを飛ばしてくれるのは良いのですが、欠損値まで飛ばしてくれちゃうのです。
試しに先程のデータから1/10から1/15を抜いたものをプロットしてみます。

```r:R
chartSeries(USDJPY60.NA.xts$Close, minor.ticks=FALSE, type="l",
            theme = chartTheme("white", up.col="black"))
```

![uj60_3.png](https://qiita-image-store.s3.amazonaws.com/0/43819/433c6683-58f1-7f6b-1fbf-a8b424465d09.png)

ね？
もちろんこれはこれでチャートツールとしては一般的な動作なのですが、複数のペアのプロットを並べて観察したい時などはこれでは困ります。
まぁそんな時のために欠損値を補間する関数もあるのですが・・・

```r:R
chartSeries(na.locf(USDJPY60.NA.xts$Close), minor.ticks=FALSE, type="l",
            theme = chartTheme("white", up.col="black"))
```

![uj60_4.png](https://qiita-image-store.s3.amazonaws.com/0/43819/0e31d4b8-b94f-6608-f824-84009050d161.png)

うーん、悪くはないんですけど、quantmod パッケージでは1枚のグラフに複数のデータを一緒に描くことができないのでやはり不便です。
もしかしたらできるのかもしれませんが、私にはそのやり方を見つけることはできませんでした。

なのでもうちょっと他のやり方を模索してみました。
存在しない週末のインデックスが描画されてしまうのはデータが POSIXct 属性だからなのです。
ということでその属性を剥がして描画してみます。

```r:R
plot(as.vector(USDJPY60.xts$Close), type="l",
     main="USDJPY60$Close", ylab="price")
```

![uj60_5.png](https://qiita-image-store.s3.amazonaws.com/0/43819/5f7e107a-31cb-b6d1-8bb0-ebe24d42171a.png)

当たり前ですが思った通りですね。
しかし x 軸の目盛りがただのインデックス値になってしまい、一体いつのデータなのかよくわからなくなってしまいました。
ならば目盛りを自分で作ってしまいましょう。
まずは x 軸の目盛りなしのグラフをプロットします。

```r:R
plot(as.vector(USDJPY60.xts$Close), type="l",
     main="USDJPY60$Close", ylab="price", xaxt="n")
```

次に目盛りのためのデータを作ります。
ここでは各日 00:00 毎に日付で刻んでみます。

```r:R
label.day <- axTicksByTime(USDJPY60.xts, "days", format.labels="%m-%d")
```

こんなのができます。

```
> head(label.day)
01-02 01-03 01-06 01-07 01-08 01-09 
    1    25    49    73    97   121
```

で、これを先程のグラフの x 軸に付け足します。

```r:R
axis(side=1, at=label.day, labels=names(label.day))
```

![uj60_6.png](https://qiita-image-store.s3.amazonaws.com/0/43819/ba31508e-aac2-58e3-34dc-e67d68a2088d.png)

そうそう、これが描きたかったんです！
これなら欠損値を含んだデータもこの通り。

![uj60_7.png](https://qiita-image-store.s3.amazonaws.com/0/43819/89f148d6-9097-278e-1600-d59b131eaed0.png)

ここに辿り着くまでに私は結構苦労してしまいました・・・。
素人の独学はしんどいです。
quantmod の chartSeries がどうやって週末を飛ばしているのか、さらに目盛りはどうやって振っているのか、その実装を調べていて axTicksByTime 関数を発見したりして。
もっとスマートなやり方をご存知の方がいらっしゃいましたらぜひご教示下さい。
そんなことしなくても ggplot2 とか rCharts とか Shiny で楽々だよ、みたいな。

ちなみに axTicksByTime と xts のコンビネーション、ticks.on の引数に "weeks" を指定すると変な値を返してきます。

```r:R
label.week <- axTicksByTime(USDJPY60.xts, "weeks")
```

```
> label.week
1 02 00:00 1 06 02:00 1 13 02:00 1 20 02:00 1 27 02:00 1 31 23:00 
         1         51        171        291        411        528 
```

"days" や "months" だったらちゃんと 00:00 の値が帰って来るんですけど、なんなんでしょうね？
とりあえずこれで得られた値を修正して先程のグラフに週頭のグリッド線を追加して今回はおしまいです。

```r:R
abline(v=c(49, 169, 289, 409), h=c(seq(102, 105, by=0.5)), col=8, lty=2)
```

![uj60_9.png](https://qiita-image-store.s3.amazonaws.com/0/43819/04b0ef3b-d005-3e35-0ca1-6247e2e4de68.png)