ChallengeR #8 - Solutions

Votre mission consistait donc à trouver un moyen de faire en sorte que :

> x == 0
[1] TRUE
> x + 1 == 2
[1] TRUE
> x / 2 == 1
[1] TRUE
> x
[1] 3
> 3 - x
[1] 3
>

Et vous deviez faire ça sans utiliser d’autres fonctions que celles fournies dans les packages de base de R.

Il y a deux façons de faire ça. La première consiste à modifier le comportement des opérateurs utilisés ci-dessus ; c'est ce qu'on proposé @sassien et @navarre_julien avec, respectivement :

'==' <- function(a,b) {TRUE}
'+' <- function(a,b) {a/3+b}
'/' <- function(a,b) {(a-1)/b}
'-' <- function(a,b) {a}
x <- 3

Ou, plus minimaliste :

x <- 3
'==' <- function(x, y) T
'-' <- function(x, y) y

L'autre, un brin plus ésotérique et proposée par @AlekVladNevski, consiste à faire varier la valeur de x à chaque évaluation avec makeActiveBinding (c'est la solution du quiz de @_ColinFay) :

f = function(){i <<- (i+1)%%4; return(i);}
makeActiveBinding(sym = "x", env = .GlobalEnv, fun = f)
i <- -1

Notez enfin qu'il y a une autre méthode pour faire presque la même chose en utilisant addTaskCallback :

foo <- function(total) {
 i <- 0
 function(expr, value, ok, visible) {
  i <<- i + 1
  x <<- (x + 1) %% 4
  i < total
 }
}

x <- -1
n <- addTaskCallback(foo(10))

Pour Challenger #9, vous voudrez bien me laisser un peu de temps. J’ai du pain sur la planche.

ChallengeR #8

Lors d’un épisode précédent, vous deviez coder une fonction month.end qui, comme son nom le suggère, renvoie le dernier jour du mois de toutes les dates passées en argument tout en utilisant le moins de caractères possibles — sachant que (i) je ne compte que le corps de la fonction et (ii) les espaces, indentations et retours à la ligne ne sont pas considérés comme des caractères).

Et les vainqueurs de ce ChallengeR sont @AlekVladNevski, @navarre_julien et @_pvictorr avec 45 caractères ! @AlekVladNevski nous propose :

month.end <- function(x){
 d=as.Date
 c=cut
 m="month"
 d(c(d(c(x,m))+32,m))-1
}

Avec une méthode similaire, @navarre_julien :

month.end <- function(x) {
  f = function(x) as.Date(cut(x, "mo"))
  f(f(x) + 32) - 1
}

Enfin, @_pvictorr utilise une autre approche qui présente l'avantage indéniable d'être significativement plus rapide :

month.end <- function(x) {
 x = as.POSIXlt(x)
 x$mon = x$mo + 1
 x$mday = 1
 as.Date(x) - 1
}

Bravo à tous les 3 !

Challenger #8

Dans la veine du casse-tête proposé par @_ColinFay il y a quelques jours, je vous propose de trouver un moyen de faire en sorte que :

> x == 0
[1] TRUE
> x + 1 == 2
[1] TRUE
> x / 2 == 1
[1] TRUE
> x
[1] 3
> 3 - x
[1] 3
>

Et vous devez faire ça sans utiliser d’autres fonctions que celles fournies dans les packages de base de R. Vous avez jusqu’à vendredi prochain (le 09/02).

Votre @username sur Twitter :


Coller votre code ici :


Validez pour enregistrer votre réponse.

ChallengeR #7

Vous deviez donc coder une fonction nbchar qui compte le nombre de caractères (hors espaces, indentations et retours à la ligne) du corps d'une autre fonction R sachant que le gagnant serait celui pour qui nbchar(nbchar) serait le plus petit possible.

Et le gagnant de ce ChallengeR #6 est @_ColinFay qui nous propose :

nbchar <- function(f){
 sum(nchar(gsub("[[:blank:]]+", "", body(f)))[-1])
}

Ce qui donne donc :

> nbchar(nbchar)
[1] 47
>

Colin me fait remarquer, à juste titre, que je n'ai pas précisé que vous n'aviez pas le droit d'utiliser une fonction externe. Auquel cas il propose :

x <- function(f){
 sum(nchar(gsub("[[:blank:]]+", "", body(f)))[-1])
}

