Type:  Package 
Title:  Portfolio Management with R 
Version:  0.193 
Date:  20231019 
Maintainer:  Enrico Schumann <es@enricoschumann.net> 
Description:  Functions and examples for 'Portfolio Management with R': backtesting investment and trading strategies, computing profit/loss and returns, analysing trades, handling lists of transactions, reporting, and more. 
Imports:  NMOF, datetimeutils, fastmatch, orgutils, parallel, textutils, utils, zoo 
Suggests:  crayon, rbenchmark, tinytest 
Depends:  R (≥ 3.5) 
License:  GPL3 
LazyLoad:  yes 
LazyData:  yes 
ByteCompile:  yes 
URL:  http://enricoschumann.net/PMwR/ , https://git.sr.ht/~enricoschumann/PMwR , https://gitlab.com/enricoschumann/PMwR , https://github.com/enricoschumann/PMwR 
NeedsCompilation:  no 
Packaged:  20231019 06:53:41 UTC; es19 
Author:  Enrico Schumann [aut, cre] 
Repository:  CRAN 
Date/Publication:  20231019 07:10:05 UTC 
Built:  R 4.5.0; ; 20240601 07:05:00 UTC; unix 
Tools for the Management of Financial Portfolios
Description
Functions for the practical management of financial portfolios: backtesting investment and trading strategies, computing profitandloss and returns, analysing trades, reporting, and more.
Details
PMwR provides a small set of reliable, efficient and convenient tools that help in processing and analysing trade/portfolio data. The Manual provides all the details; it is available from http://enricoschumann.net/PMwR/. Examples and descriptions of new features are provided at http://enricoschumann.net/notes/PMwR/.
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Gilli, M., Maringer, D. and Schumann, E. (2019) Numerical Methods and Optimization in Finance. 2nd edition. Elsevier. doi:10.1016/C2017001621X
Schumann, E. (2023) Portfolio Management with R. http://enricoschumann.net/PMwR/
Schumann, E. (2022) Financial Optimisation with R (NMOF Manual). http://enricoschumann.net/NMOF.htm#NMOFmanual
Adjust Time Series for Dividends and Splits
Description
Adjust a time series for dividends and splits.
Usage
div_adjust(x, t, div, backward = TRUE, additive = FALSE)
split_adjust(x, t, ratio, backward = TRUE)
Arguments
x 
a numeric vector: the series to be adjusted 
t 
An integer vector, specifying the positions in

div 
A numeric vector, specifying the dividends (or
payments, cashflows). If necessary, recycled to
the length of 
ratio 
a numeric vector, specifying the split ratios. The ratio must be ‘American Style’: a 2for1 stock split, for example, corresponds to a ratio of 2. (In other countries, for instance Germany, a 2for1 stock split would be called a 1for1 split: you keep your shares and receive one new share per share that you own.) 
backward 
logical 
additive 
logical 
Details
With backward
set to TRUE
, which is the
default, the final prices in the unadjusted series
matches the final prices in the adjusted series.
Value
a numeric vector of length equal to length(x)
Author(s)
Enrico Schumann
References
Schumann, E. (2021) Portfolio Management with R. http://enricoschumann.net/PMwR/
Using div_adjust
for handling generic external cashflows:
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#returnswithexternalcashflows
Examples
x < c(9.777, 10.04, 9.207, 9.406)
div < 0.7
t < 3
div_adjust(x, t, div)
div_adjust(x, t, div, FALSE)
## assume there were three splits: adjust shares outstanding
shares < c(100, 100, 200, 200, 1000, 1500)
t < c(3, 5, 6)
ratio < c(2, 5, 1.5)
### => invert ratio
split_adjust(shares, t, 1/ratio)
## [1] 1500 1500 1500 1500 1500 1500
split_adjust(shares, t, 1/ratio, backward = FALSE)
## [1] 100 100 100 100 100 100
Backtesting Investment Strategies
Description
Testing trading and investment strategies.
Usage
btest(prices, signal,
do.signal = TRUE, do.rebalance = TRUE,
print.info = NULL, b = 1, fraction = 1,
initial.position = 0, initial.cash = 0,
final.position = FALSE,
cashflow = NULL, tc = 0, ...,
add = FALSE, lag = 1, convert.weights = FALSE,
trade.at.open = TRUE, tol = 1e5, tol.p = NA,
Globals = list(),
prices0 = NULL,
include.data = FALSE, include.timestamp = TRUE,
timestamp, instrument,
progressBar = FALSE,
variations, variations.settings, replications)
Arguments
prices 
For a single asset, a matrix of prices with four
columns: open, high, low and close. For The series in Prices must be ordered by time (though the timestamps need not be provided). 
signal 
A function that evaluates to the position in units
of the instruments suggested by the trading
rule. If 
do.signal 
Logical or numeric vector, a function that
evaluates to When a logical vector, its length must match the
number of observations in prices:
If 
do.rebalance 
Same as 
print.info 
A function, called at the very end of each period,
i.e. after rebalancing. Can also be 
cashflow 
A function or 
b 
burnin (an integer). Defaults to 1. This may also
be a lengthone timestamp of the same class as

