vignettes/spread-analysis.Rmd
spread-analysis.Rmd
We are going to show a simple use case for the rRofex library by build a function that can calculate the difference in the Bid and Ask from the order book. Afterwards we are going to plot it and see how spread has been evolving over time.
We start by log in with our credentials using the function trading_login()
. For obvious reasons we are going to use data that has been already process on the back end. If you choose to use your own credentials and follow this article, you’ll be able to recreate your own spread analysis.
connection <- rRofex::trading_login(username = "XXX", password = "XXX", base_url = "XXX")
Once we are connected, we’ll query the reference data and we’ll focus our analysis on the following instruments: Rofex 20 Index, Dollar, Galicia, Gold and Oil futures. All this using two functions: trading_instruments()
and trading_instruments_fronts()
. The first is used to obtain the full reference data and the latter to determine the front months for each future contract.
instruments_to_follow <- rRofex::trading_instruments(connection = connection, request = "securities", sec_detailed = TRUE) %>% select(Symbol, Underlying, LowLimitPrice, HighLimitPrice, MinPriceIncrement, ContractMultiplier) %>% filter(Symbol %in% (rRofex::trading_instruments_fronts(connection = connection) %>% filter(Underlying %in% c("RFX20", "DO", "GGAL", "ORO", "WTI")) %>% pull(Symbol))) DT::datatable(instruments_to_follow)
Now that we have the products, we’ll build a function to retrieve it’s prices and calculate in real time the spread between the ask and bid:
spread_real_time <- function(connection, symbol) { data <- rRofex::trading_md( connection = connection, symbol = symbol, entries = c('BI', 'OF') ) %>% rename( Bid = BI_price, Offer = OF_price ) %>% mutate( SpreadNominal = Offer - Bid, Time = Sys.time() ) %>% select(Time, Bid, Offer, SpreadNominal) return(data) }
Having this, we could create a job that every days reads in market data and uses this function to record the spread into a data base. For example, this can be achieved with a function like this one, in conjunctionw with the purrr::map
family:
data_to_save <- bind_cols(instruments_to_follow, purrr::map_dfr(.x = instruments_to_follow$Symbol, .f = ~ spread_real_time(connection = connection, symbol = .x))) %>% mutate( SpreadTick = SpreadNominal / MinPriceIncrement ) DT::datatable(data_to_save %>% select(Time, Symbol, Bid, Offer, SpreadNominal, SpreadTick)) %>% DT::formatRound(c("SpreadNominal", "SpreadTick")) %>% DT::formatCurrency(c("Bid", "Offer")) %>% DT::formatDate("Time", method = "toTimeString")
If we collect each observation showned before for a couple of days, we’ll end up with a data frame like this one:
With the latter we can build a plot that analyses historical spreads for the already mentioned instruments.
plot_spreads <- spread_historico %>% filter(!(instrument == "DO" & lubridate::hour(time) > 17)) %>% nest(data = c(bid, ask, tick, SpreadNominal, SpreadTick, time)) %>% mutate( mean = purrr::map_dbl(data, ~ mean(.$SpreadTick)), median = purrr::map_dbl(data, ~ mean(.$SpreadTick)) ) %>% unnest(cols = c(data)) %>% ggplot() + geom_line( mapping = aes(x = time, y = SpreadTick, color = Symbol), alpha = 0.5, show.legend = FALSE) + geom_line( mapping = aes(x = time, y = mean, color = Symbol), linetype = "dashed", size = 1, show.legend = FALSE) + geom_line( mapping = aes(x = time, y = median, color = Symbol), linetype = "dotted", size = 1, show.legend = FALSE) + facet_wrap( facets = ~ Symbol, scales = "free") + scale_x_datetime( labels = scales::date_format("%H %M", tz = Sys.timezone(location = TRUE)), date_breaks = "1 hours") + theme_minimal() + theme( legend.position = "top", legend.title = element_blank(), panel.grid.minor = element_blank() ) + labs( x = "", y = "", title = "Spreads Bid-Ask de Productos Seleccionados", subtitle = "Medido en Tick Mínimo", caption = "Elaborado por I&D para el Webinar rRofex del 12/06/2020" ) aux_data <- spread_historico %>% filter(!(instrument == "DO" & lubridate::hour(time) > 17)) %>% group_by(Symbol) %>% summarise( mean = mean(SpreadTick), median = median(SpreadTick), max = max(SpreadTick), tick = mean(tick), .groups = "drop" ) plot_spreads <- plot_spreads + geom_text( data = aux_data, mapping = aes( x = as.POSIXct("2020-06-11 12:10:00"), y = max * 0.9, label = glue("Tick: ${tick}") ), size = 3) + geom_text( data = aux_data, mapping = aes( x = as.POSIXct("2020-06-11 12:10:00"), y = max * 0.8, label = glue("Media: {round(mean,2)} ticks") ), size = 3) + geom_text( data = aux_data, mapping = aes( x = as.POSIXct("2020-06-11 12:10:00"), y = max * 0.7, label = glue("Mediana: {round(median,2)} ticks") ), size = 3) plotly::ggplotly(p = plot_spreads)
Let’s see how the trade volume has developed for a given day.
historical_data <- purrr::map_dfr(.x = instruments_to_follow$Symbol, .f = ~ rRofex::trading_mdh(connection = connection, symbol = .x, date = "2020-07-07")) p <- historical_data %>% ggplot(aes(x = lubridate::as_datetime(servertime), y = price, size = size)) + geom_point(show.legend = FALSE, alpha = 0.3, color = "#454545") + theme_minimal() + scale_y_continuous( position = "right", label = scales::dollar_format()) + labs(x = "",y = "") + facet_wrap(.~symbol, scales = "free") plotly::ggplotly(p = p)