Originally published on the 25th, edited comment on Boris Johnson

Headline Roundup

Central Bank re-calibrates mortgage criteria

The Statement can be found here

What has changed?

First Time Buyers

  • Loan to income (LTI) increased from 3.5 times to 4 times income.
  • No changes to LTV (Loan to Value) which remains at 90%.

Second & Subsequent buyers (SSB)

  • LTI remains at 3.5 income.
  • LTV changed from 80% to 90%.

Proportionate allowances

  • 15% of FTB can take place above the limits
  • 15% of SSB can take place above the limits
  • 10% of BTL can take place above the limits.

Additionally - From a “fresh start” perspective, borrowers who are divorced or separated or have undergone bankruptcy or insolvency may be considered FTBs for the mortgage measures (where they no longer have an interest in the previous property). - FTBs who get a top-up loan or re-mortgage with an increase in the principal may be considered FTBs, provided the property remains their primary home.

*The median house price relative to the prior cap can be seen in the “Characteristics of Household Purchases” Section”.


Russians escalte the conflict with Iranian Drones

In response to the Ukrainians successes of late the Russians have been bombing civilian centers, adding to the tally of war crimes. Russia have purchased cheap 20k drones from Iran, apparently the drones they were using earlier in the war go for about $2 million. So evidently they’ve not been using them sparingly given they are so cheap, although the majority are negated by the Ukrainians anti-aircraft missles invariably some get through. Targeting power stations and utilities this means for more misery for the civilians and a higher bill to rebuild Ukraine when the time comes.

The Iranian nuclear deal has stalled, supplying drones will do nothing to improved engagement. Protests in Iran continue due to the death of a 22 year-old woman who was detained by the morality police for wearing “improper attire”. Reuters report that more than 200 people have been killed in a crackdown to counter the protests.. Russia relying on another pariah state like Iran is telling of their situation, this war has not gone to plan.

This week Russia have made accusations that the Ukrainians intend to use dirty bombs, NATO say there is no evidence of this amid speculation that the Russians are using this as an front to escalate further. - Ukraine will take the matter to the UN security council, what good that will do I don’t know.

This comes as some republicans baulk at the bill to support Ukraine. With US mid-term elections coming up some fear that this limit the support for Ukraine, but my reading of it so far is that pressure to maintain the support will be too much even if the republicans outperform.

Germans concede on energy price cap

Olaf Scholz has dropped his opposition to energy price cap, but acknowledged that there “is still a lot of concrete work to do” to implement the cap.

Meanwhile the Romanians attempt at a windfall tax of 80% to cover their price supports has backfired. The government have been convering the difference in the price cap to actual costs for consumers, this bill has increased wuicker than anticipated. The windfall tax was introduced to cover this added costs, with wholesalers increasing their costs due to margin pressure prices have increased and trading has slowed to a standstill.

Xi consoliodates power within the CCP

Economic data delayed until after the CCP congress where Xi consilidated the key offices in the state to his allies, as reported by Rueters, Bloomberg, The FT among other “western” media outlets. Interestingly footage emerged of Xis predecessor, Hu Jintao, being escorted from the conference, the aforementioned outlets commented that this was peculiar given the event is highly choreographed. There is much speculation on whether this was Xi flexing through a very public purge, or whether it was a case of a senile official being escorted out as an act of mercy.

Since Xi took over China has become less transparent. To 2016, half of all indicators published by the statistics bureaus have been (quietly) discontinued. - The FT report. There has been suspicions for years that Chinas GDP is grossly overstated, with Luis Martinez of the University of Chicago conducting a night-time light analysis from satellite imagery suggests growth to be overstated by a third over the last 20 years. How representative this is I am not sure I have not read the paper, but the acceptance that figures are overstated will hurt the Chinese in the long run.

Hong Kong and China plunge following the release of the delayed economic data and the Renimbi hits 2007 lows.

Truss resigns, Sunak confirmed as PM

In what became a one horse race, which threatened to see Boris Johnson return as Prime Minister ends with Rishi Sunak in Number 10. This was after Liz Truss & Kwasi Kwateng are effectively forced to resign for their economic policies. Kwateng was first to go, being summoned back to England from an IMF conference to be told by his close friend and PM to hand in his resignation.

Truss then brought in Jeremy Hunt to stem the pressure from the party, he promptly reverses Kwatengs policies but it is not enough to see her through. Truss lasted 44 days in office, solidifying her place in the pub quiz archives as the shortest stint as PM. - In the week leading up to her removal there was a live stream of a head of lettuce posted by te Daily Star, the purpose was to see would she outlive the lettuce. She did not.

Boris Johnson flew back from his holidays on the Caribbean with a view to put his name forward, more than 50 MPs came out to back him, publically. 100 was needed by 2pm Monday to be considered a contender. Boris later pulled out of the race, but in a characteristically Boris statement he nodded to his election win from 2019. I believe he thinks he have another opportunity to be leader after the next general election and is leaving that door open. - Some of the telling quotes:

  • I have been attracted because I led our party into a massive election victory less than three years ago – and I believe I am therefore uniquely placed to avert a general election now.
  • I believe I am well placed to deliver a Conservative victory in 2024 – and tonight I can confirm that I have cleared the very high hurdle of 102 nominations, including a proposer and a seconder, and I could put my nomination in tomorrow.

The list of critiques for the “mini-budget” is too long to begin, Bloomberg commentators referred to the damage that Truss has done to the economy as “the moron risk premium”. Fringe Tory party members have shifted the Tory party towards delusion since Cameron agreed to that referendum in 2016. While treasury yields have improved since Sunak was announced, the polls will likely favour Labour for some time to come.

AIB the first to bump rates

“Following the European Central Bank’s decisions to raise interest rates by 1.25% since July 2022 and in a rising interest rate environment, AIB Group is announcing a fixed rate mortgage increase of 0.5%”

This will be in effect from the 14th of November, as we will see later the proportion of Irish with variable loans have decreased particulalry of late. For a full view on AIBs statement follow the link.

Elsewhere

  • Head of Frances Central Bank says UK crisis demonstrates tge risks of a “vicious loop” that governments face if they undermine monetary policies efforts to curb inflation.
  • Eurozone business activity falls faster than estimates in October, its lowest for 2 years.
  • Japanese continue intervention on the Yen as the currency approaches 32 year low.
  • Berlusconi taped sympahising with Putin, discussing the gifts they have exchanged and condeming their support for Ukraine. - Not an ideal start for Melonis coalition. - Meloni having to call Zelenskyy to reassure him of Italys support.
  • The top chip suppliers halt business in China following US export restrictions.
  • The German head of cyber security, Arne Schonbohm has been sacked over reports of alleged ties to Russian intelligence.
  • ECB look set to raise rates by 0.75 on Thursday.
  • An Board Pleanala have delivered the report to its chairperson on allegations of wrongdoing, but have not yet published findings.

US & Markets

# Ensure to change CSV name to apprpriate version number / working directory
SNP <- getSymbols("^GSPC",src='yahoo',auto.assign=FALSE)
ISEQ <- getSymbols("^ISEQ",src='yahoo',auto.assign=FALSE)

SNP$Close.MA5 <- rollmean(SNP$GSPC.Close,5)
SNP$Close.MA5 <- Lag(SNP$Close.MA5,2)
SNP$Close.MA10 <- rollmean(SNP$GSPC.Close,10)
SNP$Close.MA10 <- Lag(SNP$Close.MA10,5)
ISEQ$Close.MA5 <- rollmean(ISEQ$ISEQ.Close,5)
ISEQ$Close.MA5 <- Lag(ISEQ$Close.MA5,2)
ISEQ$Close.MA10 <- rollmean(ISEQ$ISEQ.Close,10)
ISEQ$Close.MA10 <- Lag(ISEQ$Close.MA10,5)

write.csv(SNP,"SNP.N1.1.csv")
write.csv(ISEQ,"ISEQ.N1.1.csv")

SNP_Oct22 <- SNP %>%
  subset(date(index(.))>= "2022-10-01")
ISEQ_Oct22 <- ISEQ %>%
  subset(date(index(.))>= "2022-10-01")
SNP_YTD <- SNP %>%
  subset(date(index(.))>= "2022-01-01")
ISEQ_YTD <- ISEQ %>%
  subset(date(index(.))>= "2022-01-01")

Markets

SNP_end <- as.data.frame(tail(SNP_YTD,1))
ISEQ_end <- as.data.frame(tail(ISEQ_YTD,1))

Fig.SNP.YTD<-ggplot(data=SNP_YTD,aes(x=Index,y=GSPC.Close,group=1))+
  geom_line(data=SNP_YTD,aes(x=Index,y=Close.MA5,group=1),alpha=0.5,colour="#9200ff")+
  geom_line(data=SNP_YTD,aes(x=Index,y=Close.MA10,group=1),alpha=0.5,colour="#290047",linetype="dashed")+
  geom_line(colour="#D49CFE",size=1)+
  geom_text_repel(aes(label=round(GSPC.Close,digits=2)),data = SNP_YTD, size = 2.5,max.overlaps = 4,colour="#f6f7f6")+
  theme_dark()+
  ggtitle("S&P YTD")+
  xlab(NULL)+theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  scale_y_continuous(sec.axis = sec_axis(~ ., breaks = SNP_end$GSPC.Close))+ theme(axis.text = element_text(size = 6))

Fig.ISEQ.YTD<-ggplot(data=ISEQ_YTD,aes(x=Index,y=ISEQ.Close,group=1))+
  geom_line(data=ISEQ_YTD,aes(x=Index,y=Close.MA5,group=1),alpha=0.5,colour="#15e600")+
  geom_line(data=ISEQ_YTD,aes(x=Index,y=Close.MA10,group=1),alpha=0.5,colour="#0f6606",linetype="dashed")+
  geom_line(colour="#A5FE9C",size=1)+
  geom_text_repel(aes(label=round(ISEQ.Close,digits=2)),data = ISEQ_YTD, size = 2.5,max.overlaps = 4,colour="#f6f7f6")+
  theme_dark()+
  ggtitle("ISEQ YTD")+
  xlab(NULL)+ theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  scale_y_continuous(sec.axis = sec_axis(~ ., breaks = ISEQ_end$ISEQ.Close))+ theme(axis.text = element_text(size = 6))

Fig.SNP.YTD+Fig.ISEQ.YTD+plot_layout(ncol=2)+
  labs(caption = "Moving Averages: dashed line = 5 day, solid line = 10 day")

Fig.SNP.Oct<-ggplot(data=SNP_Oct22,aes(x=Index,y=GSPC.Close,group=1))+
  geom_line(data=SNP_Oct22,aes(x=Index,y=Close.MA5,group=1),alpha=0.5,colour="#9200ff")+
  geom_line(data=SNP_Oct22,aes(x=Index,y=Close.MA10,group=1),alpha=0.5,colour="#290047",linetype="dashed")+
  geom_line(colour="#D49CFE",size=1)+
  geom_text_repel(aes(label=round(GSPC.Close,digits=2)),data = SNP_Oct22, size = 2.5,max.overlaps = 4,colour="#f6f7f6")+
  theme_dark()+
  ggtitle("S&P Oct22")+
  xlab(NULL)+ theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  scale_y_continuous(sec.axis = sec_axis(~ ., breaks = SNP_end$GSPC.Close))+ theme(axis.text = element_text(size = 6))

Fig.ISEQ.Oct<-ggplot(data=ISEQ_Oct22,aes(x=Index,y=ISEQ.Close,group=1))+
  geom_line(data=ISEQ_Oct22,aes(x=Index,y=Close.MA5,group=1),alpha=0.5,colour="#15e600")+
  geom_line(data=ISEQ_Oct22,aes(x=Index,y=Close.MA10,group=1),alpha=0.5,colour="#0f6606",linetype="dashed")+
  geom_line(colour="#A5FE9C",size=1)+
  geom_text_repel(aes(label=round(ISEQ.Close,digits=2)),data = ISEQ_Oct22, size = 2.5,max.overlaps = 4,colour="#f6f7f6")+
  theme_dark()+
  ggtitle("ISEQ Oct22")+
  theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  xlab(NULL)+ scale_y_continuous(sec.axis = sec_axis(~ ., breaks = ISEQ_end$ISEQ.Close))+ theme(axis.text = element_text(size = 6))

Fig.SNP.Oct+Fig.ISEQ.Oct+plot_layout(ncol=2)+
  labs(caption = "Moving Averages: dashed line = 5 day, solid line = 10 day")

Currency

# Plot Currency
Fig.EURYTD + Fig.GBPYTD + Fig.AUDYTD + Fig.CHNYTD + plot_layout(ncol=2)

# Plot Dec Futures
Fig.YEN.FYTD + Fig.PES.FYTD + plot_layout(ncol=2)

Gold

#Plot Gold
Fig.GOLD + Fig.GOLDYTD + plot_layout(ncol=2)

Crypto

# Plot

#CRYPTO %>%
# ggplot(aes(x=date,y=value,group=Coin,colour=Coin))+geom_line()

