Emprunt immobilier

Petits calculs et graphiques. Pierre H., novembre 2014

sources :


In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

In [2]:
from IPython.html.widgets import interact

In [32]:
prix_appart = 220 # k€
travaux = 20 # k€
notaire = 7.2e-2 * prix_appart
demenagement = 3
total_invest= prix_appart + travaux + notaire + demenagement
total_invest


Out[32]:
258.84000000000003

In [33]:
apport = 60
emprunt = total_invest - apport
emprunt


Out[33]:
198.84000000000003

Emprunt : 200 k€

Assurance


In [41]:
taux_assur_annuel = 0.243e-2*2
emprunt*taux_assur_annuel*1e3/12.


Out[41]:
80.53020000000001

Coût de l'assurance sur 20 ans


In [43]:
emprunt*taux_assur_annuel*1e3 * 20


Out[43]:
19327.248000000003

Calcul des mensualités

à capital, durée et taux fixés

Théorie : Amortissement d'un prêt à taux fixe et à mensualités constantes

cf. Wikipedia - Amortissement

Il est aisé d'établir la formule donnant la mensualité $M$ de remboursement d'un prêt d'un montant (ou capital) noté $K$ effectué à un taux d'intérêt fixe annuel $T$ pendant $n$ mensualités. Le taux mensuel est donné par $r=T/12$, et le capital restant dû après i mensualités $i=1,...,n$ est noté $K_i$. Par définition, $K_n = 0$ puisque après le paiement de la n-ième et dernière mensualités le prêt est totalement remboursé.

  • Après la première mensualité il est évident que $K_1=K(1+r)-M$.
  • Après la seconde mensualité $K_2=K_1(1+r)-M$ soit $K_2=K(1+r)^2-M(1+r)-M$.
  • Après la troisième mensualité $K_3=K_2(1+r)-M=K(1+r)^3-M(1+r)^2-M(1+r)-M$.
  • ........

Il est facile de généraliser le raisonnement à la n-ième et dernière mensualité, il vient $K_n=K(1+r)^n-M\sum_{k=0}^{n-1}{(1+r)^k}$. Comme $K_n=0$ et que $\sum_{k=0}^{n-1}{(1+r)^k}=\frac{(1+r)^n-1}{r}$, puisqu'il s'agit de la somme des $n$ premiers termes d'une suite géométrique de raison $(1+r)$ et de premier terme 1, il vient finalement la formule :

$$M=K\frac{r(1+r)^n}{(1+r)^n-1},$$

souvent mise sous la forme suivante :

$$M=K\frac{r}{1-(1+r)^{-n}}.$$

Il est facile de vérifier en utilisant la règle de L'Hôpital que $\lim_{r\rightarrow 0^+} \frac{r}{1-(1+r)^{-n}} = \lim_{r\rightarrow 0^+} \frac{1}{n(1+r)^{-n-1}}=\frac{1}{n}$, et par suite dans le cas d'un taux d'intérêt nul la formule précédente se réduit bien à $M=K/n$, ce qui est attendu.

Calcul


In [44]:
def mensual(K,T,y):
    r = T/12
    n = y*12
    M = K*r/(1-1/(1+r)**n)
    M = M + K*taux_assur_annuel/12
    return M

In [45]:
mensual(200e3, 0.03, 20)


Out[45]:
1190.1951957078413

In [47]:
@interact(K_thousand=(100,300),
          T_percent=(2.0,4.0),
          y=(10,30))
def print_mensual(K_thousand=200, T_percent=3.0, y=18):
    M = mensual(K_thousand*1000, T_percent/100, y)
    print('Mensualité : {:.0f} €/mois (avec assurance)'.format(M))


Mensualité : 1280 €/mois (avec assurance)

Graphique Mensualité = f(Capital)

à durée et taux fixés


In [48]:
K_min, K_max = 150, 250 # k€
M_min, M_max = 800, 1500 # €/mois

@interact(T_percent=(2.0,4.0),
          y=(10,30))
