Easy web publishing from R

Write R Markdown documents in RStudio.
Share them here on RPubs. (It’s free, and couldn’t be simpler!)

Get Started

Recently Published

Team Dashboard
ASISA 2025
Plot
Baltimore Crime Counts by Category 2017-2024
Inference
Bitcoin price and indicators
library(httr) library(jsonlite) library(dplyr) library(TTR) library(plotly) library(zoo) fetch_binance_batch <- function(symbol = "BTCUSDT", interval = "1d", start_date) { base_url <- "https://api.binance.com/api/v3/klines" start_ms <- as.numeric(as.POSIXct(start_date, tz = "UTC")) * 1000 res <- GET(base_url, query = list(symbol = symbol, interval = interval, startTime = format(start_ms, scientific = FALSE), limit = 1000)) stop_for_status(res) data_list <- fromJSON(content(res, "text", encoding = "UTF-8")) if (length(data_list) == 0) return(NULL) df <- as.data.frame(data_list, stringsAsFactors = FALSE) colnames(df) <- c("OpenTime", "Open", "High", "Low", "Close", "Volume", "CloseTime", "QuoteAssetVolume", "NumberOfTrades", "TakerBuyBaseAssetVolume", "TakerBuyQuoteAssetVolume", "Ignore") numeric_cols <- setdiff(names(df), "Ignore") df[numeric_cols] <- lapply(df[numeric_cols], as.numeric) df$OpenTime <- as.POSIXct(df$OpenTime / 1000, origin = "1970-01-01", tz = "UTC") df$CloseTime <- as.POSIXct(df$CloseTime / 1000, origin = "1970-01-01", tz = "UTC") df } fetch_binance_daily_full <- function(symbol = "BTCUSDT", interval = "1d", start_date) { all_data <- list() start_ms <- as.numeric(as.POSIXct(start_date, tz = "UTC")) * 1000 batch_num <- 1 repeat { cat(sprintf("Fetching batch %d from %s\n", batch_num, as.POSIXct(start_ms / 1000, origin = "1970-01-01", tz = "UTC"))) df <- fetch_binance_batch(symbol, interval, as.POSIXct(start_ms / 1000, origin = "1970-01-01", tz = "UTC")) if (is.null(df)) { cat("No more data.\n") break } all_data[[batch_num]] <- df last_open_ms <- as.numeric(df$OpenTime[nrow(df)]) * 1000 if (last_open_ms <= start_ms) break start_ms <- last_open_ms + 1 batch_num <- batch_num + 1 Sys.sleep(0.5) } do.call(rbind, all_data) } btc_daily <- fetch_binance_daily_full("BTCUSDT", "1d", "2017-01-01") btc_daily$SMA20 <- SMA(btc_daily$Close, n = 20) btc_daily$EMA20 <- EMA(btc_daily$Close, n = 20) btc_daily$RSI14 <- RSI(btc_daily$Close, n = 14) macd_vals <- MACD(btc_daily$Close, nFast = 12, nSlow = 26, nSig = 9) btc_daily$MACD <- macd_vals[,1] btc_daily$MACD_signal <- macd_vals[,2] btc_daily$MACD_hist <- macd_vals[,1] - macd_vals[,2] bbands <- BBands(btc_daily$Close, n = 20, sd = 2) btc_daily$BB_up <- bbands[, "up"] btc_daily$BB_dn <- bbands[, "dn"] btc_daily$BB_mavg <- bbands[, "mavg"] btc_daily$BB_pctB <- bbands[, "pctB"] adx_vals <- ADX(HLC = btc_daily[, c("High", "Low", "Close")], n = 14) btc_daily$ADX <- adx_vals[, "ADX"] btc_daily$DIp <- adx_vals[, "DIp"] btc_daily$DIn <- adx_vals[, "DIn"] stoch_vals <- stoch(HLC = btc_daily[, c("High", "Low", "Close")], nFastK = 14, nFastD = 3, nSlowD = 3) btc_daily$Stoch_K <- stoch_vals[, "fastK"] btc_daily$Stoch_D <- stoch_vals[, "fastD"] btc_daily$TrendSignal <- ifelse(lag(btc_daily$SMA20) < lag(btc_daily$EMA20) & btc_daily$SMA20 >= btc_daily$EMA20, "Golden Cross", ifelse(lag(btc_daily$SMA20) > lag(btc_daily$EMA20) & btc_daily$SMA20 <= btc_daily$EMA20, "Death Cross", NA)) btc_daily$RSI_signal <- ifelse(btc_daily$RSI14 > 70, "Overbought", ifelse(btc_daily$RSI14 < 30, "Oversold", NA)) btc_daily$VolumeSpike <- btc_daily$Volume > 2 * SMA(btc_daily$Volume, 20) btc_daily$BB_width <- btc_daily$BB_up - btc_daily$BB_dn threshold <- quantile(btc_daily$BB_width, 0.1, na.rm = TRUE) btc_daily$BB_squeeze <- btc_daily$BB_width < threshold btc_daily$log_return <- c(NA, diff(log(btc_daily$Close))) btc_daily$volatility_20d <- rollapply(btc_daily$log_return, 20, sd, fill = NA, align = "right") btc_daily$OpenTimeStr <- format(btc_daily$OpenTime, "%Y-%m-%d") text_info <- paste("Date:", btc_daily$OpenTimeStr, "<br>Close:", round(btc_daily$Close, 2), "<br>SMA20:", round(btc_daily$SMA20, 2), "<br>EMA20:", round(btc_daily$EMA20, 2), "<br>Signal:", btc_daily$TrendSignal) p1 <- plot_ly(btc_daily, x = ~OpenTimeStr, type = "candlestick", open = ~Open, close = ~Close, high = ~High, low = ~Low, name = "Candles", text = text_info, hoverinfo = "text") %>% add_lines(y = ~SMA20, name = "SMA 20", line = list(color = 'orange')) %>% add_lines(y = ~EMA20, name = "EMA 20", line = list(color = 'purple')) %>% layout(yaxis = list(title = "Price (USDT)")) p2 <- plot_ly(btc_daily, x = ~OpenTimeStr) %>% add_lines(y = ~MACD_hist, name = "MACD Hist", line = list(color = 'steelblue')) %>% add_lines(y = ~MACD_signal, name = "MACD Signal", line = list(color = 'orange')) %>% add_lines(y = ~MACD, name = "MACD", line = list(color = 'purple')) %>% layout(yaxis = list(title = "MACD")) p3 <- plot_ly(btc_daily, x = ~OpenTimeStr, y = ~RSI14, type = 'scatter', mode = 'lines', name = "RSI (14)", line = list(color = 'darkgreen')) %>% add_lines(y = rep(70, nrow(btc_daily)), name = "Overbought (70)", line = list(dash = 'dash', color = 'red')) %>% add_lines(y = rep(30, nrow(btc_daily)), name = "Oversold (30)", line = list(dash = 'dash', color = 'red')) %>% layout(yaxis = list(title = "RSI")) p4 <- plot_ly(btc_daily, x = ~OpenTimeStr, y = ~Volume, type = 'bar', name = "Volume", marker = list(color = ifelse(btc_daily$VolumeSpike, 'red', 'steelblue'))) %>% layout(yaxis = list(title = "Volume")) fig <- subplot(p1, p2, p3, p4, nrows = 4, shareX = TRUE, heights = c(0.4, 0.2, 0.2, 0.2), titleY = TRUE) %>% layout( xaxis4 = list(title = "Date", showgrid = FALSE, zeroline = FALSE), yaxis1 = list(title = "Price (USDT)"), yaxis2 = list(title = "MACD"), yaxis3 = list(title = "RSI"), yaxis4 = list(title = "Volume"), hovermode = "x unified", legend = list(orientation = "h", x = 0.1, y = 1.1), margin = list(t=40, b=60) ) fig
DocumentInference using R
This is for materials on inference using R
Test of Hypotheses