Predict whether a public procurement tender will achieve savings or result in no_saving based on historical multi-country data.
Context
Public procurement refers to the structured purchasing processes used by governments and public institutions.In each procedure, contracting authorities publish an estimated price, suppliers submit bids, and the final price is determined at the end of the tendering process.
One important analytical question is whether a given procurement is likely to achieve meaningful savings—that is, whether the final awarded price will be lower than the initial estimate by a significant percentage of estimated price. This transforms the problem from predicting a continuous price into a classification task where the model labels each tender as:
- saving → savings achieved (sufficient reduction from estimated price), or
- no_saving → no meaningful savings.
The dataset used in this notebook contains historical public procurement offers collected from multiple countries.
These datasets vary significantly due to:
- differences in procurement legislation and rules,
- differences in macroeconomic conditions and market structures,
- differences in bidder strategies and competitive intensity.
These cross-country differences introduce realistic complexity into the classification task, making it a suitable environment for demonstrating applied machine learning.
This type of prediction can help:
- identify tenders with a low probability of savings,
- support strategic planning of procurement methods,
- prioritize monitoring or intervention for “high-risk” tenders.
We use a historical dataset of public procurement procedures from multiple countries.
For each tender, we have information about:
- tender characteristics (country, size, supply type, procedure type, CPV, year),
- funding and procedure flags (EU funded, framework, GPA, lots, electronic auction, etc.),
- buyer characteristics (buyer type, NUTS region, country),
- prices (estimated, final) and derived variables.
The target variable in this notebook will be a binary indicator of savings
(for example saving_bin, where:
savingmeans “sufficient saving achieved”,no_savingmeans “no (or low) saving”)
Task description
We formulate the problem as a supervised classification task:
Objective
Build a machine learning model that predicts whether a given tender will result in (sufficient) savings, based on information known before the tender is awarded.
Scope
The prediction model should be applicable across:
- multiple countries,
- various procurement categories (e.g., CPV codes),
- different economic environments and bidder behaviours.
The model should remain robust and generalizable, not tailored to a single country or a specific procurement sector.
Limitations
- The underlying dataset may be large, heterogeneous, and contain missing or inconsistent values.
- Data formats and structures may differ across country sources.
- Economic and regulatory differences make the prediction problem non-trivial and require careful preprocessing.
- The final model should generalize across contexts rather than overfit to a narrow subset of the data.
- The dataset is historical and may not fully capture future policy or market changes.
- The model is intended for educational and research purposes, not for fully automated decision-making.
Dataset
https://www.kaggle.com/competitions/bid-2-save-savings-prediction-challenge/data
The dataset includes information on public procurement procedures collected from multiple countries. It contains categorical and numerical features describing each tender, including tender characteristics (country, size, supply type, procedure type, CPV classification, and year), procedure and funding indicators (EU-funded status, framework agreements, GPA applicability, lots, electronic auctions), buyer-related attributes (buyer type, NUTS region, country), as well as estimated and final prices. These variables provide a comprehensive view of how procurement processes are structured and allow modeling of savings outcomes across diverse contexts.
Files
- train.csv – contains all input variables as well as the target variable that we want to predict.
- test.csv – contains the same input variables but does not include the target.
- sample.csv – a sample submission file in the correct format
Columns
- Procurement_ID – Internal persistent id of tender generated by DIGIWHIST
- tender_country – Country of the tender.
- tender_size – Whether the tender is below of above the EU publication threshold. It is based either on the original publication (if they explicitly publish this information), or our ex post estimation based on supply type, buyer type, estimated and final contract values.
- tender_supplyType – The type of the purchase. It can have the following values: supplies, services, public works.
- tender_procedureType – Procedure type mapped to DIGIWHIST standard. It is based on the original procedure type published on the source publication that we recategorized to a standard enumeration. The DIGIWHIST categories are the following: Open, Restricted, Restricted with publication, Negotiated without publication, Competitive dialog, Design contest, Minitender, DPS purchase, Outright award, Approaching bidders, Public contest, Negotiated, Innovation Partnership, Concession, Other (national type)
- tender_nationalProcedureType – Procedure type as it is published in the source publication. Therefore, it contains jurisdiction specific procedure types that might not be possible to standardize in tender_procedureType.
- tender_mainCpv – Main product code of the tender. It is based on the Common Procurement Vocabulary (CPV) codes published on the source publication – https://simap.ted.europa.eu/cpv
- tender_addressOfImplementation_nuts – Regional code of the tender implementation. (These are published NUTS codes from the source publication – https://en.wikipedia.org/wiki/Nomenclature_of_Territorial_Units_for_Statistics)
- tender_addressOfImplementation_country – Country where the tender is to be implemented.
- tender_year – Year of the tender.
- tender_fundingProgrammes – Funding programs associated with the tender.
- tender_npwp_reasons – Reasons for negotiated procedure without publication.
- tender_awardDeadline – The latest date until which the tender is to be awarded. Bidders usually need to bound by their bids until this day but it can differ across jurisdictions.
- tender_contractSignatureDate – The date of contract signature if the tender only has one lot or all lots have the same signature date.
- tender_awardDecisionDate – The award decision date.
- tender_bidDeadline – The final deadline until when companies can submit a bid. It is based on the latest call for tender document published.
- tender_estimatedStartDate – Estimated start date of the contract.
- tender_estimatedCompletionDate – Estimated completion date of the contract.
- tender_estimatedDurationInYears – Estimated length of the contract in years.
- tender_estimatedDurationInMonths – Estimated length of the contract in months.
- tender_estimatedDurationInDays – Estimated length of the contract in days.
- tender_isEUFunded – Whether the tender has EU funding.
- tender_isDps – Whether the tender is a dynamic purchasing system. (This is a purchasing mode is similar to framework agreements.)
- tender_isElectronicAuction – Whether the tender uses an electronic auction
- tender_isAwarded – Whether the tender is awarded or not.
- tender_isCentralProcurement – Whether the purchase is a centralized procurement.
- tender_isJointProcurement – Whether the purchase is a joint procurement (when multiple public bodies purshase something jointly, e.g. because of economies of scale)
- tender_isOnBehalfOf – Whether the purchase is made on behalf of another public body.
- tender_isFrameworkAgreement – Whether the tender is a framework agreement.
- tender_isCoveredByGpa – Whether the tender is covered by the WTI framework agreement. See more: * https://www.wto.org/english/tratop_e/gproc_e/gp_gpa_e.htm
- tender_hasLots – Whether the tender has multiple lots.
- tender_estimatedPrice_currency – Estimated price currency of the tender.
- tender_estimatedPrice_EUR – Estimated price of the tender in Euro
- tender_finalPrice_currency – Final price’s currency.
- Final_Price_EUR – Final price of the tender in EUR.
- tender_description – Detailed description of the tender.
- tender_description_length – Length of the tender description (number of characters).
- tender_personalRequirements_length – Length of the personal requirements set out for participation (number of characters).
- tender_economicRequirements_length – Length of the economic requirements set out for participation (number of characters).
- tender_technicalRequirements_length – Length of the technical requirements set out for participation (number of characters).
- tender_documents_count – Number of documents related to the tender (for example, tender plans or specifications).
- tender_awardCriteria_count – Number of award criteria used in evaluating the bids.
- tender_corrections_count – Number of corrections related to the tender.
- tender_onBehalfOf_count – Number of buyers on behalf the tender is managed.
- tender_lots_count – Number of lots in the tender.
- tender_publications_count – Number of publications related to the tender.
- buyer_buyerType -Type of the buyer.
- buyer_mainActivities – Main activity of the buyer.
- buyer_nuts – Regional code of the buyer. “(These are published NUTS codes from the source publication –
https://en.wikipedia.org/wiki/Nomenclature_of_Territorial_Units_for_Statistics)” - buyer_country – Country of the buyer.
- saving_bin – Classification target variable: takes value saving if Final_Price_EUR < EstimatedPrice_EUR, and no_saving otherwise.
Evaluation method
The model’s performance will be evaluated using standard classification metrics, with Accuracy as the primary evaluation measure. Accuracy reflects the overall proportion of correctly classified tenders and serves as the main benchmark for comparing submissions.
Additional metrics help provide a deeper understanding of model behavior.
Precision indicates how many predicted saving cases were truly saving, while Recall shows how effectively the model identifies all actual saving cases. The F1-score combines Precision and Recall into a single balanced metric, which is particularly helpful when working with imbalanced classes.
To understand how well the model separates saving from no_saving tenders, AUC-ROC may also be considered, where higher values indicate better class separability.
In cases of class imbalance, Precision, Recall, and F1-score provide more informative insights into model performance than Accuracy alone.
Submission File
The submission should be in a CSV file format with columns including Procurement ID and saving_bin. Ensure that the CSV file follows this structure for consistency and ease of evaluation.
Procurement_ID,saving_bin
b8bd-c6957eee8034-08e11756-afe4-46ed,saving
ab44-155d5ff7192d-0b793b17-fb1d-498f,no_saving
bf1e-05e58ae43d79-0e7cdae9-4563-40e7,no_saving
b7eb-6b70cfb0c40e-0eb96eee-fc82-4ec3,saving
etc.
Citation
Miroslava Barkóciová. Bid2Save: Savings Prediction Challenge. https://kaggle.com/competitions/bid-2-save-savings-prediction-challenge, 2025. Kaggle.

