Skip to main content

A Python framework for hierarchical B2B sales quota cascading and pipeline reconciliation.

Project description

B2B Revenue Forecasting (b2b_revenue_forecasting)

PyPI version Tests License: MIT Python 3.8+

An open-source Python framework designed mathematically for Enterprise RevOps and Data Strategy teams.

Unlike traditional bottom-up time-series libraries (which are strictly built for B2C retail/inventory forecasting and rely on mathematical averages), this package is explicitly architected to handle the realities of B2B enterprise sales: Hierarchical Quotas, Managerial Cascading, Pipeline Health Analysis, and "Sandbagging" Biases.


🚀 Features

Module Purpose
SalesHierarchy Build flexible org charts as DAGs from flat CRM data — supports 3-level startups to 10-level enterprises
QuotaCascader Distribute macro-targets top-down using rolling N-quarter capacity models with configurable managerial hedges
CommitReconciler Detect sandbagging and "happy ears" bias via historical Bias Quotients, then auto-correct forecasts
PipelineAdjuster Diagnose pipeline health with per-region thresholds and redistribute IC quotas using zero-sum logic

What's New in v0.2.0

  • PipelineAdjuster: Post-cascade pipeline health analyzer with diagnose() and adjust() modes
  • Flexible quarter support: QuotaCascader now auto-discovers any number of _Attainment columns (4, 8, 12 quarters)
  • New IC handling: Partial-history imputation and equal-share allocation for brand-new hires
  • CRO overrides: Lock specific IC quotas via new_ic_overrides to bypass the algorithm
  • Per-node hedging: Apply different hedge multipliers to different regions/managers
  • GitHub Actions CI/CD: Automated testing on Python 3.9–3.12

📦 Installation

pip install b2b-revenue-forecasting

💻 Quickstart

1. Build the Org Hierarchy

import pandas as pd
from b2b_revenue_forecasting.hierarchy import SalesHierarchy

# ⚠️ Use keep_default_na=False if your data has 'NA' as a region name
df = pd.read_csv('your_crm_data.csv', keep_default_na=False)

# Works with any depth: 3 levels or 10 levels
hierarchy = SalesHierarchy()
hierarchy.from_dataframe(
    df, 
    path_cols=['Global', 'Region', 'RVP', 'Director', 'Manager', 'IC'], 
    metrics_cols=['Q1_Attainment', 'Q2_Attainment', 'Q3_Attainment', 'Q4_Attainment',
                  'Current_Pipeline']
)

print(f"Nodes: {len(hierarchy.graph.nodes)}")
print(f"ICs:   {len(hierarchy.get_leaves('Global_Corp'))}")

2. Cascade Quotas Top-Down

from b2b_revenue_forecasting.quota_cascader import QuotaCascader

cascader = QuotaCascader(hierarchy)

# Basic: distribute $100M evenly by historical capacity
quotas = cascader.cascade_quota('Global_Corp', 100_000_000.0)

# With 5% hedge at every management level (compounds: 1.05^5 ≈ 27.6% overassignment)
quotas = cascader.cascade_quota('Global_Corp', 100_000_000.0, hedge_multiplier=1.05)

# Per-node hedge: NA gets aggressive 10%, others standard 5%
quotas = cascader.cascade_quota('Global_Corp', 100_000_000.0, hedge_multiplier={
    'Global_Corp': 1.05, 'NA': 1.10, 'EMEA': 1.05, 'APAC': 1.05
})

# CRO override: strategic hire gets exactly $500K regardless of history
quotas = cascader.cascade_quota('Global_Corp', 100_000_000.0,
    hedge_multiplier=1.05,
    new_ic_overrides={'IC_Strategic_Hire': 500_000.0}
)

3. Detect & Fix Forecasting Bias

from b2b_revenue_forecasting.commit_reconciler import CommitReconciler

historical = pd.DataFrame({
    'Manager_ID':              ['Mgr_A', 'Mgr_A', 'Mgr_B', 'Mgr_B'],
    'Historical_Commit':       [200_000,  250_000, 300_000,  350_000],
    'Historical_Actual_Closed': [300_000,  375_000, 270_000,  280_000],
})

reconciler = CommitReconciler(historical)

# Mgr_A is a sandbagger (bias = 1.5x) — commit inflated automatically
adjusted = reconciler.reconcile_forecast('Mgr_A', current_commit=100_000)
# → $150,000

# Blend with ML baseline (50/50 average)
blended = reconciler.reconcile_forecast('Mgr_A', 100_000, machine_forecast=120_000)
# → $135,000

4. Pipeline Health Diagnosis & Redistribution

from b2b_revenue_forecasting.pipeline_adjuster import PipelineAdjuster

adjuster = PipelineAdjuster(hierarchy, quotas, pipeline_attr='Current_Pipeline')

