Skip to content

poseidon-jayce/Portfolio-analytics-

Repository files navigation

Portfolio Analytics

A personal tool to track and analyze the performance of an equity portfolio, benchmarked against the S&P 500 Total Return index.

Built in Python with pandas and numpy. Input data comes from Fineco bank statements, market prices from Yahoo Finance.


Development Approach & Use of AI

This project was developed with the support of AI tools such as Google AI and Claude AI, primarily for debugging, resolving implementation issues, and improving code structure.

AI was used as a learning and productivity assistant, not as a substitute for understanding. Every suggestion was carefully reviewed, tested, and adapted to fit the logic of the system. This process helped in:

Debugging complex issues in data pipelines and calculations Understanding edge cases in portfolio accounting and return computation Improving code modularity and overall architecture Strengthening Python proficiency, especially with pandas and numerical computations

Rather than relying on generated code blindly, I focused on understanding the flow, financial logic, and mathematical foundations behind each component — including return calculations (TWR, XIRR), risk metrics (volatility, Sharpe, beta), and attribution logic.

Why This Project?

Prior to this, I had built an equity analytics project that included Monte Carlo simulation, Sharpe ratio, and beta calculations on NIFTY 50 stocks using ~63K data points over 5 years.

This project goes significantly deeper by moving from market-level analysis to real portfolio-level analytics.

Key advancements in this project: End-to-end portfolio engine (cash flows, positions, returns), Benchmark comparison against S&P 500 Total Return, Accurate handling of external cash flows (TWR vs MWR/XIRR), Rolling metrics to analyze performance across time, Per-ticker contribution & attribution analysis, Real-world data integration (broker statements, FX conversion, missing data handling).

Learning Outcomes

This project helped me develop a much deeper understanding of:

Portfolio return methodologies (TWR vs MWR), Risk and performance measurement in real-world scenarios, Data pipeline design for financial systems, Handling imperfect financial data (missing prices, timing assumptions, FX), Translating financial theory into production-like code.

Overall, this project represents a shift from theoretical analytics to practical, real-world portfolio analysis, combining finance, data science, and software engineering.

Project Structure

portfolio_analytics/
│
├── data/                        ← Input files (do not share publicly)
│   ├── Lista_Titoli.xlsx        ← Transaction history exported from Fineco
│   ├── isin_ticker.csv          ← ISIN → Yahoo Finance ticker mapping
│   └── external_cashflows.csv  ← External deposits and withdrawals
│
├── cache/                       ← Prices downloaded from Yahoo (regenerable)
│   ├── prices_close.parquet
│   └── fx_to_eur.parquet
│
├── outputs/                     ← Files generated by the program
│   ├── report_metrics.json      ← Full-period performance metrics
│   ├── report_daily.csv         ← Daily time series
│   ├── report_rolling.csv       ← Rolling metrics on 180-day window
│   ├── reconcile_lastday_by_ticker.csv  ← Current holdings by ticker
│   ├── contrib_daily.csv        ← Daily contribution by ticker
│   ├── contrib_total.csv        ← Total contribution by ticker
│   ├── contrib_by_year.csv      ← Yearly contribution by ticker
│   └── charts/
│       ├── equity_port_vs_sp500tr.png   ← Equity curve
│       ├── drawdown_portfolio.png       ← Drawdown
│       ├── contrib_total_top10.png      ← Top 10 contributors
│       ├── rolling_sharpe.png           ← Rolling Sharpe ratio
│       ├── rolling_vol.png              ← Rolling volatility
│       └── rolling_beta.png             ← Rolling beta
│
└── src/                         ← Source code
    ├── main.py                  ← Main entry point
    ├── config.py                ← Constants and paths
    ├── io_fineco.py             ← Fineco file parsing
    ├── market_data.py           ← Price and FX downloads from Yahoo Finance
    ├── portfolio_engine.py      ← Positions, cash and return calculations
    ├── attribution.py           ← Per-ticker performance attribution
    ├── metrics.py               ← Risk/return metrics including rolling
    └── viz.py                   ← Chart generation

How to Use

1. Prepare the input files

data/isin_ticker.csv — maps each security from its ISIN to its Yahoo Finance ticker:

