Plotting Stock Price with Yfinance
Mix.install([
{:yfinance, "~> 0.5.0"},
{:kino_vega_lite, "~> 0.1.10"},
{:kino, "~> 0.12.0"}
])
Introduction
Yahoo! Finance® is a great place to download financial data like stock ticker prices. While they don’t offer an API from which you can download this data, there is a Python library that makes the same calls as their web app so that you can fetch the time series data. This library was written to allow readers of Elixir For Finance to collect, analyze and visualize economic data from Yahoo! Finance®, but it can be used outside the context of the book.
To learn how you can analyze and visualize the financial markets using Livebook, Explorer, Scholar and Nx, be sure to pick up a copy of our book:

Get Historical Data
To get historical data for a stock from Yahoo! Finance®, you can use the Yfinance.Ticker module and pass in the date range for which you are interested in:
{:ok, data_frame} =
Yfinance.Ticker.history(
"aapl",
Date.shift(Date.utc_today(), month: -36),
Date.utc_today()
)
Now that you have the time series price data in an Explorer.DataFrame struct, you can render the tabular data in Livebook using Kino.DataTable:
Kino.DataTable.new(data_frame)
Lastly, you can plot the time series data using VegaLite:
alias VegaLite, as: Vl
Vl.new(width: 700, height: 400, title: "Apple Stock Price (6 Months)")
|> Vl.data_from_values(data_frame)
|> Vl.mark(:line)
|> Vl.encode_field(:x, "date", type: :temporal, title: "Date")
|> Vl.encode_field(:y, "close", type: :quantitative, title: "Close Price ($)")
You can even plot a candle stick chart using VegaLite and the data that you retrieved:
import Explorer.DataFrame
{:ok, data_frame} =
Yfinance.Ticker.history(
"aapl",
Date.shift(Date.utc_today(), month: -4),
Date.utc_today()
)
# Add color column for candlestick
candle_stick_data_frame =
Explorer.DataFrame.mutate(data_frame,
color: Explorer.Series.less(col("close"), col("open"))
)
open_close =
Vl.new()
|> Vl.mark(:rule, size: 1)
|> Vl.encode_field(:y, "low", type: :quantitative, scale: [zero: false], title: "Price")
|> Vl.encode_field(:y2, "high")
|> Vl.encode_field(:color, "color",
type: :nominal,
scale: [domain: [true, false], range: ["#e45756", "#54a24b"]],
legend: nil
)
high_low =
Vl.new()
|> Vl.mark(:bar, size: 3)
|> Vl.encode_field(:y, "open", type: :quantitative)
|> Vl.encode_field(:y2, "close")
|> Vl.encode_field(:color, "color",
type: :nominal,
scale: [domain: [true, false], range: ["#e45756", "#54a24b"]],
legend: nil
)
Vl.new(width: 700, height: 400, title: "AAPL Candlestick Chart (last 4 months)")
|> Vl.data_from_values(candle_stick_data_frame)
|> Vl.encode_field(:x, "date", type: :temporal, title: "Date")
|> Vl.layers([open_close, high_low])