nbchar <- function(f){
 x(f)
}

Soit 4 caractères. Nous allons quand même retenir la première version :)

Notez aussi celle de @navarre_julien :

nbchar <- function(f) {
 sum(nchar(gsub("\\s", "", deparse(body(f)))))
}

Elle présente l'inconvénient de compter les accolades au début et à la fin du corps mais utilise une expression régulière bien plus courte (\\s). En mixant les deux, vous pouviez faire :

nbchar <- function(f) {
 sum(nchar(gsub("\\s", "", body(f)[-1])))
}

Et je ne crois pas qu'on puisse espérer faire plus court.

Challenger #7

Votre mission, si vous l’acceptez consiste à trouver une fonction month.end qui, comme son nom le suggère, renvoie le dernier jour du mois de toutes les dates passées en argument. Par exemple :

> x <- seq(as.Date("1999-01-01"), by = 22, len = 10)
> month.end(x)
 [1] "1999-01-31" "1999-01-31" "1999-02-28" "1999-03-31" "1999-03-31"
 [6] "1999-04-30" "1999-05-31" "1999-06-30" "1999-06-30" "1999-07-31"
>

Sera déclaré vainqueur celui ou celle qui produira la fonction la plus minimaliste (au sens de nbchar) sachant que (i) vous n’avez droit qu’aux packages par défaut de R et (ii) vous ne pouvez pas faire appel à des fonctions externes (poke Colin).

Postez vos réponses ci-dessous ; vous avez jusqu’à vendredi prochain. Update : votre fonction doit impérativement retourner un objet Date. Les meilleurs sont en dessous de 50 caractères !

Votre @username sur Twitter :


Coller votre code ici :


Validez pour enregistrer votre réponse.

Qui achète des obligations à taux négatifs ?

En novembre dernier, Veolia a emprunté pour 500 millions d’euros sur les marchés via l’émission d’une obligation qui arrivera à maturité le 23 novembre 2020 (dans 3 ans). Jusqu’ici, rien d’extraordinaire : avec un endettement financier de l’ordre de 8.5 milliards d’euros, Veolia est un intervenant régulier sur le marché du crédit et les notes des agences — BBB selon Standard & Poor’s et Baa1 selon Moody’s — si elles ne témoignent pas d’une qualité de crédit exceptionnelle, place tout de même le groupe dans la catégorie des émetteurs dits investment grade.

Ce que cette émission a d’extraordinaire, c’est que le taux coupon proposé par Veolia à ses créanciers Le taux d’intérêt que le groupe se propose de payer sur lesdits 500 millions d’euros était d’exactement 0% ! — c’est-à-dire le taux d’intérêt que le groupe se propose de payer sur lesdits 500 millions d’euros — était d’exactement zéro pourcent (0%) ! Mieux encore : cette proposition a eu un tel succès (Veolia a reçu 4 fois plus d’offres qu’initialement demandé) qu’elle s’est finalement vendue à 100.078 ce qui se traduit par un taux d’intérêt de -0.026%.

La suite est ici

Combien valent vos droits à la retraite ?

Officiellement, rien du tout. Les statistiques que l’on voit circuler sur le patrimoine des français comme les lois fiscales considèrent que les droits acquis pour le versement d’une rente garantie par l’État ne valent absolument rien. C’est évidemment stupide : ce n’est pas parce que vous ne pouvez pas vendre vos droits qu’ils n’ont pas, en réalité, une valeur économique.

La réalité étant, comme toujours en France, infiniment complexe et changeante, je vais illustrer ce raisonnement avec un exemple honteusement simplifié : nous allons estimer la valeur économique d’une rente fictive de 1 000 euros par mois, payable à partir du 22 mars 2018 jusqu’au 22 janvier 2048 (soit un peu moins de 30 ans) et garantie par un État noté AAA de la zone euro [1].

Le raisonnement financier classique consiste à se poser une question toute simple : « combien faudrait-il investir aujourd’hui pour reproduire les mêmes effets ?  » Les effets, en l’occurrence, sont les suivants : nous sommes, par hypothèse, le 22 janvier 2018 et, à partir du 22 mars 2018, vous allez toucher 1 000 euros tous les mois jusqu’au 22 janvier 2048 et ce, avec une garantie d’État.

