Introduction

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")

Market API

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.

  1. We will start by picking the market and currency pairs on which we will operate
market <- "kraken"
currency_pair <- c("BTC","EUR")

Public API call

Public API calls do not require any authentication and you can query it without having an account on market.

  1. At the beginning we might be interested to see top level price data using ticker API method
ticker <- market.api.process(market, currency_pair, "ticker")
ticker
  1. a. Then we may want to lookup recent trades
trades <- market.api.process(market,currency_pair,"trades")
trades[["trades"]][,tail(.SD,10)] # print only last 10 trades
  1. b. Above call gives us a raw trades data which might be not so meaningful, we can visualize trades to see a little bit more
rbtc.plot(trades)
  1. a. We want to confirm the order book is depth enough to fulfill our order
order_book <- market.api.process(market,currency_pair,"order_book")
rbtc.plot(order_book)
  1. b. If we are going to buy we might want to check the top of asks from order book
order_book[["asks"]][,head(.SD,10)] # print only first 10 asks

Private API call

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.

  1. Query your wallet (account balance) information from market
wallet <- market.api.process(market, action = "wallet", key = "", secret = "")
wallet[["wallet"]] # print currencies and their amount in the wallet
  1. Place limit order on the market (buy amount of 0.15 BTC at 500 EUR price per 1 BTC)
place_limit_order <- market.api.process(market, currency_pair, action = "place_limit_order", 
                                        req = list(type = "buy",
                                                   price = 500,
                                                   amount = 0.15)
                                        key = "", secret = "")
  1. Fetch currently open orders on the market
open_orders <- market.api.process(market, action = "open_orders", key = "", secret = "")
  1. Cancel order on market, 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 = "")

Market API notes

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)]

Utilities

to/from BTC

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

Blockchain API

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.

Wallet Manager

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.



jangorecki/Rbitcoin documentation built on May 18, 2019, 12:24 p.m.