Home › Our work › ML Price Predictor
Our work / ML Price Predictor
What should we bid? A model that answers, or admits it cannot
Bid too high and you lose the contract. Bid too low and you win it and lose money. We built a model that recommends a unit price for an open federal supply opportunity, states how confident it is, and refuses outright when the history is too thin to support an answer.
Why pricing here is hard
Three properties of federal supply data shape every decision in this model.
Prices span five orders of magnitude. Parts go from cents to tens of thousands of dollars. A one dollar error on a five dollar part is catastrophic; on a five thousand dollar part it is noise. What matters is the proportional error, which is why the model works in logarithms throughout.
The past is a very strong predictor. About 36% of the time, a part is awarded again at exactly the same unit price it went for last time. Any model that ignores the previous price is discarding most of the available signal.
Evidence quality varies enormously. Some parts have fifty awards over five years. Others have one award, two years ago. A model that treats those two cases the same is lying to whoever reads its output.
The central design choice
The model predicts the change from the last known price. In practice it learns the correction to the obvious baseline of quoting what the part went for last time.
This sounds like a technicality and it is the single most important decision in the project. Because the baseline is already strong, a model asked to predict absolute prices spends nearly all of its capacity rediscovering that baseline and has little left for the part that matters. Asked instead to predict only the correction, everything it learns is signal the baseline lacked.
It is allowed to say no
When a part has no prior award history, the model returns nothing and the opportunity is routed to manual review.
We could have filled that gap. The obvious approach is to group similar parts by nomenclature and use the group's median price when a specific part is unknown. We built it and measured it, and the price spread inside a group turned out to be enormous, spanning a factor of roughly a million between the cheapest and most expensive item sharing a description. A number drawn from that distribution looks like an answer and carries no information.
So the model refuses. It covers fewer opportunities that way, and every price it does emit is grounded in the real history of that exact part. In a bidding context, where somebody commits real money to the output, a confident wrong answer costs more than a blank.
Measured the way the business loses money
Accuracy scores can be technically correct and commercially useless, so the evaluation was built backwards from the cost of being wrong.
The selection metric is value-weighted error: each part's contribution is scaled by the contract value at stake. A five percent miss on a million dollar contract should dominate a fifty percent miss on a fourteen dollar one, and this metric makes it do so. The usual alternative, R squared, is dominated by the heavy tail and rewards a model for getting expensive outliers roughly right while it mangles the mid-range where the business actually operates.
Training reinforces the same priority. Each historical record is weighted by the quality of its evidence and by the contract value it represents, so high-value, well-documented parts pull harder on the model than a single thin observation from years ago.
The test split is deliberate too. Each part appears in the test set at most once, at its most recent observation, so a score reads as the percentage of parts priced correctly rather than the percentage of rows. Parts with long histories would otherwise dominate the number and flatter the model.
Nineteen models, one winner
We trained a bank of nineteen: linear models, gradient-boosted trees, neural networks and quantile regressors, each with the same weighting scheme and the same split, ranked on the same metric. Picking a family early is how projects end up defending a choice made before any evidence existed.
The models that produce a band rather than a point earned their place. A quantile model returns a low, middle and high estimate, and the band is calibrated so that the true price really does fall inside it about as often as it claims to. A recommendation that comes with an honest range is worth more to a person preparing a quote than a single number with no indication of how much to trust it.
Where it runs
In production on a server, scoring open opportunities as they appear. Every feature the model needs is computable from what the opportunity listing already provides plus the stored history, which was a hard constraint from the start: a feature that cannot be reproduced at prediction time is useless no matter how much it helps in training.
The training data comes from our federal contract ETL pipeline, which reconciles fifteen years of solicitations, awards and supplier records onto the part number.