Gérer ses comptes en ligne de commande

dollar and command line

Les an­nées pas­sent, les en­fants gran­dissent et voi­là que s’an­nonce le temps des études su­pé­rieures (et des coûts as­so­ciés). C’est l’oc­ca­sion de ­re­prendre en main de ma­nière un peu plus sé­rieuse ma ges­tion fi­nan­ciè­re ­per­son­nelle.

J’ai es­sayé de re­ve­nir à gnu­cash que j’avais dé­jà u­ti­li­sé il y a quelques an­nées, mais j’ai été confron­té à quelques dif­fi­cul­tés :

  • beau­­coup de pro­­blèmes de sta­­bi­­li­­té,

  • la syn­­chro­­ni­­sa­­tion avec les fi­­chiers OFX ré­­cu­­pé­­rés de la banque de­­man­­dait ­­beau­­coup trop d’ac­­tions ma­­nuelles.

Après quelques re­cherches sur le web, je me suis dé­ci­dé à es­sayer led­ger-­cli et je pense que je l’ai adop­té. J’ai ­main­te­nant une confi­gu­ra­tion qui per­met :

  • la ré­­cu­­pé­­ra­­tion des tran­­sac­­tions ban­­caires via we­­boob,

  • la syn­­chro­­ni­­sa­­tion au­­to­­ma­­tique avec mon livre de compte via leg­­der-­au­­to­­sync,

  • l’ana­lyse des ajouts liés à la syn­chro­ni­sa­tion grâce à un lo­gi­ciel de ­ges­tion de ver­sion comme mer­cu­rial ou git,

  • l’édi­tion de rap­port tex­tuels va­riés grâce à la ligne de com­man­de led­ger,

  • l’ajout ai­sé de tran­sac­tion dans vim à l’aide du plu­gin vim-­led­ger,

  • la syn­­chro­­ni­­sa­­tion mul­­ti-­ap­­pa­­reil (an­­droid, li­­nux) via sync­­thing ou le lo­­gi­­ciel de ges­­tion de ver­­sion,

  • la mo­di­fi­ca­tion ou l’édi­tion de rap­ports sur le té­lé­phone grâce à l’uti­li­sa­tion de led­ger en ligne de com­mande dans un shell ter­mux.

Ce n’est pas fa­cile à mettre en place pour Mme Mi­chu, mais quel plai­sir de ­tra­vailler en ligne de com­mande avec les ou­tils qui vont bien.

Livres de comptes du tailleur Louis-Hippolyte Leroy. « Grand livre - n° 5 »

Livres de comptes du tailleur Louis-­Hip­po­lyte Le­roy. « Grand livre - n° 5 » (Gal­li­ca)

Documentation de référence

Le site https://­plain­tex­tac­coun­ting.org/ est une mine d’in­for­ma­tion, ain­si que bien sûr la do­cu­men­ta­tion en ligne de led­ger.

Cette « led­ger CLI cheat sheet » est éga­le­ment ­très utile.

Comptabilité en partie double

C’est le principe de base du système comptable utilisé par ledger. Ça paraît compliqué, mais ça veut simplement dire que pour chaque transaction, il y a au moins un compte débité et un compte crédité, et que la somme des crédits et débits de cette transaction est nulle.

Concrè­te­ment, on peut avoir les tran­sac­tions sui­van­tes:

2019/03/08 Docteur
   actif:banque:courant                      -30 €
   dépense:santé                              30 €

2019/03/12 Amazon
   actif:banque:courant                     -118.84 €
   dépense:habitation:entretien              114.99 €
   dépense:habitation:fourniture               3.85 €

Ce qui si­gni­fie que le 8 mars, j’ai dé­bi­té 30 € de mon compte cou­rant pour ­payer le doc­teur et que cette dé­pense est en­re­gis­trée comme une dé­pense de ­san­té. De mê­me, le 12 mars, j’ai ache­té du ma­té­riel d’en­tre­tien et des ­four­ni­tures sur Ama­zon pour un mon­tant de 118€84.

