Create a gist now

Instantly share code, notes, and snippets.

packages.list <- c(
"data.table",
"quantmod",
"jsonlite",
"prophet",
"dplyr",
"ggplot2",
"ggthemes",
"cowplot",
"zoo"
)
packages.new <- packages.list[!(packages.list %in% installed.packages()[,"Package"])]
if(length(packages.new)){
install.packages(packages.new)
}
library(data.table)
library(quantmod)
library(jsonlite)
library(prophet)
library(dplyr)
library(ggplot2)
library(ggthemes)
library(cowplot)
library(zoo)
CREST_BASE = "https://crest-tq.eveonline.com/"
## GET TYPEID/REGION ID FROM http://eve-marketdata.com/developers/index.php ##
typeID = "34"
#typeID = "29668"
#typeID = "40520"
regionID = "10000002"
chart_path = paste0(getwd(),"/Plots/")
dir.create(chart_path, showWarnings=FALSE)
plot.width = 1600
plot.height = 900
plot.predict = 60
plot.sma.slow = 15
plot.sma.fast = 5
## SEE quantmod.com for TA ARGS ##
TA_args = "addBBands(15,2);addVo();addMACD(5,15,5);addRSI();addLines(h=30, on=4);addLines(h=70, on=4)"
graph_subset = "last 400 days"
#graph_subset = "last 1 years"
## FETCH ID/NAME CONVERSIONS FROM CREST ##
typeID_addr <- paste0(CREST_BASE, "inventory/types/", typeID, "/")
typeID.json <- fromJSON(readLines(typeID_addr))
typeName <- typeID.json$name
regionID_addr <- paste0(CREST_BASE, "regions/", regionID, "/")
regionID.json <- fromJSON(readLines(regionID_addr))
regionName <- regionID.json$name
## FETCH PRICE HISTORY FROM CREST AND INSERT INTO QUANTMOD ##
priceHistory_addr = paste0(CREST_BASE, "market/", regionID, "/history/?type=", CREST_BASE, "inventory/types/", typeID, "/")
market.json <- fromJSON(readLines(priceHistory_addr))
market.data.json <- data.table(market.json$items)
market.data <- market.data.json[,list(Date = as.Date(date)[-1],
Volume= volume[-1],
High = highPrice[-1],
Low = lowPrice[-1],
Close =avgPrice[-1],
Open = avgPrice)]
n <- nrow(market.data)
market.data <- market.data[1:n-1,]
## FILTER OUT HIGH/LOW FLIERS ##
low_flag = quantile(market.data$Low,.25)/5
high_flag = quantile(market.data$High,.75)*5
market.data$Low[market.data$Low<=low_flag] <-min(market.data$Open,market.data$Close)
market.data$High[market.data$High>=high_flag] <-max(market.data$Open,market.data$Close)
market.data$move <- market.data$Close - market.data$Open
market.data$move.normal <- market.data$move / market.data$Close
market.data$sma.fast <- rollmean(
market.data$Close,
k=plot.sma.fast,
align='right',
na.pad=TRUE
)
market.data$sma.slow <- rollmean(
market.data$Close,
k=plot.sma.slow,
align='right',
na.pad=TRUE
)
market.data$deviation.fast <- market.data$Close - market.data$sma.fast
market.data$deviation.slow <- market.data$Close - market.data$sma.slow
## Build Forecasts ##
prophet.move <- prophet(data.frame(
ds=market.data$Date,
y=market.data$move
))
prophet.deviation.fast <- prophet(data.frame(
ds=market.data$Date,
y=market.data$deviation.fast
))
prophet.deviation.slow <- prophet(data.frame(
ds=market.data$Date,
y=market.data$deviation.slow
))
prophet.move.final <- predict(
prophet.move,
make_future_dataframe(prophet.move, periods=plot.predict)
)
plot(prophet.move, prophet.move.final)
prophet.deviation.fast.final <- predict(
prophet.deviation.fast,
make_future_dataframe(prophet.deviation.fast, periods=plot.predict)
)
plot(prophet.deviation.fast, prophet.deviation.fast.final)
prophet.deviation.slow.final <- predict(
prophet.deviation.slow,
make_future_dataframe(prophet.deviation.slow, periods=plot.predict)
)
plot(prophet.deviation.slow, prophet.deviation.slow.final)
market.prophet.tmp <- data.frame(
ds=market.data$Date,
y=market.data$Close
)
market.prophet <- prophet(market.prophet.tmp)
market.future <- make_future_dataframe(market.prophet, periods=plot.predict)
market.predict <- predict(market.prophet, market.future)
market.predict <- merge(
market.predict,
market.prophet.tmp,
by='ds',
all=TRUE
)
market.predict$monte <- NA
monte.date <- max(market.prophet.tmp$ds, na.rm=TRUE)
monte.price <- market.data$sma.slow[market.data$Date == monte.date]
for(val in 1:plot.predict){
step_date <- monte.date + val
monte.price <- monte.price + prophet.move.final$yhat[prophet.move.final$ds == step_date]
monte.high <- monte.price + prophet.move.final$yhat_upper[prophet.move.final$ds == step_date]
monte.low <- monte.price + prophet.move.final$yhat_lower[prophet.move.final$ds == step_date]
market.predict$monte[market.predict$ds == step_date] <- monte.price
}
#plot(market.prophet, market.predict)
## Build Plot ##
market.max_scale = max(market.predict$y, na.rm=TRUE)
plot.future <- ggplot(
market.predict,
aes(
x=ds,
ymin=yhat_lower,
ymax=yhat_upper
)
)
plot.future <- plot.future + geom_ribbon(
color='light blue',
fill='light blue',
alpha=0.5
)
plot.future <- plot.future + geom_line(
aes(
x=ds,
y=y
),
data=market.predict
)
plot.future <- plot.future + geom_line(
aes(
x=ds,
y=monte
),
data=market.predict,
color='red'
)
if(market.max_scale > 1e9){
plot.future <- plot.future + scale_y_continuous(
#limits=c(min(market.max_scale),NA),
labels=function(x)sprintf("%.2fB",x/1e9),
position='right'
)
}else if(market.max_scale > 1e6){
plot.future <- plot.future + scale_y_continuous(
#limits=c(min(market.max_scale),NA),
labels=function(x)sprintf("%.2fM",x/1e6),
position='right'
)
}else if(market.max_scale > 1e3){
plot.future <- plot.future + scale_y_continuous(
#limits=c(min(market.max_scale),NA),
labels=function(x)sprintf("%.2fK",x/1e3),
position='right'
)
}
plot.future <- plot.future + labs(
x='Date',
y='Price',
title=paste0(typeName, ' + Prediction ', plot.predict, ' days -- ', regionName)
)
plot.future <- plot.future + theme_fivethirtyeight()
print(plot.future)
## Save to File ##
image_title <- paste(
typeName,
paste0("prediction-", plot.predict),
Sys.Date(),
regionID,
sep="_"
)
png(paste0(chart_path,image_title,".png"), width=plot.width, height=plot.height)
print(plot.future)
dev.off()
## SAVE DATA TO CSV FOR OTHER PLATFORMS ##
write.csv(market.json, paste0(chart_path,image_title,".csv"), row.names=FALSE)
write.csv(market.data, paste0(chart_path,image_title,"_OHLC.csv"), row.names=FALSE)
@lockefox
Owner
lockefox commented Feb 24, 2017 edited

Using Prophet, generate (naive) forecasts for EVE items using the CREST market history endpoint

30 day pilot s license extension plex _prediction-60_2017-02-24_10000002

skill injector_prediction-60_2017-02-24_10000002

@lockefox
Owner

DISCLAIMER: forecasting strictly on price isn't a sustainable practice. ClosingPrice is the answer to a complicated non-linear set of dependencies.

Further work is required to instead forecast off something with more-normal behavior such as:

  • day-to-day change
  • deviation from moving average
  • MER Data
@lockefox
Owner
lockefox commented Feb 25, 2017 edited

Updated to include gbm/montecarlo style walker using day-to-day variation forecast to plot alternate predictions

tritanium_prediction-60_2017-02-24_10000002
mexallon_prediction-60_2017-02-24_10000002
skill injector_prediction-60_2017-02-24_10000002
Sometimes to comedic effect :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment