web-dev-qa-db-ja.com

R:日次収益を月次収益に変換します

毎日のreturnsのxtsがあり、それを毎月の返品に変換したいと思います。

毎日のpricesをピリオドリターンに変換するスレッドのトンを見つけることができますが、毎日returnsを変換する必要があります。

うまく機能する this スレッドのアドバイスに従っていると、戻り値は幾何学的ではなく、算術的であることがわかりました。

したがって、cumprod(x + 1)^(365/12)-1のようなものが必要です。

ただし、sum(cx)をそれで置き換えることはできません。

これが現状の私のコードです。

 # Generate data like the type I'm working with    
    testdata <- cbind(rnorm(100,0.0001,0.01),rnorm(100,0.0001,0.01))
    testdata <- as.xts(testdata, order.by = seq(Sys.Date()-99,Sys.Date(),1))


   myFun <- function(x) {
    # need coredata, so c.xts will not be dispatched
     cx <- coredata(x)
     Return = sum(cx)
     }

   MonthlyReturns <- NULL
   for (i in 1:ncol(testdata)){
     MonthlyReturns <- cbind(MonthlyReturns,period.apply(testdata[,i], endpoints(testdata[,i], "months"), 
     myFun))
   }

助けてくれてありがとう!

編集-出力は入力と同じ形式である必要があります-毎日ではなく毎月の収益の表。 xtsまたはdataframe/matrixのいずれか。

編集-収益マトリックスの起源に興味がある人のために、私は here のようにPerformance AnalyticsパッケージのReturn.annualized関数を使用しています。 (実際、私はReturn.cumulativeを使用して、はるかに高速に変更しています)。つまり、価格マトリックスがあり、そこから月次収益を簡単に計算できますが、日次収益マトリックスには他の計算からの追加の列があるため、日次価格ではなく、日次収益を変換する必要があります。

2
Jimbo Mahoney

returnがどのように計算されるのかはわかりませんが、正しい方向に進むための方法を次に示します。

_library(data.table) 
library(lubridate) 

dat <- as.data.table(testdata)

> str(dat)
Classes ‘data.table’ and 'data.frame':  100 obs. of  3 variables:
 $ index: Date, format: "2020-01-01" "2020-01-02" ...
 $ V1   : num  0.00213 -0.00974 0.00751 -0.01194 0.0011 ...
 $ V2   : num  0.008688 0.019436 0.002724 0.000132 -0.010013 ...
 - attr(*, ".internal.selfref")=<externalptr> 

> dat[, .(mean(V1), mean(V2)), by = round_date(x = index, unit = 'month')]
   round_date           V1           V2
1: 2020-01-01 0.0013998013  0.001087134
2: 2020-02-01 0.0026295444  0.003307676
3: 2020-03-01 0.0008552149 -0.001801693
4: 2020-04-01 0.0004444565 -0.002700886
_

lubridateパッケージの_round_date_を使用して、各index日付を最も近い月に丸めています。 returnを取得するロジックがないため、meanを概念実証として使用していますが、必要に応じて列を作成できます。 .(mean(V1), new_col = V1*V2/log(V1))

注意:_round_date_は「最も近い」月に丸めます。これは、月の15日を過ぎている場合、次の例に示すように翌月に丸められることを意味します。

_> Sys.time()
[1] "2020-04-09 12:19:51 EDT"
> round_date(x = Sys.time(), unit = 'month')
[1] "2020-04-01 EDT"

# Adding 7 days to get past the month mid
> Sys.time() + days(7)
[1] "2020-04-16 12:20:11 EDT"
> round_date(x = Sys.time() + days(7), unit = 'month')
[1] "2020-05-01 EDT"
_

「最も近い月」ではなく月に関心がある場合は、by引数を変更できます。

_> dat[, .(mean(V1), mean(V2)), by = .(year(index), month(index))]
   year month           V1           V2
1: 2020     1 0.0024584093  0.002001868
2: 2020     2 0.0011554594  0.002243072
3: 2020     3 0.0006240678 -0.003083204
4: 2020     4 0.0009490493 -0.003752814
_

by引数にyear(index)を入れたのは、同じ月を別の年に持つ可能性があり、それらを組み合わせたくない可能性が高いためです。

これがお役に立てば幸いです!

0
Gautam