#!/usr/bin/env sh ## getquote v0.5 ## (c) 2024 microsounds , GPLv3+ # scrapes Yahoo! Finance API for stock, crypto and ETF price quotes # outputs as ledger-cli commodity price history format in US Dollars # format: 'P YYYY/MM/DD HH:MM:SS SYMBOL $USD_PRICE' ## usage: getquote [-s] [SYMBOL(s)...] ## typical usage: ledger -f ledger.dat commodities | xargs getquote >> price.db [ ! -z "$1" ] || { cat "$0" | grep '^##' | sed 's/^## //g' 1>&2 exit 1 } # options case "$1" in -s) SHORT=1; shift # condensed output for use with spreadsheets esac # 06/2023: yahoo discontinued batch quote json endpoint, one query per symbol # 01/2024: yahoo discontinued options quote endpoint, lost postmarket data TIME_NOW="$(date '+%s')" UA_STR='Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36' QUOTE_API="https://query1.finance.yahoo.com/v8/finance/chart" JQ_SCRIPT=".chart.result[].meta \ | [.regularMarketPrice,.regularMarketTime] | join(\" \")" for SYM in "$@"; do wget -q -U "$UA_STR" -O - "${QUOTE_API}/${SYM}" \ | jq -r "$JQ_SCRIPT" \ | while read -r reg_price reg_time; do # quotes are probably time delayed by 15 minutes # use current time if market data is stale, eg. closed over 15 min [ $((TIME_NOW - reg_time)) -gt $((60 * 15)) ] && reg_time="$TIME_NOW" [ ! -z "$SHORT" ] && echo "$reg_price" && continue printf "%s\r" "Fetching $SYM..." 1>&2 printf 'P %s %s %s\n' \ "$(date -d "1970-01-01 UTC $reg_time seconds" '+%Y/%-m/%-d %H:%M:%S')" \ "$(echo $SYM | tr 'a-z' 'A-Z')" \ "\$$reg_price" done done