Dashboard update: Fed minutes and recent data advance interest rate hike expectations

Monitor more than 80 economic indicators with the macro and markets dashboard:

United States Macroeconomic and Markets Dashboard: Updated May 21, 2016

Dashboard update summary:

New data continue to strengthen the U.S. macroeconomic picture. Minutes from the most recent meeting of the Federal Reserve Open Markets Committee (FOMC) signal that the U.S. central bank may increase its key federal funds interest rate target by 25 basis points in June. Markets have responded by increasingly pricing higher interest rate expectations into the bond and foreign exchange markets.

Industrial production stronger than expected

The Federal Reserve publishes an index of U.S. industrial production that goes back to 1919. The monthly index data for April was released on Tuesday, and showed greater-than-expected industrial sector output. This was a result largely of a month-over-month spike in production in the utilities sector, which had previously been hard hit by declines in both demand for utilities and commodity prices (see below). The index had declined each month so far during the year, and rebounded by seven tenths of a percent from March to April.


Jobless claims drop to less alarming level

Data from the week of May 7 on the number of new claims of joblessness hit a recent high, drawing some attention. New data for the week of May 14 were better, with 278,000 new jobless claims during that week.

Inflation low and steady but pointed higher

April data on inflation, as measured by the consumer price index, was released on Tuesday. Annualized inflation for all items was 1.1 percent in April, while the Core CPI (the CPI excluding food & beverage, and energy) grew by 2.1 percent. Healthcare continues to grow at the fastest rate of any major item category in the basket. Energy and transportation costs are still below their previous year level, but less so than in March (see below).


FOMC minutes suggest June hike more likely

On Wednesday, the Fed released minutes from the FOMC meeting at the end of April. The minutes indicate that if new labor market data shows continued strengthening, and inflation continues toward two percent, then the committee will likely raise the federal funds target rate in June.


An increase in the federal funds rate causes other short-term (and to a lesser extent long-term) interest rates to rise. In essence, the fed funds target rate should act as a floor on the cost of risk-free borrowing of U.S. dollars.

Reaction of markets

Expectations about future interest rates play a major role in finance. Short term interest rate increases, like those from fed funds rate increases, generate broad effects, including on long term interest rates, the demand for money in the real economy, the propensity to save and invest, and bond and foreign exchange markets. Markets react today to changes today in expectations about the future. This happened following the release of the FOMC minutes; U.S. treasury bond prices fell immediately. The yield on ten- and two-year treasury bonds jumped, closing the week at 1.85% and 0.89% respectively.


See more indicators, as well as foreign exchange rates, in the dashboard:


Dashboard update: consumer-side improvement and other reasons not to worry

Dashboard PDF file:

Macro and Markets Dashboard: United States (May 14, 2016)
Dashboard Update Summary

Surprisingly good April retail sales growth and preliminary signs of strong May consumer sentiment suggest a continued strengthening of consumer spending. Higher wages and low but rising inflation expectations boost individuals’ willingness to make discretionary purchases. Recent quarterly earnings data suggest that these purchases are increasingly taking place through Amazon and online retailers rather than department stores. Equities were lower over the past five trading days, partially as a result of poor earnings data from the latter. Jobless claims increased in the first week of May, but remain within a reasonable range. The yield curve flattened during the week as the spread between ten-year treasury bonds and three-month t-notes fell to its lowest level since February. The dollar appreciated against most major currencies.

Consumer sentiment and spending rising

Retail sales excluding food increased year over year by 2.7 percent in April. This is the second largest increase since January 2015 (the largest in the past 15 months was in February). In April, Retails sales overall were up three percent over the previous year and up a surprising 1.3 percent over the previous month. Many online retailers, including Amazon, had their strongest-ever quarter in Q1. Meanwhile, this week’s earnings releases from Nordstrom, Kohl’s, and Macy’s shows a continuation in consumers’ pivot away from U.S. department stores. U.S. equities closed lower on the week, with the S&P down half a percent, the Nasdaq down 0.4 percent, and the Dow down 1.2 percent.


Prices remain low with some hills on the horizon

