agentleFS
noahowshnoahowsh/acesapi-mcp/skills/backtesting/SKILL.md

backtesting

Skill1 starsChanged 28 days agoMITView on GitHub

Walk-forward backtests of tennis betting rules against historical moneylines from Grand Slams (mid-2020 on) and ATP Masters and WTA 1000 events (August 2024 on): closing-line value, ROI with bootstrap intervals, drawdown, edge compression, and the sample sizes needed. Use when the user asks if a strategy would have worked, what ROI over a season looks like, or whether an edge is real. Refuses in-sample testing. Do not use for today's prices: see edge-detection. Do not use for model accuracy alone: see walk-forward-validation. Do not use for prop strategies: not supported.

6 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

1 rule. 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 6 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Write it down with its parameters: which matches (tournament tier, rounds), which side (favorite, underdog, model side), price range, …

    line 71

“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Backtesting

Default data tool: AcesAPI (acesapi-tool). Results and ids: get_matches (2 credits per 100 matches). Historical prices: get_match (2 credits per match, odds array). Credit warning: odds cost 2 credits per match, so a covered season is roughly 3,500 matches and about 7,000 credits (3,574 calls in 2026 per the pricing page). Start with one tournament. With the user's own history, no calls are needed.

You falsify claims. A backtest here exists to find out whether a rule beat the closing price after the margin, with honest uncertainty. The default answer to "does it work?" is "not shown yet".

Coverage Limits

  • Prices exist for Grand Slam matches from mid-2020, and ATP Masters and WTA 1000 from August 2024. The data page counts 11,551 matches covered from 2020 to 2026.
  • Each book has two snapshots: open and close. No full line history. No in-play. No props.
  • Lines are refreshed hourly. Books differ by match; use matches where a given book appears for book-specific tests.
  • A rule that needs other tournaments (tour 250s, 500s) cannot be tested on prices in this data.

When to Use

  • "Would betting every underdog over +300 at Slams have made money?"
  • "Does my Elo model beat the Pinnacle close?"
  • "Is my edge shrinking?"
  • "How big a sample do I need?"

When NOT to Use

  • Live prices on tomorrow's matches: see edge-detection
  • Model accuracy without prices: see walk-forward-validation
  • Tracking bets going forward: keep your own log; no tracker tool exists

Commands Available

CommandWhat It DoesCredits
list_tournamentsFind the Slam or Masters editions and tournament_id1
get_tournamentAll matches of one event with ids (2 credits for the whole draw)2
get_matchesMatches with winner_id and score; filter by tournament_id or round2
get_matchThe odds array (open and close per book) plus pre-match ratings2
get_player_matchesRatings before each match for one player5

Commands That Do NOT Exist

Not AvailableUse Instead
get_oddsget_match
get_historical_oddsget_match on past match_id values
get_line_movementOnly open and close exist: compare p1_open with p1_close
get_backtest_resultsThis skill computes them
get_bet_historyKeep your own bet log

Credit Planning (Do This First)

Credits = 2 (tournament list) + 2 (draw or results) + 2 x (number of matches priced)

One Slam, one tour (127 main-draw matches):          about 260 credits
Four Slams, one tour:                                about 1,040
One covered season, all events (pricing page):       about 7,000

Warn the user before anything above about 500 credits, and sample a single event first. The free tier is 500 credits a month, which prices about 240 matches.

Step 1: Define the Rule Before Looking

Write it down with its parameters: which matches (tournament tier, rounds), which side (favorite, underdog, model side), price range, minimum edge, the book. Count how many variants you will try, because the best of ten looks good by chance.

Step 2: Build the Table

For each covered match, in date order:

  1. match_id, match_date, winner_id, player1_id, player2_id from the results.
  2. For each book: p1_open, p2_open, p1_close, p2_close.
  3. Model probability, produced only from information before the match (see feature-engineering). Retrain walk-forward by season (see walk-forward-validation).
  4. Fair close: devigged (see odds-analysis).

Sort ascending by match_date before any calculation.

Step 3: Simulate

For each match where the rule fires:

price      = open or close price at the chosen book   # say which; "open" is optimistic, "close" is conservative
stake      = flat 1 unit, or fractional Kelly from walk-forward p
profit     = stake * (d - 1) if the bet side won else -stake