Fig_BTC.YTD <- BTC.YTD %>%
  ggplot(aes(x=date,y=value,group=Coin))+
  geom_line(aes(y=SMA.5),linetype="dotted",colour="#4D4D4D")+
  geom_line(aes(y=SMA.10),linetype="dotted",colour="#F7931A")+
  geom_line(aes(y=SMA.50),colour="#4D4D4D",alpha=0.5)+
  geom_line(aes(y=SMA.100),colour="#F7931A",alpha=0.5)+
  geom_line(size=1,colour="#F7931A",alpha=0.7)+
  geom_text_repel(aes(label=round(value,digits=0)),max.overlaps=5,size=2.25,alpha=0.7)+
  ylab("BTC to USD")+
  theme_bw()+theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  ggtitle("Bitcoin - Year to Date")+
  labs(caption="5 and 10 day moving average indicated with dotted line, 50 & 100 are the solid lines")

Fig_ETH.YTD <- ETH.YTD %>%
  ggplot(aes(x=date,y=value,group=Coin))+
  geom_line(aes(y=SMA.5),linetype="dotted",colour="#716b94")+
  geom_line(aes(y=SMA.10),linetype="dotted",colour="#48cbd9")+
  geom_line(aes(y=SMA.50),colour="#716b94",alpha=0.5)+
  geom_line(aes(y=SMA.100),colour="#48cbd9",alpha=0.5)+
  geom_line(size=1,colour="#14044d",alpha=0.7)+
  geom_text_repel(aes(label=round(value,digits=0)),max.overlaps=5,size=2.25,alpha=0.7)+
  ylab("ETH to USD")+
  theme_bw()+theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  ggtitle("Ethereum - Year to Date")+
  labs(caption="5 and 10 day moving average indicated with dotted line, 50 & 100 are the solid lines")

Fig_BTC.YTD + Fig_ETH.YTD + plot_layout(nrow=2)

Commodities

Energy Prices

Note the decline in Gas prices, good news if it can continue through to winter.

BRENT_YTD <- BRENT %>%
  subset(date(index(.))>= "2022-01-01")
WTI_YTD <- WTI %>%
  subset(date(index(.))>= "2022-01-01")
NGAS_YTD <- NGAS %>%
  subset(date(index(.))>= "2022-01-01")

BRENT_YTD_AVG <- mean(BRENT_YTD$`BZ=F.Close`,na.rm=TRUE)
BRENT_YTD_TAIL <- tail(BRENT_YTD,1)
BRENT_YTD_CLOSE <- mean(BRENT_YTD_TAIL$`BZ=F.Close`,na.rm=TRUE)
WTI_YTD_AVG <- mean(WTI_YTD$`CL=F.Close`,na.rm=TRUE)
WTI_YTD_TAIL <- tail(WTI_YTD,1)
WTI_YTD_CLOSE <- mean(WTI_YTD_TAIL$`CL=F.Close`,na.rm=TRUE)
NGAS_YTD_AVG <- mean(NGAS_YTD$`NG=F.Close`,na.rm=TRUE)
NGAS_YTD_TAIL <- tail(NGAS_YTD,1)
NGAS_YTD_CLOSE <- mean(NGAS_YTD_TAIL$`NG=F.Close`,na.rm=TRUE)

#Oil Plots
Fig.Brent2<-ggplot(data=BRENT_YTD,aes(x=Index,y=`BZ=F.Close`,group=1))+
  geom_line()+
  geom_hline(yintercept=BRENT_YTD_CLOSE,alpha=0.5)+
  geom_hline(yintercept=BRENT_YTD_AVG,linetype='dashed')+
  theme_bw()+ theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  ggtitle("Year to Date")+
  ylab(NULL)+
  xlab(NULL)+ theme(axis.text = element_text(size = 6))+
  geom_text_repel(data=BRENT_TAIL,aes(label=round(`BZ=F.Close`,digits=2),y=130),size=2.5,alpha=0.6,colour="darkred")
  
Fig.WTI2<-ggplot(data=WTI_YTD,aes(x=Index,y=`CL=F.Close`,group=1))+
  geom_line(colour="darkgrey")+
  geom_hline(yintercept=WTI_YTD_CLOSE,colour="darkgrey",alpha=0.8)+
  geom_hline(yintercept=WTI_YTD_AVG,linetype='dashed',colour="darkgrey")+
  theme_bw()+theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  ggtitle("Year to Date")+
  ylab(NULL)+
  xlab(NULL)+ theme(axis.text = element_text(size = 6))+
  geom_text_repel(data=WTI_TAIL,aes(label=round(`CL=F.Close`,digits=2),y=130),size=2.5,alpha=0.6,colour="darkred")

#Gas Plots
Fig.NGAS2<-ggplot(data=NGAS_YTD,aes(x=Index,y=`NG=F.Close`,group=1))+
  geom_line(colour="darkblue")+
  geom_hline(yintercept=NGAS_YTD_CLOSE,colour="darkblue",alpha=0.5)+
  geom_hline(yintercept=NGAS_YTD_AVG,linetype='dashed',colour="darkblue")+
  theme_bw()+theme(axis.text.y=element_text(size=6),
        plot.title = element_text(size=10,face="bold"))+
  ggtitle("Year to Date")+
  ylab(NULL)+
  xlab("Dates")+
  labs(caption = "dashed line = average, solid line = closing price (closing price also in red)")+ theme(axis.text = element_text(size = 6))+
  geom_text_repel(data=NGAS_TAIL,aes(label=round(`NG=F.Close`,digits=2),y=9),size=2.5,alpha=0.6,colour="darkred")

# YTD
Fig.Energy.YTD<-Fig.Brent2 + Fig.WTI2 + Fig.NGAS2 +
  plot_layout(nrow=3)

Fig.Brent1+Fig.Brent2+Fig.WTI1+Fig.WTI2+Fig.NGAS1+Fig.NGAS2+
  plot_layout(nrow=3)

rm(ISEQ)
rm(ISEQ_July22)
rm(ISEQ_YTD)
rm(SNP)
rm(SNP_July22)
rm(SNP_YTD)

Ireland & The Euro Area

Euro Area Bonds

I’ve added time lags to the Yield Curve & the 20 year maturity. We can see the curve flattening and approaching inversion, inverting at the 20-30 year. - I may replace this with a static line & moving gif but I’ve not cracked that yet.

# Euro Area
EA.1YR <- get_data("YC.B.U2.EUR.4F.G_N_A.SV_C_YM.SR_1Y")
EA.1YR$obstime<-convert_dates(EA.1YR$obstime)

Fig_EA.1YR<-ggplot(data=EA.1YR,aes(x=obstime,y=obsvalue,group=ref_area))+
  geom_line(colour="blue")+
  geom_hline(yintercept = 0, linetype='dotted')+
  geom_text_repel(aes(label=round(obsvalue,digits=2)),data = EA.1YR, size = 3)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("1 Year Maturity")+
  ylab("yield (%)")+
  xlab(NULL)

EA.5YR <- get_data("YC.B.U2.EUR.4F.G_N_A.SV_C_YM.SR_5Y")
EA.5YR$obstime<-convert_dates(EA.5YR$obstime)

Fig_EA.5YR<-ggplot(data=EA.5YR,aes(x=obstime,y=obsvalue,group=ref_area))+
  geom_line(colour="blue")+
  geom_hline(yintercept = 0, linetype='dotted')+
  geom_text_repel(aes(label=round(obsvalue,digits=2)),data = EA.5YR, size = 3)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("5 Year Maturity")+
  ylab("yield (%)")+
  xlab(NULL)

EA.10YR <- get_data("YC.B.U2.EUR.4F.G_N_A.SV_C_YM.SR_10Y")
EA.10YR$obstime<-convert_dates(EA.10YR$obstime)

Fig_EA.10YR<-ggplot(data=EA.10YR,aes(x=obstime,y=obsvalue,group=ref_area))+
  geom_line(colour="blue")+
  geom_hline(yintercept = 0, linetype='dotted')+
  geom_text_repel(aes(label=round(obsvalue,digits=2)),data = EA.10YR, size = 3)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("10 Year Maturity")+
  ylab("yield (%)")+
  xlab(NULL)

EA.30YR <- get_data("YC.B.U2.EUR.4F.G_N_A.SV_C_YM.SR_30Y")
EA.30YR$obstime<-convert_dates(EA.30YR$obstime)

Fig_EA.30YR<-ggplot(data=EA.30YR,aes(x=obstime,y=obsvalue,group=ref_area))+
  geom_line(colour="blue")+
  geom_hline(yintercept = 0, linetype='dotted')+
  geom_text_repel(aes(label=round(obsvalue,digits=2)),data = EA.30YR, size = 3)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("30 Year Maturity")+
  ylab("yield (%)")+
  xlab(NULL)

Fig_EA.1YR+Fig_EA.5YR+Fig_EA.10YR+Fig_EA.30YR+
  plot_layout(nrow=2,ncol=2)

# Generate yield curve
EA.1YR_Print<-tail(EA.1YR,1)
EA.5YR_Print<-tail(EA.5YR,1)
EA.10YR_Print<-tail(EA.10YR,1)
EA.30YR_Print<-tail(EA.30YR,1)

## Load 20 Year
EA.20YR <- get_data("YC.B.U2.EUR.4F.G_N_A.SV_C_YM.SR_20Y")
EA.20YR$obstime<-convert_dates(EA.20YR$obstime)
EA.20YR_Print<-tail(EA.20YR,1)

## Add lags
EA.1YR_Print$t = "Live"
EA.1YR_Print.30<-head(tail(EA.1YR,30),1)
EA.1YR_Print.30$t = "30 days"
EA.1YR_Print.90<-head(tail(EA.1YR,90),1)
EA.1YR_Print.90$t = "90 days"
EA.1YR_Print.360<-head(tail(EA.1YR,360),1)
EA.1YR_Print.360$t = "360 days"

EA.YC.1Y <- rbind(EA.1YR_Print,EA.1YR_Print.30,EA.1YR_Print.90,EA.1YR_Print.360)

EA.5YR_Print$t = "Live"
EA.5YR_Print.30<-head(tail(EA.5YR,30),1)
EA.5YR_Print.30$t = "30 days"
EA.5YR_Print.90<-head(tail(EA.5YR,90),1)
EA.5YR_Print.90$t = "90 days"
EA.5YR_Print.360<-head(tail(EA.5YR,360),1)
EA.5YR_Print.360$t = "360 days"

EA.YC.5Y <- rbind(EA.5YR_Print,EA.5YR_Print.30,EA.5YR_Print.90,EA.5YR_Print.360)

EA.10YR_Print$t = "Live"
EA.10YR_Print.30<-head(tail(EA.10YR,30),1)
EA.10YR_Print.30$t = "30 days"
EA.10YR_Print.90<-head(tail(EA.10YR,90),1)
EA.10YR_Print.90$t = "90 days"
EA.10YR_Print.360<-head(tail(EA.10YR,360),1)
EA.10YR_Print.360$t = "360 days"

EA.YC.10Y <- rbind(EA.10YR_Print,EA.10YR_Print.30,EA.10YR_Print.90,EA.10YR_Print.360)

EA.20YR_Print$t = "Live"
EA.20YR_Print.30<-head(tail(EA.20YR,30),1)
EA.20YR_Print.30$t = "30 days"
EA.20YR_Print.90<-head(tail(EA.20YR,90),1)
EA.20YR_Print.90$t = "90 days"
EA.20YR_Print.360<-head(tail(EA.20YR,360),1)
EA.20YR_Print.360$t = "360 days"

EA.YC.20Y <- rbind(EA.20YR_Print,EA.20YR_Print.30,EA.20YR_Print.90,EA.20YR_Print.360)

EA.30YR_Print$t = "Live"
EA.30YR_Print.30<-head(tail(EA.30YR,30),1)
EA.30YR_Print.30$t = "30 days"
EA.30YR_Print.90<-head(tail(EA.30YR,90),1)
EA.30YR_Print.90$t = "90 days"
EA.30YR_Print.360<-head(tail(EA.30YR,360),1)
EA.30YR_Print.360$t = "360 days"

EA.YC.30Y <- rbind(EA.30YR_Print,EA.30YR_Print.30,EA.30YR_Print.90,EA.30YR_Print.360)

## Bind and Plot
EA.YC <- rbind(EA.YC.1Y,EA.YC.5Y,EA.YC.10Y,EA.YC.20Y,EA.YC.30Y)

EA.YC$year <- sub("\\Y.*","",EA.YC$data_type_fm)
EA.YC$year <- sub(".*SR_","",EA.YC$year)
EA.YC$year <- as.numeric(EA.YC$year)

EA.YC %>%
  ggplot(aes(x=year,y=obsvalue,group=t))+
  geom_line(aes(colour=t,linetype=t))+
  scale_colour_manual(values=c("#477DFF","#477DFF","#477DFF","blue"))+
  scale_linetype_manual(values = c("solid","dotted","dashed","solid"))+
  geom_hline(yintercept = 0, linetype='dotted')+
  geom_text(label=round(EA.YC$obsvalue,digits=2),vjust=-1,hjust=1,aes(colour=t),size=2.75)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("Yield Curve")+
  ylab("yield (%)")+
  xlab("maturity (years)")


Inflation

CPI

See below, CPI is the top panel and percentage change year on year by Commodity Group makes up the panels.

# Plot
## CPM01
CPM01_1.18_LABS <- CPM01_1.18 %>%
  filter(value > 2)

