[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