fraction 
amount of rebalancing to be done: a scalar between 0 and 1 
initial.position 
a numeric vector: initial portfolio in units of instruments. If supplied, this will also be the initial suggested position. 
initial.cash 
a numeric vector of length 1. Defaults to 0. 
final.position 
logical 
tc 
transaction costs as a fraction of turnover (e.g.,
0.001 means 0.1%). May also be a function that
evaluates to such a fraction. Morecomplex
computations may be specified with
argument 
... 
other named arguments. All functions (signal, do.signal, do.rebalance, print.info, cashflow) will have access to these arguments. See Details for reserved argument names. 
add 
Default is 
lag 
default is 1 
convert.weights 
Default is 
trade.at.open 
A logical vector of length one; default is 
tol 
A numeric vector of length one: only rebalance if
the maximum absolute suggested change for at least
one position is greater than 
tol.p 
A numeric vector of length one: only rebalance
those positions for which the relative suggested
change is greater than 
Globals 
A 
prices0 
A numeric vector (default is 
include.data 
logical. If 
include.timestamp 
logical. If 
timestamp 
a vector of timestamps, along prices (optional; mainly used for print method and journal) 
instrument 
character vector of instrument names (optional; mainly used for print method and journal) 
progressBar 
logical: display 
variations 
a list. See Details. 
variations.settings 
a list. See Details. 
replications 
an integer. If set, the function returns a list of

Details
The function provides infrastructure for testing
trading rules. Essentially, btest
does
accounting: keep track of transactions and positions,
value open positions, etc. The ingredients are price
timeseries (single series or OHLC
bars), which need not be equally spaced; and several
functions that map these series and other pieces of
information into positions.
How btest
works
btest
runs a loop from b + 1
to
NROW(prices)
. In iteration t
, a
signal
can be computed based on information
from periods prior to t
. Trading then takes
place at the opening price of t
. For
slowtocompute signals this is reasonable if there
is a time lag between close and open. For daily
prices, for instance, signals could be computed
overnight. For higher frequencies, such as every
minute, the signal function should be fast to
compute. Alternatively, it may be better to use a
larger time offset (i.e. use a longer time lag) and
to trade at the close of t
by setting
argument trade.at.open
to FALSE
.
If no OHLC bars are available, a single series per asset (assumed to be close prices) can be used.
The trade logic needs to be coded in the function
signal
. Arguments to that function must be
named and need to be passed with ...
.
Certain names are reserved and cannot be used as
arguments: Open
, High
, Low
,
Close
, Wealth
, Cash
,
Time
, Timestamp
, Portfolio
,
SuggestedPortfolio
, Globals
. Further
reserved names may be added in the future:
it is suggested to not start an argument
name with a capital letter.
The function signal
must evaluate to the
target position in units of the instruments. To
work with weights, set convert.weights
to
TRUE
, and btest
will translate the
weights into positions.
Accessing data
Within signal
(and also other function
arguments, such as do.signal
), you can
access data via special functions such as
Close
. These are automatically added as
arguments to signal
. Currently, the
following functions are available: Open
,
High
, Low
, Close
,
Wealth
, Cash
, Time
,
Timestamp
, Portfolio
,
SuggestedPortfolio
, Globals
.
Globals
is special: it is an
environment
, which can be used to
persistently store data during the run of
btest
. Use the argument Globals
to
add initial objects. See the Examples below and the
manual.
Additional functions may be added to btest
in the future. The names of those functions will
always be in title case. Hence, it is recommended
to not use argument names for signal
,
etc. that start with a capital letter.
Replications and variations
btest
allows to run backtests in
parallel. See the examples at
http://enricoschumann.net/notes/parallelbacktests.html.
The argument variations.settings
is a list with the
following defaults:
method
character: supported are
"loop"
,"parallel"
(or"snow"
) and"multicore"
load.balancing
logical
cores
numeric
Value
A list with class attribute btest
. The list comprises:
position 
actual portfolio holdings 
suggested.position 
suggested holdings 
cash 
cash 
wealth 
timeseries of total portfolio value (aka equity curve) 
cum.tc 
transaction costs 
journal 

initial.wealth 
initial wealth 
b 
burnin 
final.position 
final position if 
Globals 
environment 
When include.timestamp
is TRUE
, the
timestamp is included. If no timestamp
was
specified, integers 1, 2, ...
are used
instead.
When include.data
is TRUE
, essentially
all information (prices, instrument, the
actual call
and functions signal
etc.)
are stored in the list as well.
Author(s)
Enrico Schumann es@enricoschumann.net
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/;
in particular, see the chapter on backtesting:
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#backtesting
Schumann, E. (2018) Backtesting.
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3374195
Examples
## For more examples, please see the Manual
## http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html
## 1  a simple rule
timestamp < structure(c(16679L, 16680L, 16681L, 16682L,
16685L, 16686L, 16687L, 16688L,
16689L, 16692L, 16693L),
class = "Date")
prices < c(3182, 3205, 3272, 3185, 3201,
3236, 3272, 3224, 3194, 3188, 3213)
data.frame(timestamp, prices)
signal < function() ## buy when last price is
if (Close() < 3200) ## below 3200, else sell
1 else 0 ## (more precisely: build position of 1
## when price < 3200, else reduce
## position to 0)
solution < btest(prices = prices, signal = signal)
journal(solution)
## with Date timestamps
solution < btest(prices = prices, signal = signal,
timestamp = timestamp)
journal(solution)
## 2  a simple MA model
## Not run:
library("PMwR")
library("NMOF")
dax < DAX[[1]]
n < 5
ma < MA(dax, n, pad = NA)
ma_strat < function(ma) {
if (Close() > ma[Time()])
1
else
0
}
plot(as.Date(row.names(DAX)), dax, type = "l", xlab = "", ylab = "DAX")
lines(as.Date(row.names(DAX)), ma, type = "l")
res < btest(prices = dax,
signal = ma_strat,
b = n, ma = ma)
par(mfrow = c(3, 1))
plot(as.Date(row.names(DAX)), dax, type = "l",
xlab = "", ylab = "DAX")
plot(as.Date(row.names(DAX)), res$wealth, type = "l",
xlab = "", ylab = "Equity")
plot(as.Date(row.names(DAX)), position(res), type = "s",
xlab = "", ylab = "Position")
## End(Not run)
Deutscher Aktienindex (DAX)
Description
Historical Prices of the DAX.
Usage
data("DAX")
Format
A data frame with 505 observations on the following variable:
DAX
a numeric vector
Details
Close prices.
Examples
str(DAX)
Compute Drawdowns
Description
Compute drawdown statistics.
Usage
drawdowns(x, ...)
## Default S3 method:
drawdowns(x, ...)
## S3 method for class 'zoo'
drawdowns(x, ...)
Arguments
x 
a 
... 
additional arguments, to be passed to methods 
Details
drawdowns
is a generic function. It computes drawdown
statistics: maximum; and time of peak, trough and recovery.
Value
a data.frame
:
peak 
peak before drawdown 
trough 
lowest point 
recover 
new high or 
max 
the max drawdown 
Author(s)
Enrico Schumann
References
Gilli, M., Maringer, D. and Schumann, E. (2019) Numerical Methods and Optimization in Finance. 2nd edition. Elsevier. doi:10.1016/C2017001621X
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/; in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#drawdownsstreaks
See Also
The actual computation of the drawdowns is done by function
drawdown
in package NMOF.
Series of uninterrupted up and down movements can be
computed with streaks
.
Examples
x < c(100, 98)
drawdowns(x)
x < c(100, 98, 102, 99)
dd < drawdowns(x)
dd[order(dd$max, decreasing = TRUE), ]
Retrieve or Change Instrument
Description
Generic function for retrieving and changing instrument information.
Usage
instrument(x, ...)
instrument(x, ...) < value
Arguments
x 
an object 
... 
arguments passed to methods 
value 
an object 
Details
Generic function: extract or, if meaningful, replace instrument information
Value
when used to extract instrument, a character vector
Author(s)
Enrico Schumann
References
Schumann, E. (2023) Portfolio Management with R. http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html
See Also
Examples
jnl < journal(instrument = "A",
amount = 100,
price = 1)
instrument(jnl)
instrument(jnl) < "B"
Validate Security Identification Numbers
Description
Check whether a given ISIN or SEDOL is valid.
Usage
is_valid_ISIN(isin)
is_valid_SEDOL(SEDOL, NA.FALSE = FALSE)
Arguments
isin 
a character vector 
SEDOL 
a character vector 
NA.FALSE 
logical 
Details
Checks a character vector of ISINs and SEDOLs. The
function returns TRUE
if the ISIN is valid; else
FALSE
.
International Securities Identification Numbers (ISINs): The test procedure in ISO 6166 does not differentiate between cases. Thus, ISINs are transformed to uppercase before being tested.
Value
A named logical vector. For is_valid_SEDOL
, a character vector
is attached as an attribute note
.
Author(s)
Enrico Schumann
References
https://en.wikipedia.org/wiki/ISO_6166
https://en.wikipedia.org/wiki/SEDOL
https://annaweb.org/identifiers/
Examples
isin < c("US0378331005", "AU0000XVGZA3",
"DE000A0C3743", "not_an_isin")
is_valid_ISIN(isin)
is_valid_ISIN(c("US0378331005",
"us0378331005")) ## case is ignored
SEDOL < c("0263494", "B1F3M59", "0263491", "A", NA)
is_valid_SEDOL(SEDOL)
## 0263494 B1F3M59 0263491 A <NA>
## TRUE TRUE FALSE FALSE NA
is_valid_SEDOL(SEDOL, NA.FALSE = TRUE)
## 0263494 B1F3M59 0263491 A <NA>
## TRUE TRUE FALSE FALSE FALSE
Journal
Description
Create and manipulate a journal of financial transactions.
Usage
journal(amount, ...)
as.journal(x, ...)
is.journal(x)
## Default S3 method:
journal(amount, price, timestamp, instrument,
id = NULL, account = NULL, ...)
## S3 method for class 'journal'
c(..., recursive = FALSE)
## S3 method for class 'journal'
length(x)
## S3 method for class 'journal'
aggregate(x, by, FUN, ...)
## S3 method for class 'journal'
print(x, ...,
width = getOption("width"), max.print = getOption("max.print"),
exclude = NULL, include.only = NULL)
## S3 method for class 'journal'
sort(x, decreasing = FALSE, by = "timestamp", ..., na.last = TRUE)
## S3 method for class 'journal'
summary(object, by = "instrument", drop.zero = TRUE,
na.rm = FALSE, ...)
## S3 method for class 'journal'
subset(x, ...)
## S3 method for class 'journal'
x[i, match.against = NULL,
ignore.case = TRUE, perl = FALSE, fixed = FALSE,
useBytes = FALSE, ..., invert = FALSE]
## S3 replacement method for class 'journal'
x[i, match.against = NULL,
ignore.case = TRUE, ..., invert = FALSE] < value
## S3 method for class 'journal'
as.data.frame(x, row.names = NULL, optional = FALSE, ...)
## S3 method for class 'journal'
head(x, n = 6L, ..., by = "instrument")
## S3 method for class 'journal'
tail(x, n = 6L, ..., by = "instrument")
Arguments
timestamp 
An atomic vector of mode numeric or character. Timestamps should typically be sortable. 
amount 
numeric 
price 
numeric 
instrument 
character or numeric (though typically character) 
id 
An atomic vector. Default is 
account 
An atomic vector. Default is 
... 
For For For For 
x 
a 
object 
a 
width 
integer. See 
decreasing 
passed to 
by 

na.rm 
logical 
drop.zero 
logical 
na.last 
arguments passed to sort 
max.print 
maximum number of transactions to print 
exclude 
character: fields that should not be printed 
include.only 
character: print only those fields. (Not supported yet.) 
row.names 
see 
optional 
see 
recursive 
ignored (see 
i 
integer, logical or character. The latter is interpreted as a
regexp (see 
n 
integer 
match.against 
character vector of field names. Default is 
ignore.case 
logical: passed to 
perl 
logical: passed to 
fixed 
logical: passed to 
useBytes 
logical: passed to 
invert 
logical. If 
FUN 
either a function that takes as input a journal and evaluates to a journal, or a list of named functions 
value 
a replacement value 
Details
The journal
function creates a list of its arguments
and attaches a class attribute (‘journal
’).
It is a generic function; the default method creates a
journal from atomic vectors. The btest
method
extracts the journal from the results of a backtest; see
btest
.
as.journal
coerces an object to a journal and is
primarily used for creating a journal from a
data.frame
.
Calling as.journal
on an unnamed numeric vector
interprets the vector as amounts. If the vector is named,
these are interpreted as instruments; see Examples. Calling
as.journal
on a journal returns the journal itself.
journal
methods are available for several generic
functions, for instance:
all.equal
compare contents of two journals
aggregate
Splits a journal according to
by
, applies a function to every subjournal and recombines the results into a journal.as.data.frame
Coerce journal to
data.frame
.c
Combine several journals into one. Note that the first argument to
c.journal
must inherit fromjournal
, or else the method dispatch will fail. For empty journals, usejournal()
(notNULL
).length
number of transactions in a journal; it uses the length of
amount
split
Splits a journal according to
f
, yielding a list of journals. Often used interactively to have information per subjournal printed.subset
evaluates an expression in an environment that can access all fields of the journal. The function is meant for interactive analysis; care is needed when it is used within other functions: see Examples and the Manual.
summary
provides summary statistics, such as number of trades and average buy/sell prices
toOrg
converts a journal to an Org table; package orgutils must be available
For journals that have a length, missing arguments will be
coded as NA
except for id
and
account
, which become NULL
. In
zerolength (i.e. ‘empty’) journals, all fields have
length 0. A zerolength journal is created, for instance,
by saying journal()
or when an zerorow
data.frame
is passed to as.journal
.
Value
An object of class journal
, which is a list of atomic
vectors.
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/R/packages/PMwR/;
in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#journals
See Also
Examples
j < journal(timestamp = 1:3,
amount = c(1,2,3),
price = 101:103,
instrument = c("Stock A", "Stock A", "Stock B"))
## *** subset *** in functions
## this should work as expected ...
t0 < 2.5
subset(j, timestamp > t0)
## ... but here?!
tradesAfterT < function(j, t0)
subset(j, timestamp > t0)
tradesAfterT(j, 0)
## if really required
tradesAfterT < function(j, t0) {
e < substitute(timestamp > t0, list(t0 = t0))
do.call(subset, list(j, e))
}
tradesAfterT(j, 0)
## ... or much simpler
tradesAfterT < function(j, t0)
j[j$timestamp > t0]
tradesAfterT(j, 0)
## *** aggregate ***
## several buys and sells on two days
## aim: find average buy/sell price per day
j < journal(timestamp = structure(c(15950, 15951, 15950, 15951, 15950,
15950, 15951, 15951, 15951, 15951),
class = "Date"),
amount = c(3, 4, 3, 1, 3, 2, 1, 3, 5, 3),
price = c(104, 102, 102, 110, 106, 104, 104, 106, 108, 107),
instrument = c("B", "B", "A", "A", "B", "B", "A", "B", "A", "A"))
by < list(j$instrument, sign(j$amount), as.Date(j$timestamp))
fun < function(x) {
journal(timestamp = as.Date(x$timestamp[1]),
amount = sum(x$amount),
price = sum(x$amount*x$price)/sum(x$amount),
instrument = x$instrument[1L])
}
aggregate(j, by = by, FUN = fun)
## *** iterate over transactions in (previously defined) journal ***
for (j in split(j, seq_along(j)))
print(j)
## as.journal with numeric vector
as.journal(1:3)
## amount
## 1 1
## 2 2
## 3 3
##
## 3 transactions
## as.journal with *named* numeric vector
x < 1:3; names(x) < LETTERS[1:3]
as.journal(x)
## instrument amount
## 1 A 1
## 2 B 2
## 3 C 3
##
## 3 transactions
x < 1:3; names(x) < c("A", "B", "A")
as.journal(x)
## instrument amount
## 1 A 1
## 2 B 2
## 3 A 3
##
## 3 transactions
NetAssetValue (NAV) Series
Description
Create a netassetvalue (NAV) series.
Usage
NAVseries(NAV, timestamp,
instrument = NULL, title = NULL, description = NULL,
drop.NA = NULL)
as.NAVseries(x, ...)
## S3 method for class 'NAVseries'
print(x, ... )
## S3 method for class 'NAVseries'
summary(object, ..., monthly.vol = TRUE,
bm = NULL, monthly.te = TRUE,
na.rm = FALSE, assume.daily = FALSE)
## S3 method for class 'NAVseries'
plot(x, y, ..., xlab = "", ylab = "", type = "l")
## S3 method for class 'NAVseries'
window(x, start = NULL, end = NULL, ...)
Arguments
NAV 
numeric 
timestamp 

instrument 
character 
title 
character 
description 
character 
x 
an 
object 
an 
... 
further arguments. For 
drop.NA 
logical 
bm 
an optional NAVseries. If 
monthly.vol 
if 
monthly.te 
if 
assume.daily 
logical 
na.rm 
logical 
y 
a second NAVseries to be plotted. Not supported yet. 
xlab 
character 
ylab 
character 
type 
character. See 
start 
same class as timestamp; 
end 
same class as timestamp; 
Details
NAV series
An NAVseries is a numeric vector (the actual series) and
additional information, attached as attributes: timestamp,
instrument, title, description. Of these attributes,
timestamp is the most useful, as it is used for several
computations (e.g. when calling summary
) or for
plotting.
Summaries
The summary
method returns a list of the original
NAVseries plus various statistics, such as return per year
and volatility. The method may receive several NAV series as
input
Value
an NAVseries
: see Details.
an NAVseries
summary: a list of lists. If a
benchmark series is present, the summary has an
attribute bm
: an integer, specifying the
position of the benchmark.
Note
The semantics of handling NAVseries are not stable
yet. Currently, objects of class NAVseries
are
univariate: you create a single NAVseries, summarise
it, plot it, and so one. In the future, at least some
of the methods will support the multivariate case,
i.e. be able to handle several series at once.
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/; in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#NAVseries
See Also
For handling external cashflows, see unit_prices
,
split_adjust
and div_adjust
.
Examples
summary(NAVseries(DAX[[1]], as.Date(row.names(DAX)), title = "DAX"))
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 = 1e10, 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 = 1e10, 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 = 1e10, 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 zerolength vector, the function evaluates to
c(0, 0, NaN, NaN)
.
For .pl_stats
, a list of two elements:
the average entryprice, and the realized profit/loss.
profit/loss in units of the instrument, sum of
absolute amounts, average buy price, average sell
price. For zerolength 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. http://enricoschumann.net/PMwR/; in particular http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#profitandloss
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("20170705", "20170706")))
pl(j)
pl(j,
along.timestamp = TRUE)
pl(j,
along.timestamp = seq(from = as.Date("20170704"),
to = as.Date("20170707"),
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)
Plot Time Series During Trading Hours
Description
Plot a time series after removing weekends and specific times of the day.
Usage
plot_trading_hours(x, t = NULL, interval = "5 min",
labels = "hours", label.format = NULL,
exclude.weekends = TRUE, holidays = NULL,
fromHHMMSS = "000000", toHHMMSS = "240000",
do.plot.axis = TRUE,
...,
from = NULL, to = NULL,
do.plot = TRUE,
axis1.par = list())
Arguments
x 
A numeric vector. Can also be of class 
t 
A vector that inherits from class 
interval 
A character string like “num units”, in which 
labels 
A character vector of length one, determining the grid for

label.format 
See 
exclude.weekends 
logical: default is 
holidays 
a vector of class 
fromHHMMSS 
a character vector of length one in format “HHMMSS” 
toHHMMSS 
a character vector of length one in format “HHMMSS” 
do.plot.axis 
logical. Should 
... 

from 
POSIXct: start plot at (if not specified, plot starts at first data point) 
to 
POSIXct: end plot at (if not specified, plot ends at last data point) 
do.plot 
logical. Should anything be plotted? Default is 
axis1.par 
a list of named elements 
Details
Plot a timeseries during specific times of day.
Value
A list (invisibly if do.plot
is TRUE
):
list(t, x, axis.pos = pos, axis.labels, timegrid)
t 
positions 
x 
values 
axis.pos 
positions of xtickmarks 
axis.labels 
labels at xticks 
timegrid 
a POSIXct vector 
map 
a function. See the manual (a link is under References). 
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
B.D. Ripley and K. Hornik. DateTime Classes. RNews, 1(2):8–12, 2001.
E. Schumann (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/; in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#plottradinghours
See Also
Examples
t < as.POSIXct("20120831 08:00:00") + 0:32400
x < runif(length(t))
par(tck = 0.001, mgp = c(3,1,0.5), bty = "n")
p < plot_trading_hours(x, t,
interval = "5 min", labels = "hours",
xlab = "time", ylab = "random points",
col = "blue")
## with ?lines
t < as.POSIXct("20120831 10:00:00") + 0:9000
x < seq(0, 1, length.out = 9001)
lines(p$map(t)$t, x[p$map(t)$ix], pch = 19)
Internal Functions
Description
Internal functions, not exported from the PMwR namespace.
Usage
.timestamp(x)
.timestamp(x) < value
.may_be_Date(x, ...)
Details
.timestamp
extracts or replaces an object's timestamp.
.may_be_Date
checks whether a vector could be
coerced to class Date
, in which case it
evaluates to (a single) TRUE
; otherwise it returns
FALSE
. If TRUE
, the actual Date
s are
attached as an attribute Date
.
Author(s)
Enrico Schumann
References
E. Schumann (2023) Portfolio Management with R. http://enricoschumann.net/PMwR/
Aggregate Transactions to Positions
Description
Use information on single trades to compute a position at a specific point in time.
Usage
position(amount, ...)
## Default S3 method:
position(amount, timestamp, instrument, when,
drop.zero = FALSE, account = NULL,
use.names = NULL, ...)
## S3 method for class 'journal'
position(amount, when, drop.zero = FALSE,
use.account = FALSE, ...)
## S3 method for class 'position'
print(x, ..., sep = ":")
Arguments
when 
a timestamp or a vector of timestamps; alternatively, several keywords are supported. See Details. 
amount 
numeric or an object of class 
timestamp 
numeric or character: timestamps, must be sortable 
instrument 
character: symbols to identify different instruments 
account 
character: description of account. Ignored if 
use.account 
logical 
use.names 
logical 
drop.zero 
If logical, drop instruments that have a zero
position; default is 
x 
An object of type position. 
... 
arguments passed to 
sep 
A regular expression. Split instruments accordingly. Not implemented yet. 
Details
position
is a generic function; most useful is
the method for journal
s.
The function checks if timestamp
is sorted (see
is.unsorted
) and sorts the journal by timestamp
,
if required. If there are (some) NA
values in timestamp
,
but timestamp
is sorted otherwise, the function will proceed
(with a warning, though).
The argument when
can also be specified as one of several
keywords: last
(or newest
or latest
) provides the
position at the latest timestamp; first
(or oldest
)
provides the position at the earliest timestamp; all
provides
the positions at all timestamps in the journal. endofday
,
endofmonth
and endofyear
provide positions at the end of all calendar days, months and years within the
timestamp range of the journal. The latter keywords can only work if
timestamp
can be coerced to Date
.
Value
An object of class position
, which is a numeric matrix with
instrument
and timestamp
attributes. Note that
position
will never drop the result's dim
attribute: it
will always be a matrix of size length(when)
times
length(unique(instrument))
, which may not be obvious from the
printed output.
To extract the numeric position matrix, say as.matrix(p)
.
Author(s)
Enrico Schumann
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/R/packages/PMwR/;
in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#computingbalances
See Also
Examples
position(amount = c(1, 1, 1, 3, 4), timestamp = 1:5, when = 4.9)
## using a journal
J < journal(timestamp = 1:5, amount = c(1, 1, 1, 3, 4))
position(J, when = 4.9)
Price Table
Description
Create price table
Usage
pricetable(price, ...)
Arguments
price 
a matrix 
... 
further arguments, passed to methods 
Details
pricetable
is a helper function for extracting
prices of particular instrument at specified dates.
For this, it first creates a table that merges series
passed via ... and appends a class attribute. A [
method then allows to extract prices. Importantly, if
you ask for a subset of m rows and n columns, the
result will be a matrix of size m times n, even if
times or instruments are missing.
pricetable
is a generic function, currently
with methods for numeric vectors (including vectors
with a dim
, aka matrices) and for
zoo
objects.
Value
a numeric matrix with class attribute pricetable
Author(s)
Enrico Schumann
References
Schumann, E. (2020) Portfolio Management with R. http://enricoschumann.net/R/packages/PMwR/
See Also
Examples
## quickly creating a pricetable
pricetable(1:3)
pricetable(1:3, instrument = c("A", "B", "C"))
### ... and the same
pricetable(c(A = 1, B = 2, C = 3))
## subsetting examples
m < 3
n < 2
price < array(c(1:m, 1:m + 100), dim = c(m,n))
colnames(price) < LETTERS[1:n]
pt < pricetable(price, timestamp = 1:m)
## A B
## 1 1 101
## 2 2 102
## 3 3 103
pt[ , "A"]
## A
## 1 1
## 2 2
## 3 3
pt[ , c("X", "A", "X")]
## X A X
## 1 NA 1 NA
## 2 NA 2 NA
## 3 NA 3 NA
pt[ , c("X", "A", "X"), missing = 0]
## X A X
## 1 0 1 0
## 2 0 2 0
## 3 0 3 0
pt[c(0, 1.5, 4), , missing = "locf"]
## A B
## 0 NA NA
## 1.5 2 102
## 4 3 103
Treasury Quotes with 1/32nds of Point
Description
Print treasury quotes with 1/32nds of points.
Usage
quote32(price, sep = "(':)", warn = TRUE)
q32(price, sep = "(':)", warn = TRUE)
Arguments
price 
numeric or character. See Details. 
sep 
character: a regular expression 
warn 
logical. Warn about rounding errors? 
Details
The function is meant for prettyprinting of US treasury bond quotes; it provides no other functionality.
If price
is numeric
, it is interpreted as a quote in
decimal notation and ‘translated’ into a price quoted in
fractions of a point.
If price
is character
, it is interpreted as a quote in
fractional notation.
q32
is a shorthand for quote32
.
Value
A numeric vector of class quote32
.
Author(s)
Enrico Schumann
References
CME Group (2015). Treasury Futures Price Rounding Conventions. https://www.cmegroup.com/education/articlesandreports/treasuryfuturespriceroundingconventions.html
Examples
quote32(100 + 17/32 + 0.75/32)
q32("100172")
q32("100272")  q32("100270")
as.numeric(q32("100272")  q32("100270"))
Return Contribution
Description
Return contribution of portfolio segments.
Usage
rc(R, weights, timestamp, segments = NULL,
R.bm = NULL, weights.bm = NULL,
method = "contribution",
linking.method = NULL,
allocation.minus.bm = TRUE,
tol = sqrt(.Machine$double.eps))
Arguments
R 
returns: a numeric matrix 
weights 
the segment weights: a numeric matrix.

timestamp 
character or numeric 
segments 
character. If missing, column names of 
method 
a string 
linking.method 

allocation.minus.bm 
logical 
tol 
numeric: weights whose absolute value is below

If portfolio returns are to be compared against benchmark returns, benchmark returns/weights must be supplied:
R.bm 
returns: a numeric matrix 
weights.bm 
the segment weights: a numeric matrix.

Details
The function computes segment contribution, potentially
over time. Returns and weights must be arranged in
matrices, with rows corresponding to time periods and
columns to portfolio segments. If weights
and
R
are not matrices (i.e. are atomic vectors), then
they are interpreted as crosssectional weights/returns
for a single period.
Weights can be missing, in which case R
is
assumed to already comprise segment returns.
Value
A list of two components
period_contributions 
a data.frame 
total_contributions 
a numeric vector 
Author(s)
Enrico Schumann
References
Jon A. Christopherson and David R. CariĆ±o and Wayne E. Ferson (2009), Portfolio Performance Measurement and Benchmarking, McGrawHill.
Feibel, Bruce (2003), Investment Performance Measurement, Wiley.
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#returncontribution
See Also
Examples
weights < rbind(c( 0.25, 0.75),
c( 0.40, 0.60),
c( 0.25, 0.75))
R < rbind(c( 1 , 0),
c( 2.5, 1.0),
c(2 , 0.5))/100
rc(R, weights, segment = c("equities", "bonds"))
## contribution for btest:
## run a portfolio 10% equities, 90% bonds
P < as.matrix(merge(DAX, REXP, by = "row.names")[, 1])
(bt < btest(prices = list(P),
signal = function() c(0.1, 0.9),
convert.weights = TRUE,
initial.cash = 100))
W < bt$position*P/bt$wealth
rc(returns(P)*W[nrow(W), ])$total_contributions
Rebalance Portfolio
Description
Compute the differences between two portfolios.
Usage
rebalance(current, target, price,
notional = NULL, multiplier = 1,
truncate = TRUE, match.names = TRUE,
fraction = 1, drop.zero = FALSE,
current.weights = FALSE,
target.weights = TRUE)
## S3 method for class 'rebalance'
print(x, ..., drop.zero = TRUE)
replace_weight(weights, ..., prefix = TRUE, sep = "::")
Arguments
current 
the current holdings: a (typically named) vector of position sizes;
can also be a 
target 
the target holdings: a (typically named) vector of weights;
can also be a 
price 
a numeric vector: the current prices; may be named 
notional 
a single number: the value of the portfolio; if missing,
replaced by 
multiplier 
numeric vector, possibly named 
truncate 
truncate computed positions? Default is 
match.names 
logical 
fraction 
numeric 
x 
an object of class 
... 

drop.zero 
logical: should instruments with no difference
between Note the different defaults for computing and printing. 
current.weights 
logical. If 
target.weights 
logical. If 
weights 
a numeric vector with named components 
sep 
character 
prefix 
logical 
Details
The function computes the necessary trades to move from the
current
portfolio to a target
portfolio.
replace_weight
is a helper function to split
baskets into their components. All arguments passed
via ...
should be named vectors. If names are
not syntactically valid (see
make.names
), quote them. The passed
vectors themselves should be passed as named
arguments: see examples.
Value
An object of class rebalance
, which is a
data.frame
:
instrument 
character, or 
price 
prices 
current 
current portfolio 
target 
new portfolio 
difference 
the difference between current and target 
Attached to the data.frame are several attributes:
notional 
notional 
match.names 
logical 
multiplier 
multipliers 
Author(s)
Enrico Schumann
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/R/packages/PMwR/;
in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#rebalance
See Also
Examples
r < rebalance(current = c(a = 100, b = 20),
target = c(a = 0.2, c = 0.3),
price = c(a = 1, b = 2, c = 3))
as.journal(r)
## replace_weight: the passed vectors must be named;
## 'basket_3' is ignored because not
## component of weights is named
## 'basket_3'
replace_weight(c(basket_1 = 0.3,
basket_2 = 0.7),
basket_1 = c(a = 0.1, b = 0.4, c = .5),
basket_2 = c(x = 0.1, y = 0.4, z = .5),
basket_3 = c(X = 0.5, Z = 0.5),
sep = "")
Compute Returns
Description
Convert prices into returns.
Usage
returns(x, ...)
## Default S3 method:
returns(x, t = NULL, period = NULL, complete.first = TRUE,
pad = NULL, position = NULL,
weights = NULL, rebalance.when = NULL,
lag = 1, na.rm = TRUE, ...)
## S3 method for class 'zoo'
returns(x, period = NULL, complete.first = TRUE,
pad = NULL, position = NULL,
weights = NULL, rebalance.when = NULL, lag = 1, na.rm = TRUE, ...)
## S3 method for class 'p_returns'
print(x, ..., year.rows = TRUE, month.names = NULL,
zero.print = "0", plus = FALSE, digits = 1,
na.print = NULL)
## S3 method for class 'p_returns'
toLatex(object, ...,
year.rows = TRUE, ytd = "YTD", month.names = NULL,
eol = "\\\\", stand.alone = FALSE)
## S3 method for class 'p_returns'
toHTML(x, ...,
year.rows = TRUE, ytd = "YTD", month.names = NULL,
stand.alone = TRUE, table.style = NULL, table.class = NULL,
th.style = NULL, th.class = NULL,
td.style = "textalign:right; padding:0.5em;",
td.class = NULL, tr.style = NULL, tr.class = NULL,
browse = FALSE)
.returns(x, pad = NULL, lag)
Arguments
x 
for the default method, a For 
t 
timestamps. See arguments 
period 
Typically a string. Supported are
All returns are computed as simple returns. They
will only be annualised with option 
complete.first 
logical. For holdingperiod returns such an monthly or yearly, should the first period (if incomplete) be used. 
pad 
either 
na.rm 
logical; see Details 
position 
either a numeric vector of the same length as the
number of assets (i.e. 
weights 
either a numeric vector of the same length as the
number of assets (i.e. 
rebalance.when 
logical or numeric. If 
... 
further arguments to be passed to methods 
year.rows 
logical. If 
zero.print 
character. How to print zero values. 
na.print 
character. How to print 
plus 
logical. Add a ‘ 
lag 
The lag for computing returns. A positive integer,
defaults to one; ignored for timeweighted returns
or if 
object 
an object of class 
month.names 
character: names of months. Default is an
abbreviated month name as provided by the
locale. That may cause trouble, notably with

digits 
number of digits in table 
ytd 
header for YTD 
eol 
character 
stand.alone 
logical or character 
table.class 
character 
table.style 
character 
th.class 
character 
th.style 
character 
td.class 
character 
td.style 
character 
tr.class 
character 
tr.style 
character 
browse 
logical: open table in browser? 
Details
returns
is a generic function. It computes
simple returns: current values divided by prior
values minus one. The default method works for
numeric vectors/matrices. The function
.returns
does the actual computations and may
be used when a ‘raw’ return computation is
needed.
HoldingPeriod Returns
When a timestamp is available, returns
can
compute returns for specific calendar periods. See
argument period
.
Portfolio Returns
returns
may compute returns for a portfolio
specified in weights
or position
. The
portfolio is rebalanced at rebalance.when
; the
default is every period. Weights need not sum to
one. A zeroweight portfolio, or a portfolio that never
rebalances (e.g. with rebalance.when
set to
FALSE
), will result in a zero return.
rebalance.when
may either be logical,
integers or of the same class as a timestamp
(e.g. Date
).
Handling missing values
Removing missing values (i.e. setting na.rm
to
TRUE
) only has effects when period
is
specified.
Value
If called as returns(x)
: a numeric vector or
matrix, possibly with a class attribute (e.g. for a
zoo
series).
If called with a period
argument: an object of
class "p_returns"
(period returns), which is a
numeric vector of returns with attributes t
(timestamp) and period
. Main use is to have
methods that prettyprint such period returns; currently,
there are methods for toLatex
and
toHTML
.
In some cases, additional attributes may be attached:
when portfolio returns were computed (i.e. argument
weights
was specified), there are attributes
holdings
and contributions
. For
holdingperiod returns, there may be a logical attribute
is.annualised
, and an attribute from.to
,
which tells the start and end date of the holding period.
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/R/packages/PMwR/;
in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#computingreturns
See Also
Examples
x < 101:105
returns(x)
returns(x, pad = NA)
returns(x, pad = NA, lag = 2)
## monthly returns
t < seq(as.Date("20120615"), as.Date("20121231"), by = "1 day")
x < seq_along(t) + 1000
returns(x, t = t, period = "month")
returns(x, t = t, period = "month", complete.first = FALSE)
### formatting
print(returns(x, t = t, period = "month"), plus = TRUE, digits = 0)
## returns per year (annualised returns)
returns(x, t = t, period = "ann") ## less than one year, not annualised
returns(x, t = t, period = "ann!") ## less than one year, *but* annualised
is.ann < function(x)
attr(x, "is.annualised")
is.ann(returns(x, t = t, period = "ann")) ## FALSE
is.ann(returns(x, t = t, period = "ann!")) ## TRUE
## with weights and fixed rebalancing times
prices < cbind(p1 = 101:105,
p2 = rep(100, 5))
R < returns(prices, weights = c(0.5, 0.5), rebalance.when = 1)
## ... => resulting weights
h < attr(R, "holdings")
h*prices / rowSums(h*prices)
## p1 p2
## [1,] 0.5000000 0.5000000 ## <== only initial weights are .5/.5
## [2,] 0.5024631 0.4975369
## [3,] 0.5049020 0.4950980
## [4,] 0.5073171 0.4926829
## [5,] 0.5097087 0.4902913
REXP
Description
Historical Prices of the REXP.
Usage
data("REXP")
Format
A data frame with 502 observations on the following variable:
REXP
a numeric vector
Details
Daily prices.
Examples
str(REXP)
Scale Time Series
Description
Scale time series so that they can be better compared.
Usage
scale1(x, ...)
## Default S3 method:
scale1(x, ..., when = "first.complete", level = 1,
centre = FALSE, scale = FALSE, geometric = TRUE,
total.g = NULL)
## S3 method for class 'zoo'
scale1(x, ..., when = "first.complete", level = 1,
centre = FALSE, scale = FALSE, geometric = TRUE,
inflate = NULL, total.g = NULL)
Arguments
x 
a time series 
when 
origin: for the default method, either a string or
numeric (integer). Allowed strings are

level 
numeric 
centre 
logical 
scale 
logical or numeric 
geometric 
logical: if 
inflate 
numeric: an annual rate at which the series is inflated (or deflated if negative) 
total.g 
numeric: to total growth rate (or total return) of a series 
... 
other arguments passed to methods 
Details
This is a generic function, with methods for numeric
vectors and matrices, and zoo
objects.
Value
An object of the same type as x
.
Author(s)
Enrico Schumann
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/;
in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#scalingseries
See Also
Examples
scale1(cumprod(1 + c(0, rnorm(20, sd = 0.02))), level = 100)
Up and Down Streaks
Description
Compute up and down streaks for timeseries.
Usage
streaks(x, ...)
## Default S3 method:
streaks(x, up = 0.2, down = up,
initial.state = NA, y = NULL, relative = TRUE, ...)
## S3 method for class 'zoo'
streaks(x, up = 0.2, down = up,
initial.state = NA, y = NULL, relative = TRUE, ...)
## S3 method for class 'NAVseries'
streaks(x, up = 0.2, down = up,
initial.state = NA, bm = NULL, relative = TRUE, ...)
Arguments
x 
a price series 
initial.state 

up 
a number, such as 0.1 (i.e. 10%) 
down 
a negative number, such as 0.1 (i.e. 10%) 
y 
another price series 
bm 
another price series. Mapped to ‘ 
relative 
logical 
... 
other arguments passed to methods 
Details
streaks
is a generic function. It computes
series of uninterrupted up and down movements
(‘streaks’) in a price series. Uninterrupted
is meant in the sense that no countermovement of
down
(up
) percent or more occurs in up
(down) movements.
There are methods for numeric vectors, and
NAVseries
and zoo
objects.
The turning points (extreme points) are computed with the benefit of hindsight: the starting point (the low) of an up streak can only be determined once the streak is triggered, i.e. the up streak has already run its minimum amount. Vice versa for down streaks.
When ‘up
’ and ‘down
’ are
not equal, results may be inconsistent: in the
current implementation, streaks
alternates
between up and down streaks. Suppose up
is
large compared with down
, i.e. it takes long
to trigger up streaks, but they are easily
broken. Down streaks, on the other hand, are quickly
triggered but rarely broken. Now suppose that a down
streak is broken by an up streak: it may then well be
that the up streak would never have been counted as
such, because it was actually broken itself by
another down streak. The implementation for differing
values of ‘up
’ and ‘down
’
may change in the future.
Value
A data.frame
:
start 
beginning of streak 
end 
end of streak 
state 

return , change 
the return over the streak. If 
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2023) Portfolio Management with R.
http://enricoschumann.net/PMwR/; in particular, see
http://enricoschumann.net/R/packages/PMwR/manual/PMwR.html#drawdownsstreaks
See Also
Examples
streaks(DAX[[1]], t = as.Date(row.names(DAX)))
## results < streaks(x = <...>, y = <...>)
##
## ===> *arithmetic* excess returns
## x[results$end]/x[results$start] 
## y[results$end]/y[results$start]
## ===> *geometric* excess returns
## x[results$end]/x[results$start] /
## (y[results$end]/y[results$start])  1
Import from package textutils
Description
The toHTML
function is imported from package textutils.
Help is available at textutils::toHTML
.
Say library("textutils")
in your code to use the function.
Analysing Trades: Compute Profit/Loss, Resize and more
Description
Functions to help analyse trades (as opposed to profitandloss series)
Usage
scale_trades(amount, price, timestamp, aggregate = FALSE,
fun = NULL, ...)
split_trades(amount, price, timestamp, aggregate = FALSE,
drop.zero = FALSE)
limit(amount, price, timestamp, lim, tol = 1e8)
scale_to_unity(amount)
close_on_first(amount)
tw_exposure(amount, timestamp, start, end, abs.value = TRUE)
Arguments
amount 
notionals 
price 
a vector of prices 
timestamp 
a vector. 
aggregate 

fun 
a function 
lim 
a maximum absolute position size 
start 
optional time 
end 
optional time 
drop.zero 
logical. If 
abs.value 
logical. If 
... 
passed on to fun 
tol 
numeric 
Details
scale_trades
takes a vector of notionals, prices and
scales all trades along the paths so that the maximum
exposure is 1.
The default fun
divides every element of a vector
n
by max(abs(cumsum(n)))
. If userspecified,
the function fun
needs to take a vector of notionals
(changes in position.)
split_trades
decomposes a trade list into single
trades, where a single trade comprises those trades from a
zero position to the next zero position. Note that the
trades must be sorted chronologically.
Value
Either a list or a listoflists.
Author(s)
Enrico Schumann
See Also
Examples
n < c(1,1,3,1,2)
p < 100 + 1:length(n)
timestamp < 1:length(n)
scale_trades(n, p, timestamp)
scale_trades(n, p, timestamp, TRUE) ## each _trade_ gets scaled
split_trades(n, p, timestamp)
split_trades(n, p, timestamp, TRUE) ## almost like the original series
## effect of 'drop.zero'
P < c(100, 99, 104, 103, 102, 105, 104) ## price series
S < c( 0, 1, 1, 0, 0, 1, 0) ## position to be held
dS < c(0, diff(S)) ## change in position ==> trades
t < seq_along(P)
#### ==> 1) with all zero amounts
split_trades(amount = dS, price = P, timestamp = t)
#### ==> 2) without zeroamount trades
split_trades(amount = dS, price = P, timestamp = t, drop.zero = TRUE)
#### ==> 3) without all zeroamounts
zero < dS == 0
split_trades(amount = dS[!zero], price = P[!zero], timestamp = t[!zero])
Compute Prices for Portfolio Based on Units
Description
Compute prices for a portfolio based on outstanding shares.
Usage
unit_prices(NAV,
cashflows,
initial.price, initial.shares = 0,
cf.included = TRUE)
Arguments
NAV 
a dataframe of two columns: timestamp and net asset value 
cashflows 
a data.frame of two or three columns: timestamp, cashflow and (optionally) an id 
initial.price 
initial price 
initial.shares 
number of outstanding shares for first NAV 
cf.included 
logical 
Details
This function is experimental, and its interface is not stable yet.
The function may be used to compute the returns for a portfolio with external cashflows, i.e. what is usually called timeweighted returns.
Valuation (i.e. the computation of the NAV) must take place before external cashflows. Fairness suggests that: what price would you give an external investor if you had not valued the positions? And even if fairness mattered not: suppose we traded on a specific day, had a positive PL, and ended the day in cash. We could then not differentiate any more between a cash increase because of an external inflow and a cash increase because of a profitable trade.
Value
A data.frame
timestamp 
the timestamp 
NAV 
total NAV 
price 
NAV per share 
units 
outstanding units (i.e. shares) after cashflows 
Attached as an attribute is a data.frame
transactions
.
Author(s)
Enrico Schumann
References
Schumann, E. (2023) Portfolio Management with R. http://enricoschumann.net/PMwR/
See Also
Examples
NAV < data.frame(timestamp = seq(as.Date("20170101"),
as.Date("20170110"),
by = "1 day"),
NAV = c(100:104, 205:209))
cf < data.frame(timestamp = c(as.Date("20170101"),
as.Date("20170106")),
cashflow = c(100, 100))
unit_prices(NAV, cf, cf.included = TRUE)
## timestamp NAV price units
## 1 20170101 100 100.0000 1.000000
## 2 20170102 101 101.0000 1.000000
## 3 20170103 102 102.0000 1.000000
## 4 20170104 103 103.0000 1.000000
## 5 20170105 104 104.0000 1.000000
## 6 20170106 205 105.0000 1.952381
## 7 20170107 206 105.5122 1.952381
## 8 20170108 207 106.0244 1.952381
## 9 20170109 208 106.5366 1.952381
## 10 20170110 209 107.0488 1.952381
Valuation
Description
Valuation of financial objects: map an object into a quantity that is measured in a concrete (typically currency) unit.
Usage
valuation(x, ...)
## S3 method for class 'journal'
valuation(x, multiplier = 1,
cashflow = function(x, ...) x$amount * x$price,
instrument = function(x, ...) "cash",
flip.sign = TRUE, ...)
## S3 method for class 'position'
valuation(x, vprice, multiplier = 1,
do.sum = FALSE,
price.unit,
use.names = FALSE,
verbose = TRUE, do.warn = TRUE, ...)
Arguments
x 
an object 
multiplier 
a numeric vector, typically with named elements 
cashflow 
either a numeric vector or a function that takes on argument (a journal) and transforms it into a numeric vector 
instrument 
either a character vector or a function that takes on argument (a journal) and transforms it into a character vector 
flip.sign 
logical. If 
vprice 
numeric: a matrix whose elements
correspond to those in 
do.sum 
logical: sum over positions 
use.names 
logical: use names of 
price.unit 
a named character vector. Not implemented. 
verbose 
logical 
do.warn 
logical 
... 
other arguments passed to methods 
Details
This function is experimental, and the methods' interfaces are not stable yet.
valuation
is a generic function. Its
semantics suggest that an object (e.g. a financial
instrument or a position) is mapped into a concrete
quantity (such as an amount of some currency).
The journal
method transforms the
transactions in a journal into amounts of currency
(e.g, a sale of 100 shares of a company is
transformed into the value of these 100 shares).
The position
method takes a position
and returns the value (in currency units) of the
position.
Value
depends on the object: for journals, a journal
Author(s)
Enrico Schumann <es@enricoschumann.net>
References
Schumann, E. (2020) Portfolio Management with R. http://enricoschumann.net/R/packages/PMwR/
See Also
Examples
## valuing a JOURNAL
j < journal(amount = 10, price = 2)
## amount price
## 1 10 2
##
## 1 transaction
valuation(j, instrument = NA)
## amount price
## 1 20 1
##
## 1 transaction
## valuing a POSITION
pos < position(c(AMZN = 10, MSFT = 200))
### contructing a price table:
### ==> P[i, j] must correspond to pos[i, j]
P < array(c(2200, 170), dim = c(1, 2))
colnames(P) < instrument(pos)
valuation(pos, vprice = P)
## AMZN MSFT
## [1,] 22000 34000
### contructing a price table, alternative:
### a named vector
### ==> only works when there is only a single timestamp
valuation(pos, vprice = c(MSFT = 170, AMZN = 2200))
all.equal(valuation(pos, vprice = P),
valuation(pos, vprice = c(MSFT = 170, AMZN = 2200)))