Methodology
PropBetEdge Fight DNA, for developers.
Raw data tells you what happened. Fight DNA reveals the patterns inside the record. This page explains exactly how, using the live metric registry (definition version 1, captured Sep 7, 2026).
What Fight DNA is
Fight DNA is the proprietary analytics layer above the normalized UFC record. It is a versioned, reproducible, as-of feature system that transforms event-dated bout and round history into fighter-specific and matchup-specific intelligence. It is deterministic: the same source rows always produce the same output. It is not a model, and it is not a prediction.
It answers questions a fighter page does not: how does a fighter do against southpaws, does pace survive into round three, is offense head-heavy or leg-heavy, does a takedown produce control, where do finishes happen, and which of those variables are unusually different between two fighters about to meet.
Source facts versus derived features
The API labels origin on every payload so you never confuse the two.
| Origin | Label | Meaning | Examples |
|---|---|---|---|
source | Source | Normalized facts from ESPN, UFC Stats and ufc.com. Copied, never computed. | event, fighter identity, fight result, strike counts, takedowns, official ranking snapshot |
pbe_derived | PBE derived | Computed by the Fight DNA builder from canonical rows. Every value is a MetricObject. | stance splits, strike differential, target and phase shares, per-minute and per-15 rates, finish distributions, control yield, pace retention, context splits, matchup comparisons |
licensed | Licensed | Reserved for licensed enrichment stored separately from derived features. | position profile (control time by position, finish weapon) — explicitly unavailable until a licensed source exists |
model | Model | Reserved for actual model output. Fight DNA is not labelled model. | none today |
The feature pipeline
- Source rows. Only canonical tables: fighters, events, bouts, results, round stats. Career snapshot fields are never inputs.
- Per-bout features. Two rows per completed bout, one from each fighter's perspective: stance context, outcome, method, scheduled rounds, title and main-event flags, stat coverage, observed seconds, raw totals, derived per-bout values and provenance.
- Observed time. 300 seconds per full standard round; a partial final round uses the recorded stoppage time; unrecognised time formats set observed seconds to
nullwith a warning. - As-of snapshots. One snapshot per fighter per as-of date: metrics, stance splits, round profile, finish profile, context splits, provenance.
- Matchup composition. Two snapshots compared against each other's actual profile with threshold-gated insights.
As-of reconstruction
as_of_date is exclusive: the snapshot dated D contains bouts with event_date < D, so a bout fought on D is excluded by the snapshot dated D. ?as_of=D resolves to the latest stored snapshot with as_of_date <= D, which therefore never contains a bout fought on or after D.
Use ?as_of=YYYY-MM-DD on any fighter DNA route (Pro and above) to reconstruct what was knowable before a given date. If no snapshot exists at or before that date the API answers 404 dna_not_available with the reason, never an empty profile. Example, captured live:
{
"ok": false,
"data": null,
"error": {
"code": "dna_not_available",
"message": "No Fight DNA snapshot exists for Sean Strickland at or before 2024-01-01. Nothing is synthesized.",
"detail": {
"fighter_id": "ec94d296-2db3-4e0d-be6a-46de4f480672",
"requested_as_of": "2024-01-01",
"definition_version": 1,
"reason": "no_snapshot_at_or_before_as_of"
}
},
"meta": {
"api": "PropSports UFC",
"version": "2026-09-06.3",
"request_id": "475fa213-d202-4353-a79d-d31519c3b4a3"
}
} Why sample size matters
Round-stat coverage is a backfill in progress, and many fighters have few covered bouts. A rate built on ten minutes of observed time is not the same as one built on ninety. Fight DNA therefore never returns a bare number: sample_bouts, sample_rounds and sample_seconds travel with every value, and the UI contract forbids turning a low-sample split into a categorical claim.
Example: Sean Strickland's sig_landed_per_min is 6.2327 per minute from 2 stat-covered bouts, 8 rounds and 37.4 observed minutes, confidence medium. That is exactly how it is reported.
Confidence
| Tier | Rule (v1) |
|---|---|
insufficient | sample below the metric's registry minimum (min_bouts / min_rounds / min_seconds); value is null when there is no denominator |
low | minimum met but sample_bouts < 3 (result metrics) or sample_seconds < 1800 (rate metrics) |
medium | sample_bouts < 8 (result metrics) or sample_seconds < 5400 (rate metrics) |
high | sample_bouts >= 8 (result metrics) or sample_seconds >= 5400 (rate metrics) |
coverage_status uses the same scale and describes how much of the fighter's bout history has round-stat coverage. A zero denominator produces value: null with confidence: "insufficient".
Stance DNA
How a fighter performs against southpaws, orthodox fighters and switch hitters. Record, finish, KO and submission rates, and significant-strike differential are grouped by the opponent's listed stance; open-stance and same-stance contexts are reported separately. Result counts reconcile exactly to canonical bout results.
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
open_stance_recordOpen-Stance Record | W/L/D/NC when one fighter is listed orthodox and the other southpaw. | aggregate outcomes where stance_context = open | record | 1 bouts · 0 rounds · 0s |
same_stance_recordSame-Stance Record | W/L/D/NC when both listed stances are the same. | aggregate outcomes where stance_context = same | record | 1 bouts · 0 rounds · 0s |
stance_finish_rateFinish Rate vs Stance | KO/TKO plus submission wins divided by wins against a listed opponent stance. | (ko_tko_wins + submission_wins) / wins_vs_stance | ratio | 2 bouts · 0 rounds · 0s |
stance_kd_rate_15Knockdowns / 15 vs Stance | Knockdowns created per 15 observed minutes, grouped by opponent stance. | kd * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
stance_ko_rateKO/TKO Rate vs Stance | KO/TKO wins divided by completed appearances against a listed opponent stance. | ko_tko_wins / completed_appearances_vs_stance | ratio | 2 bouts · 0 rounds · 0s |
stance_recordRecord vs Stance | W/L/D/NC by opponent listed stance. | aggregate outcomes grouped by opponent_stance | record | 1 bouts · 0 rounds · 0s |
stance_sig_diff_per_minSig. Strike Differential / Min vs Stance | Fighter significant strikes landed minus opponent landed, per observed minute, grouped by opponent stance. | (sig_str_landed - opponent_sig_str_landed) / observed_minutes | per_min | 1 bouts · 2 rounds · 300s |
stance_sub_rateSubmission Rate vs Stance | Submission wins divided by completed appearances against a listed opponent stance. | submission_wins / completed_appearances_vs_stance | ratio | 2 bouts · 0 rounds · 0s |
stance_td_rate_15Takedowns Landed / 15 vs Stance | Takedowns landed per 15 observed minutes, grouped by opponent stance. | td_landed * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
Striking DNA
Pace, accuracy and defense normalized per observed minute, target shares (head, body, leg) and phase shares (distance, clinch, ground) from UFC Stats round rows. Denominators are actual observed seconds, not scheduled time.
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
body_attack_shareBody Attack Share | Body significant-strike attempts divided by all significant-strike attempts. | body_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
clinch_attack_shareClinch Attack Share | Clinch significant-strike attempts divided by all significant-strike attempts. | clinch_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
distance_attack_shareDistance Attack Share | Distance significant-strike attempts divided by all significant-strike attempts. | distance_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
ground_attack_shareGround Attack Share | Ground significant-strike attempts divided by all significant-strike attempts. | ground_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
head_attack_shareHead Attack Share | Head significant-strike attempts divided by all significant-strike attempts. | head_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
knockdowns_absorbed_per_15Knockdowns Absorbed / 15 | Opponent knockdowns per 15 stat-covered minutes. | opponent_kd * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
knockdowns_per_15Knockdowns / 15 | Knockdowns created per 15 stat-covered minutes. | kd * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
leg_attack_shareLeg Attack Share | Leg significant-strike attempts divided by all significant-strike attempts. | leg_att / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
sig_absorbed_per_minSig. Strikes Absorbed / Min | Opponent significant strikes landed divided by observed stat-covered minutes. | opponent_sig_str_landed / observed_minutes | per_min | 1 bouts · 2 rounds · 300s |
sig_accuracySig. Strike Accuracy | Significant strikes landed divided by significant strikes attempted. | sig_str_landed / sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
sig_defenseSig. Strike Defense | One minus opponent significant strikes landed divided by opponent attempts. | 1 - opponent_sig_str_landed / opponent_sig_str_att | ratio | 1 bouts · 2 rounds · 300s |
sig_diff_per_minSig. Strike Differential / Min | Significant strikes landed minus absorbed, per observed minute. | (sig_str_landed - opponent_sig_str_landed) / observed_minutes | per_min | 1 bouts · 2 rounds · 300s |
sig_landed_per_minSig. Strikes Landed / Min | Significant strikes landed divided by observed stat-covered minutes. | sig_str_landed / observed_minutes | per_min | 1 bouts · 2 rounds · 300s |
Grappling DNA
Takedown volume and accuracy per 15 observed minutes, control seconds per takedown landed, control share of observed time, submission attempts and reversals.
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
control_seconds_per_tdControl Seconds / Takedown | Recorded control seconds divided by takedowns landed. | ctrl_sec / td_landed | seconds_per_td | 1 bouts · 2 rounds · 300s |
control_shareControl Share | Recorded control seconds divided by observed stat-covered seconds. | ctrl_sec / observed_seconds | ratio | 1 bouts · 2 rounds · 300s |
reversals_per_15Reversals / 15 | Reversals per 15 stat-covered minutes. | rev * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
sub_attempts_per_15Submission Attempts / 15 | Submission attempts per 15 stat-covered minutes. | sub_att * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
td_accuracyTakedown Accuracy | Takedowns landed divided by takedowns attempted. | td_landed / td_att | ratio | 1 bouts · 2 rounds · 300s |
td_attempts_per_15Takedown Attempts / 15 | Takedown attempts per 15 stat-covered minutes. | td_att * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
td_landed_per_15Takedowns Landed / 15 | Takedowns landed per 15 stat-covered minutes. | td_landed * 900 / observed_seconds | per_15 | 1 bouts · 2 rounds · 300s |
Finish DNA
How and when finishes happen: finish, KO and submission finish rates, finish-round distribution and median elapsed finish time, computed from canonical results only.
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
finish_rateFinish Rate | KO/TKO plus submission wins divided by wins. | (ko_tko_wins + submission_wins) / wins | ratio | 2 bouts · 0 rounds · 0s |
finish_round_distributionFinish Round Distribution | Finish wins grouped by ending round. | count finish wins by round | distribution | 1 bouts · 0 rounds · 0s |
finish_time_median_secMedian Finish Time | Median elapsed fight seconds of finish wins with a standard time format. | median((round - 1) * 300 + time_sec) over finish wins | seconds | 1 bouts · 0 rounds · 0s |
finished_by_round_distributionFinished-By Round Distribution | Losses by KO/TKO or submission grouped by ending round. | count finish losses by round | distribution | 1 bouts · 0 rounds · 0s |
ko_finish_rateKO/TKO Finish Rate | KO/TKO wins divided by wins. | ko_tko_wins / wins | ratio | 2 bouts · 0 rounds · 0s |
submission_finish_rateSubmission Finish Rate | Submission wins divided by wins. | submission_wins / wins | ratio | 2 bouts · 0 rounds · 0s |
Round DNA
Whether round-one pace survives into rounds two and three, championship-round delta for five-round fights, and defensive drift (absorbed rate in round three minus round one).
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
championship_round_deltaChampionship-Round Pace Delta | Rounds 4-5 significant-attempt pace minus rounds 1-3 pace, over bouts that reached round 4. | late_round_sig_att_per_min - early_round_sig_att_per_min | per_min | 1 bouts · 4 rounds · 1200s |
defensive_drift_r3_vs_r1Defensive Drift R3 vs R1 | Round-three significant strikes absorbed per minute minus the round-one rate, over bouts with both rounds covered. | r3_absorbed_per_min - r1_absorbed_per_min | per_min | 2 bouts · 6 rounds · 900s |
late_round_sig_attempts_per_minChampionship-Round Sig. Attempts / Min | Rounds 4-5 significant-strike attempts per observed rounds 4-5 minute. | (r4_sig_str_att + r5_sig_str_att) / (r4_observed_minutes + r5_observed_minutes) | per_min | 1 bouts · 1 rounds · 60s |
pace_retention_r2_vs_r1R2 Pace Retention | Round-two significant-strike attempt pace divided by round-one pace. | r2_sig_att_per_min / r1_sig_att_per_min | ratio | 2 bouts · 4 rounds · 600s |
pace_retention_r3_vs_r1R3 Pace Retention | Round-three significant-strike attempt pace divided by round-one pace. | r3_sig_att_per_min / r1_sig_att_per_min | ratio | 2 bouts · 6 rounds · 900s |
r1_sig_absorbed_per_minR1 Sig. Absorbed / Min | Round-1 opponent significant strikes landed per observed round-1 minute. | r1_opponent_sig_str_landed / r1_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r1_sig_attempts_per_minR1 Sig. Attempts / Min | Round-one significant-strike attempts per observed round-one minute. | r1_sig_str_att / r1_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r1_sig_landed_per_minR1 Sig. Landed / Min | Round-1 significant strikes landed per observed round-1 minute. | r1_sig_str_landed / r1_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r2_sig_absorbed_per_minR2 Sig. Absorbed / Min | Round-2 opponent significant strikes landed per observed round-2 minute. | r2_opponent_sig_str_landed / r2_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r2_sig_attempts_per_minR2 Sig. Attempts / Min | Round-two significant-strike attempts per observed round-two minute. | r2_sig_str_att / r2_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r2_sig_landed_per_minR2 Sig. Landed / Min | Round-2 significant strikes landed per observed round-2 minute. | r2_sig_str_landed / r2_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r3_sig_absorbed_per_minR3 Sig. Absorbed / Min | Round-3 opponent significant strikes landed per observed round-3 minute. | r3_opponent_sig_str_landed / r3_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r3_sig_attempts_per_minR3 Sig. Attempts / Min | Round-three significant-strike attempts per observed round-three minute. | r3_sig_str_att / r3_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r3_sig_landed_per_minR3 Sig. Landed / Min | Round-3 significant strikes landed per observed round-3 minute. | r3_sig_str_landed / r3_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r4_sig_absorbed_per_minR4 Sig. Absorbed / Min | Round-4 opponent significant strikes landed per observed round-4 minute. | r4_opponent_sig_str_landed / r4_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r4_sig_attempts_per_minR4 Sig. Attempts / Min | Round-4 significant-strike attempts per observed round-4 minute. | r4_sig_str_att / r4_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r4_sig_landed_per_minR4 Sig. Landed / Min | Round-4 significant strikes landed per observed round-4 minute. | r4_sig_str_landed / r4_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r5_sig_absorbed_per_minR5 Sig. Absorbed / Min | Round-5 opponent significant strikes landed per observed round-5 minute. | r5_opponent_sig_str_landed / r5_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r5_sig_attempts_per_minR5 Sig. Attempts / Min | Round-5 significant-strike attempts per observed round-5 minute. | r5_sig_str_att / r5_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
r5_sig_landed_per_minR5 Sig. Landed / Min | Round-5 significant strikes landed per observed round-5 minute. | r5_sig_str_landed / r5_observed_minutes | per_min | 1 bouts · 1 rounds · 60s |
Context DNA
Records under specific conditions: short notice, three-round and five-round bouts, title fights and main events. Each split carries its own appearances and confidence.
| Metric | Definition | Formula | Unit | Minimum sample |
|---|---|---|---|---|
five_round_recordFive-Round Record | W/L/D/NC in bouts scheduled for 5 rounds. | aggregate outcomes where scheduled_rounds = 5 | record | 1 bouts · 0 rounds · 0s |
main_event_recordMain Event Record | W/L/D/NC when the bout carried the highest bout_order on its event. | aggregate outcomes where is_main_event | record | 1 bouts · 0 rounds · 0s |
short_notice_recordShort-Notice Record | W/L/D/NC in bouts carrying a verified short_notice_days value. | aggregate outcomes where short_notice_days is not null | record | 1 bouts · 0 rounds · 0s |
three_round_recordThree-Round Record | W/L/D/NC in bouts scheduled for 3 rounds. | aggregate outcomes where scheduled_rounds = 3 | record | 1 bouts · 0 rounds · 0s |
title_bout_recordTitle Bout Record | W/L/D/NC in title bouts. | aggregate outcomes where is_title | record | 1 bouts · 0 rounds · 0s |
Matchup DNA
Fighter versus the opponent actually in front of them.
A matchup response resolves each fighter's own snapshot (each with its own as-of date), then compares 18 paired metrics with a signed delta and direction, adds stance context (fighter A's history against fighter B's listed stance and vice versa), and emits insights only when every documented rule is met. Below threshold, the missing sample is named in warnings[]. Nothing is fabricated.
Comparison keys
sig_landed_per_min · sig_absorbed_per_min · sig_accuracy · sig_defense · head_attack_share · body_attack_share · leg_attack_share · distance_attack_share · clinch_attack_share · ground_attack_share · kd_per_15 · td_attempts_per_15 · td_accuracy · control_seconds_per_td · sub_attempts_per_15 · pace_retention_r2_vs_r1 · pace_retention_r3_vs_r1 · finish_rate
Insight rules (version 1)
{
"version": 1,
"min_confidence": "low",
"stance_history": {
"min_appearances": 3,
"min_confidence": "low"
},
"stance_finish_rate": {
"min_appearances": 3,
"min_confidence": "low",
"note": "finish_rate MetricObject of the split must itself be >= low (registry min 2 wins)"
},
"pace_retention": {
"metric": "pace_retention_r3_vs_r1",
"min_bouts": 2,
"min_confidence": "low"
},
"pace_retention_mismatch": {
"metric": "pace_retention_r3_vs_r1",
"min_bouts": 2,
"min_confidence": "low",
"min_abs_delta": 0.1
},
"target_share_mismatch": {
"metrics": [
"head_attack_share",
"body_attack_share",
"leg_attack_share"
],
"min_confidence": "low",
"min_abs_delta": 0.1
},
"phase_share_mismatch": {
"metrics": [
"distance_attack_share",
"clinch_attack_share",
"ground_attack_share"
],
"min_confidence": "low",
"min_abs_delta": 0.1
},
"grappling_mismatch": {
"min_confidence": "low",
"min_abs_delta": {
"td_attempts_per_15": 1,
"td_accuracy": 0.1,
"control_seconds_per_td": 30,
"sub_attempts_per_15": 0.5
}
},
"finish_rate": {
"metric": "finish_rate",
"min_confidence": "low"
}
} Worked example: Sean Strickland vs Dricus Du Plessis
- Sean Strickland R3 pace retention — Sean Strickland kept 259% of round-one significant-strike attempt pace into round three across 2 bouts / 4 rounds / 17.4 min of stat-covered fights as of 2026-09-06. medium
- Sean Strickland finish rate — 50% of Sean Strickland's 2 UFC wins came by finish (0 KO/TKO, 0 submission), PBE-derived from canonical results as of 2026-09-06. low
- Dricus Du Plessis finish rate — 0% of Dricus Du Plessis's 2 UFC wins came by finish (0 KO/TKO, 0 submission), PBE-derived from canonical results as of 2026-09-06. low
And the warnings the same call produced, verbatim:
- Sean Strickland vs switch-stance opponents: 1 appearance, confidence low; needs >= 3 appearances and confidence >= low. No stance insight emitted.
- Dricus Du Plessis vs orthodox opponents: 2 appearances, confidence low; needs >= 3 appearances and confidence >= low. No stance insight emitted.
- Dricus Du Plessis pace_retention_r3_vs_r1: confidence low (1 bout / 2 rounds / 10.0 min); needs >= 2 stat-covered bouts and confidence >= low. No pace insight emitted.
- Control seconds / takedown: Sean Strickland confidence medium (2 bouts / 8 rounds / 37.4 min); Dricus Du Plessis confidence low (1 bout / 5 rounds / 25.0 min). Both sides need confidence >= low; no grappling mismatch insight emitted.
Provenance
Every MetricObject carries: metric_key, value, unit, numerator, denominator, sample_bouts, sample_rounds, sample_seconds, confidence, coverage_status, definition_version, origin, source_families and as_of_date. Snapshots additionally carry the list of bout ids in scope, the source watermark and the build run id. The commercial gateway never strips any of it; it is part of what you pay for.
{
"unit": "per_min",
"value": 6.2327,
"origin": "pbe_derived",
"numerator": 233,
"as_of_date": "2026-09-06",
"confidence": "medium",
"metric_key": "sig_landed_per_min",
"denominator": 2243,
"sample_bouts": 2,
"sample_rounds": 8,
"sample_seconds": 2243,
"coverage_status": "low",
"source_families": [
"ufcstats"
],
"definition_version": 1
} Definition versioning
Every metric is defined in a registry row with definition_version, formula, unit, source families and minimum sample. A change to a definition is a new version, never a silent recalculation; snapshots carry the version they were built with, and GET /v1/ufc/dna/metrics?version= serves the registry for a version. The commercial contract pins the definition version it targets (currently v1) and a drift guard fails our build if it changes upstream.
What Fight DNA cannot tell you
- It does not predict outcomes, price a market or output a probability. Nothing in the API is a pick.
- It does not know what is not in the record. Bouts without round stats contribute results only; position data does not exist until a licensed source is added; injuries, weigh-ins and odds are not part of Fight DNA.
- It does not adjust for opponent quality yet. Opponent-adjusted metrics and archetypes are reserved for a later definition version.
- It cannot make a small sample large. Low-sample values are reported as low-sample values.
- It is not an official UFC statistic and must not be presented as one.