The uptick in retail sales can be attributed in part to higher wages for consumers, as evidenced in recent labor market data. Additionally, fuel prices remain low, yet there is some sign that movement is towards increasing price levels, which incentivizes spending today, especially given a very low return on savings. The April producer price index (PPI), which measures how prices of the inputs to production change, was released this week. The PPI for all commodities (intermediate demand) increased to a -4 percent year over year change, from -4.8. Energy prices fell less dramatically in the twelve month period ending in April. Oil prices climbed 3.5 percent during the past week, but remain below $50 a barrel, at $46.21.


Jobless claims rise

The number of new jobless claims during the week of May 7 was higher at 294,000. While the highest level of new jobless claims since February of 2015 may seem startling, the level is still low and the increasing bargaining power of labor makes voluntarily leaving a job less scary.


Yield curve flattens as foreign investors avoid negative yields

Another potentially startling indicator is the flattening of treasury yield curves, but again, there is an explanation to assuage concern. The yield spread between ten-year treasuries their three-month t-bill counterpart fell to 1.43 on Friday, from 1.6 a week earlier, as ten-year yields fell and three-month yields rose. Likewise, the spread between ten- and two-year treasuries fell. While this indicator is a potential bad omen, we must remember that foreign inflows to treasury auctions have been increased by negative interest rates in many EU countries and Japan. For example, as ten-year Japanese Government Bond yields remain negative, Japanese investors increasingly shift portfolios to the U.S. government equivalent.


Dollar appreciates against trading partners

Lastly, the U.S. dollar was stronger against most major currencies during the past week. The dollar appreciated by 1.4 percent against the Yen, by 3.5 percent against the Rand, by 0.85 percent against the Euro, and by half a percent against the British Pound.

I’ve redesigned the exchange rates table to be quicker to read, and include it below.

Rates above as of May 13, 2016



Dashboard update: Jobs data and new uncertainty

Dashboard PDF file:

Macro and Markets Dashboard: United States (May 7, 2016 — PDF)
Dashboard Update Summary:

Jobs data for April showed payrolls continue to grow, but at a slower rate. Wage data was strong, however, the labor force participation rate gave up much of its recent improvement. Uncertainty surrounding markets and economic policy seems to have increased in the recent week, and fewer economists now predict a Fed rate hike in June. U.S. equity markets were down for the second consecutive week, while corporate bond yields rose and treasury yields fell. Recent data showed improvement in the trade balance from the weaker dollar, however, the recent depreciation trend has also become less certain.

Jobs Report showed slower jobs growth but wage improvement

The U.S. added 160,000 jobs in April, compared with 208,000 in March and 233,000 in February (both previous months were also revised downward). By sector, much of the growth came from the services side, on an annualized basis. Construction jobs, which make up less than five percent of nonfarm payrolls, were up 4.1 percent, while mining and logging jobs continued their decline and are now down more than fifteen percent over the past year (this is the smallest industry sector shown in the figure below, and represents only 0.4 percent of nonfarm payrolls). Weekly data on new jobless claims, as of April 30, showed still very low, but slightly increased, levels.


The latest jobs report shows continued improvement in both nominal and real wages in practically all sectors. Nominal wages increased most rapidly over the past year in financial services, information services, and leisure and hospitality. On average, wages from the goods sector are higher, largely as a result of low-wage service-sector jobs in leisure and hospitality.


Equity and Bond market conditions deteriorated

Equity markets were down for the second straight week. The S&P 500 was down 0.4 percent, the Nasdaq composite index was down 0.8 percent, and the Dow Jones industrial average was 0.2 percent lower. Volatility was higher during the week, and the VIX closed Friday at 14.7. The Shiller index of price to earnings ratios was up to 26.02 percent in April from 25.54 in March. Corporate bond yields ticked up during the week. The Merrill Lynch index of junk bond yields was up to 7.56 percent. Ten year treasury yields fell to 1.79 percent.

Economic policy uncertainty improved in April but may revert

Economic policy uncertainty, as measured by Baker, Bloom, and Davis, fell sharply in April, as there was little speculation of Fed action at the April meeting. However, I expect this index to bounce back; uncertainty will increase as the Fed June meeting and Brexit grow closer.


Oil was down on the week, while April food prices increased

