Profit and Loss
Compute profit and (or) loss of financial transactions.
pl(amount, ... ) ## Default S3 method: pl(amount, price, timestamp = NULL, instrument = NULL, multiplier = 1, multiplier.regexp = FALSE, along.timestamp = FALSE, approx = FALSE, initial.position = NULL, initial.price = NULL, vprice = NULL, tol = 1e-10, do.warn = TRUE, do.sum = FALSE, pl.only = FALSE, footnotes = TRUE, ... ) ## S3 method for class 'journal' pl(amount, multiplier = 1, multiplier.regexp = FALSE, along.timestamp = FALSE, approx = FALSE, initial.position = NULL, initial.price = NULL, vprice = NULL, tol = 1e-10, do.warn = TRUE, ... ) ## S3 method for class 'pl' pl(amount, ... ) ## S3 method for class 'pl' print(x, ..., use.crayon = NULL, na.print = ".", footnotes = TRUE) ## S3 method for class 'pl' as.data.frame(x, ... ) .pl(amount, price, tol = 1e-10, do.warn = TRUE)
amount |
numeric or a |
price |
numeric |
instrument |
character or numeric (though typically character) |
timestamp |
An atomic vector of mode
|
along.timestamp |
logical; or a a vector of
timestamps. If the latter, |
initial.position |
a |
initial.price |
prices to evaluate initial position |
vprice |
valuation price; a numeric vector. With several instruments, the
prices must be named, e.g. |
multiplier |
numeric vector. When |
multiplier.regexp |
logical. If |
approx |
logical |
tol |
numeric: threshold to consider a position zero. |
x |
a |
... |
further argument |
use.crayon |
logical |
na.print |
character: how to print |
do.warn |
logical: issue warnings? |
do.sum |
logical: sum profit/loss across instruments? |
pl.only |
logical: if |
footnotes |
logical, with default |
Computes profit and/or loss and returns a list with
several statistics (see Section Value, below). To get only
the profit/loss numbers as a numeric vector, set argument
pl.only
to TRUE
.
pl
is a generic function: The default input is
vectors for amount, price, etc. Alternatively (and often
more conveniently), the function may also be called with a
journal
or a data.frame
as its
input. For data frames, columns must be named
amount
, price
, and so on, as in a
journal
.
pl
may be called in two ways: either to compute
total profit/loss from a list of trades, possibly
broken down by instrument
and account
; or to
compute profit/loss over time. The latter case
typically requires setting arguments
along.timestamp
and/or vprice
(see
Examples). Profit/loss over time is always computed with
time in ascending order: so if the timestamps in
along.timestamp
are not sorted, the function will
sort them (and vprice
as well).
Using vprice
: when along.timestamp
is
logical (FALSE
or TRUE
),
vprice
can be used to value an open
position. For a single asset, it should be a single
number; for several assets, it should be named
vector, with names indicating the instrument
.
When along.timestamp
is used to pass a
custom timestamp: for a single asset, vprice
must be a vector with the same length as
along.timestamp
; for several assets, it must
be a numeric matrix with dimension
length(along.timestamp)
times number of
assets.
To use package crayon – which is only sensible
in interactive use –, either explicitly set
use.crayon
to TRUE
or set an option
PMwR.use.crayon
to TRUE
.
For pl
, an object of class pl
, which is
a list of lists: one list for each instrument. Each
such list contains numeric vectors: pl
,
realised
, unrealised
, buy
,
sell
, volume
.
For .pl
, a numeric vector with four elements:
profit/loss in units of the instrument, sum of
absolute amounts, average buy price, average sell
price.
Enrico Schumann <es@enricoschumann.net>
Schumann, E. (2020) Portfolio Management with R. http://enricoschumann.net/PMwR/
J <- journal(timestamp = c( 1, 2, 3), amount = c( 1, 1, -2), price = c(100, 102, 101)) pl(J) pl(amount = c( 1, 1, -2), price = c(100, 102, 101)) ## without a 'journal' J <- journal(timestamp = c( 1, 2, 3, 1, 2, 3), amount = c( 1, 1, -2, 1, 1, -2), price = c(100, 102, 101, 100, 102, 105), instrument = c(rep("Bond A", 3), rep("Bond B", 3))) pl(J) ## Bond A ## P/L total 0 ## average buy 101 ## average sell 101 ## cum. volume 4 ## ## Bond B ## P/L total 8 ## average buy 101 ## average sell 105 ## cum. volume 4 ## ## 'P/L total' is in units of instrument; ## 'volume' is sum of /absolute/ amounts. as.data.frame(pl(J)) ## a single data.frame ## pl buy sell volume ## Bond A 0 101 101 4 ## Bond B 8 101 105 4 lapply(pl(J), as.data.frame) ## => a list of data.frames ## $`Bond A` ## pl realised unrealised buy sell volume ## 1 0 NA NA 101 101 4 ## ## $`Bond B` ## pl realised unrealised buy sell volume ## 1 8 NA NA 101 105 4 pl(pl(J)) ## P/L as a numeric vector ## Bond A Bond B ## 0 8 ## Example for 'vprice' instrument <- c(rep("Bond A", 2), rep("Bond B", 2)) amount <- c(1, -2, 2, -1) price <- c(100, 101, 100, 105) ## ... no p/l because positions not closed: pl(amount, price, instrument = instrument, do.warn = FALSE) ## ... but with vprice specified, p/l is computed: pl(amount, price, instrument = instrument, vprice = c("Bond A" = 103, "Bond B" = 100)) ### ... and is, except for volume, the same as here: instrument <- c(rep("Bond A", 3), rep("Bond B", 3)) amount <- c(1, -2, 1, 2, -1, -1) price <- c(100, 101, 103, 100, 105, 100) pl(amount, price, instrument = instrument) ## p/l over time: example for 'along.timestamp' and 'vprice' j <- journal(amount = c(1, -1), price = c(100, 101), timestamp = as.Date(c("2017-07-05", "2017-07-06"))) pl(j) pl(j, along.timestamp = TRUE) pl(j, along.timestamp = seq(from = as.Date("2017-07-04"), to = as.Date("2017-07-07"), by = "1 day"), vprice = 101:104) ## Example for 'multiplier' jnl <- read.table(text = "instrument, price, amount FGBL MAR 16, 165.20, 1 FGBL MAR 16, 165.37, -1 FGBL JUN 16, 164.12, 1 FGBL JUN 16, 164.13, -1 FESX JUN 16, 2910, 5 FESX JUN 16, 2905, -5", header = TRUE, stringsAsFactors = FALSE, sep = ",") jnl <- as.journal(jnl) pl(jnl, multiplier.regexp = TRUE, ## regexp matching is case sensitive multiplier = c("FGBL" = 1000, "FESX" = 10)) ## use package 'crayon' ## Not run: ## on Windows, you may also need 'options(crayon.enabled = TRUE)' options(PMwR.use.crayon = FALSE) pl(amount = c(1, -1), price = c(1, 2)) options(PMwR.use.crayon = TRUE) pl(amount = c(1, -1), price = c(1, 2)) ## End(Not run)
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.