From 88ed17484b9a55133d17ffd9f3906aa68e551294 Mon Sep 17 00:00:00 2001 From: Deeman Date: Fri, 27 Feb 2026 06:40:12 +0100 Subject: [PATCH 1/3] =?UTF-8?q?feat(sql+templates):=20market=5Fscore=20v3?= =?UTF-8?q?=20=E2=80=94=20log=20density=20+=20count=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes ranking inversion where Germany (1/100k courts) outscored Spain (36/100k). Root causes: population/income were 55% of max before any padel signal, density ceiling saturated 73% of cities, small-town inflation (1 venue / 5k pop = 20/100k = full marks), and the saturation discount actively penalised mature markets. SQL (city_market_profile.sql): - Supply development 40pts: log-scaled density LN(d+1)/LN(21) × count gate min(1, count/5). Ceiling 20/100k. Count gate kills small-town inflation without hard cutoffs (1 venue = 20%, 5+ = 100%). - Demand evidence 25pts: occupancy if available; 40% density proxy otherwise. Separated from supply to avoid double-counting. - Addressable market 15pts: population as context, not maturity. - Economic context 10pts: income PPS (flat per country, low signal). - Data quality 10pts. - Removed saturation discount. High density = maturity. Verified spot-check scores: Málaga (46v, 7.77/100k): 70.1 [was 98.9] Barcelona (104v, 6.17/100k): 67.4 [was 100.0] Amsterdam (24v, 3.24/100k): 58.4 [was 93.7] Bernau bei Berlin (2v, 5.74/100k): 43.9 [was 92.7] Berlin (20v, 0.55/100k): 42.2 [was 74.1] London (66v, 0.74/100k): 44.1 [was 75.5] Templates (city-cost-de, country-overview, city-pricing): - Color coding: green >= 55 (was 65), amber >= 35 (was 40) - Intro/FAQ tiers: strong >= 55 (was 70), mid >= 35 (was 45) - Opportunity interplay: market_score < 40 (was < 50) for white-space Co-Authored-By: Claude Sonnet 4.6 --- .../models/serving/city_market_profile.sql | 51 ++++++++++--------- .../content/templates/city-cost-de.md.jinja | 12 ++--- .../content/templates/city-pricing.md.jinja | 4 +- .../templates/country-overview.md.jinja | 20 ++++---- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/transform/sqlmesh_padelnomics/models/serving/city_market_profile.sql b/transform/sqlmesh_padelnomics/models/serving/city_market_profile.sql index 3b14ec6..9956094 100644 --- a/transform/sqlmesh_padelnomics/models/serving/city_market_profile.sql +++ b/transform/sqlmesh_padelnomics/models/serving/city_market_profile.sql @@ -1,16 +1,18 @@ -- One Big Table: per-city padel market intelligence. -- Consumed by: SEO article generation, planner city-select pre-fill, API endpoints. -- --- Padelnomics Marktreife-Score v2 (0–100): +-- Padelnomics Marktreife-Score v3 (0–100): -- Answers "How mature/established is this padel market?" -- Only computed for cities with ≥1 padel venue (padel_venue_count > 0). -- For white-space opportunity scoring, see serving.location_opportunity_profile. -- --- 30 pts population — log-scaled to 1M+ city ceiling --- 25 pts income PPS — normalised to 200 ceiling (covers CH/NO/LU outliers) --- 30 pts demand — observed occupancy if available, else venue density --- 15 pts data quality — completeness discount, not a market signal --- ×0.85 saturation — discount when venues_per_100k > 8 (oversupplied market) +-- 40 pts supply development — log-scaled density (LN ceiling 20/100k) × count gate +-- (min(1, count/5) kills small-town inflation) +-- 25 pts demand evidence — occupancy when available; 40% density proxy otherwise +-- 15 pts addressable market — log-scaled population, ceiling 1M (context only) +-- 10 pts economic context — income PPS normalised to 200 ceiling +-- 10 pts data quality — completeness discount +-- No saturation discount: high density = maturity, not a penalty MODEL ( name serving.city_market_profile, @@ -61,28 +63,29 @@ WITH base AS ( scored AS ( SELECT *, ROUND( - -- Population (30 pts): log-scale, 1M+ city = full marks. - -- LN(1) = 0 so unpopulated cities score 0 here — they still score on demand. - 30.0 * LEAST(1.0, LN(GREATEST(population, 1)) / LN(1000000)) - -- Economic power (25 pts): income PPS normalised to 200 ceiling. - -- 200 covers high-income outliers (CH ~190, NO ~180, LU ~200+). - -- Drives pricing power and willingness-to-pay directly. - + 25.0 * LEAST(1.0, COALESCE(median_income_pps, 100) / 200.0) - -- Demand evidence (30 pts): observed occupancy is the best signal - -- (proves real demand). If unavailable, venue density is the proxy - -- (proves market exists; caps at 4/100K to avoid penalising dense cities). - + 30.0 * CASE + -- Supply development (40 pts): THE maturity signal. + -- Log-scaled density: LN(density+1)/LN(21) → 20/100k ≈ full marks. + -- Count gate: min(1, count/5) — 1 venue=20%, 5+ venues=100%. + -- Kills small-town inflation (1 court / 5k pop = 20/100k) without hard cutoffs. + 40.0 * LEAST(1.0, LN(COALESCE(venues_per_100k, 0) + 1) / LN(21)) + * LEAST(1.0, padel_venue_count / 5.0) + -- Demand evidence (25 pts): occupancy when Playtomic data available. + -- Fallback: 40% of density score (avoids double-counting with supply component). + + 25.0 * CASE WHEN median_occupancy_rate IS NOT NULL THEN LEAST(1.0, median_occupancy_rate / 0.65) - ELSE LEAST(1.0, COALESCE(venues_per_100k, 0) / 4.0) + ELSE 0.4 * LEAST(1.0, LN(COALESCE(venues_per_100k, 0) + 1) / LN(21)) + * LEAST(1.0, padel_venue_count / 5.0) END - -- Data quality (15 pts): measures completeness, not market quality. - -- Reduced from 20pts — kept as confidence discount, not market signal. - + 15.0 * data_confidence + -- Addressable market (15 pts): population as context, not maturity signal. + -- LN(1) = 0 so zero-pop cities score 0 here. + + 15.0 * LEAST(1.0, LN(GREATEST(population, 1)) / LN(1000000)) + -- Economic context (10 pts): country-level income PPS. + -- Flat per country — kept as context modifier, not primary signal. + + 10.0 * LEAST(1.0, COALESCE(median_income_pps, 100) / 200.0) + -- Data quality (10 pts): completeness discount. + + 10.0 * data_confidence , 1) - -- Saturation discount: venues_per_100k > 8 signals oversupply. - -- ~8/100K ≈ Spain-tier density; above this marginal return decreases. - * CASE WHEN venues_per_100k > 8 THEN 0.85 ELSE 1.0 END AS market_score FROM base ) diff --git a/web/src/padelnomics/content/templates/city-cost-de.md.jinja b/web/src/padelnomics/content/templates/city-cost-de.md.jinja index cc1b032..6f4f8c3 100644 --- a/web/src/padelnomics/content/templates/city-cost-de.md.jinja +++ b/web/src/padelnomics/content/templates/city-cost-de.md.jinja @@ -21,7 +21,7 @@ priority_column: population
padelnomics Market Score
-
{{ market_score | round(1) }}/100
+
{{ market_score | round(1) }}/100
{% if opportunity_score %}
@@ -39,7 +39,7 @@ priority_column: population
-{{ city_name }} erreicht einen **padelnomics Market Score von {{ market_score | round(1) }}/100** — damit liegt die Stadt{% if market_score >= 70 %} unter den stärksten Padel-Märkten in {{ country_name_en }}{% elif market_score >= 45 %} im soliden Mittelfeld der Padel-Märkte in {{ country_name_en }}{% else %} in einem frühen Padel-Markt mit Wachstumspotenzial{% endif %}. Aktuell gibt es **{{ padel_venue_count }} Padelanlagen** für {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} Einwohner — das entspricht {{ venues_per_100k | round(1) }} Anlagen pro 100.000 Einwohner.{% if opportunity_score %} Der **padelnomics Opportunity Score von {{ opportunity_score | round(1) }}/100** bewertet das Investitionspotenzial — Versorgungslücken, Einzugsgebiet und Sportaffinität der Region:{% if opportunity_score >= 65 and market_score < 50 %} überschaubare Konkurrenz trifft auf starkes Standortpotenzial{% elif opportunity_score >= 65 %} hohes Potenzial trotz bereits aktivem Marktumfeld{% elif opportunity_score >= 40 %} solides Potenzial, der Markt beginnt sich zu verdichten{% else %} der Standort ist vergleichsweise gut versorgt, Differenzierung wird zum Schlüssel{% endif %}.{% endif %} +{{ city_name }} erreicht einen **padelnomics Market Score von {{ market_score | round(1) }}/100** — damit liegt die Stadt{% if market_score >= 55 %} unter den stärksten Padel-Märkten in {{ country_name_en }}{% elif market_score >= 35 %} im soliden Mittelfeld der Padel-Märkte in {{ country_name_en }}{% else %} in einem frühen Padel-Markt mit Wachstumspotenzial{% endif %}. Aktuell gibt es **{{ padel_venue_count }} Padelanlagen** für {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} Einwohner — das entspricht {{ venues_per_100k | round(1) }} Anlagen pro 100.000 Einwohner.{% if opportunity_score %} Der **padelnomics Opportunity Score von {{ opportunity_score | round(1) }}/100** bewertet das Investitionspotenzial — Versorgungslücken, Einzugsgebiet und Sportaffinität der Region:{% if opportunity_score >= 65 and market_score < 40 %} überschaubare Konkurrenz trifft auf starkes Standortpotenzial{% elif opportunity_score >= 65 %} hohes Potenzial trotz bereits aktivem Marktumfeld{% elif opportunity_score >= 40 %} solides Potenzial, der Markt beginnt sich zu verdichten{% else %} der Standort ist vergleichsweise gut versorgt, Differenzierung wird zum Schlüssel{% endif %}.{% endif %} Die entscheidende Frage für Investoren: Was bringt ein Padel-Investment bei den aktuellen Preisen, Auslastungsraten und Baukosten tatsächlich? Das Finanzmodell unten rechnet mit echten Marktdaten aus {{ city_name }}. @@ -102,7 +102,7 @@ Eine detaillierte Preisanalyse mit Preisspannen und Vergleichsdaten findest Du a
Ist {{ city_name }} ein guter Standort für eine Padelhalle? -{{ city_name }} erreicht **{{ market_score | round(1) }}/100** auf dem padelnomics Market Score, der Bevölkerungsgröße, Anlagendichte und Datenqualität berücksichtigt. {% if market_score >= 70 %}Ein Score über 70 signalisiert einen starken Markt: große Bevölkerung, wachsende Anlagenzahl und belastbare Preisdaten. {% elif market_score >= 45 %}Ein mittlerer Score bedeutet solide Grundlagen, aber einen teils stärker umkämpften oder datenlimitierten Markt. {% else %}Ein niedrigerer Score spricht für eine kleinere Stadt, begrenzte Datenlage oder einen Markt im Aufbau — was gleichzeitig weniger Wettbewerb und First-Mover-Vorteile bedeuten kann. {% endif %}Mit dem [Finanzplaner](/{{ language }}/planner) kannst Du Deine eigenen Annahmen durchrechnen. +{{ city_name }} erreicht **{{ market_score | round(1) }}/100** auf dem padelnomics Market Score, der Anlagendichte, Bevölkerungsgröße und Datenqualität berücksichtigt. {% if market_score >= 55 %}Ein Score über 55 signalisiert einen starken Markt: etablierte Anlagendichte, wachsende Spielerbasis und belastbare Preisdaten. {% elif market_score >= 35 %}Ein mittlerer Score bedeutet solide Grundlagen, aber einen teils stärker umkämpften oder datenlimitierten Markt. {% else %}Ein niedrigerer Score spricht für einen Markt im frühen Aufbau — was gleichzeitig weniger Wettbewerb und First-Mover-Vorteile bedeuten kann. {% endif %}Mit dem [Finanzplaner](/{{ language }}/planner) kannst Du Deine eigenen Annahmen durchrechnen.
@@ -161,7 +161,7 @@ Der **Market Score ({{ market_score | round(1) }}/100)** misst die *Marktreife*:
padelnomics Market Score
-
{{ market_score | round(1) }}/100
+
{{ market_score | round(1) }}/100
{% if opportunity_score %}
@@ -179,7 +179,7 @@ Der **Market Score ({{ market_score | round(1) }}/100)** misst die *Marktreife*:
-{{ city_name }} has a **padelnomics Market Score of {{ market_score | round(1) }}/100** — placing it{% if market_score >= 70 %} among the strongest padel markets in {{ country_name_en }}{% elif market_score >= 45 %} in the mid-tier of {{ country_name_en }}'s padel markets{% else %} in an early-stage padel market with room for growth{% endif %}. The city currently has **{{ padel_venue_count }} padel venues** serving a population of {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} residents — a density of {{ venues_per_100k | round(1) }} venues per 100,000 people.{% if opportunity_score %} The **padelnomics Opportunity Score of {{ opportunity_score | round(1) }}/100** scores investment potential — supply gaps, catchment reach, and sports culture as a demand proxy:{% if opportunity_score >= 65 and market_score < 50 %} limited competition meets strong location fundamentals{% elif opportunity_score >= 65 %} strong potential despite an already active market{% elif opportunity_score >= 40 %} solid potential as the market starts to fill in{% else %} the area is comparatively well-served; differentiation is the key lever{% endif %}.{% endif %} +{{ city_name }} has a **padelnomics Market Score of {{ market_score | round(1) }}/100** — placing it{% if market_score >= 55 %} among the strongest padel markets in {{ country_name_en }}{% elif market_score >= 35 %} in the mid-tier of {{ country_name_en }}'s padel markets{% else %} in an early-stage padel market with room for growth{% endif %}. The city currently has **{{ padel_venue_count }} padel venues** serving a population of {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} residents — a density of {{ venues_per_100k | round(1) }} venues per 100,000 people.{% if opportunity_score %} The **padelnomics Opportunity Score of {{ opportunity_score | round(1) }}/100** scores investment potential — supply gaps, catchment reach, and sports culture as a demand proxy:{% if opportunity_score >= 65 and market_score < 40 %} limited competition meets strong location fundamentals{% elif opportunity_score >= 65 %} strong potential despite an already active market{% elif opportunity_score >= 40 %} solid potential as the market starts to fill in{% else %} the area is comparatively well-served; differentiation is the key lever{% endif %}.{% endif %} The question investors actually need answered is: given current pricing, occupancy, and build costs, what does the return look like? The financial model below uses real {{ city_name }} market data to give you that answer. @@ -242,7 +242,7 @@ For a detailed pricing breakdown with price ranges and venue comparisons, see th
Is {{ city_name }} a good location for a padel center? -{{ city_name }} scores **{{ market_score | round(1) }}/100** on the padelnomics Market Score, which accounts for population size, existing venue density, and data completeness. {% if market_score >= 70 %}A score above 70 indicates a strong market: high population, growing venue count, and solid pricing data. {% elif market_score >= 45 %}A mid-range score means decent fundamentals but a more competitive or data-limited market. {% else %}A lower score reflects either a smaller city, sparse venue data, or an early-stage market — which can also mean lower competition and first-mover advantage. {% endif %}Use the [Padelnomics planner](/{{ language }}/planner) to model your specific assumptions. +{{ city_name }} scores **{{ market_score | round(1) }}/100** on the padelnomics Market Score, which primarily reflects venue density alongside population size and data completeness. {% if market_score >= 55 %}A score above 55 indicates a strong market: established venue density, a growing player base, and solid pricing data. {% elif market_score >= 35 %}A mid-range score means decent fundamentals but a more competitive or data-limited market. {% else %}A lower score reflects an early-stage market — which can also mean lower competition and first-mover advantage. {% endif %}Use the [Padelnomics planner](/{{ language }}/planner) to model your specific assumptions.
diff --git a/web/src/padelnomics/content/templates/city-pricing.md.jinja b/web/src/padelnomics/content/templates/city-pricing.md.jinja index abaf6cc..baf380f 100644 --- a/web/src/padelnomics/content/templates/city-pricing.md.jinja +++ b/web/src/padelnomics/content/templates/city-pricing.md.jinja @@ -55,7 +55,7 @@ Die Preisspanne von {{ hourly_rate_p25 | round(0) | int }} bis {{ hourly_rate_p7 ## Wie steht {{ city_name }} im Vergleich da? -{{ city_name }} hat {{ padel_venue_count }} Padelanlagen für {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} Einwohner ({{ venues_per_100k | round(1) }} Anlagen pro 100K Einwohner). {% if market_score >= 65 %}Mit einem padelnomics Market Score von {{ market_score | round(1) }}/100 gehört {{ city_name }} zu den stärksten Padel-Märkten in {{ country_name_en }} — höhere Auslastung und Preise sind typisch für dichte, etablierte Märkte. {% elif market_score >= 40 %}Ein Market Score von {{ market_score | round(1) }}/100 steht für einen Markt im Aufbau: genug Angebot für marktgerechte Preise, aber Raum für neue Anlagen. {% else %}Ein Market Score von {{ market_score | round(1) }}/100 deutet auf einen Markt in der Frühphase hin, in dem sich Preise und Auslastung mit dem Wachstum des Sports noch deutlich entwickeln können. {% endif %} +{{ city_name }} hat {{ padel_venue_count }} Padelanlagen für {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} Einwohner ({{ venues_per_100k | round(1) }} Anlagen pro 100K Einwohner). {% if market_score >= 55 %}Mit einem padelnomics Market Score von {{ market_score | round(1) }}/100 gehört {{ city_name }} zu den stärksten Padel-Märkten in {{ country_name_en }} — höhere Auslastung und Preise sind typisch für dichte, etablierte Märkte. {% elif market_score >= 35 %}Ein Market Score von {{ market_score | round(1) }}/100 steht für einen Markt im Aufbau: genug Angebot für marktgerechte Preise, aber Raum für neue Anlagen. {% else %}Ein Market Score von {{ market_score | round(1) }}/100 deutet auf einen Markt in der Frühphase hin, in dem sich Preise und Auslastung mit dem Wachstum des Sports noch deutlich entwickeln können. {% endif %} Die Anlagendichte von {{ venues_per_100k | round(1) }} pro 100K Einwohner beeinflusst die Preisgestaltung direkt: {% if venues_per_100k >= 3.0 %}Höhere Dichte bedeutet mehr Wettbewerb, was die Preise eher stabilisiert oder senkt.{% elif venues_per_100k >= 1.0 %}Moderate Dichte ermöglicht marktgerechte Preise bei gleichzeitigem Wachstumsspielraum.{% else %}Niedrige Dichte gibt Betreibern mehr Preissetzungsmacht — vorausgesetzt, die Nachfrage ist da.{% endif %} @@ -168,7 +168,7 @@ The P25–P75 price range of {{ hourly_rate_p25 | round(0) | int }} to {{ hourly ## How Does {{ city_name }} Compare? -{{ city_name }} has {{ padel_venue_count }} padel venues for a population of {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} ({{ venues_per_100k | round(1) }} venues per 100K residents). {% if market_score >= 65 %}With a padelnomics Market Score of {{ market_score | round(1) }}/100, {{ city_name }} is one of the stronger padel markets in {{ country_name_en }} — higher occupancy and pricing typically follow dense, competitive markets. {% elif market_score >= 40 %}A market score of {{ market_score | round(1) }}/100 reflects a mid-tier market: enough supply to have competitive pricing, but room for new venues to grow. {% else %}A market score of {{ market_score | round(1) }}/100 indicates an early-stage market where pricing and occupancy benchmarks may shift as the sport grows. {% endif %} +{{ city_name }} has {{ padel_venue_count }} padel venues for a population of {% if population >= 1000000 %}{{ (population / 1000000) | round(1) }}M{% else %}{{ (population / 1000) | round(0) | int }}K{% endif %} ({{ venues_per_100k | round(1) }} venues per 100K residents). {% if market_score >= 55 %}With a padelnomics Market Score of {{ market_score | round(1) }}/100, {{ city_name }} is one of the stronger padel markets in {{ country_name_en }} — higher occupancy and pricing typically follow dense, competitive markets. {% elif market_score >= 35 %}A market score of {{ market_score | round(1) }}/100 reflects a mid-tier market: enough supply to have competitive pricing, but room for new venues to grow. {% else %}A market score of {{ market_score | round(1) }}/100 indicates an early-stage market where pricing and occupancy benchmarks may shift as the sport grows. {% endif %} Venue density of {{ venues_per_100k | round(1) }} per 100K residents directly influences pricing: {% if venues_per_100k >= 3.0 %}higher density means more competition, which tends to stabilize or compress prices.{% elif venues_per_100k >= 1.0 %}moderate density supports market-rate pricing with room for growth.{% else %}low density gives operators more pricing power — provided demand exists.{% endif %} diff --git a/web/src/padelnomics/content/templates/country-overview.md.jinja b/web/src/padelnomics/content/templates/country-overview.md.jinja index c8a5074..72682e2 100644 --- a/web/src/padelnomics/content/templates/country-overview.md.jinja +++ b/web/src/padelnomics/content/templates/country-overview.md.jinja @@ -26,7 +26,7 @@ priority_column: total_venues
padelnomics Market Score
-
{{ avg_market_score }}/100
+
{{ avg_market_score }}/100
{% if avg_opportunity_score %}
@@ -40,15 +40,15 @@ priority_column: total_venues
-In {{ country_name_en }} erfassen wir aktuell **{{ total_venues }} Padelanlagen** in **{{ city_count }} Städten**. Der durchschnittliche padelnomics Market Score liegt bei **{{ avg_market_score }}/100**{% if avg_market_score >= 65 %} — ein starker Markt mit breiter Infrastruktur und belastbaren Preisdaten{% elif avg_market_score >= 40 %} — ein wachsender Markt mit guter Abdeckung{% else %} — ein aufstrebender Markt, in dem Früheinsteiger noch Premiumstandorte sichern können{% endif %}. +In {{ country_name_en }} erfassen wir aktuell **{{ total_venues }} Padelanlagen** in **{{ city_count }} Städten**. Der durchschnittliche padelnomics Market Score liegt bei **{{ avg_market_score }}/100**{% if avg_market_score >= 55 %} — ein starker Markt mit breiter Infrastruktur und belastbaren Preisdaten{% elif avg_market_score >= 35 %} — ein wachsender Markt mit guter Abdeckung{% else %} — ein aufstrebender Markt, in dem Früheinsteiger noch Premiumstandorte sichern können{% endif %}. ## Marktlandschaft Padel wächst in {{ country_name_en }} mit bemerkenswertem Tempo. Unsere Daten zeigen {{ total_venues }} erfasste Anlagen — eine Zahl, die angesichts nicht auf Buchungsplattformen gelisteter Clubs vermutlich noch höher liegt. Der durchschnittliche padelnomics Market Score von {{ avg_market_score }}/100 über {{ city_count }} Städte spiegelt sowohl die Marktreife als auch die Datenverfügbarkeit wider. -{% if avg_market_score >= 65 %}Märkte mit Scores über 65 weisen in der Regel eine etablierte Spielerbasis, belastbare Preisdaten und berechenbare Nachfragemuster auf — entscheidend für eine solide Finanzplanung. Dennoch bleiben viele Städte unterversorgt: Selbst in reifen Märkten variiert die Anlagendichte pro 100.000 Einwohner erheblich.{% elif avg_market_score >= 40 %}Ein Score im mittleren Bereich deutet auf eine Wachstumsphase hin: Die Nachfrage ist nachweisbar, die Anlageninfrastruktur baut sich auf, und Preise haben sich noch nicht vollständig auf Wettbewerbsniveau eingependelt. Das eröffnet Chancen für gut positionierte Neueintritte.{% else %}Aufstrebende Märkte bieten First-Mover-Vorteile — weniger direkte Konkurrenz, potenziell attraktivere Mietkonditionen und die Möglichkeit, eine loyale Spielerbasis aufzubauen, bevor sich der Markt verdichtet.{% endif %} +{% if avg_market_score >= 55 %}Märkte mit Scores über 55 weisen in der Regel eine etablierte Spielerbasis, belastbare Preisdaten und berechenbare Nachfragemuster auf — entscheidend für eine solide Finanzplanung. Dennoch bleiben viele Städte unterversorgt: Selbst in reifen Märkten variiert die Anlagendichte pro 100.000 Einwohner erheblich.{% elif avg_market_score >= 35 %}Ein Score im mittleren Bereich deutet auf eine Wachstumsphase hin: Die Nachfrage ist nachweisbar, die Anlageninfrastruktur baut sich auf, und Preise haben sich noch nicht vollständig auf Wettbewerbsniveau eingependelt. Das eröffnet Chancen für gut positionierte Neueintritte.{% else %}Aufstrebende Märkte bieten First-Mover-Vorteile — weniger direkte Konkurrenz, potenziell attraktivere Mietkonditionen und die Möglichkeit, eine loyale Spielerbasis aufzubauen, bevor sich der Markt verdichtet.{% endif %} -{% if avg_opportunity_score %}Der durchschnittliche **padelnomics Opportunity Score von {{ avg_opportunity_score }}/100** zeigt, wie viel Investitionspotenzial in {{ country_name_en }} noch unerschlossen ist. {% if avg_opportunity_score >= 60 and avg_market_score < 50 %}Die Kombination aus hohem Opportunity Score und moderatem Market Score macht {{ country_name_en }} besonders interessant: Nachfragepotenzial und Sportaffinität sind vorhanden, die Infrastruktur noch im Aufbau — First-Mover-Konditionen für gut gewählte Standorte.{% elif avg_opportunity_score >= 60 %}Trotz eines bereits aktiven Markts gibt es noch Standorte mit erheblichem Potenzial — vor allem in mittelgroßen Städten und an der Peripherie großer Ballungsräume.{% else %}Viele Standorte in {{ country_name_en }} sind bereits gut versorgt. Neue Projekte brauchen eine sorgfältige Standortanalyse und ein klares Differenzierungsprofil.{% endif %}{% endif %} +{% if avg_opportunity_score %}Der durchschnittliche **padelnomics Opportunity Score von {{ avg_opportunity_score }}/100** zeigt, wie viel Investitionspotenzial in {{ country_name_en }} noch unerschlossen ist. {% if avg_opportunity_score >= 60 and avg_market_score < 40 %}Die Kombination aus hohem Opportunity Score und moderatem Market Score macht {{ country_name_en }} besonders interessant: Nachfragepotenzial und Sportaffinität sind vorhanden, die Infrastruktur noch im Aufbau — First-Mover-Konditionen für gut gewählte Standorte.{% elif avg_opportunity_score >= 60 %}Trotz eines bereits aktiven Markts gibt es noch Standorte mit erheblichem Potenzial — vor allem in mittelgroßen Städten und an der Peripherie großer Ballungsräume.{% else %}Viele Standorte in {{ country_name_en }} sind bereits gut versorgt. Neue Projekte brauchen eine sorgfältige Standortanalyse und ein klares Differenzierungsprofil.{% endif %}{% endif %} ## Top-Städte in {{ country_name_en }} @@ -122,7 +122,7 @@ Unsere Spitzenstadt nach
padelnomics Market Score
-
{{ avg_market_score }}/100
+
{{ avg_market_score }}/100
{% if avg_opportunity_score %}
@@ -172,15 +172,15 @@ Der **Market Score (Ø {{ avg_market_score }}/100)** bewertet die Marktreife: Be
-{{ country_name_en }} has **{{ total_venues }} padel venues** tracked across **{{ city_count }} cities**. The average padelnomics Market Score across tracked cities is **{{ avg_market_score }}/100**{% if avg_market_score >= 65 %} — a strong market with widespread venue penetration and solid pricing data{% elif avg_market_score >= 40 %} — a growing market with healthy city coverage{% else %} — an emerging market where early entrants can still capture prime locations{% endif %}. +{{ country_name_en }} has **{{ total_venues }} padel venues** tracked across **{{ city_count }} cities**. The average padelnomics Market Score across tracked cities is **{{ avg_market_score }}/100**{% if avg_market_score >= 55 %} — a strong market with widespread venue penetration and solid pricing data{% elif avg_market_score >= 35 %} — a growing market with healthy city coverage{% else %} — an emerging market where early entrants can still capture prime locations{% endif %}. ## Market Landscape Padel is growing rapidly across {{ country_name_en }}. Our data tracks {{ total_venues }} venues — a figure that likely understates the true count given independent clubs not listed on booking platforms. The average padelnomics Market Score of {{ avg_market_score }}/100 across {{ city_count }} cities reflects both market maturity and data availability. -{% if avg_market_score >= 65 %}Markets scoring above 65 typically show an established player base, reliable pricing data, and predictable demand patterns — all critical for sound financial planning. Yet even in mature markets, venue density per 100,000 residents varies significantly between cities, pointing to pockets of underserved demand.{% elif avg_market_score >= 40 %}A mid-range score signals a growth phase: demand is proven, venue infrastructure is building, and pricing hasn't fully settled to competitive levels. This creates opportunities for well-positioned new entrants who can secure good locations before the market matures.{% else %}Emerging markets offer first-mover advantages — less direct competition, potentially better lease terms, and the opportunity to build a loyal player base before the market fills out. The trade-off is less pricing data and more uncertainty in demand projections.{% endif %} +{% if avg_market_score >= 55 %}Markets scoring above 55 typically show an established player base, reliable pricing data, and predictable demand patterns — all critical for sound financial planning. Yet even in mature markets, venue density per 100,000 residents varies significantly between cities, pointing to pockets of underserved demand.{% elif avg_market_score >= 35 %}A mid-range score signals a growth phase: demand is proven, venue infrastructure is building, and pricing hasn't fully settled to competitive levels. This creates opportunities for well-positioned new entrants who can secure good locations before the market matures.{% else %}Emerging markets offer first-mover advantages — less direct competition, potentially better lease terms, and the opportunity to build a loyal player base before the market fills out. The trade-off is less pricing data and more uncertainty in demand projections.{% endif %} -{% if avg_opportunity_score %}The average **padelnomics Opportunity Score of {{ avg_opportunity_score }}/100** shows how much investment potential remains untapped in {{ country_name_en }}. {% if avg_opportunity_score >= 60 and avg_market_score < 50 %}The combination of a high Opportunity Score and a moderate Market Score makes {{ country_name_en }} particularly attractive for new entrants: demand potential and sports culture are there, infrastructure is still building — first-mover conditions for well-chosen locations.{% elif avg_opportunity_score >= 60 %}Despite an already active market, locations with significant potential remain — particularly in mid-size cities and at the periphery of major metro areas.{% else %}Many locations in {{ country_name_en }} are already well-served. New projects need careful site selection and a clear differentiation strategy to compete.{% endif %}{% endif %} +{% if avg_opportunity_score %}The average **padelnomics Opportunity Score of {{ avg_opportunity_score }}/100** shows how much investment potential remains untapped in {{ country_name_en }}. {% if avg_opportunity_score >= 60 and avg_market_score < 40 %}The combination of a high Opportunity Score and a moderate Market Score makes {{ country_name_en }} particularly attractive for new entrants: demand potential and sports culture are there, infrastructure is still building — first-mover conditions for well-chosen locations.{% elif avg_opportunity_score >= 60 %}Despite an already active market, locations with significant potential remain — particularly in mid-size cities and at the periphery of major metro areas.{% else %}Many locations in {{ country_name_en }} are already well-served. New projects need careful site selection and a clear differentiation strategy to compete.{% endif %}{% endif %} ## Top Cities in {{ country_name_en }} @@ -254,7 +254,7 @@ Our top-ranked city by 30km = full marks) --- 10 pts sports culture — tennis courts within 25km (≥10 = full marks) +-- NOTE: PPS values are country-level constants in the range +-- 18k-37k — ALL EU countries saturate this component (20/20). +-- Component is a flat uplift per country until city-level +-- income data becomes available. +-- 30 pts supply gap — INVERTED venue density; 0 courts/100K = full marks. +-- Ceiling raised to 8/100K (was 4) for a gentler gradient +-- and to account for ~87% data undercount vs FIP totals. +-- Linear: GREATEST(0, 1 - density/8) +-- 15 pts catchment gap — distance to nearest padel court. +-- DuckDB LEAST ignores NULLs: LEAST(1.0, NULL/30) = 1.0, +-- so NULL nearest_km = full marks (no court in bounding box +-- = high opportunity). COALESCE fallback is dead code. +-- 10 pts sports culture — tennis courts within 25km (≥10 = full marks). +-- NOTE: dim_locations tennis data is empty (all 0 rows). +-- Component contributes 0 pts everywhere until data lands. MODEL ( name serving.location_opportunity_profile, @@ -50,9 +62,11 @@ SELECT + 20.0 * LEAST(1.0, COALESCE(l.median_income_pps, 100) / 200.0) -- Supply gap (30 pts): INVERTED venue density. - -- 0 courts/100K = full 30 pts (white space); ≥4/100K = 0 pts (served market). + -- 0 courts/100K = full 30 pts (white space); ≥8/100K = 0 pts (served market). + -- Ceiling raised from 4→8/100K for a gentler gradient and to account for data + -- undercount (~87% of real courts not in our data). -- This is the key signal that separates Marktpotenzial from Marktreife. - + 30.0 * GREATEST(0.0, 1.0 - COALESCE(l.padel_venues_per_100k, 0) / 4.0) + + 30.0 * GREATEST(0.0, 1.0 - COALESCE(l.padel_venues_per_100k, 0) / 8.0) -- Catchment gap (15 pts): distance to nearest existing padel court. -- >30km = full 15 pts (underserved catchment area). From 721b2a37df129e94a5668f47c3576cf4ea242632 Mon Sep 17 00:00:00 2001 From: Deeman Date: Fri, 27 Feb 2026 06:58:48 +0100 Subject: [PATCH 3/3] docs: CHANGELOG + PROJECT.md for score recalibration (market_score v3 + opportunity_score v2) Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 9 +++++++++ PROJECT.md | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cecc5a..1bae5b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Changed +- **Market Score v3 (Marktreife-Score recalibration)** — fixes ranking inversion where early-stage markets (Germany 1/100k) outscored mature markets (Spain 36/100k): + - **Formula rewrite** (`city_market_profile.sql`): supply development now 40 pts (log-scaled density LN(d+1)/LN(21) × count gate min(1,count/5)); demand evidence 25 pts (occupancy or 40% density proxy); population reduced to 15 pts (context); income to 10 pts (context); data quality to 10 pts; saturation discount removed + - **Count gate** eliminates small-town inflation: a single venue in a 5k-resident town can no longer outscore Berlin (was 92.7 → now 43.9 for Bernau bei Berlin) + - **LN ceiling at 20/100k** (was linear 4/100k) gives meaningful differentiation from 0 to 20: Málaga 70.1, Barcelona 67.4, Madrid 66.9, Amsterdam 58.4, Berlin 42.2, London 44.1 + - **Template thresholds updated** across all 3 pSEO templates (city-cost-de, country-overview, city-pricing): color coding green ≥55 (was ≥65) / amber ≥35 (was ≥40); intro/FAQ tiers strong ≥55 (was ≥70) / mid ≥35 (was ≥45); white-space signal interplay market_score < 40 (was < 50) + +- **Opportunity Score supply gap ceiling raised 4→8/100k** (`location_opportunity_profile.sql`) — gentler gradient for partially-served markets; accounts for ~87% data undercount vs FIP real-world totals. Documents discovered formula behaviour: DuckDB `LEAST(1.0, NULL)=1.0` means NULL catchment already yields full 15 pts; income PPS saturates for all EU countries; tennis courts data currently empty (formula correct, data pending) + ### Added - **Opportunity Score integration** — second scoring dimension (`Marktpotenzial`) now visible in city and country articles: - **SQL chain**: `dim_cities` now carries `geoname_id` (from the existing GeoNames LEFT JOIN); threaded through `city_market_profile` → `pseo_city_costs_de` which LEFT JOINs `location_opportunity_profile` on `(country_code, geoname_id)`; `pseo_country_overview` gains `avg_opportunity_score`, `top_opportunity_score`, `top_opportunity_slugs`, `top_opportunity_names` diff --git a/PROJECT.md b/PROJECT.md index 4f21dc4..3dc0649 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -1,7 +1,7 @@ # Padelnomics — Project Tracker > Move tasks across columns as you work. Add new tasks at the top of the relevant column. -> Last updated: 2026-02-25. +> Last updated: 2026-02-27. --- @@ -87,6 +87,8 @@ - [x] Markets hub (`//markets`) — article listing with FTS + country/region filters - [x] DuckDB refresh script (`refresh_from_daas.py`) - [x] **Opportunity Score integration** — `opportunity_score` (Marktpotenzial) wired into city + country templates; `geoname_id` threaded through SQL chain (dim_cities → city_market_profile → pseo_city_costs_de); 71.4% city match rate; stats strip, intro paragraphs, market tables, and FAQ updated in both DE + EN +- [x] **Market Score v3 recalibration** — fixes ranking inversion (Germany 1/100k was outscoring Spain 36/100k); log-scaled density + count gate replaces linear formula; saturation discount removed; template thresholds updated across all 3 pSEO templates; verified: Málaga 70.1, Barcelona 67.4, Madrid 66.9, Amsterdam 58.4, Bernau 43.9 (was 92.7), Berlin 42.2, London 44.1 +- [x] **Opportunity Score v2** — supply gap ceiling raised 4→8/100k (gentler gradient, accounts for 87% data undercount); formula documentation added (DuckDB LEAST NULL behaviour, income saturation, tennis data gap) ### Data Pipeline (DaaS) - [x] Overpass API extractor (OSM padel courts)