FinancialInstrument Moves to CRAN

[This article was first published on tradeblotter » R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

I thought I would break up the posts about GSOC (no, I’m not done yet – there are a few more to do) with a quick note about FinancialInstrument.

The FinancialInstrument package provides a construct for defining and storing meta-data for tradable contracts (referred to as instruments, e.g., stocks, futures, options, etc.). The package can be used to create any asset class and derivatives, so it is required for packages like blotter and quantstrat.

FinancialInstrument was originally conceived as blotter was being written. Blotter provides portfolio accounting functionality, accumulating transactions into positions, then into portfolios and an account. Blotter, of course, needs to know something about the instrument being traded.

FinancialInstrument is used to hold the meta-data about an instrument that blotter uses to calculate the notional value of positions and the resulting P&L. FinancialInstrument, however, has plenty of utility beyond portfolio accounting, such as pre-trade pricing, risk management, etc., and was carved out so that others might take advantage of its functionality. Brian Peterson did the heavy lifting there, constructing FinancialInstrument as a meta-data container based on a data design we developed for a portfolio management system years ago.

Utility packages like this are generally thankless work, although incredibly useful and powerful for (potentialy several) end applications. They quietly do a bunch of heavy lifting that allows the user interface to be simpler, more powerful and more flexible than they otherwise might be, and allow the developer to focus on the specific application rather than re-inventing already-existing but trapped functionality.

Thankfully, Garrett See has found both the time and motivation to take what was a useful but unfinished package and help Brian carry it across the finish line into CRAN. Garrett also added a great deal of functionality around managing the .instrument namespace, such as ls_instruments() and many other ls_* and rm_* functions. Those ls_* functions get names of instruments of a particular type or denominated in a given currency (or currencies), while rm_* functions remove instruments. Similarly, a series of update_* functions help update instruments from various sources, such as Yahoo!.

At this point, FinancialInstrument has a lot of functionality. Let’s take a closer look…

A simple example of an instrument is a common stock. An instrument can be defined in brief terms with an identifier (e.g., “IBM”). Beyond the primary identifier, additional identifiers may be added as well and will work as ‘aliases’. Any identifier will do – Bloomberg, Reuters-RIC, CUSIP, etc. – as long as it’s unique to the workspace. In addition, a stock price will be denominated in a currency (e.g., “USD”) and will have a specific tick size which is the minimum amount that the price can be quoted and transacted in (e.g., $0.01). We also define a ‘multiplier’ that is used when calculating the notional value of a position or transaction using a quantity and price (sometimes called a contract multiplier). For a stock it’s usually ’1′. For example:

> require("FinancialInstrument")
> currency(c("USD", "EUR")) # define some currencies
[1] "USD" "EUR"
> stock(c("SPY", "LQD", "IBM", "GS"), currency="USD") # define some stocks
[1] "SPY" "LQD" "IBM" "GS" 
> exchange_rate("EURUSD") # define an exchange rate
[1] "EURUSD"
> ls_stocks() #get the names of all the stocks, including some I had previously defined
 [1] "DBC" "GLD" "GM"  "GS"  "IBM" "IEF" "LQD" "SPY" "VEU" "VNQ" "VTI" "XLB" "XLE" "XLF"
[15] "XLI" "XLK" "XLP" "XLU" "XLV" "XLY" "XOM"
> ls_instruments() # all instruments
 [1] "DBC"    "EUR"    "EURUSD" "GLD"    "GM"     "GS"     "IBM"    "IEF"    "LQD"   
[10] "SPY"    "USD"    "VEU"    "VNQ"    "VTI"    "XLB"    "XLE"    "XLF"    "XLI"   
[19] "XLK"    "XLP"    "XLU"    "XLV"    "XLY"    "XOM"   

Now we’ve defined some instruments. Say we have an application in which we want to value a position in IBM stock or want to know something else about the symbol “IBM”. Much like getSymbols, we:

> getInstrument("IBM")
primary_id :"IBM"
currency   :"USD"
multiplier :1
tick_size  :0.01
identifiers: list()
type       :"stock"

… and we get back a list of attributes. For my P&L example, I would want to know the multiplier and the currency the instrument is denominated in. If I know those two things, I can have a multi-currency, multi-instrument portfolio that includes derivatives. If I defined “sector” and “country” I can then partition the portfolio along those lines for attribution.

More care is needed when dealing with complex instruments, like futures. First, we have to define a future as a root contract. This root is not tradable unto itself, but is used to generate a series of futures which are tradable and expire through time. The root contract will provide an identifier (e.g., ‘C’ for the CME’s corn contract), a denomination currency, a multiplier (one futures contract will cover multiple items) and a minimum tick size. From that definition, a series of expiring contracts can be generated (“C_H08″, “C_Z08″, etc.) by specifying a suffix to be associated with the series, usually something like ‘Z9′ or ‘Mar10′ denoting expiration and year.

> ## before defining a derivative, must define the root (can define the underlying
> ## in the same step)
> future("ES", "USD", multiplier=50, tick_size=0.25,
+        underlying_id=synthetic("SPX", "USD", src=list(src='yahoo', name='^GSPC')))
[1] "ES"
> # above, in addition to defining the future root "ES", we defined an instrument
> # named "SPX".  Using the "src" argument causes setSymbolLookup to be called.
> # Using the "src" arg as above is the same as
> # setSymbolLookup(SPX=list(src='yahoo', name='^GSPC'))
> getSymbols("SPX") # this now works even though the Symbol used by is "^GSPC", not "SPX"
> ## Back to the futures; we can define a future_series
> future_series("ES_U2", identifiers=list(other="ESU2"))
[1] "ES_U2"
> # Identifiers are not necessary, but they allow for the instrument to be found
> # by more than one name
> # This will find the instrument even though the primary_id is "ES_U2"
> getInstrument("ESU2") 
primary_id   :"ES_U2"
currency     :"USD"
multiplier   :50
tick_size    :0.25
identifiers  :List of 1
 ..$ other:"ESU2"
type         :"future_series" "future"
root_id      :"ES"
suffix_id    :"U2"
expires      :"2012-09"
> # can also add indentifiers later
> add.identifier("ES_U2", inhouse="ES_U12")
> # can add an arbitrary field with instrument_attr
> instrument_attr("ES_U2", "description", "S&P 500 e-mini")
> getInstrument("ES_U2")
primary_id   :"ES_U2"
currency     :"USD"
multiplier   :50
tick_size    :0.25
identifiers  :List of 2
 ..$ other  :"ESU2"
 ..$ inhouse:"ES_U12"
type         :"future_series" "future"
root_id      :"ES"
suffix_id    :"U2"
expires      :"2012-09"
description  :"S&P 500 e-mini"

As you might expect, options are treated similarly. One of my favorite of Garrett’s additions, however, is populating instruments from public data sources such as Yahoo!:

>"GS") # define a bunch of options on "GS"
 [1] "GS_120922C70"   "GS_120922C75"   "GS_120922C80"   "GS_120922C85"   "GS_120922C87.5"
 [6] "GS_120922C90"   "GS_120922C92.5" "GS_120922C95"   "GS_120922C97.5" "GS_120922C100" 
