← Return to the book

FUTURECENTRAL PRESS · PRACTICE SAMPLE

Python Fundamentals for Finance

From Your First Line of Code to a Complete Analytical Project

Chapter 9: A Complete Worked Project

From data download to written interpretation: a notebook another analyst can re-run and a committee can review

Practice sample

This book includes self-check questions, programming exercises and worked solutions in Appendix E. This online sample shows four questions from Chapter 9 and an investment-analysis exercise with its worked solution. It is a sample of the book’s practice material.

Self-check questions

1. (Credit) Which dataset do you load to begin the credit portfolio worked example in Section 9.3?

  • a) S&P 500 daily returns
  • b) The lending-club style loan portfolio CSV referenced in Chapter 4
  • c) A synthetic options chain
  • d) FX tick data
Show answer

Answer: b

2. (Credit) The default rate for a segment is computed as:

  • a) Sum of loan amounts divided by count
  • b) Count of defaulted loans divided by count of loans in the segment
  • c) Mean of interest rates
  • d) Median of credit scores
Show answer

Answer: b

3. (Investments) Daily simple returns for an equity series are computed as:

  • a) prices.diff()
  • b) prices.pct_change()
  • c) np.log(prices)
  • d) prices.cumsum()
Show answer

Answer: b

4. (Risk) The threshold-exceedance count for a daily P&L series is:

  • a) The number of days the loss breached a stated threshold
  • b) The average loss
  • c) The volatility
  • d) The Sharpe ratio
Show answer

Answer: a

Programming exercise

Exercise 9.2 (Investments). Repeat the Section 9.4 equity EDA on a basket of five NSE largecaps of your choice. Produce daily returns, summary statistics, the correlation heatmap, and a one-paragraph interpretation of diversification within the basket.

Read the worked solution and common mistake

Solution.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf

tickers = ['RELIANCE.NS', 'TCS.NS', 'HDFCBANK.NS', 'INFY.NS', 'ITC.NS']
prices = yf.download(tickers, start='2022-01-01', end='2024-12-31',
                     auto_adjust=True)['Close']
prices = prices.dropna(how='all').ffill()

# Daily simple returns
rets = prices.pct_change().dropna()

# Annualized summary statistics
summary = pd.DataFrame({
    'ann_mean_pct' : (rets.mean()  * 252 * 100).round(2),
    'ann_vol_pct'  : (rets.std()   * np.sqrt(252) * 100).round(2),
    'sharpe_proxy' : (rets.mean() / rets.std() * np.sqrt(252)).round(2),
    'skew'         : rets.skew().round(3),
    'kurtosis'     : rets.kurt().round(3),
})
print(summary)

# Correlation heatmap
corr = rets.corr().round(3)
print('\nCorrelation matrix:')
print(corr)

fig, ax = plt.subplots(figsize=(6, 5))
im = ax.imshow(corr, cmap='coolwarm', vmin=-1, vmax=1)
ax.set_xticks(range(len(tickers))); ax.set_yticks(range(len(tickers)))
ax.set_xticklabels(tickers, rotation=45, ha='right')
ax.set_yticklabels(tickers)
for i in range(len(tickers)):
    for j in range(len(tickers)):
        ax.text(j, i, corr.iloc[i, j], ha='center', va='center', color='black')
plt.colorbar(im); plt.title('NSE Largecap Correlation, 2022-2024')
plt.tight_layout(); plt.savefig('outputs/nse_corr.png', dpi=150)

Expected output: pairwise correlations cluster in the 0.30 to 0.60 band; HDFCBANK and the IT names (TCS, INFY) sit at the lower end, ITC sits the most independent, and RELIANCE moves with the broad market.

Discussion.

A five-stock large-cap basket gives meaningful but not dramatic diversification: typical pairwise correlation around 0.45 means roughly half the variance is common-factor (Nifty beta) and half is idiosyncratic. Adding more large-caps from the same index pushes correlation up, not down. Real diversification at this stage requires moving across asset classes (gold, bonds) or geographies (US, EM ex-India). The summary table also reveals fat tails: kurtosis is positive for all five names, which is the standard equity-return signature.

Common mistake.

Computing correlation on prices instead of returns. Price levels of two stocks both drifting upward can show correlation of 0.95 even when their day-to-day moves are unrelated. Always work with returns for diversification analysis.