Fig_ALL.18 <- CPM01_1.18 %>%
  ggplot(aes(x=Date,y=value,group=Commodity.Group))+
  geom_hline(yintercept = 2, linetype="dashed",alpha=0.6)+
  geom_col(aes(fill=colourcol),alpha=0.7)+
  scale_fill_manual(values=c("#CC0000","#1b5545"))+
  theme_bw()+
  theme(legend.position = "none")+
  ylab("%")+xlab(NULL)+
  ggtitle("Consumer Price Index - Year on Year")+
  geom_text(data=CPM01_1.18_LABS,aes(label = value,
                              vjust= ifelse(value >=0,0.25,0.5),
                              hjust= ifelse(value >=0,1,-0.25)),size = 3,angle = 90)
# Plot
## CPM01
Fig_CG.18 <- CPM01_2.18 %>%
  ggplot(aes(x=Date,y=value,group=Commodity.Group))+
  geom_hline(yintercept = 2, linetype="dashed",alpha=0.6)+
  geom_col(aes(fill=colourcol),alpha=0.7)+
  scale_fill_manual(values=c("#CC0000","#1b5545"))+
  theme_bw()+
  theme(legend.position = "none")+
  ylab("%")+xlab(NULL)+
  geom_text_repel(aes(label=value),size=2.5,max.overlaps = 6,alpha=0.7)+
  facet_wrap(~Commodity.Group,ncol=2)

Fig_ALL.18 + Fig_CG.18 + plot_layout(nrow=2,heights = c(1,5))

Contribution to Inflation

See broad based inflation thats present, some commodity groups alone are contributing 2 percentage points to CPI. - See dotted line.

# Plot
## CPM11
CPM11_1.12M_Max <- CPM11_1.12M %>%
  group_by(COICOP.Group) %>%
  slice(which.max(Date))
CPM11_1.12M_Max$lab <- paste(CPM11_1.12M_Max$Month, ":", CPM11_1.12M_Max$value)

CPM11_1.12M %>%
  ggplot(aes(x=Date,y=value,group=COICOP.Group,colour=COICOP.Group))+
  geom_hline(yintercept = 2, linetype="dashed",alpha=0.2)+
  geom_hline(yintercept = 0, alpha=0.2)+
  geom_line()+
  theme_bw()+
  theme(legend.position = "none")+
  ylab("%")+xlab(NULL)+
  ggtitle("Contribution to Inflation - Year on Year")+
  geom_text(data=CPM11_1.12M_Max,aes(label=lab,y=-3),hjust="right",size=3,fontface="bold",alpha=0.6)+
  facet_wrap(~COICOP.Group,ncol=3,labeller = labeller(COICOP.Group = label_wrap_gen(width = 35)))

The CSO released data on the Characteristics of Residential Property Purchasers. The next two sections contains data based on this series.

Residential Movement

The below illustrations are called “Sankey” charts, they are used to illustrate the flow from one object to another. Our objects are residences, so the county a purchaser moved from is on the left column and where they moved to is on the right. The colour of the flow is based on the destination county.

Dublin to GDA

For the GDA I’ve displayed to sets of sankey charts, the latter I’ve removed Dublin as a destination county. As you can see the large number of moving within Dublin makes assessing the other counties more difficult.

#### Filter for From.Dublin & To.GDA
CRP05.F_DUB.T_GDA <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="GDA") %>%
  filter(To.Region=="Dublin"|To.Region=="GDA")

options(scipen=999)

library()

ggplot(CRP05.F_DUB.T_GDA,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The GDA")+scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

##### Version 2      Filter for From.Dublin & To.Midlands
CRP05.F_DUB.T_GDA2 <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="GDA") %>%
  filter(To.Region=="GDA")

ggplot(CRP05.F_DUB.T_GDA2,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The GDA")+
  labs(subtitle="Dublin excluded from destination county")+scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

Dublin to Midlands

#### Filter for From.Dublin & To.Midlands
CRP05.F_DUB.T_MID <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="Midlands") %>%
  filter(To.Region=="Midlands")

ggplot(CRP05.F_DUB.T_MID,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The Midlands")+
  labs(subtitle="Dublin excluded from destination county")+scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

Dublin to North

#### Filter for From.Dublin & To.North
CRP05.F_DUB.T_NOR <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="North") %>%
  filter(To.Region=="North")

ggplot(CRP05.F_DUB.T_NOR,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The North")+
  labs(subtitle="Dublin excluded from destination county")+scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

Dublin to West

#### Filter for From.Dublin & To.West
CRP05.F_DUB.T_WES <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="West") %>%
  filter(To.Region=="West")

ggplot(CRP05.F_DUB.T_WES,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The West")+
  labs(subtitle="Dublin excluded from destination county")+
  scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

Dublin to South

#### Filter for From.Dublin & To.South
CRP05.F_DUB.T_SOU <- CRP05 %>%
  filter(From.Region=="Dublin"|From.Region=="South") %>%
  filter(To.Region=="South")

ggplot(CRP05.F_DUB.T_SOU,
       aes(y=value,
           axis1=Purchasers.Location.Given.During.Purchase,,axis2=County.Where.Property.Was.Purchased))+
  geom_alluvium(aes(fill=County.Where.Property.Was.Purchased),width = 1/12) +
  geom_stratum(width = 1/12, fill = "black", color = "grey") +
  geom_label(stat = "stratum", aes(label = after_stat(stratum)),size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6))+
  ggtitle("Residential Movement between Dublin & The South")+
  labs(subtitle="Dublin excluded from destination county")+
  scale_fill_brewer(type = "qual", palette = "Spectral")+
  facet_wrap(~year,ncol=2)

Characteristics of Household Purchases

Ireland

Headline Characteristics

