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