fair.compute
Calculate fair probabilities and odds for football match outcomes including 1X2, over/under 2.5 goals, and both teams to score using Poisson distribution.
Instructions
Calcola probabilità e quote fair (Poisson semplice) per 1X2 / OU 2.5 / BTTS.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| match_id | Yes | Fixture id da API-Football |
Implementation Reference
- src/tools/fair.ts:13-17 (handler)The execute handler for the fair.compute tool. Builds a match snapshot using the provided match_id and computes fair odds, returning a JSON string with both.execute: async (args) => { const snapshot = await buildMatchSnapshot(args.match_id); const fair = computeFairOddsFromSnapshot(snapshot); return JSON.stringify({ snapshot, fair }, null, 2); },
- src/tools/fair.ts:10-12 (schema)Zod input schema defining the required match_id parameter (number: Fixture id from API-Football).parameters: z.object({ match_id: z.number().describe("Fixture id da API-Football"), }),
- src/tools/fair.ts:6-19 (registration)The registerFairTool function that defines and registers the fair.compute tool on a FastMCP server instance, including name, description, schema, and handler.export const registerFairTool = (server: FastMCP) => { server.addTool({ name: "fair.compute", description: "Calcola probabilità e quote fair (Poisson semplice) per 1X2 / OU 2.5 / BTTS.", parameters: z.object({ match_id: z.number().describe("Fixture id da API-Football"), }), execute: async (args) => { const snapshot = await buildMatchSnapshot(args.match_id); const fair = computeFairOddsFromSnapshot(snapshot); return JSON.stringify({ snapshot, fair }, null, 2); }, }); };
- src/index.ts:19-19 (registration)Top-level registration call that invokes registerFairTool to add the fair.compute tool to the main MCP server.registerFairTool(server);
- src/services/fairOddsEngine.ts:7-38 (helper)Key helper function that performs the Poisson-based fair odds computation from a match snapshot, deriving lambdas, integrating distributions for probabilities (1X2, OU2.5, BTTS), and calculating fair odds.export const computeFairOddsFromSnapshot = (snapshot: MatchSnapshot): FairOddsPayload => { const lambdaHome = deriveLambda( snapshot.home.avgGoalsFor, snapshot.away.avgGoalsAgainst, config.modeling.homeAdvantage, ); const lambdaAway = deriveLambda(snapshot.away.avgGoalsFor, snapshot.home.avgGoalsAgainst, 1); const { homeWin, awayWin, draw, over25, bttsYes } = integrateDistributions(lambdaHome, lambdaAway); const probs = { HOME: clampProbability(homeWin), DRAW: clampProbability(draw), AWAY: clampProbability(awayWin), OVER_2_5: clampProbability(over25), UNDER_2_5: clampProbability(1 - over25), BTTS_YES: clampProbability(bttsYes), BTTS_NO: clampProbability(1 - bttsYes), } satisfies Record<SelectionKey, number>; const fairOdds = Object.fromEntries( Object.entries(probs).map(([key, value]) => [key, Number((1 / value).toFixed(3))]), ) as Record<SelectionKey, number>; return { matchId: snapshot.match.matchId, lambdaHome: Number(lambdaHome.toFixed(3)), lambdaAway: Number(lambdaAway.toFixed(3)), probabilities: probs, fairOdds, }; };