Plotting Market Data from AlphaVantage.jl with Gnuplot.jl
The following description on how to get data from AlphaVantage is mainly based on Dean Markwick post AlphaVantage.jl - Getting Market Data into Julia.
AlphaVantage
Alpha Vantage is a stock API provider that is nice enough to provide free access to a wide variety of data. Available functionality
Stock data at both intraday, daily, weekly and monthly frequencies.
Technical indicators for stocks.
FX rates at both intraday, daily, weekly and monthly frequencies.
Crypto currencies, again, at the intraday, daily, weekly and monthly time scales.
The package is designed to replicate the API functions from the AlphaVantage documentation, so you can look up any of the functions in their documentation here and find the equivalent in this Julia package. If something is missing or isn’t working correctly, raise an issue on Github here.
Gnuplot.jl
Here, the goal is to simply show how the data can be plotted with this package. Gnuplot.jl is a simple package able to send both data and commands from Julia to an underlying gnuplot process. Its main purpose it to provide a fast and powerful data visualization framework, using an extremely concise Julia syntax.
Let's get ready with all the packages that we will need.
Getting gnuplot and Julia packages
If you are in Linux, usually doing the following is enough to get gnuplot.
apt-get -qq update
apt-get install gnuplot gnuplot-nox
Remember, after you also need to install Gnuplot.jl, with add Gnuplot
in the Julia repl
, plus some extra packages for the market data.
]add Dates DataFrames DataFramesMeta Gnuplot AlphaVantage
For easy plotting I did some recipies
in Gnuplot
(not all cases but most), so that our exploration becomes easier. So, if you try to reproduce these plots don't forget to include the script plotMarketData.jl
and raw_to_df.jl
to convert our data into DataFrames.
Loading all packages
# ENV["ALPHA_VANTAGE_API_KEY"] = "your key" # please get one!
using AlphaVantage, DataFrames, Dates, DataFramesMeta
using Gnuplot
import Gnuplot: PlotElement, DatasetText
include(rawtodf.jl)
include(plotMarketData.jl)
Gnuplot.gpversion()
Stocks
AlphaVantage provides daily, weekly and monthly historical stock data from 2000 right up to when you call the function. With the adjusted functions you also get dividends and adjusted closing prices to account for these dividends. Read more on how stock API providers generally adjust historical prices based on corporate actions such as splits and dividends.
tslaRaw = time_series_daily_adjusted("TSLA", outputsize="full", datatype="csv");
tsla = raw_to_dataframe(tslaRaw)
first(tsla, 5)
timestamp | open | high | low | close | adjusted_close | volume | dividend_amount | split_coefficient |
---|---|---|---|---|---|---|---|---|
2020-07-10 | 1396.0 | 1548.92 | 1376.01 | 1544.65 | 1544.65 | 23346400 | 0.0 | 1.0 |
2020-07-09 | 1396.99 | 1408.56 | 1351.28 | 1394.28 | 1394.28 | 11718300 | 0.0 | 1.0 |
2020-07-08 | 1405.0 | 1417.26 | 1311.34 | 1365.88 | 1365.88 | 16330200 | 0.0 | 1.0 |
2020-07-07 | 1405.01 | 1429.5 | 1336.71 | 1389.86 | 1389.86 | 21493300 | 0.0 | 1.0 |
2020-07-06 | 1276.69 | 1377.79 | 1266.04 | 1371.58 | 1371.58 | 20570300 | 0.0 | 1.0 |
Then, our first plot looks like
plot(tsla, :timestamp, :open)
save(term = "svg size 650,400", output = "/results/TSLAopen.svg")
And something really great about Gnuplot is that you can update your plot again by using @gp :-
as follows
plot(tsla, :timestamp, :open, lc = :red, leg_p ="l")
:- plot!(tsla, :timestamp, :close)
:- "set title font ',15' 'TSLA'" :-
:- "set xlab font ',15' 'Date Time'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/TSLAopen_close.svg")
S&P500
A very familiar stock is S&P 500, so here we are getting the daily S&P500 data and plotting it as
SP500Raw = time_series_daily("SPY", datatype="csv")
SP500 = raw_to_dataframe(SP500Raw, indc = 4)
first(SP500, 5)
timestamp | open | high | low | close | volume |
---|---|---|---|---|---|
2020-07-10 | 314.31 | 317.88 | 312.76 | 317.59 | 57454400 |
2020-07-09 | 316.84 | 317.1 | 310.68 | 314.38 | 83079100 |
2020-07-08 | 314.61 | 316.3 | 312.7 | 316.18 | 54202600 |
2020-07-07 | 315.38 | 317.52 | 313.37 | 313.78 | 82583400 |
2020-07-06 | 316.37 | 317.68 | 315.56 | 317.05 | 61149300 |
plot(SP500, :timestamp, :open, title = "SP500", leg_p = "b", rot_xtics=0) :-
:- plot!(SP500, :timestamp, :close, :red) :-
:- plot!(SP500, :timestamp, :low) :-
:- plot!(SP500, :timestamp, :high)
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,400", output = "/results/SP500.svg")
Or, if you have all your prices, by default you can get the candle-bars as follows
plot(SP500, :timestamp, rot_xtics=-45)
:- "set title 'SP500'" :-
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_candle.svg")
And with a different color
plot(SP500, :timestamp, box_color = "orange",rot_xtics=-45)
:- "set title 'SP500'" :-
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_candle_color.svg")
And for a smaller interval
plot(SP500, :timestamp,ini_date ="2020-03-01", end_date = "2020-04-01",
box_color = "black", leg_p = "t")
:- "set title 'SP500'"
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_candle_zoom.svg")
And you can even add a new line on top...
plot(SP500, :timestamp,ini_date ="2020-03-01", end_date = "2020-04-01",
box_color = "black", leg_p = "t")
:- plot!(SP500, :timestamp, :open)
:- "set title 'SP500'"
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_candle_open.svg")
Shaded area under price
plot(SP500, :timestamp, :close, "gold", :plasma; lcol = "orange", α =0.95)
:- "set title 'SP500'"
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_shaded.svg")
Note: if you use any another terminal
, not svg
, the transparencies look nicer.
And as before, you can add more lines on top:
plot(SP500, :timestamp, :close, "gold", :plasma; lcol = "orange", α =0.952)
:- plot!(SP500, :timestamp, :open, :black)
:- plot!(SP500, :timestamp, :high, :blue)
:- "set title 'SP500'"
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/SP500_shaded_lines.svg")
Intraday
What separates AlphaVantage from say google or yahoo finance data is the intraday data. They provide high frequency bars at intervals from 1 minute to an hour. The only disadvantage is that the maximum amount of data appears to be 5 days for a stock. Still better than nothing!
tslaIntraRaw = AlphaVantage.time_series_intraday("TSLA", "1min",
outputsize="full", datatype="csv")
tslaIntra = intra_to_dataframe(tslaIntraRaw)
Be careful with the number of days before!
tslaIntraDay = (tslaIntra, :DateTime .> DateTime(today()-Day(2)))
first(tslaIntraDay,4)
timestamp | open | high | low | close | volume | DateTime |
---|---|---|---|---|---|---|
2020-07-10 20:00:00 | 1541.75 | 1542.0 | 1541.75 | 1542.0 | 1654 | 2020-07-10T20:00:00 |
2020-07-10 19:59:00 | 1542.34 | 1542.98 | 1542.0 | 1542.98 | 1669 | 2020-07-10T19:59:00 |
2020-07-10 19:58:00 | 1543.0 | 1543.0 | 1542.1 | 1542.1 | 1134 | 2020-07-10T19:58:00 |
2020-07-10 19:57:00 | 1544.0 | 1544.0 | 1544.0 | 1544.0 | 1169 | 2020-07-10T19:57:00 |
plot(tslaIntraDay, :DateTime, :close, "#cc0000", :plasma;
lcol = "#333333", α =0.92, rot_xtics = -45)
:- "set title font ',15' 'TSLA Intraday $(today()-Day(1))'" :-
:- "set xlab font ',15' 'Date Time'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/TSLAintraday.svg")
or no shading at all
plot(tslaIntra, :DateTime, :open )
:- "set title 'TSLA Intraday'"
:- "set xlab font ',15' 'Date Time'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/TSLAintraday_noshade.svg")
Technical Indicators
AlphaVantage also provide a wide range of technical indicators. In this example we are using the Relative Strength Index.
rsiRaw = AlphaVantage.RSI("TSLA", "1min", 10, "open", datatype="csv")
rsiDF = DataFrame(rsiRaw[1])
rsiDF = rename(rsiDF, Symbol.(vcat(rsiRaw[2]...)))
rsiDF.time = DateTime.(rsiDF.time, "yyyy-mm-dd HH:MM:SS")
rsiDF.RSI = Float64.(rsiDF.RSI)
rsiSub = (rsiDF, :time .> DateTime(today() - Day(2)))
first(rsiSub,5)
time | RSI |
---|---|
2020-07-10T20:00:00 | 39.0232 |
2020-07-10T19:59:00 | 43.6106 |
2020-07-10T19:58:00 | 49.4649 |
2020-07-10T19:57:00 | 60.5484 |
2020-07-10T19:56:00 | 75.4619 |
minimum(rsiSub[!,:time]), maximum(rsiSub[!,:time])
iniDate = "2020-07-10T04:16:00"
lastDate = "2020-07-10T20:00:00"
plot(rsiSub, :time, :RSI, "", :lajolla; lcol = "black", α =0.85)
:- plot(iniDate, lastDate, 30; label = "Oversold")
:- plot(iniDate, lastDate, 70, :red; label = "Overbought")
:- "set title 'RSI'"
:- "set xlab font ',15' 'Date Time'"
save(term = "svg size 650,450", output = "/results/RSI.svg")
In this case, adding the threshold lines make a nice channel that the value falls between.
Sector Performance
AlphaVantage
also provides the sector performance on a number of timescales through one API
call.
sectorRaw = AlphaVantage.sector_performance()
sectorRaw["Rank F: Year-to-Date (YTD) Performance"]
Great year for IT, not so great for energy.
Forex
Moving into the foreign exchange market, again, AlphaVantage
provide multiple time scales and many currencies.
eurgbpRaw = AlphaVantage.fx_weekly("EUR", "GBP", datatype="csv");
eurgbp = DataFrame(eurgbpRaw[1])
eurgbp = rename(eurgbp, Symbol.(vcat(eurgbpRaw[2]...)))
eurgbp.Date = Date.(eurgbp.timestamp)
eurgbp.open = Float64.(eurgbp.open)
eurgbp.high = Float64.(eurgbp.high)
eurgbp.low = Float64.(eurgbp.low)
eurgbp.close = Float64.(eurgbp.close);
plot(eurgbp, :Date, :open, title="EURGBP")
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/EURGBP.svg")
Which looks great for a liquid currency like EURGBP, but they have a whole host of currencies so don’t limit yourself to just the basics, explore some NDF’s.
usdkrwRaw = AlphaVantage.fx_monthly("USD", "KRW", datatype="csv");
usdkrw = DataFrame(usdkrwRaw[1])
usdkrw = rename(usdkrw, Symbol.(vcat(usdkrwRaw[2]...)))
#usdkrw =
usdkrw.Date = Date.(usdkrw.timestamp)
usdkrw.open = Float64.(usdkrw.open)
usdkrw.high = Float64.(usdkrw.high)
usdkrw.low = Float64.(usdkrw.low)
usdkrw.close = Float64.(usdkrw.close);
plot(usdkrw, :Date, :open, title="USDKRW")
:- "set xlab font ',15' 'Date Time'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/USDKRW.svg")
plot(usdkrw, :timestamp)
:- "set title 'USDKRW'"
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/USDKRW_candle.svg")
FX Intraday
Again, intraday data is available for the FX pairs.
usdcadRaw = AlphaVantage.fx_intraday("USD", "CAD", datatype="csv");
usdcad = DataFrame(usdcadRaw[1])
usdcad = rename(usdcad, Symbol.(vcat(usdcadRaw[2]...)))
usdcad.timestamp = DateTime.(usdcad.timestamp, "yyyy-mm-dd HH:MM:SS")
usdcad.open = Float64.(usdcad.open);
plot(usdcad, :timestamp, :open, "", :roma; α =0.9)
:- "set title 'USDCAD'"
:- "set xlab font ',15' 'Date Time'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/USDCAD.svg")
Crypto
Now for digital currencies. The API follows the same style as traditional currencies and again has more digital currencies than you can shake a stick at. Again daily, weekly and monthly data is available plus a ‘health-index’ monitor that reports how healthy a cryptocurrency is based on different features.
ethRaw = AlphaVantage.digital_currency_daily("ETH", "USD", datatype="csv")
ethHealth = AlphaVantage.crypto_rating("ETH");
titleString = ethHealth["Crypto Rating (FCAS)"];
The health rating looks like that, four scores, a qualitative rating and some meta information. The price charts look like as you would expect.
eth = DataFrame(ethRaw[1])
eth = rename(eth, Symbol.(vcat(ethRaw[2]...)), makeunique=true)
eth[!,:timestamp] = Dates.Date.(eth[!,:timestamp])
eth[!,Symbol("open (USD)")] = Float64.(eth[!, Symbol("open (USD)")])
first(eth, 6)
timestamp | open (USD) | high (USD) | low (USD) | close (USD) | open (USD)_1 | high (USD)_1 | low (USD)_1 | close (USD)_1 | volume | market cap (USD) |
---|---|---|---|---|---|---|---|---|---|---|
2020-07-12 | 239.19 | 239.99 | 239.0 | 239.83 | 239.19 | 239.99 | 239.0 | 239.83 | 8263.12 | 8263.12 |
2020-07-11 | 241.27 | 241.67 | 237.54 | 239.19 | 241.27 | 241.67 | 237.54 | 239.19 | 294476.0 | 294476.0 |
2020-07-10 | 241.97 | 242.16 | 235.72 | 241.26 | 241.97 | 242.16 | 235.72 | 241.26 | 455025.0 | 455025.0 |
2020-07-09 | 246.94 | 247.9 | 237.88 | 241.98 | 246.94 | 247.9 | 237.88 | 241.98 | 647642.0 | 647642.0 |
2020-07-08 | 239.39 | 248.88 | 237.78 | 246.95 | 239.39 | 248.88 | 237.78 | 246.95 | 958186.0 | 958186.0 |
2020-07-07 | 241.6 | 243.77 | 234.4 | 239.39 | 241.6 | 243.77 | 234.4 | 239.39 | 600425.0 | 600425.0 |
plot(eth, :timestamp, Symbol("open (USD)"), "", :devon; lcol = "black",
α =0.952)
:- "set title 'Ethereum'" :-
:- "set xlab font ',15' 'Date'" "set ylab font ',15' 'Price'"
save(term = "svg size 650,450", output = "/results/Ethereum.svg")
Conclusion
As you can see it's pretty easy to explore financial data by using AlphaVantage and Gnuplot. So go grab yourself an API key, download these packages and see what you can do.
Find me on twitter as @LazarusAlon