jacob

@jacob

Notes to my future self

3,403 words

https://jacoblindberg.com/ Thank
You'll only receive email when jacob publishes a new post

bokeh plot




Bokeh Plot







Countries with high inflation

42 countries have a historical inflation rate above 8%. The sum of these countries GDP in 2017 was USD 6,719,239 million - this is 35% of the United States' GDP.

Historical inflation is calculated as the average CPI between 2000 and 2017.

The table below shows the inflation rate, along with GDP numbers and sample size. The two GDP columns can be used to gauge the size of each economy. The reason for the sample size n to be less than 17 is if the inflation rate is NA. Data comes from the World bank.

country Inflation (1999-2017 average) GDP as % of US GDP mUSD in 2017 n
Zimbabwe 1786.9 0.1 17846 15
South Sudan 87.8 0.0 2904 6
Congo, Dem. Rep. 73.4 0.2 37241 14
Angola 53.1 0.6 124209 17
Belarus 32.6 0.3 54442 17
Venezuela, RB 25.9 2.5 482359 15
Serbia 17.5 0.2 41432 17
Iran, Islamic Rep. 17.1 2.3 439514 17
Turkey 17.1 4.4 851102 17
Guinea 16.8 0.1 10496 12
Suriname 16.6 0.0 3324 17
Ghana 16.2 0.2 47330 17
Malawi 16.1 0.0 6303 17
Sudan 15.3 0.6 117488 17
Myanmar 14.9 0.4 69322 17
Zambia 13.9 0.1 25809 17
Sao Tome and Principe 13.4 0.0 391 16
Ukraine 13.2 0.6 112154 17
Ethiopia 12.2 0.4 80561 17
Iraq 12.2 1.0 197716 12
Haiti 12.1 0.0 8408 17
Ecuador 12.0 0.5 103057 17
Nigeria 11.8 1.9 375771 17
Russian Federation 11.6 8.1 1577524 17
Tajikistan 11.2 0.0 7146 16
Yemen, Rep. 11.1 0.1 18213 15
Romania 10.7 1.1 211803 17
Burundi 9.9 0.0 3478 17
Moldova 9.7 0.0 8128 17
Liberia 9.6 0.0 2158 15
Jamaica 9.5 0.1 14768 17
Kenya 9.5 0.4 74938 17
Dominican Republic 9.4 0.4 75932 17
Madagascar 9.2 0.1 11500 17
Argentina 9.1 3.3 637590 14
Mongolia 9.0 0.1 11488 17
Mozambique 8.9 0.1 12334 17
Egypt, Arab Rep. 8.7 1.2 235369 17
Kazakhstan 8.6 0.8 159407 17
Sri Lanka 8.5 0.4 87175 17
Uruguay 8.5 0.3 56157 17
Pakistan 8.0 1.6 304952 17

Code

The code is split into two parts:

  1. reading and cleaning
  2. seeing the relationships

Reading the data

## library 

library(WDI)
library(readr)
library(tibble)
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)

## pick indicators and years 

countries <- "all"

startyear <- 1990
endyear <- 2018

WDIsearch(string='inflation', field='name')
WDIsearch(string='FP.CPI.TOTL.ZG', field='indicator')
indic_inflation <- "FP.CPI.TOTL.ZG" # cpi 

WDIsearch(string='gdp per capita')
WDIsearch(string='gdp')
WDIsearch('gdp.*capita.*constant')
indic_gdp <-  "NY.GDP.MKTP.CD" # "GDP (current US$)"
indic_gdp_pcap <- "NY.GDP.PCAP.CD" # "GDP per capita (current US$)"

## import 

dfn <- WDI(countries, indic_inflation, startyear, endyear)
dfgdp <- WDI(countries, indic_gdp, startyear, endyear)
dfpcgdp <- WDI(countries, indic_gdp_pcap, startyear, endyear)

dfn <- as_tibble(dfn)
dfgdp <- as_tibble(dfgdp)
dfpcgdp <- as_tibble(dfpcgdp)

## see 

df %>%
  select(iso2c, country) %>%
  summarise(length(unique(iso2c)), 
            length(unique(country)))

## check 

# same nr of countries
stopifnot(length(unique(dfpcgdp$iso2c)) == length(unique(dfgdp$iso2c)))
stopifnot(length(unique(dfpcgdp$iso2c)) == length(unique(dfn$iso2c)))

## merge 

str(dfn)
str(dfgdp)
str(dfpcgdp)