Oil prices closed lower on the week. The U.S. measure of crude oil prices, West Texas Intermediate crude front-month contracts, fell 2.7 percent during the week, to $44.66 a barrel. World food prices from the Food and Agriculture Organization (which I half-jokingly also use as a proxy of political instability) ticked up slightly in April, but remain low.

A weaker dollar improved the trade balance in March

The Fed’s trade-weighted dollar broad index against major currencies fell last Friday (April 29–past week data is released on Mondays) to its lowest level since May 2015. The year-to-date rapid depreciation of the dollar has cut import quantities, as further evidenced in the March data on trade. The trade deficit, which remains roughly 2.2 percent of GDP, improved to -40.4B in March. However, more recent foreign exchange data shows uncertainty about recent depreciation trends. The dollar was stronger against nearly all major trading partners during the past week, notably 1.2 percent against the British pound, 2.76 percent against the Canadian dollar, 3.16 percent against the Australian dollar, 4.5 percent against the Turkish lira, 3,86 percent against the Mexican peso, and 4.3 percent against the South African rand.


Machine Reading IMF Data: Data Retrieval with Python 

Updated November 16, 2016


The International Monetary Fund (IMF) Statistics Department (STA) allows API access to their economic time series. Well-known datasets such as International Financial Statistics (IFS) can be machine read through the API. This example will use Python to retrieve Direction of Trade Statistics (DOTS) data from STA’s JSON RESTful Web Service so that we can determine the United States’ share of world exports over the past 50 years.

The IMF knowledge base provides more information on the three avaiable API formats and IMF data services. For more information on the work of STA, see their PDF annual report (PDF), STA at a glance 2015.

Gathering series and dimension information

First, we will need to import the requests and pandas libraries. These will allow us to read json data, open urls, and request information from the web.


In [1]:
# Import libraries
import requests
import pandas as pd

Since we are using the JSON RESTful API, we start by using the ‘Dataflow’ endpoint URL to look at what series are available and find the series id of interest. The full output is long, so I’ve removed the data unrelated to this example. The IMF has many more series than what is shown below.

Find Series Name

In [2]:
# Find the series id and text name.
url = 'http://dataservices.imf.org/REST/SDMX_JSON.svc/Dataflow/'
seriesids = requests.get(url).json()
df = pd.DataFrame(seriesids['Structure']['Dataflows']['Dataflow'])
for x in range(6, 13):
     items = (str(df['@id'][x]), str(df['Name'][x]['#text']))
     print ': '.join(items)
DOT: Direction of Trade Statistics (DOTS)
FSIREM: Financial Soundness Indicators (FSI), Reporting Entities - Multidimensional
CDIS: Coordinated Direct Investment Survey (CDIS)
GFS01M: Government Finance Statistics (GFS 2001) - Multidimensional
GFS01: Government Finance Statistics (GFS 2001)
BOP: Balance of Payments (BOP)
BOPAGG: Balance of Payments (BOP), World and Regional Aggregates

We found above that the id for Direction of Trade Statistics is DOT. We can use this id to read notes about the series. We will next need to identify the dimensions of the data. For example, direction of trade data is based on a home country a flow and measure and a counterpart country. The data also has multiple frequencies and units of measurement. All of this information will be needed to later make our data request.

Find Series Details and Description