Ce que vous voyez ici-dessus est exactement le contenu du livre de compte. C’est un fichier ascii simple. Facile à saisir et à gérer en configuration. Un simple hg diff (ou git diff) permet de voir les modification en cours.

L’outil ledger peut alors donner la balance des comptes :

ledger -f test.ledger bal
           -148.84 €  actif:banque:courant
            148.84 €  dépense
            118.84 €    habitation
            114.99 €      entretien
              3.85 €      fourniture
             30.00 €    santé
--------------------
                   0

Notez que dans une transaction on peut laisser un des comptes de crédit ou de débit sans montant auquel cas ledger calcule le montant manquant pour assurer une transaction dont la balance est nulle.

Organisation des fichiers

J’ai plusieurs comptes dans des banques différentes et j’ai choisi de mettre les transaction dans un fichier associé à chaque compte. J’ai alors le fichier principal perso.ledger qui inclus les autres fichiers :

include banque1-courant.ledger
include banque2-courant.ledger
include banque2-livreta.ledger

Import des données

Récupération des OXF

J’ai écrit le pe­tit script sui­vant qui ré­cu­père les comptes dans des fi­chiers OXF :

#!/bin/bash

backends="-b bppc,boursorama"
accountsdir="/$HOME/banques/OXF"
format="${1:-oxf}"

function accountsList()
{
      boobank --auto-update $backends list --formatter simple --no-header\
              --no-keys --select id --condition 'type=1 OR type=2'
}

echo "Get accounts list..."
accountsList | while read account
do
      filename="$accountsdir/$account"-$(date +%Y%m%d)".$format"
      printf "Dump $account to $filename..."
      boobank history "$account" -f "$format" -n 999 > "$filename" &&\
      boobank history "$account" -f "$format" -n 999 > "$filename" && printf "        ok!\n" || printf "      failed!\n"
done

Les backends boobank sont configurés dans le fichier ~/.­config/­we­boob/­ba­ckends. Par exemple :

[bppc]
module = banquepopulaire
password = `runcached pass show weboob/bppc`
website = www.ibps.mediterranee.banquepopulaire.fr
login = XXXXXXXXXX

[boursorama]
module = boursorama
enable_twofactors = True
device = weboob
pin_code =
login = XXXXXXXXXXXX
password = `runcached pass show weboob/boursorama`

Mes mots de passe sont gérés par l’application pass et chiffrés via une clef yubikey. runcached est un script qui permet de cacher le mot de passe quelques minutes afin de ne pas avoir à le ressaisir pour toutes les requêtes réalisées par boobank.

Synchronisation dans ledger

J’utilise ensuite led­ger-­au­to­sync (la branche de développement en python3) pour synchroniser les fichiers OXF avec le fichier ledger correspondant. Là aussi c’est fait dans un script, mais en gros ça donne pour chaque compte :

ledger-autosync -a "actif:banque:bppc" --assertions --fid "40618" \
     -l "bppc-courant.ledger" "$OXFDIR/CPTYYYYYY@bppc.oxf" \
     | sed -e 's/Expenses:Misc/dépense:Unknown/' -e 's/\<EUR\>/€/' \
     >>  bppc-courant.ledger

Le problème que vous avez alors à traiter et d’attribuer le bon compte de dépense en lieu et place de tous les dépense:Unknown que vous verrez sur chaque transaction.

Heureusement, ledger permet d’associer un compte à un certain nombre de bénéficiaires lorsque le compte d’une transaction contient Unknown.

Ain­si, le livre de compte sui­vant :

account dépense:santé
   payee Docteur


2019/03/08 Docteur
   actif:banque:courant                      -30 €
   dépense:Unknown

est in­ter­pré­té comme :

ledger -f test.ledger bal
              -30 €  actif:banque:courant
               30 €  dépense:santé
-------------------
                  0

Pour chaque fichier compte.ledger, j’ai un fichier compte.account qui est inclus et qui définit les bénéficiaires (payee) associés à chaque compte ledger.

Utilisation au quotidien

Hiérarchie des comptes

