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.equal
compare contents of two journals
aggregate
Splits a journal according
to by
, applies a function to every
sub-journal and recombines the results into a
journal.
as.data.frame
coerces journal to
data.frame
c
Combine 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
).
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 sub-journal
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 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.