Fig.Head.VOL <- CRP01.IRL.VOL.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#F59A08")+
  geom_text_repel(aes(label=value),alpha=0.7,size=3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Volume of Sales")+
  xlab(NULL)+
  ylab("number")

Fig.Head.AGE <- CRP01.IRL.AGE.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#08F5BC")+
  geom_text_repel(aes(label=value),alpha=0.7,size=3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Age")+
  xlab(NULL)+
  ylab("number")

Fig.Head.PRC <- CRP01.IRL.PRC.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#32AE04")+
  geom_text_repel(aes(label=value),alpha=0.7,size=3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Price")+
  xlab(NULL)+
  ylab("euro")

Fig.Head.INC <- CRP01.IRL.INC.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#0416AE")+
  geom_text_repel(aes(label=value),alpha=0.7,size=3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Income")+
  labs(caption="CRP01: Characteristics of Residential Property Purchasers")+
  xlab(NULL)+
  ylab("euro")

Fig.Head <- Fig.Head.VOL + Fig.Head.AGE + Fig.Head.PRC + Fig.Head.INC

Fig.Head

Transaction Category

By 2021 joint transactions were 1.5 times sole transactions, on average they were three years younger with a combined income that was 1.9 times higher than sole purchasers. They bought houses at 1.4 times at a median price of € 318 k, which is 13.5% above the aggregate median price.

####### View the 4 statistical measures for Ireland for each transaction category and aggregated buyers (i.e. OTH.ALL)
##### Title: Figure.IRL.TCAT
Fig.IRL.TCAT.VOL <- CRP01.IRL.VOL.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#F59A08")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
 theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Volume of Sales")+
  xlab(NULL)+
  ylab("number")

Fig.IRL.TCAT.AGE <- CRP01.IRL.AGE.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#08F5BC")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
 theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Age")+
  xlab(NULL)+
  ylab("number")

Fig.IRL.TCAT.PRC <- CRP01.IRL.PRC.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#32AE04")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Price")+
  xlab(NULL)+
  ylab("euro")

Fig.IRL.TCAT.INC <- CRP01.IRL.INC.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#0416AE")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Income")+
  xlab(NULL)+
  ylab("euro")

Fig.IRL.TCAT <- Fig.IRL.TCAT.VOL + Fig.IRL.TCAT.AGE + Fig.IRL.TCAT.PRC + Fig.IRL.TCAT.INC

Fig.IRL.TCAT

Buyer Category

The Buyer Category, those with and without children, trend is largely explained by the same factors as the Transaction Category. The gap bewteen incomes and prices are narrower at 1.35 and 1.17 respectively.

####### View the 4 statistical measures for Ireland for aggregated transaction category and each buyer (i.e. ALL.OTH)
##### Title: Figure.IRL.TBUY  || Filter >= 2016
CRP01.IRL.VOL.ALL.OTH <- CRP01.IRL.VOL.ALL.OTH %>%
  filter(year>="2016")

Fig.IRL.TBUY.VOL <- CRP01.IRL.VOL.ALL.OTH %>%
  ggplot(aes(x=year,y=value,group=Type.of.Buyer))+
  geom_line(aes(colour=Type.of.Buyer),size=1.25,alpha=0.6)+
  scale_colour_manual(values=c("#F59A08","#875501"))+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Volume of Sales")+
  xlab(NULL)+
  ylab("number")

CRP01.IRL.AGE.ALL.OTH <- CRP01.IRL.AGE.ALL.OTH %>%
  filter(year>="2016")

Fig.IRL.TBUY.AGE <- CRP01.IRL.AGE.ALL.OTH %>%
  ggplot(aes(x=year,y=value,group=Type.of.Buyer))+
  geom_line(aes(colour=Type.of.Buyer),size=1.25,alpha=0.6)+
  scale_colour_manual(values=c("#08F5BC","#06A07B"))+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Age")+
  xlab(NULL)+
  ylab("number")

CRP01.IRL.PRC.ALL.OTH <- CRP01.IRL.PRC.ALL.OTH %>%
  filter(year>="2016")

Fig.IRL.TBUY.PRC <- CRP01.IRL.PRC.ALL.OTH %>%
  ggplot(aes(x=year,y=value,group=Type.of.Buyer))+
  geom_line(aes(colour=Type.of.Buyer),size=1.25,alpha=0.6)+
  scale_colour_manual(values=c("#32AE04","#174D03"))+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Price")+
  xlab(NULL)+
  ylab("euro")

CRP01.IRL.INC.ALL.OTH <- CRP01.IRL.INC.ALL.OTH %>%
  filter(year>="2016")

Fig.IRL.TBUY.INC <- CRP01.IRL.INC.ALL.OTH %>%
  ggplot(aes(x=year,y=value,group=Type.of.Buyer))+
  geom_line(aes(colour=Type.of.Buyer),size=1.25,alpha=0.6)+
  scale_colour_manual(values=c("#0416AE","#030B53"))+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=6),
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Income")+
  xlab(NULL)+
  ylab("euro")

Fig.IRL.TBUY <- Fig.IRL.TBUY.VOL + Fig.IRL.TBUY.AGE + Fig.IRL.TBUY.PRC + Fig.IRL.TBUY.INC

Fig.IRL.TBUY

NUTS 3 Regions

Aggregate

### NUTS 3 Region
#### Volume
CRP01.NUTS3.VOL.ALL.ALL <- CRP01.NUTS3.VOL.ALL %>%
  filter(Type.of.Buyer=="All buyer types")

####### View the 4 statistical measures for NUTS3 across the aggregated categories (i.e. ALL.ALL)

CRP01.NUTS3.VOL.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#F59A08")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Volume of Sales")+
  xlab(NULL)+
  ylab("number")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.AGE.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#08F5BC")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Age")+
  xlab(NULL)+
  ylab("number")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.PRC.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#32AE04")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Price")+
  xlab(NULL)+
  ylab("euro")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.INC.ALL.ALL %>%
  ggplot(aes(x=year,y=value,group=Statistic))+
  geom_line(size=1.25,alpha=0.6,colour="#0416AE")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Income")+
  xlab(NULL)+
  ylab("euro")+
  facet_wrap(~NUTS.3.Region,ncol=2)

# Fig.NUTS3 <- Fig.NUTS3.VOL + Fig.NUTS3.AGE + Fig.NUTS3.PRC + Fig.NUTS3.INC # May be unsuitable, run in Markdown and if so revert to individual

Transaction Category

####### View the 4 statistical measures for NUTS3 for each transaction category and aggregated buyers (i.e. OTH.ALL)
##### Title: Figure.NUTS3.TCAT
CRP01.NUTS3.VOL.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#F59A08")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Volume of Sales")+
  xlab(NULL)+
  ylab("number")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.AGE.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#08F5BC")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Age")+
  xlab(NULL)+
  ylab("number")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.PRC.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#32AE04")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Price")+
  xlab(NULL)+
  ylab("euro")+
  facet_wrap(~NUTS.3.Region,ncol=2)

CRP01.NUTS3.INC.OTH.ALL %>%
  ggplot(aes(x=year,y=value,group=Transaction.Class))+
  geom_line(aes(linetype=Transaction.Class),size=1.25,alpha=0.6,colour="#0416AE")+
  geom_text_repel(aes(label=value),alpha=0.3,size=3,max.overlaps = 3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  ggtitle("Median Income")+
  xlab(NULL)+
  ylab("euro")+
  facet_wrap(~NUTS.3.Region,ncol=2)

Price to Income Ratio

I’ve included variables for price to income, a loan ceiling/cap which is 3.5 times income plus 10% of that figure as a deposit and finally a the latter expressed as a percentage of the median price. - This being the spread between what the median buyer can afford vs what the average price is, in the absence of savings.

Naturally Central Bank rules are not the only factor that determines prices but the below gives us an indication of how far off on average the buyers are.

The median price exceeded the loan ceiling for the first rime in 2021, having acted as a cap in 2019 & 2020.

PTI.Facet1 <- RATIO %>%
  ggplot(aes(x=year,y=PtI,group=NUTS.3.Region))+
  geom_line(aes(y=CAPtI),alpha=0.8,linetype="dotted")+
  geom_line(size=1.25,colour="#5DD7D2",alpha=0.7)+
  geom_text_repel(aes(label=PtI),alpha=0.4)+
  theme_bw()+
  theme(legend.position = "bottom",
      plot.title = element_text(size=12,face="bold"))+
  labs(caption="dotted line represents 3.5x median income plus 10% of that figure")+
  ggtitle("Price to Income Ratio")+
  ylab("price to income")

RATIO$price.lab <-  comma((RATIO$price/1000),digits=0)
RATIO$CAP.lab <-  comma((RATIO$CAP/1000),digits=0)
price.Facet2 <- RATIO %>%
  ggplot(aes(x=year,y=price,group=NUTS.3.Region))+
  geom_line(size=1.25,colour="#3C46A1",alpha=0.7)+
  geom_line(aes(y=CAP),colour="darkred",alpha=0.7,size=1.25)+
  geom_text_repel(aes(label=price.lab),colour="black",hjust="left",alpha=0.3)+
  geom_text_repel(aes(label=CAP.lab,y=CAP),colour="darkred",hjust="left",vjust=0.5,alpha=0.3)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(size=12,face="bold"))+
  labs(caption="red line represents 3.5x median income plus 10% of that figure")+
  ggtitle("Median Prices vs Average Loan Capacity")

spr.colour <- ifelse(RATIO$SPR > 0,"darkred","#1b5545")
SPR.Facet3 <- RATIO %>%
  ggplot(aes(x=year,y=SPR,group=NUTS.3.Region))+
  geom_hline(yintercept = 0,alpha=0.6,linetype="dotted")+
  geom_line(size=1.25,colour="#A13C56",alpha=0.7)+
  geom_text_repel(aes(label=SPR,colour=spr.colour),hjust="left",alpha=0.5)+
  scale_colour_manual(values=c("#CC0000","#1b5545"))+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(size=12,face="bold"))+
  labs(caption="")+
  ggtitle("Median Prices vs Average Loan Capacity: Spread")+
  ylab("euro")

#### MAP
NUTS <- sf::read_sf("C:\\Users\\charten\\OneDrive - Glenveagh Properties\\Research & Development\\1. Analysis\\NUTS_RG_01M_2021_4326.shp")
NUTS.IE <- NUTS %>%
  filter(CNTR_CODE=="IE")%>%
  filter(LEVL_CODE=="3")
NUTS.CLEAN <- readxl::read_xlsx(path="C:\\Users\\charten\\OneDrive - Glenveagh Properties\\Research & Development\\1. Analysis\\NUTS3_CLEAN.xlsx")
  
RATIO.PRC_NUTS3 <- CRP01.NUTS3.PRC.ALL.ALL %>%
  rename(price=value)
RATIO.PRC_NUTS3 <- RATIO.PRC_NUTS3 %>%
  select(3:7)
RATIO.INC_NUTS3 <- CRP01.NUTS3.INC.ALL.ALL %>%
  rename(income=value)
RATIO.INC_NUTS3 <- RATIO.INC_NUTS3 %>%
  select(3:7)

RATIO_NUTS3 <- merge(RATIO.PRC_NUTS3,RATIO.INC_NUTS3,by=c("Transaction.Class","NUTS.3.Region","Type.of.Buyer","year"))
RATIO_NUTS3 <- RATIO_NUTS3 %>%
  filter(year>="2012")
RATIO_NUTS3$PtI <- comma((RATIO_NUTS3$price/RATIO_NUTS3$income),digits = 2)
RATIO_NUTS3$CAP <- (RATIO_NUTS3$income*3.5)+(RATIO_NUTS3$income*3.5*.1)
RATIO_NUTS3$CAP <- comma(RATIO_NUTS3$CAP,big.mark = ",",digits=0)
RATIO_NUTS3$CAPtI <- comma((RATIO_NUTS3$CAP/RATIO_NUTS3$income),digits=2)
RATIO_NUTS3$SPR <- RATIO_NUTS3$CAP - RATIO_NUTS3$price  
RATIO_NUTS3$SPR <- comma(RATIO_NUTS3$SPR,big.mark = ",",digits=0)
RATIO_NUTS3$SPRPC <- comma((RATIO_NUTS3$SPR/RATIO_NUTS3$price),big.mark = ",",digits=2)*100

RATIO_NUTS3 <- merge(RATIO_NUTS3,NUTS.CLEAN,by="NUTS.3.Region")
SHP.RATIO_NUTS3 <- merge(NUTS.IE,RATIO_NUTS3,by.x="NAME_LATN",by.y="NAME_LATN")

SHP.RATIO_NUTS3.21 <- SHP.RATIO_NUTS3 %>%
  filter(year=="2021")
  
SPR.Facet4 <- SHP.RATIO_NUTS3.21 %>%
    ggplot()+
    geom_sf(aes(fill=SPRPC),alpha=0.6)+
    theme_void()+
    scale_fill_viridis_c(option = "magma", name="%")+
    geom_sf_text(aes(label=SPRPC),color="navy",size=2.5)+
    theme(legend.title = element_text(size = 10),
          legend.text = element_text(size = 8))+
    theme(legend.position = "right")+
    theme(plot.title = element_text(size=12,face="bold"))+
    facet_wrap(~year,ncol=4)+
    theme(strip.text.x = element_text(size = 10,colour = "navy"))+
    ggtitle("Spread as Percentage of price - NUTS 3 Regions")

#PTI.Facet1 + price.Facet2 + SPR.Facet3 + SPR.Facet4 + plot_layout(widths = c(1,1))
  
PTI.Facet1 

price.Facet2 

SPR.Facet3 

SPR.Facet4

SHP.RATIO_NUTS3 %>%
  ggplot()+
  geom_sf(aes(fill=PtI),alpha=0.9)+
  theme_void()+
  scale_fill_distiller(palette = "Spectral", name="Price to Income")+
  theme(legend.title = element_text(size = 10),
        legend.text = element_text(size = 8))+
  theme(legend.position = "left")+
  theme(plot.title = element_text(size=16,face="bold"))+
  facet_wrap(~year,ncol=3)+
  theme(strip.text.x = element_text(size = 10,colour = "navy"))+
  ggtitle("Price to Income - NUTS 3 Regions")

Spread

options(scipen=999)
RATIO_NUTS3_Max <- RATIO_NUTS3 %>%
  group_by(NUTS.3.Region) %>%
  slice(which.max(year))
RATIO_NUTS3_Max$lab <- paste("Spread : ", RATIO_NUTS3_Max$SPRPC," %")
spr.max.colour <- ifelse(RATIO_NUTS3_Max$SPR > 0,"darkred","#1b5545")
# 
# # Option A
# RATIO_NUTS3 %>%
#   ggplot(aes(x=year,y=price,group=NUTS.3.Region))+
#   geom_line(size=1.25,colour="#3C46A1",alpha=0.7)+
#   geom_line(aes(y=CAP),colour="darkred",alpha=0.7,size=1.25)+
#   geom_text(data=RATIO_NUTS3_Max,aes(label=lab,y=105000,colour=spr.max.colour),hjust="right",alpha=0.6)+
#   scale_colour_manual(values=c("#CC0000","#1b5545"))+
#   theme_bw()+
#   theme(legend.position = "none",
#         plot.title = element_text(size=12,face="bold"))+
#   labs(caption="red line represents 3.5x median income plus 10% of that figure")+
#   ggtitle("Median Prices vs Average Loan Capacity")+
#   facet_wrap(~NUTS.3.Region,ncol=2)
# 
# # Option B
spr.colour <- ifelse(RATIO_NUTS3$SPR > 0,"darkred","#1b5545")

RATIO_NUTS3 %>%
  ggplot(aes(x=year,y=SPRPC,group=NUTS.3.Region))+
  geom_hline(yintercept = 0,alpha=0.4,linetype="dotted")+
  geom_line(size=1.25,colour="#A13C56",alpha=0.7)+
  geom_text_repel(aes(label=SPRPC,colour=spr.colour),alpha=0.7,size=2.75)+
  scale_colour_manual(values=c("#CC0000","#1b5545"))+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(size=12,face="bold"))+
  labs(caption="")+
  ggtitle("Median Prices vs Average Loan Capacity: Spread %")+
  ylab("%")+
  facet_wrap(~NUTS.3.Region,ncol=2)

House Price Index

setwd("/Users/charten/OneDrive - Glenveagh Properties/Research & Development/1. Analysis/")
GEO_Merge <- readxl::read_xlsx(path="C:\\Users\\charten\\OneDrive - Glenveagh Properties\\Research & Development\\1. Analysis\\HPM04_GEO.xlsx",sheet = 1)
shp <- sf::read_sf("Constituency_Boundaries_Ungeneralised___OSi_National_Electoral_Boundaries___2017.shp")

HPM09 <- cso_get_data("HPM09")
HPM09_long <- HPM09 %>%
  pivot_longer(!1:2, names_to = "year_month")
rm(HPM09)
HPM09 <- HPM09_long
rm(HPM09_long)

HPM09$Month <- as.Date(paste(HPM09$year_month, "01", sep = "-"), "%YM%m-%d")
HPM09$Year <- year(HPM09$Month)
HPM04 <- cso_get_data("HPM04")
HPM04_long <- HPM04 %>%
  pivot_longer(!1:5, names_to = "year_month")
rm(HPM04)
HPM04 <- HPM04_long
rm(HPM04_long)
### Date transformation
HPM04$Year <-substr(HPM04$year_month,1,4)
HPM04$Month <- sub(".* ", "", HPM04$year_month)
HPM04$Month_NR <- as.integer(factor(HPM04$Month, levels=month.name))
HPM04$Date <- as.yearmon(paste(HPM04$Year, HPM04$Month_NR), "%Y %m")
HPM04_join <- full_join(HPM04, GEO_Merge, by = "Eircode.Output")
HPM04 <- HPM04_join
rm(HPM04_join)
HPM09$Year <-substr(HPM09$year_month,1,4)
HPM09$Month <- sub(".* ", "", HPM09$year_month)
HPM09$Month_NR <- as.integer(factor(HPM09$Month, levels=month.name))
HPM09$Date <- as.yearmon(paste(HPM09$Year, HPM09$Month_NR), "%Y %m")

HPM09_1 <- HPM09 %>%
  filter(Statistic == "Residential Property Price Index")%>%
  filter(Type.of.Residential.Property == "National - all residential properties")

HPM09_2 <- HPM09 %>%
  filter(Statistic == "Percentage Change over 12 months for Residential Property Price Index")%>%
  filter(Type.of.Residential.Property == "National - all residential properties")

RPPI_tail_2 <- tail(HPM09_2,1)
RPPI_tail_2_lag <-head(tail(HPM09_2,2),1)
RRPI_Line_1 <- ggplot(data=HPM09_1, aes(x=Date, y=value, group = Type.of.Residential.Property))+
  geom_line(linejoin="mitre",size = 1.25, linetype = 1,alpha = 0.5, colour="#1b5545")+
  labs(title = "Residential Property Price Index" ,
       y="2015 = 100",
       x="Month")+
  geom_text_repel(aes(label=value),data = HPM09_1, size = 3)+
  theme_bw()+
  theme(legend.position = "bottom")+theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

HPM09_1_T12 <- tail(HPM09_1,12)
RRPI_Line_2 <- ggplot(data=HPM09_1_T12, aes(x=Date, y=value, group = Type.of.Residential.Property))+
  geom_line(linejoin="mitre",size = 1.25, linetype = 1,alpha = 0.5, colour="#1b5545")+
  labs(title = "Residential Property Price Index" ,
       subtitle = "12 Month Series",
       y="2015 = 100",
       x="Month")+
  geom_text(aes(label=value),vjust= 1.5, hjust = 0, size=3)+
  theme_bw()+
  theme(legend.position = "bottom")+theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

RRPI_Line_1+RRPI_Line_2+plot_layout(ncol = 2)

HPM09_2_T24 <- tail(HPM09_2,24)
colour <- ifelse(HPM09_2_T24$value < 0,"#CC0000","#1b5545")
RPPI_Bar_2 <- ggplot(data=HPM09_2_T24, aes(x=Date, y=value, group = Type.of.Residential.Property))+
  geom_col(alpha = 0.5, colour="#373634", fill = colour)+
  labs(title = "Year on Year Percentage Change for Residential Property Price Index" ,
       subtitle = "24 Month Series",
       y="Percentage change",
       x="Month")+
  geom_text(aes(label=value),vjust= 1.5, size=3)+
  theme_bw()+
  theme(legend.position = "bottom")+

rm(HPM09)

The national house price inflation for is 12.2%. This represents a -1.1 change from which was 13.3%.

Prices: 12 Month Rolling Average

# Rolling 12 Month Market-based Household Purchases of Residential Dwellings

HPM08 <- cso_get_data("HPM08")

HPM08 <- HPM08 %>%
  pivot_longer(!1:5, names_to = "year_month")
HPM08$Year <-substr(HPM08$year_month,1,4)
HPM08$Month <- sub(".* ", "", HPM08$year_month)
HPM08$Month_NR <- as.integer(factor(HPM08$Month, levels=month.name))
HPM08$Date <- as.yearmon(paste(HPM08$Year, HPM08$Month_NR), "%Y %m")

HPM08$value = as.numeric(HPM08$value)
HPM08$value <- comma(HPM08$value,big.mark = ",")
HPM08$lab <- paste(HPM08$Month,":",round(HPM08$value,digits=0))
HPM08$value_short <- round((HPM08$value/1000),digits=1)
# Mean
## Subset

HPM08_1 <- HPM08 %>%
  filter(Statistic=="Moving 12 Month Mean Sale Price")

### Take the Executions & All Buyer Types, remove All Dwelling Statuses

HPM08_1 <- HPM08_1 %>%
  filter(Type.of.Buyer=="All Buyer Types") %>%
  filter(Stamp.Duty.Event=="Executions") %>%
  filter(Dwelling.Status!="All Dwelling Statuses")

### Split by all and Eircode Output Areas

HPM08_1.ALL <- HPM08_1 %>%
  filter(Eircode.Output=="All")

HPM08_1.ALL_Max <- HPM08_1.ALL %>%
  group_by(Dwelling.Status) %>%
  slice(which.max(Date))

HPM08_1.EOA <- HPM08_1 %>%
  filter(Eircode.Output!="All")

HPM08_1.EOA <- HPM08_1.EOA %>%                            # Add lagged column
  group_by(Eircode.Output,Dwelling.Status) %>%
  dplyr::mutate(lag12 = dplyr::lag(value, n = 12, default = NA)) %>% 
  as.data.frame()

HPM08_1.EOA$Diffpc <- ((HPM08_1.EOA$value-HPM08_1.EOA$lag12)/HPM08_1.EOA$lag12)*100

GEO_Merge <- readxl::read_xlsx(path="C:\\Users\\charten\\OneDrive - Glenveagh Properties\\Research & Development\\1. Analysis\\HPM04_GEO.xlsx",sheet = 1)
HPM08_1.EOA <- full_join(HPM08_1.EOA, GEO_Merge, by = "Eircode.Output")

SUM_HPM08_1.EOA <-HPM08_1.EOA %>%
  group_by(Seat_Tag, Dwelling.Status, Date)%>% 
  summarise(value = mean(value,na.rm=TRUE))
  
SUM_HPM08_1.EOA <- SUM_HPM08_1.EOA %>%                            # Add lagged column
  group_by(Seat_Tag,Dwelling.Status) %>%
  dplyr::mutate(lag12 = dplyr::lag(value, n = 12, default = NA)) %>% 
  as.data.frame()

SUM_HPM08_1.EOA$Diffpc <- ((SUM_HPM08_1.EOA$value-SUM_HPM08_1.EOA$lag12)/SUM_HPM08_1.EOA$lag12)*100

HPM08_1.EOA_Max <- HPM08_1.EOA %>%
  group_by(Eircode.Output,Dwelling.Status) %>%
  slice(which.max(Date))

SUM_HPM08_1.EOA_Max <- SUM_HPM08_1.EOA %>%
  group_by(Seat_Tag,Dwelling.Status) %>%
  slice(which.max(Date))

# Plot
HPM08_1.ALL %>%
  ggplot(aes(x=Date,y=value,group=Dwelling.Status,colour=Dwelling.Status))+
  geom_line(size=1.25,alpha=0.7)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ylab("euro")+xlab(NULL)+
  ggtitle("Market-based Household Purchases")+
  labs(subtitle="Mean Rolling 12 Month") +
  geom_text_repel(aes(label=value_short),alpha=0.6,size=2.75)+
  geom_text(data=HPM08_1.ALL_Max,aes(label=lab),colour="black",hjust="right",vjust=1,size=3,fontface="bold",alpha=0.6)

A chart for each Eircode Output Area can be seen in the Appendix below.

12 Month Variation

The latest values for these can be seen in the scroll box below. Also included is the lagged value, the rolling average for the 12 month period prior. The variation for each can be seen in the right most column.

Table <- HPM08_1.EOA_Max %>%
  select(2,3,6,7,14,15,23)
Table <- Table[,c(2,7,1,3,4,5,6)]
  
Table %>%
  kbl(caption = "Eircode Output Areas")%>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = T)%>%
  scroll_box(width = "800px", height = "300px") 