Vous êtes li­bre, à titre per­son­nel, de dé­fi­nir la hié­rar­chie qui vous in­té­resse. En ce qui me concer­ne, j’ai quelque chose comme :

actif:banque1:courant
actif:banque1:livreta
actif:banque2:courant
capital:solde initial
dépense:administratif
dépense:alimentation
dépense:alimentation:cantine
dépense:alimentation:restaurant
dépense:banque:frais
dépense:cadeau
dépense:communication
dépense:divers
dépense:don
dépense:habitation:assurance
dépense:habitation:bricolage
dépense:habitation:construction
dépense:habitation:eau
dépense:habitation:entretien
dépense:habitation:fourniture
dépense:habitation:jardin
dépense:habitation:mobilier
dépense:habitation:électroménager
dépense:habitation:énergie
dépense:impôt
dépense:impôt:foncier
dépense:impôt:habitation
dépense:impôt:revenu
dépense:impôt:taxe
dépense:liquide
dépense:loisir
dépense:loisir:art
dépense:loisir:informatique
dépense:loisir:livre
dépense:loisir:logiciel
dépense:loisir:musique
dépense:loisir:photo
dépense:loisir:presse
dépense:loisir:spectacle expo
dépense:loisir:sport
dépense:loisir:voyage
dépense:mobilité
dépense:mobilité:avion
dépense:mobilité:commun
dépense:mobilité:voiture
dépense:mobilité:voiture:amende
dépense:mobilité:voiture:assurance
dépense:mobilité:voiture:carburant
dépense:mobilité:voiture:maintenance
dépense:mobilité:voiture:péage
dépense:mobilité:voiture:stationnement
dépense:mobilité:voiture:électricité
dépense:mobilité:vélo
dépense:remboursement
dépense:santé
dépense:service:web
dépense:vêtement
passif:prêt immobilier
revenu:assurance:caf
revenu:assurance:santé
revenu:banque
revenu:banque:intérêt
revenu:remboursement
revenu:salaire

Exemple de requêtes

  • État de mes fi­nances

    ledger bal actif passif
  • Bi­lan des gains ou pertes sur 2018

    ledger bal dépense revenu -p 2018
  • Ré­par­ti­tion moyenne men­suelle des dé­penses pour 2018

    ledger bal -E -p 2018 dépense --display-total "display_total/12"
  • To­tal des dé­penses men­suelles

    ledger --group-by 'format_date(date, "%Y/%m")' bal dépense --depth 1

    qui donne par exemple

    2018/11
             2078.02 €  dépense
    
    2018/12
             1775.98 €  dépense
    
    2019/01
             2973.27 €  dépense
    
    2019/02
             2988.48 €  dépense
  • Ba­lance par mois sur 2019

    ledger --group-by 'format_date(date, "%Y/%m")' bal -p 2019

Transactions automatiques

C’est une fonc­tion­na­li­té que j’uti­lise pour ajus­ter au­to­ma­ti­que­ment ­cer­taines tran­sac­tions. Par exem­ple, je ne rentre pas le dé­tail de mes ­dé­penses faites avec du li­quide re­ti­ré en DAB, mais j’es­time que 70 % de mes re­traits en li­quide servent à des dé­penses ali­men­taires.

J’ai donc ajou­té la tran­sac­tion sui­vante :

= dépense:liquide
      dépense:alimentation      0.7  ; 70% en alimentaire estimé
      dépense:liquide          -0.7  ;

De la même ma­niè­re, j’ai cal­cu­lé que sur chaque fac­ture d’élec­tri­ci­té, j’avais en­vi­ron 45€ qui étaient dé­diés à la charge de la voi­ture. J’ai donc ajou­té la ­tran­sac­tion sui­van­te :

= /dépense:habitation:énergie/ and (expr payee =~ /Enercoop/)
      dépense:mobilité:voiture:électricité  45 €  ; charge zoé estimée
      dépense:habitation:énergie            -45€

Ainsi, pour chaque transaction qui concerne le compte dépense:habitation:énergie et dont le bénéficiaire est Enercoop, je débite le compte mo­bi­li­té:­voi­tu­re:­élec­tri­ci­té``de 45€ et je re­cré­dite le ­compte de dé­pense ``­ha­bi­ta­tion:­éner­gie de ces 45 €.