# Configure per-region coverage thresholds (ICs inherit from ancestors)
thresholds = {
    'NA':       {'healthy': 1.5, 'at_risk': 0.8},
    'EMEA':     {'healthy': 2.5, 'at_risk': 1.2},
    'APAC':     {'healthy': 3.0, 'at_risk': 1.5},
    '_default': {'healthy': 2.0, 'at_risk': 1.0}
}

# Diagnose — returns a DataFrame with risk status for every node
diagnosis = adjuster.diagnose(thresholds)
print(diagnosis.groupby('Risk_Status')['Node'].count())

# Flag-only mode — returns original quotas unchanged (for pre-approval review)
flagged = adjuster.adjust(mode='flag_only', coverage_thresholds=thresholds)

# Redistribute mode — zero-sum IC adjustment within each manager's team
adjusted = adjuster.adjust(
    mode='redistribute',
    coverage_thresholds=thresholds,
    max_adjustment_pct=0.20,                          # ±20% cap per IC
    locked_nodes={'IC_Protected': 500_000.0}           # CRO-locked ICs excluded
)
# ✅ Manager totals preserved | ✅ Donors give, receivers get | ✅ 20% cap enforced

🧠 Key Concepts

Managerial Hedge (Overassignment Buffer)

A multiplier applied at each management level to create mathematical safety. A 5% hedge across 5 layers compounds to ~27.6% total overassignment (1.05⁵), ensuring the enterprise hits its number even if some ICs miss.

Bias Quotient

Bias Quotient = Σ(Actual Closed) / Σ(Committed)
  • > 1.0 = Sandbagger (closes more than committed → inflate their forecast)
  • = 1.0 = Neutral
  • < 1.0 = Happy Ears (over-promises → deflate their forecast)

Pipeline Coverage Ratio

Coverage = Current Pipeline / Cascaded Quota
Coverage Status Action
≥ healthy threshold 🟢 Healthy May receive quota
≥ at_risk threshold 🟡 Moderate No action
≥ 1.0 🟠 At Risk May donate quota
< 1.0 🔴 Critical Urgent — pipeline below target (May donate quota)

New IC Handling

Scenario Behavior
Full history Proportional by total capacity
Partial history (e.g., 1 of 4 quarters) Zero quarters imputed with own non-zero average
Brand new (all zeros) Equal share of team target
CRO override Fixed amount, excluded from pool

🧪 Testing

# Run all tests
cd hierarchical_sales_forecasting
pip install -e .
python -m pytest tests/ -v

# Run the full demo
python demo_full_pipeline.py

📄 Publications

This framework is the subject of peer-reviewed research and technical publications:

Publication Venue Status
Hierarchical Sales Target Cascading using DAGs in Python Towards AI ✅ Published
Graph-Theoretic Approaches to Hierarchical Revenue Target Allocation in B2B Enterprises SSRN (Preprint) ✅ Published
Graph-Theoretic Approaches to Hierarchical Revenue Target Allocation in B2B Enterprises Journal of Revenue and Pricing Management (Springer) ⏳ Under Review

If you use this package in your research, please cite:

Karwa, S. (2026). Graph-Theoretic Approaches to Hierarchical Revenue Target Allocation
in B2B Enterprises: A Methodological Framework. SSRN Working Paper. https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6626318

📋 Requirements

  • Python ≥ 3.8
  • pandas ≥ 1.0.0
  • networkx ≥ 2.5
  • numpy ≥ 1.19.0

🤝 Contributing

Built explicitly for RevOps analysts, Data Scientists, and VP Revenue Operations executing scaling go-to-market strategies. Contributions, issues, and pull requests are warmly welcomed!


📄 License

MIT License — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

b2b_revenue_forecasting-0.2.4.tar.gz (21.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

b2b_revenue_forecasting-0.2.4-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file b2b_revenue_forecasting-0.2.4.tar.gz.

File metadata

  • Download URL: b2b_revenue_forecasting-0.2.4.tar.gz
  • Upload date:
  • Size: 21.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for b2b_revenue_forecasting-0.2.4.tar.gz
Algorithm Hash digest
SHA256 088ea61eb7e6415f735702965dc739f5b00fba08140300ff36ba5abf9ca06fd0
MD5 701bb5203f840e77cccf668b02370f58
BLAKE2b-256 de776c6b5e2082f49b6f1175b87f8d876715aed3c759f64f8baa8a9025175aae

See more details on using hashes here.

File details

Details for the file b2b_revenue_forecasting-0.2.4-py3-none-any.whl.

File metadata

File hashes

Hashes for b2b_revenue_forecasting-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 b63e6f50f8f7d6d47e0c643616c6d7d3aa22e73417ee0f4d2b97792c13b38f91
MD5 4b69002278da0c32c66b2f1ec9f03077
BLAKE2b-256 fa6e622d41129f6230ce29450e253169de0d1026e456a5e13032406a377e3c43

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page