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 
gdppotDataFrame 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