The content covers a comprehensive analysis of stock market data, focusing on setting a 70-year historical date range for economic analysis, retrieving U.S. Real Potential GDP data from FRED, and calculating Year-over-Year and Quarter-over-Quarter growth rates. It includes detailed Python code examples for data retrieval, growth rate calculations, and visualizations using dual y-axis plots to display GDP values and growth rates effectively.

Week 1: Introduction and Data Sources
Setting the Date
GDP
The next stage is to collect data for Real potential GDP
gdppot = pdr.DataReader("GDPPOT", "fred", start=start)
gdppot['gdppot_us_yoy'] = gdppot.GDPPOT/gdppot.GDPPOT.shift(4)-1
gdppot['gdppot_us_qoq'] = gdppot.GDPPOT/gdppot.GDPPOT.shift(1)-1
gdppot.tail(15)
Objective
To retrieve and analyze U.S. Real Potential Gross Domestic Product (GDPPOT) from the Federal Reserve Economic Data (FRED), and calculate:
- Year-over-Year (YoY) growth
- Quarter-over-Quarter (QoQ) growth
🧾 Dataset Description
- GDPPOT: Real Potential GDP
- Unit: Billions of chained 2012 dollars
- Frequency: Quarterly
- Source: U.S. Congressional Budget Office via FRED
- FRED Series Code:
GDPPOT
⚙️ Code Breakdown
python
CopyEdit
from pandas_datareader import data as pdr
from datetime import date
# Get current date and create a 70-year date range
end = date.today()
start = date(year=end.year - 70, month=end.month, day=end.day)
end
: today’s datestart
: same day/month but 70 years earlier- This range captures long-term economic trends.
📥 Download GDPPOT Data from FRED
python
CopyEdit
gdppot = pdr.DataReader("GDPPOT", "fred", start=start)
- Retrieves quarterly potential GDP starting from
start
. - Resulting
gdppot
DataFrame contains: - Index: Dates (quarterly)
- Column:
'GDPPOT'
📊 Calculate Growth Rates
🟢 Year-over-Year (YoY) Growth
python
CopyEdit
gdppot['gdppot_us_yoy'] = gdppot['GDPPOT'] / gdppot['GDPPOT'].shift(4) - 1
- Compares each quarter with the same quarter of the previous year
shift(4)
: Moves data 4 rows (quarters) backward- Output is decimal form (e.g., 0.025 = 2.5%)
🟡 Quarter-over-Quarter (QoQ) Growth
python
CopyEdit
gdppot['gdppot_us_qoq'] = gdppot['GDPPOT'] / gdppot['GDPPOT'].shift(1) - 1
- Compares current quarter to the previous quarter
- Useful for short-term economic trend analysis
📋 View Recent Data
python
CopyEdit
gdppot.tail(15)
- Shows the most recent 15 entries
- Helps track recent GDP levels and growth performance
GDP Analysis Study Notes - Python Implementation
GDP Visualization Study Notes - Dual Y-Axis Plotting
Table of Contents
- Overview and Concept
- Required Libraries
- Figure Setup
- Primary Axis (GDP Values)
- Secondary Axis (Growth Rates)
- Formatting and Styling
- Complete Implementation
- Customization Options
Overview and Concept
Purpose
Create a dual y-axis plot to visualize both:
- GDP absolute values (billions of dollars) - Primary axis
- GDP growth rates (percentage) - Secondary axis
Why Dual Y-Axis?
Different scales make it impossible to plot both metrics on a single axis effectively:
- GDP values: Range from ~$8,000B to $25,000B
- Growth rates: Range from -2% to +8%
Reference Source
Based on: cmdlinetips.com dual y-axis tutorial
Required Libraries
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
Library Components
Library | Module | Purpose |
matplotlib.pyplot | plt | Core plotting functionality |
matplotlib.ticker | mtick | Advanced tick formatting (percentage) |
Figure Setup
Basic Figure Creation
fig, ax = plt.subplots(figsize=(20, 6))
plt.grid(True)
Syntax Breakdown
Component | Purpose | Parameters |
plt.subplots() | Creates figure and axis objects | figsize=(width, height) in inches |
figsize=(20, 6) | Sets plot dimensions | Width=20", Height=6" |
plt.grid(True) | Adds grid lines | Boolean parameter |
Alternative Syntax
# Method 1: Using plt.subplots()
fig, ax = plt.subplots(figsize=(20, 6))
# Method 2: Using plt.figure()
plt.figure(figsize=(20, 6))
ax = plt.gca() # Get current axis
Primary Axis (GDP Values)
Fill Between Plot
ax.fill_between(gdppot.index, gdppot.GDPPOT,
color="red", alpha=0.3,
label="US Potential GDP")
Parameter Details
Parameter | Type | Purpose | Example Value |
gdppot.index | DatetimeIndex | X-axis values (dates) | Quarterly dates |
gdppot.GDPPOT | Series | Y-axis values (GDP) | GDP in billions |
color | string | Fill color | "red" , "#FF0000" |
alpha | float | Transparency (0-1) | 0.3 = 30% opacity |
label | string | Legend label | For legend display |
Alternative Fill Options
# Fill between zero and values
ax.fill_between(x, y, color="red", alpha=0.3)
# Fill between two series
ax.fill_between(x, y1, y2, color="blue", alpha=0.2)
# Fill above/below a threshold
ax.fill_between(x, y, 20000, where=(y > 20000),
color="green", alpha=0.4)
Secondary Axis (Growth Rates)
Creating Secondary Y-Axis
ax2 = ax.twinx()
Syntax Explanation
ax.twinx()
: Creates a new axis sharing the same x-axisax2
: New axis object for right y-axis- Both axes share the same x-coordinates but have independent y-scales
Percentage Formatting
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
Formatter Options
Parameter | Meaning | Input Format | Display |
1.0 | Decimal input | 0.05 | 5% |
100.0 | Percentage input | 5.0 | 5% |
Growth Rate Plot
ax2.plot(gdppot.gdppot_us_yoy, color="blue", marker="o",
label="US Potential GDP Growth, % Y/Y")
Plot Parameters
Parameter | Purpose | Options | Example |
color | Line color | Color names, hex codes | "blue" , "#0000FF" |
marker | Point markers | "o" , "s" , "^" , "*" | "o" = circles |
label | Legend text | String | For legend display |
Marker Options
# Common marker styles
markers = {
"o": "circle",
"s": "square",
"^": "triangle up",
"v": "triangle down",
"*": "star",
"+": "plus",
"x": "x mark"
}
Formatting and Styling
Axis Labels
ax.set_xlabel("Date", fontsize=14)
ax.set_ylabel("US Potential GDP, $b", color="red", fontsize=14)
ax2.set_ylabel("US Potential GDP Growth, % Y/Y", color="blue", fontsize=14)
Label Parameters
Parameter | Purpose | Example Values |
fontsize | Text size | 12 , 14 , 16 , 'large' |
color | Text color | "red" , "blue" , "#FF0000" |
Font Size Options
# Numeric sizes
fontsize=10 # Small
fontsize=12 # Medium
fontsize=14 # Large
fontsize=16 # Extra large
# Named sizes
fontsize='small'
fontsize='medium'
fontsize='large'
fontsize='x-large'
Legend Handling
Combining Legends from Both Axes
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper left')
Step-by-Step Process
- Extract from primary axis:
ax.get_legend_handles_labels()
- Extract from secondary axis:
ax2.get_legend_handles_labels()
- Combine both:
lines + lines2, labels + labels2
- Create unified legend:
ax2.legend(...)
Legend Locations
Parameter | Position |
'upper left' | Top left corner |
'upper right' | Top right corner |
'lower left' | Bottom left corner |
'lower right' | Bottom right corner |
'center' | Center of plot |
'best' | Automatic best position |
Complete Implementation
Full Code Template
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
# Create figure and primary axis
fig, ax = plt.subplots(figsize=(20, 6))
plt.grid(True)
# Plot GDP values on primary axis (left y-axis)
ax.fill_between(gdppot.index, gdppot.GDPPOT,
color="red", alpha=0.3,
label="US Potential GDP")
# Create secondary axis (right y-axis)
ax2 = ax.twinx()
# Format secondary axis for percentages
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
# Plot growth rates on secondary axis
ax2.plot(gdppot.gdppot_us_yoy, color="blue", marker="o",
label="US Potential GDP Growth, % Y/Y")
# Set axis labels
ax.set_xlabel("Date", fontsize=14)
ax.set_ylabel("US Potential GDP, $b", color="red", fontsize=14)
ax2.set_ylabel("US Potential GDP Growth, % Y/Y", color="blue", fontsize=14)
# Combine legends from both axes
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper left')
# Display the plot
plt.show()
Customization Options
Color Schemes
# Professional color scheme
primary_color = "#2E86AB" # Blue
secondary_color = "#A23B72" # Purple
fill_alpha = 0.2
# Economic data color scheme
gdp_color = "#1f77b4" # Blue
growth_color = "#ff7f0e" # Orange
Enhanced Styling
# Add title
plt.title("US Potential GDP and Growth Rate Analysis",
fontsize=16, fontweight='bold', pad=20)
# Customize grid
plt.grid(True, alpha=0.3, linestyle='--')
# Set axis limits
ax.set_ylim(0, gdppot.GDPPOT.max() * 1.1)
ax2.set_ylim(-0.05, gdppot.gdppot_us_yoy.max() * 1.2)
Advanced Formatting
# Rotate x-axis labels
plt.xticks(rotation=45)
# Add annotations
ax2.annotate('Financial Crisis',
xy=('2008-01-01', -0.02),
xytext=('2010-01-01', 0.04),
arrowprops=dict(arrowstyle='->'))
# Tight layout
plt.tight_layout()
Save Options
# Save as high-quality image
plt.savefig('gdp_analysis.png', dpi=300, bbox_inches='tight')
plt.savefig('gdp_analysis.pdf', bbox_inches='tight')
Troubleshooting Common Issues
Issue 1: Legend Not Showing
# Ensure both plots have labels
ax.fill_between(..., label="GDP Values")
ax2.plot(..., label="Growth Rate")
Issue 2: Percentage Not Displaying
# Check formatter parameter
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(1.0)) # For decimal input
# OR
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(100.0)) # For percentage input
Issue 3: Overlapping Text
# Use tight_layout
plt.tight_layout()
# OR adjust figure size
fig, ax = plt.subplots(figsize=(22, 8))
Practice Exercises
- Color Variations: Change colors and transparency levels
- Different Markers: Experiment with various marker styles
- Multiple Series: Add QoQ growth rate to the secondary axis
- Time Filtering: Plot only the last 20 years of data
- Annotations: Add markers for recession periods
- Style Themes: Apply different matplotlib style sheets