---
title: "One family's track record"
method: GET
path: "/families/{family}/stats"
tags: ["families"]
---

# One family's track record

`GET /families/{family}/stats`

## Request

- Base URL: `https://api.tradingpal.io/api/v1`
- URL: `https://api.tradingpal.io/api/v1/families/{family}/stats`
- Auth: one of:
  - none
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.tradingpal.io/oauth/authorize`, token URL `https://api.tradingpal.io/oauth/token`, scopes: `patterns`)

Returns one family's 20-year backtest record, the same block GET /families lists for it. An unknown family answers 404 unknown_family with the valid names in fix. No key is needed; keyless calls are limited per IP.

## Path parameters

- `family` 'rising_wedge' | 'falling_wedge' | 'bullish_pennant' | 'bearish_pennant' | 'triangle', required

## Response `200`

OK

- Family: One pattern family with its 20-year record.
  - `api_version` 'v1', required: The contract version, always v1. Field names in v1 do not change, and v1 stays available at least 12 months after a v2 ships.
  - `as_of_session` string, date, nullable, required: The last trading session the data describes, as an ISO date. Setups change nightly, so say it when presenting data and do not cache setups across days. Null on routes that do not read a dated artifact (account, tickers, history, families, universe and the demo index).
  - `data_version` string, nullable: Identifier of the stored artifact the answer came from: the candidate-book generation for patterns, the sealed manifest for family records. Null when the route reads no versioned artifact.
  - `source` object, required: Who produced the data. Constant on every response.
    - `name` string: Always "TradingPal".
    - `url` string, uri: Always https://tradingpal.io.
  - `disclaimer` 'Educational breakout-pattern analysis from TradingPal, not investment advice. Past results do not guarantee future outcomes.', required: The educational-use disclaimer, constant on every response. Repeat it when presenting a setup as something the user might act on.
  - `family` 'rising_wedge' | 'falling_wedge' | 'bullish_pennant' | 'bearish_pennant' | 'triangle': Family identifier.
  - `label` string: Human-readable family name.
  - `track_record` StatBlock, nullable: A track record: how one pattern family resolved over the last 20 years of the served universe, or how it resolved on one ticker. Null where a record would go when none is stored; never a partial block. Never present win_rate_pct without sample_size and avg_loss_pct; quote summary whole.
    - `scope` 'family' | 'ticker': family when the record covers every ticker in the served universe, ticker when it covers one symbol.
    - `family` string: The pattern family the record is for (rising_wedge, falling_wedge, bullish_pennant, bearish_pennant, triangle).
    - `symbol` string, nullable: The ticker at ticker scope; null at family scope.
    - `win_rate_pct` number, nullable: Share of resolved trades that reached the target, as a percent (54.0 means 54%), one decimal. At ticker scope the stored rate is shrunk toward the family rate so a handful of trades cannot read as 0% or 100%; wins and losses stay raw. Never quote it without sample_size and avg_loss_pct.
    - `sample_size` integer: Number of trades in the record: the stored trade count, or wins plus losses when no count is stored. The summary sentence quotes it as resolved trades.
    - `wins` integer: Resolved trades that reached the target.
    - `losses` integer: Resolved trades that hit the stop. A bar that reaches both target and stop counts as a loss.
    - `avg_win_pct` number, nullable: Mean price move of the winning trades from entry to exit, as a percent of the entry price (positive), two decimals.
    - `avg_loss_pct` number, nullable: Mean price move of the losing trades from entry to exit, as a percent of the entry price (negative), two decimals.
    - `median_win_pct` number, nullable: Median winning move as a percent of the entry price: the typical win, less sensitive to outliers than avg_win_pct.
    - `avg_trade_pct` number, nullable: Mean price move over all resolved trades, wins and losses together, as a percent of the entry price.
    - `avg_r` number, nullable: Mean R multiple over resolved trades, where one R is the entry-to-stop distance; 0.41 means the average trade made 0.41 times its risk.
    - `expected_r` number, nullable: Per-trade expectancy in R: win rate times the average winning R plus loss rate times the average losing R. Equals avg_r when both come from the same trades.
    - `profit_factor` number, nullable: Gross R of the winning trades divided by gross R of the losing trades; above 1 means the wins outweigh the losses. Null when the record has no losses.
    - `avg_hold_bars` number, nullable: Mean number of daily bars (sessions) from entry to exit over resolved trades, one decimal.
    - `backtest_range` string[], nullable: The window the trades were taken from, as [first date, last date] in ISO format, at most the last 20 years. Null when the record carries no dates.
    - `measured` string: The measurement rule in one paragraph: how entries, stops, targets and exits are counted. Identical on every block.
    - `summary` string: One sentence with the sample size, the window, the win rate, the average win, the average loss and the median win. Quote it whole rather than picking numbers out of it.

## Other responses

- `404`: unknown_family
- `429`: rate_limited; wait details.retry_after_seconds

---

[API](https://skmtc.dev/tradingpal/apis/tradingpal-pattern-api.md) · [All operations](https://skmtc.dev/tradingpal/apis/tradingpal-pattern-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tradingpal/apis/tradingpal-pattern-api/revisions/e96e1f20c1ce?raw)
