175 lines
4.1 KiB
Bash
Executable File
175 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
|
export LC_ALL=C
|
|
export POSIXLY_CORRECT=yes
|
|
|
|
printUsage() {
|
|
cat <<-EOF
|
|
Usage: $(basename "$0") [-h|--help] [FILTER] [COMMAND] [LOG [LOG2 [...]]
|
|
COMMAND:
|
|
list-tick list all tickers mentioned in the logs
|
|
profit final product of all entries (negative for a net loss)
|
|
pos currently held positions ordered asc. by value
|
|
last-price last
|
|
hist-ord histogram of transactions grouped by tickers
|
|
graph-pos graph positions for each ticker
|
|
[ommited] entries are echoed according to the provided filters (if any)
|
|
|
|
FILTER:
|
|
-a DATETIME only records AFTER (exclusive) this date are considered
|
|
-b DATETIME only records BEFORE (exclusive) this date are considered
|
|
format: YYYY-MM-DD HH:MM:SS or in POSIX: %Y-%m-%d %H:%M:%S
|
|
-t TICKER count records for this TICKER, can be repeated
|
|
-w WIDTH sets the width (in columns) of the longest line for commands
|
|
hist-ord - if ommited, one block = one transaction
|
|
graph-pos - if ommited, one block = 1000 units of currency
|
|
|
|
Note: When printing blocks of the graph, division products are floored
|
|
(rounded towards zero). So for \`graph-pos -w 6\` with 1234 (equal
|
|
to 6 blocks) as the maximum value, 1233.99 will be shown as #####.
|
|
|
|
Format:
|
|
DATUM A CAS;TICKER;TYP TRANSAKCE;JEDNOTKOVA CENA;MENA;OBJEM;ID
|
|
|
|
Exit codes:
|
|
0 Success.
|
|
1 Invalid date provided for the -a or -b filter.
|
|
2 Duplicated parameter.
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
ARG_DATE_AFTER="0000-01-01 00:00:00"
|
|
ARG_DATE_BEFORE="9999-12-31 23:59:59"
|
|
ARG_TICKER=""
|
|
ARG_WIDTH="0"
|
|
ARG_COMMAND="echo"
|
|
# needs spaces around all quotes
|
|
ACCEPTED_COMMANDS=" list-tick profit pos last-price hist-ord graph-pos echo "
|
|
|
|
# validateDateFormat (date)
|
|
# Returns 0 if the provided string follows YYYY-MM-DD HH:MM:SS.
|
|
# Note: This is a veeeeeeeeeeery basic check, allows e. g. "2020-12-24 15"
|
|
function validateDateFormat {
|
|
# accepts 60 for leap seconds
|
|
awkOut="$(echo "$1" | awk -v FS='[-: ]' -v RS='\0' ' {
|
|
print (match($0, /^[[:digit:]]{4,}-[[:digit:]]{2,}-[[:digit:]]{2,} [[:digit:]]{2,}:[[:digit:]]{2,}:[[:digit:]]{2,}\n?$/)) ? "good" : "bad"
|
|
}')"
|
|
[ "$awkOut" = "good" ];
|
|
}
|
|
|
|
# processFile (file)
|
|
function processFile {
|
|
catcmd="cat"
|
|
if [ "${1: -3}" == ".gz" ]; then
|
|
catcmd="zcat"
|
|
fi
|
|
|
|
aftercmd="cat"
|
|
|
|
# it could be done in awk, but so far we managed without GNU extensions,
|
|
# hence we'll bite our tongue and just do this
|
|
case "$ARG_COMMAND" in
|
|
list-tick )
|
|
aftercmd="sort -dk1"
|
|
;;
|
|
pos )
|
|
aftercmd="sort -nk3 -r"
|
|
;;
|
|
last-price )
|
|
aftercmd="sort -dk1"
|
|
;;
|
|
hist-ord )
|
|
aftercmd="sort -dk1"
|
|
;;
|
|
esac
|
|
|
|
"$catcmd" "$1" | awk \
|
|
-f "$ARG_COMMAND.awk" \
|
|
-v ARG_TICKER="$ARG_TICKER" \
|
|
-v ARG_DATE_AFTER="$ARG_DATE_AFTER" \
|
|
-v ARG_DATE_BEFORE="$ARG_DATE_BEFORE" \
|
|
-v ARG_WIDTH="$ARG_WIDTH" \
|
|
- | $aftercmd
|
|
|
|
# Note: Oh wouldn't it be great to use the @include keyword
|
|
# from GNU awk and avoid all that duplicated code. Oh well.
|
|
}
|
|
|
|
# Transform long options into short ones
|
|
for arg in "$@"; do
|
|
shift
|
|
case "$arg" in
|
|
"--help") set -- "$@" "-h" ;;
|
|
*) set -- "$@" "$arg"
|
|
esac
|
|
done
|
|
|
|
_hasSpecifiedWidth=0
|
|
|
|
if [ ! $1 ]; then
|
|
cat -
|
|
exit 0
|
|
fi
|
|
|
|
while getopts "ha:b:t:w:" o; do
|
|
case "$o" in
|
|
a)
|
|
ARG_DATE_AFTER="$OPTARG"
|
|
if ! validateDateFormat "$OPTARG"; then
|
|
echo "Invalid after date." 1>&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
b)
|
|
ARG_DATE_BEFORE="$OPTARG"
|
|
if ! validateDateFormat "$OPTARG"; then
|
|
echo "Invalid before date." 1>&2
|
|
exit 1
|
|
fi
|
|
p="$OPTARG"
|
|
;;
|
|
t)
|
|
ARG_TICKER="$ARG_TICKER;$OPTARG"
|
|
# if [ ! "$OPTARG" ]; then echo "Missing argument for -t" ; exit 2 ; fi
|
|
;;
|
|
w)
|
|
ARG_WIDTH="$OPTARG"
|
|
if [ $_hasSpecifiedWidth = "1" ]; then
|
|
echo "Width specified twice!" 1>&2
|
|
exit 2
|
|
fi
|
|
_hasSpecifiedWidth=1
|
|
;;
|
|
h)
|
|
printUsage
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
done
|
|
shift "$((OPTIND-1))"
|
|
|
|
# otherwise fails with "binary operator expected" ?!?!?!
|
|
_tmpArgs="$@"
|
|
if [ -z "$_tmpArgs" ]; then
|
|
processFile -
|
|
fi
|
|
|
|
for arg in "$@"; do
|
|
if [ -z "${ACCEPTED_COMMANDS##* $arg *}" ]; then
|
|
ARG_COMMAND="$arg"
|
|
shift
|
|
fi
|
|
done
|
|
|
|
for arg in "$@"; do
|
|
processFile "$arg"
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|