Journal
Create and manipulate a journal of financial transactions.
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")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 |
The journal function creates a list of the
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;
mostly used for creating a journal from a
data.frame.
journal methods are available for several
generic functions, for instance:
all.equalcompare contents of two journals
aggregateSplits a journal according
to by, applies a function to every
sub-journal and recombines the results into a
journal.
as.data.framecoerces journal to
data.frame
cCombine several journals into one.
Note that the first argument to c.journal
must inherit from journal, or else the
method dispatch will fail. For empty journals,
use journal() (not NULL).
lengthnumber of transactions in a
journal; it uses the length of amount.
splitSplits a journal according to
f, yielding a list of journals. Often used
interactively to have information per sub-journal
printed.
subsetevaluates 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.
summaryprovides summary statistics, such as number of trades and average buy/sell prices
toOrgconverts 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 zero-length (i.e. ‘empty’) journals, all
fields have length 0. A zero-length journal is created, of instance,
by saying journal() or when an zero-row data.frame is
passed to as.journal.
An object of class journal, which is a list of atomic
vectors.
Enrico Schumann <es@enricoschumann.net>
Schumann, E. (2019) Portfolio Management with R. http://enricoschumann.net/R/packages/PMwR/
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)Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.