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
Plot
Baltimore Crime Counts by Category 2017-2024
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