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 prin­cipe de base du sys­tème comp­table uti­li­sé par led­ger. Ça ­pa­raît com­pli­qué, mais ça veut sim­ple­ment dire que pour chaque tran­sac­tion, il y a au moins un compte dé­bi­té et un compte cré­di­té, et que la somme des ­cré­dits et dé­bits de cette tran­sac­tion 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-­des­sus est exac­te­ment le conte­nu du livre de compte. C’est un fi­chier as­cii simple. Fa­cile à sai­sir et à gé­rer en confi­gu­ra­tion. Un ­simple hg diff (ou git diff) per­met de voir les mo­di­fi­ca­tion en cours.

L’ou­til led­ger peut alors don­ner la ba­lance des comp­tes :

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

No­tez que dans une tran­sac­tion on peut lais­ser un des comptes de cré­dit ou de ­dé­bit sans mon­tant au­quel cas led­ger cal­cule le mon­tant man­quant pour as­su­rer une tran­sac­tion dont la ba­lance est nulle.

Organisation des fichiers

J’ai plu­sieurs comptes dans des banques dif­fé­rentes et j’ai choi­si de ­mettre les tran­sac­tion dans un fi­chier as­so­cié à chaque compte. J’ai alors le fi­chier prin­ci­pal per­so.­led­ger qui in­clus les autres fi­chiers :

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 ba­ckends boo­bank sont confi­gu­rés dans le fi­chier ~/.­­con­fig/­­we­­boob/­­ba­­ckends. Par exem­ple :

[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’ap­pli­ca­tion pass et chif­frés via une ­clef yu­bi­key. run­ca­ched est un script qui per­met de ca­cher le mot de pas­se ­quelques mi­nutes afin de ne pas avoir à le res­sai­sir pour toutes les re­quê­tes ­réa­li­sées par boo­bank.

Synchronisation dans ledger

J’uti­lise en­suite led­­ger-­au­­to­­sync (la branche de dé­ve­lop­pe­ment en ­py­thon3) pour syn­chro­ni­ser les fi­chiers OXF avec le fi­chier led­ger cor­res­pon­dant. Là aus­si c’est fait dans un script, mais en gros ça don­ne ­pour chaque comp­te :

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 pro­blème que vous avez alors à trai­ter et d’at­tri­buer le bon compte de ­dé­pense en lieu et place de tous les dé­pen­se:Unk­nown que vous ver­rez sur ­chaque tran­sac­tion.

Heu­reu­se­ment, led­ger per­met d’as­so­cier un compte à un cer­tain nombre de ­bé­né­fi­ciaires lorsque le compte d’une tran­sac­tion contient Unk­nown.

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 fi­chier compte.­led­ger, j’ai un fi­chier compte.ac­count qui est in­clus et qui dé­fi­nit les bé­né­fi­ciaires (payee) as­so­ciés à chaque comp­te ­led­ger.

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€

Ain­si, pour chaque tran­sac­tion qui concerne le comp­te dé­pen­se:­ha­bi­ta­tion:­éner­gie et dont le bé­né­fi­ciaire est Ener­coop, 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 tran­sac­tions sont en­re­gis­trées dans le fi­chier ban­que1.­led­ger com­me ­suit :

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

et dans le fi­chier ban­que2.­led­ger 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 so­lu­tion simple est élé­gante consiste à in­for­mer led­ger que dé­pen­se:­trans­fert vers ban­que2 et re­ve­nu:­trans­fert de­puis ban­que1 sont un seul et même compte. Ce­la se fait grâce à la di­rec­tive 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 éga­le­ment pos­sible de dé­fi­nir un bud­get. J’ai par exemple en tête de ­mon fi­chier per­so.­led­ger  :

~ 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 do­cu­men­ta­tion parle aus­si de la pos­si­bi­li­té de faire des pré­vi­sions (a­vec l’op­tion --­­fo­­re­­cast), mais ce­la ne fonc­tionne pas et de nom­breux rap­ports de bug re­la­tifs à cette fonc­tion­na­li­té sont ou­vert sur le gi­thub du pro­jet.

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,…).

Beau­coup de fonc­tion­na­li­tés n’ont pas été abor­dées dans cette ar­ticle. Je ­fe­rais sans doute un ar­ticle sup­plé­men­taire pour tra­cer l’évo­lu­tion de ma ­fa­çon de tra­vailler 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.