pct_change Method¶
The pct_change() method calculates percentage change between consecutive elements, essential for financial analysis.
Basic Usage¶
Calculate period-over-period percentage change.
1. Simple pct_change¶
import pandas as pd
import yfinance as yf
df = yf.Ticker('WMT').history(start='2020-01-01', end='2020-01-10')
df = df[['Close']]
df['pct_change'] = df['Close'].pct_change()
print(df)
Close pct_change
Date
2020-01-02 116.459999 NaN
2020-01-03 116.279999 -0.001546
2020-01-06 116.230003 -0.000430
2020-01-07 116.849998 0.005333
2020-01-08 116.220001 -0.005392
2. Formula¶
\[r_D = \frac{P_t - P_{t-1}}{P_{t-1}} = \frac{P_t}{P_{t-1}} - 1\]
3. First Value is NaN¶
No previous value to compare with.
periods Parameter¶
Calculate change over multiple periods.
1. Daily (Default)¶
df['daily_return'] = df['Close'].pct_change(periods=1)
2. Weekly¶
df['weekly_return'] = df['Close'].pct_change(periods=5)
3. Monthly¶
df['monthly_return'] = df['Close'].pct_change(periods=21)
Discrete vs Log Returns¶
Different return calculations.
1. Discrete Returns¶
# Standard percentage change
df['discrete_return'] = df['Close'].pct_change()
2. Log Returns¶
import numpy as np
df['log_return'] = np.log(df['Close'] / df['Close'].shift(1))
3. Relationship¶
\[r_C = \log\frac{P_t}{P_{t-1}} \approx \frac{P_t}{P_{t-1}} - 1 = r_D\]
For small changes, log and discrete returns are approximately equal.
Cumulative Returns¶
Calculate total return over time.
1. From pct_change¶
df['daily_return'] = df['Close'].pct_change()
df['cum_return'] = (1 + df['daily_return']).cumprod() - 1
2. Direct Calculation¶
df['cum_return'] = df['Close'] / df['Close'].iloc[0] - 1
3. Total Return¶
total_return = df['Close'].iloc[-1] / df['Close'].iloc[0] - 1
Rolling Statistics¶
Combine with rolling windows.
1. Rolling Volatility¶
df['volatility'] = df['Close'].pct_change().rolling(21).std() * np.sqrt(252)
2. Rolling Average Return¶
df['avg_return'] = df['Close'].pct_change().rolling(21).mean()
3. Sharpe Ratio (Simplified)¶
returns = df['Close'].pct_change()
sharpe = returns.mean() / returns.std() * np.sqrt(252)
Multiple Columns¶
Apply to entire DataFrame.
1. All Columns¶
df = yf.Ticker('WMT').history(start='2020-01-01', end='2020-12-31')
returns = df.pct_change()
2. Selected Columns¶
price_cols = ['Open', 'High', 'Low', 'Close']
returns = df[price_cols].pct_change()
3. Correlation of Returns¶
returns.corr()
fill_method Parameter¶
Handle missing values.
1. Forward Fill (Default)¶
df['return'] = df['Close'].pct_change(fill_method='ffill')
2. No Fill¶
df['return'] = df['Close'].pct_change(fill_method=None)
3. With Missing Data¶
# If data has gaps, fill_method controls behavior
df['Close'].fillna(method='ffill').pct_change()
Financial Analysis Example¶
Complete return analysis.
1. Load Data¶
df = yf.Ticker('SPY').history(period='1y')
2. Calculate Returns¶
df['daily_return'] = df['Close'].pct_change()
df['cum_return'] = (1 + df['daily_return']).cumprod() - 1
3. Summary Statistics¶
print(f"Mean Daily Return: {df['daily_return'].mean():.4%}")
print(f"Daily Volatility: {df['daily_return'].std():.4%}")
print(f"Total Return: {df['cum_return'].iloc[-1]:.2%}")
print(f"Annualized Return: {df['daily_return'].mean() * 252:.2%}")
print(f"Annualized Volatility: {df['daily_return'].std() * np.sqrt(252):.2%}")
Compare to Manual Calculation¶
Verify pct_change formula.
1. pct_change¶
df['pct'] = df['Close'].pct_change()
2. Manual¶
df['manual'] = (df['Close'] - df['Close'].shift(1)) / df['Close'].shift(1)
3. Verify Equal¶
print(df['pct'].equals(df['manual'])) # True (ignoring NaN)
GroupBy with pct_change¶
Calculate returns by group.
1. Per-Stock Returns¶
# Multiple stocks in one DataFrame
df['return'] = df.groupby('ticker')['close'].pct_change()
2. Reset per Group¶
# Cumulative return per stock
df['cum_return'] = df.groupby('ticker')['return'].transform(
lambda x: (1 + x).cumprod() - 1
)
3. Compare Stocks¶
# Pivot for comparison
pivot = df.pivot(columns='ticker', values='cum_return')