This was temporarily deleted because I've realized too late that this Q is about marketcaps not prices. However Marketcap = (price * number of bitcoins in circulation) so I've undeleted this post.
Bitinfocharts.com provide a directory with numerous compressed gz files with historic data from various trading platforms.
There are many datasets, even from MountGox days apparently.
However, I have only looked at this file: http://api.bitcoincharts.com/v1/csv/krakenEUR.csv.gz.
This 115MB zipfile is 615 MB uncompressed. It contains a dataset from the Kraken Platform, the series starts in 2014. At this time the table structure looks like this:
Observations: 15,386,405
Variables: 3
$ unixtime <int> 1389173189, 1389173198, 1389173198, 1389173265, 1389173339, 1389173528, 1389173534, ...
$ price <dbl> 624.0, 624.0, 623.5, 623.5, 623.5, 623.5, 623.5, 623.5, 623.5, 623.5, 623.5, 623.5, ...
$ amount <dbl> 0.20000, 0.09767, 0.01358, 0.14896, 0.20000, 0.17630, 0.40633, 0.20000, 1.80000, 0.3...
It has a periodicity of 1-10 seconds. You probably can apply your own window function to aggregate up to 1 hour periodicity.
I have done this and it looks like this (pink dots are hourly median prices):

To get marketcap you can download the number of bitcoins in circulation from Quandl.com: https://www.quandl.com/data/BCHAIN/TOTBC-Total-Bitcoins
The number of Bitcoins in circulation is also well known. Every 10 minutes one block containing (at this time) 12.5 Bitcoins is added tothe blockchain.
The R code I've used to generate this plot:
library(lubridate)
library(tidyverse)
# setwd("~/code/git/_my/R_stuff/R_diverse")
# days back in humanreadable form, e.g. "2017-12-28"
n <- 30
days_back <- today() - days(n)
btc_kraken_url <- "http://api.bitcoincharts.com/v1/csv/krakenEUR.csv.gz"
btc_kraken_gz <- basename(btc_kraken_url)
btc_kraken_csv <- str_replace(btc_kraken_gz, "\\.gz$", "")
if(!file.exists(btc_kraken_gz) && !file.exists(btc_kraken_csv)){
download.file(btc_kraken, destfile = btc_hist)
system(sprintf("gunzip %s", btc_kraken_gz))
} else if(!file.exists(btc_kraken_csv)){
system(sprintf("gunzip %s", btc_kraken_gz))
}
csv0 <- read_csv(
btc_kraken_csv,
col_names = c("unixtime", "price", "amount")
)
glimpse(csv0)
# grab
csv0 <- csv0 %>%
mutate(datetime = as.POSIXct(unixtime, origin = "1970-01-01")) %>%
arrange(unixtime, price) %>%
select(datetime, price, amount)
summary(csv0)
csv0 <- csv0 %>%
filter(datetime >= days_back)
# Periodicity
csvz <- xts::as.xts(csv0[,2], order.by=csv0$datetime, unique = FALSE)
xts::periodicity(csvz)
csv <- csv0 %>%
mutate(datetime = floor_date(datetime, unit = "hour"),
price = as.integer(price))
csv2 <- csv %>%
group_by(datetime, price) %>%
summarize(sum_amount = sum(amount)) %>%
select(-sum_amount) %>%
group_by(datetime) %>%
summarize(median_price = median(price)) %>%
ungroup()
csv2 <- csv2 %>%
mutate(datetime = datetime + lubridate::minutes("30")) %>%
arrange(datetime)
head(csv2)
myplot <- ggplot(csv0, aes(datetime, price)) +
geom_line(size=0.1) +
geom_point(data = csv2,
aes(datetime, median_price),
color="hotpink", size=0.1) +
ggtitle("Bitcoin prices on kraken.com, per-Second and Hourly",
subtitle = sprintf("Bitcoin in Euro, from %s to %s \nsource: %s",
days_back, today(), btc_kraken_url)) +
ylab("BTC/€")
ggsave(plot = myplot,
filename =sprintf("bitcoin--%s--%s.png", days_back, today()))