Virement de compte à compte

J’ai un vi­re­ment au­to­ma­tique men­suel de la banque qui re­çoit mon sa­lai­re ­sur le compte cou­rant de la banque que j’uti­lise au quo­ti­dien.

Ces transactions sont enregistrées dans le fichier banque1.ledger comme suit :

2019/03/01 * VIR.PERMANENT Salaire
   actif:banque1:courant                         -1000.00 €
   dépense:transfert vers banque2                 1000.00 €

et dans le fichier banque2.ledger comme suit :

2019/03/04 * Salaire
   actif:banque2:courant                          1000.00 €
   revenu:transfert depuis banque1               -1000.00 €

Le pro­blème est que la ba­lance af­fiche les deux compte de trans­fert, ce qui ­vient pol­luer tous les rap­ports :

ledger -f test.ledger bal
                 0  actif
        -1000.00 €    banque1:courant
         1000.00 €    banque2:courant
         1000.00 €  dépense:transfert vers banque2
        -1000.00 €  revenu:transfert depuis banque1
------------------
                 0

La solution simple est élégante consiste à informer ledger que dépense:transfert vers banque2 et revenu:transfert depuis banque1 sont un seul et même compte. Cela se fait grâce à la directive alias :

alias dépense:transfert vers banque2=revenu:transfert depuis banque1

Ce qui donne bien le ré­sul­tat es­comp­té :

ledger -f test.ledger bal
                 0  actif
        -1000.00 €    banque1:courant
         1000.00 €    banque2:courant
------------------
                 0

Budget

Il est également possible de définir un budget. J’ai par exemple en tête de mon fichier perso.ledger :

~ Monthly
   dépense:alimentation                                 444 €
   dépense:communication                                 56 €
   dépense:divers                                        29 €
   dépense:habitation:bricolage                          35 €

~ Yearly
   dépense:habitation:assurance                         380 €
   dépense:mobilité:voiture:assurance                   330 €

Ce qui me per­met en­suite d’avoir un œil sur les dé­pense non bud­ge­tées :

ledger bal --unbudgeted dépense -p "this month"
            27.35 €  dépense
             0.06 €    banque:frais
            23.90 €    cadeau
             3.39 €    service:web
-------------------
            27.35 €

Ou de faire un point sur le bud­get de l’an­née (le rap­port donne en pour­cen­ta­ge un avan­ce­ment des dif­fé­rents compte par rap­port au bud­get) :

ledger budget -p 2019 dépense revenu

La documentation parle aussi de la possibilité de faire des prévisions (avec l’option --­fo­re­cast), mais cela ne fonctionne pas et de nombreux rapports de bug relatifs à cette fonctionnalité sont ouvert sur le github du projet.

Conclusion

Led­ger-­cli est un ou­til vrai­ment puis­sant. Une fois mis en rou­te, on ap­pré­cie la pos­si­bi­li­té de tra­vailler avec les ou­tils du quo­ti­dien (é­di­teur de tex­te, ges­tion de conf, ligne de com­man­de, com­plé­tion au­to­ma­ti­que,…).

Beaucoup de fonctionnalités n’ont pas été abordées dans cette article. Je ferais sans doute un article supplémentaire pour tracer l’évolution de ma façon de travailler avec led­ger-­cli.

Leave a comment
The name you want to show others

Comment by: Mathieu Clabaut

Je ne me suis pas encore vraiment penché sur les graphiques dans la mesure ou ces informations sont disponibles en ligne de commande. Ceci dit, certaines personnes ont fait des choses :

  • utilisation de gnuplot : https://www.sundialdreams.com/report-scripts-for-ledger-cli-with-gnuplot/
  • application fournissant une page web permettant de produire des graphiques : https://kndrck.co/posts/ledger-analytics/

Je pense que je ferais un jour quelque chose avec gnuplot… Si j’aboutis à quelque chose de satisfaisant, je ferais un deuxième billet.