Fuzzyな結合

たとえば,財務データを使った投資モデルを考えるとき,決算日から即日データが更新されるわけではないので発表までのラグを考慮する必要がある.
考慮しないで捕らぬ狸の皮算用を喜ぶのはLook-aheadバイアス(先読みバイアス)とよび,その筋の分析屋に配属された新人がよく陥りがちな罠である.

ほかにもマーケットに絡むバイアスの例として,たとえばゴイスーにイケイケなマーケットのトレーディングモデルのバックテストを考える.
種々の事情により,直近の投資ユニバースしかとれなかったとする.
そのなかから,モメンタムトレードのバックテストをすると,オペレーションじたいは正確であっても結果のChartがExplodeする.
ユニバース指数自体はたいしたことないのに.

慣れると自分は天才でないことがわかるのだが,ごく希に有頂天になって周囲に自分の才能を吹聴する輩がいる.
これが,Survivorshipバイアスである.オマエは天才ではない.愚かなだけだ.
そんな報告を受けたら,そのチャートを元に個人トレーダになることを勧めることが周囲にも会社にも貢献するにちがいない.

そう,経済の発展と繁栄の背後には,死屍累々がいることを忘れてはならない.
USAとかJAPANとかUSJとか,あの頃が忘れられつつあるときに落とし穴がある.


閑話休題,月次データと四半期データがあったとき,これをうまいことバインドさせる方法は次の通り.
dd1にDATE,valueからなる月次データと,(めんどくさいから)そこから3ヵ月取り出したデータをくっつける.
普通に***_joinすると一致行しか結合されずにほかはNAになるんだけど,fuzzyjoinなるものをつかうと大なり,小なりで結合できる.

さいごにunique()でダブりをとらないといけないのだが,なぜそうなるかとか,そういう話はわかりません.

> require(tidyverse)
> require(fuzzyjoin)
> # Fuzzyな結合
> dd1 <- tibble(DATE=c(200101:200512))
> dd1 %>% mutate(value=runif(412), 
+                MM=DATE-round(DATE/100,0)*100) %>% 
+   filter(MM<=12 & MM>0) %>% 
+   select(-MM) -> dd1
> dd1 %>% 
+   mutate(MM=DATE%%3) %>% 
+   filter(MM==0) %>% 
+   select(-MM) %>% 
+   rename(DATE1=DATE, value1=value) %>% 
+   mutate(DATE2=lead(DATE1)) -> dd2
> 
> dd2 %>% 
+   fuzzy_right_join(dd1, .,
+                    by = c("DATE" = "DATE1", "DATE" = "DATE2"),
+                    match_fun = list(`>=`, `<`)) %>%
+   unique()
# A tibble: 57 × 5
     DATE      value  DATE1     value1  DATE2
    <int>      <dbl>  <int>      <dbl>  <int>
1  200103 0.90545862 200103 0.90545862 200106
2  200104 0.51608878 200103 0.90545862 200106
3  200105 0.81122443 200103 0.90545862 200106
4  200106 0.06892801 200106 0.06892801 200109
5  200107 0.25179652 200106 0.06892801 200109
6  200108 0.09716054 200106 0.06892801 200109
7  200109 0.45138717 200109 0.45138717 200112
8  200110 0.60871467 200109 0.45138717 200112
9  200111 0.58150930 200109 0.45138717 200112
10 200112 0.37703122 200112 0.37703122 200202
# ... with 47 more rows