Lesson 3 · Finance and Stock Market Analytics
Types of Financial Data: OHLCV, Fundamentals, and Sentiment Explained
Financial data helps us understand the real world of stocks and companies. We will explore common types: OHLCV (price/volume), Fundamentals (balance sheet),…
- CourseFinance and Stock Market Analytics
- Lesson3 of 16
- Video24 min
- FormatJupyter notebook · 20 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbTypes of Financial Data in Stock Market Analytics#
- Financial data helps us understand the real world of stocks and companies.
- We will explore common types: OHLCV (price/volume), Fundamentals (balance sheet), and Sentiment (how people feel).
- These data types are crucial for investors, analysts, and finance professionals.
- You will learn to read, load, and analyze each type with real Python code.
- You will see where mistakes happen and get hands-on with real datasets.
- By the end, you will understand how to recognize and use these data types in practical stock analysis tasks.
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import yfinance as yf
Core Data Concepts: OHLCV, Fundamentals, and Sentiment#
- OHLCV stands for Open, High, Low, Close, and Volume. It describes day-to-day stock prices and trading activity.
- Fundamentals capture a company's business and health, such as earnings, valuation ratios, and sector.
- Sentiment reflects market mood or crowd psychology, often scraped from news or social media.
- OHLCV data is structured with one row for each date and ticker pair.
- Fundamental data is typically one row per company, with columns for each metric (like P/E ratio, sector, market cap, etc).
- Beginners often confuse wide (pivoted, one column per ticker) and long (one row per date/ticker) OHLCV formats.
- Beginners might incorrectly assign columns to multi-ticker frames: always use datasets as given by yfinance.
- Not all companies report every fundamental ratio, so expect missing or null values in real data.
- Sentiment is not covered in-depth in this notebook, as robust labeled datasets are rarely public, but we discuss concepts.
# Beginner Example 1: Load multi-ticker OHLCV data for 5 tech stocks
tickers = ['AAPL','MSFT','GOOGL','AMZN','TSLA']
ohlcv = yf.download(tickers, period='1y', auto_adjust=True, progress=False)
ohlcv = ohlcv.stack(future_stack=True).rename_axis(['Date','Ticker']).reset_index()
ohlcv.columns.name = None
print(ohlcv.shape)
print(ohlcv.head(3))
# Beginner Example 2: Pivot OHLCV data to see closing prices in wide format
close_pivot = ohlcv.pivot(index='Date', columns='Ticker', values='Close')
print(close_pivot.shape)
print(close_pivot.head(3))
# Beginner Example 3: Filter OHLCV for just Tesla (TSLA)
tsla_ohlcv = ohlcv[ohlcv['Ticker'] == 'TSLA']
print(tsla_ohlcv.head(3))
# Intermediate Example 1: Load fundamental data for 12 companies
tickers = ['AAPL','MSFT','GOOGL','AMZN','TSLA','NVDA','META','JPM','JNJ','XOM','WMT','V']
rows = []
for tk in tickers:
info = yf.Ticker(tk).info
rows.append({
'ticker': tk,
'sector': info.get('sector', 'Unknown'),
'market_cap': info.get('marketCap'),
'pe_ratio': info.get('trailingPE'),
'eps': info.get('trailingEps'),
'profit_margin':info.get('profitMargins'),
'debt_equity': info.get('debtToEquity')
})
fund_df = pd.DataFrame(rows)
print(fund_df.shape)
print(fund_df.head(3))
# Intermediate Example 2: Which companies have the highest P/E ratio?
print(fund_df[['ticker','pe_ratio']].sort_values('pe_ratio', ascending=False))
# Intermediate Example 3: Check sector counts in the fundamentals DataFrame
print(fund_df['sector'].value_counts())
# Intermediate Example 4: Find companies with missing debt-to-equity data
missing_de = fund_df[fund_df['debt_equity'].isnull()]
print(missing_de[['ticker','debt_equity']])
# Intermediate Example 5: Calculate average profit margin by sector
avg_profit_margin = fund_df.groupby('sector')['profit_margin'].mean()
print(avg_profit_margin)
# Intermediate Example 6: Screen for high earnings per share (EPS) companies
top_eps = fund_df[['ticker','eps']].sort_values('eps', ascending=False).head(5)
print(top_eps)
# Advanced Example 1: Load S&P 500 company list and join with fundamentals
url = 'https://raw.githubusercontent.com/datasets/s-and-p-500-companies/main/data/constituents.csv'
sp500 = pd.read_csv(url)
merged = pd.merge(sp500, fund_df, how='left', left_on='Symbol', right_on='ticker')
print(merged[['Symbol', 'Security', 'sector', 'market_cap']].head(5))
# Advanced Example 2: Select top 3 companies by market cap in each sector
top_by_sector = merged.sort_values(['sector', 'market_cap'], ascending=[True,False]).groupby('sector').head(3)
print(top_by_sector[['Symbol','sector','market_cap']])
# Advanced Example 3: Visualize the distribution of P/E ratios
import matplotlib.pyplot as plt
plt.hist(fund_df['pe_ratio'].dropna(), bins=8, color='skyblue', edgecolor='black')
plt.title('Distribution of Price-to-Earnings (P/E) Ratios')
plt.xlabel('P/E Ratio')
plt.ylabel('Frequency')
plt.show()
# Advanced Example 4: End-to-End - Portfolio gain/loss calculation
np.random.seed(42)
tickers = ['AAPL','MSFT','GOOGL','AMZN','TSLA','NVDA','META','NFLX','JPM','JNJ']
sector_map = {'AAPL':'Tech','MSFT':'Tech','GOOGL':'Tech','AMZN':'Consumer',
'TSLA':'Auto','NVDA':'Tech','META':'Tech','NFLX':'Media',
'JPM':'Finance','JNJ':'Health'}
data = yf.download(tickers, period='1y', auto_adjust=True, progress=False)['Close']
rows = []
for tk in tickers:
buy = round(float(data[tk].iloc[0]), 2)
cur = round(float(data[tk].iloc[-1]), 2)
rows.append({'ticker': tk, 'shares': int(np.random.randint(5, 100)),
'buy_price': buy, 'cur_price': cur, 'sector': sector_map[tk]})
df = pd.DataFrame(rows)
df['gain_pct'] = np.round((df['cur_price'] - df['buy_price']) / df['buy_price'] * 100, 2)
print(df.head(5))
# Error Example 1: What happens if you assign columns directly to multi-ticker OHLCV data?
df = yf.download(['AAPL','MSFT'], period='1y', auto_adjust=True, progress=False)
try:
df.columns = ['Date','AAPL_Close','MSFT_Close','AAPL_High','MSFT_High','AAPL_Low','MSFT_Low',
'AAPL_Open','MSFT_Open','AAPL_Volume','MSFT_Volume']
except Exception as e:
print('Error:', e)
# Error Example 2: Attempt to access a missing column in fundamentals
try:
print(fund_df['dividend_yield'])
except KeyError as e:
print('KeyError:', e)
# Error Example 3: Handling missing values in financial ratios
fund_df['profit_margin_filled'] = fund_df['profit_margin'].fillna(0)
print(fund_df[['ticker','profit_margin','profit_margin_filled']])
# Best Practice: Always check data types before analysis
print(fund_df.dtypes)
# Common Pattern: Combine price and fundamental data for enhanced screening
combo = pd.merge(ohlcv[ohlcv['Ticker']=='AAPL'][['Date','Close']],
fund_df[fund_df['ticker']=='AAPL'][['pe_ratio','eps']], how='cross')
print(combo.head(5))
# End-to-End Example: From raw fundamentals to sector ranking by average EPS
avg_sector_eps = fund_df.groupby('sector')['eps'].mean().sort_values(ascending=False)
print(avg_sector_eps)
End of Lesson: Summary and Practice Prompts#
- You have learned how to load, compare, and process real stock OHLCV and fundamental data in Python.
- You can now spot structure, handle errors, and combine data for practical analytics.
- Remember: Always check your data shape, types, and missing values before analysis.
- Watch our channel for more deep dives and hands-on market data walkthroughs!
- Try out your own ticker list or join our group to share your questions.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