[11] "GS_120922C105"  "GS_120922C110"  "GS_120922C115"  "GS_120922C120"  "GS_120922C125" 
[16] "GS_120922C130"  "GS_120922C135"  "GS_120922C140"  "GS_120922P50"   "GS_120922P55"  
[21] "GS_120922P60"   "GS_120922P65"   "GS_120922P70"   "GS_120922P75"   "GS_120922P80"  
[26] "GS_120922P85"   "GS_120922P87.5" "GS_120922P90"   "GS_120922P92.5" "GS_120922P95"  
[31] "GS_120922P97.5" "GS_120922P100"  "GS_120922P105"  "GS_120922P110"  "GS_120922P115" 
[36] "GS_120922P120"  "GS_120922P125"  "GS_120922P130"  "GS_120922P140" 
Warning messages:
1: In option(primary_id = paste(".", symbol, sep = ""), currency = currency,  :
  underlying_id not found
> # The warning means that the option root was automatically created
> getInstrument(".GS")
primary_id   :".GS"
currency     :"USD"
multiplier   :100
tick_size    : NULL
identifiers  : list()
type         :"option"
> # could also find ".GS" by looking for "GS", but specifying type
> getInstrument("GS", type='option')
primary_id   :".GS"
currency     :"USD"
multiplier   :100
tick_size    : NULL
identifiers  : list()
type         :"option"
> ls_options()
 [1] ".GS"            "GS_120922C100"  "GS_120922C105"  "GS_120922C110"  "GS_120922C115" 
 [6] "GS_120922C120"  "GS_120922C125"  "GS_120922C130"  "GS_120922C135"  "GS_120922C140" 
[11] "GS_120922C70"   "GS_120922C75"   "GS_120922C80"   "GS_120922C85"   "GS_120922C87.5"
[16] "GS_120922C90"   "GS_120922C92.5" "GS_120922C95"   "GS_120922C97.5" "GS_120922P100" 
[21] "GS_120922P105"  "GS_120922P110"  "GS_120922P115"  "GS_120922P120"  "GS_120922P125" 
[26] "GS_120922P130"  "GS_120922P140"  "GS_120922P50"   "GS_120922P55"   "GS_120922P60"  
[31] "GS_120922P65"   "GS_120922P70"   "GS_120922P75"   "GS_120922P80"   "GS_120922P85"  
[36] "GS_120922P87.5" "GS_120922P90"   "GS_120922P92.5" "GS_120922P95"   "GS_120922P97.5"

To get a sense of why that’s important, go ahead and do the same for SPY – you’ll see how much trouble he’s saved you.

In that same vein, the package also includes constructors for certain synthetic instruments, such as spreads.

FinancialInstrument doesn’t try to exhaust the possibilities of attributes, so it instead allows for flexibility. If you wanted to add an attribute to tag the exchange the instrument is listed on, just add it when defining the instrument:

future('CL', multiplier=1000, currency="USD", tick_size=.01, exchange="CME", description="Crude Light futures"))

