Garrett See
The TFX package is available on CRAN.
# CRAN version
install.packages("TFX")
# development version
#install.packages("TFX", repos="http://r-forge.r-project.org")
The TFX package is a simple interface to the TrueFX™ Web API. If you
call QueryTrueFX()
with its defaults, it will create an unauthenticated session
and return quotes for 10 currency pairs. (All timestamps are in GMT.)
library(TFX)
QueryTrueFX()
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 EUR/USD 1.30394 1.30398 1.30476 1.29838 2012-12-03 02:31:25.507
## 2 USD/JPY 82.38800 82.39200 82.50800 82.32500 2012-12-03 02:31:26.434
## 3 GBP/USD 1.60403 1.60410 1.60486 1.60112 2012-12-03 02:31:28.147
## 4 EUR/GBP 0.81289 0.81299 0.81309 0.81035 2012-12-03 02:31:25.851
## 5 USD/CHF 0.92464 0.92475 0.92843 0.92439 2012-12-03 02:31:26.403
## 6 EUR/JPY 107.43000 107.43900 107.50700 106.91200 2012-12-03 02:31:28.311
## 7 EUR/CHF 1.20560 1.20580 1.20623 1.20472 2012-12-03 02:31:25.802
## 8 USD/CAD 0.99234 0.99244 0.99461 0.99212 2012-12-03 02:31:27.665
## 9 AUD/USD 1.04126 1.04134 1.04341 1.03932 2012-12-03 02:31:25.404
## 10 GBP/JPY 132.15900 132.16300 132.26100 131.88700 2012-12-03 02:31:28.147
Note: if you don't see millisecond resolution, set options(digits.secs=3)
or higher
In order to make customized requests, you must create an authenticated session which requires a username and password. Go to TrueFX.com to register for a free TrueFX™ account; you only need to provide an e-mail address.
I'll pretend that you chose “JSTrader” as your username and “Ou812” for your password because that is the example used in the official TrueFX Market Data Web API Developer Guide, but you should use your actual, authenticated username and password instead.
Once you have a registered username and password, you can create an authenticated session. With an authenticated session, you can request only the pairs that you want.
yen <- ConnectTrueFX("USD/JPY,EUR/JPY,GBP/JPY,AUD/JPY,CAD/JPY,CHF/JPY",
username="JSTrader", password="Ou812")
QueryTrueFX(yen)
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 USD/JPY 82.388 82.392 82.508 82.325 2012-12-03 02:31:26.434
## 2 EUR/JPY 107.430 107.439 107.507 106.912 2012-12-03 02:31:28.311
## 3 GBP/JPY 132.159 132.163 132.261 131.887 2012-12-03 02:31:28.147
## 4 AUD/JPY 85.787 85.797 86.011 85.578 2012-12-03 02:31:26.380
## 5 CAD/JPY 83.015 83.026 83.052 82.825 2012-12-03 02:31:29.348
## 6 CHF/JPY 89.096 89.109 89.144 88.700 2012-12-03 02:31:28.536
If you pass an empty string (""
) to the currency.pairs
argument,
the 15 pairs for which TrueFX™ provides
historical data will
be used (for a full list of currency.pairs
available for real-time quotes see
the TrueFX Market Data Web API Developer Guide
which you can view in your pdf viewer by calling TrueFXRef()
)
QueryTrueFX(ConnectTrueFX("", "JSTrader", "Ou812", snapshot=TRUE))
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 EUR/USD 1.30394 1.30398 1.30476 1.29838 2012-12-03 02:31:25.507
## 2 USD/JPY 82.38800 82.39200 82.50800 82.32500 2012-12-03 02:31:26.434
## 3 GBP/USD 1.60403 1.60410 1.60486 1.60112 2012-12-03 02:31:28.147
## 4 EUR/GBP 0.81289 0.81299 0.81309 0.81035 2012-12-03 02:31:25.851
## 5 USD/CHF 0.92464 0.92475 0.92843 0.92439 2012-12-03 02:31:28.592
## 6 EUR/JPY 107.43000 107.43900 107.50700 106.91200 2012-12-03 02:31:28.311
## 7 EUR/CHF 1.20560 1.20580 1.20623 1.20472 2012-12-03 02:31:29.384
## 8 USD/CAD 0.99234 0.99244 0.99461 0.99212 2012-12-03 02:31:27.665
## 9 AUD/USD 1.04126 1.04134 1.04341 1.03932 2012-12-03 02:31:25.404
## 10 GBP/JPY 132.15900 132.16300 132.26100 131.88700 2012-12-03 02:31:28.147
## 11 AUD/JPY 85.78700 85.79700 86.01100 85.57800 2012-12-03 02:31:26.380
## 12 AUD/NZD 1.27090 1.27116 1.27334 1.27022 2012-12-03 02:31:27.076
## 13 CAD/JPY 83.01500 83.02600 83.05200 82.82500 2012-12-03 02:31:29.348
## 14 CHF/JPY 89.09600 89.10900 89.14400 88.70000 2012-12-03 02:31:29.404
## 15 NZD/USD 0.81921 0.81938 0.82089 0.81703 2012-12-03 02:31:28.227
Authenticated sessions retrieve only incremental updates by default. This can be easily demonstrated by creating a session with a lot of symbols and making multiple requests. You'll see that an authenticated session does not always return data for all pairs by default.
If ConnectTrueFX
is called with snapshot=TRUE
(as above), then the session
that is created will be disconnected after a request and will have to be
reconnected for each request. By default, the QueryTrueFX
function, will
automatically reconnect a disconnected session but can be called with
reconnect=FALSE
if you want to throw an error when there is an attempt to
request data with a disconnected session. Also note that even non-snapshot
sessions become disconnected after roughly a minute of inactivity.
# this session gets only incremental updates
up <- ConnectTrueFX("", "JSTrader", "Ou812", snapshot=FALSE)
# this one is disconnected after a request and will have to be reconnected
# for a subsequent request.
ss <- ConnectTrueFX("", "JSTrader", "Ou812", snapshot=TRUE)
Now, make multiple requests and look at how many pairs are updated in each call.
the up
session was created with snapshot=FALSE
so it only gets updates for
pairs that have values that have changed since the last request.
# make 20 requests and count the rows of each response
sapply(1:20, function(i) nrow(QueryTrueFX(up)))
## [1] 15 0 2 0 1 0 1 1 1 0 6 9 4 3 4 1 1 0 2 0
The ss
connection was created with snapshot=TRUE
, so each time it is passed
to QueryTrueFX
it gets temporarily reconnected.
sapply(1:20, function(i) nrow(QueryTrueFX(ss)))
## [1] 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15
Note that the snapshot session is no longer active.
isActive(ss)
## [1] FALSE
But the other one is still connected
isActive(up)
## [1] TRUE
reconnect
argument to QueryTrueFX()
Let's make a new snapshot session that doesn't have as many pairs just so that the output won't take up as much space
eurss <- ConnectTrueFX("EUR/USD", "JSTrader", "Ou812", snapshot = TRUE)
The first request with a snapshot session returns data and then the session is immediately disconnected.
QueryTrueFX(eurss, reconnect = FALSE) #after the request, eurss will be disconnected
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 EUR/USD 1.30393 1.30398 1.30476 1.29838 2012-12-03 02:31:31.513
QueryTrueFX(eurss, reconnect = FALSE) # Error; no longer connected
## Error: 'session' is not connected and 'reconnect' is not TRUE
Reconnect(eurss)
QueryTrueFX(eurss, reconnect = FALSE) #disconnected after request
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 EUR/USD 1.30393 1.30398 1.30476 1.29838 2012-12-03 02:31:31.513
If QueryTrueFX is called with reconnect=TRUE (the default) it will do the re-connection step for you.
isActive(eurss)
## [1] FALSE
QueryTrueFX(eurss)
## Symbol Bid.Price Ask.Price High Low TimeStamp
## 1 EUR/USD 1.30393 1.30398 1.30476 1.29838 2012-12-03 02:31:31.513
A snapshot session terminates after it has been used. There are two other ways for a session to become disconnected (regardless of whether it is a snapshot session or not).
Disconnect()
* technically, sessions timeout in about 70 seconds, but, since this is not
documented in the Developer Guide, isActive
returns
FALSE
after 60 seconds of inactivity to ensure no false positives
isActive(up)
## [1] TRUE
Disconnect(up)
isActive(up)
## [1] FALSE
Reconnect(up)
isActive(up)
## [1] TRUE
#Sys.sleep(70) # session will become inactive after roughly 60 seconds
#isActive(up) # FALSE
By default, QueryTrueFX()
will parse the results of a query (by calling
ParseTrueFX()
) and return a data.frame
. You can choose not to parse the
response by using parse.response=FALSE
.
QueryTrueFX(ConnectTrueFX('USD/CAD,EUR/JPY', 'JSTrader', 'Ou812'),
parse.response=FALSE)
## [1] "USD/CADEUR/JPY0.99107.2344300.99107.2444370.99461107.5070.99212106.91213545018906661354501892466"
(ParseTrueFX()
can be used to make sense of that string)
format
argument to ConnectTrueFX()
Above you see what TrueFX™ returns when you use the "default"
format. My
advice is to always use the "default"
format, because, last I checked, the
"default"
format gets updates before the other formats do. The next quickest
to update is the "html"
format, and "csv"
is the slowest to update. The
one benefit to using "html"
or "csv"
is that in addition to the columns
returned when format is "default"
, they also return an Open
column.
However, in addition to being delayed relative to the "default"
format,
the values for High and Low are backwards (i.e. wrong) for these formats.
For the sake of completeness, let's look at them anyway. I'll use
parse.response=FALSE
to show the differences in the raw responses. If you
use parse.response=TRUE
(the default) the response will be passed through
ParseTrueFX()
to get a data.frame
by default, or a list
if
pretty=FALSE
.
QueryTrueFX(ConnectTrueFX("USD/CAD,EUR/JPY", 'JSTrader', 'Ou812', format='html'),
parse.response=FALSE)
## [1] "<table><tr><td>USD/CAD</td><td>1354501884748</td><td>0.99</td><td>234</td><td>0.99</td><td>244</td><td>0.99212</td><td>0.99461</td><td>0.99368</td></tr><tr><td>EUR/JPY</td><td>1354501892466</td><td>107.</td><td>430</td><td>107.</td><td>437</td><td>106.912</td><td>107.507</td><td>107.019</td></tr></table>"
QueryTrueFX(ConnectTrueFX("USD/CAD,EUR/JPY", 'JSTrader', 'Ou812', format='csv'),
parse.response=FALSE)
## [1] "USD/CAD,1354501884748,0.99,234,0.99,244,0.99212,0.99461,0.99368"
## [2] "EUR/JPY,1354501892466,107.,430,107.,437,106.912,107.507,107.019"
## [3] ""
ParseTrueFX()
can be used on any of the three formats. It will determine
which format it has been given, and parse it appropriately.
pretty
argument to ParseTrueFX()
ParseTrueFX()
first splits the input into a list
of unprocessed character
vectors:
QueryTrueFX(ConnectTrueFX('USD/CAD,EUR/JPY', 'JSTrader', 'Ou812'),
parse.response=TRUE, pretty=FALSE)
## $Symbol
## [1] "USD/CAD" "EUR/JPY"
##
## $BidBigNumber
## [1] "0.99" "107."
##
## $BidPip
## [1] "234" "430"
##
## $OfferBigNumber
## [1] "0.99" "107."
##
## $OfferPip
## [1] "244" "437"
##
## $High
## [1] "0.99461" "107.507"
##
## $Low
## [1] "0.99212" "106.912"
##
## $TimeStamp
## [1] "1354501890666" "1354501892466"
Then, if called with pretty=TRUE
(the default), it will convert
the list
to a data.frame
– like those in the previous examples –
converting strings to numeric
or POSIXct
as necessary.
qualifier
argument to ConnectTrueFX()
An authenticated session must have a qualifier
which can be any alphanumeric
string. The default value for the qualifier
argument to ConnectTrueFX()
is "default"
, although you're free to use something else.
con <- ConnectTrueFX('USD/JPY,EUR/JPY', 'JSTrader', 'Ou812',
qualifier="2yen")
con$qualifier
## [1] "2yen"
A TFXsession
object is just an environment that contains the info needed by
QueryTrueFX()
. There is a print.TFXsession
method in version 0.1.1 of
TFX. If you are using version 0.1.0, your output will look different. The
print.TFXsession
method will only print “non-private” info. It will not print
username or password.
eurss
## <TFXsession 1354501895887>
## $ currency.pairs:"EUR/USD"
## $ qualifier :"default"
## $ active :FALSE
## $ snapshot :TRUE
## $ format :"default"
## $ last.used :"2012-12-02 20:31:35.679 CST"
You can explore a TFXsession
object just like any other environment
:
ls
, ls.str
, as.list
, etc.
ls(eurss)
## [1] "active" "currency.pairs" "format" "id"
## [5] "last.used" "password" "qualifier" "session"
## [9] "snapshot" "URL" "username"
RStudio's shiny is awesome. If you haven't played with it yet, you should check it out (http://www.rstudio.com/shiny/).
You can install shiny by entering these commands:
options(repos = c(RStudio = "http://rstudio.org/_packages", getOption("repos")))
install.packages("shiny")
I put together a really simple shiny app that will open a browser and display real-time quotes that update every 750 milliseconds.
You can run the app with:
library(shiny)
runGist("4122626")
This shiny app uses an unauthenticated session which means that it always displays the same 10 currency pairs. However, you can easily modify the code to use an authenticated session using your login credentials. It could also be modified to update more often and/or show milliseconds in the timestamps. The code for this shiny app can be viewed or downloaded from http://gist.github.com/4122626
In addition to real-time quotes, TrueFX™ also provides historical tick data going back to 2009 for 15 currency pairs.
From the TrueFX™ website:
TrueFX is the first service that brings you real, dealable prices from real market participants from all the major market makers, with absolutely no intermediary. As a technology company, we can offer you historical tick-by-tick market data, at zero cost to you.
This data is top-of-the-book, tick-by-tick market data, with fractional pip spreads in millisecond detail. All timestamps are based on GMT.
The data can be downloaded from http://www.truefx.com/?page=downloads
The TFX package is in no way affiliated, endorsed, or approved by TrueFX™, Integral Development Corp, or any of its affiliates. TrueFX™ is a brand name that is owned by Integral Development Corp.