2019-01-20

Intrinsic time for cryptocurrency data

This week, I attended a three-day hacking event of the Crypto Traders Berlin Meetup group.

The aim was to find relationships between sentiment data of bitcointalk and twitter and the price of crypto currencies. In practise, it turns out to be not that easy. For starters, it is not easy to determine if the social media discussion spikes up after a significant price change or the other way round.

During this meetup series, I explored the concept of "intrinsic time", as proposed by a team at the University of Essex. The idea is to summarize price data not by fixed intervals, but by directional changes in the price. This, they argue, has the advantage of covering more extreme points of the price data (a longer coast line). Also, some empirical scaling laws emerge when looking at the data this way.

The R code I came up with can be found here at pastebin, and here is a chart showing the output:


There is still a lot to explore, for instance if the cryptocurrency price do follow some empirical scaling laws and identify market regimes based on this kind of summary, but it was a good start.

Being a trading rooky, it was also interesting to learn some ideas, like the maker-taker model and the metapher of "surfing the waves" for trend following.

It was a friendly meetup with interesting people to get acquainted with, I recommend this meetup if you are in the area and interested in this topic. Thanks to the organizers and sponsor, as well!

EDIT 27. Jan. 2019: there was an error in the code at pastebin. This is now fixed I think. However, when processing real tick data, the code seems to be too slow. Also, for tick data, a smaller threshold is recommened (such as 0.02% or 0.1%). A sample of tick data can be found here. I will look for a faster solution, maybe using sql or a better vectorized version.


8 comments:

Anonymous said...

Interesting post. Your code seems to expect OHLC trades data, which already contradicts the idea of forming tick trades into price frames rather than time frames. Could you comment on that? should the code work for tick trades? Example input data have not been provided, maybe you could link a gist to that so your analysis will be reproducible. Thank you!

Karsten W. said...

Hi, thanks for reading & commenting. The code should work for tick trades. I used OHLC data because I do not have other (yet). I plan to research data this weekend and post it if public available.

Anonymous said...

Thanks. Good resources of tick trades easily available can be found at https://api.bitcoincharts.com/v1/csv/
Regarding your code, the else branch in while loop below is not always what the comment suggests. `mode` value is initialized as "uoi/dei" or "doi/uei". Is it OK that `else` kicks in for those values then?

if(mode=="dcc_up") {
...
} else { # mode=="dcc_down"
...
}

Karsten W. said...

Yep, that seems to be an error. Will fix it on weekend.

Karsten W. said...

Added a link to tick data, thanks for the hint to bitcoincharts.com. The code is now fixed, but seems to be too slow for my taste.

Anonymous said...

try this, loop can be moved to C/C++ for even faster processing
```r
library(data.table)
# priceframes - directional changes
get_priceframes = function(x, threshold) {
stopifnot(is.double(x), is.double(threshold))
nx = length(x)
if (nx < 2L) stop("provided input is length ", nx)
imx = imn = 1L
trend = open = confirm = rep(NA_integer_, nx)
last_trend = 0L
for (i in 2:nx) {
if (last_trend < 1L && x[i] >= x[imn] * (1.0 + threshold)) {
trend[i] = last_trend = 1L
open[i] = imn
confirm[i] = i
imx = i
} else if (last_trend > -1L && x[i] <= x[imx] * (1.0 - threshold)) {
trend[i] = last_trend = -1L
open[i] = imx
confirm[i] = i
imn = i
}
if (x[i] > x[imx]) imx = i
if (x[i] < x[imn]) imn = i
}
d = as.data.table(list(
trend=trend, i_open=open, i_confirm=confirm
))[!is.na(trend)][, "i_close" := shift(i_open, -1L)][]
icols = c("open","confirm","close")
d[, paste("price", icols, sep="_") := lapply(.SD, function(i) x[i]), .SDcols=paste("i", icols, sep="_")][]
d
}
```

Felix Dietrich said...

Hi, do you have a custom "plot" method? Or how does it accept dat=1 and dc_dat=dc_dat? Thank you!

Karsten W. said...

No, it's base::plot