RPubs will retire in June 2027. Your existing documents will stay accessible through December 31, 2031
and Connect Cloud is the recommended home for new publishing. Read the blog post

Recently Published

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
Inference using R
Document
Foundations for Inference in R
Practical Analysis for inference in R