Pour reproduire cette série de cash-flows avec une certitude équivalente, il n’y a pas cinquante solutions : vous allez devoir investir sur des obligations dites zéro-coupon ; c’est-à-dire des obligations qui remboursent le capital et les intérêts en une seule fois, quand elles arrivent à échéance [2].

Concrètement, pour assurer votre premier versement de 1 000 euros dans 3 mois, vous allez devoir acheter une obligation zéro-coupon qui arrive à maturité le 22 mars 2018, pour le second versement vous achèterez une autre obligation qui arrivera à échéance le 22 avril 2018 et ainsi de suite jusqu’au 22 janvier 2048. Au total, ça vous fera un portefeuille de 358 obligations [3] ; chacune assurant, lorsqu’elle arrivera à maturité, un paiement de 1 000 euros exactement.

La question est donc de savoir combien vous devrez investir sur chacune de ces obligations ce qui, naturellement, dépend des taux d’intérêt et, plus précisément des taux spot (le taux des obligations zéro coupon) avec une garantie similaire à celle d’un État noté AAA. Fort heureusement pour nous, la Banque Centrale Européenne met cette information à notre disposition sur son site.

Par exemple, vous pouvez facilement vérifier qu’au 22 janvier 2018, le taux des obligations zéro coupon notée AAA à 30 ans (c’est-à-dire remboursable le 22 janvier 2048) était d’environ 1.3889%. Pour vous assurer de toucher exactement 1 000 euros le 22 janvier 2048, vous auriez donc dû investir la valeur actualisée ($C_0$) de 1 000 ($C_t$) à ce taux ($k$) sur 30 ans ($t$) [4] :

$$C_0 = C_t \times e^{-tk}$$

Sous R :

> Ct <- 1000
> t <- 30
> k <- 1.389/100
> Ct*exp(-t*k)
[1] 659.2187
>

Pour vous assurer de toucher vos 1 000 le 22 janvier 2048, il fallait donc acheter pour environ 659.22 euros d’obligation zéro coupon arrivant à maturité à cette date. Reste à faire le même calcul pour tous les 357 autres paiements futurs. Toutes les données dont vous avez besoin sont ici (remplacez url par ce lien dans le code ci-dessous).

# Chargez tous les taux ZC en mémoire :
source(url)

# Montant à récupérer chaque mois :
Ct <- 1000

# Temps qui nous sépare de chaque paiement en années :
t <- yc$x/12

# Taux spot :
k <- yc$y

# Et nous devons investir...
sum(Ct*exp(-t*k))

Ce qui nous fait un peu plus de 307 115 euros. C'est le montant que vous auriez dû investir sur des zéro coupon, le 22 janvier 2018, pour reproduire les paiements de notre rente fictive et c’est donc la valeur économique réelle de ladite rente. C’est-à-dire que, si vous pouviez vendre vos droits, c’est à ce prix qu’elle se négocierait : plus, vous faites une affaire ; moins, vous vous faites avoir.

Évidemment, ma rente fictive n’est pas tout à fait équivalente à des droits à la retraites. Pour commencer, elle garantit (presque) 30 ans de paiements à quiconque en est propriétaire — y compris vos éventuels héritiers si vous avez passé l’arme à gauche trop tôt — là où vos droits à la retraite sont garantis à vie mais ne bénéficierons à ceux qui restent que dans des conditions très restrictives et compliquées. Ensuite, elle ne sera pas réévaluée en cas d’inflation : vous vous êtes assuré de toucher 1 000 euros, quelle que soit la valeur de l’euro dans 10, 20 ou 30 ans, y-compris si l'euro ne vaut plus rien.

Enfin et peut être surtout, il existe une autre différence notable entre cette rente fictive et des droits à la retraites : propriétaire de ce portefeuille d’obligations, vous êtes tout à fait officiellement à la tête d’un patrimoine financier de 307 115 euros (notamment aux yeux de l’administration fiscale) tandis qu’avec vos droits à la retraite, vous êtes présumé pauvre comme Job.

Quand vous considérez les statistiques mondiales sur le patrimoine des uns et des autres, c’est un élément à prendre en compte : sauf erreur de ma part, les fonds de pensions de nos amis américains (par exemple) sont intégrés dans le calcul de leur patrimoine tandis que nos droits à la retraite, officiellement, ne valent rien.