Or add a field with more slightly more detail, such as description=’IBM Common Stock’. You can also add attribute after the instrument has been created using instrument_attr as shown in the examples section below.

Garrett also added a bunch of convenience functions that will help you define and create instruments. A couple of my favorites include a ‘month-to-code’ generator for those damned futures symbols I can never remember:

> M2C()
jan feb mar apr may jun jul aug sep oct nov dec 
"F" "G" "H" "J" "K" "M" "N" "Q" "U" "V" "X" "Z"

Another is a parser that infers descriptive information from the name of an instrument:

> parse_id("ES_U3")
List of 10
 root  : chr "ES"
 suffix: chr "U3"
 type  : chr  "outright" "future"
 month : chr "SEP"
 year  : num 2013
 strike: logi NA
 right : logi NA
 cm    : logi FALSE
 cc    : logi FALSE
 format: chr "CY"

Another is instrument.table, which assembles a data.frame of the instruments and attributes defined:

> instrument.table()
    primary_id currency multiplier tick_size identifiers     type exchange description
DBC        DBC      USD          1      0.01      list()    stock     NULL        NULL
GLD        GLD      USD          1      0.01      list()    stock     NULL        NULL
GM          GM      USD          1      0.01      list()    stock     NYSE        NULL
IEF        IEF      USD          1      0.01      list()    stock     NULL        NULL
USD        USD      USD          1      0.01      list() currency     NULL        NULL
VEU        VEU      USD          1      0.01      list()    stock     NULL        NULL
VNQ        VNQ      USD          1      0.01      list()    stock     NULL        NULL
VTI        VTI      USD          1      0.01      list()    stock     NULL        NULL
XLB        XLB      USD          1      0.01      list()    stock     NULL        NULL
XLE        XLE      USD          1      0.01      list()    stock     NULL        NULL
XLF        XLF      USD          1      0.01      list()    stock     NULL        NULL
XLI        XLI      USD          1      0.01      list()    stock     NULL        NULL
XLK        XLK      USD          1      0.01      list()    stock     NULL        NULL
XLP        XLP      USD          1      0.01      list()    stock     NULL        NULL
XLU        XLU      USD          1      0.01      list()    stock     NULL        NULL
XLV        XLV      USD          1      0.01      list()    stock     NULL        NULL
XLY        XLY      USD          1      0.01      list()    stock     NULL        NULL
XOM        XOM      USD          1      0.01      list()    stock     NULL Exxon Mobil

Cool, eh? There’s a lot more. All in all, FinancialInstrument is now well over 130 functions, well documented, and well-applied. You’ll find it now on CRAN or the development version on r-forge.

Thanks again to Garrett See and Brian Peterson for all their work on this package!

To leave a comment for the author, please follow the link and comment on their blog: tradeblotter » R. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)