In [3]:
# Annotations for the series
url = "http://dataservices.imf.org/REST/SDMX_JSON.svc/DataStructure/DOT"
dotstruct = requests.get(url).json()
df = pd.DataFrame(dotstruct['Structure']['KeyFamilies']\
for x in range(0, 7): 
     items = (str(df['Annotation'][x]['AnnotationTitle']), \
     print ': '.join(items)
Latest Update Date: 04/26/2016
Name: Direction of Trade Statistics (DOTS)
Temporal Coverage: Monthly and quarterly data are available starting 1960. Annual data are available starting 1947.
Geographic Coverage: DOTS covers 184 countries, the world, and major areas.
Methodology: Guide to Direction of Trade Statistics, 1993. See Documents tab.
Definition: The <B>Direction of Trade Statistics (DOTS)</B> presents current figures on the value of merchandise exports and imports disaggregated according to a country's primary trading partners. Area and world aggregates are included in the display of trade flows between major areas of the world. Reported data is supplemented by estimates whenever such data is not available or current. Imports are reported on a cost, insurance and freight (CIF) basis and exports are reported on a free on board (FOB) basis, with the exception of a few countries for which imports are also available FOB. Time series data includes estimates derived from reports of partner countries for non-reporting and slow-reporting countries.
Code: DOT

Find Series Dimensions

In [4]:
# Look at structure of DOTS data to find the dimensions for our data request
url = "http://dataservices.imf.org/REST/SDMX_JSON.svc/DataStructure/DOT"
dotstruct = requests.get(url).json()
df = pd.DataFrame(dotstruct['Structure']['KeyFamilies']['KeyFamily']\
for x in range(0, 4): 
     items = ("Dimension", str(x+1), str(df['@codelist'][x]))
     print ': '.join(items)
Dimension: 1: CL_FREQ
Dimension: 2: CL_AREA_DOT
Dimension: 3: CL_INDICATOR_DOT

We can now copy the code for each dimension into the CodeList Method to get the list of possible values. For example, we will need to identify the value of the second dimension, CL_AREA_DOT, for the United States. Below, we show that the code is US. I’ve manually placed the index number for the U.S. and World codes (again to save space), however, you can replace [200, 248] with [0, 248] to get the full list of country/area codes.

Find Country Codes

In [5]:
# Obtain country codes
url = "http://dataservices.imf.org/REST/SDMX_JSON.svc/CodeList/CL_AREA_DOT"
country = requests.get(url).json()
df = pd.DataFrame(country['Structure']['CodeLists']['CodeList']['Code'])
for x in [200, 248]: 
     items = (str(df['@value'][x]), str(df['Description'][x]['#text']))
     print ': '.join(items)
US: United States
W00: All Countries, excluding the IO

The series ID is DOT and the country codes (we will use this with the exporting country, CL_AREA_DOT, and the counterpart, CL_COUNTERPART_AREA_DOT) of interest are W00 for world and US for the US. We see below that the indicator of interest is TXG_FOB_USD, Goods, Value of Exports, Free on board (FOB), US Dollars.

Find Column IDs

In [6]:
# Obtain series info and ids
url = "http://dataservices.imf.org/REST/SDMX_JSON.svc/CodeList/CL_INDICATOR_DOT"
series = requests.get(url).json()
df = pd.DataFrame(series['Structure']['CodeLists']['CodeList']['Code'])
for x in range(0, 4): 
     items = (str(df['@value'][x]), str(df['Description'][x]['#text']))
     print ': '.join(items)
TXG_FOB_USD: Goods, Value of Exports, Free on board (FOB), US Dollars
TMG_CIF_USD: Goods, Value of Imports, Cost, Insurance, Freight (CIF), US Dollars
TMG_FOB_USD: Goods, Value of Imports, Free on board (FOB), US Dollars
All Indicators: All Indicators

We repeat the above steps for each dimension and record which series values are of interest to us.

Retrieving Data

The guide to STA’s API shows how we can combine information from the previous steps to call and retrieve data. For direction of trade statistics, we see that the dimensions are as follows:

  • Dimension 1: CL_FREQ (the frequency of the data–we want to use monthly data) – M
  • Dimension 2: CL_AREA_DOT (the primary country) – US
  • Dimension 3: CL_INDICATOR_DOT (the measure–we want to look at exports free of board) – TXG_FOB_USD
  • Dimension 4: CL_COUNTERPART_AREA_DOT (the counterpart country) – W00

The JSON RESTful API method for requesting the data is the CompactData Method. The format for putting together dimension and time period information is shown on the Web Service knowledge base as:

http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/{database ID}/ {item1 from dimension1}+{item2 from dimension1}{item N from dimension1}.{item1 from dimension2} +{item2 from dimension2}+{item M from dimension2}? startPeriod={start date}&endPeriod={end date}

Putting all of this information together, the URL to retrieve a JSON dictionary for 1966-2016 US exports to the world data is:


The python code which gets the data and saves it as a dictionary is as follows:

Request data from IMF API

In [7]:
url = 'http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/DOT/M.US.TXG_FOB_USD.W00.?startPeriod=1981&endPeriod=2016'
data = requests.get(url).json()
usexp = pd.DataFrame(data['CompactData']['DataSet']['Series']['Obs'])
usexp.columns = ['status', 'usexports','date'];
date usexports
415 2015-08 123065777734
416 2015-09 125394024247
417 2015-10 130599515853
418 2015-11 120731632371
419 2015-12 119907169367

We can repeat the above code with a different URL to obtain data on total world exports and the exports of other countries which we may want to compare with the United States. We combine the request for several series into one URL, by adding ‘+code2+code3’. For example, ‘US+JP+CN.TXG..’

Example of request with multiple columns

In [8]:
ourl = 'http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/DOT/M.US+CN+JP+W00.TXG_FOB_USD.W00.?startPeriod=1972&endPeriod=2016'
odata = requests.get(ourl).json();

Cleaning the dataframe and naming rows

In [9]:
wexp = pd.DataFrame(odata['CompactData']['DataSet']['Series'][0]['Obs'])
wexp.columns = ['status','wexports','date']
del wexp['date']
del wexp['status']
chexp = pd.DataFrame(odata['CompactData']['DataSet']['Series'][1]['Obs'])
chexp.columns = ['status', 'chexports','date']
del chexp['date']
del chexp['status']
jpexp = pd.DataFrame(odata['CompactData']['DataSet']['Series'][2]['Obs'])
jpexp.columns = ['jpexports','date']
del jpexp['date']
usexp = pd.DataFrame(odata['CompactData']['DataSet']['Series'][3]['Obs'])
usexp.columns = ['status', 'usexports','date']
del usexp['status'];

Now we combine the two series into one dataframe and tell our script to read the export value columns as numbers.

Read as numeric

In [10]:
combined = pd.concat([usexp, wexp, chexp, jpexp], axis=1)
combined = combined.set_index(pd.DatetimeIndex(combined['date']))
usexports = pd.to_numeric(combined.usexports)
wexports = pd.to_numeric(combined.wexports)
cexports = pd.to_numeric(combined.chexports)
jexports = pd.to_numeric(combined.jpexports)

Finally, we can calculate the U.S. percentage share of world exports. We simply divide the us exports by the world exports and multiply by 100. If using the data for economic research, we would likely take the log forms and apply some filters.


Calculate share of world exports for each country

In [11]:
combined['usshare'] = usexports / wexports * 100
combined['chinashare'] = cexports / wexports * 100
combined['japanshare'] = jexports / wexports * 100


date usshare chinashare japanshare
2015-08 9.460 15.121 3.668
2015-09 8.830 14.455 3.754
2015-10 9.330 13.737 3.892
2015-11 9.018 14.663 3.645
2015-12 8.776 16.362 3.804

Graphing the data

Let’s use matplotlib to view the result of our work.

Graph of US share of world exports

In [12]:
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
txt = '''Source: International Monetary Fund.'''

# Plot US share of world exports
combined.usshare.plot(grid=True, figsize=(9, 5), color="blue", linewidth=2,)
plt.ylabel('percentage of world exports')
plt.title('U.S. Share of World Exports');

The graph shows a decrease in the U.S. share of exports from nearly 20 percent in 1966 to roughly 9 percent in 2015. We can also easily examine how changes in the U.S. share of exports compare with changes in the share of Japan and China.

Graph of moving average of US, China, and Japan shares of world exports

In [13]:
# Calculate moving average for each share, to reduce noise
combined['ussharema'] = combined['usshare'].rolling(12,12).mean()
combined['chsharema'] = combined['chinashare'].rolling(12,12).mean()
combined['jpsharema'] = combined['japanshare'].rolling(12,12).mean()

combshares = combined[['ussharema', 'chsharema', 'jpsharema']]
shares = list(combshares);
# Plot various shares of world exports
combined[shares][120:].plot(grid=True, figsize=(9, 5), linewidth=2)
plt.ylabel('percentage of world exports')
plt.title('Share of World Exports', );
download (1)

Export dataset to .csv

Let’s save the dataset in a portable format that can be read by any statistical software. My preference is to create a .csv file, which I will use for my U.S. Macroeconomic and Markets Dashboard.

Create csv file

In [14]: