## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
##
## first, last
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
## Loading required package: MASS
##
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
## Loading required package: strucchange
## Loading required package: sandwich
## Loading required package: urca
## Loading required package: lmtest
## samadb 0.3.0, see help(samadb). Commercial users require a license at https://econdata.co.za/support/
##
## Attaching package: 'TSA'
## The following objects are masked from 'package:PerformanceAnalytics':
##
## kurtosis, skewness
## The following objects are masked from 'package:stats':
##
## acf, arima
## The following object is masked from 'package:utils':
##
## tar
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
## Registered S3 methods overwritten by 'forecast':
## method from
## fitted.Arima TSA
## plot.Arima TSA
##
## Attaching package: 'imputeTS'
## The following object is masked from 'package:zoo':
##
## na.locf
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.4 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.1
## ✔ readr 2.1.5
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ stringr::boundary() masks strucchange::boundary()
## ✖ mosaic::count() masks dplyr::count()
## ✖ purrr::cross() masks mosaic::cross()
## ✖ mosaic::do() masks dplyr::do()
## ✖ tidyr::expand() masks Matrix::expand()
## ✖ dplyr::filter() masks stats::filter()
## ✖ xts::first() masks dplyr::first()
## ✖ dplyr::lag() masks stats::lag()
## ✖ xts::last() masks dplyr::last()
## ✖ tidyr::pack() masks Matrix::pack()
## ✖ MASS::select() masks dplyr::select()
## ✖ readr::spec() masks TSA::spec()
## ✖ mosaic::stat() masks ggplot2::stat()
## ✖ mosaic::tally() masks dplyr::tally()
## ✖ tidyr::unpack() masks Matrix::unpack()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
##
## Attaching package: 'matrixStats'
##
##
## The following objects are masked from 'package:mosaic':
##
## count, iqr
##
##
## The following object is masked from 'package:dplyr':
##
## count
##
##
## ── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.11 ──
## ✔ quantmod 0.4.26 ✔ TTR 0.24.4
## ── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date() masks base::as.Date()
## ✖ zoo::as.Date.numeric() masks base::as.Date.numeric()
## ✖ stringr::boundary() masks strucchange::boundary()
## ✖ matrixStats::count() masks mosaic::count(), dplyr::count()
## ✖ purrr::cross() masks mosaic::cross()
## ✖ mosaic::do() masks dplyr::do()
## ✖ tidyr::expand() masks Matrix::expand()
## ✖ dplyr::filter() masks stats::filter()
## ✖ xts::first() masks dplyr::first()
## ✖ TSA::kurtosis() masks PerformanceAnalytics::kurtosis()
## ✖ dplyr::lag() masks stats::lag()
## ✖ xts::last() masks dplyr::last()
## ✖ PerformanceAnalytics::legend() masks graphics::legend()
## ✖ imputeTS::na.locf() masks zoo::na.locf()
## ✖ tidyr::pack() masks Matrix::pack()
## ✖ MASS::select() masks dplyr::select()
## ✖ TSA::skewness() masks PerformanceAnalytics::skewness()
## ✖ readr::spec() masks TSA::spec()
## ✖ mosaic::stat() masks ggplot2::stat()
## ✖ quantmod::summary() masks urca::summary(), Matrix::summary(), base::summary()
## ✖ mosaic::tally() masks dplyr::tally()
## ✖ tidyr::unpack() masks Matrix::unpack()
## ✖ tidyquant::VAR() masks vars::VAR()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
##
## Attaching package: 'tidyquant'
##
##
## The following object is masked from 'package:vars':
##
## VAR
Economic theory has a rich history there’s no shortage of perspectives which have not been taken when looking into economics. To avoid rambling on about my own economic philosophy, I feel I should simply point out that I have limited experience with neo-classical theory as it is taught at the undergraduate level but my foray into heterodox economics has had me question many of the teachings of strict economic theory. To appease the anti-empiricist schools of thought (side-eye to the Austrians), this project is an investigation into the historical dynamics of the structure of monetary policy. It’s an exercise in economic history. It’s a personal project to make use of data that is published by the South African Reserve Bank (SARB) and StatsSA to gain an understanding of the long term influence of monetary policy on prices and output.
This implies that the person reading this is familiar with the concept of the equation of exchange. Mv=Pq where M is the quantity of money and q is the number of units of output, P is the price of each good, thus Pq represents the total monetary value of transactions in an interval of time. v, the last variable, can be interpreted as the turnover rate of money i.e. the aggregate number of exchanges each unit of currency is involved in over a time period.
The classical monetarist perspective, put forth by David Hume and most recently represented by Milton Friedman rests on the assumption of monetary neutrality. This implies that the turnover rate of money (v) and the number of units of output are relatively stable and that changes in the money supply are “fully” reflected in changes in the “level” of prices (P). In modern day practice, it isn’t the quantity of money that is targeted by Central Banks. Central banks alter the quantity of money circulating in an economy by influencing the baseline rate of interest through open market operations, which alters the cost of borrowing and therefore alters nominal spending (to the extent that nominal spending is financed through credit backed deposits).
Yet the assumption that, in the long run, money is neutral still stands; while short to medium term expansionary effects of expansionary monetary policy are taken to be the focus of most Central Banks.
What is an index number? In the IMF’s guide to index numbers, the following definition is put forth: “How exactly should … micro-economic information involving possibly millions of [transactions]be aggregated into a smaller number of price and quantity variables? … the basic index number problem.”
Say, you’re an economist whose tasked with assessing the monetary dynamics of an economy; what kind of information would you require? The quantities and prices of all goods traded in a given interval over multiple periods would be helpful. You’ll also need to measure the quantity of money in the economy as well as a manner of estimating the velocity of circulation over similar intervals and the same time periods. The first requirement is one that most countries track, to some extent, in the form of nominal GDP and nominal GDE. Though imperfect as measures of anything other than the monetary value of output (like quality of life or efficacy of institutions), it is the closest measure (aside from Gross Output) to the total value of transactions in an economy Pq.
Data on the quantity of money can likewise be collected from most Nation’s Central banks. The difficult, and elusive, category to track is the velocity of circulation. Though information on the volume (number) of EFTs and Payment settlements may be able to allow us to construct an index that is meant to capture the dynamics of the velocity of circulation (which, in the Cambridge tradition, represents the inverse of the demand to hold money).
To keep our task manageable, we’ll begin by trying to tease out a relationship between the quantity of money and the level of prices
Since we’re interested in changes in the magnitudes of Money, output and prices over time, we’ll be making use of time series data and monetary theory to guide our model selection and statistical aggregation tools.
Since GDE and the volume of deposits is typically quoted in millions of Rands, while prices are quoted in much smaller figures the variation in the scale of the variables may lead to statistical models providing unhelpful data. To mitigate this we can Index the data on a chosen Base year to give us more manageable magnitudes while maintaining information about the dynamics. After indexing the data, it will then be log-transformed so as to mitigate the variance between the variables. A vector error correction model is then applied for two reasons; Economic theory suggests a long run equilibrium relationship between the quantity of money and the level of prices (for a given level of output and velocity of circulation) and the regular VAR models tend to have roots either extremely close to, or above unity (implying co-integration).
There are two classes of Index numbers according to basic index number theory, superlative and standard. Superlative Index numbers are a class of economic index numbers (like a price or quantity index) that are designed to provide a more accurate approximation of underlying economic concepts (e.g., cost-of-living, production output, Quantity of money) across a wide range of consumer preferences or production (or financial) technologies. They do a great job at approximating the true value of the magnitude being measured, in fact they are the best we can do. The creme of the crop in this regard is a Divisia Aggregate, which is the superlative index we’ll be using to measure the monetary aggregate.
Standard index numbers tend to be poor approximations for the true concepts you as an economist are interested in due to their inherent biases. Say we have price data and quantity data where their value at time (t) is a row-wise sum of the different quantities and likewise for the price data. These are called simple sum aggregates. To convert them to an index number, you simply divide each aggregate across all observations by the chosen base period’s aggregate and multiply by 100.
These are the types of index numbers you come across in A-level and, while they do a decent job as an introduction to index numbers, they are flawed. For example, all of the elements in the index (columns) are treated equally, so a quantity aggregate for one country that specializes in making grains of sand will be orders of magnitude greater than that of a country that specialized in making one teleportation device. Likewise a simple sum aggregate of prices will be orders of magnitude higher in the teleportation country than in the sandy one since one grain of sand is worth less than one teleportation machine. So most index numbers take quantities and prices into account.
Laspeyres index = frac{p(t) q(0)}{p(0) q(0)}
tracks changes in the value(price/cost) of a fixed set of elements (a basket of goods), at current prices, relative to base period prices. Using Base period expenditure shares leads to overstatement of price/cost/value increases.
Paasche index = frac{p(t) q(t)}{p(0) q(t)}
tracks price changes using current-period elements (basket of goods/portfolio) at current period prices, relative to base period prices. It assumes consumers have already substituted away from expensive elements.
How about incorporating data from successive periods? That’s called chain-linking an index number and it’s preferable for making comparisons over longer periods of time because substitution errors are more likely to be avoided. An example of chain-linking index numbers will be explored in our Divisia—Törnqvist Index.
The smart workflow would be to get accustomed to constructing simple indexes before moving on to the more complicated indices but alas I’m Mr. bite off more than I can chew; I work my way backwards to find digestible bits. So the our ultimate goal is to create a superlative Tornqvist monetary index, and see how related/corrrelated our monetary index is to nominal output, and then to inflation, using the GDP deflation definition due to it’s broader scope (will I have to explain what that is?, we’ll see when we get there). Simple right?
We should probably start with the fun part first: constructing a monetary aggregate. The fist step is to extract the time series we want from the samaDB package:
# Oddly, retrieves all Monthly QB data instead of the one I asked for. This nonsense took me months to find a workaround.
df.MQB <- samadb::sm_data(dsid = "QB",
series = "KBP1360M",
from = "1994-01-01", # Dates must be strings
to = "2023-01-01", # Dates must be strings
freq = "M",
labels = TRUE, # Use logicals
wide = TRUE,
ordered = TRUE) ## Returns all monthly series in QB
# Weekly data
df.WQB <- samadb::sm_data(dsid = "QB",
series = "KBP1450W",
from = "1994-01-01",
to = "2023-01-01",
freq = "W",
labels = TRUE,
wide = TRUE,
ordered = TRUE) ##Returns all weekly series in QB
## a dataframe consisting of the many monthly and weekly magnitudes I could include in my divisia quantity index
##samadb is meant to have GDP data but it is annual, the closest is quarterly nominal GDP, which we'll use here
df.NatAcc <- samadb::sm_data(dsid = "NATL_ACC_SARB",
series = "KBP6006_N_S",
from = "1994-01-01",
to = "2023-01-01",
freq = "Q",
labels = TRUE,
wide = TRUE,
ordered = TRUE)
df.NatAccM <- samadb::sm_data(dsid = "QB_NATLACC",
series = "KBP6045C_Q_R_N_LVL",
from = "1994-01-01",
to = "2023-01-01",
freq = "Q",
labels = TRUE,
wide = TRUE,
ordered = TRUE)
The above code collects weekly and monthly Quarterly Bulletin data and Quarterly Natonal Accounts Data from the SamaDB package (sourced from the SARB QB and STATSA). We’ll use this data to create time series objects, but first we pick out the series we want for our core monetary aggregate. We can always come back and change some things, depending on feedback and what the contemporary monetary theory suggests. Some tweaking may be required for the own rates of return but that’s getting ahead of ourselves.
The first step is to create a time series object that stores the quantities we are interested in. This part of the process requires an adherence to theoretical rigor, strict selection standards and the artistic intution of the statistician. I focused mostly on deposits as well cash and notes in legal tender, though the inclusion of different assets as money may have been useful, their own rate of return is difficult to compute and thus their place in the Törnqvist index may be questionable. Our xts object is constructed from a dataframe wherein we selected the important quantities, including the date column to use as an index.
Certain quantities returned N/A s as data may have not been collected going back all the way to 2000-01-01. For those, I imputed them and used the method “mode”. There is little scientific rigour to this step, it was just to fill in the columns, and the majority of observations were “1” either way.
df.quant.money<- df.MQB %>%
dplyr::select(date,
KBP1312M, ## CASH AND COIN CIRCULATING (own rate of return is negative CPI inflation)
KBP1392M, ##Average Daily Notes and Coin in Circulation Outside SARB
KBP1070M, ## CASH AND CHEQUE DEPOSITS (own rate of return is KBP1600M)
KBP1314M, ## DEMAND DEPOSITS (orr is KBP1601M)
KBP1071M, ## Other demand deposits Priv.Sector
KBP1321M, ## SAVINGS DEPOSITS (orr KBP1606M)
KBP1316M, ## SHORT-TERM DEPOSITS (orr is KBP1609M)
KBP1322M, ## MEDIUM-TERM DEPOSITS (orr is KBP2007M / KBP1611M)
KBP1319M, ## LONG-TERM DEPOSITS (orr is KBP1612M)
KBP1122M, ## OVERDRAFT AND LOANS
KBP1155M, ## - DEPOSITS BY MONETARY INSTITUTIONS
KBP1161M, ## DISCOUNTED TREASURY BILLS
KBP1200M, ## MUTUAL BANK TRANSMISSION DEPOSITS
KBP1201M, ## M BANK SAVINGS DEPOSITS
KBP1202M, ## M BANK OTHER SHORT-MED TERM DEPOSITS
KBP1203M, ## M BANK LONG TERM DEPOSITS
KBP1209M, ## POSTBANK DEPOSITS
)
quant.mon.imp <- imputeTS::na_mean(df.quant.money, option = "mode") ## impute the empty values with the modal value of the column (the empty columns have a modsl value of 1 so I doubt they're that consequebtial)
quant.money.xts <- xts(quant.mon.imp[,-1], order.by = quant.mon.imp$date) ## turn em to an xts object
quant.money.xts[, 11] <- quant.money.xts[, 11] * -1 ## Deposits by other monetary institutions is a negative to the total money supply
plot(quant.money.xts)
It’s a good thing we have a matrix of quantity data because a Tornqvist index requires that, and an index of “prices” of the assets, which we’ll be using as the carrying cost. This means we begin with an xts object of approximate internal rates of return for each category. The QB dataseries came in clutch here. The carrying cost of cash and notes was set as the rate of inflation seeing as that is the effective rate of return on holding cash and notes over a particular period.
df.irr <- df.MQB %>% ## a df of internal rates of return for calculating the opportunity cost of different monies
dplyr::select(
date,
KBP7146A, # CPI
KBP7177A, # core-CPI Inflation rate
KBP1600M, # weighted average deposit rates checque accounts
KBP1414M, # Notice Deposits with Banks1 to 32 Days
KBP1602M, # BA930 Deposit ratesAll Domestic Private sectorsOther - Weighted Average (%)
KBP1415M, ## savings deosits
KBP1417M, ## short-term deposits
KBP2007M, ## Medium- term deposits
KBP2008M, ## Long-term deposits
KBP2026M, ## Overdraft and loan
KBP1626M, ## Deposits from mon instiutions
KBP2874M, ## Nominal Fixed Interest Rate on RSA Retail Savings Bonds - 3 Years
KBP1617M, ## BA930 Deposit ratesCorporate sectorNotice Deposits (1-
KBP1620M, ##
KBP1622M,
KBP1623M,
KBP2009M
)
df.irr.imp <- imputeTS::na_mean(df.irr, option = "median") ## impute empty values with the median value
irr.xts <- xts(df.irr.imp[,-1], order.by = df.irr.imp$date ) ## an xts object of irr
irr.xts[, 1] <- irr.xts[, 1] * -1
irr.xts[, 2] <- irr.xts[, 2] * -1
plot(irr.xts)
We have an xts object of internal rates of returns that has the same dimensions as our quantity index, ordered according to the quantity index. We’ve also multiplied the inflation rates by negative one to indicate that holding cash has a positive opportunity cost beyond the opportunity cost of not investing in the baseline asset.
Speaking of the baseline asset, this is a bar that is set as a “safe” investment option, we alternated between the bank rate and the nominal fixed interest rate on Bonds. Went with the interest rate on retail savings bonds.
Ah, this is for calculating User Cost by the way. User cost is a concept economists use to approximate the opportunity cost of holding a particular asset. the formula is (R-irr)/(1+R). Now it should be obvious why we needed the irr for the different assets
## 6 month treasury bill tender rate
tendrate <- df.WQB %>%
dplyr::select(date,
KBP1466W)
weekly.terate <- xts(tendrate[,-1], order.by = tendrate$date)
monthly.trate <- apply.monthly(weekly.terate,FUN = "mean")
monthly.Tender.rate <- xts(monthly.trate, order.by = index(irr.xts))
plot(monthly.Tender.rate)
df.bankrate <- df.MQB %>% ## our benchmark rate in the formula for user cost: [(R-irr)/(1+R)]
dplyr::select(
date,
KBP1401M ## Bankrate
)
bankrate.xts <- xts(df.bankrate[,-1], order.by = df.bankrate$date)
bankrate.xtsimp <- na.ma(bankrate.xts)
## Warning in na.ma(bankrate.xts): na.ma will be replaced by na_ma.
## Functionality stays the same.
## The new function name better fits modern R code style guidelines.
## Please adjust your code accordingly.
plot(bankrate.xtsimp)
This should look familiar, it tracks the central Bank’s base rate quite religiously, allowing for more stable estimates of user cost over time
irr.xts$KBP7177A <- irr.xts$KBP7146A
align.benchmark <- monthly.Tender.rate[index(irr.xts)] ## aligning the indexes of the benchmark rate data
benchmrk.vec <- as.numeric(align.benchmark) ## create a numeric vector of the indexed bank rate data
Just replacing the columns of 1’s in the second irr column with the CPI inflation data from the first. Also turnng our observations of the benchmark rate into a vector of 277 observations.
This is the confusing part, we’ll take a break from the Tornqvist index after this to let our brains cool off. Usinf a for loop in r, we set the index of columns to i, going column-wise and calculating the user cost for each entry using data from the irr, benchmark rate and leaving us with an xts object of user costs.
usercost.xts <- irr.xts
for(i in 1:ncol(irr.xts)) { ## cycle through each column of the xts object
asset_rate <- as.numeric(irr.xts[, i])
usercost.xts[, i] <- (benchmrk.vec - asset_rate) / (1 + benchmrk.vec) ## calculate the user cost using irr and benchmark rate
}
And thus:
plot(usercost.xts)
The above is a time series with the user cost of all the measures of money listed above, decomposed.
Now for our simple sum aggregate. In the case of a simple sum aggregate.We just add the values row-wise using the rowSums() function. I included this to ensure that through my selection of monetary categories, the estimates quantity of money wasn’t an order of magnitude off. So here’s a simple sum monetary aggregate:
M.simplesum <- rowSums(quant.money.xts)
Msimplesum.xts <- xts(M.simplesum, order.by = quant.mon.imp$date)
plot(Msimplesum.xts)
We’ll call it M(simple). Though, this isn’t an index yet. to do that we’ll need to pick a base year and perform some wizadry, which will be explained as we go along. We go on to index the simple sum quantity by the first observation so January 1/ 2000.
##Using 2000-01-01 as the base month
base.val <- as.numeric(Msimplesum.xts["2000-01-01"])
ss.index <- (Msimplesum.xts/base.val)*100 ## simple index number formula
ss.index.xts <- xts(ss.index, order.by = quant.mon.imp$date) ## turn it to an xts object
plot(ss.index.xts) ## I promise it's more impressive than it looks
log.ss <- log(ss.index.xts)
plot(log.ss)
This concludes the construction of the simple-sum monetary aggregate although, importantly, it isn’t chain linked and thus our results may vary depending on the base year chosen.
Superlative Index numbers are superior for reasons already discussed, and among those, the Divisia-Törnqvist indexes are the most robust that we can come to construct.
common_dates <- index(quant.money.xts) ##alining th indexes
usercost.xts <- usercost.xts[common_dates,]
quant.money.xts <- quant.money.xts[common_dates, ]
monthly_xts <- xts(, order.by = common_dates)
The first step is to calculate what we call expendature shares for each observation. The expendature for asset i is defined as cost times quantity, which sets it as the usercost of i times the quantity of i. The total expendature is the rowise sum of individual asset expendature. The fraction of the expendature of asset i and the total expendature share multiplied by the user cost represents the relative shares of each asset.
Now, already I find this interesting because I see the capacity for accounting for asset substitution in, what we may call the economy’s money portfolio.
# Calculate expenditure shares (s_{i,t})
# s_{i,t} = (user_cost_{i,t} * quantity_{i,t}) / total_expenditure_t
expenditure.xts <- usercost.xts * quant.money.xts
total_expenditure <- rowSums(expenditure.xts, na.rm = TRUE)
shares <- expenditure.xts / total_expenditure ## s_{i,t}
plot(shares)
plot(expenditure.xts)
# 3. Compute lagged quantities and shares
lag_quantities <- lag.xts(quant.money.xts, 1)
lag_shares <- lag.xts(shares, 1)
Lagged qantities and shares are essentially the shares from the previous period
# 4. Calculate Törnqvist index components
# a. Quantity growth ratios
lag_quantities[lag_quantities < 1e-10] <- NA
growth_ratios <- quant.money.xts / lag_quantities
growth_ratios[growth_ratios <= 0 | is.infinite(growth_ratios)] <- NA
growth_ratios[growth_ratios > 1e100] <- NA
Growth ratios are, just that, the ratio of the present quantities to the previous ones
# b. Weighted average of shares (t and t-1), this is the chaining of weights
weights <- (shares + lag_shares) / 2
The weights for our tornqvist index incorporate shares from the present period and the last, almost “chaining” the observations to one another.
# c. Compute log-growth contributions
log_growth <- log(growth_ratios) * weights
Multiplying the log of the growth ratios by the weights tells us the log-growth contributions of each asset
# 5. Sum contributions across assets (for each period)
sum_log_growth <- rowSums(log_growth, na.rm = TRUE)
sumlog.growth.xts <- xts(sum_log_growth, order.by = common_dates)
summary(sumlog.growth.xts) # Look for -Inf/Inf
## Index sumlog.growth.xts
## Min. :1994-01-01 Min. :-0.823557
## 1st Qu.:2001-04-01 1st Qu.:-0.020858
## Median :2008-07-01 Median : 0.008185
## Mean :2008-07-01 Mean : 0.007895
## 3rd Qu.:2015-10-01 3rd Qu.: 0.041315
## Max. :2023-01-01 Max. : 0.589000
Taking the rowise sum of the log growth contributions allows us to create an xts object of the total contribution to the changes in the T index.
cumulative_log_growth <- cumsum(replace(sum_log_growth, is.na(sum_log_growth), 0))
tornqvist_vals <- 100 * exp(cumulative_log_growth - cumulative_log_growth[1])
tornqvist_index <- xts(tornqvist_vals, order.by = common_dates)
The values for our tornqvist index are computed by taking 100 times exp(change in cumulative log growth after 1 period)
n <- length(common_dates)
tornqvist_vals <- rep(NA_real_, n)
tornqvist_vals[1] <- 100 # Base period
for (i in 2:n) {
if (!is.na(sum_log_growth[i])) {
tornqvist_vals[i] <- tornqvist_vals[i-1] * exp(sum_log_growth[i])
}
}
# 8. Create final xts object
tornqvist_index <- xts(tornqvist_vals, order.by = common_dates)
# 7. (Optional) Rename and inspect
colnames(tornqvist_index) <- "Tornqvist_Index"
head(tornqvist_index)
## Tornqvist_Index
## 1994-01-01 100.0000
## 1994-02-01 104.9856
## 1994-03-01 109.8296
## 1994-04-01 113.3495
## 1994-05-01 116.8605
## 1994-06-01 120.3268
plot(sumlog.growth.xts)
plot(tornqvist_index)
tornqvist.window <- window(
tornqvist_index,
start = "2013-12-01",
end = "2023-01-01"
)
plot(tornqvist.window)
ln.tornqvist <- log(tornqvist_index) ##Log transformed tornqvist index
plot(ln.tornqvist)
We have officially created a tornqvist index. it looks wonky but it does reflect the 2020 inflation was quite unprecedented. Using the eye test, the money supply became slightly more volatile post 2008, this may reflect financial innovation or an increase in trading noise.
df.Mon.Off <- df.MQB %>% ### The Official M1, M2 and M3
dplyr::select(
date,
KBP1371M,
KBP1373M,
KBP1374M
)
monthly_xts <- xts(, order.by = common_dates)
Mon.off.xts <- xts(df.Mon.Off[,-1], order.by = df.Mon.Off$date)
colnames(Mon.off.xts) <- c("M(1)", "M(2)", "M(3)")
head(Mon.off.xts)
## M(1) M(2) M(3)
## 1994-01-01 77830 179000 211764
## 1994-02-01 83180 189328 219846
## 1994-03-01 84606 193007 224061
## 1994-04-01 86038 192238 222287
## 1994-05-01 91411 199770 227212
## 1994-06-01 90297 196484 224620
This is an xts object of the three official monetary aggregates
sqr.Mon <- Mon.off.xts*Mon.off.xts
sum.sqrs.mon <- rowSums(sqr.Mon)
g.mean.mon <- sqrt(sum.sqrs.mon/3) ## I bet you were confused lol, I'm taking the geometric mean of the three aggregates because my intuition has it that a geometric mean would be more informatve
mean.M.xts <- xts(g.mean.mon, order.by = df.Mon.Off$date)
plot(mean.M.xts)
I couldn’t make my mind up as to which aggregate to use so I went. with the geometric mean of the three of them. This looks a lot like my simple sum aggregate which makes me think I have been mostly in line with convention when it comes to the selection of magnitudes in the simple sum aggregare.
plot(mean.M.xts)
ln.M.xts <- log(mean.M.xts) ## log transform
plot(ln.M.xts)
nom.GDP <- df.NatAccM %>%
dplyr::select(date,
KBP6006L_Q_N_S_LA)
nom.GDP.xts <- xts(nom.GDP, order.by = nom.GDP$date)
merged_data <- merge(monthly_xts, nom.GDP.xts)
## Warning in merge.xts(monthly_xts, nom.GDP.xts): NAs introduced by coercion
merged.data.n <- merged_data[, -1]
nGDP.imp <- na_ma(merged.data.n, k = 4, weighting = "exponential")
ln.nGDP.xts <- log(nGDP.imp)
offlogvar.data <- cbind(ln.M.xts, ln.nGDP.xts)
colnames(offlogvar.data) <- c("M( log of geometric sum of official)", "log of nominal GDP")
offloglag_selection <- VARselect(offlogvar.data, type = "const") # "const" includes intercept
offlogoptimal_lags <- offloglag_selection$selection["AIC(n)"] # Use AIC criterion
offlog.model <- vars::VAR(
y = offlogvar.data,
p = offlogoptimal_lags, # Lag order from selection
type = "const", # Include constant term
season = NULL,
exogen = NULL
)
summary(offlog.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: M..log.of.geometric.sum.of.official., log.of.nominal.GDP
## Deterministic variables: const
## Sample size: 339
## Log Likelihood: 2183.345
## Roots of the characteristic polynomial:
## 0.9972 0.9569 0.9104 0.9104 0.8627 0.8412 0.8412 0.8352 0.8352 0.8196 0.8196 0.7762 0.7762 0.7157 0.7157 0.6583 0.6583 0.5806 0.5544 0.5544
## Call:
## vars::VAR(y = offlogvar.data, p = offlogoptimal_lags, type = "const",
## exogen = NULL)
##
##
## Estimation results for equation M..log.of.geometric.sum.of.official.:
## =====================================================================
## M..log.of.geometric.sum.of.official. = M..log.of.geometric.sum.of.official..l1 + log.of.nominal.GDP.l1 + M..log.of.geometric.sum.of.official..l2 + log.of.nominal.GDP.l2 + M..log.of.geometric.sum.of.official..l3 + log.of.nominal.GDP.l3 + M..log.of.geometric.sum.of.official..l4 + log.of.nominal.GDP.l4 + M..log.of.geometric.sum.of.official..l5 + log.of.nominal.GDP.l5 + M..log.of.geometric.sum.of.official..l6 + log.of.nominal.GDP.l6 + M..log.of.geometric.sum.of.official..l7 + log.of.nominal.GDP.l7 + M..log.of.geometric.sum.of.official..l8 + log.of.nominal.GDP.l8 + M..log.of.geometric.sum.of.official..l9 + log.of.nominal.GDP.l9 + M..log.of.geometric.sum.of.official..l10 + log.of.nominal.GDP.l10 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M..log.of.geometric.sum.of.official..l1 0.881176 0.055719 15.815 < 2e-16
## log.of.nominal.GDP.l1 0.198709 0.088375 2.248 0.02523
## M..log.of.geometric.sum.of.official..l2 0.105290 0.075833 1.388 0.16597
## log.of.nominal.GDP.l2 -0.470610 0.147621 -3.188 0.00158
## M..log.of.geometric.sum.of.official..l3 -0.036600 0.077009 -0.475 0.63493
## log.of.nominal.GDP.l3 0.499066 0.152849 3.265 0.00121
## M..log.of.geometric.sum.of.official..l4 0.139963 0.076774 1.823 0.06923
## log.of.nominal.GDP.l4 -0.164853 0.150188 -1.098 0.27319
## M..log.of.geometric.sum.of.official..l5 -0.152215 0.076635 -1.986 0.04786
## log.of.nominal.GDP.l5 -0.242502 0.147130 -1.648 0.10030
## M..log.of.geometric.sum.of.official..l6 0.069503 0.076296 0.911 0.36300
## log.of.nominal.GDP.l6 0.441712 0.147257 3.000 0.00292
## M..log.of.geometric.sum.of.official..l7 -0.003475 0.075179 -0.046 0.96316
## log.of.nominal.GDP.l7 -0.230546 0.152017 -1.517 0.13037
## M..log.of.geometric.sum.of.official..l8 0.058326 0.074085 0.787 0.43170
## log.of.nominal.GDP.l8 -0.072096 0.154120 -0.468 0.64026
## M..log.of.geometric.sum.of.official..l9 -0.034828 0.074553 -0.467 0.64071
## log.of.nominal.GDP.l9 0.223139 0.147885 1.509 0.13233
## M..log.of.geometric.sum.of.official..l10 -0.051571 0.056589 -0.911 0.36282
## log.of.nominal.GDP.l10 -0.155449 0.085857 -1.811 0.07115
## const -0.044147 0.050358 -0.877 0.38134
##
## M..log.of.geometric.sum.of.official..l1 ***
## log.of.nominal.GDP.l1 *
## M..log.of.geometric.sum.of.official..l2
## log.of.nominal.GDP.l2 **
## M..log.of.geometric.sum.of.official..l3
## log.of.nominal.GDP.l3 **
## M..log.of.geometric.sum.of.official..l4 .
## log.of.nominal.GDP.l4
## M..log.of.geometric.sum.of.official..l5 *
## log.of.nominal.GDP.l5
## M..log.of.geometric.sum.of.official..l6
## log.of.nominal.GDP.l6 **
## M..log.of.geometric.sum.of.official..l7
## log.of.nominal.GDP.l7
## M..log.of.geometric.sum.of.official..l8
## log.of.nominal.GDP.l8
## M..log.of.geometric.sum.of.official..l9
## log.of.nominal.GDP.l9
## M..log.of.geometric.sum.of.official..l10
## log.of.nominal.GDP.l10 .
## const
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.01267 on 318 degrees of freedom
## Multiple R-Squared: 0.9998, Adjusted R-squared: 0.9998
## F-statistic: 8.094e+04 on 20 and 318 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation log.of.nominal.GDP:
## ===================================================
## log.of.nominal.GDP = M..log.of.geometric.sum.of.official..l1 + log.of.nominal.GDP.l1 + M..log.of.geometric.sum.of.official..l2 + log.of.nominal.GDP.l2 + M..log.of.geometric.sum.of.official..l3 + log.of.nominal.GDP.l3 + M..log.of.geometric.sum.of.official..l4 + log.of.nominal.GDP.l4 + M..log.of.geometric.sum.of.official..l5 + log.of.nominal.GDP.l5 + M..log.of.geometric.sum.of.official..l6 + log.of.nominal.GDP.l6 + M..log.of.geometric.sum.of.official..l7 + log.of.nominal.GDP.l7 + M..log.of.geometric.sum.of.official..l8 + log.of.nominal.GDP.l8 + M..log.of.geometric.sum.of.official..l9 + log.of.nominal.GDP.l9 + M..log.of.geometric.sum.of.official..l10 + log.of.nominal.GDP.l10 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M..log.of.geometric.sum.of.official..l1 -0.151482 0.034587 -4.380 1.62e-05
## log.of.nominal.GDP.l1 1.342363 0.054858 24.470 < 2e-16
## M..log.of.geometric.sum.of.official..l2 0.142078 0.047072 3.018 0.002748
## log.of.nominal.GDP.l2 -0.421856 0.091634 -4.604 6.01e-06
## M..log.of.geometric.sum.of.official..l3 0.003813 0.047802 0.080 0.936482
## log.of.nominal.GDP.l3 -0.092009 0.094879 -0.970 0.332907
## M..log.of.geometric.sum.of.official..l4 0.056360 0.047656 1.183 0.237838
## log.of.nominal.GDP.l4 0.296017 0.093227 3.175 0.001644
## M..log.of.geometric.sum.of.official..l5 0.043963 0.047570 0.924 0.356096
## log.of.nominal.GDP.l5 -0.414757 0.091329 -4.541 7.94e-06
## M..log.of.geometric.sum.of.official..l6 -0.065191 0.047360 -1.376 0.169637
## log.of.nominal.GDP.l6 0.473683 0.091408 5.182 3.91e-07
## M..log.of.geometric.sum.of.official..l7 -0.058858 0.046666 -1.261 0.208143
## log.of.nominal.GDP.l7 -0.312593 0.094362 -3.313 0.001031
## M..log.of.geometric.sum.of.official..l8 0.129858 0.045987 2.824 0.005046
## log.of.nominal.GDP.l8 0.004113 0.095668 0.043 0.965736
## M..log.of.geometric.sum.of.official..l9 -0.058183 0.046278 -1.257 0.209581
## log.of.nominal.GDP.l9 0.301371 0.091798 3.283 0.001141
## M..log.of.geometric.sum.of.official..l10 -0.029510 0.035127 -0.840 0.401489
## log.of.nominal.GDP.l10 -0.193648 0.053295 -3.634 0.000326
## const 0.081137 0.031259 2.596 0.009880
##
## M..log.of.geometric.sum.of.official..l1 ***
## log.of.nominal.GDP.l1 ***
## M..log.of.geometric.sum.of.official..l2 **
## log.of.nominal.GDP.l2 ***
## M..log.of.geometric.sum.of.official..l3
## log.of.nominal.GDP.l3
## M..log.of.geometric.sum.of.official..l4
## log.of.nominal.GDP.l4 **
## M..log.of.geometric.sum.of.official..l5
## log.of.nominal.GDP.l5 ***
## M..log.of.geometric.sum.of.official..l6
## log.of.nominal.GDP.l6 ***
## M..log.of.geometric.sum.of.official..l7
## log.of.nominal.GDP.l7 **
## M..log.of.geometric.sum.of.official..l8 **
## log.of.nominal.GDP.l8
## M..log.of.geometric.sum.of.official..l9
## log.of.nominal.GDP.l9 **
## M..log.of.geometric.sum.of.official..l10
## log.of.nominal.GDP.l10 ***
## const **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.007862 on 318 degrees of freedom
## Multiple R-Squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 1.495e+05 on 20 and 318 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## M..log.of.geometric.sum.of.official.
## M..log.of.geometric.sum.of.official. 1.604e-04
## log.of.nominal.GDP 2.924e-07
## log.of.nominal.GDP
## M..log.of.geometric.sum.of.official. 2.924e-07
## log.of.nominal.GDP 6.182e-05
##
## Correlation matrix of residuals:
## M..log.of.geometric.sum.of.official.
## M..log.of.geometric.sum.of.official. 1.000000
## log.of.nominal.GDP 0.002936
## log.of.nominal.GDP
## M..log.of.geometric.sum.of.official. 0.002936
## log.of.nominal.GDP 1.000000
offlogirf_results <- irf(offlog.model,
impulse = "M..log.of.geometric.sum.of.official.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(offlogirf_results)
nomofflogirf_results <- irf(offlog.model,
impulse = "log.of.nominal.GDP",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(nomofflogirf_results)
Using the geometric sum of the monetary aggregates, I believe we come to a different conclusion than my T index suggests. This M(g) almost implies an oscilatory propogation mechanism for monetary shocks. This can be seen using an impulse response function on the data.
## To see how much more helpful a divisia-inspired monetary aggregate can be, we bring back the classical equation of exchange. MV=PY, looking at nominal GDP to calculate implicit velocity measures.
monthly_xts <- xts(, order.by = common_dates)
real.GDE <- df.NatAccM %>%
dplyr::select(date,
KBP6019D_Q_R_S_LA)
real.GDE.xts <- xts(real.GDE[,-1], order.by = df.NatAccM$date)
colnames(real.GDE.xts) <- "Real GDE in 2015 prices"
rGDE.sup <- merge(monthly_xts, real.GDE.xts)
realGDEimp.xts <- na_ma(rGDE.sup, k = 6, weighting = "linear")
nominal.GDE <- df.NatAccM %>%
dplyr::select(date,
KBP6012L_Q_N_S_LA)
nominal.GDE.xts <- xts(nominal.GDE[,-1], order.by = df.NatAccM$date)
colnames(nominal.GDE.xts) <- "Nominal GDE in 2015 prices"
deflated.GDE.xts <- (nominal.GDE.xts/real.GDE.xts)
colnames(deflated.GDE.xts) <- "GDE Deflator"
realmerged_data <- merge(monthly_xts, deflated.GDE.xts)
deflate.GDE.xts <- na_ma(realmerged_data, k = 6, weighting = "linear")*100
plot(deflate.GDE.xts) #the GDE deflator
log.defEx.xts <- log(deflate.GDE.xts)
plot(log.defEx.xts) #the log of the GDE deflator
#///////////////////////////////////////////////////////////////////////////////
##NominalGDP
plot(nGDP.imp)
nGDP.window <- window(
nGDP.imp,
start = "2013-12-01",
end = "2023-01-01"
)
nGDP.win.xts <- xts(nGDP.window, order.by =index(tornqvist.window))
plot(nGDP.win.xts)
So now we have three time series objects, our simple sum index, our tornqvist index number and we have quarterly nominal GDP figures indexed monthly through linear interpolation. From here we can conduct VAR between our nominal GDP and either monetary aggregate to see if there’s any difference and why.
var.data <- cbind(ss.index.xts, nGDP.imp)
colnames(var.data) <- c("M(sum)", "nGDP")
lag_selection <- VARselect(var.data, type = "const") # "const" includes intercept
optimal_lags <- lag_selection$selection["SC(n)"] # Use AIC criterion
ss.model <- vars::VAR(
y = var.data,
p = optimal_lags, # Lag order from selection
type = "const", # Include constant term
season = NULL,
exogen = NULL
)
summary(ss.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: M.sum., nGDP
## Deterministic variables: const
## Sample size: 343
## Log Likelihood: -5069.309
## Roots of the characteristic polynomial:
## 1.004 0.9668 0.8537 0.8093 0.8093 0.7849 0.7849 0.731 0.731 0.7097 0.7097 0.7042
## Call:
## vars::VAR(y = var.data, p = optimal_lags, type = "const", exogen = NULL)
##
##
## Estimation results for equation M.sum.:
## =======================================
## M.sum. = M.sum..l1 + nGDP.l1 + M.sum..l2 + nGDP.l2 + M.sum..l3 + nGDP.l3 + M.sum..l4 + nGDP.l4 + M.sum..l5 + nGDP.l5 + M.sum..l6 + nGDP.l6 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M.sum..l1 8.262e-01 5.459e-02 15.135 < 2e-16 ***
## nGDP.l1 1.315e-05 7.844e-06 1.677 0.09454 .
## M.sum..l2 6.282e-02 7.588e-02 0.828 0.40835
## nGDP.l2 -3.600e-05 1.306e-05 -2.756 0.00617 **
## M.sum..l3 1.008e-01 7.764e-02 1.299 0.19487
## nGDP.l3 3.421e-05 1.222e-05 2.800 0.00541 **
## M.sum..l4 -1.056e-02 7.396e-02 -0.143 0.88660
## nGDP.l4 -1.328e-05 1.236e-05 -1.074 0.28340
## M.sum..l5 -1.707e-01 7.512e-02 -2.272 0.02374 *
## nGDP.l5 -1.977e-06 1.272e-05 -0.155 0.87655
## M.sum..l6 1.695e-01 5.998e-02 2.826 0.00500 **
## nGDP.l6 8.357e-06 7.397e-06 1.130 0.25938
## const -5.658e-01 8.758e-01 -0.646 0.51870
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 4.951 on 330 degrees of freedom
## Multiple R-Squared: 0.9997, Adjusted R-squared: 0.9997
## F-statistic: 9.072e+04 on 12 and 330 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation nGDP:
## =====================================
## nGDP = M.sum..l1 + nGDP.l1 + M.sum..l2 + nGDP.l2 + M.sum..l3 + nGDP.l3 + M.sum..l4 + nGDP.l4 + M.sum..l5 + nGDP.l5 + M.sum..l6 + nGDP.l6 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M.sum..l1 -3.113e+03 3.553e+02 -8.761 < 2e-16 ***
## nGDP.l1 1.366e+00 5.106e-02 26.750 < 2e-16 ***
## M.sum..l2 2.265e+03 4.939e+02 4.585 6.46e-06 ***
## nGDP.l2 -3.665e-01 8.502e-02 -4.311 2.15e-05 ***
## M.sum..l3 1.815e+02 5.054e+02 0.359 0.719795
## nGDP.l3 -3.035e-01 7.955e-02 -3.815 0.000162 ***
## M.sum..l4 2.639e+03 4.814e+02 5.482 8.35e-08 ***
## nGDP.l4 6.083e-01 8.044e-02 7.562 3.97e-13 ***
## M.sum..l5 2.594e+02 4.890e+02 0.530 0.596157
## nGDP.l5 -5.811e-01 8.280e-02 -7.018 1.28e-11 ***
## M.sum..l6 -2.148e+03 3.904e+02 -5.503 7.53e-08 ***
## nGDP.l6 2.681e-01 4.815e-02 5.568 5.35e-08 ***
## const 1.270e+04 5.701e+03 2.227 0.026603 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 32230 on 330 degrees of freedom
## Multiple R-Squared: 0.9997, Adjusted R-squared: 0.9997
## F-statistic: 9.615e+04 on 12 and 330 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## M.sum. nGDP
## M.sum. 24.51 1.957e+03
## nGDP 1956.80 1.039e+09
##
## Correlation matrix of residuals:
## M.sum. nGDP
## M.sum. 1.00000 0.01226
## nGDP 0.01226 1.00000
Mssirf_results <- irf(ss.model,
impulse = "M.sum.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Mssirf_results)
Yssirf_results <- irf(ss.model,
impulse = "nGDP",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Yssirf_results)
Tvar.data <- cbind(tornqvist_index, nGDP.imp)
colnames(Tvar.data) <- c("M(Torn)", "nGDP")
Tlag_selection <- VARselect(Tvar.data, type = "const") # "const" includes intercept
Toptimal_lags <- Tlag_selection$selection["HQ(n)"] # HQ
T.model <- vars::VAR(
y = Tvar.data,
p = Toptimal_lags, # Lag order from selection
type = "const", # Include constant term
season = NULL,
exogen = NULL
)
summary(T.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: M.Torn., nGDP
## Deterministic variables: const
## Sample size: 343
## Log Likelihood: -6414.176
## Roots of the characteristic polynomial:
## 1.004 0.9873 0.8508 0.8029 0.8029 0.7658 0.7658 0.6616 0.6616 0.2856 0.2856 0.2628
## Call:
## vars::VAR(y = Tvar.data, p = Toptimal_lags, type = "const", exogen = NULL)
##
##
## Estimation results for equation M.Torn.:
## ========================================
## M.Torn. = M.Torn..l1 + nGDP.l1 + M.Torn..l2 + nGDP.l2 + M.Torn..l3 + nGDP.l3 + M.Torn..l4 + nGDP.l4 + M.Torn..l5 + nGDP.l5 + M.Torn..l6 + nGDP.l6 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M.Torn..l1 7.533e-01 5.509e-02 13.675 < 2e-16 ***
## nGDP.l1 4.009e-04 3.252e-04 1.233 0.219
## M.Torn..l2 -7.766e-02 6.967e-02 -1.115 0.266
## nGDP.l2 -8.445e-04 5.578e-04 -1.514 0.131
## M.Torn..l3 5.650e-01 6.673e-02 8.467 8.39e-16 ***
## nGDP.l3 7.835e-04 5.345e-04 1.466 0.144
## M.Torn..l4 -3.399e-01 6.611e-02 -5.141 4.70e-07 ***
## nGDP.l4 -2.401e-05 5.301e-04 -0.045 0.964
## M.Torn..l5 8.889e-02 7.094e-02 1.253 0.211
## nGDP.l5 -5.272e-04 5.392e-04 -0.978 0.329
## M.Torn..l6 -6.555e-03 5.763e-02 -0.114 0.910
## nGDP.l6 2.139e-04 3.155e-04 0.678 0.498
## const 1.227e+01 2.269e+01 0.541 0.589
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 222.1 on 330 degrees of freedom
## Multiple R-Squared: 0.97, Adjusted R-squared: 0.9689
## F-statistic: 888.9 on 12 and 330 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation nGDP:
## =====================================
## nGDP = M.Torn..l1 + nGDP.l1 + M.Torn..l2 + nGDP.l2 + M.Torn..l3 + nGDP.l3 + M.Torn..l4 + nGDP.l4 + M.Torn..l5 + nGDP.l5 + M.Torn..l6 + nGDP.l6 + const
##
## Estimate Std. Error t value Pr(>|t|)
## M.Torn..l1 31.45456 9.00877 3.492 0.000546 ***
## nGDP.l1 1.43825 0.05319 27.041 < 2e-16 ***
## M.Torn..l2 2.84868 11.39460 0.250 0.802741
## nGDP.l2 -0.49023 0.09123 -5.374 1.46e-07 ***
## M.Torn..l3 -9.17391 10.91284 -0.841 0.401151
## nGDP.l3 -0.27155 0.08742 -3.106 0.002059 **
## M.Torn..l4 -49.46805 10.81221 -4.575 6.74e-06 ***
## nGDP.l4 0.57288 0.08669 6.608 1.56e-10 ***
## M.Torn..l5 16.91209 11.60095 1.458 0.145841
## nGDP.l5 -0.49931 0.08819 -5.662 3.26e-08 ***
## M.Torn..l6 6.19622 9.42458 0.657 0.511348
## nGDP.l6 0.25412 0.05159 4.925 1.33e-06 ***
## const 6423.61827 3710.55776 1.731 0.084356 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 36320 on 330 degrees of freedom
## Multiple R-Squared: 0.9996, Adjusted R-squared: 0.9996
## F-statistic: 7.571e+04 on 12 and 330 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## M.Torn. nGDP
## M.Torn. 49315 -518236
## nGDP -518236 1318980153
##
## Correlation matrix of residuals:
## M.Torn. nGDP
## M.Torn. 1.00000 -0.06426
## nGDP -0.06426 1.00000
Tirf_results <- irf(T.model,
impulse = "M.Torn.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Tirf_results)
TYirf_results <- irf(T.model,
impulse = "nGDP",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(TYirf_results)
A Naive VAR(6) model looking at The custom Tornqvist index and its interrelationship provides results that imply our series fail the unit root test (stationarity) which means we may end up with impulses whose effect never dissipates. However, it implies, quite heavily, that the money supply has had more of an influence on future values of nominal GDP than nominal GDP has had on the money supply. A money supply shock seems begin with a reduction in nominal GDP, followed by a reversal.
##Perhaps looking at log transformed GDP data
log.GDP <- log(nGDP.imp)
logvar_data <- cbind(ln.tornqvist, log.GDP)
colnames(logvar_data) <- c("log(Mt)", "log(nGDP)")
log.lag_selection <- VARselect(logvar_data, lag.max = 8, type = "const")
log.optimal_lags <- log.lag_selection$selection["AIC(n)"]
log.model <- vars::VAR(
y= logvar_data,
p= log.optimal_lags,
type = "const",
season = NULL,
exogen = NULL
)
summary(log.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: log.Mt., log.nGDP.
## Deterministic variables: const
## Sample size: 341
## Log Likelihood: 1440.161
## Roots of the characteristic polynomial:
## 0.9978 0.9858 0.8819 0.8483 0.8483 0.7729 0.7729 0.7583 0.7583 0.6312 0.6312 0.6243 0.6243 0.5099 0.5099 0.1087
## Call:
## vars::VAR(y = logvar_data, p = log.optimal_lags, type = "const",
## exogen = NULL)
##
##
## Estimation results for equation log.Mt.:
## ========================================
## log.Mt. = log.Mt..l1 + log.nGDP..l1 + log.Mt..l2 + log.nGDP..l2 + log.Mt..l3 + log.nGDP..l3 + log.Mt..l4 + log.nGDP..l4 + log.Mt..l5 + log.nGDP..l5 + log.Mt..l6 + log.nGDP..l6 + log.Mt..l7 + log.nGDP..l7 + log.Mt..l8 + log.nGDP..l8 + const
##
## Estimate Std. Error t value Pr(>|t|)
## log.Mt..l1 0.723599 0.055874 12.950 < 2e-16 ***
## log.nGDP..l1 0.419296 0.786647 0.533 0.59439
## log.Mt..l2 0.099209 0.070250 1.412 0.15884
## log.nGDP..l2 -0.978674 1.269478 -0.771 0.44131
## log.Mt..l3 0.343424 0.070433 4.876 1.7e-06 ***
## log.nGDP..l3 1.368806 1.264239 1.083 0.27974
## log.Mt..l4 -0.217040 0.072950 -2.975 0.00315 **
## log.nGDP..l4 -0.251069 1.250993 -0.201 0.84106
## log.Mt..l5 0.028724 0.076453 0.376 0.70738
## log.nGDP..l5 -0.623243 1.207864 -0.516 0.60622
## log.Mt..l6 -0.007138 0.072870 -0.098 0.92203
## log.nGDP..l6 0.182429 1.204694 0.151 0.87973
## log.Mt..l7 0.014604 0.072369 0.202 0.84021
## log.nGDP..l7 0.504344 1.202967 0.419 0.67531
## log.Mt..l8 -0.003130 0.059482 -0.053 0.95807
## log.nGDP..l8 -0.602606 0.732241 -0.823 0.41113
## const -0.168976 0.213980 -0.790 0.43029
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.1146 on 324 degrees of freedom
## Multiple R-Squared: 0.9894, Adjusted R-squared: 0.9888
## F-statistic: 1885 on 16 and 324 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation log.nGDP.:
## ==========================================
## log.nGDP. = log.Mt..l1 + log.nGDP..l1 + log.Mt..l2 + log.nGDP..l2 + log.Mt..l3 + log.nGDP..l3 + log.Mt..l4 + log.nGDP..l4 + log.Mt..l5 + log.nGDP..l5 + log.Mt..l6 + log.nGDP..l6 + log.Mt..l7 + log.nGDP..l7 + log.Mt..l8 + log.nGDP..l8 + const
##
## Estimate Std. Error t value Pr(>|t|)
## log.Mt..l1 1.256e-02 3.865e-03 3.250 0.00128 **
## log.nGDP..l1 1.313e+00 5.441e-02 24.122 < 2e-16 ***
## log.Mt..l2 3.223e-03 4.859e-03 0.663 0.50767
## log.nGDP..l2 -4.202e-01 8.781e-02 -4.785 2.60e-06 ***
## log.Mt..l3 1.595e-03 4.872e-03 0.327 0.74366
## log.nGDP..l3 9.067e-02 8.745e-02 1.037 0.30059
## log.Mt..l4 -2.965e-02 5.046e-03 -5.875 1.05e-08 ***
## log.nGDP..l4 1.100e-02 8.654e-02 0.127 0.89897
## log.Mt..l5 3.290e-03 5.289e-03 0.622 0.53426
## log.nGDP..l5 -2.365e-01 8.355e-02 -2.830 0.00494 **
## log.Mt..l6 7.231e-06 5.041e-03 0.001 0.99886
## log.nGDP..l6 4.364e-01 8.333e-02 5.236 2.95e-07 ***
## log.Mt..l7 8.804e-03 5.006e-03 1.759 0.07957 .
## log.nGDP..l7 -4.128e-01 8.321e-02 -4.960 1.14e-06 ***
## log.Mt..l8 -4.339e-04 4.115e-03 -0.105 0.91608
## log.nGDP..l8 2.171e-01 5.065e-02 4.286 2.40e-05 ***
## const 3.705e-02 1.480e-02 2.503 0.01280 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.007926 on 324 degrees of freedom
## Multiple R-Squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 1.88e+05 on 16 and 324 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## log.Mt. log.nGDP.
## log.Mt. 1.313e-02 -9.886e-05
## log.nGDP. -9.886e-05 6.282e-05
##
## Correlation matrix of residuals:
## log.Mt. log.nGDP.
## log.Mt. 1.0000 -0.1089
## log.nGDP. -0.1089 1.0000
Tlogirf_results <- irf(log.model,
impulse = "log.Mt.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Tlogirf_results)
Ylogirf_results <- irf(log.model,
impulse = "log.nGDP.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Ylogirf_results)
Overall, it seems there is a marked lack of a relationship between the log of nominal GDP and the log of my TD Index. This implies the short-run expansionary effects of monetary policy have little influence on nominal GDP while the autoregressive effects are dampening. The impulse response to a change in nominal GDP has a largely uninformative effect, the confdence intervals include zero for 20 periods. Despite this, however, it looks like a logNGDP shock is sef-persistent while there is apparent negative relationship between the Log GDP and the Log Tornqvist.
Perhaps comparing the monetary aggregate to the deflated version of GDP may tease out a relationship between the money supply and inflation.
Before that, a VAR using the geometric mean of the monetary indexes and nominal GDP
log.YGDP.xts <- log(nGDP.imp)
plot(log.YGDP.xts)
And now we compare the geometric mean of the three monetary aggregates to nGDP’
log.OGDP <- log(nGDP.imp)
log.offM.xts <- log(mean.M.xts)
logY_data <- cbind(log.offM.xts, log.OGDP)
colnames(logY_data) <- c("log(MOff)", "log(nGDP)")
plot(logY_data)
log.Ylag_selection <- vars::VARselect(logY_data, lag.max = 8, type = "const")
log.Yoptimal_lags <- log.Ylag_selection$selection["AIC(n)"]
log.Ymodel <- vars::VAR(
y= logY_data,
p= log.Yoptimal_lags,
type = "const",
season = NULL,
exogen = NULL
)
Tlogirf_results <- irf(log.Ymodel,
impulse = "log.MOff.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Tlogirf_results)
Yofflogirf_results <- irf(log.Ymodel,
impulse = "log.nGDP.",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(Yofflogirf_results)
summary(log.Ymodel)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: log.MOff., log.nGDP.
## Deterministic variables: const
## Sample size: 341
## Log Likelihood: 2183.217
## Roots of the characteristic polynomial:
## 0.9973 0.9602 0.8752 0.8666 0.8666 0.7913 0.7913 0.7657 0.7657 0.6986 0.6986 0.6682 0.4686 0.4686 0.4363 0.1795
## Call:
## vars::VAR(y = logY_data, p = log.Yoptimal_lags, type = "const",
## exogen = NULL)
##
##
## Estimation results for equation log.MOff.:
## ==========================================
## log.MOff. = log.MOff..l1 + log.nGDP..l1 + log.MOff..l2 + log.nGDP..l2 + log.MOff..l3 + log.nGDP..l3 + log.MOff..l4 + log.nGDP..l4 + log.MOff..l5 + log.nGDP..l5 + log.MOff..l6 + log.nGDP..l6 + log.MOff..l7 + log.nGDP..l7 + log.MOff..l8 + log.nGDP..l8 + const
##
## Estimate Std. Error t value Pr(>|t|)
## log.MOff..l1 0.883034 0.055599 15.882 < 2e-16 ***
## log.nGDP..l1 0.190478 0.085602 2.225 0.026759 *
## log.MOff..l2 0.105738 0.075604 1.399 0.162898
## log.nGDP..l2 -0.485292 0.139239 -3.485 0.000559 ***
## log.MOff..l3 -0.023814 0.076375 -0.312 0.755385
## log.nGDP..l3 0.574927 0.141496 4.063 6.08e-05 ***
## log.MOff..l4 0.125727 0.075392 1.668 0.096354 .
## log.nGDP..l4 -0.254538 0.141751 -1.796 0.073478 .
## log.MOff..l5 -0.147579 0.074406 -1.983 0.048163 *
## log.nGDP..l5 -0.188602 0.142223 -1.326 0.185740
## log.MOff..l6 0.080415 0.072917 1.103 0.270920
## log.nGDP..l6 0.397187 0.145146 2.736 0.006553 **
## log.MOff..l7 -0.051866 0.072321 -0.717 0.473792
## log.nGDP..l7 -0.245400 0.144268 -1.701 0.089902 .
## log.MOff..l8 0.007561 0.055615 0.136 0.891948
## log.nGDP..l8 0.032766 0.084694 0.387 0.699105
## const -0.018630 0.048837 -0.381 0.703107
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.0127 on 324 degrees of freedom
## Multiple R-Squared: 0.9998, Adjusted R-squared: 0.9998
## F-statistic: 1.031e+05 on 16 and 324 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation log.nGDP.:
## ==========================================
## log.nGDP. = log.MOff..l1 + log.nGDP..l1 + log.MOff..l2 + log.nGDP..l2 + log.MOff..l3 + log.nGDP..l3 + log.MOff..l4 + log.nGDP..l4 + log.MOff..l5 + log.nGDP..l5 + log.MOff..l6 + log.nGDP..l6 + log.MOff..l7 + log.nGDP..l7 + log.MOff..l8 + log.nGDP..l8 + const
##
## Estimate Std. Error t value Pr(>|t|)
## log.MOff..l1 -0.150514 0.035265 -4.268 2.59e-05 ***
## log.nGDP..l1 1.332007 0.054295 24.533 < 2e-16 ***
## log.MOff..l2 0.140478 0.047954 2.929 0.003636 **
## log.nGDP..l2 -0.440383 0.088315 -4.986 1.00e-06 ***
## log.MOff..l3 0.018749 0.048442 0.387 0.698984
## log.nGDP..l3 -0.002485 0.089747 -0.028 0.977929
## log.MOff..l4 0.044548 0.047819 0.932 0.352236
## log.nGDP..l4 0.183891 0.089908 2.045 0.041631 *
## log.MOff..l5 0.040261 0.047193 0.853 0.394234
## log.nGDP..l5 -0.337734 0.090208 -3.744 0.000214 ***
## log.MOff..l6 -0.041716 0.046250 -0.902 0.367742
## log.nGDP..l6 0.415743 0.092062 4.516 8.84e-06 ***
## log.MOff..l7 -0.113202 0.045871 -2.468 0.014109 *
## log.nGDP..l7 -0.335035 0.091505 -3.661 0.000293 ***
## log.MOff..l8 0.077062 0.035275 2.185 0.029635 *
## log.nGDP..l8 0.162594 0.053719 3.027 0.002670 **
## const 0.104103 0.030976 3.361 0.000870 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.008052 on 324 degrees of freedom
## Multiple R-Squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 1.822e+05 on 16 and 324 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## log.MOff. log.nGDP.
## log.MOff. 1.612e-04 4.101e-06
## log.nGDP. 4.101e-06 6.484e-05
##
## Correlation matrix of residuals:
## log.MOff. log.nGDP.
## log.MOff. 1.00000 0.04012
## log.nGDP. 0.04012 1.00000
A positive shock from the log(of the geometric mean of the official aggregates) has a negative effect on nominal GDP in the short run that reverses in the longer period. Increases in the log(M{geom}) are persistent while damping over time, which is consistent with the money supply being highly auto-regressive. Significant lagged periods suggests the log of the geometric mean of m1 through 3 has a significant influence on the future values of nominal GDP. The immediate effect seems to be negative, has a less significant reversal but then reinforces a negative but statistically insignificant relationship.
Ultimately, there’s unlikely to be a relationship between nominal output and the money supply, even in the short term. The classical moneterist perspective falls on it’s face. Unless there’s a relationship between the money supply and general prices. Seeing as I’ve already incorporated CPI inflation as part of the user cost of holding money, I need a different measure of general price movements, which I approximated using deflated gross domestic expendature.
##What of inflation? We're gonna overcomplicate things a bit but that's because CPI is closer to a cost of living index with a basket of goods that rotates every so often. we use deflated statistics for broader generality and because we're less focused on consumer cost of living in this escapade.
inf.mon.xts <- cbind(tornqvist_index, deflate.GDE.xts)
plot(inf.mon.xts)
infmon.lagselect <- vars::VARselect(inf.mon.xts, lag.max = 12, type = "const")
infmon.optilag <- infmon.lagselect$selection["HQ(n)"]
infmon.model <- vars::VAR(
y= inf.mon.xts,
p = infmon.optilag,
type = "const",
season = NULL,
exogen = NULL
)
summary(infmon.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: Tornqvist_Index, GDE.Deflator
## Deterministic variables: const
## Sample size: 345
## Log Likelihood: -2499.853
## Roots of the characteristic polynomial:
## 1.004 0.9833 0.7801 0.7801 0.5544 0.5163 0.388 0.388
## Call:
## vars::VAR(y = inf.mon.xts, p = infmon.optilag, type = "const",
## exogen = NULL)
##
##
## Estimation results for equation Tornqvist_Index:
## ================================================
## Tornqvist_Index = Tornqvist_Index.l1 + GDE.Deflator.l1 + Tornqvist_Index.l2 + GDE.Deflator.l2 + Tornqvist_Index.l3 + GDE.Deflator.l3 + Tornqvist_Index.l4 + GDE.Deflator.l4 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Tornqvist_Index.l1 0.73463 0.05217 14.080 < 2e-16 ***
## GDE.Deflator.l1 -27.35250 31.47688 -0.869 0.38548
## Tornqvist_Index.l2 -0.02659 0.05765 -0.461 0.64497
## GDE.Deflator.l2 120.55096 43.18907 2.791 0.00555 **
## Tornqvist_Index.l3 0.56370 0.05716 9.863 < 2e-16 ***
## GDE.Deflator.l3 -92.73159 44.10058 -2.103 0.03623 *
## Tornqvist_Index.l4 -0.29032 0.05182 -5.602 4.41e-08 ***
## GDE.Deflator.l4 -0.37600 32.90497 -0.011 0.99089
## const -0.55437 29.96297 -0.019 0.98525
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 218.8 on 336 degrees of freedom
## Multiple R-Squared: 0.9705, Adjusted R-squared: 0.9698
## F-statistic: 1380 on 8 and 336 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation GDE.Deflator:
## =============================================
## GDE.Deflator = Tornqvist_Index.l1 + GDE.Deflator.l1 + Tornqvist_Index.l2 + GDE.Deflator.l2 + Tornqvist_Index.l3 + GDE.Deflator.l3 + Tornqvist_Index.l4 + GDE.Deflator.l4 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Tornqvist_Index.l1 8.966e-05 9.196e-05 0.975 0.33027
## GDE.Deflator.l1 8.710e-01 5.548e-02 15.700 < 2e-16 ***
## Tornqvist_Index.l2 -4.753e-05 1.016e-04 -0.468 0.64028
## GDE.Deflator.l2 2.386e-01 7.612e-02 3.134 0.00188 **
## Tornqvist_Index.l3 8.355e-05 1.007e-04 0.829 0.40748
## GDE.Deflator.l3 -1.937e-01 7.773e-02 -2.492 0.01319 *
## Tornqvist_Index.l4 -1.634e-04 9.134e-05 -1.789 0.07444 .
## GDE.Deflator.l4 8.892e-02 5.800e-02 1.533 0.12618
## const 8.322e-02 5.281e-02 1.576 0.11602
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.3857 on 336 degrees of freedom
## Multiple R-Squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 3.307e+05 on 8 and 336 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## Tornqvist_Index GDE.Deflator
## Tornqvist_Index 47893.527 -4.1922
## GDE.Deflator -4.192 0.1488
##
## Correlation matrix of residuals:
## Tornqvist_Index GDE.Deflator
## Tornqvist_Index 1.00000 -0.04966
## GDE.Deflator -0.04966 1.00000
infmon_results <- irf(infmon.model,
impulse = "Tornqvist_Index",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(infmon_results)
nominfmon_results <- irf(infmon.model,
impulse = "GDE.Deflator",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(nominfmon_results)
summary(infmon.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: Tornqvist_Index, GDE.Deflator
## Deterministic variables: const
## Sample size: 345
## Log Likelihood: -2499.853
## Roots of the characteristic polynomial:
## 1.004 0.9833 0.7801 0.7801 0.5544 0.5163 0.388 0.388
## Call:
## vars::VAR(y = inf.mon.xts, p = infmon.optilag, type = "const",
## exogen = NULL)
##
##
## Estimation results for equation Tornqvist_Index:
## ================================================
## Tornqvist_Index = Tornqvist_Index.l1 + GDE.Deflator.l1 + Tornqvist_Index.l2 + GDE.Deflator.l2 + Tornqvist_Index.l3 + GDE.Deflator.l3 + Tornqvist_Index.l4 + GDE.Deflator.l4 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Tornqvist_Index.l1 0.73463 0.05217 14.080 < 2e-16 ***
## GDE.Deflator.l1 -27.35250 31.47688 -0.869 0.38548
## Tornqvist_Index.l2 -0.02659 0.05765 -0.461 0.64497
## GDE.Deflator.l2 120.55096 43.18907 2.791 0.00555 **
## Tornqvist_Index.l3 0.56370 0.05716 9.863 < 2e-16 ***
## GDE.Deflator.l3 -92.73159 44.10058 -2.103 0.03623 *
## Tornqvist_Index.l4 -0.29032 0.05182 -5.602 4.41e-08 ***
## GDE.Deflator.l4 -0.37600 32.90497 -0.011 0.99089
## const -0.55437 29.96297 -0.019 0.98525
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 218.8 on 336 degrees of freedom
## Multiple R-Squared: 0.9705, Adjusted R-squared: 0.9698
## F-statistic: 1380 on 8 and 336 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation GDE.Deflator:
## =============================================
## GDE.Deflator = Tornqvist_Index.l1 + GDE.Deflator.l1 + Tornqvist_Index.l2 + GDE.Deflator.l2 + Tornqvist_Index.l3 + GDE.Deflator.l3 + Tornqvist_Index.l4 + GDE.Deflator.l4 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Tornqvist_Index.l1 8.966e-05 9.196e-05 0.975 0.33027
## GDE.Deflator.l1 8.710e-01 5.548e-02 15.700 < 2e-16 ***
## Tornqvist_Index.l2 -4.753e-05 1.016e-04 -0.468 0.64028
## GDE.Deflator.l2 2.386e-01 7.612e-02 3.134 0.00188 **
## Tornqvist_Index.l3 8.355e-05 1.007e-04 0.829 0.40748
## GDE.Deflator.l3 -1.937e-01 7.773e-02 -2.492 0.01319 *
## Tornqvist_Index.l4 -1.634e-04 9.134e-05 -1.789 0.07444 .
## GDE.Deflator.l4 8.892e-02 5.800e-02 1.533 0.12618
## const 8.322e-02 5.281e-02 1.576 0.11602
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.3857 on 336 degrees of freedom
## Multiple R-Squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 3.307e+05 on 8 and 336 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## Tornqvist_Index GDE.Deflator
## Tornqvist_Index 47893.527 -4.1922
## GDE.Deflator -4.192 0.1488
##
## Correlation matrix of residuals:
## Tornqvist_Index GDE.Deflator
## Tornqvist_Index 1.00000 -0.04966
## GDE.Deflator -0.04966 1.00000
loginf.mon.xts <- cbind(ln.tornqvist, log(deflate.GDE.xts))
loginfmon.lagselect <- vars::VARselect(loginf.mon.xts, lag.max = 12, type = "const")
loginfmon.optilag <- loginfmon.lagselect$selection["AIC(n)"]
loginfmon.model <- vars::VAR(
y= loginf.mon.xts,
p = loginfmon.optilag,
type = "const",
season = NULL,
exogen = NULL
)
loginfmon_results <- irf(loginfmon.model,
impulse = "Tornqvist_Index",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(loginfmon_results)
nloginfmon_results <- irf(loginfmon.model,
impulse = "GDE.Deflator",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(nloginfmon_results)
infcoint_test <- ca.jo(loginf.mon.xts, type = "trace", K = loginfmon.optilag, ecdet = "const")
summary(infcoint_test)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 1.078195e-01 7.940782e-03 3.801045e-16
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 1 | 2.69 7.52 9.24 12.97
## r = 0 | 41.26 17.85 19.96 24.60
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## Tornqvist_Index.l11 GDE.Deflator.l11 constant
## Tornqvist_Index.l11 1.000000 1.0000000 1.000000
## GDE.Deflator.l11 2.326793 -1.6320536 -4.253596
## constant -27.355085 0.3993055 11.106089
##
## Weights W:
## (This is the loading matrix)
##
## Tornqvist_Index.l11 GDE.Deflator.l11 constant
## Tornqvist_Index.d -0.0001425888 -1.899491e-02 2.788204e-16
## GDE.Deflator.d -0.0005031828 7.027545e-05 -5.247601e-17
vecm_infmon <- cajorls(infcoint_test, r = 1)
summary(vecm_infmon[["rlm"]])
## Response Tornqvist_Index.d :
##
## Call:
## lm(formula = Tornqvist_Index.d ~ ect1 + Tornqvist_Index.dl1 +
## GDE.Deflator.dl1 + Tornqvist_Index.dl2 + GDE.Deflator.dl2 +
## Tornqvist_Index.dl3 + GDE.Deflator.dl3 + Tornqvist_Index.dl4 +
## GDE.Deflator.dl4 + Tornqvist_Index.dl5 + GDE.Deflator.dl5 +
## Tornqvist_Index.dl6 + GDE.Deflator.dl6 + Tornqvist_Index.dl7 +
## GDE.Deflator.dl7 + Tornqvist_Index.dl8 + GDE.Deflator.dl8 +
## Tornqvist_Index.dl9 + GDE.Deflator.dl9 + Tornqvist_Index.dl10 +
## GDE.Deflator.dl10 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.80584 -0.03194 -0.00042 0.03310 0.63569
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 -0.0001426 0.0019122 -0.075 0.94061
## Tornqvist_Index.dl1 -0.2777907 0.0562527 -4.938 1.28e-06 ***
## GDE.Deflator.dl1 -1.3739559 1.2927622 -1.063 0.28868
## Tornqvist_Index.dl2 -0.1511973 0.0583847 -2.590 0.01005 *
## GDE.Deflator.dl2 1.8772519 1.2997061 1.444 0.14962
## Tornqvist_Index.dl3 0.1843316 0.0582116 3.167 0.00169 **
## GDE.Deflator.dl3 1.0285014 1.3107560 0.785 0.43324
## Tornqvist_Index.dl4 -0.0219632 0.0590846 -0.372 0.71035
## GDE.Deflator.dl4 0.5109831 1.3067650 0.391 0.69604
## Tornqvist_Index.dl5 -0.0391636 0.0590879 -0.663 0.50794
## GDE.Deflator.dl5 1.3154028 1.3093756 1.005 0.31585
## Tornqvist_Index.dl6 0.0408538 0.0588771 0.694 0.48826
## GDE.Deflator.dl6 0.9985470 1.3032392 0.766 0.44413
## Tornqvist_Index.dl7 0.0528513 0.0590153 0.896 0.37117
## GDE.Deflator.dl7 -0.6006494 1.2920780 -0.465 0.64234
## Tornqvist_Index.dl8 0.1410769 0.0579619 2.434 0.01549 *
## GDE.Deflator.dl8 -2.0568767 1.3032519 -1.578 0.11550
## Tornqvist_Index.dl9 -0.0110025 0.0580154 -0.190 0.84971
## GDE.Deflator.dl9 0.4281253 1.3019985 0.329 0.74251
## Tornqvist_Index.dl10 -0.0523568 0.0587796 -0.891 0.37375
## GDE.Deflator.dl10 -0.6075248 1.3106685 -0.464 0.64331
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1139 on 317 degrees of freedom
## Multiple R-squared: 0.1922, Adjusted R-squared: 0.1387
## F-statistic: 3.592 on 21 and 317 DF, p-value: 4.013e-07
##
##
## Response GDE.Deflator.d :
##
## Call:
## lm(formula = GDE.Deflator.d ~ ect1 + Tornqvist_Index.dl1 + GDE.Deflator.dl1 +
## Tornqvist_Index.dl2 + GDE.Deflator.dl2 + Tornqvist_Index.dl3 +
## GDE.Deflator.dl3 + Tornqvist_Index.dl4 + GDE.Deflator.dl4 +
## Tornqvist_Index.dl5 + GDE.Deflator.dl5 + Tornqvist_Index.dl6 +
## GDE.Deflator.dl6 + Tornqvist_Index.dl7 + GDE.Deflator.dl7 +
## Tornqvist_Index.dl8 + GDE.Deflator.dl8 + Tornqvist_Index.dl9 +
## GDE.Deflator.dl9 + Tornqvist_Index.dl10 + GDE.Deflator.dl10 -
## 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0166331 -0.0029969 -0.0004214 0.0027481 0.0212964
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 -0.0005032 0.0000816 -6.166 2.13e-09 ***
## Tornqvist_Index.dl1 0.0013189 0.0024006 0.549 0.58312
## GDE.Deflator.dl1 -0.0879742 0.0551682 -1.595 0.11179
## Tornqvist_Index.dl2 -0.0014184 0.0024915 -0.569 0.56958
## GDE.Deflator.dl2 0.1054156 0.0554646 1.901 0.05826 .
## Tornqvist_Index.dl3 0.0014280 0.0024842 0.575 0.56579
## GDE.Deflator.dl3 -0.0932752 0.0559361 -1.668 0.09640 .
## Tornqvist_Index.dl4 -0.0017081 0.0025214 -0.677 0.49862
## GDE.Deflator.dl4 0.1123707 0.0557658 2.015 0.04474 *
## Tornqvist_Index.dl5 0.0003551 0.0025216 0.141 0.88809
## GDE.Deflator.dl5 0.1725144 0.0558772 3.087 0.00220 **
## Tornqvist_Index.dl6 0.0021355 0.0025126 0.850 0.39600
## GDE.Deflator.dl6 -0.0768738 0.0556154 -1.382 0.16787
## Tornqvist_Index.dl7 -0.0015217 0.0025185 -0.604 0.54614
## GDE.Deflator.dl7 -0.1031822 0.0551390 -1.871 0.06222 .
## Tornqvist_Index.dl8 0.0001540 0.0024735 0.062 0.95040
## GDE.Deflator.dl8 -0.0003442 0.0556159 -0.006 0.99507
## Tornqvist_Index.dl9 -0.0054288 0.0024758 -2.193 0.02905 *
## GDE.Deflator.dl9 -0.0599962 0.0555624 -1.080 0.28105
## Tornqvist_Index.dl10 0.0083086 0.0025084 3.312 0.00103 **
## GDE.Deflator.dl10 -0.0711394 0.0559324 -1.272 0.20435
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.004862 on 317 degrees of freedom
## Multiple R-squared: 0.5868, Adjusted R-squared: 0.5595
## F-statistic: 21.44 on 21 and 317 DF, p-value: < 2.2e-16
summary(vecm_infmon[["beta"]])
## ect1
## Min. :-27.355
## 1st Qu.:-13.178
## Median : 1.000
## Mean : -8.009
## 3rd Qu.: 1.663
## Max. : 2.327
So Ultimately, what this VAR(11) tells us is that the inflation rate has little causal effect on the money supply, while the changes in the money supply tend to increase prices as captured by the GDE deflator. At the same time our index implies a lack of a relationship between the log money supply and the log of nominal income. These seem to be counter-intuitive to me, unless increases in the money supply have a slight positive influence on prices and a slight negative influence on real income. The money supply is highly auto-regressive. We’ve found a means of isolating price data and shown that the relationship between the money supply and inflation is somewhat in line with classical monetarist theory, while it’s relationship with nominal GDP is less significant. our VECM for log GDE deflator and log T index implied a long run equilibrium relationship between log T and log GDE deflator, while it is the GDE deflator that adjusts in the short term in response to deviations from this equilibrium relation.
The ultimate result is that approximately 60% of the short-run changes in the GDE deflator (general price increases) can be explained by changes in the quantity of money, properly defined.
Perhaps we should perform VARs to investigate the real GDP-Money supply relation. If a slight negative correlation is revealed, then Monetary policy that directly or indirectly influences the Money Supply may have reached it’s structural limitation in South Africa.
##Taking the log of real GDE data
ln.rGDE <- log(realGDEimp.xts)
colnames(ln.rGDE) <- "Log Real GDE"
colnames(ln.tornqvist) <- "Log Tornqvist"
YMVarsdata <- cbind(ln.rGDE, ln.tornqvist)
YMlagselect <- vars::VARselect(YMVarsdata, lag.max = 12, type = "const")
YM.optilag <- YMlagselect$selection["HQ(n)"]
YN.model <- vars::VAR(
y= YMVarsdata,
p = YM.optilag,
type = "const",
season = NULL,
exogen = NULL
)
summary(YN.model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: Log.Real.GDE, Log.Tornqvist
## Deterministic variables: const
## Sample size: 342
## Log Likelihood: 1486.667
## Roots of the characteristic polynomial:
## 0.9965 0.9838 0.8084 0.8084 0.8002 0.8002 0.6821 0.6821 0.6643 0.6643 0.4497 0.4497 0.2125 0.2125
## Call:
## vars::VAR(y = YMVarsdata, p = YM.optilag, type = "const", exogen = NULL)
##
##
## Estimation results for equation Log.Real.GDE:
## =============================================
## Log.Real.GDE = Log.Real.GDE.l1 + Log.Tornqvist.l1 + Log.Real.GDE.l2 + Log.Tornqvist.l2 + Log.Real.GDE.l3 + Log.Tornqvist.l3 + Log.Real.GDE.l4 + Log.Tornqvist.l4 + Log.Real.GDE.l5 + Log.Tornqvist.l5 + Log.Real.GDE.l6 + Log.Tornqvist.l6 + Log.Real.GDE.l7 + Log.Tornqvist.l7 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Log.Real.GDE.l1 0.989756 0.054309 18.225 < 2e-16 ***
## Log.Tornqvist.l1 0.014489 0.003406 4.254 2.75e-05 ***
## Log.Real.GDE.l2 0.198638 0.073358 2.708 0.007130 **
## Log.Tornqvist.l2 -0.006325 0.004267 -1.482 0.139196
## Log.Real.GDE.l3 -0.368521 0.074351 -4.956 1.15e-06 ***
## Log.Tornqvist.l3 0.008999 0.004291 2.097 0.036756 *
## Log.Real.GDE.l4 0.371269 0.070494 5.267 2.52e-07 ***
## Log.Tornqvist.l4 -0.024234 0.004397 -5.511 7.23e-08 ***
## Log.Real.GDE.l5 0.006853 0.068786 0.100 0.920697
## Log.Tornqvist.l5 -0.001521 0.004501 -0.338 0.735616
## Log.Real.GDE.l6 -0.380408 0.068002 -5.594 4.69e-08 ***
## Log.Tornqvist.l6 0.010200 0.004478 2.278 0.023383 *
## Log.Real.GDE.l7 0.181586 0.050416 3.602 0.000365 ***
## Log.Tornqvist.l7 -0.002030 0.003646 -0.557 0.578105
## const 0.016811 0.050224 0.335 0.738046
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.006989 on 327 degrees of freedom
## Multiple R-Squared: 0.9993, Adjusted R-squared: 0.9993
## F-statistic: 3.365e+04 on 14 and 327 DF, p-value: < 2.2e-16
##
##
## Estimation results for equation Log.Tornqvist:
## ==============================================
## Log.Tornqvist = Log.Real.GDE.l1 + Log.Tornqvist.l1 + Log.Real.GDE.l2 + Log.Tornqvist.l2 + Log.Real.GDE.l3 + Log.Tornqvist.l3 + Log.Real.GDE.l4 + Log.Tornqvist.l4 + Log.Real.GDE.l5 + Log.Tornqvist.l5 + Log.Real.GDE.l6 + Log.Tornqvist.l6 + Log.Real.GDE.l7 + Log.Tornqvist.l7 + const
##
## Estimate Std. Error t value Pr(>|t|)
## Log.Real.GDE.l1 -0.183283 0.884141 -0.207 0.83590
## Log.Tornqvist.l1 0.710667 0.055448 12.817 < 2e-16 ***
## Log.Real.GDE.l2 1.294298 1.194269 1.084 0.27927
## Log.Tornqvist.l2 0.115729 0.069461 1.666 0.09665 .
## Log.Real.GDE.l3 -0.448832 1.210433 -0.371 0.71102
## Log.Tornqvist.l3 0.320171 0.069859 4.583 6.53e-06 ***
## Log.Real.GDE.l4 0.119037 1.147633 0.104 0.91745
## Log.Tornqvist.l4 -0.207171 0.071584 -2.894 0.00406 **
## Log.Real.GDE.l5 -0.052663 1.119825 -0.047 0.96252
## Log.Tornqvist.l5 -0.006084 0.073273 -0.083 0.93388
## Log.Real.GDE.l6 -0.895365 1.107073 -0.809 0.41924
## Log.Tornqvist.l6 0.040593 0.072899 0.557 0.57802
## Log.Real.GDE.l7 0.250315 0.820769 0.305 0.76058
## Log.Tornqvist.l7 0.001439 0.059351 0.024 0.98067
## const -1.091195 0.817649 -1.335 0.18295
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.1138 on 327 degrees of freedom
## Multiple R-Squared: 0.9895, Adjusted R-squared: 0.9891
## F-statistic: 2203 on 14 and 327 DF, p-value: < 2.2e-16
##
##
##
## Covariance matrix of residuals:
## Log.Real.GDE Log.Tornqvist
## Log.Real.GDE 4.885e-05 -6.348e-05
## Log.Tornqvist -6.348e-05 1.295e-02
##
## Correlation matrix of residuals:
## Log.Real.GDE Log.Tornqvist
## Log.Real.GDE 1.00000 -0.07982
## Log.Tornqvist -0.07982 1.00000
YN_results <- irf(YN.model,
impulse = "Log.Real.GDE",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(YN_results)
nYN_results <- irf(YN.model,
impulse = "Log.Tornqvist",
n.ahead = 20,
ortho = TRUE,
boot = TRUE,
ci = 0.95)
plot(nYN_results)
coint_test <- ca.jo(YMVarsdata, type = "trace", K = YM.optilag, ecdet = "const")
summary(coint_test)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 4.333886e-02 7.371454e-03 -2.913638e-17
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 1 | 2.53 7.52 9.24 12.97
## r = 0 | 17.68 17.85 19.96 24.60
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## Log.Real.GDE.l7 Log.Tornqvist.l7 constant
## Log.Real.GDE.l7 1.000000 1.0000000 1.00000000
## Log.Tornqvist.l7 -1.062448 -0.2630869 -0.06089176
## constant -6.155098 -13.3568511 -14.56944781
##
## Weights W:
## (This is the loading matrix)
##
## Log.Real.GDE.l7 Log.Tornqvist.l7 constant
## Log.Real.GDE.d 0.0008011734 -0.001627832 -6.543572e-16
## Log.Tornqvist.d 0.0033603771 0.080147009 3.829516e-14
With this, we find that there is no long term relationship between the money supply and real Gross Domestic Expendature, while there is a such a relationship between the money supply and inflation. This would seem to imply that money may be neutral in the long run. However, the adjustment period for inflation is relatively slow, which means the influence of a change in intrest rates and the money supply will lead to a long period of disequilibrium, during which additional expansionary policy can drive mal-investments to compound.