[Blotter-commits] r716 - in pkg/FinancialInstrument: . R man

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Aug 7 21:56:28 CEST 2011


Author: gsee
Date: 2011-08-07 21:56:28 +0200 (Sun, 07 Aug 2011)
New Revision: 716

Added:
   pkg/FinancialInstrument/R/MonthCodes.R
   pkg/FinancialInstrument/R/parse_id.R
   pkg/FinancialInstrument/man/C2M.Rd
   pkg/FinancialInstrument/man/parse_id.Rd
   pkg/FinancialInstrument/man/parse_suffix.Rd
Modified:
   pkg/FinancialInstrument/DESCRIPTION
   pkg/FinancialInstrument/NAMESPACE
Log:
- add parse_id and parse_suffix functions
- add M2C and C2M functions that are used by parsing functions


Modified: pkg/FinancialInstrument/DESCRIPTION
===================================================================
--- pkg/FinancialInstrument/DESCRIPTION	2011-08-06 16:32:34 UTC (rev 715)
+++ pkg/FinancialInstrument/DESCRIPTION	2011-08-07 19:56:28 UTC (rev 716)
@@ -32,3 +32,5 @@
     'splooth.R'
     'synthetic.R'
     'volep.R'
+    'parse_id.R'
+    'MonthCodes.R'

Modified: pkg/FinancialInstrument/NAMESPACE
===================================================================
--- pkg/FinancialInstrument/NAMESPACE	2011-08-06 16:32:34 UTC (rev 715)
+++ pkg/FinancialInstrument/NAMESPACE	2011-08-07 19:56:28 UTC (rev 716)
@@ -6,6 +6,7 @@
 export(buildSpread)
 export(build_spread_symbols)
 export(butterfly)
+export(C2M)
 export(currency)
 export(exchange_rate)
 export(fn_SpreadBuilder)
@@ -22,9 +23,12 @@
 export(is.currency)
 export(is.instrument)
 export(load.instruments)
+export(M2C)
 export(option)
 export(option_series)
 export(option_series.yahoo)
+export(parse_id)
+export(parse_suffix)
 export(redenominate)
 export(setSymbolLookup.FI)
 export(spread)

Added: pkg/FinancialInstrument/R/MonthCodes.R
===================================================================
--- pkg/FinancialInstrument/R/MonthCodes.R	                        (rev 0)
+++ pkg/FinancialInstrument/R/MonthCodes.R	2011-08-07 19:56:28 UTC (rev 716)
@@ -0,0 +1,45 @@
+
+#' Month-to-Code and Code-to-Month
+#'
+#' Convert month code (used for futures contracts) 
+#' to abbreviated month name, or convert abbreviated month name to month code
+#' @aliases C2M M2C
+#' @param code Month code: F, G, H, J, K, M, N , Q, U, V, X, or Z
+#' @param month Abbreviated month: jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, or dec
+#' @return corresponding code or month.
+#' @author Garrett See
+#' @examples
+#' C2M()
+#' C2M("M")
+#' C2M()[6]
+#' M2C()
+#' M2C("Sep")
+#' M2C()[9]
+#' @export
+C2M <- function(code) {
+    if (missing(code)) c(F='Jan',G='Feb',H='Mar',
+                    J='Apr',K='May',M='Jun',
+                    N='Jul',Q='Aug',U='Sep',
+                    V='Oct',X='Nov',Z='Dec')    
+    else switch(toupper(code), F='Jan', G='Feb',H='Mar',
+                    J='Apr',K='May',M='Jun',
+                    N='Jul',Q='Aug',U='Sep',
+                    V='Oct',X='Nov',Z='Dec')
+}
+
+#' @export
+#' @rdname C2M
+M2C <- function(month) {
+    if (missing(month)) c(jan='F',feb='G',mar='H',
+                    apr='J',may='K',jun='M',
+                    jul='N',aug='Q',sep='U',
+                    oct='V',nov='X',dec='Z')
+    else switch(toupper(month), JAN=, JANUARY='F',
+                FEB=, FEBRUARY='G',MAR=, MARCH='H', 
+                APR=, APRIL='J', MAY='K', JUN=, JUNE='M',
+                JUL=, JULY='N', AUG=, AUGUST='Q',
+                SEP=, SEPTEMBER='U', OCT=, OCTOBER='V',
+                NOV=, NOVEMBER='X', DEC=, DECEMBER='Z')
+}
+
+

