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)