braverock / blotter

blotter provides transaction infrastructure for defining transactions, portfolios and accounts for trading systems and simulation. Provides portfolio support for multi-asset class and multi-currency portfolios. Actively maintained and developed.
112 stars 48 forks source link

currency breaks updatePortf #103

Open paglos opened 4 years ago

paglos commented 4 years ago

Following code works on blotter 0.9.1695, but not on 0.14.7

library(quantstrat)
library(quantmod)

currency("USD")
currency("EUR")

exchange_rate("EURUSD", currency="EUR", counter_currency="USD", src=list(name='EUR/USD', src='oanda'))

getSymbols("EURUSD", from="2019-11-01",to="2019-11-07")
colnames(EURUSD) <- "price"

initPortf("PF1", symbols= c("EURUSD"), currency="USD",initDate="2019-11-04")
initAcct("myacct", portfolios="PF1", initDate="2019-11-04",currency="USD", initEq=200000)
initOrders(portfolio="PF1",initDate="2019-11-04")

addTxn("PF1", Symbol="EURUSD", TxnDate="2019-11-05", TxnPrice = 1.24650, TxnQty= 100000)
addTxn("PF1", Symbol="EURUSD", TxnDate="2019-11-05", TxnPrice = 1.24620, TxnQty=-100000)

updatePortf("PF1",   Dates = "2019-11-04::2019-11-05")

Error in NextMethod(.Generic) : number of items to replace is not a multiple of replacement length

jaymon0703 commented 4 years ago

Hi @paglos the amzn_test.R demo works on 0.14.7 and shares the most similar structure to your example code. In order to reproduce your error could you share your source data?

joshuaulrich commented 4 years ago

Here's a self-contained example. I'm not sure an example with data(amzn) would work though. This may be an issue with daily data ("Date" class) interacting with POSIXct.

require(blotter)

currency(c("USD", "EUR"))
exchange_rate("EURUSD", "EUR", "USD")

EURUSD <-
  xts(c(1.116014, 1.11654, 1.116545, 1.11534, 1.110306, 1.10765, 1.106165),
      timeBasedSeq("2019-11-01/2019-11-07"), dimnames = list(NULL, "price"))

initPortf("PF1", "EURUSD", 0, "2019-11-04")
initAcct("myacct", "PF1", "2019-11-04", initEq = 200000)

addTxn("PF1", "EURUSD", "2019-11-05",  100000, 1.24650)
addTxn("PF1", "EURUSD", "2019-11-05", -100000, 1.24620)

updatePortf("PF1", NULL, "2019-11-04::2019-11-05")

Note that you get a different error if the column name of the EURUSD object is not "price".

require(blotter)

currency(c("USD", "EUR"))
exchange_rate("EURUSD", "EUR", "USD")

EURUSD <-
  xts(c(1.116014, 1.11654, 1.116545, 1.11534, 1.110306, 1.10765, 1.106165),
      timeBasedSeq("2019-11-01/2019-11-07"), dimnames = list(NULL, "foo"))

initPortf("PF1", "EURUSD", 0, "2019-11-04")
initAcct("myacct", "PF1", "2019-11-04", initEq = 200000)

addTxn("PF1", "EURUSD", "2019-11-05",  100000, 1.24650)
addTxn("PF1", "EURUSD", "2019-11-05", -100000, 1.24620)

updatePortf("PF1", NULL, "2019-11-04::2019-11-05")
# Error in getPrice(get(Symbol, pos = env), symbol = symbol, prefer = prefer) : 
#   subscript out of bounds, no price was discernible from the data
jaymon0703 commented 4 years ago

Thanks @joshuaulrich. Do you also get this error for your original self-contained example?

Error in attributes(xx) <- c(attributes(xx), dot.attrs) : 
  length of 'dimnames' [2] not equal to array extent
In addition: Warning message:
In max(start, as.numeric(s), na.rm = TRUE) :
  no non-missing arguments to max; returning -Inf
Called from: .xts(rep(NA, length(i)), .index(x)[i], dimnames = list(NULL, 
    colnames(x)))

Originates in line 94 of .updatePosPL.

joshuaulrich commented 4 years ago

@jaymon0703 I'm not sure what you mean. My first example replicates the error in the OP. My second example throws the error in the comment at the bottom of the example.

For what it's worth, here's my sessionInfo():

R> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 19.10

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.8.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.8.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] blotter_0.14.7               PerformanceAnalytics_1.5.2.2
[3] FinancialInstrument_1.3.1    quantmod_0.4-16             
[5] TTR_0.23-5                   xts_0.12-0                  
[7] zoo_1.8-5                   

loaded via a namespace (and not attached):
[1] compiler_3.6.1   curl_4.2         codetools_0.2-16 grid_3.6.1      
[5] iterators_1.0.12 foreach_1.4.7    boot_1.3-20      lattice_0.20-38 
[9] quadprog_1.5-7  
jaymon0703 commented 4 years ago

Apologies @joshuaulrich my bad...i think it was a case of premature debugging or debugging in a dirty environment.

@paglos if you use a timestamp in your example the code will work just fine. This would make sense to do for intraday transactions.

addTxn("PF1", "EURUSD", "2019-11-05 10:00:00",  100000, 1.24650)
addTxn("PF1", "EURUSD", "2019-11-05 11:00:00", -100000, 1.24620)

The error occurs in line 233. The problem starts in line 213 because we are merging objects of differing lengths. This can be avoided with more granularity in the transaction timestamps for intraday transactions.

jaymon0703 commented 4 years ago

hi @paglos can we close this issue?