Added: pkg/FinancialInstrument/R/parse_id.R
===================================================================
--- pkg/FinancialInstrument/R/parse_id.R	                        (rev 0)
+++ pkg/FinancialInstrument/R/parse_id.R	2011-08-07 19:56:28 UTC (rev 716)
@@ -0,0 +1,256 @@
+#' Parse a primary_id
+#'
+#' Extract/infer descriptive information about an instrument from its name.
+#'
+#' This function is primarily intended to be used on the names of \code{\link{future_series}} 
+#' and \code{\link{option_series}} instruments, and it will work best if the id has an 
+#' underscore in it that separates the root_id from the suffix_id.  (However, it should be able 
+#' to handle most ids even if the underscore is missing). 
+#' After splitting \code{x} into a root_id and suffix_id, the suffix_id is 
+#' passed to \code{\link{parse_suffix}} (see also) for further processing.
+#' @param x the id to be parsed (e.g. \sQuote{ES_U11}, \sQuote{SPY_111217C130})
+#' @param silent silence warnings?
+#' @param root character name of instrument root_id.  Optionally provide this to make parsing easier.
+#' @return a list of class \sQuote{id.list} containing \sQuote{root} and \sQuote{suffix} as well as 
+#' what is returned from \code{\link{parse_suffix}} (type, month, year, strike, right, cm, cc)
+#' @author Garrett See
+#' @seealso \code{\link{parse_suffix}}
+#' @examples
+#' parse_id("ES_Z11")
+#' parse_id("CLZ1")
+#' parse_id("SPY_111217C130")
+#' @export
+parse_id <- function(x, silent=TRUE, root=NULL) {
+    if (!is.null(root)) {
+            suffix <- gsub(root,"",x) #turns ESU1 into U1, or ES_U11 into _U11 
+            suffix <- gsub("_","",x) #take out the underscore if there is one
+    } else if (identical(x, gsub('_','',x))) { #no underscore; have to guess what is root and what is suffix       
+        hasdot <- !identical(integer(0),grep("\\.",x))        
+        if (!silent) 
+            warning("id of future_series should have an underscore in it. Trying to parse anyway.")
+        if (nchar(x) <= 3) {
+            root <- substr(x, 1, nchar(x))
+            suffix <- ""
+        } else if (nchar(x) < 9 && !hasdot) { #assume it's a future like ESU1 or ESU11
+            root <- substr(x,1,2)
+            suffix <- substr(x,3,nchar(x))
+        } else if (identical(all.equal(nchar(x) - nchar( gsub("\\.","",x)),1), TRUE)) { 
+            #only 1 dot, so it's not a fly
+            #SPY.DIA, EUR.USD, SPY110917C122.5, T2010917P25
+            if (!is.na(as.numeric(strsplit(x,"\\.")[[1]][2]))) { #probably an option with a decimal in the strike
+                #if we take out all the numbers, periods, and dashes, 
+                #we should be left with the ticker and either "C" or "P"                
+                root <- gsub("[0-9.-]","",x) #now it looks like SPYC or TP
+                root <- substr(root, 1,nchar(root)-1)
+                suffix <- gsub(root,"",x) #whatever isn't the root
+            } else { #probably a synthetic: SPY.DIA, GLD.EUR
+                suffix <- x
+                root <- x
+            }
+        } else {
+            root <- gsub("[0-9.-]","",x) #now it looks like SPYC or TP
+            root <- substr(root, 1,nchar(root)-1)
+            suffix <- gsub(root,"",x) #whatever isn't the root         
+        }
+    } else { #there _is_ an underscore
+        root <- strsplit(x,"_")[[1]][1]
+        suffix <- strsplit(x,"_")[[1]][2]
+    }
+    suff <- parse_suffix(suffix, silent=silent)
+    structure(list(root=root, suffix=suffix, type=suff$type, month=suff$month, 
+                    year=suff$year, strike=suff$strike, right=suff$right, 
+                    cm=suff$cm, cc=suff$cc),class='id.list')
+}
+
+#' parse a suffix_id
+#' 
+#' extract information from the suffix_id of an instrument
+#'
+#' These would be recognized as a Sep 2011 outright futures contract: 
+#' U1, U11, SEP1, SEP11, U2011, Sep2011, SEP2011
+#' 
+#' These would be recognized as a call with a strike of 122.5 that expires Sep 17, 2011:
+#' 110917C122.5, 20110917C122.5
+#'
+#' These would be recognized as Sep 2011 single stock futures:
+#' 1CU1, 1CU11, 1CSEP11, 1DU1 (dividend protected)
+#'
+#' These would be recognized as Adjusted futures:
+#' cm.30 == 30 day constant maturity future
+#' cc.OI == continuous contract rolled when Open Interest rolls
+#' cc.Vol == continuous contract roll when Volumn rolls
+#' cc.Exp.1 == continuous contract rolled 1 day before Expiration
+#'
+#' Synthetics only return a value for the $type slot:
+#' U1.Z1 --> type == calendar, spread; 
+#' U11.Z11 --> type == calendar, spread; 
+#' SPY.DIA --> type == synthetic; 
+#' 110917C125.110917P125 --> type == option_spread, spread
+#' @param x the suffix_id to be parsed
+#' @param silent silence warnings? (warning will usually be about infering a 4 digit year from a 1 or 2 digit year)
+#' @return an object of class \sQuote{suffix.list} which is a list containing \sQuote{type} of instrument, 
+#' \sQuote{month} of expiration, \sQuote{year} of expiration, \sQuote{strike} price of option, 
+#' \sQuote{right} of option (\dQuote{C} or \dQuote{P}), \sQuote{cm} (maturity in days of a constant maturity contract),
+#' \sQuote{cc} (method for calculating a continuous contract).
+#' @author Garrett See
+#' @seealso \code{\link{parse_id}}
+#' @examples
+#' parse_suffix("U11")
+#' parse_suffix("110917C125")
+#' @export
+parse_suffix <- function(x, silent=TRUE) {
+#TODO better support for spreads and flies; inter and intra. 
+    type <- 'outright'
+    cm <- FALSE
+    cc <- FALSE
+    month <- 0
+    year <- 0
+    strike <- NA
+    right <- NA
+    if (x == "") {
+        type <- "root"
+    } else if (!identical(gsub("cm.","",x), x)) {
+    #A 30 day constant maturity synthetic futures contract 
+    #on the vix would look like VX_cm.30 
+        type <- c('outright', 'cm')
+        cm <- as.numeric(strsplit(x,"\\.")[[1]][2])
+    } else if (!identical(gsub("cc.","",x),x)) {
+    #cc.OI for rolling on Open Interest, 
+    #cc.Vol for rolling on Volume, 
+    #cc.Exp.1 for rolling 1 day before Expiration date.  (Exp.0 would be rolling on expiration)    
+        type <- c('outright', 'cc')
+        cc <- gsub('cc.','',x)
+    } else if (nchar(x) > 7 && (any(substr(x,7,7) == c("C","P")) || any(substr(x,9,9) == c("C","P"))) ) {
+        # if the 7th or 9th char is a "C" or "P", it's an option
+        # 110917C125 or 20110917C125
+        hasdot <- !identical(integer(0),grep("\\.",x))
+        if (!hasdot
+            || (hasdot 
+                && !is.na(as.numeric(strsplit(x,"\\.")[[1]][2])))) {
+                #&& nchar(strsplit(x,"\\.")[[1]][2]) <= 2)) {
+        #if it doesn't have a dot, or it does have dot, but what follows 
+        #the dot is numeric, then it's an option outright
+            if (any(substr(x,7,7) == c("C","P"))) {
+                type <- c("outright","option")
+                month <- toupper(month.abb[as.numeric(substr(x,3,4))])
+                year <- 2000 + as.numeric(substr(x,1,2))
+                strike <- as.numeric(substr(x,8,nchar(x)))
+                right <- substr(x,7,7)
+            } else if (any(substr(x,9,9) == c("C","P"))) {
+                type <- c("outright","option")
+                month <- toupper(month.abb[as.numeric(substr(x,5,6))])
+                year <- as.numeric(substr(x,1,4))
+                strike <- as.numeric(substr(x,10,nchar(x)))
+                right <- substr(x,9,9)
+            } else stop("how did you get here?")
+        } else type <- c("option_spread","spread")
+    } else if (!identical(gsub("\\.","",x),x)) { #has a dot. U1.Z1, U11.Z11, SPY.DIA, 
+        if (identical(all.equal(nchar(x) - nchar( gsub("\\.","",x)),1), TRUE)) { #only 1 dot, so it's not a fly
+            #U1.Z1, U11.Z11, SPY.DIA, EUR.USD
+            s <- strsplit(x,"\\.")[[1]]
+            s1 <- try(parse_suffix(s[1],silent=TRUE),silent=TRUE)
+            s2 <- try(parse_suffix(s[2],silent=TRUE),silent=TRUE)
+            if (inherits(s1,'try-error')) {
+                s1 <- parse_id(s[1],silent=TRUE)
+            }
+            if (inherits(s2,'try-error')) {
+                s2 <- parse_id(s[2],silent=TRUE)
+            }
+            #if (s1$
+            if (all(c(s1$type,s2$type) == 'root')) {
+                type='synthetic'
+            } else { 
+                type=c('calendar','spread')
+            }
+        }
+    ##End check for suffixes with a dot
+    } else if (any(substr(x,1,2) == c("1C","1D"))) { # Single-stock future (SSF) 
+        #1CU1, 1CU11, 1CSEP11 -- 1DU1 for dividend protected
+        if (substr(x,1,2) == "1C") {
+            type <- c('outright', 'SSF')
+        } else if (substr(x,1,2) == "1D") {
+            type <- c('outright', 'SSF', 'NoDivRisk')
+        }
+        suff <- parse_suffix(substr(x,3,nchar(x)),silent=silent)
+        month <- suff$month
+        year <- suff$year
+    } else if (nchar(x) == 2) { #U1
+        if (substr(x,1,1) %in% M2C() && !is.na(as.numeric(substr(x,2,2)))) {
+            type <- c("outright","future")
+            month <- toupper(C2M(substr(x,1,1)))
+            year <- as.numeric(substr(x,2,2)) + 2010
+            if (!silent)
+                warning("Converting 1 digit year to 4 digit year assumes there are no futures before 2010")
+        } else if (is.na(as.numeric(x))) type <- 'root'
+    } else if (nchar(x) == 3) { #U11
+        if (substr(x,1,1) %in% M2C() && !is.na(as.numeric(substr(x,2,3)))) {
+            type <- c("outright","future")
+            month <- toupper(C2M(substr(x,1,1)))
+            year <- as.numeric(substr(x,2,3)) + 2000
+            if (year > 2040) year <- year - 100
+            if (!silent)
+                warning('Converting 2 digit year to 4 digit year will result in a year between 1941 and 2040')
+        } else type <- 'root'
+    } else if (nchar(x) == 4) { #SEP1, VXU1, 0911
+        if (toupper(substr(x, 1, 3)) %in% toupper(C2M()) && !is.na(as.numeric(substr(x,4,4)))) { 
+            #sep1, Sep1, SEP1
+            suff <- paste(M2C(tolower(substr(x,1,3))), substr(x,4,4), sep="") #convert from Sep1 to U1
+            return(parse_suffix(suff,silent=silent)) #call recursively with 2 character suffix
+        } else if (substr(x,3,3) %in% M2C() && !is.na(as.numeric(substr(x,4,4)))) {
+            n <- suppressWarnings(as.numeric(substr(x,1,1)))
+            if (is.na(n) || n != 1) { #first char will be 1 if it's a single stock future
+                #xxU1, VXU1 #ignore the 1st 2 characters, and 
+                #call recursively with nchar==2 suffix
+                return(parse_suffix(substr(x,3,4),silent=silent)) 
+            }
+            #Single Stock Futures, SPY_1CU1, SPY_1DU1 (1DU1 is the OCX.NoDivRisk)
+            if (substr(x,1,2) == "1C" ) {  #1CU1
+                type <- c('outright', 'SSF')
+            } else if (substr(x,1,2) == "1D") {  #1DU1
+               type <- c('outright', 'SSF', 'NoDivRisk')
+            } else { #shouldn't ever get here...it would have to be something like 11U1
+                stop("unknown 4 char suffix that begins with 1")
+            }
+            suff <- parse_suffix(substr(x,3,4), silent=silent)
+            month <- suff$month
+            year <- suff$year         
+        } else if (!is.na(as.numeric(x))) { 
+            #0911
+            #convert to U11 and call recursively
+            suff <- paste(M2C()[as.numeric(substr(x,1,2))], substr(x, 3,4), sep="")
+            return(parse_suffix(suff,silent=silent)) 
+        } else {
+            if (!silent)
+                warning("Could not parse 4 character suffix")
+            return(NULL)
+        }
+
+    } else if (nchar(x) == 5) { #SEP11, U2011
+        type <- c("outright","future")
+        if (toupper(substr(x,1,3)) %in% toupper(C2M()) && !is.na(as.numeric(substr(x,4,5)))) {
+            #SEP11        
+            month <- toupper(substr(x,1,3))
+            year <- as.numeric(substr(x,4,5)) + 2000
+            if (!silent) warning('Converting 2 digit year to 4 digit year assumes there are no futures before 2000')
+       } else if (!is.na(as.numeric(substr(x,2,5))) && (substr(x,1,1) %in% M2C()) ) {
+            #U2011
+            month <- toupper(C2M(substr(x,1,1)))
+            year <- as.numeric(substr(x,2,5))
+       }
+    } else if (nchar(x) == 6) {
+        #201109, 092011, 091611
+        if (!silent)
+            warning("I'm not programmed to handle a 6 character suffix")
+        return(NULL)
+            
+    } else if (nchar(x) == 7) {
+        #Sep2011
+        if (toupper(substr(x, 1, 3)) %in% toupper(C2M()) && !is.na(as.numeric(substr(x,4,7))) ) {
+            type <- c("outright","future")
+            month <- toupper(substr(x,1,3))
+            year <- as.numeric(substr(x, 4,7))
+        }    
+    } 
+    structure(list(type=type, month=month,year=year, strike=strike, right=right, cm=cm, cc=cc), class='suffix.list')
+}
+


