All financial metrics (contract cost, highest/lowest bid, estimated cost, awarded value, and derived percentages like disparity or cost shortfall) are restricted to Turkish Lira (TRY) denominated records. Non-TRY currencies (EUR, USD, etc.) are excluded from financial calculations because mixing currency scales would produce meaningless aggregates. This may underrepresent certain sectors such as defense or international contracts.
Statistical Methodology
Reference guide for our standard deviation metrics — formulas, filters, and rationale
Contents
Data Approach
All data is sourced from the Turkish Electronic Public Procurement Platform (EKAP). The following conventions apply across all dashboard pages, leaderboards, and statistical analyses.
A partial tender (is_partial = true) is split into multiple parts (lots),
each with its own result, bid values, and document download records. This creates multiple
database rows per tender. Our handling:
- Counting (tenders won, bids, downloads, objections): Partial tenders are counted as one tender regardless of how many parts exist. A contractor winning 5 parts of the same tender = 1 tender won.
- Financial sums (total awarded value): All parts are summed. If a tender has 5 parts worth 100K TRY each, the total is 500K TRY. This reflects the true total contract value.
- Averages (avg per tender): Calculated as total value divided by distinct tender count. The 500K tender above contributes 500K to the average, not 100K.
- Histograms (Filter Lab): Financial columns are aggregated per tender (sum of parts) before binning. Bid counts use the max across parts. This prevents partial tenders from inflating the distribution.
- Parts column: Leaderboard tables include a "Parts" column showing raw row counts for transparency. When parts > tenders won, the contractor has partial tender awards.
Win rate is computed as: distinct tenders won / distinct tenders bid on × 100%.
Both numerator and denominator count distinct tenders (not parts) to ensure the rate
cannot exceed 100%. A minimum threshold of 10 bids is required to appear on the
win rate leaderboard, filtering out noise from low-activity contractors.
Contract award results from tenders that were later cancelled are included in all metrics. If EKAP published a result notice, it is counted. This reflects the official record as published. The tender status filter in Filter Lab can be used to exclude cancelled tenders from specific analyses.
The "Bids Submitted" metric counts raw rows (not distinct tenders), because each part of a partial tender requires a separate bid submission. A contractor bidding on a 20-part tender counts as 20 bid submissions. This is the only metric that intentionally counts at the part level.
Approach & Formula
We use population standard deviation (not sample standard deviation). This is deliberate: our dataset contains the entire population of EKAP tenders for a given quarter, not a random sample drawn from a larger universe. Since we are describing the full set of observed data rather than estimating a parameter for an unseen population, the population formula is the correct choice.
σ = √ 1⁄N ∑(xi − μ)²
Where:
- N = total number of observations in the quarter
- xi = individual measurement
- μ = population mean (arithmetic average of all xi)
For each metric, PostgreSQL computes all statistics in a single pass:
COUNT, AVG, VAR_POP, STDDEV_POP,
MIN, and MAX. Results are stored per metric per quarter.
Why Standard Deviation Matters in Procurement
Public procurement is governed by principles of fairness, transparency, and competition. Standard deviation helps identify patterns and anomalies across three dimensions:
Metrics like bid count and bid spread reveal whether tenders attract genuine competition. Low bid counts or narrow spreads may indicate barriers to entry or coordinated behavior.
Comparing contract costs to estimated costs surfaces systematic underpricing (potential quality risks) or overpricing (potential waste of public funds). High variance suggests inconsistent estimation practices.
Decision period and disqualification rate track whether the procurement process runs smoothly. Unusual values can flag administrative bottlenecks or overly restrictive specifications.
Tracking these metrics over time (quarter by quarter) lets us detect trends: is competition improving? Are cost deviations narrowing? Are certain quarters consistently anomalous?
Aggregation
All metrics are computed per quarter, grouped by the tender's scheduled date
(tender_scheduled_datetime). This provides granularity fine enough to track seasonal
and policy-driven shifts while keeping each group large enough for meaningful statistics.
The key constraint: EXTRACT(YEAR FROM tender_scheduled_datetime) = Y and
EXTRACT(QUARTER FROM tender_scheduled_datetime) = Q.
Metrics
What it measures: The total number of bids received per tender result.
| Property | Value |
|---|---|
| Source field | tender_result.total_bid_count |
| Unit | Count (integer) |
| Base table | tender_result joined to tender |
| Filters | None beyond the quarter constraint |
Why it matters: The number of bidders is a direct indicator of market competition. A high mean with low standard deviation suggests a healthy, competitive market. A low mean or high standard deviation can signal barriers to entry, overly restrictive specifications, or market concentration in specific sectors.
What it measures: The number of days between the tender's scheduled date and the result notice date.
| Property | Value |
|---|---|
| Formula | DATE_PART('day', notice_date - tender_scheduled_datetime) |
| Unit | Days |
| Base table | tender_result joined to tender |
| Filters | None beyond the quarter constraint |
Why it matters: Measures how long the evaluation-to-decision pipeline takes. A high standard deviation indicates inconsistent processing times. Outliers may signal administrative delays, disputes, or legal challenges that extend the timeline.
What it measures: The percentage of bids disqualified per tender.
| Property | Value |
|---|---|
| Formula | (1 - valid_bid_count / total_bid_count) × 100 |
| Unit | Percentage (%) |
| Base table | tender_result joined to tender |
| Filters |
total_bid_count ≠ 0,
valid_bid_count ≠ 0
(excludes tenders with no bids or no valid bids to avoid division by zero)
|
Why it matters: A high disqualification rate can indicate overly complex documentation requirements, restrictive technical specifications, or a market where participants lack the capacity to prepare compliant bids. Tracking the standard deviation reveals whether high disqualification is systemic or concentrated in specific tenders.
What it measures: The percentage spread between the highest and lowest bids, relative to their midpoint.
| Property | Value |
|---|---|
| Formula | 100 × |highest_bid - lowest_bid| / ((highest_bid + lowest_bid) / 2) |
| Unit | Percentage (%) |
| Base table | tender_result joined to tender |
| Filters |
Both bids > 0,
both in TRY currency
|
Formula note: The midpoint denominator (a + b) / 2 is used instead of
dividing by one of the values. This symmetric percentage difference treats both values equally and
avoids bias toward either the highest or lowest bid.
Why it matters: A narrow spread suggests bidders converge on similar cost estimates (healthy competition). A wide spread can indicate poor cost estimation by some bidders, information asymmetry, or speculative bidding. Currency filtering to TRY ensures comparability.
What it measures: The character length of each tender's name/title.
| Property | Value |
|---|---|
| Formula | LENGTH(tender.name) |
| Unit | Characters (integer) |
| Base table | tender (no join to results) |
| Filters | None beyond the quarter constraint |
Why it matters: Tender names that are unusually short may be vaguely specified, while extremely long names can obscure the scope or bundle multiple unrelated items. Monitoring this metric helps identify naming practice trends and potential specification quality issues.
What it measures: The percentage deviation when the contract cost is below the estimated cost (savings).
| Property | Value |
|---|---|
| Formula | 100 × |contract_cost - estimated_cost| / ((contract_cost + estimated_cost) / 2) |
| Unit | Percentage (%) |
| Condition | contract_cost < estimated_cost |
| Base table | tender_result joined to tender |
| Filters |
Both costs > 0,
both in TRY,
PDF estimated cost differs from system estimated cost
|
Why it matters: When a contract is awarded below the estimate, it may indicate genuine efficiency or an underpriced bid that risks quality delivery. A high standard deviation here means the "savings" vary wildly — some tenders award at near-estimate while others see dramatic undercutting. The PDF filter ensures we compare against a verified estimate, not a duplicated value.
What it measures: The percentage deviation when the contract cost is above the estimated cost (overrun).
| Property | Value |
|---|---|
| Formula | 100 × |contract_cost - estimated_cost| / ((contract_cost + estimated_cost) / 2) |
| Unit | Percentage (%) |
| Condition | contract_cost > estimated_cost |
| Base table | tender_result joined to tender |
| Filters |
Both costs > 0,
both in TRY,
PDF estimated cost differs from system estimated cost
|
Why it matters: Cost overruns are a primary concern in public procurement. A high mean indicates systematic under-estimation of costs or weak cost control. The standard deviation reveals whether overruns are concentrated in a few outliers or spread uniformly across tenders. Separating shortfall from upperfall avoids cancellation effects that would hide both patterns in a single combined metric.
What it measures: The percentage spread between the highest and lowest bids, specifically for tenders with exactly two valid bids.
| Property | Value |
|---|---|
| Formula | 100 × |highest_bid - lowest_bid| / ((highest_bid + lowest_bid) / 2) |
| Unit | Percentage (%) |
| Condition | valid_bid_count = 2 |
| Base table | tender_result joined to tender |
| Filters |
Both bids > 0,
both in TRY
|
Why it matters: Two-bidder tenders are at the minimum threshold for competition. In this scenario, the spread between the two bids is especially informative: a very narrow spread might suggest coordination, while an extreme spread suggests one bidder may be non-competitive (a "courtesy bid"). Isolating this subset from the general bid spread provides a focused view of near-monopolistic conditions.
Interpreting the Results
The Dashboard presents two views of these metrics:
- Overview bar chart: Shows the mean and standard deviation side by side for the most recent quarter. A large standard deviation relative to the mean indicates high variability — the metric is not uniform across tenders.
- Timeseries line chart: Tracks the mean of each metric over quarters. Trend direction matters more than absolute values — a rising disqualification rate over several quarters is more concerning than a single high quarter.
To compare variability across metrics with different scales, use the coefficient of variation (CV):
CV = σ / μ × 100%
A CV above 100% means the standard deviation exceeds the mean — the data is highly dispersed. A CV below 30% suggests the data clusters tightly around the mean. This is useful when comparing, for instance, bid count variability (small absolute numbers) against cost shortfall variability (percentages).
- Outlier sensitivity: Standard deviation is not robust to outliers. A single tender with an extremely high bid count or cost deviation can inflate the standard deviation for the entire quarter. Always check the min/max values alongside the standard deviation.
- Non-normal distributions: Many procurement metrics are right-skewed (e.g., bid counts cluster low with a long tail). Standard deviation assumes no particular distribution, but its interpretive power is strongest for roughly symmetric data. For heavily skewed metrics, the Filter Lab histogram view provides better insight.
- Currency filtering: Bid and cost metrics only include TRY-denominated values. Foreign-currency tenders are excluded, which may underrepresent certain sectors (e.g., defense or international contracts).
- Quarter boundaries: A tender near the boundary of two quarters is assigned to one based on its scheduled date. Quarter-over-quarter comparisons should account for seasonal effects (e.g., budget cycle end-of-year rushes in Q4).