A domain-driven Python module for creating, managing, and analyzing financial indices. Designed for index professionals.
- Domain-Driven Design: API uses terminology familiar to index professionals
- Fluent Interface: Chainable methods for intuitive configuration
- Type-Safe: Full type hints for IDE support and early error detection
- Interchangeable Data Sources: Easily swap between free (Yahoo Finance) and proprietary data
- Production-Ready: Includes validation, backtesting, and comprehensive testing
pip install indexforge# Clone the repository
git clone https://github.com/reubencapio/indexforge.git
cd indexforge
# Install with Poetry
poetry install
# Activate the virtual environment
poetry shell# Install from GitHub
pip install git+https://github.com/reubencapio/indexforge.gitfrom indexforge import Index, Universe, WeightingMethod, Currency
# Create an index
index = Index.create(
name="Tech Leaders Index",
identifier="TECHLDRS",
currency=Currency.USD,
base_date="2025-01-01",
base_value=1000.0
)
# Define the universe
universe = Universe.from_tickers(["AAPL", "MSFT", "GOOGL", "AMZN", "META"])
# Configure
index.set_universe(universe)
index.set_weighting_method(WeightingMethod.equal_weight())
# Get constituents
constituents = index.get_constituents(date="2025-11-15")
for c in constituents:
print(f"{c.ticker}: {c.name} - {c.weight:.2%}")from indexforge import (
Index, Universe, SelectionCriteria, WeightingMethod,
RebalancingSchedule, Currency, Factor
)
# Create the index
index = Index.create(
name="Tech Leaders Index",
identifier="TECHLDRS",
currency=Currency.USD,
base_date="2025-01-01",
base_value=1000.0
)
# Define universe with criteria
universe = (Universe.builder()
.asset_class("EQUITIES")
.sectors(["Technology"])
.min_market_cap(1_000_000_000)
.build()
)
# Select top 50 by market cap
selection = (SelectionCriteria.builder()
.ranking_by(Factor.MARKET_CAP)
.select_top(50)
.apply_buffer_rules(add_threshold=45, remove_threshold=60)
.build()
)
# Market cap weighting with 10% cap
weighting = (WeightingMethod.market_cap()
.with_cap(max_weight=0.10)
.build()
)
# Quarterly rebalancing
rebalancing = RebalancingSchedule.quarterly()
# Configure the index
(index
.set_universe(universe)
.set_selection_criteria(selection)
.set_weighting_method(weighting)
.set_rebalancing_schedule(rebalancing)
)
# Backtest
result = index.backtest(
start_date="2024-01-01",
end_date="2024-12-31"
)
print(f"Sharpe Ratio: {result.sharpe_ratio:.2f}")from indexmaker import DataConnector, DataProvider, Constituent
import pandas as pd
class MyDataConnector(DataConnector):
"""Your custom data source."""
def get_prices(self, tickers, start_date, end_date):
# Fetch from your database/API
return pd.DataFrame(...)
def get_constituent_data(self, tickers, as_of_date=None):
# Return list of Constituent objects
return [Constituent(ticker=t, ...) for t in tickers]
def get_market_cap(self, tickers, as_of_date=None):
return {t: market_cap for t in tickers}
# Use custom data
provider = (DataProvider.builder()
.add_source("mydata", MyDataConnector())
.set_default("mydata")
.build()
)
index.set_data_provider(provider)┌──────────────────────────────────────────────────────────┐
│ User API Layer │
│ Index.create() → set_universe() → calculate() │
├──────────────────────────────────────────────────────────┤
│ Domain Model Layer │
│ Index │ Universe │ Constituent │ SelectionCriteria │
├──────────────────────────────────────────────────────────┤
│ Strategy Layer │
│ WeightingMethod │ RebalancingSchedule │ Validation │
├──────────────────────────────────────────────────────────┤
│ Data Layer │
│ DataProvider → DataConnector (Yahoo, Custom, etc.) │
└──────────────────────────────────────────────────────────┘
The main entry point. Represents a financial index.
Defines which securities are eligible for inclusion (asset class, region, market cap, etc.)
How constituents are chosen from the universe (top N by factor, composite scoring, etc.)
How constituents are weighted (equal, market cap, factor-based, custom)
When the index is updated (quarterly, monthly, annual)
Abstraction for market data - swap between free and proprietary sources
See the examples/ directory:
simple_index.py- Basic equal-weighted indexmarket_cap_index.py- Full-featured market cap weighted indexcustom_data_source.py- Using your own data source
Run examples:
poetry run python examples/simple_index.py
poetry run python examples/market_cap_index.py
poetry run python examples/custom_data_source.py# Install dependencies
poetry install
# Run all tests
poetry run pytest
# Run with coverage
poetry run pytest --cov=indexmaker
# Format code
poetry run black src/ tests/ examples/
# Lint code
poetry run ruff check src/ tests/ examples/
# Type check
poetry run mypy src/indexmakerOr use the Makefile shortcuts:
make test # Run tests
make coverage # Tests with coverage
make format # Format with Black
make lint # Run Ruff + Mypy
make all # Format + Lint + Testindexmaker/
├── src/indexmaker/
│ ├── core/ # Domain models (Index, Universe, Constituent)
│ ├── selection/ # Selection criteria and factors
│ ├── weighting/ # Weighting methods
│ ├── rebalancing/ # Rebalancing schedules
│ ├── data/ # Data providers and connectors
│ └── validation/ # Validation rules
├── tests/ # Unit tests
├── examples/ # Usage examples
└── docs/ # Documentation
- Domain Language: API uses industry terminology (constituents, rebalancing, weighting)
- Data Source Agnostic: Core logic separated from data fetching
- Type Safety: Full type hints and validation
- Builder Pattern: Fluent configuration for complex objects
- Testability: Components can be tested in isolation
- API Design Proposal - Complete API specification
- Quick Reference - Common patterns cheat sheet
- Free Data Sources - Using Yahoo Finance and other free data
- Design Rationale - Why the API is designed this way
- Module Structure - Architecture details
- Python 3.9+
- pandas >= 2.0.0
- numpy >= 1.24.0
- yfinance >= 0.2.0 (for free data)
MIT License - see LICENSE file for details.
Contributions welcome! Please read the contributing guidelines first.
- Fork the repository
- Create a feature branch
- Write tests for new functionality
- Submit a pull request
Inspired by industry-standard index methodologies.