FRE-GY 6883 Financial Computing - Fall 2025 Team Project
A C++ application that analyzes the impact of quarterly earnings reports on stock price movements for Russell 3000 stocks using Cumulative Average Abnormal Returns (CAAR) methodology.
- Project Overview
- Features
- Project Structure
- UML Class Diagram
- Class Documentation
- Build Instructions
- Usage
- Data Files
- Configuration
This project evaluates how earnings announcements affect stock prices by:
- Classifying stocks into Beat, Meet, and Miss groups based on earnings surprise (sector-neutral)
- Removing outliers (top 2% and bottom 2% within each sector)
- Running Bootstrap analysis with 40 samplings of 30 stocks per group
- Calculating Abnormal Returns (AR = Stock Return - Market Return)
- Computing CAAR (Cumulative Average Abnormal Returns) over a 2N-day window
- Visualizing results using gnuplot
- Object-oriented design with proper encapsulation
- Matrix and Vector classes with operator overloading
- libcurl integration for fetching historical prices from EODHistoricalData API
- Optimized data fetching: All stock and market data fetched once, then cached for 40 bootstrap iterations
- Sector-neutral stock classification with outlier removal
- Bootstrap sampling with configurable parameters
- Save/Load results to CSV for persistence
- Interactive menu system
- Gnuplot visualization of CAAR curves
fre6883-teamproject-the-lal-street-boys/
├── main.cpp # Entry point with menu system
├── Makefile # Build configuration
├── presentation.pptx # Project presentation slides
├── include/ # Header files
│ ├── stock.h # Stock class definition
│ ├── Matrix.h # Vector and Matrix classes
│ ├── MarketData.h # API data fetching
│ ├── Bootstrap.h # Bootstrap analysis
│ └── Plotting.h # Gnuplot visualization
├── src/ # Implementation files
│ ├── Stock.cpp
│ ├── Matrix.cpp
│ ├── MarketData.cpp
│ ├── Bootstrap.cpp
│ └── Plotting.cpp
├── input/ # Input data files
│ ├── stock.csv # Russell 3000 stock data
│ └── earnings.csv # Earnings announcements data
├── output/ # Generated results
│ └── results.csv
├── .env # API token (gitignored)
└── .env.example # Example environment file
┌─────────────────────────────────────────────────────────────────────────────────┐
│ EARNINGS ANALYSIS SYSTEM │
└─────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ «enum» │ │ Vector │ │ Matrix │
│ Group │ ├──────────────────┤ ├──────────────────┤
├──────────────────┤ │ -data: vector │ │ -data: vector │
│ Beat │ ├──────────────────┤ │ -rows: size_t │
│ Meet │ │ +operator+() │ │ -cols: size_t │
│ Miss │ │ +operator-() │ ├──────────────────┤
│ None │ │ +operator*() │ │ +operator+() │
└──────────────────┘ │ +operator/() │ │ +operator-() │
│ +sum() │ │ +operator*() │
│ +mean() │ │ +operator/() │
│ +stddev() │ │ +colMean() │
│ +cumsum() │ │ +colStddev() │
└──────────────────┘ │ +getRow() │
△ │ +setRow() │
│ └──────────────────┘
│ uses
┌─────────────────────────────────────┴─────────────────────────────────────┐
│ │
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ Stock │ │ Bootstrap │
├──────────────────────────────┤ ├──────────────────────────────┤
│ -symbol: string │ │ -allStocks: StockMap* │
│ -name: string │ │ -marketData: MarketData* │
│ -sector: string │ │ -beatStocks: vector<string> │
│ -group: Group │ │ -meetStocks: vector<string> │
│ -earningDate: string │◄───────────────────────│ -missStocks: vector<string> │
│ -periodEnding: string │ contains │ -N: int │
│ -estimatedEPS: double │ │ -numSamplings: int │
│ -reportedEPS: double │ │ -beatAARMatrix: Matrix │
│ -surprise: double │ │ -avgBeatCAAR: Vector │
│ -surprisePercent: double │ │ -stdBeatCAAR: Vector │
│ -dailyPrices: vector<pair> │ ├──────────────────────────────┤
│ -dailyReturns: vector │ │ +buildGroups() │
│ -cumulativeReturns: vector │ │ +runAllSamplings() │
├──────────────────────────────┤ │ +runSampling() │
│ +calculateDailyReturns() │ │ +calculateStatistics() │
│ +calculateCumulativeReturns()│ │ +printGroupStats() │
│ +extractPricesAroundDate() │ │ +saveResults() │
│ +printInfo() │ │ +loadResults() │
│ +getters/setters... │ │ +hasResults() │
└──────────────────────────────┘ └──────────────────────────────┘
│
│ uses
▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ MarketData │ │ GnuplotHandler │
├──────────────────────────────┤ ├──────────────────────────────┤
│ -curlHandle: CURL* │ │ -gnuplotPipe: FILE* │
│ -apiToken: string │ ├──────────────────────────────┤
│ -initialized: bool │ │ +GnuplotHandler() │
├──────────────────────────────┤ │ +~GnuplotHandler() │
│ +init() │ │ +isOpen() │
│ +fetchPrices() │ │ +plotCAAR() │
│ +fetchPricesAroundDate() │ │ +sendCommand() │
│ +populateStockPrices() │ └──────────────────────────────┘
│ +loadStockInfo() │
│ +loadEarningsData() │
│ -WriteCallback() │
│ -adjustDate() │
└──────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Type Aliases │
├─────────────────────────────────────────────────────────────────────────────────┤
│ StockMap = std::map<std::string, Stock> // Stock symbol → Stock object │
└─────────────────────────────────────────────────────────────────────────────────┘
Represents a single stock with its earnings and price data.
| Member | Type | Description |
|---|---|---|
symbol |
string |
Stock ticker symbol (e.g., "AAPL") |
name |
string |
Company name |
sector |
string |
Industry sector |
group |
Group |
Classification: Beat, Meet, Miss, or None |
earningDate |
string |
Earnings announcement date (YYYY-MM-DD) |
periodEnding |
string |
Fiscal period end date |
estimatedEPS |
double |
Analyst estimated EPS |
reportedEPS |
double |
Actual reported EPS |
surprise |
double |
EPS surprise (reported - estimated) |
surprisePercent |
double |
Surprise as percentage |
dailyPrices |
vector<pair<string,double>> |
Date → Adjusted close price |
dailyReturns |
vector<double> |
Log returns: ln(P_t / P_{t-1}) |
cumulativeReturns |
vector<double> |
Cumulative sum of daily returns |
| Method | Description |
|---|---|
Stock() |
Default constructor, initializes all members |
Stock(sym, name, sector) |
Parameterized constructor |
calculateDailyReturns() |
Computes log returns from daily prices |
calculateCumulativeReturns() |
Computes cumulative sum of returns |
extractPricesAroundDate(date, N) |
Extracts 2N+1 prices centered on date |
printInfo() |
Displays all stock information to console |
get*/set*() |
Accessor and mutator methods |
A wrapper around std::vector<double> with arithmetic operators and statistical functions.
| Member | Type | Description |
|---|---|---|
data |
vector<double> |
Underlying data storage |
| Method | Description |
|---|---|
Vector() |
Default constructor |
Vector(size, val) |
Creates vector of given size with initial value |
Vector(initializer_list) |
Construct from initializer list |
operator[](i) |
Element access |
operator+(other) |
Element-wise addition |
operator-(other) |
Element-wise subtraction |
operator*(scalar) |
Scalar multiplication |
operator/(scalar) |
Scalar division |
operator+=, -=, *=, /= |
Compound assignment operators |
sum() |
Returns sum of all elements |
mean() |
Returns arithmetic mean |
stddev() |
Returns sample standard deviation |
cumsum() |
Returns cumulative sum vector |
size() |
Returns number of elements |
push_back(val) |
Appends element |
clear() |
Removes all elements |
A 2D matrix class with arithmetic operators and column-wise statistics.
| Member | Type | Description |
|---|---|---|
data |
vector<vector<double>> |
2D data storage |
rows |
size_t |
Number of rows |
cols |
size_t |
Number of columns |
| Method | Description |
|---|---|
Matrix() |
Default constructor |
Matrix(rows, cols, val) |
Creates matrix with initial value |
operator[](i) |
Row access |
at(r, c) |
Element access with bounds checking |
operator+, -, *, / |
Matrix arithmetic (element-wise) |
getRow(r) |
Returns row as Vector |
getCol(c) |
Returns column as Vector |
setRow(r, vec) |
Sets row from Vector |
setCol(c, vec) |
Sets column from Vector |
colMean() |
Returns Vector of column means |
colStddev() |
Returns Vector of column standard deviations |
colSum() |
Returns Vector of column sums |
resize(r, c, val) |
Resizes matrix |
print(precision) |
Displays matrix to console |
Handles API communication and data loading using libcurl.
| Member | Type | Description |
|---|---|---|
curlHandle |
CURL* |
libcurl easy handle |
apiToken |
string |
EODHistoricalData API token |
initialized |
bool |
Whether API is ready |
| Method | Description |
|---|---|
MarketData() |
Constructor, initializes CURL globally |
~MarketData() |
Destructor, cleans up CURL |
init(envFile) |
Loads API token from .env file |
isInitialized() |
Returns initialization status |
fetchPrices(symbol, start, end) |
Fetches prices for date range |
fetchPricesAroundDate(symbol, date, N) |
Fetches 2N+1 days of prices |
populateStockPrices(stock, N) |
Fills stock with price data |
loadStockInfo(file, stocks) |
Static: loads stock.csv into StockMap |
loadEarningsData(file, stocks) |
Static: loads earnings.csv into StockMap |
| Method | Description |
|---|---|
WriteCallback(...) |
CURL callback for response data |
adjustDate(date, days) |
Date arithmetic helper |
Implements the bootstrap sampling algorithm and CAAR calculations.
| Member | Type | Description |
|---|---|---|
allStocks |
StockMap* |
Pointer to all loaded stocks |
marketData |
MarketData* |
Pointer to data fetcher |
beatStocks |
vector<string> |
Symbols in Beat group |
meetStocks |
vector<string> |
Symbols in Meet group |
missStocks |
vector<string> |
Symbols in Miss group |
N |
int |
Window size (30-60) |
numSamplings |
int |
Number of bootstrap iterations (40) |
stocksPerGroup |
int |
Stocks per group per sampling (30) |
rng |
mt19937 |
Random number generator |
iwvCache |
map<string, vector<pair>> |
Cached IWV prices by earning date |
beatAARMatrix |
Matrix |
AAR values: rows=samplings, cols=2N |
beatCAARMatrix |
Matrix |
CAAR values: rows=samplings, cols=2N |
avgBeatAAR |
Vector |
Average AAR across samplings |
stdBeatAAR |
Vector |
Std dev of AAR across samplings |
avgBeatCAAR |
Vector |
Average CAAR across samplings |
stdBeatCAAR |
Vector |
Std dev of CAAR across samplings |
| (similar for Meet and Miss groups) |
| Method | Description |
|---|---|
Bootstrap(stocks, md) |
Constructor with stock map and market data |
setN(n) |
Sets window size |
setNumSamplings(n) |
Sets number of bootstrap iterations |
setStocksPerGroup(n) |
Sets stocks per group |
getN() |
Returns window size |
buildGroups() |
Classifies stocks into Beat/Meet/Miss |
fetchAllData() |
Pre-fetches all stock and IWV prices (called once) |
runAllSamplings() |
Executes all 40 bootstrap samplings |
runSampling(num) |
Executes single sampling iteration |
calculateStatistics() |
Computes mean and std across samplings |
printGroupStats(group) |
Displays AAR/CAAR table for one group |
printAllStats() |
Displays stats for all groups |
saveResults(filename) |
Saves results to CSV file |
loadResults(filename) |
Loads results from CSV file |
hasResults() |
Returns true if results are available |
getAvg*CAAR() |
Getters for average CAAR vectors |
getStd*CAAR() |
Getters for std CAAR vectors |
get*Stocks() |
Getters for group stock lists |
| Method | Description |
|---|---|
classifyStocks() |
Sector-neutral classification algorithm |
removeOutliers(stocks, pct) |
Removes top/bottom percentile |
calculateAbnormalReturns(stock, market) |
AR = R_stock - R_market |
Handles gnuplot visualization through a pipe.
| Member | Type | Description |
|---|---|---|
gnuplotPipe |
FILE* |
Pipe to gnuplot process |
| Method | Description |
|---|---|
GnuplotHandler() |
Opens gnuplot pipe with -persist flag |
~GnuplotHandler() |
Closes gnuplot pipe |
isOpen() |
Returns true if pipe is valid |
plotCAAR(beat, meet, miss, N) |
Plots all three CAAR curves |
sendCommand(cmd) |
Sends raw command to gnuplot |
- C++14 compatible compiler (g++ or clang++)
- libcurl development libraries
- gnuplot (for visualization)
# Install dependencies
brew install curl gnuplot
# Build
make
# Run
./main# Install dependencies
sudo apt install libcurl4-openssl-dev gnuplot
# Build
make
# Run
./main-
Copy
.env.exampleto.env:cp .env.example .env
-
Add your EODHistoricalData API token to
.env:API_TOKEN=your_api_token_here
./main============================================================
Earnings Announcement Impact Analysis - Russell 3000
============================================================
1. Enter N to retrieve historical price data for all stocks
2. Pull information for one stock
3. Show AAR, AAR-STD, CAAR, CAAR-STD for one group
4. Show CAAR graph for all three groups (gnuplot)
5. Save results to file
6. Load results from file and visualize
7. Exit
============================================================
| Option | Description |
|---|---|
| 1 | Enter N (30-60), fetches data, runs 40 bootstrap samplings |
| 2 | Look up any stock's earnings data and prices |
| 3 | Display AAR/CAAR statistics table for Beat, Meet, or Miss |
| 4 | Show gnuplot chart with all three CAAR curves |
| 5 | Save results to output/results.csv |
| 6 | Load saved results and display chart (no API calls) |
| 7 | Exit program |
Contains Russell 3000 stock information:
Symbol,Name,Sector
AAPL,Apple Inc.,Technology
...
Contains Q1 2025 earnings announcements:
Ticker,Date,Period Ending,Estimated,Reported,Surprise,Surprise %
AAPL,2025-01-30,2024-12-31,2.35,2.40,0.05,2.13
...
Generated results file with metadata and CAAR data:
# Bootstrap Results
# N=60
# NumSamplings=40
# StocksPerGroup=30
#
Day,Beat_AAR,Beat_AAR_STD,Beat_CAAR,Beat_CAAR_STD,...
-59,0.00123456,0.00045678,0.00123456,0.00045678,...
API_TOKEN=your_eodhistoricaldata_api_tokenCXX = g++
CXXFLAGS = -Wall -std=c++14 -I include
LIBS = -lcurl- Group stocks by sector
- Within each sector, sort by surprise percentage (descending)
- Remove top 2% and bottom 2% as outliers
- Divide remaining into thirds: Beat (top), Meet (middle), Miss (bottom)
- Combine across sectors for final groups
The analysis runs in two phases for efficiency:
Phase 1: Data Fetching (One-Time)
- Collect all stocks from Beat, Meet, and Miss groups
- For each stock, fetch 2N+1 days of prices from API
- Cache IWV (Russell 3000 ETF) prices for each unique earning date
- This phase involves API calls and may take several minutes
Phase 2: Bootstrap Iterations (Fast) For each of 40 iterations:
- Randomly select 30 stocks from each group
- Use cached prices (no additional API calls)
- Calculate daily returns:
R = ln(P_t / P_{t-1}) - Calculate abnormal returns:
AR = R_stock - R_IWV - Calculate AAR (average across stocks at each time point)
- Calculate CAAR (cumulative sum of AAR)
This two-phase approach significantly reduces execution time by fetching data once instead of redundantly during each iteration.
- Average AAR/CAAR across 40 samplings
- Standard deviation of AAR/CAAR across 40 samplings
This project is part of the FRE-GY 6883 Financial Computing course at NYU Tandon School of Engineering.