---
[1] La France n’est plus notée AAA. Inutile de me le rappeler.
[2] Avec des obligations d’État classique qui, comme les OAT françaises, paient des coupons, votre rendement réel dépendra du taux auquel vous réinvestirez lesdits coupons futurs ; taux qui nous est inconnu aujourd’hui.
[3] Dans la vraie vie, il est fort peu probable que vous trouviez toutes ces obligations mais peu importe.
[4] Note technique : les taux proposés par la BCE sont des taux composés en continu. D’où les formules que j’utilise.

Volatility and the square root of time

When I was a rookie, I asked one of the senior members of my team how to compute the volatility of an asset. His answer was as follow:

That’s simply an annualized standard deviation. If you are using daily data:

  1. Compute the daily returns of the asset,
  2. Compute the standard deviation of these returns,
  3. Multiply the standard deviation by the square root of 260 (because there are about 260 business days in a year).

“Of course, he added, if you are using weekly returns you have to multiply by the square root of 52 and if you are using monthly data you should multiply by the square root of 12. Simple as that.

And so I did for years, not even trying to understand why I was multiplying the standard deviation by the square root of time.

Time passed by and one day, I found time to solve that mystery. Then, I understood why this formula makes perfect sense but, more importantly, I realized that the calculations made by most people I know in the financial industry, including seasoned investment professionals, are dead wrong.

Let me explain.

Discrete returns

Let $P_t$ be the price of an asset (that doesn’t pay any interim income such as dividends or coupons for the sake of simplicity) on day $t$. Then, the way most people would compute the return ($\delta_t$) on that asset from day $t-1$ to day $t$ is:

$$\delta_t = \frac{P_t}{P_{t-1}} - 1$$

Now suppose we have price data for $T$ days with $t \in{\{0, 1, 2, .., T\}}$ and, therefore, $T-1$ daily of $\delta_t$, and we want to compute the return over the whole period ($\delta_T$). We would use:

$$\delta_T = \prod_{t=1}^T(1+\delta_t)-1$$

For instance, using the data for the DAX from the EuStockMarkets dataset in R:

> P <- as.numeric(EuStockMarkets[, "DAX"])
> T <- length(P)
> 
> dP <- P[-1]/P[-T]-1
> prod(1+dP)-1
[1] 2.360688
>

Indeed, it's equivalent to:

> P[T]/P[1]-1
[1] 2.360688
>

And the mean return $\bar{\delta_t}$ over the same period is given by:

$$\bar{\delta_t} = (1+\delta_T)^{1/T}-1$$

In R:

> rT <- prod(1+dP)-1
> (1+rT)^(1/T)-1
[1] 0.0006519036
>

Or:

$$\bar{\delta_t} = \left( \frac{P_T}{P_0} \right)^{1/T}-1$$

Note we use $P_0$ because $\delta_1$ is the return between $t=0$ and $t=1$. In R:

> (P[T]/P[1])^(1/T)-1
[1] 0.0006519036
>

Using all this, it's easy to compute what the annualized return of the DAX was over that period. We have a daily mean return ($\bar{\delta_t}$) and we assume a year is 260 business days long; it follows that:

$$\bar{\delta_{260}} = (1+\bar{\delta_t})^{260}-1$$

In R:

> mT <- (1+rT)^(1/T)-1
> (1+mT)^260-1
[1] 0.1846409
>

In words: over that period, the DAX has returned 18.5% per annum on average.

Now, back to the subject: what is the volatility — that is, the annualized standard deviation — of our daily returns ($\delta_t$)? We know how to compute the standard deviation of daily returns; in R:

> sd(dP)
[1] 0.01028088
>

And, according to my former colleague, we should multiply this by $\sqrt{260}$:

> sd(dP)*sqrt(260)
[1] 0.1657742
>

Well, guess what: this is wrong and, not only it is wrong, it doesn't mean anything.

Continuous returns

Using discrete returns is absolutely correct for most uses but, when computating a volatility (and, therefore, a Sharpe ratio or an information ratio) you should use log returns or, as I like to call them, continuous returns:

$$\delta_t = \ln{\left(\frac{P_t}{P_{t-1}}\right)}$$

Or, equivalently:

$$\delta_t = \ln{(P_t)} - \ln{(P_{t-1})}$$

Let me explain why.

The critical property of continuous returns is that the total (continuous) return over the whole period (the $T$ days) is a sum:

