Quantitative library for physically-settled commodity markets.
Project description
sipQuant
Quantitative library for physically-settled commodity markets.
About
sipQuant is a pure-NumPy quantitative stack for building, maintaining, and trading against physically-settled commodity price indices in thin, opaque markets. It covers the full pipeline from raw trade data to OTC structured products.
It is the internal quantitative infrastructure of SIP Global, open-sourced under GPL-3.0. All mathematics are implemented in pure NumPy.
About SIP Global
Systematic Index Partners (SIP Global) brings liquidity to overlooked markets that move the world. We apply systematic rigour and modern trading standards to create transparent pricing, real liquidity, and durable market function in physically-settled commodity markets.
Tota Ad Manum.
Installation
pip install sipQuant
Requires Python 3.10+ and NumPy 1.23+. No other dependencies.
Quick Start
The full SIP pricing pipeline in one block:
import sipQuant as sq
import numpy as np
# 1. Ingest a physical trade
trade = sq.schema.TradeRecord(
date='2026-03-14',
price=187.50,
volume=500.0,
grade='premium_bale_14pct_moisture',
origin='lethbridge_ab',
destination='red_deer_ab',
counterpartyId='CP_ANON_004',
)
assert sq.schema.validate(trade) == []
# 2. Decompose price seasonality (weekly hay prices)
prices = np.array([182.0, 184.5, 187.0, 189.0, 185.5, 183.0, 186.5])
decomp = sq.commodity.seasonality(np.arange(7), prices, period=52)
# 3. Build a local forward curve
fwd = sq.commodity.localForwardCurve(
spotPrice=187.50,
tenor=np.array([0.0, 0.25, 0.50, 0.75, 1.0]),
r=0.046,
convYield=0.028,
storageCost=0.020,
basisAdjustment=-2.50,
)
curve = sq.schema.ForwardCurve(
tenors=fwd['tenors'],
prices=fwd['forwards'],
baseDate='2026-03-14',
market='alberta_hay_premium',
)
# 4. Price a commodity swap against the index curve
swap = sq.otc.commoditySwap(
fixedPrice=190.0,
indexCurve=curve['prices'],
notional=1000.0,
schedule=curve['tenors'],
r=0.046,
)
print(f"Swap NPV: ${swap['npv']:,.2f}")
# 5. Calculate an IOSCO-aligned index
spec = sq.schema.IndexSpec(
name='SIP-AHI-001',
version='1.0',
constituents=['premium_bale_14pct_moisture', 'feed_grade'],
weightsMethod='volume',
rollRule='monthly_last_business_day',
effectiveDate='2026-01-01',
)
result = sq.index.calculateIndex([trade], spec, '2026-03-14')
audit = sq.index.auditTrail(result, spec)
print(f"Index value: {result['indexValue']:.2f} Checksum: {audit['checksum']}")
Design Philosophy
- Pure NumPy — all mathematics implemented without pandas, scipy, or statsmodels
- Vectorised operations — performance-first for simulation-heavy workflows
- Schema-validated inputs — every function accepts validated dict objects from
sipQuant.schema - Lightweight outputs — all functions return plain dicts or NumPy arrays; convert to DataFrame as needed
- Production-ready — IOSCO-aligned audit trail, restatement procedures, and margin estimation built in
Module Reference
Core Commodity Stack
schema — Data Contract Layer
The foundation of sipQuant. Every pricing, risk, and index function accepts schema objects.
| Object | Purpose |
|---|---|
PriceSeries |
Regular price time series (broker quotes, exchange settlements) |
SparsePriceSeries |
Irregular physical trade observations (thin/weekly markets) |
TradeRecord |
Single physical trade (price, volume, grade, origin, destination) |
QuoteSheet |
OTC broker quote with bid/ask/mid and tenor |
ForwardCurve |
Forward curve for pricing and hedging |
OTCPosition |
Live OTC position for dealer book aggregation |
IndexSpec |
Immutable index methodology specification |
validate() |
Universal validation — returns list of error strings |
commodity — Physical Pricing Primitives
| Function | Use Case |
|---|---|
seasonality() |
STL-like decomposition: trend + seasonal + residual |
convenienceYield() |
Implied convenience yield from spot/futures pair |
basis() |
Local cash price minus benchmark reference |
gradeAdjustment() |
Quality-adjusted price from grade factor dict |
transportDifferential() |
Delivered price including logistics costs |
localForwardCurve() |
Forward curve from spot, carry, and convenience yield |
rollingRollCost() |
Roll cost estimated from forward curve shape |
index — IOSCO-Aligned Index Infrastructure
| Function | Use Case |
|---|---|
calculateIndex() |
VWAP-weighted index value from trade records |
auditTrail() |
IOSCO-aligned audit record with checksum |
restatement() |
Documented index correction procedure |
rollSchedule() |
Roll date generation (monthly/weekly/quarterly) |
proxyRegression() |
OLS or Huber regression for sparse-market proxy values |
backtestIndex() |
Historical index values, returns, volatility, drawdown |
otc — OTC Instrument Pricing
| Function | Use Case |
|---|---|
commoditySwap() |
Fixed-float commodity swap NPV and Greeks |
asianSwap() |
Arithmetic average price swap NPV |
collar() |
Long cap + short floor (buyer protection) |
physicalForward() |
PV of a physically-settled forward contract |
swaption() |
Black's formula swaption on forward swap rate |
asianOption() |
Monte Carlo Asian option with antithetic variates |
book — Dealer Book Management
| Function | Use Case |
|---|---|
netGreeks() |
Aggregate Greeks across all positions |
hedgeRatios() |
Delta-hedge units to flatten book delta |
pnlAttribution() |
Taylor expansion P&L decomposition |
scenarioShock() |
Pre-event scenario analysis (WASDE, weather, quota) |
bookSummary() |
Position summary by instrument type |
marginEstimate() |
Initial and variation margin estimation |
liquidity — Thin-Market Risk
| Function | Use Case |
|---|---|
liquidityAdjustedVar() |
LVAR following Bangia et al. |
marketImpact() |
Almgren-Chriss permanent + temporary impact |
optimalExecution() |
AC optimal liquidation schedule |
thinMarketScore() |
Liquidity score [0,1] for market quality assessment |
concentrationRisk() |
HHI position concentration |
optimalLiquidation() |
TWAP/VWAP cost estimation |
Quantitative Toolkit
sim — Price Process Simulation
gbm, ou, levyOu, ar1, arma, markovSwitching, arch, garch, heston, cir, vasicek, poisson, compoundPoisson, simulate
fit — Model Calibration
fitGbm, fitOu, fitLevyOU, fitAr1, fitArma, fitGarch, fitHeston, fitCir, fitVasicek, fitJumpDiffusion, fitCopula, fitDistributions, aic, bic
options — Option Pricing
blackScholes, binomial, trinomial, asian, binary, spread, barrier, simulate, impliedVol, buildForwardCurve, bootstrapCurve
econometrics — Statistical Testing
ols, whiteTest, breuschPaganTest, durbinWatson, ljungBox, adfTest, kpssTest, grangerCausality
bootstrap — Curve & Surface Construction
curve, surface, zeroRateCurve, forwardCurve, discountCurve, yieldCurve, volSurface, creditCurve, fxForwardCurve, inflationCurve
Portfolio & Risk
portfolio — Portfolio Optimisation
blackLitterman, meanVariance, minVariance, riskParity, equalWeight, maxDiversification, tangency, maxSharpe, efficientFrontier, hierarchicalRiskParity, minCvar
risk — Risk Metrics
parametricVar, historicalVar, parametricCvar, historicalCvar, expectedShortfall, drawdown, maxDrawdownDuration, calmarRatio, sharpeRatio, sortinoRatio, omegaRatio, treynorRatio, informationRatio, modifiedVar, hillTailIndex, beta, downsideDeviation, ulcerIndex, painIndex, tailRatio, capturRatio, stabilityRatio
distributions — Distribution Fitting
fitNormal, fitLognormal, fitExponential, fitGamma, fitBeta, fitT, fitMixture, moments, ksTest, adTest, klDivergence, jsDivergence, quantile, qqPlot
dimension — Dimensionality Reduction
pca, lda, tsne, ica, nmf, kernelPca, mds, isomap
factor — Factor Models
famaFrench3, carhart4, apt, capm, estimateBeta, estimateFactorLoading, rollingBeta, pcaFactors, factorMimicking, jensenAlpha, treynorMazuy, multifactor
ml — Machine Learning
regressionTree, decisionTree, predictTree, isolationForest, anomalyScore, kmeans, knn, naiveBayes, randomForest, gradientBoosting, pca, lda, logisticRegression
Converting to Pandas or Polars
All functions return NumPy arrays or dicts. Convert as needed:
import pandas as pd
import polars as pl
from sipQuant import sim
paths = sim.gbm(mu=0.1, sigma=0.2, nSteps=252, nSims=100)
df_pandas = pd.DataFrame(paths.T, columns=[f'sim_{i}' for i in range(100)])
df_polars = pl.DataFrame(paths.T)
Documentation
Full documentation: sipquant.readthedocs.io
License
This project is licensed under GPL-3.0. See LICENSE for details.
Contact
For inquiries: packages@sipglobally.com
Brayden Boyko — brayden@sipglobally.com
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 sipquant-1.0.0.tar.gz.
File metadata
- Download URL: sipquant-1.0.0.tar.gz
- Upload date:
- Size: 108.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73d53b8d3f7425e51d2b56780b208ce734ee4ac21c4e3fcd517d9cc0ee4454df
|
|
| MD5 |
4583c70bd6e0a6eaf7cd99443e23d74d
|
|
| BLAKE2b-256 |
767f4c96f423e2fabfb3c4c9fb668b35ffa38ef5abd6b91fe7d276eae10e944c
|
File details
Details for the file sipquant-1.0.0-py3-none-any.whl.
File metadata
- Download URL: sipquant-1.0.0-py3-none-any.whl
- Upload date:
- Size: 88.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
359c0cff97509bb80bab521ffab01a841ee172c7b0e9c41bae8db1ceddf9ff84
|
|
| MD5 |
6f80bdbd70aaf60649be25f60b27ac3a
|
|
| BLAKE2b-256 |
01b28de9d25574208af23f66af01162c591a8d3d8e673b5fd2b6e93f86803e19
|