CREA API Documentation

Overview

CREA API

Welcome to the documentation for our Economic Indicators API. This API has been meticulously developed by our team of economic specialists to grant applied economics researchers immediate access to a wide spectrum of essential economic indicators. The API gives access to crucial economic data such as the Business Cycle Index (BCI) and cantonal GDP growth rates for Switzerland, fostering a deeper understanding of regional economic trends and performance. By seamlessly integrating into both machine-based systems and human researcher applications, our API facilitates effortless data extraction, enabling the construction of financial models, the performance of economic analyses, and the generation of data visualizations, all within a dynamic and continuously updated platform for economic data exploration.

What is an API?

An API (Application Programming Interface) is like a server in a restaurant that allows customers (in this case, researchers/developers/journalists) to interact with the kitchen (the server or application) to order and receive the desired dishes (data in this case). In this analogy, the API serves as the bridge between the customer and the kitchen, ensuring seamless communication and exchange of information.

Similarly, in the world of software development, an API defines a set of rules and protocols that enable different software systems to interact with each other. It provides a standardized way for developers to request and receive data or perform certain operations from a remote server or application.

API Waiter
Source: apipheny.io

Endpoints

Endpoint: CREA Business Cycle Index (BCI)

GET /api/v1/indicators/bci/

Description: Retrieve the Business Cycle Index of Switzerland and its cantons.

Output:

  • dates: Dates corresponding to the index values.
  • bci: Business Cycle Index values.
  • bci_trend: Trend component of the Business Cycle Index.
  • recession: Boolean indicator (1 for recession period, 0 for non-recession).

Example:

crea-web.unil.ch/api/v1/indicators/bci/geneva_bci

Endpoint: Cantonal GDP Growth Rates

GET /api/v1/indicators/cantonal_gdp/

Description: Retrieve the quarterly or yearly growth rate of the GDP for all cantons.

Expected Output:

  • dates: Dates corresponding to the growth rate values.
  • gdp_growth: Growth rate of the cantonal GDP.
  • recession: Boolean indicator (1 for recession period, 0 for non-recession).

Example:

crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_gdp_growth
crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_year_gdp_growth

Datasets

A list of all our datasets is available here.

Data Formats

The API supports two data formats: JSON and CSV. The format is determined by the endpoint path:

  • JSON: crea-web.unil.ch/api/v1/indicators/bci/switzerland_bci
  • CSV: crea-web.unil.ch/api/v1/indicators/bci/switzerland_bci.csv

Sample Code and Usage Examples

Python

For Python users, the requests library can be used to interact with your API.

Getting BCI data:

import requests
import pandas as pd
response = requests.get('https://crea-web.unil.ch/api/v1/indicators/bci/geneva_bci')
data = response.json()
df = pd.DataFrame(data)
print(df)

Getting cantonal GDP growth data:

response = requests.get('https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_year_gdp_growth')
data = response.json()
df = pd.DataFrame(data)
print(df)

Usage Example: Cantonal Economic Resilience during COVID-19

CREA BCI is an indicator that tracks economic activity. An increasing BCI is often associated with a growing economy, while a decreasing BCI can suggest economic contraction or even recession. In this simple example, we will investigate which canton was least (and most) affected by COVID-19 by:

  1. Plotting the data during the COVID-19 period:Visual inspection
  2. Computing the drop in CREA BCI for each canton: The canton with the lowest drop is the most resilient.
  3. Computing the overall change in CREA BCI: A single drop might not be representative, as the CREA BCI could have also recovered during the period. Thus, we will also consider the overall change in CREA by computing the sum of all changes.
  4. Computing time spent below a certain threshold: We will also consider the time spent under a threshold. This represents the recovery period. A canton might not have a high drop and might have a small change in CREA BCI but might take a long time to recover. The threshold chosen is the last value just before the COVID-19 period.

Finally, a resilience score is computed as follows:

  1. Rank each canton based on each of the three measurements. The canton with the smallest drop gets 1 point, the canton with the second smallest drop gets 2 points, and so on. Do the same for the overall change and the time spent below the threshold.
  2. Add up the points from each of the three measurements for each canton. This will give each canton a total score.
  3. The canton with the lowest total score could be considered the least affected, and the canton with the highest total score could be considered the most affected.

