CASE STUDY · PRODUCT ENGINEERING & DATA ANALYTICS

RacingStatto: Building a horse-racing analytics platform end to end

A horse-racing analytics platform that brings historical form, within-race rankings, and combination scores into a searchable product. I built the platform end to end and lead its technical development.

13
Primary Metrics
Relative intra-race field ranks across form, speed, and track factors
End-to-End
Architecture
Ingestion pipelines, ranking logic, web app, and membership billing
Combos
Combination Engine
Qualifying multi-metric leads mapped to transparent point values
Testing
Live Deployment
Live platform actively gathering early user feedback
01 / Challenge & Context

01 / Problem & ownership

Bringing multi-dimensional racing form into a consistent, traceable intra-race comparison.

RacingStatto brings several aspects of racing form into a consistent comparison within each race. The product combines raw information, runner rankings, and combination scores so users can inspect the factors behind a comparison.

I built the platform end to end, including data processing, ranking logic, the web application, and membership features. The work involved connecting domain-specific scoring rules with a product that users could navigate and test.

Traditional racecards often present isolated, absolute statistics without calibration to that day's specific race conditions. RacingStatto normalizes every competitor against its opponents within the exact conditions of the race.

SCORING METHODOLOGY
Traditional Racecards vs. RacingStatto
Isolated Absolute NumbersTraditional
Raw figures lack direct calibration to track, going, and opponent quality.
Relative Intra-Race RanksRacingStatto
Ranks runners across 13 primary dimensions strictly within that contest.
Opaque ScoringTraditional
Black-box rating systems hide how factors combine.
Transparent Combination EngineRacingStatto
Explicit point sequence (3, 2, 1, 1, 1) for qualifying metric leaders.
02 / System Architecture

02 / How it works

From scheduled data collection to Next.js application delivery and membership access.

The data pipeline collects racecards and results, stores the information, and calculates the metrics used by the application.

Each runner receives ranks across 13 primary metrics. An average of those ranks contributes to an overall ordering within the race. A separate combination engine awards points when a runner satisfies qualifying combinations of top-ranked metrics.

The web application presents these outputs alongside racecards, historical form, filtering, and membership access. Scheduled updates support the daily data workflow.

Architecture Flow
01Python · API
Data Ingestion
Scheduled background jobs pull daily racecards and results with error handling and retry logic.
02PostgreSQL · RDS
Intra-Race Ranking
Computes ordinal competition ranks across 13 primary orthogonal dimensions.
03Prisma 5
Combination Scoring
Evaluates qualifying combinations where a runner ranks first across all included metrics.
04Next.js · Stripe
Application & Access
Next.js web application with filtering, searchable historical form, and membership tiers.
03 / Algorithmic Deep-Dive

03 / Engineering decisions

Relative field rankings and separate combination scoring logic.

Relative rankings: Metrics are ranked within the current field. This provides a consistent way to compare runners across multiple dimensions, but the resulting rank is an ordinal score, not a win probability.

Separate aggregate and combination scores: The overall ranking summarises performance across the primary metrics. The combination score answers a different question: whether a runner leads on particular groups of metrics.

Explicit point allocation: Under the documented scoring rules, a runner qualifies for a combination only when it ranks first on every included metric. Qualifying combinations receive points according to their position in the selected combination table, using the sequence 3, 2, 1, 1, 1.

Illustrative worked scoring example: A runner ranking first on metrics A and B qualifies for combination AB. Ranking first on A but second on B does not qualify. When AB is the highest-ranked qualifying combination in its table, it contributes 3 points.

RacingStatto Relative Metrics & Combination Points Breakdown
src/lib/combos.tstypescript
// Competition Ranking & Combination Points Calculation
export function computeOverallRanks(runners: Runner[]): RankedRunner[] {
  const primaryMetrics = ['A','B','C','D','E','F','G','H','I','J','K','L','P'];
  return runners.map(runner => {
    const sum = primaryMetrics.reduce((acc, m) => acc + runner.ranks[m], 0);
    const avgRank = sum / primaryMetrics.length;
    return { ...runner, avgRank };
  }).sort((a, b) => a.avgRank - b.avgRank)
    .map((r, i, arr) => ({
      ...r,
      overallRank: arr.findIndex(x => x.avgRank === r.avgRank) + 1
    }));
}
04 / Production & Reliability

04 / Evidence & limitations

Current operational status and evaluation boundaries.

RacingStatto is live and in early user testing. The current outcome is a working product with end-to-end technical ownership, not established commercial traction.

Rankings and historical combination statistics explain the scoring system, but do not establish predictive accuracy or financial returns. Those claims would require a separate evaluation with clearly defined data and testing conditions.

Frontend
Next.jsReactTailwind CSSPWA
Backend & Data
Python Data PipelinesPrisma ORMPostgreSQLAWS RDS
DevOps & Cloud
AWS EC2DockerGitHub ActionsCaddy Proxy
Auth & Billing
NextAuthStripe SubscriptionsStripe Webhooks