HOME




Cross-Exchange Price Analysis

Quantifying Market Inefficiencies and Arbitrage Opportunities





Cross-Exchange Price Analysis

1 Dataset Overview


Our comprehensive market analysis is based on high-frequency price data collected from 5 major cryptocurrency exchanges over a 14-day period. The dataset encompasses:

  • 5 cryptocurrencies monitored continuously
  • 5 exchanges providing real-time market data
  • 2-week observation period with sub-minute granularity
  • 800,000+ data points enabling statistical significance

This extensive dataset allows for detailed cross-exchange price comparison and identification of market inefficiencies that may present arbitrage opportunities.


Ethereum Price Correlation Analysis: The following visualization demonstrates the price evolution of Ethereum across all monitored exchanges, revealing both strong correlation and subtle discrepancies:

# Load required libraries for analysis
library(tidyverse)
library(ggplot2)
library(DT)
library(plotly)
library(hrbrthemes)
library(viridis)
library(lubridate)

# Load comprehensive market dataset
load("../DATA/public_ticker_harvest.Rdata")
Ticker$last <- as.numeric(Ticker$last)

# Create multi-exchange price comparison
p <- Ticker %>%
  filter(symbol=="ETHEUR") %>%
  filter(last>400) %>%    # Remove anomalous data points
  ggplot( aes(x=time, y=last, color=platform, group=platform)) +
    geom_line( size=0.8, alpha=0.7) +
    scale_color_viridis(discrete=TRUE, name="Exchange") +
    ylab("Ethereum Price (EUR)") +
    xlab("Date (February 2018)") +
    theme_ipsum() +
    scale_x_datetime(date_breaks = "1 day", date_labels = "%d", minor_breaks=NULL) +
    ggtitle("Ethereum Price Evolution Across Multiple Exchanges") +
    theme( plot.title = element_text(size=14, color="grey"))
p

High-Resolution Market Microstructure: When examining the first 1,000 data points at higher resolution, market microstructure effects and temporary price discrepancies become apparent:

# Detailed microstructure analysis
p <- Ticker %>%
  filter(symbol=="ETHEUR") %>%
  filter(last>400) %>%    # Remove anomalous data points
  head(1000) %>%
  ggplot( aes(x=time, y=last, color=platform, group=platform)) +
    geom_line( size=1.2) +
    scale_color_viridis(discrete=TRUE, name="Exchange") +
    ylab("Ethereum Price (EUR)") +
    theme_ipsum() +
    ggtitle("High-Resolution Price Microstructure (First 1,000 Observations)") +
    theme( plot.title = element_text(size=14, color="grey")) 
  
p

2 Statistical Analysis of Price Differences


While the visualizations above demonstrate strong price correlation between exchanges, systematic analysis reveals significant price discrepancies that create potential arbitrage opportunities. These differences, though often small in absolute terms, can be substantial enough to generate profits when leveraged appropriately.


Methodology: The following analysis quantifies price differences using the ‘last’ transaction price between exchange pairs. The chart below displays the percentage price differential between Kraken and Bitstamp for Ethereum at each timestamp:

# Function to calculate price differences between exchanges
get_last_difference <- function(plat1, plat2, currency){
  # Calculate percentage difference in 'last' price between exchanges
  diff <- Ticker %>%
    filter(symbol==currency) %>%
    filter(platform %in% c(plat1, plat2)) %>%
    select(time, platform, last, symbol) %>%
    spread(platform, last) %>%
    mutate(diff=.[[4]] - .[[3]], diff_perc=(.[[4]] - .[[3]]) / .[[4]] *100 ) %>%
    filter(!is.na(diff_perc))
  return(diff)
}
  
# Function to visualize price differences
plot_last_difference <- function(diff, plat1, plat2){
  p <-  diff %>%
        sample_frac(0.1) %>%    
        ggplot( aes(x=time, y=diff_perc, group=symbol, fill=symbol)) +
          geom_area(fill="#69b3a2") +
          theme_ipsum() +
          theme(
            legend.position="none",
            plot.title = element_text(size=14, color="grey")
          ) +
          ylab("Price Difference (%)") +
          xlab("Date (February 2018)") +
          ggtitle(paste0("Ethereum Price Differential: ", plat1, " vs ", plat2)) +
          scale_x_datetime(date_breaks = "1 day", date_labels = "%d", minor_breaks=NULL) +
          ylim(-3,3)
  
  p
}

# Execute analysis for Kraken vs Bitstamp
diff <- get_last_difference("Kraken", "Bitstamp", "ETHEUR")
p <- plot_last_difference(diff, "Kraken", "Bitstamp")
p

## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_align()`).

Statistical Summary: This analysis covers a 14-day period with 42,087 price observations. Key findings include:

  • 2,293 instances where Bitstamp exceeded Kraken prices by ≥1%
  • 644 instances where Kraken exceeded Bitstamp prices by ≥1%
  • Total significant differences: 2,937 occurrences
  • Average frequency: 209.7857143 significant price differences per day