df <- dfn %>%
  merge(dfgdp, on="iso2c") %>%
  merge(dfpcgdp, on="iso2c") %>%
  as_tibble() %>%
  rename(inflation = FP.CPI.TOTL.ZG,
         gdp = NY.GDP.MKTP.CD,
         pc_gdp = NY.GDP.PCAP.CD
         ) %>%
  mutate(pop = gdp / pc_gdp)


## remove non countries 

# all cuntry codes 
unique(dfpcgdp$iso2c)

# function 
iso_to_country <- function(isocode, data){
  data %>%
    filter(iso2c %in% isocode) %>%
    select(iso2c, country) %>%
    distinct()
}

# create list of iso & country pair
iso_to_country("AD", dfgdp)
all_iso <- unique(dfgdp$iso2c)
all_iso_cntr <- iso_to_country(all_iso, dfpcgdp)
all_iso_cntr <- as.data.frame(all_iso_cntr)

# select non countries 
all_iso_cntr
non_countries <- all_iso_cntr$iso2c[1:47] 

# remove non countries 
`%not in%` <- function (x, table) is.na(match(x, table, nomatch=NA_integer_))
df <- df %>%
  filter(iso2c %not in% non_countries) %>%
  arrange(iso2c)

df

saveRDS(df, file = "data/df.RDS")

Seeing the data

## read from web or disk 
read_web <- FALSE
if(read_web){source("read.R")}
if(!read_web){
  df <- readRDS("data/df.RDS")
}

df

## plot 

# median inflation
median_infl_tot <- median(df$inflation, na.rm=TRUE)

# swe median 
df %>%
  filter(country == "Sweden") %>%
  filter(!is.na(inflation)) %>%
  summarise(median(inflation))

# swe plot 
df %>%
  filter(country == "Sweden") %>%
  ggplot(aes(year, inflation)) + 
  geom_smooth() + 
  ggtitle("Sweden")

plotinf <- function(cntry, data=df){
  data %>%
    filter(country == cntry) %>%
    ggplot(aes(year, inflation)) + 
    geom_smooth() + 
    ggtitle(cntry)
}

plotinfp <- function(cntry, data=df){
  data %>%
    filter(country == cntry) %>%
    ggplot(aes(year, inflation)) + 
    geom_point() +
    geom_smooth() + 
    ggtitle(cntry)
}


plotinf("United States")
plotinfp("Chile")

# us min max 
df %>%
  filter(country == "United States") %>%
  filter(!is.na(inflation)) %>%
  summarise(max(inflation), min(inflation))

# outlier inflaiton 
df %>% 
  filter(country == "Zimbabwe", year > 1999) %>%
  summarise(mean(inflation, na.rm=TRUE))

# plot countries with high inflation
df %>%
  filter(year > 1999) %>%
  filter(!is.na(inflation)) %>%
  group_by(country) %>%
  mutate(mean_infl = mean(inflation)) %>%
  filter(mean_infl > 15) %>%
  filter(mean_infl < 1000) %>%
  arrange(mean_infl) %>%
  ggplot(aes(mean_infl, country)) + 
  geom_point() +
  ggtitle("Inflation (%) since year 1999")

# mean inflation (and nr of datapoints) 
df %>%
  group_by(country) %>%
  filter(!is.na(inflation)) %>%
  filter(year > 1999) %>%
  summarise(mean_infl = mean(inflation)) %>%
  filter(mean_infl > 15) %>%
  mutate(n = length(country))

# countries with high inflation
df %>%
  filter(year > 1999) %>%
  filter(!is.na(inflation)) %>%
  group_by(country) %>%
  summarise(mean_infl = mean(inflation), 
            mean_gdp = mean(gdp),
            mean_pop = mean(pop)
  )

# gdp united states 
gdp_2017_us <- gdp_2017[gdp_2017$country == "United States", "gdp"]
gdp_2017_us <- as.numeric(gdp_2017_us)

# mean infl and gdp last 18y, for countries with high infl. 
tab_1 <- df %>%
  group_by(country) %>%
  filter(!is.na(inflation), !is.na(gdp)) %>% 
  filter(year > 1999) %>%
  mutate(n = length(year)) %>%
  summarise_all(mean, na.rm=TRUE) %>%
  select(country, inflation, n) %>%
  arrange(desc(inflation)) %>%
  filter(inflation > 8) %>%
  mutate(inflation = round(inflation, 1)) %>%
  rename(`Inflation (1999-2017 average)` = inflation)
tab_1
as.data.frame(tab_1)