You can see the results of this demonstration here:

Open In Colab

    import requests
    import pandas as pd
    import matplotlib.pyplot as plt
    
    # List of cantons with their corresponding API endpoints
    cantons = {
        'Geneva': 'https://crea-web.unil.ch/api/v1/indicators/bci/geneva_bci',
        'Valais': 'https://crea-web.unil.ch/api/v1/indicators/bci/valais_bci',
        'Fribourg': 'https://crea-web.unil.ch/api/v1/indicators/bci/fribourg_bci',
        'Neuchatel': 'https://crea-web.unil.ch/api/v1/indicators/bci/neuchatel_bci',
        'Jura': 'https://crea-web.unil.ch/api/v1/indicators/bci/jura_bci',
        'Vaud': 'https://crea-web.unil.ch/api/v1/indicators/bci/vaud_bci',
        'Switzerland': 'https://crea-web.unil.ch/api/v1/indicators/bci/switzerland_bci',
    }
    
    # Initialize an empty dataframe to store data
    df = pd.DataFrame()
    
    # Fetch data for each canton
    for canton, url in cantons.items():
        response = requests.get(url)
        data = response.json()
        temp_df = pd.DataFrame(data)
        temp_df['date'] = pd.to_datetime(temp_df['dates'])
        temp_df.set_index('date', inplace=True)
        temp_df[f'{canton}_bci'] = temp_df['bci'].astype(float)
        temp_df[f'{canton}_bci_trend'] = temp_df['bci_trend'].astype(float)
        df = pd.concat([df, temp_df[[f'{canton}_bci', f'{canton}_bci_trend']]], axis=1)
    
    # Specify the covid period
    start_date = pd.to_datetime('2020-01-31')
    end_date = pd.to_datetime('2021-12-31')
    covid_period = df.loc[start_date:end_date]
    
    # Compute resilience measurements excluding '_bci_trend' and 'Switzerland'
    covid_period_filtered = covid_period[[col for col in covid_period.columns if ('_bci_trend' not in col) and ('Switzerland' not in col)]]
    
    max_drop = covid_period_filtered.min() - covid_period_filtered.loc[start_date]
    print("Maximum drop in CREA BCI during the COVID-19 period for each canton:")
    print(max_drop.sort_values())
    
    overall_change = covid_period_filtered.diff().sum()
    print("\nOverall change in CREA BCI during the COVID-19 period for each canton:")
    print(overall_change.sort_values(ascending=False))
    
    below_threshold = (covid_period_filtered < covid_period_filtered.loc[start_date]).sum()
    print("\nNumber of instances below the pre-COVID-19 period CREA BCI for each canton:")
    print(below_threshold.sort_values())
    
    resilience_score = pd.DataFrame({'max_drop': max_drop, 'overall_change': overall_change, 'below_threshold': below_threshold})
    
    # invert ranking for 'max_drop' and 'below_threshold'
    resilience_score['max_drop_rank'] = resilience_score['max_drop'].abs().rank(ascending=True)
    resilience_score['below_threshold_rank'] = resilience_score['below_threshold'].rank(ascending=True)
    resilience_score['overall_change_rank'] = resilience_score['overall_change'].rank(ascending=False)
    
    # sum up ranks to get the final score
    resilience_score['resilience_score'] = resilience_score[['max_drop_rank', 'below_threshold_rank', 'overall_change_rank']].sum(axis=1)
    most_resilient = resilience_score['resilience_score'].idxmin().split('_')[0]
    
    # Sort the dataframe by resilience score
    resilience_score = resilience_score.sort_values('resilience_score')
    
    print("\nResilience score (lower is better) for each canton:")
    print(resilience_score['resilience_score'])
    
    print(f"\nThe most resilient canton during the COVID-19 period was: {most_resilient}")
    
    # Plot the BCI trend during covid period
    plt.figure(figsize=(14,7))
    for column in covid_period.columns:
        if 'bci' in column and 'bci_trend' not in column:
            if 'Switzerland' in column:
                plt.plot(covid_period.index, covid_period[column], linestyle='dashed', color='black', label=column)
            else:
                plt.plot(covid_period.index, covid_period[column], label=column)
    plt.title('CREA BCI during COVID-19 period')
    plt.xlabel('Date')
    plt.ylabel('CREA BCI')
    plt.grid(axis='y')
    plt.legend()
    plt.show()
    
    plt.tight_layout(pad=5)
    
    # Plot the BCI trend during covid period
    plt.figure(figsize=(14,7))
    for column in covid_period.columns:
        if 'bci_trend' in column:
            if 'Switzerland' in column:
                plt.plot(covid_period.index, covid_period[column], linestyle='dashed', color='black', label=column)
            else:
                plt.plot(covid_period.index, covid_period[column], label=column)
    plt.title('CREA BCI Trend during COVID-19 period')
    plt.xlabel('Date')
    plt.ylabel('CREA BCI Trend')
    plt.grid(axis='y')
    plt.legend()
    plt.show()
    
      

