--- description: This document explains the system architecture and data flow of the Folio application globs: * alwaysApply: true --- # Folio Project Design This document outlines how the Folio codebase is structured and how data flows through the application. Folio provides tools for analyzing and visualizing investment portfolios, with a focus on stocks and options, through both a web-based dashboard and a command-line interface (CLI). ## Application Overview Folio is a Python-based application that provides comprehensive portfolio analysis capabilities through multiple interfaces: 1. **Web Interface**: A Dash-based web application for visualizing portfolio data 2. **CLI Interface (`focli`)**: A command-line interface for portfolio analysis and simulation Both interfaces leverage the same core library (`src/folio/`) for business logic, following our [strict separation of concerns](#separation-of-concerns) principles. The primary domain entities for this app are outlined below. For an authoritative overview of the data model, [data_model.py](src/folio/data_model.py) is the source of truth. ## Deployment Modes Folio can run in multiple deployment environments: - **Local Development**: Running directly on a developer's machine - **Docker Container**: Running in a containerized environment - **Hugging Face Spaces**: Deployed as a Hugging Face Space for public access The application detects its environment and adjusts settings accordingly, such as cache directories and logging behavior. ## Core Data Model The core data model consists of several key classes that represent portfolio components: - **Position**: Base class for all positions - **StockPosition**: Represents a stock position with quantity, price, beta, etc. - **OptionPosition**: Represents an option position with strike, expiry, option type, delta, etc. - **PortfolioGroup**: Groups a stock with its related options (e.g., AAPL stock with AAPL options) - **PortfolioSummary**: Contains aggregated metrics for the entire portfolio - **ExposureBreakdown**: Detailed breakdown of exposure metrics by category These classes are defined in [data_model.py](src/folio/data_model.py) and provide the foundation for all portfolio analysis. ## Data Flow The data flow in Folio follows these main steps: 1. **Data Input**: User uploads a portfolio CSV file or loads a sample portfolio 2. **Data Processing**: The CSV is parsed, validated, and transformed into structured portfolio data 3. **Position Grouping**: Stocks and their related options are grouped together 4. **Metrics Calculation**: Exposure, beta, and other metrics are calculated for each position and group 5. **Visualization**: The processed data is displayed in the dashboard with charts and tables 6. **Interactivity**: User interactions trigger callbacks that update the displayed data ### CSV Processing When a user uploads a CSV file, the following process occurs: 1. The file is validated for security in [security.py](src/folio/security.py) 2. The CSV is parsed into a pandas DataFrame 3. The DataFrame is processed by `process_portfolio_data()` in [portfolio.py](src/folio/portfolio.py) 4. Stock positions are identified and processed 5. Option positions are parsed and matched to their underlying stocks 6. Cash-like positions are identified using [cash_detection.py](src/folio/cash_detection.py) 7. Portfolio groups and summary metrics are calculated ### Stock Data Fetching Folio uses a pluggable data fetching system to retrieve stock data: 1. A `DataFetcherInterface` defined in [stockdata.py](src/stockdata.py) provides a common interface 2. Concrete implementations include `YFinanceDataFetcher` and `FMP` (Financial Modeling Prep) fetchers 3. A singleton pattern ensures only one data fetcher is created throughout the application 4. The data source can be configured at runtime through the `folio.yaml` configuration file 5. Data is cached to improve performance and reduce API calls ### Options Processing Option positions require special processing: 1. Option descriptions are parsed in [options.py](src/folio/options.py) to extract strike, expiry, and option type 2. QuantLib is used for option pricing and Greeks calculations 3. Delta exposure is calculated as delta * notional value 4. Options are matched to their underlying stocks to form portfolio groups 5. Option metrics are aggregated into the portfolio summary ### Portfolio Metrics Calculation Portfolio metrics are calculated in several steps: 1. Individual position metrics are calculated first (market value, beta, exposure) 2. Positions are grouped by underlying ticker 3. Group-level metrics are calculated (net exposure, beta-adjusted exposure) 4. Portfolio-level metrics are calculated (total exposure, portfolio beta, etc.) 5. Exposure breakdowns are created for visualization The canonical implementations for these calculations are in [portfolio_value.py](src/folio/portfolio_value.py). ## Web UI Components The web UI is built with Dash and consists of several key components: 1. **Summary Cards**: Display high-level portfolio metrics 2. **Charts**: Visualize portfolio allocation and exposure 3. **Portfolio Table**: Display all positions with key metrics 4. **Position Details**: Show detailed information for a selected position 5. **P&L Chart**: Visualize profit/loss scenarios for options strategies Each component is defined in the [components](src/folio/components) directory and registered with callbacks in [app.py](src/folio/app.py). ### Component Interaction Components interact through Dash callbacks: 1. Data is stored in `dcc.Store` components that act as a client-side state 2. User interactions trigger callbacks that update the stored data 3. Components subscribe to changes in the stored data and update accordingly 4. This pattern allows for a reactive UI without page reloads ## CLI Interface The CLI interface (`focli`) provides a command-line tool for portfolio analysis and simulation: ### Architecture 1. **Shell**: An interactive shell implemented in [shell.py](src/focli/shell.py) using the `cmd` module 2. **Commands**: Command handlers in the [commands](src/focli/commands) directory 3. **Formatters**: Output formatting utilities in [formatters.py](src/focli/formatters.py) 4. **Utils**: CLI-specific utilities in [utils.py](src/focli/utils.py) ### Command Structure The CLI follows a command-subcommand structure: ``` folio> command [subcommand] [options] ``` Key commands include: - `simulate`: Simulate portfolio performance with SPY changes - `position`: Analyze a specific position group - `portfolio`: View and analyze portfolio data ### Separation of Concerns The CLI strictly adheres to the [separation of concerns](#separation-of-concerns) principles: - Command handlers only handle parsing, validation, and presentation - All business logic is delegated to the core library - No calculation or simulation logic exists in the CLI layer ## Key Modules ### Core Library (src/folio/) #### Data Processing - **portfolio.py**: Core portfolio processing logic - **portfolio_value.py**: Canonical implementations of portfolio value calculations - **simulator.py**: Portfolio and position simulation logic - **options.py**: Option pricing and Greeks calculations - **cash_detection.py**: Identification of cash-like positions #### Data Fetching - **stockdata.py**: Common interface for data fetchers - **yfinance.py**: Yahoo Finance data fetcher - **fmp.py**: Financial Modeling Prep data fetcher #### Application Core - **data_model.py**: Core data structures - **logger.py**: Logging configuration - **security.py**: Security utilities for validating user inputs ### Web UI (src/folio/) #### UI Components - **components/**: UI components for the dashboard - **charts.py**: Portfolio visualization charts - **portfolio_table.py**: Table of portfolio positions - **position_details.py**: Detailed view of a position - **pnl_chart.py**: Profit/loss visualization - **summary_cards.py**: High-level portfolio metrics #### Web Application - **app.py**: Main Dash application setup and callbacks ### CLI Interface (src/focli/) #### Command Handling - **shell.py**: Interactive shell implementation - **commands/**: Command handlers - **simulate.py**: Portfolio simulation commands - **position.py**: Position analysis commands - **portfolio.py**: Portfolio management commands #### Presentation - **formatters.py**: Output formatting utilities - **utils.py**: CLI-specific utilities (no business logic) ## Configuration Folio uses a YAML configuration file (`folio.yaml`) for runtime settings: - **Data Source**: Configure which data source to use (Yahoo Finance or FMP) - **Cache Settings**: Configure cache directories and TTL - **UI Settings**: Configure dashboard appearance and behavior The configuration is loaded at startup and can be overridden by environment variables. ## Error Handling Folio implements robust error handling: 1. **Fail Fast, Fail Transparently**: Errors are raised early and clearly 2. **Graceful Degradation**: The application continues to function even if some components fail 3. **Structured Logging**: Errors are logged with context for debugging 4. **User Feedback**: Error messages are displayed to the user when appropriate ## Testing The codebase includes comprehensive tests: - **Unit Tests**: Test individual functions and classes - **Integration Tests**: Test interactions between components - **Mock Data**: Use mock data for testing to avoid API calls Tests are organized to mirror the structure of the source code, with test files corresponding to source files. ## Development Workflow To add new features to Folio: 1. **UI Components**: Add new components in the `components/` directory 2. **Data Processing**: Extend the data model in `data_model.py` and processing logic in `utils.py` 3. **Callbacks**: Add new callbacks in `app.py` to handle user interactions 4. **Testing**: Add tests for new functionality ## Separation of Concerns Folio strictly adheres to separation of concerns principles: ### Core Library vs Interface Layers 1. **Core Library (`src/folio/`)**: - Contains ALL business logic, data processing, and calculation functionality - Provides a stable API for interface layers to use - Should never depend on interface-specific code 2. **Interface Layers (`src/focli/`, web UI)**: - Handle user interaction, command parsing, and result presentation - Call core library functions to perform business operations - Should NEVER contain business logic - Focus solely on translating user inputs to core library calls and formatting outputs ### Business Logic Placement Business logic must ALWAYS reside in the core library, not in interface layers. Examples include: - Calculations and algorithms - Data transformations - Simulation logic - Portfolio analysis - Value calculations Interface layers should be thin wrappers around the core library, focusing only on: - Parsing user input - Calling appropriate core library functions - Formatting and presenting results - Managing UI state ## Conclusion Folio is designed with a clean separation of concerns: - Business logic is centralized in the core library - Data fetching is abstracted behind interfaces - Data processing is separated from UI components - UI components are modular and reusable - Configuration is externalized for flexibility - Interface layers are thin and focused on user interaction This architecture makes the codebase maintainable, testable, and extensible, allowing for easy addition of new features and improvements.