# gdp per country 
tab_2 <- df %>%
  group_by(country) %>%
  fill(gdp) %>%
  filter(year == 2017) %>%
  select(country, gdp) %>%
  ungroup() %>%
  merge(tab_1, on="country") %>%
  arrange(desc(`Inflation (1999-2017 average)`)) %>%
  mutate(`GDP as % of US` = round(100* gdp / gdp_2017_us,1)) %>%
  mutate(`GDP mUSD in 2017` = round(gdp / 10^6, 0)) %>%
  select(-gdp)
names(tab_2)
tab_2 <- tab_2[, c(1,2,4,5,3)]
sum(tab_2$`GDP as % of US`)
sum(tab_2$`GDP mUSD in 2017`)

dim(tab_1)[1]
sum(tab_2$`GDP as % of US`)
conclusion_1 <- "42 countries have above 8 percent inflation (measured as CPI average 1999 to 2017)."
conclusion_2 <- "Their total gdp is 1/3 of the United States' GDP."

kable(tab_2)

Podcasts I listen to

I listen to a few podcasts on a regular basis. Here is a description of these, along with links to a few of the episodes I enjoyed.

Waking Up with Sam Harriss

  • Universal basic income. Presidential candidate Andrew Yang about universal basic income. They discuss the state of the economy, the rise of automation and AI, the arguments for and against UBI.
  • The science of meditation. Sam talk with Golemand and Davidson about the current scientific understanding of meditation practice. They speak about the original stigma associated with meditation, the history of introspection in eastern and western cultures, the recent collaboration between Buddhism and western science, the difference between altered states and altered traits, an alternate conception of mental health.
  • Yuval Noah Harari and Sam talk about the need for stories, the power of technology to erase the boundary between fact and fiction, wealth inequality, the problem of finding meaning in a world without work, religion as a virtual reality game, the difference between pain and suffering, the future of globalism, and other topics.

Sam Harris is the author of five New York Times bestsellers and the host of the Waking Up Podcast. His books include The End of Faith, Letter to a Christian Nation, The Moral Landscape, Free Will, Lying, Waking Up, and Islam and the Future of Tolerance (with Maajid Nawaz). The End of Faith won the 2005 PEN Award for Nonfiction. His writing and public lectures cover a wide range of topics—neuroscience, moral philosophy, religion, meditation practice, human violence, rationality—but generally focus on how a growing understanding of ourselves and the world is changing our sense of how we should live.

Freakonomics

Freakonomics is a ground-breaking collaboration between Levitt and Stephen J. Dubner, an award-winning author and journalist. They usually begin with a mountain of data and a simple, unasked question. Some of these questions concern life-and-death issues; others have an admittedly freakish quality.

Farnam Street

Flippening

A podcast for cryptocurrency investors.

  • Understanding China's Largest Blockchain Fund. Eric Meltzer is a partner at INBlockchain, China's oldest and largest institutional crypto asset and blockchain fund. To give you a sense of INBlockchain's size and scope, consider that they recently announced a $1.6 Billion dollar fund with 30% coming from the Hangzhou government.
  • Programmable Tokenized Debt. "In chapter one, we discuss the history and origins of debt from the origin of the human species, up until around the year 2000. We also discuss the web 2.0 peer to peer lending solutions that preceded Dharma, such as prosper and lending club. In the second chapter, we discuss the history and development of Crypto Asset Technology that has paved the way for programmable, tokenized debt."
  • Tokenize The World: A Security Token Audio Documentary

Personal income statement and balance sheet

I completed an exercise which gave me the impression of having a thorough understanding of my personal finances. The exercise takes 5 to 10 min so it was worthwhile. I will try to repeat it once a year. It goes like this:

  1. Write down your balance sheet
  2. Write down your monthly cash flows

Balance sheet

Write down all major assets (A) and liabilities (L). In my case that is: apartment, morgage, equity funds, and student debt.

The sum of all assets minus the sum of all liabilities is my personal equity, which is a good measure of how wealthy I am. This personal equity is also a good yard stick to compare expenses against: If my personal equity is 100 is a monthly spending on 10 appropriate?

Monthly cash flows

My personal cash flows

The code to produce the plot (using mermaid) is pasted below.

graph LR

S((Salary))  --> NJL{Bank account}

ICA(Our credit card) --> |1. Expenses| C1[Our costs]
E(My credit card) --> |1. Expenses| C2[My costs]

NJL -->|2. Pay invoice| ICA
NJL --> |2. Pay invoice| E

NJL-- "3. Savings increase or decrease" ---A{Brokerage account}

NJL -->|Amortization | B(Bank)

Bitcoin information for beginners