Eircode Output Areas
Eircode.Output Constituency Dwelling.Status year_month value lag12 Diffpc
A41: Ballyboughal Dublin Fingal New 2022 August NA 517,474.00 NA
A41: Ballyboughal Dublin Fingal Existing 2022 August 674,357.00 545,417.00 23.64
A42: Garristown Dublin Fingal New 2022 August 475,000.00 387,475.00 22.59
A42: Garristown Dublin Fingal Existing 2022 August 428,929.00 390,560.00 9.82
A45: Oldtown Dublin Fingal New 2022 August 597,169.00 NA NA
A45: Oldtown Dublin Fingal Existing 2022 August 405,750.00 372,000.00 9.07
A63: Greystones Wicklow New 2022 August 548,685.00 608,014.00 -9.76
A63: Greystones Wicklow Existing 2022 August 559,849.00 474,033.00 18.10
A67: Wicklow Wicklow New 2022 August 349,294.00 373,807.00 -6.56
A67: Wicklow Wicklow Existing 2022 August 397,377.00 345,539.00 15.00
A75: Castleblaney Cavan-Monaghan New 2022 August 97,894.00 241,211.00 -59.42
A75: Castleblaney Cavan-Monaghan Existing 2022 August 175,249.00 176,569.00 -0.75
A81: Carrickmacross Cavan-Monaghan New 2022 August 261,342.00 173,770.00 50.40
A81: Carrickmacross Cavan-Monaghan Existing 2022 August 227,268.00 201,792.00 12.62
A82: Kells Meath East New 2022 August 292,293.00 234,898.00 24.43
A82: Kells Meath East Existing 2022 August 226,599.00 203,110.00 11.56
A83: Enfield Meath West New 2022 August 329,961.00 321,129.00 2.75
A83: Enfield Meath West Existing 2022 August 331,874.00 281,470.00 17.91
A84: Ashbourne Meath East New 2022 August 506,364.00 442,808.00 14.35
A84: Ashbourne Meath East Existing 2022 August 313,764.00 317,275.00 -1.11
A85: Dunshaughlin Meath East New 2022 August 370,661.00 349,468.00 6.06
A85: Dunshaughlin Meath East Existing 2022 August 418,030.00 380,426.00 9.88
A86: Dunboyne Meath East New 2022 August 418,425.00 384,410.00 8.85
A86: Dunboyne Meath East Existing 2022 August 421,134.00 384,627.00 9.49
A91: Dundalk Louth New 2022 August 290,953.00 289,546.00 0.49
A91: Dundalk Louth Existing 2022 August 257,736.00 226,852.00 13.61
A92: Drogheda Louth New 2022 August 317,629.00 311,477.00 1.98
A92: Drogheda Louth Existing 2022 August 269,520.00 241,723.00 11.50
A94: Blackrock Dun Laoghaire New 2022 August 1,065,670.00 1,003,873.00 6.16
A94: Blackrock Dun Laoghaire Existing 2022 August 787,026.00 730,753.00 7.70
A96: Glenageary Dun Laoghaire New 2022 August 857,849.00 817,604.00 4.92
A96: Glenageary Dun Laoghaire Existing 2022 August 864,749.00 751,126.00 15.13
A98: Bray Wicklow New 2022 August 575,821.00 721,499.00 -20.19
A98: Bray Wicklow Existing 2022 August 501,768.00 445,319.00 12.68
C15: Navan Meath West New 2022 August 342,694.00 369,738.00 -7.31
C15: Navan Meath West Existing 2022 August 298,174.00 258,289.00 15.44
D01: Dublin 1 Dublin Central New 2022 August 461,567.00 NA NA
D01: Dublin 1 Dublin Central Existing 2022 August 326,794.00 305,234.00 7.06
D02: Dublin 2 Dublin Bay South New 2022 August 704,705.00 766,962.00 -8.12
D02: Dublin 2 Dublin Bay South Existing 2022 August 568,741.00 444,478.00 27.96
D03: Dublin 3 Dublin Bay North New 2022 August 757,263.00 727,723.00 4.06
D03: Dublin 3 Dublin Bay North Existing 2022 August 546,512.00 490,565.00 11.40
D04: Dublin 4 Dublin Bay South New 2022 August 1,424,748.00 1,349,270.00 5.59
D04: Dublin 4 Dublin Bay South Existing 2022 August 837,563.00 774,576.00 8.13
D05: Dublin 5 Dublin Bay North New 2022 August 615,714.00 666,569.00 -7.63
D05: Dublin 5 Dublin Bay North Existing 2022 August 466,454.00 426,934.00 9.26
D06: Dublin 6 Dublin Bay South New 2022 August 1,334,454.00 862,005.00 54.81
D06: Dublin 6 Dublin Bay South Existing 2022 August 870,537.00 778,205.00 11.86
D07: Dublin 7 Dublin West New 2022 August NA 1,022,666.00 NA
D07: Dublin 7 Dublin West Existing 2022 August 416,169.00 373,190.00 11.52
D08: Dublin 8 Dublin South Central New 2022 August 806,794.00 655,701.00 23.04
D08: Dublin 8 Dublin South Central Existing 2022 August 395,331.00 376,463.00 5.01
D09: Dublin 9 Dublin North-West New 2022 August 770,182.00 575,819.00 33.75
D09: Dublin 9 Dublin North-West Existing 2022 August 457,270.00 431,519.00 5.97
D10: Dublin 10 Dublin South Central New 2022 August NA NA NA
D10: Dublin 10 Dublin South Central Existing 2022 August 272,754.00 242,535.00 12.46
D11: Dublin 11 Dublin West New 2022 August 262,131.00 269,149.00 -2.61
D11: Dublin 11 Dublin West Existing 2022 August 334,577.00 297,358.00 12.52
D12: Dublin 12 Dublin South Central New 2022 August 632,387.00 523,483.00 20.80
D12: Dublin 12 Dublin South Central Existing 2022 August 389,952.00 359,035.00 8.61
D13: Dublin 13 Dublin Bay North New 2022 August 545,287.00 471,571.00 15.63
D13: Dublin 13 Dublin Bay North Existing 2022 August 551,397.00 467,795.00 17.87
D14: Dublin 14 Dublin Bay South New 2022 August 776,578.00 735,756.00 5.55
D14: Dublin 14 Dublin Bay South Existing 2022 August 683,587.00 625,472.00 9.29
D15: Dublin 15 Dublin West New 2022 August 436,381.00 406,288.00 7.41
D15: Dublin 15 Dublin West Existing 2022 August 399,415.00 379,896.00 5.14
D16: Dublin 16 Dublin South-West New 2022 August 771,962.00 611,194.00 26.30
D16: Dublin 16 Dublin South-West Existing 2022 August 571,482.00 503,481.00 13.51
D17: Dublin 17 Dublin Fingal New 2022 August 456,777.00 NA NA
D17: Dublin 17 Dublin Fingal Existing 2022 August 302,113.00 269,468.00 12.11
D18: Dublin 18 Dublin Rathdown New 2022 August 650,309.00 606,455.00 7.23
D18: Dublin 18 Dublin Rathdown Existing 2022 August 618,147.00 554,144.00 11.55
D20: Dublin 20 Dublin South Central New 2022 August 605,467.00 600,000.00 0.91
D20: Dublin 20 Dublin South Central Existing 2022 August 351,834.00 347,429.00 1.27
D22: Dublin 22 Dublin South Central New 2022 August 376,914.00 388,114.00 -2.89
D22: Dublin 22 Dublin South Central Existing 2022 August 311,216.00 284,755.00 9.29
D24: Dublin 24 Dublin South-West New 2022 August 402,960.00 433,158.00 -6.97
D24: Dublin 24 Dublin South-West Existing 2022 August 341,898.00 310,444.00 10.13
D6W: Dublin 6W Dublin South Central New 2022 August 776,188.00 604,856.00 28.33
D6W: Dublin 6W Dublin South Central Existing 2022 August 624,795.00 614,362.00 1.70
E21: Cahir Tipperary New 2022 August 245,000.00 119,175.00 105.58
E21: Cahir Tipperary Existing 2022 August 195,115.00 169,073.00 15.40
E25: Cashel Tipperary New 2022 August 192,950.00 234,879.00 -17.85
E25: Cashel Tipperary Existing 2022 August 175,957.00 163,500.00 7.62
E32: Carrick-on-Suir Tipperary New 2022 August 340,001.00 228,506.00 48.79
E32: Carrick-on-Suir Tipperary Existing 2022 August 192,744.00 163,256.00 18.06
E34: Tipperary Tipperary New 2022 August 102,150.00 349,353.00 -70.76
E34: Tipperary Tipperary Existing 2022 August 164,675.00 142,192.00 15.81
E41: Thurles Tipperary New 2022 August 191,815.00 197,490.00 -2.87
E41: Thurles Tipperary Existing 2022 August 189,277.00 166,329.00 13.80
E45: Nenagh Tipperary New 2022 August 249,338.00 215,532.00 15.68
E45: Nenagh Tipperary Existing 2022 August 227,522.00 186,517.00 21.98
E53: Roscrea Tipperary New 2022 August 164,000.00 193,418.00 -15.21
E53: Roscrea Tipperary Existing 2022 August 177,820.00 154,116.00 15.38
E91: Clonmel Tipperary New 2022 August 342,500.00 272,514.00 25.68
E91: Clonmel Tipperary Existing 2022 August 220,704.00 201,325.00 9.63
F12: Claremorris Mayo New 2022 August 191,843.00 146,274.00 31.15
F12: Claremorris Mayo Existing 2022 August 166,346.00 140,615.00 18.30
F23: Castlebar Mayo New 2022 August 275,594.00 237,165.00 16.20
F23: Castlebar Mayo Existing 2022 August 190,288.00 166,861.00 14.04
F26: Ballina Mayo New 2022 August 229,117.00 230,776.00 -0.72
F26: Ballina Mayo Existing 2022 August 168,258.00 142,312.00 18.23
F28: Westport Mayo New 2022 August 312,053.00 211,787.00 47.34
F28: Westport Mayo Existing 2022 August 262,451.00 219,781.00 19.41
F31: Ballinrobe Mayo New 2022 August 363,200.00 190,880.00 90.28
F31: Ballinrobe Mayo Existing 2022 August 172,347.00 147,845.00 16.57
F35: Ballyhaunis Mayo New 2022 August 154,370.00 161,454.00 -4.39
F35: Ballyhaunis Mayo Existing 2022 August 131,370.00 117,022.00 12.26
F42: Roscommon Roscommon-Galway New 2022 August 308,999.00 233,305.00 32.44
F42: Roscommon Roscommon-Galway Existing 2022 August 176,997.00 169,576.00 4.38
F45: Castlerea Roscommon-Galway New 2022 August 184,573.00 127,417.00 44.86
F45: Castlerea Roscommon-Galway Existing 2022 August 128,502.00 103,269.00 24.43
F52: Boyle Sligo-Leitrim New 2022 August 147,562.00 173,613.00 -15.01
F52: Boyle Sligo-Leitrim Existing 2022 August 157,059.00 139,962.00 12.22
F56: Ballymote Sligo-Leitrim New 2022 August 191,853.00 142,818.00 34.33
F56: Ballymote Sligo-Leitrim Existing 2022 August 140,619.00 112,524.00 24.97
F91: Sligo Sligo-Leitrim New 2022 August 252,904.00 185,159.00 36.59
F91: Sligo Sligo-Leitrim Existing 2022 August 207,647.00 178,255.00 16.49
F92: Letterkenny Donegal New 2022 August 259,078.00 236,610.00 9.50
F92: Letterkenny Donegal Existing 2022 August 174,936.00 162,736.00 7.50
F93: Lifford Donegal New 2022 August 287,993.00 175,180.00 64.40
F93: Lifford Donegal Existing 2022 August 146,197.00 133,515.00 9.50
F94: Donegal Donegal New 2022 August 226,689.00 178,678.00 26.87
F94: Donegal Donegal Existing 2022 August 169,122.00 144,508.00 17.03
H12: Cavan Cavan-Monaghan New 2022 August 225,013.00 216,331.00 4.01
H12: Cavan Cavan-Monaghan Existing 2022 August 179,041.00 157,962.00 13.34
H14: Belturbet Cavan-Monaghan New 2022 August 236,186.00 206,570.00 14.34
H14: Belturbet Cavan-Monaghan Existing 2022 August 143,837.00 127,309.00 12.98
H16: Cootehill Cavan-Monaghan New 2022 August 200,600.00 NA NA
H16: Cootehill Cavan-Monaghan Existing 2022 August 158,109.00 143,482.00 10.19
H18: Monaghan Cavan-Monaghan New 2022 August 316,525.00 386,001.00 -18.00
H18: Monaghan Cavan-Monaghan Existing 2022 August 200,940.00 170,905.00 17.57
H23: Clones Cavan-Monaghan New 2022 August NA NA NA
H23: Clones Cavan-Monaghan Existing 2022 August 131,406.00 92,750.00 41.68
H53: Ballinasloe Roscommon-Galway New 2022 August 228,447.00 222,164.00 2.83
H53: Ballinasloe Roscommon-Galway Existing 2022 August 190,176.00 158,897.00 19.69
H54: Tuam Galway East New 2022 August 214,402.00 222,370.00 -3.58
H54: Tuam Galway East Existing 2022 August 203,953.00 178,465.00 14.28
H62: Loughrea Galway East New 2022 August 290,454.00 264,826.00 9.68
H62: Loughrea Galway East Existing 2022 August 216,463.00 204,182.00 6.01
H65: Athenry Galway East New 2022 August 323,264.00 285,161.00 13.36
H65: Athenry Galway East Existing 2022 August 286,619.00 251,219.00 14.09
H71: Clifden Galway West New 2022 August 440,000.00 292,830.00 50.26
H71: Clifden Galway West Existing 2022 August 270,808.00 205,769.00 31.61
H91: Galway Galway West New 2022 August 417,121.00 382,361.00 9.09
H91: Galway Galway West Existing 2022 August 323,597.00 292,169.00 10.76
K32: Balbriggan Dublin Fingal New 2022 August 344,561.00 335,215.00 2.79
K32: Balbriggan Dublin Fingal Existing 2022 August 282,850.00 240,914.00 17.41
K34: Skerries Dublin Fingal New 2022 August 347,839.00 417,362.00 -16.66
K34: Skerries Dublin Fingal Existing 2022 August 504,376.00 467,727.00 7.84
K36: Malahide Dublin Fingal New 2022 August 652,799.00 595,288.00 9.66
K36: Malahide Dublin Fingal Existing 2022 August 623,505.00 560,274.00 11.29
K45: Lusk Dublin Fingal New 2022 August 411,087.00 358,088.00 14.80
K45: Lusk Dublin Fingal Existing 2022 August 353,022.00 319,987.00 10.32
K56: Rush Dublin Fingal New 2022 August 387,796.00 386,041.00 0.45
K56: Rush Dublin Fingal Existing 2022 August 349,927.00 349,669.00 0.07
K67: Swords Dublin Fingal New 2022 August 443,510.00 404,208.00 9.72
K67: Swords Dublin Fingal Existing 2022 August 362,941.00 329,651.00 10.10
K78: Lucan Dublin Mid-West New 2022 August 452,816.00 432,288.00 4.75
K78: Lucan Dublin Mid-West Existing 2022 August 376,653.00 355,877.00 5.84
N37: Athlone Longford-Westmeath New 2022 August 319,212.00 304,504.00 4.83
N37: Athlone Longford-Westmeath Existing 2022 August 227,500.00 203,397.00 11.85
N39: Longford Longford-Westmeath New 2022 August 208,706.00 222,379.00 -6.15
N39: Longford Longford-Westmeath Existing 2022 August 161,751.00 132,566.00 22.02
N41: Carrick-on-Shannon Sligo-Leitrim New 2022 August 208,972.00 157,606.00 32.59
N41: Carrick-on-Shannon Sligo-Leitrim Existing 2022 August 164,708.00 141,331.00 16.54
N91: Mullingar Longford-Westmeath New 2022 August 355,432.00 314,949.00 12.85
N91: Mullingar Longford-Westmeath Existing 2022 August 235,605.00 198,412.00 18.75
P12: Macroom Cork North-West New 2022 August 309,853.00 261,091.00 18.68
P12: Macroom Cork North-West Existing 2022 August 230,613.00 217,719.00 5.92
P14: Crookstown Cork North-West New 2022 August 367,030.00 424,362.00 -13.51
P14: Crookstown Cork North-West Existing 2022 August 281,536.00 340,042.00 -17.21
P17: Kinsale Cork South-West New 2022 August 388,450.00 422,798.00 -8.12
P17: Kinsale Cork South-West Existing 2022 August 520,559.00 393,662.00 32.24
P24: Cobh Cork East New 2022 August 302,376.00 282,214.00 7.14
P24: Cobh Cork East Existing 2022 August 284,606.00 239,510.00 18.83
P25: Midleton Cork East New 2022 August 362,041.00 336,455.00 7.60
P25: Midleton Cork East Existing 2022 August 287,286.00 259,115.00 10.87
P31: Ballincollig Cork North-West New 2022 August 390,991.00 390,065.00 0.24
P31: Ballincollig Cork North-West Existing 2022 August 370,220.00 331,136.00 11.80
P32: Rylane Cork North-West New 2022 August 415,750.00 380,000.00 9.41
P32: Rylane Cork North-West Existing 2022 August 287,583.00 205,778.00 39.75
P36: Youghal Cork East New 2022 August 606,240.00 337,989.00 79.37
P36: Youghal Cork East Existing 2022 August 236,988.00 218,654.00 8.38
P43: Carrigaline Cork South-Central New 2022 August 358,090.00 357,223.00 0.24
P43: Carrigaline Cork South-Central Existing 2022 August 375,227.00 302,733.00 23.95
P47: Dunmanway Cork South-West New 2022 August 407,499.00 350,325.00 16.32
P47: Dunmanway Cork South-West Existing 2022 August 216,283.00 177,329.00 21.97
P51: Mallow Cork East New 2022 August 294,915.00 273,739.00 7.74
P51: Mallow Cork East Existing 2022 August 203,360.00 163,530.00 24.36
P56: Charleville Cork North-West New 2022 August NA 125,533.00 NA
P56: Charleville Cork North-West Existing 2022 August 182,117.00 148,207.00 22.88
P61: Fermoy Cork East New 2022 August 431,350.00 332,398.00 29.77
P61: Fermoy Cork East Existing 2022 August 260,532.00 200,913.00 29.67
P67: Mitchelstown Cork East New 2022 August 316,363.00 280,972.00 12.60
P67: Mitchelstown Cork East Existing 2022 August 232,338.00 190,567.00 21.92
P72: Bandon Cork South-West New 2022 August 318,016.00 397,138.00 -19.92
P72: Bandon Cork South-West Existing 2022 August 282,198.00 224,716.00 25.58
P75: Bantry Cork South-West New 2022 August 242,615.00 261,190.00 -7.11
P75: Bantry Cork South-West Existing 2022 August 227,777.00 193,530.00 17.70
P81: Skibbereen Cork South-West New 2022 August 329,254.00 251,718.00 30.80
P81: Skibbereen Cork South-West Existing 2022 August 345,496.00 270,952.00 27.51
P85: Clonakilty Cork South-West New 2022 August 357,131.00 353,393.00 1.06
P85: Clonakilty Cork South-West Existing 2022 August 277,309.00 289,442.00 -4.19
R14: Athy Kildare South New 2022 August 300,000.00 NA NA
R14: Athy Kildare South Existing 2022 August 217,302.00 200,725.00 8.26
R21: Mhuine Bheag Carlow-Kilkenny New 2022 August NA 312,125.00 NA
R21: Mhuine Bheag Carlow-Kilkenny Existing 2022 August 257,771.00 187,940.00 37.16
R32: Portlaoise Laois-Offaly New 2022 August 284,450.00 248,754.00 14.35
R32: Portlaoise Laois-Offaly Existing 2022 August 219,724.00 196,774.00 11.66
R35: Tullamore Laois-Offaly New 2022 August 286,385.00 264,707.00 8.19
R35: Tullamore Laois-Offaly Existing 2022 August 228,192.00 195,006.00 17.02
R42: Birr Laois-Offaly New 2022 August 284,898.00 255,272.00 11.61
R42: Birr Laois-Offaly Existing 2022 August 195,449.00 157,787.00 23.87
R45: Edenderry Laois-Offaly New 2022 August 251,959.00 240,681.00 4.69
R45: Edenderry Laois-Offaly Existing 2022 August 216,735.00 185,648.00 16.75
R51: Kildare Kildare South New 2022 August 295,246.00 298,854.00 -1.21
R51: Kildare Kildare South Existing 2022 August 299,525.00 254,422.00 17.73
R56: Curragh Kildare South New 2022 August 410,698.00 368,386.00 11.49
R56: Curragh Kildare South Existing 2022 August 340,282.00 292,988.00 16.14
R93: Carlow Carlow-Kilkenny New 2022 August 259,384.00 249,235.00 4.07
R93: Carlow Carlow-Kilkenny Existing 2022 August 223,522.00 206,521.00 8.23
R95: Kilkenny Carlow-Kilkenny New 2022 August 394,463.00 348,345.00 13.24
R95: Kilkenny Carlow-Kilkenny Existing 2022 August 274,345.00 245,474.00 11.76
T12: Cork Southside Cork North-Central New 2022 August 441,822.00 417,636.00 5.79
T12: Cork Southside Cork North-Central Existing 2022 August 353,355.00 325,933.00 8.41
T23: Cork Northside Cork North-Central New 2022 August 425,818.00 397,421.00 7.15
T23: Cork Northside Cork North-Central Existing 2022 August 260,989.00 244,546.00 6.72
T34: Carrignavar Cork East New 2022 August 332,258.00 NA NA
T34: Carrignavar Cork East Existing 2022 August 371,542.00 285,112.00 30.31
T45: Glanmire Cork North-Central New 2022 August 342,767.00 337,284.00 1.63
T45: Glanmire Cork North-Central Existing 2022 August 366,274.00 310,939.00 17.80
T56: Watergrasshill Cork North-Central New 2022 August 321,977.00 325,904.00 -1.20
T56: Watergrasshill Cork North-Central Existing 2022 August 318,477.00 292,461.00 8.90
V14: Shannon Clare New 2022 August 136,200.00 234,888.00 -42.01
V14: Shannon Clare Existing 2022 August 192,268.00 170,269.00 12.92
V15: Kilrush Clare New 2022 August 194,820.00 268,506.00 -27.44
V15: Kilrush Clare Existing 2022 August 178,253.00 154,521.00 15.36
V23: Caherciveen Kerry New 2022 August 244,811.00 219,491.00 11.54
V23: Caherciveen Kerry Existing 2022 August 243,357.00 192,963.00 26.12
V31: Listowel Kerry New 2022 August 224,316.00 195,605.00 14.68
V31: Listowel Kerry Existing 2022 August 191,157.00 165,748.00 15.33
V35: Kilmallock Limerick County New 2022 August 297,384.00 313,861.00 -5.25
V35: Kilmallock Limerick County Existing 2022 August 186,124.00 166,509.00 11.78
V42: Newcastle West Limerick County New 2022 August 199,859.00 166,975.00 19.69
V42: Newcastle West Limerick County Existing 2022 August 193,402.00 158,432.00 22.07
V92: Tralee Kerry New 2022 August 281,695.00 299,137.00 -5.83
V92: Tralee Kerry Existing 2022 August 219,929.00 192,346.00 14.34
V93: Killarney Kerry New 2022 August 325,856.00 345,354.00 -5.65
V93: Killarney Kerry Existing 2022 August 281,515.00 227,361.00 23.82
V94: Limerick Limerick City New 2022 August 357,728.00 331,534.00 7.90
V94: Limerick Limerick City Existing 2022 August 249,276.00 234,523.00 6.29
V95: Ennis Clare New 2022 August 321,030.00 289,794.00 10.78
V95: Ennis Clare Existing 2022 August 250,897.00 205,167.00 22.29
W12: Newbridge Kildare South New 2022 August 399,492.00 349,483.00 14.31
W12: Newbridge Kildare South Existing 2022 August 308,919.00 271,374.00 13.84
W23: Celbridge Kildare North New 2022 August 429,622.00 410,994.00 4.53
W23: Celbridge Kildare North Existing 2022 August 395,407.00 368,716.00 7.24
W34: Monasterevin Kildare South New 2022 August 323,879.00 285,566.00 13.42
W34: Monasterevin Kildare South Existing 2022 August 239,767.00 213,457.00 12.33
W91: Naas Kildare North New 2022 August 391,839.00 358,218.00 9.39
W91: Naas Kildare North Existing 2022 August 358,761.00 333,652.00 7.53
X35: Dungarvan Waterford New 2022 August 279,929.00 287,986.00 -2.80
X35: Dungarvan Waterford Existing 2022 August 290,448.00 228,178.00 27.29
X42: Kilmacthomas Waterford New 2022 August 307,473.00 297,004.00 3.52
X42: Kilmacthomas Waterford Existing 2022 August 246,092.00 198,152.00 24.19
X91: Waterford Waterford New 2022 August 326,547.00 285,653.00 14.32
X91: Waterford Waterford Existing 2022 August 240,571.00 209,961.00 14.58
Y14: Arklow Wicklow New 2022 August 534,338.00 337,608.00 58.27
Y14: Arklow Wicklow Existing 2022 August 263,939.00 240,034.00 9.96
Y21: Enniscorthy Wexford New 2022 August 265,480.00 244,564.00 8.55
Y21: Enniscorthy Wexford Existing 2022 August 225,866.00 204,000.00 10.72
Y25: Gorey Wexford New 2022 August 298,846.00 296,110.00 0.92
Y25: Gorey Wexford Existing 2022 August 286,177.00 235,858.00 21.33
Y34: New Ross Wexford New 2022 August 182,312.00 273,434.00 -33.33
Y34: New Ross Wexford Existing 2022 August 203,439.00 182,018.00 11.77
Y35: Wexford Wexford New 2022 August 280,072.00 302,877.00 -7.53
Y35: Wexford Wexford Existing 2022 August 236,307.00 206,572.00 14.39