Property changes on: pkg/FinancialInstrument/R/parse_id.R
___________________________________________________________________
Added: svn:executable
   + *

Added: pkg/FinancialInstrument/man/C2M.Rd
===================================================================
--- pkg/FinancialInstrument/man/C2M.Rd	                        (rev 0)
+++ pkg/FinancialInstrument/man/C2M.Rd	2011-08-07 19:56:28 UTC (rev 716)
@@ -0,0 +1,36 @@
+\name{C2M}
+\alias{C2M}
+\alias{M2C}
+\title{Month-to-Code and Code-to-Month}
+\usage{
+  C2M(code)
+
+  M2C(month)
+}
+\arguments{
+  \item{code}{Month code: F, G, H, J, K, M, N , Q, U, V, X,
+  or Z}
+
+  \item{month}{Abbreviated month: jan, feb, mar, apr, may,
+  jun, jul, aug, sep, oct, nov, or dec}
+}
+\value{
+  corresponding code or month.
+}
+\description{
+  Convert month code (used for futures contracts) to
+  abbreviated month name, or convert abbreviated month name
+  to month code
+}
+\examples{
+C2M()
+C2M("M")
+C2M()[6]
+M2C()
+M2C("Sep")
+M2C()[9]
+}
+\author{
+  Garrett See
+}
+