If you know close to nothing about Bitcoin, but are curious and want to know the facts, the videos listed below will serve your needs well.

  1. The real value of bitcoin and crypto currency technology a 6 min animated video.
  2. What is Bitcoin? a quick 1.5 min intro by Bitcoin.org
  3. Bitcoin 101, a talk by Andreas Antonopoulos, but only the first 10 min is interesting.
  4. Trust disrupted, a mini documentary about blockchains by TechCrunch in the format of 7 videos 7 min each.
  5. The Essence of How Bitcoin Works illustrates how it works under the hood, and how thousands of strangers can agree on who owns what.

Every link leads to YouTube.

Köpa_lägenhet.R

Skulden på den gamla lägenheten är idag 2.1 miljoner. Om vi vet att lånelöftet ligger på 3.8 miljoner, och tror att priset på den gamla lägenheten kommer att ligga mellan 2.5 och 2.9 miljoner, då får vi följande samband mellan försäljningspriset på den gamla lägenheten (övre raden) och hur mycket den nya lägenheten maximalt kan kosta (under raden).

Sälj: 2.5 2.55 2.6 2.65 2.7 2.75 2.8 2.85 2.9
Köp: 2.33 2.67 3 3.33 3.67 4.0 4.33 4.5 4.55

Om vi däremot är osäkra på hur stort lånelöftet är, så kan vi låta det variera mellan 2.6 till 3.8 miljoner. Priset på gamla lägenheten kan vi återigen låta variera mellan 2.5 till 2.9 miljoner. Skulden är fortfarande 2.1 miljoner. Genom att variera såväl lånelöfte som säljpris får vi tabellen nedan som anger vad nya lägenhetens pris kan vara, givet ett visst lånelöfte (rader) och säljpriset (kolumner).

Lån \ Sälj 2.5 2.55 2.6 2.65 2.7 2.75 2.8 2.85 2.9
2.6 2.33 2.67 3 3.10 3.15 3.2 3.25 3.3 3.35
2.8 2.33 2.67 3 3.30 3.35 3.4 3.45 3.5 3.55
3 2.33 2.67 3 3.33 3.55 3.6 3.65 3.7 3.75
3.2 2.33 2.67 3 3.33 3.67 3.8 3.85 3.9 3.95
3.4 2.33 2.67 3 3.33 3.67 4.0 4.05 4.1 4.15
3.6 2.33 2.67 3 3.33 3.67 4.0 4.25 4.3 4.35
3.8 2.33 2.67 3 3.33 3.67 4.0 4.33 4.5 4.55

Hur priset för nya lägenheten (output) beror på lånelöfte och pris på gamla lägenheten (input) visualiseras i 3D plot nedan.

Koden (skriven i R) för att generera plot och tabell finns nedan.

## library

library(data.table)
library(knitr)
library(lattice)

## define function

# output: buy price you can affor. 
# input: sell price and the bank's debt promise.
calcer <- function(sellprice, debt_promise, cash_savings=0){
  debt_today = 2.1
  brokerfee = 50/1000
  cash_apartment = sellprice -  debt_today - brokerfee

  # total cash: cash from apartment sale + cash in savings account 
  cash_tot = cash_apartment + cash_savings

  kvot = debt_promise / (debt_promise + cash_tot)
  scenario = ifelse(kvot >= 0.85, 
                    1, 
                    2)
  buyprice = ifelse(scenario == 1, 
                    cash_tot/0.15,
                    cash_tot + debt_promise)
  return(buyprice)
}

# exempel 
calcer(2.9, 3)

# set params 
debt_list <- seq(2.6, 3.8, 0.2)
sellprice_list <- seq(2.5, 2.9, 50/1000)

# example 
calcer(sellprice_list, 3)
calcer(2.7, debt_list)

## tabulate a few alternative prices and debt levels  

# setup matrix 
n_debt <- length(debt_list)
n_salesprice <- length(sellprice_list)
pricematrix <- matrix(NA, nrow=n_debt, ncol=n_salesprice)

# save values to matrix 
for (row in 1:n_debt){
  for (col in 1:n_salesprice){
    sp <- sellprice_list[col]
    d <- debt_list[row]
    pricematrix[row, col] <- calcer(sp, d)
  }
}

# edit matrix 
rownames(pricematrix) <- debt_list
colnames(pricematrix) <- sellprice_list
pricematrix <- round(pricematrix, 2)

# show matrix 
pricematrix
kable(pricematrix) 

## 3d plot 

