AlphaVantage is a market data provider that is nice enough to provide free access to a wide variety of data. It is my goto financial data provider ( used here ) , because a) it’s free and b) there is an R package that accesses the API easily. However, there was no Julia package for AlphaVantage, so I saw a gap in the market.

After searching GitHub I found this repository that was two years out of date, but had the bare bones of functionality that I knew I would be able to build upon. I forked the project, brought it up to date with all the AlphaVantage functions and have now released it to the world in the Julia registry. You can easily install the package just like any other Julia package using Pkg.add("AlphaVantage").

This blog post will detail all the different function available and illustrate how you can pull the data, massage it into a nice format and plot using the typical Julia tools.

Available Functionality

  1. Stock data at both intraday, daily, weekly and monthly frequencies.
  2. Technical indicators for stocks.
  3. FX rates at both intraday, daily, weekly and monthly frequencies.
  4. Crypto currencies, again, at the intraday, daily, weekly and monthly time scales.

So jump into the section that interests you.

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 I’ve missed any or one isn’t working correctly, raise on issue on Github here.

These are the Julia packages I use in this blog post:

using AlphaVantage
using DataFrames
using DataFramesMeta
using Dates
using Plots

Plus we define some helper functions to convert between the raw data and Julia dataframes.

function raw_to_dataframe(rawData)
    df = DataFrame(rawData[1])
    dfNames = Symbol.(vcat(rawData[2]...))
    df = rename(df, dfNames)

    df.Date = Date.(df.timestamp)
    for x in (:open, :high, :low, :close, :adjusted_close, :dividend_amount)
        df[!, x] = Float64.(df[!, x])
    end 
    df.volume = Int64.(df.volume)
    return df
end

function intra_to_dataframe(rawData)
    df = DataFrame(rawData[1])
    dfNames = Symbol.(vcat(rawData[2]...))
    df = rename(df, dfNames)

    df.DateTime = DateTime.(df.timestamp, "yyyy-mm-dd HH:MM:SS")
    for x in (:open, :high, :low, :close)
        df[!, x] = Float64.(df[!, x])
    end 
    df.volume = Int64.(df.volume)
    return df
end

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.

tslaRaw = AlphaVantage.time_series_daily_adjusted("TSLA", outputsize="full", datatype="csv")
tsla = raw_to_dataframe(tslaRaw);
first(tsla, 5)

5 rows × 10 columns (omitted printing of 2 columns)

timestampopenhighlowcloseadjusted_closevolumedividend_amount
AnyFloat64Float64Float64Float64Float64Int64Float64
12020-06-29969.011010.0948.521009.351009.3588713560.0
22020-06-26994.78995.0954.87959.74959.7488549080.0
32020-06-25954.27985.98937.15985.98985.9892545490.0
42020-06-24994.111000.88953.141960.85960.85109595930.0
52020-06-23998.881012.0994.011001.781001.7863652710.0
plot(tsla.Date, tsla.open, label="Open", title="TSLA Daily")

svg

Here is the Tesla daily opening stock price.

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)
tslaIntraDay = @where(tslaIntra, :DateTime .> DateTime(today()-Day(1)))
subPlot = plot(tslaIntraDay.DateTime, tslaIntraDay.open, label="Open", title="TSLA Intraday $(today()-Day(1))")
allPlot = plot(tslaIntra.DateTime, tslaIntra.open, label="Open", title = "TSLA Intraday")
plot(allPlot, subPlot, layout=(1,2))

svg

Technical Indicators

AlphaVantage also provide a wide range of technical indicators, the most of which I don’t understand and will probably never use. But, they provide them, so I’ve written an interface for them. In this example I’m 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 = @where(rsiDF, :time .> DateTime(today() - Day(1)));
plot(rsiSub[!, :time], rsiSub[!, :RSI], title="TSLA")
hline!([30, 70], label=["Oversold", "Overbought"])

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"]
Dict{String,Any} with 11 entries:
  "Health Care"            => "-3.46%"
  "Financials"             => "-25.78%"
  "Consumer Discretionary" => "4.79%"
  "Materials"              => "-9.33%"
  "Consumer Staples"       => "-7.80%"
  "Energy"                 => "-38.38%"
  "Real Estate"            => "-11.37%"
  "Information Technology" => "12.06%"
  "Utilities"              => "-12.96%"
  "Communication Services" => "-2.26%"
  "Industrials"            => "-16.05%"

Great year for IT, not so great for energy.

Forex

Moving onto 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, eurgbp.open, label="open", title="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.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, usdkrw.open, label="open", title="USDKRW")

svg

Although I’m not sure exactly what they are providing here, be it a spot price or a 1 month forward that is more typical for NDFs.

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, usdcad.open, label="Open", title="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)"]
Dict{String,Any} with 9 entries:
  "7. utility score"         => "972"
  "9. timezone"              => "UTC"
  "1. symbol"                => "ETH"
  "2. name"                  => "Ethereum"
  "4. fcas score"            => "957"
  "5. developer score"       => "964"
  "6. market maturity score" => "843"
  "8. last refreshed"        => "2020-06-29 00:00:00"
  "3. fcas rating"           => "Superb"

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.Date = Date.(eth.timestamp)
eth.Open = Float64.(eth[!, Symbol("open (USD)")])

plot(eth.Date, eth.Open, label="Open", title = "Ethereum")

svg

Conclusion

If you’ve ever wanted to explore financial timeseries you can’t really do much better than using AlphaVantage. So go grab yourself an API key, download this package and see if you can work out what Hilbert transform, dominant cycle phase (HT_DCPHASE in the package) represents for a stock!