The maps below are the aggregate values of each Eircode Area rolled up to Constituency level. The variation displayed on the maps represent the difference between the average value of this aggregation and its 12 month lag. - Not an average of the variation in the scroll box above.

# Map
setwd("/Users/charten/OneDrive - Glenveagh Properties/Research & Development/1. Analysis/")
shp <- sf::read_sf("Constituency_Boundaries_Ungeneralised___OSi_National_Electoral_Boundaries___2017.shp")

shpEOA <- merge(shp,SUM_HPM08_1.EOA_Max, by.x = "CON_SEAT_", by.y="Seat_Tag")

shpEOA.GDA <- shpEOA %>%
  filter(grepl('Dublin|Laoghaire|Meath|Louth|Kildare|Wicklow', CON_SEAT_))

shpEOA %>%
  ggplot()+
  geom_sf(aes(fill = Diffpc),colour=alpha("white",0.5))+
  scale_fill_stepsn(n.breaks = 10,
                    colors=c("#F92306","#FFFFFF","#0C4F00"),
                    limits = c(-25,25),
                    name = "% change")+
  ggtitle('National: Percentage Change - CSO: HPM08')+
  labs(subtitle="12 month rolling average: Locations aggregated to constituency",caption="scales limited to absolute value of 25%")+
  theme_void()+
  theme(legend.title = element_text(size = 10),
        legend.text = element_text(size = 8))+
  theme(legend.position = "left")+
  theme(plot.title = element_text(size=16,face="bold"))+
  facet_wrap(~Dwelling.Status,ncol=1)+
  theme(strip.text.x = element_text(size = 10,colour = "navy"))

