Skip to content
All library documents

Tracking Trades, Positions, and Profit and Loss in R

Article Quant Q&A · Author: benr

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.