quantmod icon indicating copy to clipboard operation
quantmod copied to clipboard

modelReturn skips the first day of returns

Open AndreMikulec opened this issue 7 years ago • 1 comments

Description

modelReturn does not include in its math the first day of returns. In modelReturn, the calculation of 'daily returns' is incorrect.

Expected behavior

modelReturn must include in its math the 'first day of returns.'

Minimal, reproducible example

When I run the code, the following occurs.


library(quantmod)

getSymbols("IBM", from = "2017-01-01", to = "2018-10-20")

m <- specifyModel(Next(OpCl(IBM)) ~ Lag(OpHi(IBM)))
m.built <- buildModel(m,method='rpart',training.per=c("2017-01-01","2017-04-01"))
tm <- tradeModel(m.built,leverage=2)
tm

In modelReturn, the following happens.

# our model data in modelReturns
model.data <- modelData(tR.results$model, trade.dates, exclude.training = exclude.training)

Browse[3]> head(model.data)
           Next.OpCl.IBM Lag.OpHi.IBM
2017-04-03  0.0057630243  0.005575359 - (NOT INVESTED): DETERMINING WHAT TO INVEST  NEXT
2017-04-04 -0.0104178136  0.006040663
2017-04-05 -0.0058800023  0.008298772
2017-04-06  0.0003486576  0.009330309
2017-04-07 -0.0077088159  0.000000000
2017-04-10 -0.0004101494  0.004939511

# daily return and our morning signal
Browse[3]> head(trade.signal)
           Next.OpCl.IBM signal.zoo
2017-04-04  0.0057630243          1 - MORNING OF THE 4TH ( RETURN OF INVESTED ALL DAY  TODAY ) 
2017-04-05 -0.0104178136          1
2017-04-06 -0.0058800023          1
2017-04-07  0.0003486576          1
2017-04-10 -0.0077088159          1
2017-04-11 -0.0004101494          1

# profit that day (4TH)
model.results <- trade.signal[, 1] * leverage * trade.signal[, 2]
model.results[which(is.na(model.results))] <- 0

Browse[3]> head(model.results)
           Next.OpCl.IBM
2017-04-04  0.0115260486  0.005763024 * 2 = 0.01152605 (correct) - (4TH PROFIT)
2017-04-05 -0.0208356271
2017-04-06 -0.0117600045
2017-04-07  0.0006973152
2017-04-10 -0.0154176318
2017-04-11 -0.0008202989

# total returns
model.cumret <- cumprod(1 + model.results)

Browse[3]> head(model.cumret)
           Next.OpCl.IBM
2017-04-04     1.0115260 - EVE OF THE 4TH CUMULATIVE RETURN (I WAS INVESTED ALL DAY)
2017-04-05     0.9904503
2017-04-06     0.9788026
2017-04-07     0.9794851
2017-04-10     0.9643838
2017-04-11     0.9635927

# every days return
returnsBy <- allReturns(model.cumret)

Browse[3]> head(returnsBy) 
                   daily      weekly monthly quarterly yearly
2017-04-04            NA          NA      NA        NA     NA - returns of the 4th are SKIPPED
2017-04-05 -0.0208356271          NA      NA        NA     NA
2017-04-06 -0.0117600045          NA      NA        NA     NA
2017-04-07  0.0006973152 -0.03167585      NA        NA     NA
2017-04-10 -0.0154176318          NA      NA        NA     NA
2017-04-11 -0.0008202989          NA      NA        NA     NA

# that is actually 

Browse[3]> head(dailyReturn(model.cumret))
           daily.returns
2017-04-04  0.0000000000 - NOT CORRECT, I WAS INVESTED ALL DAY ON THE 4TH
2017-04-05 -0.0208356271
2017-04-06 -0.0117600045
2017-04-07  0.0006973152
2017-04-10 -0.0154176318
2017-04-11 -0.0008202989

# Perhaps, One may need to include the 'night of the previous day'
# where the Price == 1.0
Browse[3]> head( rbind( model.cumret, xts(1.0, head(index(model.data),1)) ) )
           Next.OpCl.IBM
2017-04-03     1.0000000 
2017-04-04     1.0115260 - ON THE 4TH, I WAS INVESTED ALL DAY
2017-04-05     0.9904503
2017-04-06     0.9788026
2017-04-07     0.9794851
2017-04-10     0.9643838

# So,now that looks right
Browse[3]> head(dailyReturn( rbind( model.cumret, xts(1.0, head(index(model.data),1)) ) ))
           daily.returns
2017-04-03  0.0000000000
2017-04-04  0.0115260486 - ON THE 4TH, I WAS INVESTED ALL DAY
2017-04-05 -0.0208356271
2017-04-06 -0.0117600045
2017-04-07  0.0006973152
2017-04-10 -0.0154176318

Session Info

Browse[2]> devtools::session_info()
- Session info ---------------------------------------------------------------
 setting  value
 version  R version 3.5.1 Patched (2018-10-09 r75424)
 os       Windows 10 x64
 system   x86_64, mingw32
 ui       RTerm
 language (EN)
 collate  English_United States.1252
 ctype    English_United States.1252
 tz       America/Chicago
 date     2018-10-25

- Packages -------------------------------------------------------------------
 package              * version date       lib source
 curl                   3.2     2018-03-28 [1] CRAN (R 3.5.1)
 devtools               2.0.0   2018-10-19 [1] CRAN (R 3.5.1)
 quantmod             * 0.4-13  2018-04-13 [1] CRAN (R 3.5.1)
 TTR                  * 0.23-4  2018-09-20 [1] CRAN (R 3.5.1)
 xts                  * 0.11-1  2018-09-12 [1] CRAN (R 3.5.1)
 zoo                  * 1.8-4   2018-09-19 [1] CRAN (R 3.5.1)

AndreMikulec avatar Nov 12 '18 02:11 AndreMikulec

@AndreMikulec as @joshuaulrich already pointed out, the 'mod'el in quantmod has never been complete or correct.

Linear model signals like this, in my experience, are not used in practice. They may be used to generate an indicator, more rarely to drive a signal process, but are simply impractical for actual trading rules. The model code in quantmod is more than a decade old at this point. It drove a lot of additional development in other R/Finance packages, but wasn't really useful or complete on its own.

All of the model should probably be deprecated and removed from the package completely.

Barring that, patches might be considered, but I don't think anyone with commit access is going to spend any time on feature requests.

braverock avatar Nov 12 '18 10:11 braverock