shpEOA.GDA %>%
  ggplot()+
  geom_sf(aes(fill = Diffpc),colour=alpha("white",0.5))+
  scale_fill_stepsn(n.breaks = 10,
                    colors=c("#F92306","#FFFFFF","#0C4F00"),
                    limits = c(-25,25),
                    name = "% change")+
  geom_sf_text(aes(label=Diffpc),color="black",alpha=0.9,size=2.25)+
  ggtitle('Greater Dublin Area - CSO: HPM08')+
  labs(subtitle="12 month rolling average: Locations aggregated to constituency",caption="scales limited to absolute value of 25%")+
  theme_void()+
  theme(legend.title = element_text(size = 10),
        legend.text = element_text(size = 8))+
  theme(legend.position = "left")+
  theme(plot.title = element_text(size=16,face="bold"))+
  facet_wrap(~Dwelling.Status,ncol=1)+
  theme(strip.text.x = element_text(size = 10,colour = "navy"))

Irish Economy

Lending Data

Included below are loan volumes and growth rates, interest rates and the proportion of mortgages which are variable rate loans in Ireland vs the Euro Area average.

Loans

Facet1 <- CBM01.OUT %>%
  ggplot(aes(x=Date,y=value,group=Type.of.Loan,colour=Type.of.Loan))+
  geom_line(size=1.5,alpha=0.5)+
  geom_text_repel(aes(label=value),max.overlaps = 8,size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(face="bold"))+
  ggtitle("Outstanding Amount of Loans and Securitisations")+
  labs(subtitle="CSO - CBM01: Loans, including Securitisations to Irish Residents")+
  ylab("euro million")+
  xlab(NULL)+
  geom_text(data=CBM01.OUT_Max,aes(label=lab,x=Date,y=value,group=Type.of.Loan),size=3,hjust="right",vjust="bottom",fontface="bold",colour="black",alpha=0.6)

CBM01.GRY_Max <- CBM01.GRY %>%
  group_by(Type.of.Loan) %>%
  slice(which.max(Date))
CBM01.GRY_Max$lab <- paste(CBM01.GRY_Max$Month,":",CBM01.GRY_Max$value)

CBM01.GRY <- CBM01.GRY %>%
  filter(Date >= "2004-01-01")

Facet2 <- CBM01.GRY %>%
  ggplot(aes(x=Date,y=value,group=Type.of.Loan,colour=Type.of.Loan))+
  geom_hline(yintercept = 0,alpha=0.5, linetype="dotted")+
  geom_line(size=1.25,alpha=0.5)+
  geom_text_repel(aes(label=value),max.overlaps = 10,size=2.5)+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(face="bold"))+
  ggtitle("Annual Growth Rate")+
  ylab("%")+
  xlab(NULL)+
  geom_text(data=CBM01.GRY_Max,aes(label=lab,x=Date,y=value,group=Type.of.Loan),size=3,hjust="right",vjust="bottom",fontface="bold",colour="black",alpha=0.6)+
  facet_wrap(~Type.of.Loan,nrow=2,labeller = labeller(Type.of.Loan = label_wrap_gen(width = 45)))

Facet1 + Facet2 + plot_layout(ncol=2, widths = c(2,1))

Rates: CSO vs ECB Loan Data

We have been working of the ECB statistics for interest rate statistics, comparing them with other eurozone countries. Part of the CSOs obligations is to report statistics to Eurostat, the interest rate statistics that the CSO publishes from their database can be seen below. I’ve included a dotted line for the ECB statistic which is:

“Bank interest rates - loans to households for house purchase with a floating rate and an IRF period of up to one year (new business)”

CBM02 %>%
  ggplot(aes(x=Date,y=value,group=Statistic,colour=Statistic))+
  geom_line(size=1.25,alpha=0.6)+
  scale_colour_manual(values = c("#0857F5","#F59A08"))+
  geom_text_repel(aes(label=value),max.overlaps = 6,size=2.5)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(face="bold"))+
  ggtitle("Retail Interest Rates: Households")+
  labs(subtitle="CSO - CBM02",caption="Dotted line represents ECB statistic for Household Loans for Ireland")+
  ylab("%")+
  xlab(NULL)+
  geom_text(data=CBM02_Max,aes(label=lab,x=Date,y=value,group=Statistic),size=3,hjust="right",vjust="bottom",fontface="bold",colour="black",alpha=0.8)+
  geom_line(data=IE.BIR_H,aes(x=obstime,y=obsvalue,group=ref_area),colour="black",alpha=0.6,linetype="dotted")+
  geom_text(data=IE.BIR_H_Max,aes(label=obsvalue,x=obstime,y=obsvalue,group=ref_area),colour="black",alpha=0.6,size=2.75,hjust="left")

Variable Rate Loans

SVL %>%
  ggplot(aes(x=obstime,y=obsvalue,group=area,colour=area))+
  geom_line(size=1.05,alpha=0.5)+
  scale_colour_manual(values=c("navy","darkgreen"))+
  geom_text_repel(aes(label=lab),max.overlaps = 5,alpha=0.35,size=3)+
  geom_text(data=SVL_Max,aes(label=lab),colour="black",alpha=0.9,size=3,hjust="right",fontface="bold")+
  theme_bw()+
  theme(legend.position="bottom",
        plot.title = element_text(face="bold"))+
  xlab(NULL)+
  ylab("percent (%)")+
  ggtitle("Share of Variable Rate Loans in Total Loans")

In Ireland, the share of variable rate loans has halved year to date.

This is some comfort given that rates are increasing, this limits the contribution of mortgage interest to inflation over the coming months.

SVL_20 <- SVL %>%
  filter(obstime>="2020-01-01")
dates_vline <- as.Date("2022-07-01")
dates_vline <- which(SVL_20$obstime %in% dates_vline)

SVL_20 %>%
  ggplot(aes(x=obstime,y=obsvalue,group=area,colour=area))+
  geom_line(size=1.05,alpha=0.5)+
  scale_colour_manual(values=c("navy","darkgreen"))+
  geom_text_repel(aes(label=lab),max.overlaps = 5,alpha=0.35,size=3)+
  geom_text(data=SVL_Max,aes(label=lab),colour="black",alpha=0.9,size=3,hjust="right",fontface="bold")+
  theme_bw()+
  theme(legend.position="bottom",
        plot.title = element_text(face="bold"))+
  xlab(NULL)+
  ylab("percent (%)")+
  ggtitle("Signs of Switching?")+
  labs(subtitle="Share of Variable Rate Loans in Total Loans",caption="Red line: first ECB rate hike of the cycle")+
  geom_vline(xintercept = as.numeric(SVL_20$obstime[dates_vline]),colour="darkred",linetype="dotted")

Construction Price Index

Year on year percentage change

colour <-ifelse(WPM28_B$value < 0,"#CC0000","#1b5545")

ggplot(WPM28_B, aes(x=Date, y=value, group=Type.of.Material))+
  geom_col(aes(group=Type.of.Material), alpha = 0.65, colour="#373634", fill = colour)+
  labs(title = "Percentage Change over 12 month in Wholesale Price Index")+
  xlab("Year-Month")+
  ylab("Percentage change")+
   # scale_x_date(date_labels="%b-%Y",date_breaks  ="3 month")+
  geom_text_repel(aes(label=value),data = WPM28_B, size = 3)+
  theme_bw()+
  theme(axis.text.x = element_text(angle=90))+
  theme(axis.text.x=element_text(size=10))+
  theme(legend.position="none")+
  theme(axis.text = element_text(size = rel(1)))+
  theme(plot.title=(element_text(vjust =2)))+
  theme(panel.border = element_rect(linetype = 1, fill = NA))+
  facet_wrap(~Type.of.Material, ncol = 3)

