Rbitcoin package can be used to create end-to-end trading engine in R.
The goal of the vignettes is to present a possible workflow based on the functions available in the package. Additionally few other handy utilies are also presented.
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", dev="svg") suppressPackageStartupMessages(library(Rbitcoin)) Sys.setenv(TZ="UTC") # plot always in UTC options("Rbitcoin.antiddos.sec"=5) # faster build vignette
There is also simple shinyApp as GUI for Rbitcoin package shinyBTC which can be complementary to this vignette.
shiny::runGitHub("jangorecki/shinyBTC")
The core functionality of Rbitcoin is to communicate with cryptocurrency exchanges API directly from R, and to unify the structure of market API response across the different markets.
Lets see the full process.
market <- "kraken" currency_pair <- c("BTC","EUR")
Public API calls do not require any authentication and you can query it without having an account on market.
ticker <- market.api.process(market, currency_pair, "ticker") ticker
trades <- market.api.process(market,currency_pair,"trades") trades[["trades"]][,tail(.SD,10)] # print only last 10 trades
rbtc.plot(trades)
order_book <- market.api.process(market,currency_pair,"order_book") rbtc.plot(order_book)
order_book[["asks"]][,head(.SD,10)] # print only first 10 asks
Private API calls requires authentication, user need to have an account on market and generate API keys (key
and secret
param pair).
Below examples will not be evaluated due to missing key
and secret
parameters in the vignette.
wallet <- market.api.process(market, action = "wallet", key = "", secret = "") wallet[["wallet"]] # print currencies and their amount in the wallet
place_limit_order <- market.api.process(market, currency_pair, action = "place_limit_order", req = list(type = "buy", price = 500, amount = 0.15) key = "", secret = "")
open_orders <- market.api.process(market, action = "open_orders", key = "", secret = "")
oid
must be provided (oid can be obtained using open_orders method)cancel_order <- market.api.process(market, action = "cancel_order", req = list(oid = "") key = "", secret = "")
To avoid ban on API interface caused by a sequence of API calls, the market.api.process
(and any other function which query over web) will perform antiddos procedure behind the scene (to customize see ?antiddos
).
Because of the market.api.process
function do post-process and pre-process of API calls to common structure across markets, the function is limited to defined markets and currency pairs in the dictionary (?api.dict
). User can extend built-in dictionary for new markets (?query.dict
) or new currency pairs or new API methods (?api.dict
).
In case if user wants to use currency pair or method not defined in the dictionary it is possible using market.api.query
function which can handle any currency pair and any method but it requires appropriate format of method arguments and it will not post-process API response to common structure.
Built-in dictionary supports following market and currency pairs
api.dict <- getOption("Rbitcoin.api.dict") api.dict[!is.na(base), .(market, currency_pair = paste0(base,quote))][,unique(.SD)]
Simple conversion of fiat currencies to BTC (based on blockchain.info rates)
fromBTC(1) # current BTCUSD price toBTC(150, "GBP") # convert 150 GBP to BTC
Query blockchain.info API
# some first wallets btc address details addr <- blockchain.api.process('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa') str(addr) # some transaction details tx <- blockchain.api.process('e5c4de1c70cb6d60db53410e871e9cab6a0ba75404360bf4cda1b993e58d45f8') str(tx, max.level=1)
If you need to query any other data from blockchain API you can use blockchain.api.query
function which allows any methods but do not post-process response.
There is wise advice to do not store assets in a single location. This function assists in the management of assets distributed across different locations.
Wallet manager is quite complex function to track your cryptocurrency balances (and it's values at a time) on different markets/accounts/addresses.
By default function do not archive it's results, this must be setup using archive_write=TRUE
args but user should be aware that sensitive data (balance and its sources but not api keys) will be archived locally in working directory as wallet_archive.rds
file. Archive will allow rbtc.plot
to plot historical assets balance over time. Historical balances might be also important for user's further analysis.
Below is the example of sources definition and wallet manager execution.
# example market.sources market.sources <- list( "john smith" = list(market='kraken', key='', secret=''), "jane smith" = list(market='kraken', key='', secret=''), "john smith" = list(market='btce', key='', secret=''), "jane smith" = list(market='btce', key='', secret='') ) # example blockchain.sources blockchain.sources <- list( "john smith" = list(address='') ) # example manual.sources manual.sources <- list( "john smith" = list(location='bitfinex', location_type='market', currency=c('BTC','USD'), amount=c(0.4,0)), "john smith" = list(location='fidor', location_type='bank', currency=c('EUR','USD'), amount=c(20,0)), "jane smith" = list(location='fidor', location_type='bank', currency=c('EUR','GBP'), amount=c(10,105)) ) # execute wallet_dt <- wallet_manager( market.sources = market.sources, blockchain.sources = blockchain.sources, manual.sources = manual.sources, value_currency = 'USD', # your target currency rate_priority = c('bitstamp','kraken','hitbtc','btce','bitmarket'), # value rates source priority archive_write = TRUE # by default FALSE, read ?wallet_manager )
full_wallet_dt <- structure( list(wallet_id = c(1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L,1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1396310400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1398902400L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1401580800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1404172800L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1406851200L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L, 1409529600L), currency = c("BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD", "BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD", "BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD", "BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD", "BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD", "BTC", "BTC", "BTC", "BTC", "BTC", "EUR", "EUR", "EUR", "EUR", "GBP", "LTC", "LTC", "LTC", "USD", "USD", "USD", "USD", "USD"), currency_type = c("crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat", "crypto", "crypto", "crypto", "fiat", "fiat", "fiat", "fiat", "fiat"), auth = c("john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "john smith", "john smith", "jane smith", "jane smith", "john smith", "jane smith", "jane smith", "john smith", "john smith", "john smith", "john smith", "jane smith"), timestamp = structure(c(1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1396310400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1398902400, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1401580800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1404172800, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1406851200, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600, 1409529600), class = c("POSIXct", "POSIXt"), tzone = "UTC"), location = c("bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce", "bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce", "bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce", "bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce", "bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce", "bitfinex", "kraken", "kraken", "btce", "15Mb2QcgF3XDMeVn6M7oCG6CQLw4mkedDi", "fidor", "fidor", "kraken", "kraken", "fidor", "kraken", "kraken", "btce", "fidor", "bitfinex", "kraken", "btce", "btce"), location_type = c("market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market", "market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market", "market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market", "market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market", "market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market", "market", "market", "market", "market", "blockchain", "bank", "bank", "market", "market", "bank", "market", "market", "market", "bank", "market", "market", "market", "market"), amount = c(0, 0.15, 0, 0, 0.1, 190, 130, 40, 80, 110, 0, 4, 1, 275, 25, 10, 30, 30, 0, 0.15, 0, 0, 0.1, 10, 0, 170, 260, 0, 0, 4, 1, 0, 100, 110, 130, 205, 0.22, 0.6, 0.45, 0.3, 0.1, 10, 10, 0, 40, 15, 10, 8, 10.5, 0, 0, 5, 15, 105, 0.12, 0.1, 0.45, 0.3, 0.7, 10, 20, 0, 40, 105, 10, 0, 18.5, 0, 0, 5, 0, 5, 0, 0.1, 0.2, 0, 0.15, 10, 20, 0, 140, 105, 10, 5, 0, 0, 400, 5, 225, 160, 0.4, 0.1, 0.6, 0.4, 0.55, 10, 20, 0, 0, 105, 10, 5, 35, 0, 0, 5, 50, 15), value_currency = c("USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD", "USD"), value_rate = c(478.98, 478.98, 478.98, 478.98, 478.98, 1.380905, 1.380905, 1.380905, 1.380905, 1.674109, 13.24, 13.24, 13.24, 1, 1, 1, 1, 1, 460.97, 460.97, 460.97, 460.97, 460.97, 1.373171, 1.373171, 1.373171, 1.373171, 1.68398, 11.02, 11.02, 11.02, 1, 1, 1, 1, 1, 630.99, 630.99, 630.99, 630.99, 630.99, 1.359912, 1.359912, 1.359912, 1.359912, 1.691485, 11.04, 11.04, 11.04, 1, 1, 1, 1, 1, 638.25, 638.25, 638.25, 638.25, 638.25, 1.353611, 1.353611, 1.353611, 1.353611, 1.70729, 7.83, 7.83, 7.83, 1, 1, 1, 1, 1, 589.59, 589.59, 589.59, 589.59, 589.59, 1.331674, 1.331674, 1.331674, 1.331674, 1.669659, 7.67, 7.67, 7.67, 1, 1, 1, 1, 1, 474.54, 474.54, 474.54, 474.54, 474.54, 1.288716, 1.288716, 1.288716, 1.288716, 1.629786, 4.7, 4.7, 4.7, 1, 1, 1, 1, 1), value = c(0, 71.847, 0, 0, 47.898, 262.37195, 179.51765, 55.2362, 110.4724, 184.15199, 0, 52.96, 13.24, 275, 25, 10, 30, 30, 0, 69.1455, 0, 0, 46.097, 13.73171, 0, 233.43907, 357.02446, 0, 0, 44.08, 11.02, 0, 100, 110, 130, 205, 138.8178, 378.594, 283.9455, 189.297, 63.099, 13.59912, 13.59912, 0, 54.39648, 25.372275, 110.4, 88.32, 115.92, 0, 0, 5, 15, 105, 76.59, 63.825, 287.2125, 191.475, 446.775, 13.53611, 27.07222, 0, 54.14444, 179.26545, 78.3, 0, 144.855, 0, 0, 5, 0, 5, 0, 58.959, 117.918, 0, 88.4385, 13.31674, 26.63348, 0, 186.43436, 175.314195, 76.7, 38.35, 0, 0, 400, 5, 225, 160, 189.816, 47.454, 284.724, 189.816, 260.997, 12.88716, 25.77432, 0, 0, 171.12753, 47, 23.5, 164.5, 0, 0, 5, 50, 15)), .Names = c("wallet_id", "currency", "currency_type", "auth", "timestamp", "location", "location_type", "amount", "value_currency", "value_rate", "value"), row.names = c(NA, -108L), class = c("data.table", "data.frame"), sorted = c("wallet_id", "currency") )
Function gathers all the wallet balances from specified sources, calculates its values in specified value_currency and returns following structure (value_currency can be also cryptocurrency).
wallet_dt <- full_wallet_dt[wallet_id==max(wallet_id)] # ECHO OFF recent wallet from populated data str(wallet_dt)
Simple plot of only recent balances, last wallet manager check on example dummy data.
rbtc.plot(wallet_dt) # type="recent" due to `archive_read=FALSE` so: wallet_dt[,length(unique(wallet_id))]==1 wallet_dt <- full_wallet_dt # ECHO OFF full wallet archive from populated data
After multiple runs of wallet_manager(..., archive_write=TRUE)
we may plot historical balances.
Simple low-resolution (monthly, n=6) example of wallet manager dummy data over time.
# load archive only wallet_dt <- wallet_manager(archive_write=FALSE, archive_read=TRUE)
rbtc.plot(wallet_dt) # type="value" due to `archive_read=TRUE` # in case of poor legend scaling it might be better to export plot to file svg("wallet_manager_value.svg") rbtc.plot(wallet_dt) dev.off()
Notice the graphs in this html are in svg format so are well zoom-able.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.