Current section
Files
Jump to
Current section
Files
lib/alpa/models/snapshot.ex
defmodule Alpa.Models.Snapshot do
@moduledoc """
Market snapshot combining latest trade, quote, minute bar, daily bar, and previous daily bar.
"""
use TypedStruct
alias Alpa.Models.{Bar, Quote, Trade}
typedstruct do
field :symbol, String.t()
field :latest_trade, Trade.t()
field :latest_quote, Quote.t()
field :minute_bar, Bar.t()
field :daily_bar, Bar.t()
field :prev_daily_bar, Bar.t()
end
@doc """
Parse snapshot data from API response.
"""
@spec from_map(map(), String.t()) :: t()
def from_map(data, symbol) when is_map(data) do
%__MODULE__{
symbol: symbol,
latest_trade: parse_trade(data["latestTrade"], symbol),
latest_quote: parse_quote(data["latestQuote"], symbol),
minute_bar: parse_bar(data["minuteBar"], symbol),
daily_bar: parse_bar(data["dailyBar"], symbol),
prev_daily_bar: parse_bar(data["prevDailyBar"], symbol)
}
end
@doc """
Parse multiple snapshots from API response.
"""
@spec from_response(map()) :: %{String.t() => t()}
def from_response(%{"snapshots" => snapshots}) when is_map(snapshots) do
Map.new(snapshots, fn {symbol, data} ->
{symbol, from_map(data, symbol)}
end)
end
def from_response(data) when is_map(data) do
# The multi-snapshot API returns data directly as %{"AAPL" => %{...}, ...}
# Check if the values look like snapshot data (have "latestTrade" key)
if Enum.any?(data, fn {_k, v} -> is_map(v) and Map.has_key?(v, "latestTrade") end) do
Map.new(data, fn {symbol, snap_data} ->
{symbol, from_map(snap_data, symbol)}
end)
else
data
end
end
def from_response(data), do: data
defp parse_trade(nil, _symbol), do: nil
defp parse_trade(data, symbol), do: Trade.from_map(data, symbol)
defp parse_quote(nil, _symbol), do: nil
defp parse_quote(data, symbol), do: Quote.from_map(data, symbol)
defp parse_bar(nil, _symbol), do: nil
defp parse_bar(data, symbol), do: Bar.from_map(data, symbol)
end