Government Finance

The below is useful to get an idea of the proportion of government debt and expenditure relative to income.

Debt to GDP

This statistic is a notoriously contentious one, it was heavily debated in the austerity years with the IMF arguing a level of 90% based on research by Reinhart and Rogoff, this was included in their historical analysis of financial crisis. - This Time is Different. Later, it was found that this level was insignificant but they reached the conclusion due to an excel spreadsheet error.

Rogoff at one stage was approached to be special advisor to the UK government, according to Howard Davies in his latest book The Chancellors: Steering the British Economy in Crisis Times. He had to refuse for family/health reasons, regardless his findings were influential into austerity.

I read the book, there are still many useful historical case studies in it.

####################################################### General Government Net Worth, Gross and Net Debt ESA 2010
# Load & Clean
GFQ12 <- cso_get_data("GFQ12")

GFQ12 <- GFQ12 %>%
  pivot_longer(!1:2,names_to="year_qtr")
GFQ12$Year_Q <- as.yearqtr(GFQ12$year_qtr)
GFQ12$Year <- year(GFQ12$Year_Q)

GFQ12_Max <- GFQ12 %>%
  slice(which.max(Year_Q))
GFQ12_Max$lab <- paste(GFQ12_Max$Year_Q,": ",GFQ12_Max$value,"%")

#Plot
GFQ12 %>%
  ggplot(aes(x=Year_Q,y=value))+
  geom_line(size=1.25,colour="darkgreen",alpha=0.6)+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(face="bold"))+
  ggtitle("Gross Government Debt to GDP")+
  ylab("%")+
  xlab(NULL)+
  labs(subtitle="GFQ12: Debt ESA2010 as a Percentage of the Annualised Gross Domestic Product")+
  geom_text_repel(data=GFQ12_Max,aes(label=lab),colour="darkgreen",fontface="bold")

Financing

# Plot
GFQ01.SUR %>%
  ggplot(aes(x=Year_Q,y=value,group=Item))+
  geom_hline(yintercept = 0,colour="darkred",alpha=0.5)+
  geom_line(aes(colour=Item,linetype=Item),size=1,alpha=0.7)+
  scale_colour_manual(values=c("#6C7272","#09716D"))+
  geom_line(aes(y=SMA.12,linetype=Item),colour="#027100",alpha=0.2)+
  theme_bw()+
  theme(legend.position = "bottom",
        plot.title = element_text(face="bold"),
        legend.key.size = unit(1, 'cm'),
        legend.key.height = unit(0.5, 'cm'), 
        legend.key.width = unit(0.5, 'cm'),
        legend.title = element_text(size=8),
        legend.text = element_text(size=8))+
  ggtitle("General Government Surplus & Deficit")+
  ylab("euro million")+
  xlab(NULL)+
  labs(caption="thin green line represents the 12 month moving average")

Revenue

GFQ01.REV %>%
  ggplot(aes(x=Year_Q,y=value,group=Item))+
  geom_line(aes(colour=Item),alpha=0.4)+
  geom_line(aes(y=SMA.12,colour=Item),alpha=0.8)+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(face="bold"))+
  ggtitle("General Government Transactions: Revenue")+
  ylab("euro million")+
  xlab(NULL)+
  labs(subtitle="12 month moving average")+
  facet_wrap(~Item,ncol=2,labeller = labeller(Item = label_wrap_gen(width = 55)))+
  geom_text(data=GFQ01.REV_Max,aes(x=Year_Q,y=10000,label=lab,colour=Item),hjust="right")

Expenditure

GFQ01.EXP %>%
  ggplot(aes(x=Year_Q,y=value,group=Item))+
  geom_line(aes(colour=Item),alpha=0.4)+
  geom_line(aes(y=SMA.12,colour=Item),alpha=0.8)+
  scale_colour_brewer(palette = "Set3")+scale_colour_hue(l = 45)+
  theme_bw()+
  theme(legend.position = "none",
        plot.title = element_text(face="bold"))+
  ggtitle("General Government Transactions: Expenditure")+
  ylab("euro million")+
  xlab(NULL)+
  labs(subtitle="12 month moving average")+
  facet_wrap(~Item,ncol=2,labeller = labeller(Item = label_wrap_gen(width = 55)))+
  geom_text(data=GFQ01.EXP_Max,aes(x=Year_Q,y=11000,label=lab,colour=Item),hjust="right")

Trade

We seen this in more detail last issue, I will keep the overall moving average going once new data is out (data released in the past week). I there is anything interesting in the more granular data I will include that as and when I see it.

# Step 1. Load Commodity Groups (local) and Value of Merchandise Trade from the CSO
CG <- readxl::read_xlsx(path="C:\\Users\\charten\\OneDrive - Glenveagh Properties\\Research & Development\\1. Analysis\\Commodity Groups.xlsx",sheet = 1)

TSM10 <- cso_get_data("TSM10")
TSM10 <- TSM10 %>%
  pivot_longer(!1:3,names_to="year_month")

TSM10$Year <-substr(TSM10$year_month,1,4)
TSM10$Month <- sub(".* ", "", TSM10$year_month)
TSM10$Month_NR <- as.integer(factor(TSM10$Month, levels=month.name))
TSM10$Date <- as.yearmon(paste(TSM10$Year, TSM10$Month_NR), "%Y %m")

# Step 2. Create Subsets
## 2.1 Total merchandise trade (0 - 9)
TSM10.1 <- TSM10 %>%
  filter(Commodity.group=="Total merchandise trade (0 - 9)")

### Total
TSM10.1.T <- TSM10.1 %>%
  group_by(Statistic,Commodity.group,year_month,Year,Date) %>%
  summarise(value = sum(value,na.rm = TRUE))
TSM10.1.T <- TSM10.1.T[order(TSM10.1.T$Statistic,TSM10.1.T$Date),]

TSM10.1.T$SMA.6 <- round(SMA(TSM10.1.T$value,n=6),digits=2)
TSM10.1.T$SMA.6[TSM10.1.T$Date=="Jan 2015" | TSM10.1.T$Date=="Feb 2015" | TSM10.1.T$Date=="Mar 2015"|TSM10.1.T$Date=="Apr 2015" | TSM10.1.T$Date=="May 2015"] <- NA

## 2.2 Exclude Total Merchandise Trade & Unclassified estimates
TSM10.2 <- TSM10 %>%
  filter(Commodity.group!="Total merchandise trade (0 - 9)") %>%
  filter(Commodity.group!="Unclassified estimates")

TSM10.2.T <- TSM10.2 %>%
  group_by(Statistic,Commodity.group,year_month,Year,Date) %>%
  summarise(value = sum(value,na.rm = TRUE))
TSM10.2.T <- TSM10.2.T[order(TSM10.2.T$Statistic,TSM10.2.T$Commodity.group,TSM10.2.T$Date),]

TSM10.2.T$SMA.6 <- round(SMA(TSM10.2.T$value,n=6),digits=2)
TSM10.2.T$SMA.6[TSM10.2.T$Date=="Jan 2015" | TSM10.2.T$Date=="Feb 2015" | TSM10.2.T$Date=="Mar 2015"|TSM10.2.T$Date=="Apr 2015" | TSM10.2.T$Date=="May 2015"] <- NA

TSM10.2.T <- merge(x=TSM10.2.T,y=CG,by.x="Commodity.group",by.y="Commodity.Group")
TSM10.2.T <- TSM10.2.T[order(TSM10.2.T$Statistic,TSM10.2.T$Commodity.group,TSM10.2.T$Date),]

## Subset by Group
TSM10.2.T.0 <- TSM10.2.T %>%
  filter(Group=="0")
TSM10.2.T.1 <- TSM10.2.T %>%
  filter(Group=="1")
TSM10.2.T.2 <- TSM10.2.T %>%
  filter(Group=="2")
TSM10.2.T.3 <- TSM10.2.T %>%
  filter(Group=="3")
TSM10.2.T.4 <- TSM10.2.T %>%
  filter(Group=="4")
TSM10.2.T.5 <- TSM10.2.T %>%
  filter(Group=="5")
TSM10.2.T.6 <- TSM10.2.T %>%
  filter(Group=="6")
TSM10.2.T.7 <- TSM10.2.T %>%
  filter(Group=="7")
TSM10.2.T.8 <- TSM10.2.T %>%
  filter(Group=="8")
TSM10.2.T.9 <- TSM10.2.T %>%
  filter(Group=="9")

# Step 3. Plot
options(scipen = 999)
TSM10.1.T_max <- TSM10.1.T %>%
  group_by(Statistic)%>%
  slice(which.max(Date))
TSM10.1.T_max$lab_SMA.6 <- paste(as.character(TSM10.1.T_max$Date), "-", comma(TSM10.1.T_max$SMA.6,digits=0))
TSM10.1.T_max$lab_value <- comma(TSM10.1.T_max$value,digits=0)

TSM10.1.T %>%
  ggplot(aes(x=Date,y=SMA.6,group=Statistic,colour=Statistic))+
  geom_text(data=TSM10.1.T_max,aes(label=lab_SMA.6),size=2.75,hjust=1.15,vjust=1,colour="black")+
  geom_text(data=TSM10.1.T_max,aes(y=value,label=lab_value),size=2.5,colour="#616161")+
  geom_line(aes(x=Date,y=value,group=Statistic,colour=Statistic),alpha=0.25)+
  geom_line()+
  theme_bw()+
  theme(legend.position = "bottom")+
  ggtitle("Value of Merchandise Trade")+
  labs(subtitle="CSO: TSM10 - Total merchandise",caption="latest month actual value printed in grey at the end of the monthly series")+
  ylab("6 month moving average - (Euro Thousand)")+
  scale_y_continuous(labels = scales::number_format(accuracy = 1,decimal.mark = ','))

Appendix

House Prices

HPM08_1.EOA.DUB <- HPM08_1.EOA %>%
  filter(Return.County == "Dublin")
HPM08_1.EOA.DUB_Max <- HPM08_1.EOA.DUB %>% 
  group_by(Eircode.Output,Dwelling.Status)%>%
  slice(which.max(Date))

HPM08_1.EOA.DUB %>%
  ggplot(aes(x=Date,y=value,group=Dwelling.Status,colour=Dwelling.Status))+
  geom_line(size=1.25,alpha=0.7)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ylab("euro")+xlab(NULL)+
  ggtitle("Market-based Household Purchases")+
  labs(subtitle="Mean Rolling 12 Month") +
  geom_text_repel(aes(label=value_short),alpha=0.6,size=2.75)+
  geom_text(data=HPM08_1.EOA.DUB_Max,aes(label=lab),colour="black",hjust="right",vjust=1,size=2.75,fontface="bold",alpha=0.6) +
  facet_wrap(~Eircode.Output,ncol=2)

options(scipen = 999)

HPM08_1.EOA.OTH <- HPM08_1.EOA %>%
  filter(Return.County != "Dublin")
HPM08_1.EOA.OTH_Max <- HPM08_1.EOA.OTH %>%
  group_by(Eircode.Output,Dwelling.Status)%>%
  slice(which.max(Date))

HPM08_1.EOA.OTH %>%
  ggplot(aes(x=Date,y=value,group=Dwelling.Status,colour=Dwelling.Status))+
  geom_line(size=1.25,alpha=0.7)+
  theme_bw()+
  theme(legend.position = "bottom")+
  ylab("euro")+xlab(NULL)+
  ggtitle("Market-based Household Purchases")+
  labs(subtitle="Mean Rolling 12 Month") +
  geom_text_repel(aes(label=value_short),alpha=0.6,size=2.75)+
  geom_text(data=HPM08_1.EOA.OTH_Max,aes(label=lab),colour="black",hjust="right",vjust=1,size=2.75,fontface="bold",alpha=0.6) +
  facet_wrap(~Eircode.Output,ncol=2)

Wholesale Price Index

Black line (100) indicates 2015 as baseline

WPM28_A_Max <- WPM28_A %>%
  group_by(Type.of.Material) %>%
  slice(which.max(Date))
WPM28_A_Max$lab <- paste(WPM28_A_Max$Month,":",WPM28_A_Max$value)

ggplot(WPM28_A, aes(x=Date, y=value, group=Type.of.Material, colour=Type.of.Material))+
  geom_line(aes(group=Type.of.Material),size = 1.05, linetype=1, alpha = 0.65)+geom_text_repel(aes(label=value),data = WPM28_A, size = 3)+
  labs(title = "Percentage Change over 12 month in Wholesale Price Index")+
  xlab("Year-Month")+
  ylab("2015 = 100")+
  geom_hline(aes(yintercept=100), 
             colour= "#404040",
             linetype = 1)+
   # scale_x_date(date_labels="%b-%Y",date_breaks  ="3 month")+
  theme_bw()+
  theme(axis.text.x = element_text(angle=90))+
  theme(axis.text.x=element_text(size=10))+
  theme(legend.position="none")+
  theme(axis.text = element_text(size = rel(1)))+
  theme(plot.title=(element_text(vjust =2)))+
  theme(panel.border = element_rect(linetype = 1, fill = NA))+
  geom_text_repel(data=WPM28_A_Max,aes(label=lab,y=160),colour="black",alpha=0.2,size=3)+
  facet_wrap(~Type.of.Material, ncol = 3,labeller = labeller(Type.of.Material = label_wrap_gen(width = 40)))