$$\delta_T = \sum_{t=1}^T\delta_t$$

In R:

> dP <- diff(log(P))
> sum(dP)
[1] 1.212146
>

Is, indeed, equivalent to:

> log(P[T]/P[1])
[1] 1.212146
>

As a result, the mean daily (continuous) return over the whole period ($\bar{\delta_t}$) is simply the arithmetic mean of the daily (continuous) return:

> mean(dP)
[1] 0.0006520417
>

And, you guessed it, the annualized (continuous) return of the DAX was over that period is given by:

> mean(dP)*260
[1] 0.1695309
>

Starting from this, let's go for a (random) walk.

Random walk

Following Jules Regnault [1], consider a random variable $\delta_t$ that follow some distribution (we don’t care which one) over $T$ periods and just make two basic assumptions: (i) the distribution is stable across time and (ii) the observations of $\delta_t$ are independent one from another.

Denoting $\mu$ the mean of the distribution which is supposed to be stable (assumption i), we know that the sum of $T$ observations will follow a mean $\mu_T$ given by:

$$\mu_T = \mu \times T$$

Now, that distribution also has a standard deviation ($\sigma$): what is the standard deviation of the sum of $T$ observations?

Thanks to the Bienaymé formula [2], we know that the variance of the sum of uncorrelated (assumption ii) random variables is the sum of their variances:

$$Var{\left(\sum_{t=1}^T\delta_t \right)} = \sum_{t=1}^T Var{(\delta_t)}$$

Since we have assumed the distribution is stable (assumption i), so does the variante ($\sigma^2$). From which:

$$Var{\left(\sum_{t=1}^T\delta_t \right)} = \sigma^2 \times T$$

Therefore, standard deviation of the sum of $T$ observations:

$$\sqrt{Var{\left(\sum_{t=1}^T\delta_t \right)}} = \sigma \times \sqrt{T}$$

Here you go: here is the square root of time.

