Tracking Trades, Positions, and Profit and Loss in R
Summary
The document introduces two R packages for maintaining a record of portfolio trades and calculating positions and profit and loss: blotter and PMwR. It focuses on PMwR, showing how trades can be organized as a journal with instrument, date, quantity, and price, then summarized by instrument and used to calculate positions on a selected date.
The examples also show total and time-series profit and loss, including realized and unrealized components. Open positions require a valuation price to calculate profit and loss; without one, the example reports an unavailable total. The material is a practical illustration rather than a comparison of package features or a full accounting guide. It does not discuss fees, taxes, corporate actions, or how its calculations handle different accounting conventions, so users would need to check package documentation before relying on results for formal reporting.
Key ideas
- A trade journal records each transaction's instrument, date, amount, and price.
- Trade records can be used to calculate instrument positions at a chosen date.
- PMwR can report total profit and loss as well as realized and unrealized components over time.
- Open positions need a valuation price for profit and loss calculations.
Tags
Full text
# Portfolio Management in R
# Portfolio Management in R
I’ve been looking around for a R-package that will allow me to track my stock portfolio - basically I would like to enter stocks that I own, track the trades I make, calculate my open position & average cost, unrealized & realized P/L, etc… but I have not seen a package that does this. Has anyone read about/use one with these sorts of functions? Thanks.
## Answer by Joshua Ulrich (score 1)
https://quant.stackexchange.com/a/21505
You can do that with the blotter package. We use it to reconcile our trades.
It's only available on R-Forge, so see this stackoverflow question for how to install it. Run the "amzn_test" demo for an example of how to use it:
```
library(blotter)
demo(amzn_test)
```
## Answer by Enrico Schumann (score 1)
https://quant.stackexchange.com/a/46423
The PMwR package, which I maintain, provides such computations. The package is on CRAN and GitHub/GitLab.
Some example code:
```
library("PMwR")
trades <- read.table(text="
timestamp , instrument , amount , price
2019-06-25 , Amazon , 20 , 1878
2019-06-26 , Amazon , -10 , 1902
2019-07-01 , Amazon , -10 , 1921
2019-04-15 , Netflix , 20 , 362",
header = TRUE, sep = ",",
strip.white = TRUE, stringsAsFactors = FALSE)
trades$timestamp <- as.Date(trades$timestamp)
trades <- as.journal(trades)
trades
## instrument timestamp amount price
## 1 Amazon 2019-06-25 20 1878
## 2 Amazon 2019-06-26 -10 1902
## 3 Amazon 2019-07-01 -10 1921
## 4 Netflix 2019-04-15 20 362
##
## 4 transactions
```
`trades` is a `journal`, a list of your trades.
```
summary(trades)
## journal: 4 transactions in 2 instruments
##
## instrument n avg buy avg sell first last
## Amazon 3 1878 1911.5 2019-06-25 2019-07-01
## Netflix 1 362 NA 2019-04-15 2019-04-15
```
From this `journal`, you can now compute positions.
```
position(trades)
## 2019-07-01
## Amazon 0
## Netflix 20
position(trades, drop.zero = TRUE)
## 2019-07-01
## Netflix 20
position(trades, when = as.Date("2019-06-27"))
## 2019-06-27
## Amazon 10
## Netflix 20
```
And you can compute profit/loss.
```
pl(trades)
## Amazon
## P/L total 670
## average buy 1878
## average sell 1911.5
## cum. volume 40
##
## Netflix
## P/L total NA
## average buy 362
## average sell NA
## cum. volume 20
##
## ‘P/L total’ is in units of instrument;
## ‘volume’ is sum of /absolute/ amounts.
## ‘sum(amount)’ is not zero for Netflix: specify ‘vprice’ to compute p/l.
```
Since there is an open position in Netflix, we need to provide a price that is used for valuation (`vprice`).
```
pl(trades, vprice = c(Netflix = 380))
## Amazon
## P/L total 670
## average buy 1878
## average sell 1911.5
## cum. volume 40
##
## Netflix
## P/L total 360
## average buy 362
## average sell 380
## cum. volume 20
##
## ‘P/L total’ is in units of instrument;
## ‘volume’ is sum of /absolute/ amounts.
```
The function `pl` can also compute profit/loss over time.
```
pl(trades["Amazon"], along.timestamp = TRUE)
## Amazon
## timestamp 2019-06-25 2019-06-26 2019-07-01
## P/L total 0 480 670
## __ realised 0 240 670
## __ unrealised 0 240 0
## average buy 1878
## average sell 1911.5
## cum. volume 20 30 40
##
## ‘P/L total’ is in units of instrument;
## ‘volume’ is sum of /absolute/ amounts.
```Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.