Can you turn 1,500 R$ into 1,000,430 R$ by investing in the stock market?

[This article was first published on R on msperlin, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In the last few weeks we’ve seen a great deal of controversy in Brazil regarding financial investments. Too keep it short, Empiricus, an ad-based company that massively sells online courses and subscriptions, posted a YouTube ad where a young girl, Bettina, says the following:

Hi, I'm Bettina, I am 22 years old and, starting with R$ 1,500, I now own R$ 1,042,000 of  accumulated wealth.

She later explains that she earned the money by investing in the stock market over three years. For my international audience, the proposed investment is equivalent of turning $394 into $263,169 over a three year period.

Anyone with a economics or business background will easily spot that the financial returns stated in the ad is simply not possible. Even if Bettina is a very good investor, reaching this level of returns over a three year period in the stock market is unheard of. The yearly rate of return of the investment is equal to 774% per year. The monthly rate proposed in the ad is equivalent to 19,8% per month.

Giving perspective, Buffet, one of the greatest long term investor of all times, has reached the approximate rate of 19% per year, around 1.46% per month. So, Bettina is either a financial genius that, with only 22 years old, was able to beat Buffet in its own game, or the ad is not fully committed to the truth. To be fair, even if we took the difference of inflation rates between Brazil and US into account, the difference is still very impressive and misleading.

Others have pointed out that if you compound these return over time, the result will be economically unrealistic. See next what happens to R$ 1.500 if we assume that you can replicate the alledged investment return of Bettina (774% per month) over a 10 year period.

Table 1: Compounding returns for Bettina
Number of years Investiment value
1 R$ 13.103,89
2 R$ 114.474,71
3 R$ 1.000.043,00
4 R$ 8.736.305,50
5 R$ 76.319.752,11
6 R$ 666.724.001,23
7 R$ 5.824.454.109,93
8 R$ 50.882.022.569,93
9 R$ 444.501.780.243,15
10 R$ 3.883.136.374.301,74

If Bettina is a genius and can replicate her result over the years, she will be a billionaire in 7 years and a trillionaire in 10. If she waited one more year, she could even buy the whole country if she wanted to. The current GDP of Brazil is around 2 trillion USD (7.5 trillion in R$). She can easily reach this amount of cash in 12 years or more.

But lets go further in this endeavor. Let’s stop being skeptic about her returns and see whether its possible to achieve such returns in the stock market. As you can expect, I’m taking a data based approach. I’ll compare the returns of Bettina to GodBot, a computer algorithm that can perfectly predict stock prices.

First, let’s download some stock data from B3, the Brazilian stock exchange.

library(BatchGetSymbols)

df.sp500 <- GetSP500Stocks()
df.sp500 <- GetIbovStocks()
my.tickers <- paste0(df.sp500$tickers, '.SA')

df.stocks <- BatchGetSymbols(tickers = my.tickers,
                            first.date = '2010-01-01', 
                            last.date = Sys.Date())[[2]]
## 
## Running BatchGetSymbols for:
##    tickers = ABEV3.SA, B3SA3.SA, BBAS3.SA, BBDC3.SA, BBDC4.SA, BBSE3.SA, BRAP4.SA, BRDT3.SA, BRFS3.SA, BRKM5.SA, BRML3.SA, BTOW3.SA, CCRO3.SA, CIEL3.SA, CMIG4.SA, CSAN3.SA, CSNA3.SA, CVCB3.SA, CYRE3.SA, ECOR3.SA, EGIE3.SA, ELET3.SA, ELET6.SA, EMBR3.SA, ENBR3.SA, EQTL3.SA, ESTC3.SA, FLRY3.SA, GGBR4.SA, GOAU4.SA, GOLL4.SA, HYPE3.SA, IGTA3.SA, ITSA4.SA, ITUB4.SA, JBSS3.SA, KLBN11.SA, KROT3.SA, LAME4.SA, LOGG3.SA, LREN3.SA, MGLU3.SA, MRFG3.SA, MRVE3.SA, MULT3.SA, NATU3.SA, PCAR4.SA, PETR3.SA, PETR4.SA, QUAL3.SA, RADL3.SA, RAIL3.SA, RENT3.SA, SANB11.SA, SBSP3.SA, SMLS3.SA, SUZB3.SA, TAEE11.SA, TIMP3.SA, UGPA3.SA, USIM5.SA, VALE3.SA, VIVT4.SA, VVAR3.SA, WEGE3.SA
##    Downloading data for benchmark ticker | Found cache file
## ABEV3.SA | yahoo (1|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## B3SA3.SA | yahoo (2|65) | Found cache file - Got 82.0% of valid prices | Nice!
## BBAS3.SA | yahoo (3|65) | Found cache file - Got 96.0% of valid prices | Good stuff!
## BBDC3.SA | yahoo (4|65) | Found cache file - Got 96.0% of valid prices | Got it!
## BBDC4.SA | yahoo (5|65) | Found cache file - Got 96.0% of valid prices | Mais contente que cusco de cozinheira!
## BBSE3.SA | yahoo (6|65) | Found cache file - Got 61.6% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## BRAP4.SA | yahoo (7|65) | Found cache file - Got 96.0% of valid prices | Good stuff!
## BRDT3.SA | yahoo (8|65) | Found cache file - Got 13.0% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## BRFS3.SA | yahoo (9|65) | Found cache file - Got 96.0% of valid prices | Got it!
## BRKM5.SA | yahoo (10|65) | Found cache file - Got 96.0% of valid prices | You got it!
## BRML3.SA | yahoo (11|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## BTOW3.SA | yahoo (12|65) | Found cache file - Got 96.0% of valid prices | Well done!
## CCRO3.SA | yahoo (13|65) | Found cache file - Got 96.0% of valid prices | OK!
## CIEL3.SA | yahoo (14|65) | Found cache file - Got 96.0% of valid prices | You got it!
## CMIG4.SA | yahoo (15|65) | Found cache file - Got 96.0% of valid prices | You got it!
## CSAN3.SA | yahoo (16|65) | Found cache file - Got 96.0% of valid prices | Youre doing good!
## CSNA3.SA | yahoo (17|65) | Found cache file - Got 96.0% of valid prices | Youre doing good!
## CVCB3.SA | yahoo (18|65) | Found cache file - Got 55.1% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## CYRE3.SA | yahoo (19|65) | Found cache file - Got 96.0% of valid prices | Feels good!
## ECOR3.SA | yahoo (20|65) | Found cache file - Got 93.4% of valid prices | Looking good!
## EGIE3.SA | yahoo (21|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## ELET3.SA | yahoo (22|65) | Found cache file - Got 96.0% of valid prices | OK!
## ELET6.SA | yahoo (23|65) | Found cache file - Got 94.6% of valid prices | Youre doing good!
## EMBR3.SA | yahoo (24|65) | Found cache file - Got 96.0% of valid prices | You got it!
## ENBR3.SA | yahoo (25|65) | Found cache file - Got 96.0% of valid prices | Good job!
## EQTL3.SA | yahoo (26|65) | Found cache file - Got 96.0% of valid prices | Feels good!
## ESTC3.SA | yahoo (27|65) | Found cache file - Got 96.0% of valid prices | Good job!
## FLRY3.SA | yahoo (28|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## GGBR4.SA | yahoo (29|65) | Found cache file - Got 96.0% of valid prices | Youre doing good!
## GOAU4.SA | yahoo (30|65) | Found cache file - Got 96.0% of valid prices | OK!
## GOLL4.SA | yahoo (31|65) | Found cache file - Got 96.0% of valid prices | Good job!
## HYPE3.SA | yahoo (32|65) | Found cache file - Got 96.0% of valid prices | Got it!
## IGTA3.SA | yahoo (33|65) | Found cache file - Got 96.0% of valid prices | Well done!
## ITSA4.SA | yahoo (34|65) | Found cache file - Got 96.0% of valid prices | You got it!
## ITUB4.SA | yahoo (35|65) | Found cache file - Got 96.0% of valid prices | Well done!
## JBSS3.SA | yahoo (36|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## KLBN11.SA | yahoo (37|65) | Not Cached - Got 0.0431% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## KROT3.SA | yahoo (38|65) | Found cache file - Got 73.1% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## LAME4.SA | yahoo (39|65) | Found cache file - Got 96.0% of valid prices | You got it!
## LOGG3.SA | yahoo (40|65) | Not Cached - Got 0.0431% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## LREN3.SA | yahoo (41|65) | Found cache file - Got 96.0% of valid prices | Well done!
## MGLU3.SA | yahoo (42|65) | Found cache file - Got 82.2% of valid prices | OK!
## MRFG3.SA | yahoo (43|65) | Found cache file - Got 96.0% of valid prices | You got it!
## MRVE3.SA | yahoo (44|65) | Found cache file - Got 96.0% of valid prices | OK!
## MULT3.SA | yahoo (45|65) | Found cache file - Got 96.0% of valid prices | You got it!
## NATU3.SA | yahoo (46|65) | Found cache file - Got 96.0% of valid prices | OK!
## PCAR4.SA | yahoo (47|65) | Found cache file - Got 96.0% of valid prices | Good job!
## PETR3.SA | yahoo (48|65) | Found cache file - Got 96.0% of valid prices | Youre doing good!
## PETR4.SA | yahoo (49|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## QUAL3.SA | yahoo (50|65) | Found cache file - Got 80.5% of valid prices | Feels good!
## RADL3.SA | yahoo (51|65) | Found cache file - Got 96.0% of valid prices | Feels good!
## RAIL3.SA | yahoo (52|65) | Found cache file - Got 41.4% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## RENT3.SA | yahoo (53|65) | Found cache file - Got 96.0% of valid prices | OK!
## SANB11.SA | yahoo (54|65) | Found cache file - Got 89.2% of valid prices | Youre doing good!
## SBSP3.SA | yahoo (55|65) | Found cache file - Got 96.0% of valid prices | Good stuff!
## SMLS3.SA | yahoo (56|65) | Found cache file - Got 61.6% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## SUZB3.SA | yahoo (57|65) | Found cache file - Got 96.0% of valid prices | Looking good!
## TAEE11.SA | yahoo (58|65) | Not Cached - Got 0.0431% of valid prices | OUT: not enough data (thresh.bad.data = 75.0%)
## TIMP3.SA | yahoo (59|65) | Found cache file - Got 96.0% of valid prices | Youre doing good!
## UGPA3.SA | yahoo (60|65) | Found cache file - Got 96.0% of valid prices | Well done!
## USIM5.SA | yahoo (61|65) | Found cache file - Got 96.0% of valid prices | Feels good!
## VALE3.SA | yahoo (62|65) | Found cache file - Got 96.0% of valid prices | Good stuff!
## VIVT4.SA | yahoo (63|65) | Found cache file - Got 96.0% of valid prices | Good job!
## VVAR3.SA | yahoo (64|65) | Found cache file - Got 96.0% of valid prices | Good job!
## WEGE3.SA | yahoo (65|65) | Found cache file - Got 96.0% of valid prices | Well done!

My god bot has a single and simple rule:

  • For each month, it will always invest 100% in the stock with the highest return for the month

Next we code this bot using tidyverse:

library(tidyverse)

res.inv <- df.stocks %>%
 mutate(ref.month = as.Date(format(ref.date, '%Y-%m-01'))) %>%
 group_by(ref.month, ticker) %>%
 summarise(ret.month = last(price.adjusted)/first(price.adjusted) - 1) %>%
 group_by(ref.month) %>%
 summarise(best.ticker = ticker[which.max(ret.month)],
           best.return = ret.month[which.max(ret.month)])

Now, let’s have a look in those returns:

library(ggplot2)

# bettinas returns
initial.cash <- 1500
last.cash <- 1000043
my.T <- 3 # years

r.aa <- (last.cash/initial.cash)^(1/3) -1 
r.am <- (last.cash/initial.cash)^(1/(3*12)) -1 

p <- ggplot(res.inv, aes(x = ref.month, y = best.return)) + 
 geom_col() + 
 geom_hline(yintercept =r.am, color = 'red', size =1.5) + 
 labs(x = 'Time', y = 'Monthly Returns',
      title = 'Monthly Returns of Bettina and GodBot',
      subtitle = paste0('- This plot shows the "alleged" returns from Bettina against a perfect predictor \n for the BR stock market\n',
                        '- The horizontal red line represents the return of Bettina (19.79% monthly)'),
      caption = 'www.msperlin.com/blog'
       ) + 
 scale_y_continuous(labels = scales::percent)

p

As you can see, Bettina did good with a constant monthly return of 19,8%. But, GodBot is better. Bettina is clearly missing something out!

When looking at the nominal value of the investment, the effect of compound returns explodes the value of the portfolio.

library(tidyr)

format.cash <- function(x) {
 require(scales)

 x.formatted <- dollar(x,
                       prefix = 'R$ ',
                       decimal.mark = ',',
                       big.mark = '.',
                       largest_with_cents = Inf)

 return(x.formatted)
}

df.cumret <- res.inv %>%
 mutate(cumret.godbot = initial.cash*cumprod(1+res.inv$best.return),
        cumret.bettina =initial.cash*cumprod(1+rep(r.am, n())) ) %>%
 select(-best.ticker, -best.return)

df.to.plot <- gather(df.cumret, 'Investor', "Value", -ref.month )

p <- ggplot(df.to.plot, aes(x = ref.month, y = Value, color = Investor)) + 
 geom_line(size =2) + 
 labs(x = 'Time', 
      y = 'Value of Return',
      title = 'Accumulated Value of Portfolio',
      subtitle = 'This figure shows the value of accumulated return for Bettina in comparison to GodBot, a perfect predictor of stock markets') + 
 scale_y_continuous(labels = format.cash)

p

The results show that Bettina’s returns are possible. All you need to do is to perfectly predict, for each month, which stock will do best in the market. If you haven’t sensed my irony, let me be crystal clear: Market prices are impossible to predict. The result I just showed you is only possible in my computer. No one will ever be able to replicate it in practice.

The ad from Empiricus is very misleading. In my opinion as a finance professor, the real problem in this episode is that the great majority of the Brazilian population is not financially educated. Many people will believe that is legally possible to reach a 20% return over a month.

I’ve seen countless cases of financial pyramids, usually tied to some exotic cryptocurrency, to rise and shortly burn here in Brazil. This is specially – and sadly – most frequent in the poorer areas of the country. Those that follow Empiricus advice will soon learn its lesson. Making money in short run in stocks is very difficult.

Unfortunately, every disapointed person that followed Empiricus advice is never going back to investing in financial markets. They will miss what is probably the greatest system ever designed for investing and passively creating wealth in the long run.

To leave a comment for the author, please follow the link and comment on their blog: R on msperlin.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)