| pl {PMwR} | R Documentation |
Profit and Loss
Description
Compute profit and (or) loss of financial transactions.
Usage
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)
.pl_stats(amount, price, tol = sqrt(.Machine$double.eps))
Arguments
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 |
Details
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.
.pl and .pl_stats are helper functions
that are called by pl. .pl_stats
requires amount and price to be sorted in time, and
to be of length > 0.
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.
Value
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. If along.timestamp
is not FALSE, a vector timestamp
is also present.
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. For zero-length vector, the function evaluates to
c(0, 0, NaN, NaN).
For .pl_stats, a list of two elements:
the average entry-price, and the realized profit/loss.
profit/loss in units of the instrument, sum of
absolute amounts, average buy price, average sell
price. For zero-length vector, the function evaluates to
c(0, 0, NaN, NaN).
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2023) Portfolio Management with R. https://enricoschumann.net/PMwR/; in particular https://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#profit-and-loss
See Also
Examples
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)