This demonstration showcases the CREA BCI capabilities for analyzing economic fluctuations and should not be taken as a rigorous academic exercise. Although the computations here are simple, they serve as an indication of the index's vast potential.

R

For R users, the httr and jsonlite libraries can be used.

Getting BCI data:

library(httr)
library(jsonlite)
response <- GET("https://crea-web.unil.ch/api/v1/indicators/bci/geneva_bci")
data <- fromJSON(content(response, "text"))
print(data)

Getting cantonal GDP growth data:

response <- GET("https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_year_gdp_growth")
data <- fromJSON(content(response, "text"))
print(data)

Usage Example: Average Cantonal GDP Growth Rate during COVID-19

To complement the Python showcase, we will investigate the cantonal GDP growth rate during the same period.

Investigating the average cantonal GDP growth rate during the COVID-19 pandemic provides valuable insights into the economic impact of the crisis at a regional level. By examining the average GDP growth rate across different cantons, we can assess the resilience and adaptability of each region's economy during this critical period.

Additionally, it can shed light on the effectiveness of the CREA BCI to capture economic fluctuations and capture information beyond the simple GDP.

To see the results of this demonstration, you can run this code in RStudio.


    # Step 1: Import libraries
required_packages <- c("lubridate", "httr", "jsonlite","dplyr","tidyverse")
installed_packages <- rownames(installed.packages())
new_packages <- setdiff(required_packages, installed_packages)
if (length(new_packages) > 0) {
  install.packages(new_packages)
}

library(httr)
library(jsonlite)
library(dplyr)
library(tidyverse)
library(lubridate)

# Step 2: Import data
list_api <- c('https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/aargau_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/appenzell_ausserrhoden_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/appenzell_innerrhoden_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/basel_landschaft_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/basel_stadt_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/bern_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/fribourg_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/glarus_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/graubunden_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/jura_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/luzern_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/neuchatel_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/nidwalden_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/obwalden_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/schaffhausen_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/schwyz_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/solothurn_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/st_gallen_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/thurgau_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/ticino_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/uri_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/valais_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/vaud_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/zug_gdp_growth',
               'https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/zurich_gdp_growth')

start_date <- as.Date('2020-01-01')
end_date <- as.Date('2021-07-01')

# Create an empty data frame to store the results
# Define the empty dataframe with the right column names
all_data <- data.frame(dates = as.Date(character()), 
                       gdp_growth = numeric(), 
                       canton = character(), 
                       stringsAsFactors = FALSE)

# Get data for each canton
for (url in list_api) {
  # Make a GET request
  response <- GET(url)
  
  # Parse the response to a list
  data_list <- content(response, "parsed")
  
  # Iterate through each item in the list
  for (data in data_list) {
    # Convert dates to date format
    date <- as.Date(data$date)
    
    # Check if the date is within the specified date range
    if (date >= start_date && date <= end_date) {
      # Add the data frame to the main data frame
      all_data <- rbind(all_data, data.frame(
        dates = date, 
        gdp_growth = as.numeric(data$gdp_growth), 
        canton = str_extract(url, "(?<=cantonal_gdp/).*(?=_gdp_growth)"), 
        stringsAsFactors = FALSE
      ))
    }
  }
}

all_data$canton <- tools::toTitleCase(all_data$canton)

# Step 3: Computations
# Calculate the average growth rate for each canton during the period
results <- all_data %>%
  group_by(canton) %>%
  summarise(avg_growth = mean(gdp_growth, na.rm = TRUE))