isin,ticker
IE0031442068,IUSA.MI
US0378331005,AAPL

To find the correct ticker: go to finance.yahoo.com, search by security name or ISIN, and use the symbol shown.

data/external_cashflows.csv — every deposit or withdrawal on the account:

date,amount_eur,type
2020-09-16,3000,DEPOSIT
2021-03-01,2000,DEPOSIT
2022-01-10,-500,WITHDRAWAL

Deposits = positive numbers. Withdrawals = negative numbers. The type column is optional but recommended for readability.

Timing note: the analysis starts from the first trade in the Fineco ledger, not from the first deposit. Funds deposited before the first trade are automatically carried forward to the first available trading day.

data/Lista_Titoli.xlsx — exported directly from Fineco: Go to "Dossier Titoli" → "Movimenti" → export to Excel.

2. Run the program

python -m src.main

3. Refresh data

rm cache/prices_close.parquet cache/fx_to_eur.parquet
python -m src.main

Output Files Explained

report_metrics.json

All performance metrics computed over the full historical period.

report_rolling.csv

Metrics computed on a rolling 180-trading-day window (~9 months). Contains:

  • rolling_sharpe_180d — Sharpe ratio over the last 180 days
  • rolling_vol_port_180d — portfolio volatility over the last 180 days
  • rolling_vol_bench_180d — benchmark volatility over the last 180 days
  • rolling_beta_180d — portfolio beta vs S&P 500 over the last 180 days

report_daily.csv

One row per trading day with:

  • mv_total_eur — total portfolio value (assets + cash)
  • mv_assets_eur — asset value only (excluding cash)
  • cash_eur — available cash balance
  • external_flows_eur — deposits/withdrawals on that day
  • port_ret / bench_ret — daily return for portfolio and benchmark
  • port_eq / bench_eq — equity curve (indexed to 1.0)

reconcile_lastday_by_ticker.csv

A snapshot of the portfolio on the last available trading day. Compare against your Fineco balance to verify data accuracy.

contrib_by_year.csv

Per-ticker contribution to total return, year by year. is_partial_year = True flags incomplete years (e.g. current year): the figure shown is YTD, not annualized.


Metrics Explained

Return

Metric What it measures
port_ann_return Portfolio CAGR. Compounded average yearly growth rate.
bench_ann_return Same calculation for the S&P 500 Total Return benchmark.
xirr_mwr Return from the investor's perspective, accounting for deposit timing.

Risk

Metric What it measures
port_ann_vol Annualized volatility. How much daily returns fluctuate.
port_max_drawdown Largest peak-to-trough loss across the entire history.

Risk-Adjusted Performance

Metric What it measures Good if...
port_sharpe Excess return divided by total volatility. > 1.0
port_sortino Like Sharpe but penalizes only downside volatility. > 1.0
port_calmar Annualized return divided by absolute max drawdown. > 1.0

Active Metrics (portfolio vs benchmark)

Metric What it measures
tracking_error How much daily returns deviate from the S&P 500.
information_ratio Active return divided by tracking error. Negative = underperforming benchmark.

CAPM

Metric What it measures
capm_beta Market sensitivity. Beta 0.67 = portfolio moves ~6.7% for every 10% market move.
capm_alpha_annual Return above what the beta level would predict.
capm_r2 Share of portfolio movement explained by the S&P 500.

Rolling Metrics (180-day window)

Rolling metrics show how the risk/return profile has changed over time, rather than collapsing everything into a single number for the full period.

Metric What it shows
rolling_sharpe_180d Periods of strong/weak risk-adjusted performance.
rolling_vol_port_180d High/low volatility regimes in the portfolio.
rolling_vol_bench_180d S&P 500 volatility over the same period (for comparison).
rolling_beta_180d Whether the portfolio is becoming more or less market-sensitive over time.

Code Architecture

The program follows a linear 14-step pipeline (see main.py):

Input (Fineco + CSV files)
    ↓
Yahoo Finance price download
    ↓
Trading calendar construction
    ↓
Cash flow alignment
(pre-first-trade deposits carried forward to first trading day)
    ↓
Currency conversion → EUR
    ↓
Portfolio Engine
  ├── Daily positions (shares held per ticker per day)
  ├── Daily cash (trades + external deposits)
  └── Market value + TWR returns
    ↓
