| | """ |
| | eda_utils.py - Exploratory Data Analysis utilities for your stock app. |
| | This file generates: |
| | - daily returns |
| | - returns histogram |
| | - drawdown curve |
| | - rolling volatility |
| | - correlation with NIFTY |
| | - basic indicators (SMA, RSI, MACD) |
| | Everything is written simply for a beginner. |
| | """ |
| |
|
| | import pandas as pd |
| | import numpy as np |
| | import matplotlib.pyplot as plt |
| | import yfinance as yf |
| |
|
| | |
| | |
| | |
| | def compute_daily_returns(df): |
| | """Return percent change (daily returns).""" |
| | returns = df['Close'].pct_change().dropna() |
| | return returns |
| |
|
| |
|
| | |
| | |
| | |
| | def compute_drawdown(df): |
| | """Compute drawdown (drop from the peak).""" |
| | close = df['Close'] |
| | rolling_max = close.cummax() |
| | drawdown = (close - rolling_max) / rolling_max |
| | return drawdown |
| |
|
| |
|
| | |
| | |
| | |
| | def compute_volatility(df, window=30): |
| | """Rolling 30-day standard deviation (volatility).""" |
| | return df['Close'].pct_change().rolling(window).std() |
| |
|
| |
|
| | |
| | |
| | |
| | def correlation_with_nifty(df, start_date="2010-01-01"): |
| | """ |
| | Downloads NIFTY (^NSEI) and computes correlation of returns. |
| | """ |
| | nifty = yf.Ticker("^NSEI").history(start=start_date) |
| | if nifty.empty: |
| | return None |
| |
|
| | stock_ret = df['Close'].pct_change() |
| | nifty_ret = nifty['Close'].pct_change() |
| |
|
| | merged = pd.concat([stock_ret, nifty_ret], axis=1, join='inner').dropna() |
| | merged.columns = ['stock', 'nifty'] |
| |
|
| | return merged['stock'].corr(merged['nifty']) |
| |
|
| |
|
| | |
| | |
| | |
| | def add_sma(df, windows=[20, 50, 200]): |
| | """Adds Simple Moving Averages to DataFrame.""" |
| | for w in windows: |
| | df[f"SMA_{w}"] = df['Close'].rolling(w).mean() |
| | return df |
| |
|
| |
|
| | |
| | |
| | |
| | def add_rsi(df, period=14): |
| | """Add RSI indicator.""" |
| | delta = df['Close'].diff() |
| | gain = delta.clip(lower=0) |
| | loss = (-delta).clip(lower=0) |
| |
|
| | avg_gain = gain.rolling(period).mean() |
| | avg_loss = loss.rolling(period).mean() |
| |
|
| | rs = avg_gain / avg_loss |
| | df['RSI'] = 100 - (100 / (1 + rs)) |
| |
|
| | return df |
| |
|
| |
|
| | |
| | |
| | |
| | def add_macd(df): |
| | """Add MACD, Signal Line.""" |
| | exp1 = df['Close'].ewm(span=12, adjust=False).mean() |
| | exp2 = df['Close'].ewm(span=26, adjust=False).mean() |
| | df['MACD'] = exp1 - exp2 |
| | df['Signal'] = df['MACD'].ewm(span=9, adjust=False).mean() |
| | return df |
| |
|
| |
|
| | |
| | |
| | |
| | def plot_eda(df, ticker): |
| | """Generate basic EDA plots.""" |
| |
|
| | plt.figure(figsize=(12,4)) |
| | df['Close'].plot(title=f"{ticker} - Close Price") |
| | plt.grid(True) |
| | plt.show() |
| |
|
| | plt.figure(figsize=(12,4)) |
| | compute_daily_returns(df).hist(bins=40) |
| | plt.title("Histogram of Returns") |
| | plt.grid(True) |
| | plt.show() |
| |
|
| | plt.figure(figsize=(12,4)) |
| | compute_drawdown(df).plot(title="Drawdown Curve") |
| | plt.grid(True) |
| | plt.show() |
| |
|
| | plt.figure(figsize=(12,4)) |
| | compute_volatility(df).plot(title="Rolling Volatility (30-day)") |
| | plt.grid(True) |
| | plt.show() |
| |
|
| | print("SMA added → columns:", [c for c in df.columns if 'SMA' in c]) |
| | print("RSI added? →", 'RSI' in df.columns) |
| | print("MACD added? →", 'MACD' in df.columns) |
| |
|