What we are computing here is the standard deviation of a sum and this is indeed how we accumulate continuous returns; not the way we accumulate periodic returns (it's a product). In other words, that formula only make sense if your daily (weekly, monthly... whatever) returns are computed as continuous returns.

The volatility is simply that very same calculation over a standard period of one year (here, $T=260$ days). In R:

> P <- as.numeric(EuStockMarkets[, "DAX"])
> T <- 260
> dP <- diff(log(P))
> mean(dP)*T
[1] 0.1695309
> sd(dP)*sqrt(T)
[1] 0.166096
>

Even better, since we have assumed that our $\delta_t$ are independent, the Central Limit Theorem tells us that, after a large enough number of observations ($T$), their sum should follow (or, at least, be close of) — guess what — a normal distribution.

In other words, with our two assumptions and using continuous returns, we are able to compute the mean and the standard deviation of a normal distribution; which basically means that we knows everything else.

A demo

Let's make a step-by-step demo with the DAX data.

P <- as.numeric(EuStockMarkets[, "DAX"])
dP <- diff(log(P))
T <- 260
# After T days, we should have:
mT <- mean(dP)*T
sT <- sd(dP)*sqrt(T)

Now, we’re going to use ecdf to generate 1000 random series of length T that follow the empirical distribution of the DAX:

N <- 1000
dist <- ecdf(dP)
Rt <- matrix(quantile(dist, runif(T*N)), T, N)

Let's plot them:

Ct <- apply(Rt, 2, cumsum)
cols <- heat.colors(N)
op <- par(mar = rep(5, 4))
plot(1:T, Ct[, 1], type = "n", ylim = c(-.5, .7), cex.lab = .7,
 cex.axis = .7, cex.main = .8, main = "Figure 1")
for(i in 1:N) lines(1:T, Ct[, i], col = cols[i])
par(op)

You shoud get something like:

Now let's see what the distribution looks like after T days:

# The mean:
mean(Ct[T, ])
# Compare to:
mT
# The standard deviation:
sd(Ct[T, ])
# Compare to:
sT

Lastly, compare the empirical distribution at time T with a normal distribution with mean mT and standard deviation sT:

# Density estimate:
d <- density(Ct[T, ], from = -.5, to = .8)

# Normal distribution with our estimated mean/sd (volatility):
y <- dnorm(d$x, mT, sT)

# Plot:
op <- par(mar = rep(5, 4))
plot(d$x, d$y, type = "l", xlim = c(-.5, .8), cex.lab = .7,
 cex.axis = .7, cex.main = .8, main = "Figure 2")
lines(d$x, y, col = "red")
par(op)

It should look like this:

Pretty close right?

From this, one can compute the probability associated with any level of return and it is clear that the higher the volatility, the more likely you are to face losses [3].

Takeaways

First and should you only remember one thing from that post: a volatility should always be computed using continuous (a.k.a log) returns. Any other calculation is false. Period.

Second, most financial models don’t assume anything about the distribution of (say) daily returns: saying that, after $T$ periods, the distribution will be normally distributed is just a consequence of the CLT.

Lastly, the whole random walk thing is based on just two assumptions (i and ii); if you’re looking for weeknesses, this is where you should start.

---
[1] Jules Augustin Frédéric Regnault, a French stock broker who first suggested the concept of a random walk of prices in 1863.
[2] Named after Irénée-Jules Bienaymé (1796-1878), one of the last great French statisticians.
[3] For price probabilities, you'll need to use the corresponding log-normal distribution (see ?dlnorm).

Querying FRED from R

FRED is an amazingly useful website provided by the Federal Reserve Bank of St. Louis compiling over 500k time series from 87 different sources. Here are 2 short R functions to retrieve FRED data in R. You'll need rjson (with admin privileges  : install.packages("rjson")) and a valid API key (register for free here) to run them.

iFRED returns basic information about a time series as a list. For instance, assuming you’re interested by the Russell 1000 index Total Market Index (RU1000TR):

> sid <- "RU1000TR"
> iFRED(sid)
$id
[1] "RU1000TR"

$realtime_start
[1] "2018-01-23"

$realtime_end
[1] "2018-01-23"

(...)

qFRED retrieves the time series itself as a matrix (with dates as row names). Id addition to sid, there are 6 other optional argument:

  • from: the start date as a Date object (defaults to 1776-07-04);

  • to: the end date as a Date object (defaults to Sys.Date());

  • units: one of lin (levels, the default), chg (change), ch1 (change from one year ago), pch (percent change), pc1 (percent change from one year ago), pca (compounded annual rate of change), cch (continuously compounded rate of change), cca (continuously compounded annual rate of change) or log (natural log);

  • freq: one of d (daily, the default), w (weekly), bw(bi-weekly), m (monthly), q (quarterly), sa (semiannual), a (annual), wef (weekly ending Friday), weth (weekly ending Thursday), wew (weekly ending Wednesday), wetu (weekly ending Tuesday), wem (weekly ending Monday), wesu (weekly ending Sunday), wesa (weekly ending Saturday), bwew (bi-weekly ending wednesday) or bwem (bi-weekly ending Monday).

  • aggreg: when using freq, how should data be aggregated? One of eop (end of period, the default), avg (average) or sum (sum)

  • na.rm: logical, should missing values (NAs) be removed from the output?

For instance, always with RU1000TR:

> from <- as.Date("2018-01-01")
> qFRED(sid, from)
           RU1000TR
2018-01-01       NA
2018-01-02  8346.42
2018-01-03  8398.08
2018-01-04  8431.26
2018-01-05  8487.97
2018-01-08  8504.18
(...)

Let's say you want weekly data with end-of-the-period observations:

> qFRED(sid, from, freq = "w", aggreg = "eop")
           RU1000TR
2018-01-05  8487.97
2018-01-12  8624.19
2018-01-19  8698.12
2018-01-26       NA

Same thing but with weekly averages:

> qFRED(sid, from, freq = "w", aggreg = "avg")
           RU1000TR
2018-01-05  8415.93
2018-01-12  8543.91
2018-01-19  8653.44
2018-01-26       NA

Percent change from one year ago:

> qFRED(sid, from, units = "pc1")
           RU1000TR
2018-01-01       NA
2018-01-02 21.66084
2018-01-03 21.54941
2018-01-04 22.16739
2018-01-05 22.54979
2018-01-08 23.23220
(...)

The code is on Github. Don't forget to replace .FRED_api_key with your own API key!

ChallengeR #8 - Solutions

Votre mission consistait donc à trouver un moyen de faire en sorte que : > x == 0 [1] TRUE > x + 1 == 2 [1] TRUE > x / 2 == 1 [1...