Full-period performance metrics
    ↓
Rolling metrics (180-day window)
    ↓
Per-ticker attribution
    ↓
Charts and output files

Technical Notes

Forward fill capped at 5 days: missing prices are propagated for a maximum of 5 days. Beyond that threshold, the value becomes NaN to flag the issue explicitly.

Cash flow timing assumption: external deposits are assumed to arrive at end of day, the standard convention when intraday timing is unavailable.

Pre-calendar deposits: funds deposited before the first trade are automatically accumulated and assigned to the first available trading day.

Dividends: cash dividends increase the portfolio's cash balance. If Fineco reinvests them automatically they appear as BUY transactions — both cases are handled correctly.


Dependencies

pip install pandas numpy scipy yfinance matplotlib openpyxl pyarrow

Future Improvements & Roadmap

This project is designed as a continuously evolving system. The following enhancements are planned to improve scalability, robustness, and real-world usability.

1. Data Infrastructure & Storage

Replace flat files (.csv, .xlsx, .parquet) with a structured database: SQLite (local lightweight setup), PostgreSQL (production-ready),

Build a proper data schema for: Transactions (ledger), Market prices, FX rates, Portfolio snapshots, Enable incremental updates instead of full reprocessing, Add versioning for historical data consistency.

2. Automated Data Pipelines

Automate data ingestion from broker statements: Scheduled jobs (daily/weekly refresh), Auto-detection of new transactions.

Replace manual Yahoo Finance pulls with: Cached API layer, Retry + validation mechanisms Introduce logging and monitoring for pipeline reliability

3. Multi-Broker & Multi-Asset Support

Extend support beyond Fineco to: Zerodha / Groww / Interactive Brokers Add new asset classes: Mutual funds / ETFs (full support) Bonds and fixed income instruments Crypto assets (via exchange APIs) Standardize a universal transaction schema across brokers

4. Portfolio Features & Analytics

Add advanced analytics: Factor exposure (Fama-French factors) Sector allocation & drift tracking Performance attribution (allocation vs selection effect) Risk enhancements: Value at Risk (VaR) / Conditional VaR Stress testing (market crash scenarios) Benchmark flexibility: Custom benchmarks (NIFTY, sector indices, blended benchmarks)

5. Performance Optimization

Optimize heavy computations using: Vectorization improvements in pandas/numpy Optional use of Polars for faster data processing Introduce caching layers for: Computed metrics Intermediate datasets Parallelize data fetching and processing where applicable 6. User Interface & Visualization Build an interactive dashboard using: Streamlit or Dash Features: Portfolio overview (P&L, allocation, drawdown) Interactive charts (zoom, filter by ticker/time) Real-time metric updates Export reports in user-friendly formats (PDF / HTML dashboards)

7. Backtesting & Strategy Layer

Extend the system into a backtesting engine: Strategy simulation on historical data Comparison of multiple strategies vs actual portfolio Add support for: Rebalancing strategies Dollar-cost averaging simulations Factor-based portfolios

8. Testing & Code Quality

Add comprehensive unit and integration tests: Portfolio engine validation Cash flow and return calculations Introduce CI/CD pipeline: Automated testing on every commit Improve documentation: Function-level docstrings Type validation and stricter schemas (e.g., pydantic)

9.. API Layer & Integration

Expose core functionality via a REST API: Portfolio metrics endpoint Time-series data endpoint Enable integration with: Frontend dashboards External applications

10. Real-World Production Readiness

Add configuration management (env-based configs) Implement robust error handling and alerts Secure handling of sensitive data (API keys, financial data) Prepare for deployment: Docker containerization Cloud deployment (AWS/GCP) Long-Term Vision

The long-term goal is to evolve this project from a personal analytics tool into a modular portfolio analytics platform, capable of:

Handling institutional-grade data pipelines Supporting multiple users and portfolios Providing real-time analytics and insights Bridging the gap between finance theory and production systems

About

Portfolio Analytics is a data-driven tool that helps users track, evaluate, and optimize investment portfolios using metrics like returns, volatility, and risk-adjusted performance, combined with data visualization to deliver actionable insights.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages