Fan Charts

Starting on 7 November 2019, the Bank of England‘s Inflation Report became the Monetary Policy Report. This quarterly publication communicates economic analysis and inflation projections that the Monetary Policy Committee uses to make its interest rate decisions.

Since 1996 the Bank of England (BoE) inflation forecast has been published as a probability distribution and presented in what is now known as ‘the fan chart’.

Screenshot 2019-11-17 at 00.12.43

The first fan charts that were published by the BoE can be found in its Inflation Report-February 1996. A digital copy of the printed report (which used to be sold for £3!) can be found here (see page 48 for the charts).

In this post, we will review the ideas behind the fan charts, as well as details on how they are constructed and interpreted. We will use the fanchart library to plot them with Python!


The BoE introduced the fan charts aiming to communicate a more accurate representation of their forecast for medium term inflation. In particular, the charts have two key objectives:

  • To convey the uncertainty in their forecasts. This is, to focus attention on the the forecast distribution, rather than only on small changes to the central projection.
  • To promote discussion of the risks to the economic outlook, and thus contribute to a wider debate about economic policy. Fan charts help to make it clear that monetary policy is about making decisions instead of knowing the exact rate of inflation in two years time.

Choice of the Two-Piece Normal

Historical observations showed that inflation outcomes were not symmetrically dispersed around a central value, with the values closer to the centre being more likely than those further away. This led to the choice of the  two-piece normal distribution, which can capture asymmetry through a skewness parameter, for the forecast model.

As we know, the probability density function (pdf) of the two-piece normal (see my previous post for more details) is defined as $$
s(x) := s\left(x; \mu,\sigma_1,\sigma_2\right) =
\dfrac{2}{\sigma_1+\sigma_2}f\left(\dfrac{x-\mu}{\sigma_1}\right), \qquad \mbox{if } x < \mu, \\
\dfrac{2}{\sigma_1+\sigma_2}f\left(\dfrac{x-\mu}{\sigma_2}\right), \qquad \mbox{if } x \geq \mu, \\
$$ where $f: \mathbb{R} \mapsto \mathbb{R}_{+}$ is the pdf of the standard normal distribution. However, the Bank of England uses the following re-parametrisation:$$
\sigma_1 = \dfrac{\sigma}{\sqrt{1-\gamma}} ; \qquad
\sigma_2 = \dfrac{\sigma}{\sqrt{1+\gamma}}, 
$$ where $\sigma >0$ and $\gamma \in (-1, 1)$. Thus, the pdf of the two-piece normal can be written as$$
s(x) := s\left(x; \mu,\sigma,\gamma\right) =
\dfrac{A}{\sqrt{2\pi}\sigma} \exp \left\{ -\dfrac{1-\gamma}{2\sigma^2} \left[(x-\mu)^2\right] \right\}, \qquad \mbox{if } x < \mu, \\
\dfrac{A}{\sqrt{2\pi}\sigma} \exp \left\{ -\dfrac{1+\gamma}{2\sigma^2} \left[(x-\mu)^2\right] \right\}, \qquad \mbox{if } x \geq \mu, \\
$$ where $A = \dfrac{2}{\frac{1}{\sqrt{1-\gamma}}+\frac{1}{\sqrt{1+\gamma}}}$.

So, in order to derive the forecast distribution for each quarter ahed, three parameters need to be estimated:

  • $\mu$ : a measure of the central tendency for inflation
  • $\sigma$ : a view on the degree of uncertainty
  • $\gamma$ : a view on the balance of the risks, to get a measure of the skew.

Once these parameters are set, the two-piece normal is completely defined. BoE publishes these parameters as part of its quarterly report as:

  • Mode
  • Uncertainty
  • Skewness

You can download all the data related to the fan charts by using the “Download the chart slides and data (ZIP)” option in the Monetary Policy Report website.

Options from the Monetary Policy Report November 2019.

Python Implementation

We will use the fanchart library to reproduce the fan charts. This library contains a copy of the BoE data and parameters (already in the format required by the functions) as of November 2019. 

from fanchart.plot import *

Quarter Fan Chart

First, we plot a variant of the fan charts which uses only the projection associated to a single quarter.

For this purpose, we will use the function fan_single which provides functionality for two kinds of charts, namely the probability density function (pdf) and the cumulative distribution function (cdf).

In order to use the fan_single function, we need to provide:

  • The parameters $\mu, \sigma, \gamma$ (loc, sigma, and gamma) for the two-piece distribution corresponding to the quarterly projection.
  • A set of probabilities which define the bands of the chart
  • The kind of plot, namely ‘pdf’ or ‘cdf ‘