def plot_mensual(T_percent=3.0, y=20):
    K = np.linspace(K_min*1e3, K_max*1e3, 100)
    M = mensual(K, T_percent/100, y)
    plt.plot(K/1e3, M)
    ax = plt.gca()
    ax.set(xlabel=u'Capital (k€)',
           ylabel=u'Mensualités (€)', ylim=(M_min, M_max),
           title=u'Emprunt à {:.2f}% sur {:.0f} ans'.format(T_percent, y));


Graphique Mensualité = f(Durée)

à capital et taux fixés


In [49]:
M_wish = 1300 # €/mois

In [55]:
M_min, M_max = 800, 1500 # €/mois
y_min, y_max = 15, 25 # années

@interact(K_thousand=(100,300),
          T_percent=(2.0,4.0))
def plot_mensual(K_thousand=200, T_percent=3.0, T_model=False):
    y = np.linspace(y_min, y_max, 100)
    if T_model:
        T_percent = y*a+b
    M = mensual(K_thousand*1000, T_percent/100, y)
    plt.plot(y, M)
    plt.hlines(M_wish, y[0], y[-1],
               colors='r', linestyles='dashed')
    ax = plt.gca()
    ax.set(xlabel=u'Durée (années)',
           ylabel=u'Mensualités (€)', ylim=(M_min, M_max),
           #title=u'Emprunt de {:.0f} k€ à {:.2f}%'.format(K_thousand, T_percent)
           );


Amélioration possible : taux dépendant de la durée

prendre en compte que le taux dépend de la durée : $T = f(n)$

→ exemple issu du simulateur de la Société Générale https://particuliers.societegenerale.fr/emprunter/prets-immobiliers/prets-bancaires/pret-taux-fixe.html

Voir aussi le tableau sur http://www.cyberpret.com/pret-immobilier-taux-fixe.html


In [51]:
# collected on 2014-11-06
year_rate = np.array([
    [11,2.25],
    [12,2.25],
    [13,2.40],
    [15,2.40],
    [16,2.65],
    [17,2.65],
    [18,2.75],
    [20,2.75],
    [21,2.95],
    [25,2.95],
    [26,3.30],
    [30,3.30],
])

In [52]:
a = 0.065 # %/an
b = 1.6 # %

plt.plot(year_rate[:,0], year_rate[:,1], 'd-')
plt.plot(year_rate[:,0], year_rate[:,0]*a+b, '--', label='model T = {:.2f} + {:.2f}*y'.format(a,b))

plt.legend(loc='lower right')
ax = plt.gca()
ax.set(xlabel='duration (yr)', ylabel='rate (%)', ylim=(2.2, 3.4));


Calcul de la durée

durée, à capital, mensualités et taux fixés


In [56]:
from numpy import log

In [61]:
def duration(K,T,M):
    # Assurance:
    M = M - K*taux_assur_annuel/12
    r = T/12
    n = log(M/(M-K*r))/log(1+r)
    y = n/12.
    return y

In [64]:
duration(220e3, 0.03, 1309.2) # exemple BNP


Out[64]:
20.000330376992522

In [67]:
@interact(K_thousand=(100,300),
          T_percent=(2.0,4.0),
          M=(800,1600))
def print_duration(K_thousand=200, T_percent=3.0, M=1300):
    y = duration(K_thousand*1000, T_percent/100, M)
    print('Durée de remboursement : {:.1f} années'.format(y))


Durée de remboursement : 17.6 années

Graphique Capital = f(Durée)

à taux et mensualités fixés


In [70]:
K_min, K_max = 150, 250 # k€
y_min, y_max = 13, 23 # années

@interact(T_percent=(2.0,4.0),
          M=(800,1600))
def plot_capital(T_percent=3.0, M=1300):
    K = np.linspace(K_min*1e3, K_max*1e3, 100)
    y = duration(K,T_percent/100,M)
    plt.plot(y,K/1000)
    ax = plt.gca()
    ax.set(xlabel=u'Durée (années)', xlim=(y_min, y_max),
           ylabel=u'Capital (k€)', ylim=(K_min, K_max),
           title=u'Emprunt à {:.2f}% pour {:.0f}€/mois'.format(T_percent, M));