Exclude matches whose outcome is not completed, or apply the book's void rule consistently, and record how many you dropped. Never use a price from after the match started.

Step 4: Measure

MeasureDefinitionWhy
Bets, winscountsSample size
ROIprofit / total stakeHeadline, noisy
CLVfair_close(side) - implied(price taken)Skill signal independent of results
Brier or log loss vs the closeon the bet setIs the model informative?
Max drawdownpeak to trough in unitsPain
By season, tier, price bandsplitsWhere it works or does not

Bootstrap the ROI. Resample bets (blocks by tournament to respect clustering) 2,000 times, report the 2.5 and 97.5 percentiles. If the interval includes zero, the backtest has not shown an edge.

Sample size reality. At a true 2 percent edge and a per-bet standard deviation near 1 unit, 400 bets give a standard error near 5 percent; 2,500 bets are needed to bring the standard error down to 2 percent. A single Slam gives well under 150 priced bets on a selective rule. Say the number out loud.

Step 5: Stress

  • Edge compression. Compute ROI and CLV by season. A shrinking edge is the usual outcome.
  • Price assumption. Re-run at the close price. If the edge disappears, it came from the open.
  • Book assumption. Re-run at the worst and the best book for each match. A rule that works only at the best price may not be fillable.
  • Parameter sensitivity. Move the thresholds a notch. If the result flips, it was an accident.
  • Selection of tournaments. Dropping one Slam should not change the story.

Worked Example (design, with the real shape of the data)

Question: "Do underdogs over +300 at Slams beat their implied probability?"

1. list_tournaments {"season": 2025}           -> 1 credit, pick the four Slams (major = true)
2. get_matches {"tournament_id": "188-2025"}    -> 2 credits per 100 matches, with winner_id
3. get_match per row where an underdog fits     -> 2 credits each

Real row shape from step 3 (Pinnacle, Wimbledon 2025 final): {"p1_open": 102, "p1_close": -116, "p2_open": -115, "p2_close": 105}. For a +300 rule you would filter p?_close >= 300, devig with odds-analysis, then compare realized wins with the no-vig close. Run it first on one Slam (about 260 credits per tour), look at the count of qualifying bets, and decide whether the sample can answer the question at all. If you have fewer than a few hundred qualifying bets, the honest result is "inconclusive".

Pitfalls

  • Look-ahead. Using a model trained on the test season, using rating.after, or using the final draw to choose rounds. See feature-engineering.
  • Survivorship. Slams drop weaker players quickly; late rounds contain only winners. Condition on pre-match information only.
  • Tuning on the test. Report a rule chosen before seeing the test seasons.
  • Price realism. Odds at the open are available for a short window and at limited stakes. Treat open-price backtests as upper bounds.
  • Void rules. Retirement and walkover handling can swing small samples.
  • Multiple comparisons. Ten variants tried means the best of ten is expected to look good.
  • Overlapping bets. Two bets in the same match on both sides is not a strategy.
  • Variance. A profitable-looking month is not evidence.

Anti-patterns

What Claude Might DoWhy It's WrongDo This Instead
Report ROI without an intervalHides noiseBootstrap
Backtest on covered Slams, then say it works "in tennis"Coverage limitedName the events
Use the best price at any book as fillableMay not beTest the worst and best
Fit and test on the same seasonsIn-sampleWalk forward
Count void bets as pushes in one run and losses in anotherInconsistentFix the rule first
Say "profitable" from 60 betsMeaninglessState the standard error

Output Format

Rule: [definition]    Events: [list]    Period: [dates]
Bets [n], wins [w], avg price [x], ROI [r]% (95% interval [lo, hi]%)
CLV: [mean] pts   Max drawdown: [u] units
By season: ...
Credits used: [n]
Verdict: [shown / not shown / inconclusive], because [sample, interval, sensitivity]

Results are estimates from history, not predictions of future profit.

What to Do Next

What You FoundNext ActionSkill
A promising ruleCheck calibration and out-of-sample stabilityprobability-calibration
Edge only at the openTreat as not obtainableedge-detection
Inconclusive sampleExtend the period or stopn/a

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.