Skip to main content

IndexMaker

A domain-driven Python module for creating, managing, and analyzing financial indices. Designed for index professionals.

CI PyPI version Python 3.9+ Code style: black Ruff License: MIT

Features

  • 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

Installation

From PyPI

pip install indexforge

Using Poetry (Development)

# Clone the repository
git clone https://github.com/reubencapio/indexforge.git
cd indexforge

# Install with Poetry
poetry install

# Activate the virtual environment
poetry shell

From Source

# Install from GitHub
pip install git+https://github.com/reubencapio/indexforge.git

Quick Start

Create a Simple Index

from 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%}")

Market Cap Weighted Index with Caps

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}")

Using Custom Data Source

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)

Architecture

┌──────────────────────────────────────────────────────────┐
│                    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.)    │
└──────────────────────────────────────────────────────────┘

Core Concepts

1. Index

The main entry point. Represents a financial index.

2. Universe

Defines which securities are eligible for inclusion (asset class, region, market cap, etc.)

3. SelectionCriteria

How constituents are chosen from the universe (top N by factor, composite scoring, etc.)

4. WeightingMethod

How constituents are weighted (equal, market cap, factor-based, custom)

5. RebalancingSchedule

When the index is updated (quarterly, monthly, annual)

6. DataProvider

Abstraction for market data - swap between free and proprietary sources

Examples

See the examples/ directory:

  • simple_index.py - Basic equal-weighted index
  • market_cap_index.py - Full-featured market cap weighted index
  • custom_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

Development

# 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/indexmaker

Or 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 + Test

Project Structure

indexmaker/
├── 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

Key Design Principles

  1. Domain Language: API uses industry terminology (constituents, rebalancing, weighting)
  2. Data Source Agnostic: Core logic separated from data fetching
  3. Type Safety: Full type hints and validation
  4. Builder Pattern: Fluent configuration for complex objects
  5. Testability: Components can be tested in isolation

Documentation

Requirements

  • Python 3.9+
  • pandas >= 2.0.0
  • numpy >= 1.24.0
  • yfinance >= 0.2.0 (for free data)

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please read the contributing guidelines first.

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new functionality
  4. Submit a pull request

Acknowledgments

Inspired by industry-standard index methodologies.

Metadata

Release files for indexforge 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for indexforge 0.1.5
File Size Uploaded
indexforge-0.1.5.tar.gz 57.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for indexforge 0.1.5
File Interpreter ABI Platform
indexforge-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 125.2 kB

Release files / indexforge-0.1.5.tar.gz

Download URL indexforge-0.1.5.tar.gz
Size 57.8 kB
Tags Source
SHA-256 checksum
How to use checksums
456de8690ba50fe23172857ed5ecc5757a753d7d7b1bb76257fa66eb915d26fc
BLAKE2b-256 checksum
How to use checksums
9c0e3eb4c680d9d604618bb4f06da1b9bf00afacb1755fad1d975caaa429031a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 24, 2026.

Transparency log

Release files / indexforge-0.1.5-py3-none-any.whl

Download URL indexforge-0.1.5-py3-none-any.whl
Size 67.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ca78ec7441ecb5601108fdb6bbab63f7d40f894e538178d89a75a5e63fa73411
BLAKE2b-256 checksum
How to use checksums
1e14705780c8fbc9f62f7492b768f8cf8861a289915b343c54486d82b5aadca2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page