[Blotter-commits] r456 - in pkg/FinancialInstrument: . R man
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Nov 17 21:27:57 CET 2010
Author: braverock
Date: 2010-11-17 21:27:53 +0100 (Wed, 17 Nov 2010)
New Revision: 456
Added:
pkg/FinancialInstrument/R/load.instruments.R
pkg/FinancialInstrument/man/load.instruments.Rd
Modified:
pkg/FinancialInstrument/NAMESPACE
pkg/FinancialInstrument/R/instrument.R
pkg/FinancialInstrument/man/instrument.Rd
pkg/FinancialInstrument/man/is.instrument.Rd
Log:
- add load.instruments function
- add additional custom fields handling in constructor
- add identifier recognition, better getInstrument search
- update roxygen docs
Modified: pkg/FinancialInstrument/NAMESPACE
===================================================================
--- pkg/FinancialInstrument/NAMESPACE 2010-11-17 03:24:29 UTC (rev 455)
+++ pkg/FinancialInstrument/NAMESPACE 2010-11-17 20:27:53 UTC (rev 456)
@@ -10,6 +10,7 @@
export(is.currency)
export(exchange_rate)
export(getInstrument)
+export(load.instruments)
export(synthetic)
export(synthetic.ratio)
export(spread)
Modified: pkg/FinancialInstrument/R/instrument.R
===================================================================
--- pkg/FinancialInstrument/R/instrument.R 2010-11-17 03:24:29 UTC (rev 455)
+++ pkg/FinancialInstrument/R/instrument.R 2010-11-17 20:27:53 UTC (rev 456)
@@ -17,7 +17,7 @@
}
#' class test for object supposedly of type 'instrument'
-#' @param x object to test for type
+#' @param x object or primary_id of instrument to test for type
#' @export
is.instrument <- function( x ) {
inherits( x, "instrument" )
@@ -27,15 +27,22 @@
#'
#' All 'currency' instruments must be defined before instruments of other types may be defined.
#'
-#' In \dots you may pass any other arbitrary instrument fields.
+#' In \dots you may pass any other arbitrary instrument fields that will be used to create 'custom' fields.
#' S3 classes in \R are basically lists with a class attribute.
#' We use this to our advantage to allow us to set arbitrary fields.
#'
#' \code{identifiers} should be a named list to specify other identifiers beyond the \code{primary_id}.
-#' Please note that whenever possible, these should still be unique. Perhaps Bloomberg, Reuters-RIC, CUSIP, etc.
+#' Please note that whenever possible, these should still be unique. Perhaps Bloomberg, Reuters-X.RIC, CUSIP, etc.
#' The code will return the first (and only the first) match that it finds, starting with the primary_id, and then searching all instruments in the list alphabetically by primary_id.
#' This is robust enough if you take some care, though a more robust patch would be welcomed.
#'
+#' The \code{primary_id} will be coerced within reason to a valid \R variable name by
+#' replacing +-=^\%$#@:; with _ .
+#'
+#' Identifiers will also try to be discovered as regular named arguments passed in via \code{...}.
+#' We currently match any of the following: \code{"CUSIP","SEDOL","ISIN","OSI","Bloomberg","Reuters","X.RIC","CQG","TT","Yahoo","Google"}
+#' Others mat be specified using a named list of identifiers, as described above.
+#'
#' @param primary_id string describing the unique ID for the instrument
#' @param ... any other passthru parameters
#' @param currency string describing the currency ID of an object of type \code{\link{currency}}
@@ -55,16 +62,33 @@
#' \code{\link{exchange_rate}}
#' \code{\link{option_series}}
#' \code{\link{future_series}}
+#' \code{\link{load.instruments}}
#' @export
instrument<-function(primary_id , ..., currency , multiplier , tick_size=NULL, identifiers = NULL, type=NULL ){
if(is.null(primary_id)) stop("you must specify a primary_id for the instrument")
-
- # not sure this is correct, maybe should store the primary_id for the currency instead. Why doesn't R have pointers?
+
+ primary_id<-gsub("[+-=^%$#@:;]","_",primary_id) # replace illegal characters
+
if(!is.currency(currency)) stop("currency must be an object of type 'currency'")
- if(!hasArg(identifiers)) identifiers = list()
-
- ## note that multiplier could be a time series, probably add code here to check
+ if(!hasArg(identifiers) || is.null(identifiers)) identifiers = list()
+ if(!is.list(identifiers)) {
+ warning("identifiers",identifiers,"do not appear to be a named list")
+ } else {
+ arg<-list(...)
+ #check for identifiers we recognize
+ ident_str<-c("X.RIC","CUSIP","SEDOL","OSI","Bloomberg","Reuters","ISIN","CQG","TT","Yahoo","Google")
+ for(i_s in ident_str ){
+ if(any(grepl(i_s,names(arg),ignore.case=TRUE))) {
+ pos<-first(grep(i_s,names(arg),ignore.case=TRUE))
+ identifiers<-c(identifiers,arg[[pos]])
+ names(identifiers)[length(identifiers)]<-names(arg)[pos]
+ arg[[pos]]<-NULL
+ }
+ }
+ }
+
+ ## TODO note that multiplier could be a time series, probably add code here to check
if(!is.numeric(multiplier) | length(multiplier) > 1) stop("multiplier must be a single number")
if(!is.numeric(tick_size) | length(tick_size) > 1) stop("tick_size must be a single number")
@@ -77,8 +101,7 @@
tick_size=tick_size,
identifiers = identifiers
)
-
- tmpinstr <- c(tmpinstr,list(...))
+ if(length(arg)>=1) tmpinstr <- c(tmpinstr,arg)
class(tmpinstr)<-tclass
return(tmpinstr)
}
@@ -120,8 +143,8 @@
# TODO add check for Date equivalent in first_traded and expires
## with futures series we probably need to be more sophisticated,
- ## and find the existing series from prior periods (probably years)
- ## and then add the first_traded and expires to the time series
+ ## and find the existing series from prior periods (probably years or months)
+ ## and then add the first_traded and expires to the time series bu splicing
temp_series<-try(getInstrument(paste(primary_id, suffix_id,sep="_")),silent=TRUE)
if(inherits(temp_series,"future_series")) {
message("updating existing first_traded and expires")
@@ -224,12 +247,11 @@
if(!exists(second_currency, where=.instrument,inherits=TRUE)) warning("second_currency not found") # assumes that we know where to look
## now structure and return
- exrate_temp= instrument(primary_id=primary_id , currency=primary_id , multiplier=1 , tick_size=.01, identifiers = identifiers, ..., secon_currency=second_currency, type=c("exchange_rate","currency"))
+ exrate_temp= instrument(primary_id=primary_id , currency=currency , multiplier=1 , tick_size=.01, identifiers = identifiers, ..., secon_currency=second_currency, type=c("exchange_rate","currency"))
assign(primary_id, exrate_temp, envir=as.environment(.instrument) )
}
-#@TODO: government bond
-#@TODO auction dates, coupons, etc for govmt. bonds
+#TODO auction dates, coupons, etc for govmt. bonds
bond <- function(primary_id , currency , multiplier, tick_size=NULL , identifiers = NULL, ...){
bond_temp = instrument(primary_id=primary_id , currency=currency , multiplier=multiplier , tick_size=tick_size, identifiers = identifiers, ..., type="bond" )
assign( primary_id, bond_temp, envir=as.environment(.instrument) )
Added: pkg/FinancialInstrument/R/load.instruments.R
===================================================================
--- pkg/FinancialInstrument/R/load.instruments.R (rev 0)
+++ pkg/FinancialInstrument/R/load.instruments.R 2010-11-17 20:27:53 UTC (rev 456)
@@ -0,0 +1,82 @@
+###############################################################################
+# R (http://r-project.org/) Instrument Class Model
+#
+# Copyright (c) 2009-2010
+# Peter Carl, Dirk Eddelbuettel, Jeffrey Ryan, Joshua Ulrich and Brian G. Peterson
+#
+# This library is distributed under the terms of the GNU Public License (GPL)
+# for full details see the file COPYING
+#
+# $Id$
+#
+###############################################################################
+
+
+#' load instrument metadata into the .instrument environment
+#'
+#' This function will load instrument metadata (data about the data)
+#' either from a file specified by the \code{file} argument or
+#' from a \code{data.frame} specified by the \code{metadata} argument.
+#'
+#' The function will attempt to make reasonable assumptions about what you're trying to do, but this isn't magic.
+#'
+#' You will typically need to specify the \code{type} of instrument to be loaded, failure to do so will generate a Warning and \code{default_type} will be used.
+#'
+#' You will need to specify a \code{primary_id}, or define a \code{id_col} that contains the data to be used as the primary_id of the instrument.
+#'
+#' You will need to specify a \code{currency}, unless the instrument \code{type} is 'currency'
+#'
+#' Typically, columns will exist for \code{multiplier} and \code{tick_size}.
+#'
+#' Any other columns necessary to define the specified instrument type will also be required to avoid Errors.
+#'
+#' Additional columns will be processed, either as additional identifiers for recognized identifier names, or as custom feilds. See \code{\link{instrument}} for more information on custom fields.
+#'
+#' @param file string identifying file to load, default NULL, see Details
+#' @param ... any other passthru parameters
+#' @param metadata optional, data.frame containing metadata, default NULL, see Details
+#' @param id_col numeric column containing id if primary_id isn't defined, default 1
+#' @param default_type character string to use as instrument type fallback, see Details
+#' @seealso instrument
+#' @export
+load.instruments <- function (file=NULL, ..., metadata=NULL, id_col=1, default_type='stock') {
+
+ if(is.null(file) && is.null(metadata)) stop("You must pass either a file identifier string or a metadata object to be converted.")
+ if(is.null(metadata)){
+ if (file.exists(file)){
+ filedata<-read.csv(file,stringsAsFactors=FALSE)
+ } else {
+ stop("The specified file",file,"does not seem to exist, maybe specify the full path?")
+ }
+ } else {
+ filedata<-metadata
+ rm(metadata)
+ }
+
+ # check required column headers
+ if(!any(grepl('primary_id',colnames(filedata)))) {
+ #no primary_id column name, use id_col as the name
+ set_primary<-TRUE
+ } else {
+ set_primary<-FALSE
+ }
+ if(!any(grepl('type',colnames(filedata)))) {
+ warning("metadata does not appear to contain instrument type, using",default_type,". This may produce incorrect valuations.")
+ filedata$type<-rep(default_type,nrow(filedata))
+ }
+
+ #now process the data
+ for(rn in 1:nrow(filedata)){
+ if(!isTRUE(is.instrument(getInstrument(as.character(filedata[rn,id_col]))))){
+ arg<-as.list(filedata[rn,])
+ arg$type<-NULL
+ arg<-arg[!is.na(arg)]
+ arg<-arg[!arg==""]
+ if (set_primary) arg$primary_id<-filedata[rn,id_col]
+ try(do.call(as.character(filedata[rn,'type']),arg))
+ } else {
+ warning(filedata[rn,id_col],"already exists in the .instrument environment")
+ }
+ }
+
+}
Property changes on: pkg/FinancialInstrument/R/load.instruments.R
___________________________________________________________________
Added: svn:keywords
+ Revision Id Date Author
Modified: pkg/FinancialInstrument/man/instrument.Rd
===================================================================
--- pkg/FinancialInstrument/man/instrument.Rd 2010-11-17 03:24:29 UTC (rev 455)
+++ pkg/FinancialInstrument/man/instrument.Rd 2010-11-17 20:27:53 UTC (rev 456)
@@ -5,14 +5,17 @@
\description{instrument class constructors}
\details{All 'currency' instruments must be defined before instruments of other types may be defined.
-In \dots you may pass any other arbitrary instrument fields.
+In \dots you may pass any other arbitrary instrument fields that will be used to create 'custom' fields.
S3 classes in \R are basically lists with a class attribute.
We use this to our advantage to allow us to set arbitrary fields.
\code{identifiers} should be a named list to specify other identifiers beyond the \code{primary_id}.
-Please note that whenever possible, these should still be unique. Perhaps Bloomberg, Reuters-RIC, CUSIP, etc.
+Please note that whenever possible, these should still be unique. Perhaps Bloomberg, Reuters-X.RIC, CUSIP, etc.
The code will return the first (and only the first) match that it finds, starting with the primary_id, and then searching all instruments in the list alphabetically by primary_id.
-This is robust enough if you take some care, though a more robust patch would be welcomed.}
+This is robust enough if you take some care, though a more robust patch would be welcomed.
+
+The \code{primary_id} will be coerced within reason to a valid \R variable name by
+replacing +-=^\%$#}
\alias{stock}
\alias{bond}
\alias{future}
@@ -21,7 +24,8 @@
\alias{instrument}
\seealso{\code{\link{exchange_rate}}
\code{\link{option_series}}
-\code{\link{future_series}}}
+\code{\link{future_series}}
+\code{\link{load.instruments}}}
\arguments{\item{primary_id}{string describing the unique ID for the instrument}
\item{...}{any other passthru parameters}
\item{currency}{string describing the currency ID of an object of type \code{\link{currency}}}
Modified: pkg/FinancialInstrument/man/is.instrument.Rd
===================================================================
--- pkg/FinancialInstrument/man/is.instrument.Rd 2010-11-17 03:24:29 UTC (rev 455)
+++ pkg/FinancialInstrument/man/is.instrument.Rd 2010-11-17 20:27:53 UTC (rev 456)
@@ -3,4 +3,4 @@
\title{class test for object supposedly of type 'instrument'...}
\usage{is.instrument(x)}
\description{class test for object supposedly of type 'instrument'}
-\arguments{\item{x}{object to test for type}}
+\arguments{\item{x}{object or primary_id of instrument to test for type}}
Added: pkg/FinancialInstrument/man/load.instruments.Rd
===================================================================
--- pkg/FinancialInstrument/man/load.instruments.Rd (rev 0)
+++ pkg/FinancialInstrument/man/load.instruments.Rd 2010-11-17 20:27:53 UTC (rev 456)
@@ -0,0 +1,28 @@
+\name{load.instruments}
+\alias{load.instruments}
+\title{load instrument metadata into the...}
+\usage{load.instruments(file, ..., metadata, id_col=1, default_type="stock")}
+\description{load instrument metadata into the .instrument environment}
+\details{This function will load instrument metadata (data about the data)
+either from a file specified by the \code{file} argument or
+from a \code{data.frame} specified by the \code{metadata} argument.
+
+The function will attempt to make reasonable assumptions about what you're trying to do, but this isn't magic.
+
+You will typically need to specify the \code{type} of instrument to be loaded, failure to do so will generate a Warning and \code{default_type} will be used.
+
+You will need to specify a \code{primary_id}, or define a \code{id_col} that contains the data to be used as the primary_id of the instrument.
+
+You will need to specify a \code{currency}, unless the instrument \code{type} is 'currency'
+
+Typically, columns will exist for \code{multiplier} and \code{tick_size}.
+
+Any other columns necessary to define the specified instrument type will also be required to avoid Errors.
+
+Additional columns will be processed, either as additional identifiers for recognized identifier names, or as custom feilds. See \code{\link{instrument}} for more information on custom fields.}
+\seealso{instrument}
+\arguments{\item{file}{string identifying file to load, default NULL, see Details}
+\item{...}{any other passthru parameters}
+\item{metadata}{optional, data.frame containing metadata, default NULL, see Details}
+\item{id_col}{numeric column containing id if primary_id isn't defined, default 1}
+\item{default_type}{character string to use as instrument type fallback, see Details}}
More information about the Blotter-commits
mailing list