# convert matrix to dataframe format 
df <- CJ(debt_list, sellprice_list)
df <- as.data.frame(df)
df$debt <- df$V1
df$sellprice <- df$V2
df <- df[, c("debt", "sellprice")]
df$buyprice <- calcer(df$sellprice, df$debt)

# show plot 
wireframe(buyprice ~ sellprice * debt, data=df)

Buy cheap wine and relabel it

Does All Wine Taste the Same? was an article in the New Yorker. I summarize the post below in a few bullets.

  • A cheap wine won a wine competition (the panel consisted of experts).
  • White wine were poured into two glasses, then one of them was tinted with red food coloring. The experts thought very differently of those two glasses.
  • A certain wine bottle was presented in two forms: one with the original lable and one with a fancy lable — the experts critized the formed and praised the latter.

Reading on the web

Here is a good workflow for reading from the web.

Firstly, pick a few sources that you want to read from. Save their RSS to Feedly.com (In the background, every new article is now saved into feedly.)

Secondly, install the feedly app on your phone. When you have some idle time, scroll though the RSS feed in you app and hit “save for later” on the articles you would like to read. (In the background, a IFTTT.com script places the saved items on Instapaper.com)

Thirdly, when you have time and energy to read, go to Instapaper.com and read from there in a great reading environment – dark background, large font and no ads. If you are on the go, you can print the articles or read them on your kindle.

The system outlined above has made me read more and browse less.

Passive investing beats active

A professor at NYU has provided empirical evidence that passive investing beats active. He also explains why this is. Any avid reader of financial literature already have heard these arguments, however, professor Damodaran's video presentation and blog post is an easy read for anyone that does not have a thorough financial background. Damodaran breaks his argument into four sections.

1. Active managers cannot collectively beat the market

This is just pure math, as proved by Sharpe in 1991. Some active managers must have returns higher the market, and some must have returns lower than the market. As a collective, they will have a return equal to the market. After including fees, however, the sum of all active investors will be beaten by the market due to trading costs.

2. Sub-groups of active investors do not beat their index

Active managers investing in a certain style (e.g. large cap growth stocks or stocks with low PE or high dividend yield) do not beat their sub-index. This is logical since almost any style can be replicated with an index - at a lower cost than the active manager.

The empirical evidence on this is large enough that it is now considered a well known fact. As an example, here is an excerpt from the abstract of Jensen's influential 1967 paper:

The evidence on mutual fund performance indicates not only that these 115 mutual funds were on average not able to predict security prices well enough to outperform a buy-the-marketand-hold policy, but also that there is very little evidence that any individual fund was able to do significantly better than that which we expected from mere random chance.

3. Top performers do not stay top performers

The last argument for active investing is that whilst the two previous arguments are true, there exists people who can make the right judgement call and beat the market consistently. Data suggests the opposite. By ranking the portfolio managers by quarter in one period, and then studying how they performed in the following periods (a so called transition matrix) we can draw the conclusion that the top performers do not stay top performers.

Moreover, a simple graphic from Morningstar suggests the superstar fund managers quickly came down to earth during the years after being named as a top performer. This is logical, since risk taking can give extreme returns - sometimes extremely positive and sometimes extremely negative.

Damodaran's arguments are inline with those made by Fama in his 1961 paper "Efficient capital markets" where Fama writes

... for individual funds, returns with performance above the norm in one subperiod do not seem to be associated with performance above the norm in other subperiods.

4. What about outliers like Warren Buffet?

Pulling out this outlier argument is a sign of weakness and desperation - the activist already lost the debate. It is impossible to tease out skill from luck in such rare cases like these.
It must be the case that some fund managers outperform the market - a few outliers a posterio are to be expected. This does not imply there are trading strategies that a prioir are profitable. Fama makes a point about this in his paper as well, where he writes "the number of funds with large positive deviations of returns from the market line of Figure 2 is less than the number that would be expected by chance", which is an academic way of saying they were lucky.

Conclusion

Damodaran sums up his article with the following sentence:

The performance of active money managers provides the best evidence yet that indexing may be the best strategy for many investors.

He also makes a closing remark on the industry as a whole:

... active investing, as structured today, is an awful business, with little to show for all the resources that are poured into it. In fact, given how much value is destroyed in this business, the surprise is not that passive investing has encroached on its territory but that active investing stays standing as a viable business.

Online account names

It is good to have some structure when choosing names for online services such as email and twitter. Here is the order that I try them out in. If the first name is taken, I go to the second one, and so on.

  1. Jacob
  2. Lindberg
  3. JacobLindberg
  4. Jacobv
  5. Vlindberg
  6. Jacobvlindberg
  7. jacob930321