Skip to content

Instantly share code, notes, and snippets.

@dncgst
Forked from lcpz/revolut-gma.bash
Created June 20, 2022 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dncgst/2beccff999fd29ad4e14f42d3d2f4c42 to your computer and use it in GitHub Desktop.
Save dncgst/2beccff999fd29ad4e14f42d3d2f4c42 to your computer and use it in GitHub Desktop.
Giacenza Media Annua for Revolut accounts
#!/bin/bash
# Compute the Giacenza Media Annua (GMA) of a Revolut account, required by the Italian INPS.
# Dependencies: awk, GNU date, getopts, xargs
# Computation method: https://bit.ly/3avDLu3
# Thread on Revolut forum: https://bit.ly/3511e5h
# Assumptions:
# 1. Dates are in YYYY-MM-DD format. The Revolut app uses your locale, so if this is set
# to it-IT, then this assumption is already satisfied. Otherwise, convert the dates in
# your CSV to ISO 8601 before using the script.
# 2. The time interval considered is between January 1 and December 31 of the same year
# (since it is an annual value).
# 3. Transactions are in ascending date order.
# 4. The actual balance of day D is the last registered during D. This is because the GMA
# is a weighted arithmetic mean, and the entries of the CSV are sorted by date. Hence,
# if T is an array of transactions registered during D, with |T| > 1, then all entries
# in T except the last one have null weight, because they have been on the account for
# less than one day. Thus, they do not affect the GMA, and can be safely skipped.
version="2022.05"
completed_date=4
balance=10
separator=","
use_decimal_point=false
print_usage() {
printf "Usage: `basename "$0"` [options]\n%-2sOptions:\n"
printf "%-4s-c \n%-6s'Completed Date' column number\n"
printf "%-6sDefault: $completed_date\n"
printf "%-4s-a \n%-6s'Balance' column number\n%-6sDefault: $balance\n"
printf "%-4s-s \n%-6sSeparator character of the input CSV\n"
printf "%-6sDefault: '$separator'\n"
printf "%-4s-d \n%-6sUse point instead of comma as decimal separator\n"
printf "%-6sDefault: $use_decimal_point\n"
}
if [[ $# -lt 1 ]]
then
print_usage
exit 1
fi
while getopts "cbs:dvh" flag; do
case "${flag}" in
c) completed_date="${OPTARG}" ;;
b) balance="${OPTARG}" ;;
s) separator="${OPTARG}" ;;
d) use_decimal_point=true ;;
v) printf "Version: $version\n"
exit 0 ;;
*) print_usage
exit 0 ;;
esac
done
result=0
prev_date=""
year=""
get_days() {
# input values are in seconds, and there are 60 * 60 * 24 = 86400 seconds in a day
days=$((($1 - $2) / 86400))
days=${days#-}
days=$(($days + 1))
printf $days
}
mycmd="awk -F '$separator' '(!unique[\$$completed_date]++ && NR > 1) {print \$$completed_date,\$$balance}' '$1'"
while read curr_date
do
d1=""
d2s=""
if [[ ! $prev_date ]]
then
year=$(date -d "${curr_date% *}" "+%Y")
d1=$(date -d "$year-01-01" +%s)
d1s="1 Jan $year"
prev_date="$year-01-01"
printf "Calculating the Giacenza Media Annua of the year $year\n\n"
fi
if [[ ! $d1 ]]
then
d1=$(date -d "${prev_date%% *}" +%s)
fi
d2=$(date -d "${curr_date%% *}" +%s)
days="$(get_days $d1 $d2)"
money=`echo ${curr_date##* } | xargs`
# approximated to 2 decimal values for ease of reading, comment to see exact values
money=$(awk "BEGIN {printf(\"%.2f\", $money); exit}")
p=$(awk "BEGIN {print $money*$days; exit}")
result=$(awk "BEGIN {print $result+$p; exit}")
d1s=`echo ${prev_date%% *} | xargs`
if [[ ! $d2s ]]
then
d2s=`echo ${curr_date%% *} | xargs`
fi
printf "$d1s to $d2s: $money x $days = $p\n"
prev_date=$curr_date
done <<< `eval $mycmd`
if [[ ! "$d2s" = "$year-12-31" ]] # last date is not the last day of the year
then
days="$(get_days $(date -d "$year-12-31" +%s) $d2)"
p=$(awk "BEGIN {print $money*$days; exit}")
result=$(awk "BEGIN {print $result+$p; exit}")
printf "$d2s to $year-12-31: $money x $days days = $p\n"
fi
result=`awk "BEGIN {print $result/365; exit}"`
if !$use_decimal_point
then
result=${result/\./\,}
fi
if [[ "$result" -lt 0 ]] # if the GMA is negative, the value to declare must be 0
then
result_ceil=0
else
result_ceil=${result%.*}
result_ceil=$((result_ceil + 1))
fi
printf "\nResult: $result, to be rounded up to $result_ceil\n"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment