476
stocks.sh
Executable file
476
stocks.sh
Executable file
@@ -0,0 +1,476 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# MIT License
|
||||
# forked from https://github.com/appatalks/ticker.sh
|
||||
# original script https://github.com/pstadler/ticker.sh
|
||||
|
||||
VERSION="v1.0"
|
||||
|
||||
### TODO
|
||||
# Verif stocks in $@
|
||||
# Locale compliant
|
||||
# Localization
|
||||
|
||||
|
||||
### API
|
||||
: ${TMPDIR:=/tmp}
|
||||
SESSION_DIR="${TMPDIR%/}/ticker.sh-$(whoami)"
|
||||
COOKIE_FILE="${SESSION_DIR}/cookies.txt"
|
||||
API_ENDPOINT="https://query1.finance.yahoo.com/v8/finance/chart/"
|
||||
API_SUFFIX="?interval=1d"
|
||||
|
||||
### Variables
|
||||
ScriptArgs=( "$@" )
|
||||
ScriptPath="$(readlink -f "$0")" # /Users/user/Documents/Scripts/stocks/crypto.sh
|
||||
ScriptWorkDir="$(dirname "$ScriptPath")" # /Users/user/Documents/Scripts/stocks
|
||||
|
||||
|
||||
####### Configurations ######
|
||||
|
||||
#NO_COLOR=1
|
||||
|
||||
LANG=C
|
||||
LC_NUMERIC=C
|
||||
|
||||
# Check if NO_COLOR is set to disable colorization
|
||||
if [ -z "$NO_COLOR" ]; then
|
||||
: "${COLOR_GREEN:=$'\e[32m'}"
|
||||
: "${COLOR_GREEN_BOLD:=$'\e[1;32m'}"
|
||||
: "${COLOR_RED:=$'\e[31m'}"
|
||||
: "${COLOR_RED_BOLD:=$'\e[1;31m'}"
|
||||
: "${COLOR_YELLOW=$'\e[33m'}"
|
||||
: "${COLOR_YELLOW_BOLD:=$'\e[1;33m'}"
|
||||
: "${COLOR_SILVER=$'\e[37m'}"
|
||||
: "${COLOR_LIGHT_GREY=$'\e[249m'}"
|
||||
: "${COLOR_BRIGHT_PURPLE=$'\e[35;1m'}"
|
||||
: "${BOLD:=$'\e[1m'}"
|
||||
: "${ITALIC:=$'\e[3m'}"
|
||||
: "${COLOR_RESET:=$'\e[00m'}"
|
||||
else
|
||||
: "${BOLD:=$'\e[1m'}"
|
||||
: "${COLOR_RESET:=$'\e[00m'}"
|
||||
: "${ITALIC:=$'\e[3m'}"
|
||||
fi
|
||||
|
||||
|
||||
# Help
|
||||
Help() {
|
||||
clear
|
||||
echo -e "\n${COLOR_GREEN_BOLD}Bash Stocks $VERSION${COLOR_RESET}\n"
|
||||
echo "Syntax: stocks.sh [<stock>]"
|
||||
echo
|
||||
echo "Examples: stocks.sh AAPL ORA.PA AUB.PA"
|
||||
echo " stocks.sh (need ~/.stocks.yaml file)"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo "-h Print this Help."
|
||||
echo
|
||||
echo "Requires jq and yq installed"
|
||||
echo " -https://stedolan.github.io/jq/"
|
||||
echo " -https://github.com/kislyuk/yq"
|
||||
}
|
||||
|
||||
### Parse options
|
||||
|
||||
while getopts "h" opt; do
|
||||
case ${opt} in
|
||||
h|*) Help
|
||||
Help
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND -1))
|
||||
|
||||
|
||||
### Config file
|
||||
stocks_list=$HOME/.stocks.yaml
|
||||
#json_file="/tmp/purchased.json"
|
||||
json_file="$ScriptWorkDir/purchased.json"
|
||||
#json_file=""
|
||||
|
||||
####### /Configurations ######
|
||||
|
||||
|
||||
### Requierements
|
||||
if ! $(type jq >/dev/null 2>&1); then
|
||||
echo -e "${COLOR_RED}'jq' is not in the PATH. (See: https://stedolan.github.io/jq/)${COLOR_RESET}"
|
||||
exit 1
|
||||
fi
|
||||
if ! $(type yq >/dev/null 2>&1); then
|
||||
echo -e "${COLOR_RED}'yq' is not in the PATH. (See: https://github.com/kislyuk/yq)${COLOR_RESET}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat < /dev/null > /dev/tcp/1.1.1.1/53
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "\n${COLOR_RED}No Internet connection !${COLOR_RESET}"
|
||||
echo -e "Exit !"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
####### Functions ######
|
||||
|
||||
symbol_currency() {
|
||||
case $currency in
|
||||
EUR)
|
||||
echo -n "€"
|
||||
;;
|
||||
USD)
|
||||
echo -n "$"
|
||||
;;
|
||||
GBP)
|
||||
echo -n "£"
|
||||
;;
|
||||
JPY)
|
||||
echo -n "¥"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if number is positive (or 0) or negative
|
||||
CheckSign() {
|
||||
local n="$1" # Capture the number passed as a parameter.
|
||||
|
||||
if [ $(echo "$n < 0" | bc -l) -eq 1 ] ; then
|
||||
#printf "%+17.13f : %s\n" "$n" "negative"
|
||||
p="-"
|
||||
else
|
||||
#printf "%+17.13f : %s\n" "$n" "positive or zero"
|
||||
p="+"
|
||||
fi
|
||||
echo "$p"
|
||||
}
|
||||
|
||||
[ ! -d "$SESSION_DIR" ] && mkdir -m 700 "$SESSION_DIR"
|
||||
|
||||
|
||||
preflight () {
|
||||
curl --silent --output /dev/null --cookie-jar "$COOKIE_FILE" "https://finance.yahoo.com" \
|
||||
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
|
||||
}
|
||||
|
||||
fetch_chart () {
|
||||
local symbol=$1
|
||||
local url="${API_ENDPOINT}${symbol}${API_SUFFIX}"
|
||||
curl --silent -b "$COOKIE_FILE" "$url"
|
||||
}
|
||||
|
||||
[ ! -f "$COOKIE_FILE" ] && preflight
|
||||
|
||||
|
||||
####### Start Display ######
|
||||
|
||||
echo -e "${COLOR_GREEN_BOLD}Bash Stocks${COLOR_RESET} $VERSION"
|
||||
echo -e "Using Yahoo Finance API ($API_ENDPOINT)\n"
|
||||
|
||||
|
||||
### Read quotes from arguments or from~/.stocks.yaml config file
|
||||
SYMBOLS=()
|
||||
|
||||
# from arguments
|
||||
if [ -n "$ScriptArgs" ]; then
|
||||
|
||||
REGEXP='^[a-zA-Z0-9.,_ ]+$'
|
||||
q="$@"
|
||||
if [[ "$q" =~ $REGEXP ]]; then
|
||||
q=${q//,/\ }
|
||||
q=${q//_/\ }
|
||||
|
||||
SYMBOLS+=($q)
|
||||
else
|
||||
Help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: <<'END_COMMENT'
|
||||
|
||||
# Check if quotes passed as argument really exist
|
||||
|
||||
for val in ${!SYMBOLS[@]}
|
||||
do
|
||||
k="${SYMBOLS[$val]}"
|
||||
|
||||
#echo $val # index
|
||||
#echo $k # value
|
||||
|
||||
if [[ ! "$list_coins" == *"$k"* ]]; then
|
||||
echo -e "${COLOR_RED}$k is not a crypto. Remove it !${COLOR_RESET}"
|
||||
unset SYMBOLS[$val]
|
||||
fi
|
||||
done
|
||||
|
||||
# Recreate the array, because the gaps have to disappear
|
||||
SYMBOLS=("${SYMBOLS[@]}")
|
||||
END_COMMENT
|
||||
|
||||
echo -e "${COLOR_GREEN}Found ${#SYMBOLS[@]} stocks to display: ${SYMBOLS[@]} ...${COLOR_RESET}"
|
||||
|
||||
# from ~/.stocks.yaml config file
|
||||
else
|
||||
|
||||
if [ -f "$stocks_list" ]; then
|
||||
sl=$(cat $stocks_list)
|
||||
[ $? -eq 0 ] && echo -e "${COLOR_GREEN}Reading $stocks_list ...${COLOR_RESET}" || echo -e "${COLOR_RED}Error while reading $stocks_list ...${COLOR_RESET}"
|
||||
|
||||
a=$(yq '.watchlist[]' <<< $sl)
|
||||
SYMBOLS+=(${a})
|
||||
[ $? -eq 0 ] && echo -e "${COLOR_GREEN}Found ${#SYMBOLS[@]} stocks to display: ${SYMBOLS[@]} ...${COLOR_RESET}" || echo -e "${COLOR_RED}No coins to display...${COLOR_RESET}"
|
||||
|
||||
b=$(yq '.lot' <<< $sl)
|
||||
u=$((yq '.lots[] | select(.quantity != 0) | .symbol' | tr '\n' ' ') <<< $sl)
|
||||
purchased=(${u})
|
||||
[ $? -eq 0 ] && echo -e "${COLOR_GREEN}Found ${#purchased[@]} quotes purchased: ${purchased[@]} ...${COLOR_RESET}" || echo -e "${COLOR_RED}Fail to load quotes list purchased...${COLOR_COLOR_RESET}"
|
||||
|
||||
# Check that purchased's stocks are in display list
|
||||
for val in ${!purchased[@]}
|
||||
do
|
||||
x="${purchased[$val]}"
|
||||
if [[ " ${SYMBOLS[*]} " != *"$x"* ]]; then
|
||||
SYMBOLS+=(${x})
|
||||
echo -e "${COLOR_RED}$x is not in stocks's list to display. We add it !${COLOR_GREEN}"
|
||||
fi
|
||||
done
|
||||
[ $? -eq 0 ] && echo -e "${COLOR_GREEN}Found ${#SYMBOLS[@]} stocks to display: ${SYMBOLS[@]} ...${COLOR_RESET}" || echo -e "${COLOR_RED}No coins to display...${COLOR_RESET}"
|
||||
|
||||
else
|
||||
echo -e "${COLOR_RED}$stocks_list not present !${COLOR_RESET}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#echo "${SYMBOLS[@]}"
|
||||
#echo "${purchased[@]}"
|
||||
|
||||
: <<'END_COMMENT'
|
||||
while IFS= read -r obj; do
|
||||
#echo "$obj"
|
||||
stock=${obj:2}
|
||||
#echo "$stock"
|
||||
SYMBOLS+=("$stock")
|
||||
done < <(echo "$a")
|
||||
[ $status -eq 0 ] && echo -e "${COLOR_GREEN}Found ${#SYMBOLS[@]} stocks to display: ${SYMBOLS[@]} ...${COLOR_RESET}" || echo -e "${COLOR_RED}No coins to display...${COLOR_RESET}"
|
||||
END_COMMENT
|
||||
if [ -z "$SYMBOLS" ]; then
|
||||
echo "Usage: ./crypto.sh"
|
||||
echo " - add quotes to ~/.stocks.yaml file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
: <<'END_COMMENT'
|
||||
### Parse options
|
||||
|
||||
while getopts "g" opt; do
|
||||
case ${opt} in
|
||||
h )
|
||||
echo "Usage: ./ticker.sh [-g] AAPL GOOG ORA.PA"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND -1))
|
||||
|
||||
|
||||
|
||||
END_COMMENT
|
||||
|
||||
|
||||
# volume %11s
|
||||
echo
|
||||
printf "%s%-22s %-8s %9s %8s %8s %9s %9s %11s %9s %9s %18s %18s %s \n" \
|
||||
"${BOLD}" "ShortName" "Symbol" \
|
||||
"Current" "Change" "Percent" \
|
||||
"Day High" "Day Low" "Volume" \
|
||||
"52w +" "52w -" "Last Date" "Timezone" \
|
||||
"${COLOR_RESET}"
|
||||
|
||||
# Sort arrays (lists of quotes / purchased)
|
||||
|
||||
IFS=$'\n'
|
||||
SYMBOLS=($(sort <<<"${SYMBOLS[*]}"))
|
||||
purchased=($(sort <<<"${purchased[*]}"))
|
||||
unset IFS
|
||||
|
||||
|
||||
### Create JSON purchased quotes
|
||||
|
||||
# Create an initial block
|
||||
jq -n '{"quotes":[]}' > "${json_file}"
|
||||
ii=1
|
||||
|
||||
|
||||
# Initialize an array to hold background process IDs (avec les PID activés => affichage dans le désordre (au fil de l'eau))
|
||||
pids=()
|
||||
|
||||
echo "quotes: ${#SYMBOLS[@]} - ${SYMBOLS[@]}"
|
||||
echo "purchased: ${#purchased[@]} - ${purchased[@]}"
|
||||
|
||||
|
||||
for symbol in "${SYMBOLS[@]}"; do
|
||||
(
|
||||
# Running in subshell
|
||||
|
||||
results=$(fetch_chart "$symbol")
|
||||
|
||||
regularMarketTime=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketTime')
|
||||
#rdate -d @$regularMarketTime +"%c"
|
||||
rmt=$(LC_ALL=fr_FR.UTF-8 date -d @$regularMarketTime +"%d/%m/%y %H:%M:%S" 2>/dev/null || LC_ALL=fr_FR.UTF-8 date -r $regularMarketTime +"%d/%m/%y %H:%M:%S")
|
||||
|
||||
exchangeTimezoneName=$(echo "$results" | jq -r '.chart.result[0].meta.exchangeTimezoneName')
|
||||
fiftyTwoWeekHigh=$(echo "$results" | jq -r '.chart.result[0].meta.fiftyTwoWeekHigh')
|
||||
fiftyTwoWeekLow=$(echo "$results" | jq -r '.chart.result[0].meta.fiftyTwoWeekLow')
|
||||
regularMarketDayHigh=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketDayHigh')
|
||||
regularMarketDayLow=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketDayLow')
|
||||
regularMarketVolume=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketVolume')
|
||||
longName=$(echo "$results" | jq -r '.chart.result[0].meta.longName')
|
||||
shortName=$(echo "$results" | jq -r '.chart.result[0].meta.shortName')
|
||||
|
||||
currentPrice=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketPrice')
|
||||
previousClose=$(echo "$results" | jq -r '.chart.result[0].meta.chartPreviousClose')
|
||||
currency=$(echo "$results" | jq -r '.chart.result[0].meta.currency')
|
||||
symb=$(symbol_currency $currency)
|
||||
symbol=$(echo "$results" | jq -r '.chart.result[0].meta.symbol')
|
||||
|
||||
[ "$previousClose" = "null" ] && previousClose="1.0"
|
||||
|
||||
priceChange=$(awk -v currentPrice="$currentPrice" -v previousClose="$previousClose" 'BEGIN {printf "%.2f", currentPrice - previousClose}')
|
||||
percentChange=$(awk -v currentPrice="$currentPrice" -v previousClose="$previousClose" 'BEGIN {printf "%.2f", ((currentPrice - previousClose) / previousClose) * 100}')
|
||||
|
||||
open=$(echo "$results" | jq -r '.chart.result[0].indicators.quote' | jq -r '.[].open[0]')
|
||||
|
||||
#firstTradeDate=$(echo "$results" | jq -r '.chart.result[0].meta.firstTradeDate')
|
||||
#ftd==$(LC_ALL=fr_FR.UTF-8 date -d @$firstTradeDate +"%c" 2>/dev/null || LC_ALL=fr_FR.UTF-8 date -r $ts +"%c")
|
||||
#volume=$(echo "$results" | jq -r '.chart.result[0].indicators.quote' | jq -r '.[].volume[0]')
|
||||
#high=$(echo "$results" | jq -r '.chart.result[0].indicators.quote' | jq -r '.[].high[0]')
|
||||
#close=$(echo "$results" | jq -r '.chart.result[0].indicators.quote' | jq -r '.[].close[0]')
|
||||
|
||||
if [[ " ${purchased[*]} " == *"$symbol"* ]]; then
|
||||
|
||||
|
||||
# Create a temporary JSON file for purchased quotes because requests arrive as they come in (not in order)
|
||||
# https://www.codegix.com/use-jq-to-create-a-dynamic-json-data-in-bash/
|
||||
json_data=$(jq \
|
||||
--arg symbol "$symbol" \
|
||||
--arg price "$currentPrice" \
|
||||
--arg volume "$regularMarketVolume" \
|
||||
--arg last "$regularMarketTime" \
|
||||
--arg symb "$symb" \
|
||||
--arg percent "$percentChange" \
|
||||
--argjson value "$ii" '.quotes += [{ "symbol": $symbol, "price": $price, "volume": $volume, "last": $last, "symb": $symb, "percent": $percent }]' "${json_file}")
|
||||
|
||||
echo "${json_data}" > "${json_file}"
|
||||
|
||||
((ii++))
|
||||
|
||||
: <<'END_COMMENT'
|
||||
|
||||
# Check quotes we have (from .stocks.yaml)
|
||||
z=$(echo "$sl" | yq '.lots[] | select(.symbol == "'${symbol}'")')
|
||||
q=$(echo "$z" | yq '.quantity')
|
||||
uc=$(echo "$z" | yq '.unit_cost')
|
||||
|
||||
purchase_cost=$(echo "$q * $uc" | bc -l)
|
||||
valuations=$(echo "$q * $currentPrice" | bc -l)
|
||||
profit=$(echo "$valuations - $purchase_cost" | bc -l)
|
||||
performance=$(echo "($valuations / $purchase_cost - 1) * 100" | bc -l)
|
||||
#performance=$(round $performance 2)
|
||||
|
||||
echo "$q - $uc - $purchase_cost - $valuations - $profit - $performance"
|
||||
END_COMMENT
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
COLOR_pri=$([ $(CheckSign "$priceChange") == "-" ] && echo ${COLOR_RED} || echo ${COLOR_GREEN})
|
||||
COLOR_per=$([ $(CheckSign "$percentChange") == "-" ] && echo ${COLOR_RED} || echo ${COLOR_GREEN})
|
||||
|
||||
if [ -z "$NO_COLOR" ]; then
|
||||
printf "%s%-22s %-8s %8.2f%s%s %s%7.2f%s%s %s%7.2f%%%s %s%8.2f%s %8.2f%s %11s %8.2f%s %8.2f%s %18s %18s %s\n" \
|
||||
"${COLOR_YELLOW_BOLD}" "$shortName" "$symbol" \
|
||||
"$currentPrice" "$symb" "${COLOR_RESET}" "${COLOR_pri}" "$priceChange" "$symb" "${COLOR_RESET}" "${COLOR_per}" "$percentChange" "${COLOR_RESET}" \
|
||||
"${COLOR_YELLOW_BOLD}" "$regularMarketDayHigh" "$symb" "$regularMarketDayLow" "$symb" "$regularMarketVolume" \
|
||||
"$fiftyTwoWeekHigh" "$symb" "$fiftyTwoWeekLow" "$symb" "$rmt" "$exchangeTimezoneName" "${COLOR_RESET}"\
|
||||
|
||||
else
|
||||
printf "%-22s %-8s %8.2f%s %7.2f%s %7.2f%% %8.2f%s %8.2f%s %11s %8.2f%s %8.2f%s %18s %18s\n" \
|
||||
"$shortName" "$symbol" \
|
||||
"$currentPrice" "$symb" "$priceChange" "$symb" "$percentChange" \
|
||||
"$regularMarketDayHigh" "$symb" "$regularMarketDayLow" "$symb" "$regularMarketVolume" \
|
||||
"$fiftyTwoWeekHigh" "$symb" "$fiftyTwoWeekLow" "$symb" "$rmt" "$exchangeTimezoneName"
|
||||
fi
|
||||
|
||||
) #&
|
||||
|
||||
# Stack PIDs
|
||||
pids+=($!)
|
||||
|
||||
done
|
||||
|
||||
# Wait for all background processes to finish
|
||||
for pid in "${pids[@]}"; do
|
||||
wait "$pid"
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "quotes: ${#SYMBOLS[@]} - ${SYMBOLS[@]}"
|
||||
echo "purchased: ${#purchased[@]} - ${purchased[@]}"
|
||||
#cat $json_file
|
||||
|
||||
if [ ${#purchased[@]} -gt 0 ]; then
|
||||
|
||||
echo
|
||||
echo -e "${COLOR_GREEN}Displaying purchased quotes ...${COLOR_RESET}"
|
||||
echo
|
||||
|
||||
quotes="$(cat $json_file)"
|
||||
counter=0
|
||||
|
||||
printf "%s%-8s %13s %10s %9s %11s %16s %13s %13s %13s %11s %18s %s\n" \
|
||||
"${BOLD}" "Symbol" "Percent" "Current" "Quantity" "Unit cost" "Purchase cost" "Valuations" "Profit" "Performance" "Volume" "Last quote" "${COLOR_RESET}"
|
||||
|
||||
while [ "$counter" -lt "${#purchased[@]}" ]; do
|
||||
|
||||
purchase="${purchased[$counter]}"
|
||||
|
||||
s=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.symbol)') # Symbol
|
||||
p=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.price)') # Price
|
||||
v=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.volume)') # Volume
|
||||
l=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.last)') # Last quote
|
||||
rmt=$(LC_ALL=fr_FR.UTF-8 date -d @$l +"%d/%m/%y %H:%M:%S" 2>/dev/null || LC_ALL=fr_FR.UTF-8 date -r $l +"%d/%m/%y %H:%M:%S")
|
||||
#echo $l # 1736526916
|
||||
#rmt=$(LC_ALL=fr_FR.UTF-8 date -d "@$l" +"%c" 2>/dev/null || LC_ALL=fr_FR.UTF-8 date -r "$l" +"%c")
|
||||
|
||||
sy=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.symb)') # Symb (€/$/£)
|
||||
pc=$(echo "$quotes" | jq -r '.quotes | .[] | select(.symbol == "'${purchase}'") | (.percent)') # Percent change
|
||||
|
||||
z=$(echo "$sl" | yq '.lots[] | select(.symbol == "'${purchase}'")')
|
||||
q=$(echo "$z" | yq '.quantity')
|
||||
uc=$(echo "$z" | yq '.unit_cost')
|
||||
|
||||
purchase_cost=$(echo "$q * $uc" | bc -l)
|
||||
valuations=$(echo "$q * $p" | bc -l)
|
||||
profit=$(echo "$valuations - $purchase_cost" | bc -l)
|
||||
performance=$(echo "($valuations / $purchase_cost - 1) * 100" | bc -l)
|
||||
#performance=$(round $performance 2)
|
||||
|
||||
COLOR_performance=$([ $(CheckSign "$performance") == "-" ] && echo ${COLOR_RED} || echo ${COLOR_GREEN})
|
||||
|
||||
#echo "$s - $p - $v - $rmt - $q - $uc - $purchase_cost - $valuations - $profit - $performance"
|
||||
#echo "$purchase_cost - $valuations - $profit - $performance"
|
||||
|
||||
# symbol(s) percent (pc) price(p) quantity(q) unit_cost(uc) purchase_cost valuations profit performance volume(v) last_quote(l)
|
||||
|
||||
printf "%s%-8s %12.2f%% %9.2f%s %9d %10.2f%s %15.2f%s %12.2f%s %12.2f%s %12.2f%% %11d %18s %s\n" \
|
||||
"${COLOR_performance}" "$s" "$pc" "$p" "$sy" "$q" "$uc" "$sy" "$purchase_cost" "$sy" "$valuations" "$sy" "$profit" "$sy" "$performance" "$v" "$rmt" "${COLOR_RESET}"
|
||||
|
||||
|
||||
((++counter))
|
||||
done
|
||||
fi
|
||||
|
||||
echo -e "\n${ITALIC}Script with ${#SYMBOLS[@]} requests to Yahoo Finance API finished in $SECONDS seconds.${COLOR_RESET}"
|
||||
94
ticker.sh
94
ticker.sh
@@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
LANG=C
|
||||
LC_NUMERIC=C
|
||||
|
||||
SYMBOLS=("$@")
|
||||
|
||||
if ! $(type jq > /dev/null 2>&1); then
|
||||
echo "'jq' is not in the PATH. (See: https://stedolan.github.io/jq/)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$SYMBOLS" ]; then
|
||||
echo "Usage: ./ticker.sh AAPL MSFT GOOG BTC-USD"
|
||||
exit
|
||||
fi
|
||||
|
||||
FIELDS=(symbol marketState regularMarketPrice regularMarketChange regularMarketChangePercent regularMarketVolume regularMarketPreviousClose \
|
||||
preMarketPrice preMarketChange preMarketChangePercent postMarketPrice postMarketChange postMarketChangePercent \
|
||||
shortName longName fullExchangeName)
|
||||
#API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US®ion=US&corsDomain=finance.yahoo.com"
|
||||
API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=fr-FR®ion=FR&corsDomain=finance.yahoo.com"
|
||||
|
||||
if [ -z "$NO_COLOR" ]; then
|
||||
: "${COLOR_BOLD:=\e[1;37m}"
|
||||
: "${COLOR_GREEN:=\e[32m}"
|
||||
: "${COLOR_RED:=\e[31m}"
|
||||
: "${COLOR_RESET:=\e[00m}"
|
||||
fi
|
||||
|
||||
symbols=$(IFS=,; echo "${SYMBOLS[*]}")
|
||||
echo "$symbols"
|
||||
|
||||
fields=$(IFS=,; echo "${FIELDS[*]}")
|
||||
|
||||
results=$(curl --silent "$API_ENDPOINT&fields=$fields&symbols=$symbols" | jq '.quoteResponse .result')
|
||||
#echo "$results"
|
||||
|
||||
query () {
|
||||
echo $results | jq -r ".[] | select(.symbol == \"$1\") | .$2"
|
||||
}
|
||||
|
||||
for symbol in $(IFS=' '; echo "${SYMBOLS[*]}" | tr '[:lower:]' '[:upper:]'); do
|
||||
marketState="$(query $symbol 'marketState')"
|
||||
|
||||
if [ -z $marketState ]; then
|
||||
printf 'No results for symbol "%s"\n' $symbol
|
||||
continue
|
||||
fi
|
||||
|
||||
preMarketChange="$(query $symbol 'preMarketChange')"
|
||||
postMarketChange="$(query $symbol 'postMarketChange')"
|
||||
|
||||
longName="$(query $symbol 'longName')"
|
||||
#regularMarketPreviousClose="$(query $symbol 'regularMarketPreviousClose')"
|
||||
|
||||
if [ $marketState == "PRE" ] \
|
||||
&& [ $preMarketChange != "0" ] \
|
||||
&& [ $preMarketChange != "null" ]; then
|
||||
nonRegularMarketSign='*'
|
||||
price=$(query $symbol 'preMarketPrice')
|
||||
diff=$preMarketChange
|
||||
percent=$(query $symbol 'preMarketChangePercent')
|
||||
elif [ $marketState != "REGULAR" ] \
|
||||
&& [ $postMarketChange != "0" ] \
|
||||
&& [ $postMarketChange != "null" ]; then
|
||||
nonRegularMarketSign='*'
|
||||
price=$(query $symbol 'postMarketPrice')
|
||||
diff=$postMarketChange
|
||||
percent=$(query $symbol 'postMarketChangePercent')
|
||||
else
|
||||
nonRegularMarketSign=''
|
||||
price=$(query $symbol 'regularMarketPrice')
|
||||
diff=$(query $symbol 'regularMarketChange')
|
||||
percent=$(query $symbol 'regularMarketChangePercent')
|
||||
previous=$(query $symbol 'regularMarketPreviousClose')
|
||||
fi
|
||||
|
||||
if [ "$diff" == "0" ] || [ "$diff" == "0.0" ]; then
|
||||
color=
|
||||
elif ( echo "$diff" | grep -q ^- ); then
|
||||
color=$COLOR_RED
|
||||
else
|
||||
color=$COLOR_GREEN
|
||||
fi
|
||||
|
||||
if [ "$price" != "null" ]; then
|
||||
#printf "%-10s$COLOR_BOLD%8.2f$COLOR_RESET" $symbol $price
|
||||
printf "%-10s%-35s$COLOR_BOLD%8.2f$COLOR_RESET" $symbol "$longName" $price
|
||||
printf "$color%10.2f%12s$COLOR_RESET%+10s" $diff $(printf "(%.2f%%)" $percent) $previous
|
||||
printf " %s\n" "$nonRegularMarketSign"
|
||||
fi
|
||||
done
|
||||
Reference in New Issue
Block a user