FinancialInstrument Moves to CRAN
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 getSymbols.yahoo is "^GSPC", not "SPX" "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" underlying_id:"SPX" > # 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" underlying_id:"SPX" 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!:
> option_series.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" underlying_id:"GS" > # 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" underlying_id:"GS" > 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!
R-bloggers.com 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.