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 49 forks source link

Can you add trades in one currency and value the portfolio in a different currency #124

Open joshuaulrich opened 3 weeks ago

joshuaulrich commented 3 weeks ago

@fmoudoute provided the code below in a comment on a separate issue. They want to know if blotter can report portfolio and account valuations in CNY based on changes in instrument and FX prices in a situation where an instrument trades in CNY but a trade is executed on swap with a price in USD.

He said:

So far from what I see, the transaction is recorded in USD indeed, but the portfolio summary seems to be showing CNY metrics.

I was hoping that I could book the trade in USD and blotter would update the valuation based on FX move and instrument closing prices.

Is it possible and am I not doing it properly, or is it not possible (a bit too stretch?) N.B. I did more exploratory work and by booking the trade in CNY (the instrument currency) and keeping the portfolio in USD, I get the right valuation metrics. But I could book the trade in another currency and having blotter convert it to CNY at the valuation step.

### set timezone
Sys.setenv(TZ="Asia/Taipei")
library(blotter)

### get prices (and adjust time to 3pm - arbitrary)
fetch <- function(symbol) {
    x <- getSymbols(symbol, from = "2024-01-01", to = "2024-09-09", auto.assign = FALSE)
    index(x) <- as.POSIXct(paste(index(x), "15:00:00"))
    colnames(x) <- sub("^.*\\.", "", colnames(x))
    x
}
GREE <- fetch("000651.SZ")
CNY <- na.approx(fetch("CNY=X"))

### assign the symbol as CNY/USD for use in blotter
`USD/CNY` <- USDCNY <- CNY
`CNY/USD` <- CNYUSD <- 1/Cl(CNY)

### define instruments
currency(c("CNY", "USD"))
exchange_rate("CNYUSD")
exchange_rate("USDCNY")
stock("GREE", currency = "CNY")

### delete account and portfolio if they exist
suppressWarnings({
    rm("account.Strategy1", "portfolio.Strategy1", pos = .blotter)
})

initDate <- as.POSIXct("2024-07-21 15:00:00", usetz = TRUE)
initEquity <- 12000000  # this amount is in USD

### initiate portfolio and account
initPortf("Strategy1", symbols = "GREE", initDate = initDate, currency = "USD")
initAcct("Strategy1", portfolios = "Strategy1", initEq = initEquity, initDate = initDate, currency = "USD")
addPortfInstr(Portfolio = "Strategy1", symbols = "GREE")

### prepare transaction (NOTE: trading on swap, so book trade in USD)
### daily valuation will/should be impacted by both currency (USDCNY) and equity move
trade_qty <- 250000
price_cny <- 38.50  # Price in RMB
fx_rate <- 7.12     # FX rate (1 USD = 7 RMB)
price_usd <- price_cny / fx_rate  # Converted price in USD
tradeDate <- as.POSIXct("2024-07-22 15:00", usetz = TRUE)

### add transaction
addTxn(Portfolio="Strategy1", Symbol="GREE", TxnDate=tradeDate,
       TxnPrice=price_usd, TxnQty=trade_qty, TxnFees=0, Currency="USD")

### update portfolio
updatePortf("Strategy1", Dates = "2024-07-22 15:00/")

image

fmoudoute commented 2 weeks ago

Thank you @joshuaulrich for creating the new post for me.