Added: pkg/FinancialInstrument/man/parse_id.Rd
===================================================================
--- pkg/FinancialInstrument/man/parse_id.Rd	                        (rev 0)
+++ pkg/FinancialInstrument/man/parse_id.Rd	2011-08-07 19:56:28 UTC (rev 716)
@@ -0,0 +1,48 @@
+\name{parse_id}
+\alias{parse_id}
+\title{Parse a primary_id}
+\usage{
+  parse_id(x, silent = TRUE, root = NULL)
+}
+\arguments{
+  \item{x}{the id to be parsed (e.g. \sQuote{ES_U11},
+  \sQuote{SPY_111217C130})}
+
+  \item{silent}{silence warnings?}
+
+  \item{root}{character name of instrument root_id.
+  Optionally provide this to make parsing easier.}
+}
+\value{
+  a list of class \sQuote{id.list} containing \sQuote{root}
+  and \sQuote{suffix} as well as what is returned from
+  \code{\link{parse_suffix}} (type, month, year, strike,
+  right, cm, cc)
+}
+\description{
+  Extract/infer descriptive information about an instrument
+  from its name.
+}
+\details{
+  This function is primarily intended to be used on the
+  names of \code{\link{future_series}} and
+  \code{\link{option_series}} instruments, and it will work
+  best if the id has an underscore in it that separates the
+  root_id from the suffix_id.  (However, it should be able
+  to handle most ids even if the underscore is missing).
+  After splitting \code{x} into a root_id and suffix_id,
+  the suffix_id is passed to \code{\link{parse_suffix}}
+  (see also) for further processing.
+}
+\examples{
+parse_id("ES_Z11")
+parse_id("CLZ1")
+parse_id("SPY_111217C130")
+}
+\author{
+  Garrett See
+}
+\seealso{
+  \code{\link{parse_suffix}}
+}
+

