bokeh plot
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 |
The code is split into two parts:
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)
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:
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?
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)
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.
Every link leads to YouTube.
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)
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.
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.
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.
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.
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.
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.
Does All Wine Taste the Same? was an article in the New Yorker. I summarize the post below in a few bullets.
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.
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.