For illustration purposes, we use the parameters corresponding to the projection for 2020-10-01. You can find parameters corresponding to other dates here. Remember that the parameters are called mode, uncertainty, and skewness by the BoE. 

prob = [0.05, 0.20, 0.35, 0.65,0.80,  0.95]
fan_single(loc=1.51, sigma=1.34, gamma=0.0, p=prob, kind='pdf');
fan_single(loc=1.51, sigma=1.34, gamma=0.0, p=prob, kind='cdf');
prob = np.arange(0.10, 1, 0.05)
fan_single(loc=1.51, sigma=1.34, gamma=0.0, p=prob, kind='pdf');
fan_single(loc=1.51, sigma=1.34, gamma=0.0, p=prob, kind='cdf');

Projection Fan Chart

Now, we will plot the fan chart that illustrates the entire projection ahead. For this we will use the function fan which requires:

  • A data frame containing the parameters $\mu, \sigma, \gamma$ (loc, sigma, and gamma) for every quarter in the projection. You can load the parameters corresponding to the Nov-2019 Report from the fanchart library.
  • A data frame with the observed historical inflation. This serves to produce the solid line before the fan part. You can load the historical data corresponding to the Nov-2019 Report from the fanchart library.
  • A set of probabilities which define the bands of the chart.
history = load_boe_history()
parameters = load_boe_parameters()
probs = [0.05, 0.20, 0.35, 0.65,0.80,  0.95]
fan(data=parameters, p=probs, historic=history[history.Date >='2015'].iloc[::3,]);
CPI inflation projection based on constant nominal interest rates at 0.75% (wide bands).
probs = np.arange(0.10, 1, 0.05)
fan(data=parameters, p=probs, historic=history[history.Date >= '2015'].iloc[::3,]);
CPI inflation projection based on constant nominal interest rates at 0.75% (narrow bands)

Note that at any particular point in the forecast period (which has a grey background) the shading of the bands gets lighter as the probability of inflation lying further away from the central projection decreases.

Besides, as predictions become increasingly uncertain over time, these forecast ranges spread out, creating the distinctive”fan” or wedge shapes which originated the “fan chart” term.

Surface Fan Chart

As we mentioned, uncertainty increases over time so we can think of looking at the whole density function over time. This is done in the following three-dimensional chart, which includes the probability density on the z-axis.

The shading of this chart emphasises that there is much less certainty about the outcome two/three years ahead than about the outcome one quarter ahead.

We can eve even create an animation which allows us to look at the forecast in detail.

Further Reading


Quant Girl

I write about Mathematics, Statistics, Finance, Programming, and the relationships among them. I enjoy learning, listening to music and podcasts, practicing yoga, reading magazines, and watching documentaries.

5 thoughts on “Fan Charts

  1. Hello Dialid thank you for this very interesting analyses! Could you please provide some application areas for the mentioned two-piece (normal) family of distributions ? For example, whether they would be reasonably applied in analyzing asset returns and simulating portfolio returns under different market regimes. Also, could you provide a python code overview behind the single/projection fan charts functions ? Would be helpful to understand how these are generated. Thanks!



    1. Hi Nikola,

      Many thanks for your suggestions. I am working on some more entries with applications to econometrics 🙂 but in the meanwhile I suggest to take a look at the paper Bayesian Regression Analysis with Scale Mixtures of Normals by Carmen Fernández and Mark F. J. Steel
      in Econometric Theory. Regarding the code, take a look at the Demo of my package ‘fanchart’ which is open source 🙂

      Best regards!

      1. Hello Dialid,

        Thank you for your reply and the link provided, I will look into it! Apologies for a delayed answer was a rather busy few weeks on my end. Also thanks for the paper reference, I do recall the Fernandez/Steel parameterizations of different distributions (in a location-scale-shape manner) when I was exploring GARCH modelling framework a while back (mostly in R!), will go through it! Have a nice weekend and stay safe!



  2. Hi Dialid!
    Thanks for sharing your awesome work.

    Could you give me a tip How to calculate(predict) the parameters(Mode,Uncertainty,Skewness)?

    1. Hi Honeybat,
      Many thanks for your comment 🙂 that is a very good question indeed. Unsurprisingly, the BoE does not disclose the method they use to estimate these parameters. However, my guess would be Maximum Likelihood estimation on historical data.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.