# Order the cantons by average growth rate
results <- results[order(results$avg_growth),]


# Step 4: Results
# Plot GDP growth rate
# Create color palette
color_palette <- c("#008ccc", "#e5243b", "#dda63a", "#4c9f38", "#c5192d", "#471365",
                   "#26bde2", "#fcc30b", "#a21942", "#fd6925", "#dd1367", "#fd9d24",
                   "#bf8b2e", "#5d1c6e", "#3f7e44", "#1a17d9", "#56c02b", "#00689d",
                   "#19486a", "#2487ac", "#70cf80", "#795548", "#144a48", "#42be63",
                   "#0d0887", "#f40154", "#460a5d", "#ff3a21", "#dae021", "#4f658e",
                   "#208f8e", "#ffb47c", "#70337f", "#fe3989", "#26ad68", "#ffd31d",
                   "#436a8e", "#f1a5b2", "#5cc85b", "#af87fa", "#9bd961")

# Assign colors to cantons in the order they appear in the data
cantons <- unique(all_data$canton)
canton_colors <- setNames(color_palette[1:length(cantons)], cantons)

# Plot GDP growth rate
ggplot(all_data, aes(x = dates, y = gdp_growth, color = canton)) +
  geom_line() +
  labs(title = "Quarterly GDP Growth Rate by Canton", x = "Dates", y = "GDP Growth Rate") +
  theme(legend.position = "bottom", legend.box = "horizontal") +
  scale_color_manual(values = canton_colors)

# Plot Average GDP growth rate
# Assign colors to cantons in the order they appear in the data
results$canton <- factor(results$canton, levels = unique(results$canton))
results$canton_color <- canton_colors[results$canton]

# Plot Average GDP growth rate
ggplot(results, aes(x = reorder(canton, avg_growth), y = avg_growth, fill = canton_color)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  labs(title = "Average GDP Growth by Canton", x = "Canton", y = "Average GDP Growth") +
  scale_fill_identity() +
  theme(legend.position = "none")

# Table
print(results)

# Plot Average GDP growth rate for French Speaking Cantons
# Filter the results for the specific cantons
selected_cantons <- c("Geneva", "Valais", "Fribourg", "Neuchatel", "Jura", "Vaud")
filtered_results <- results[results$canton %in% selected_cantons, ]

ggplot(filtered_results, aes(x = reorder(canton, avg_growth), y = avg_growth, fill = canton_color)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  labs(title = "Average GDP Growth for Selected Cantons", x = "Canton", y = "Average GDP Growth") +
  scale_fill_identity() +
  theme(legend.position = "none")

# Table
print(filtered_results)

While this should not be taken as a rigorous academic exercise, the results of the Average Cantonal GDP Growth Rate during COVID-19 validate the CREA BCI's potential for analyzing economic fluctuations and underscore its value in assessing the resilience of regions during crises like COVID-19.

Researchers can utilize the cantonal GDP growth rate as a valuable economic indicator to analyze regional economic performance, identify patterns, and investigate the impact of various factors on cantonal economies.

Stata

In Stata, you can import data directly from a URL using import delimited or import json.

Getting BCI data:

import delimited "https://crea-web.unil.ch/api/v1/indicators/bci/geneva_bci.csv", clear

Getting cantonal GDP growth data:

import delimited "https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_year_gdp_growth.csv", clear

Excel

Excel users can use Power Query to import data.

  1. Click on "Data" in the Ribbon, then "Get Data" > "From Other Sources" > "From Web".
  2. Enter the API URL (https://crea-web.unil.ch/api/v1/indicators/bci/geneva_bci.csv or https://crea-web.unil.ch/api/v1/indicators/cantonal_gdp/geneva_year_gdp_growth.csv).
  3. Click "OK", then "Transform Data" if needed, and finally "Close & Load".

License

The data served by the API and the code of CREA Interactive Chart are licensed under CC BY 4.0.

The recession data is sourced from FRED (Federal Reserve Economic Data), provided by the Federal Reserve Bank of St. Louis.

Federal Reserve Bank of St. Louis, OECD based Recession Indicators 
for Switzerland from the Period following the Peak through the Trough [CHEREC], 
https://fred.stlouisfed.org/series/CHEREC