Added: pkg/FinancialInstrument/man/parse_suffix.Rd
===================================================================
--- pkg/FinancialInstrument/man/parse_suffix.Rd	                        (rev 0)
+++ pkg/FinancialInstrument/man/parse_suffix.Rd	2011-08-07 19:56:28 UTC (rev 716)
@@ -0,0 +1,57 @@
+\name{parse_suffix}
+\alias{parse_suffix}
+\title{parse a suffix_id}
+\usage{
+  parse_suffix(x, silent = TRUE)
+}
+\arguments{
+  \item{x}{the suffix_id to be parsed}
+
+  \item{silent}{silence warnings? (warning will usually be
+  about infering a 4 digit year from a 1 or 2 digit year)}
+}
+\value{
+  an object of class \sQuote{suffix.list} which is a list
+  containing \sQuote{type} of instrument, \sQuote{month} of
+  expiration, \sQuote{year} of expiration, \sQuote{strike}
+  price of option, \sQuote{right} of option (\dQuote{C} or
+  \dQuote{P}), \sQuote{cm} (maturity in days of a constant
+  maturity contract), \sQuote{cc} (method for calculating a
+  continuous contract).
+}
+\description{
+  extract information from the suffix_id of an instrument
+}
+\details{
+  These would be recognized as a Sep 2011 outright futures
+  contract: U1, U11, SEP1, SEP11, U2011, Sep2011, SEP2011
+
+  These would be recognized as a call with a strike of
+  122.5 that expires Sep 17, 2011: 110917C122.5,
+  20110917C122.5
+
+  These would be recognized as Sep 2011 single stock
+  futures: 1CU1, 1CU11, 1CSEP11, 1DU1 (dividend protected)
+
+  These would be recognized as Adjusted futures: cm.30 ==
+  30 day constant maturity future cc.OI == continuous
+  contract rolled when Open Interest rolls cc.Vol ==
+  continuous contract roll when Volumn rolls cc.Exp.1 ==
+  continuous contract rolled 1 day before Expiration
+
+  Synthetics only return a value for the $type slot: U1.Z1
+  --> type == calendar, spread; U11.Z11 --> type ==
+  calendar, spread; SPY.DIA --> type == synthetic;
+  110917C125.110917P125 --> type == option_spread, spread
+}
+\examples{
+parse_suffix("U11")
+parse_suffix("110917C125")
+}
+\author{
+  Garrett See
+}
+\seealso{
+  \code{\link{parse_id}}
+}
+



More information about the Blotter-commits mailing list