A Python framework for hierarchical B2B sales quota cascading and pipeline reconciliation.
Project description
B2B Revenue Forecasting (b2b_revenue_forecasting)
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 withdiagnose()andadjust()modes- Flexible quarter support:
QuotaCascadernow auto-discovers any number of_Attainmentcolumns (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_overridesto 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 donate quota |
| ≥ at_risk threshold | 🟡 Moderate | No action |
| ≥ 1.0 | 🟠 At Risk | May receive quota |
| < 1.0 | 🔴 Critical | Urgent — pipeline below target |
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
📋 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!
- Report bugs: GitHub Issues
- Source code: GitHub
📄 License
MIT License — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file b2b_revenue_forecasting-0.2.1.tar.gz.
File metadata
- Download URL: b2b_revenue_forecasting-0.2.1.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d7c6a33e982fd316aa340a91fbe28d3b750ebe60589c4a51d3ca65d8f442aba
|
|
| MD5 |
249b86a83da882abbac5eb5aed7b6f35
|
|
| BLAKE2b-256 |
9f93eee4c785cc4143c397aa74d522afe28f5a88f180f7e2d554f490e1b3acc1
|
File details
Details for the file b2b_revenue_forecasting-0.2.1-py3-none-any.whl.
File metadata
- Download URL: b2b_revenue_forecasting-0.2.1-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c30763c9033bb6a7030823ccad9e0624eede6eb02b6581c13c1f4ecc7b52726d
|
|
| MD5 |
c54b40d3ee5c031693693ceb15c03d4f
|
|
| BLAKE2b-256 |
bad7ba8884caae6080e4fddf0de776b755f32225fb22d7912342d30acc7551e0
|