Important Note: This analysis uses ‘last’ transaction prices. In practice, arbitrage execution requires bid/ask spreads, where cryptocurrencies are purchased at the ‘ask’ price and sold at the ‘bid’ price, resulting in smaller effective differences.

3 Optimal Exchange Pair Identification


To maximize arbitrage potential, we must identify exchange pairs with the highest frequency of significant price discrepancies and determine which cryptocurrencies exhibit the most pronounced inefficiencies.


The following analysis quantifies arbitrage opportunities by examining bid/ask spreads across exchange pairs, providing a more realistic assessment of executable profit potential:

# Function to calculate bid/ask arbitrage opportunities
find_askbid_difference <- function(plat1, plat2){
  
  diff <- Ticker %>% 
    filter(platform %in% c(plat1, plat2)) %>%
    select(time, platform, symbol, ask, bid) %>%
    mutate(ask=as.numeric(ask), bid=as.numeric(bid)) %>%
    gather(temp, value, -time, -platform, -symbol) %>%
    mutate(platform=gsub(plat1,"plat1", platform)) %>%
    mutate(platform=gsub(plat2,"plat2", platform)) %>%
    unite(temp1, platform, temp, sep="_") %>%
    spread( key=temp1, value=value) %>%
    mutate( 
      diff1=(plat1_bid-plat2_ask)/plat1_bid*100, 
      diff2=(plat2_bid-plat1_ask)/plat2_bid*100
    ) %>%
    rowwise() %>%
    mutate( diff_perc=max(diff1, diff2) ) %>%
    filter(!is.na(diff_perc))
  return(diff)
}

# Function to quantify significant differences across thresholds
find_signif_diff <- function(diff){
  nbSignifDiff=data.frame()
  for( i in seq(0.7,4,0.2)){
    df <-  diff %>%
      group_by(symbol) %>%
      filter(diff_perc > i) %>%
      summarise( nb_over_thres = n() ) %>%
      mutate( thres = i) %>%
      arrange( nb_over_thres )
    nbSignifDiff <- rbind( nbSignifDiff, df)
  }
  return(nbSignifDiff)
}

# Function to visualize arbitrage frequency by threshold
plot_signif_diff <- function(nbSignifDiff){
  p <- nbSignifDiff %>%
    mutate(nb_over_thres = nb_over_thres / time_length(lengthPeriod, unit="day")) %>%
    mutate(mytext=paste0("Currency: ", gsub("EUR", "",symbol), "\n", round(nb_over_thres,0)," opportunities per day above ",thres, "%")) %>%
    mutate(symbol = gsub("EUR", "", symbol)) %>%
    ggplot( aes(x=thres, y=nb_over_thres, group=symbol, color=symbol, text=mytext)) +
      geom_line(size=1.2) +
      geom_point(size=2) +
      ylab("Arbitrage Opportunities per Day") +
      xlab("Minimum Price Difference Threshold (%)") +
      ggtitle("Daily Arbitrage Frequency by Cryptocurrency (Kraken vs Bitstamp)") +
      theme_ipsum() +
      theme(
        plot.title = element_text(size=14, color="grey"),
        legend.title = element_text(size=12),
        legend.position = "right"
      ) +
      scale_color_viridis(discrete=TRUE, name="Cryptocurrency") +
      scale_x_continuous(breaks=seq(0.8, 4, 0.4))
  
  ggplotly(p, tooltip="text")
}

# Execute comprehensive analysis
diff <- find_askbid_difference("Kraken", "Bitstamp")
nbSignifDiff <- find_signif_diff(diff)
plot_signif_diff(nbSignifDiff)

Key Insights:

  1. Bitcoin Cash (BCH) and Ripple (XRP) show the highest frequency of arbitrage opportunities
  2. Price differences above 1% occur approximately 200-300 times per day for most cryptocurrencies
  3. Opportunities above 1.7% become extremely rare, indicating market efficiency limits
  4. Litecoin (LTC) demonstrates consistent arbitrage potential across all thresholds

4 Market Efficiency Analysis


The analysis reveals that while cryptocurrency markets exhibit strong price correlation between exchanges, systematic inefficiencies persist that create measurable arbitrage opportunities. These findings suggest:

Market Characteristics: - High correlation (>99%) between exchange prices over longer timeframes - Frequent micro-inefficiencies creating short-term arbitrage windows - Currency-specific patterns with some assets showing higher volatility - Threshold effects where opportunities diminish rapidly above certain percentage differences

Arbitrage Viability: - Daily opportunities ranging from 200-400 instances per cryptocurrency pair - Optimal thresholds between 0.8-1.5% for sustainable arbitrage strategies - Exchange-specific patterns suggesting systematic pricing differences

5 Next Phase: Strategy Development


Having quantified significant market inefficiencies across multiple exchange pairs and cryptocurrencies, the next phase involves developing a comprehensive arbitrage strategy that can systematically exploit these opportunities while managing associated risks.


Explore Arbitrage Theory →