Score both teams' optimal starting lineups before and after swapping the
given give/receive players, using the league's own lineup optimizer
(see best_roster()) rather than an external trade value chart – so the
answer reflects this league's actual roster settings and ESPN's own
per-week projections, not a generic consensus ranking.
Numeric league ID or ESPN fantasy page URL. Defaults to
getOption("fflr.leagueId"). Function fails if no ID is found.
The team ID evaluating the trade (see league_teams()).
Integer vector of player IDs leaving teamId's roster. Every
ID must currently be on that roster.
Integer vector of player IDs arriving on teamId's roster,
all currently rostered by other teams.
Integer year of the NFL season. Defaults to the current
season (see ffl_year()) rather than ffl_api()'s fixed default, which
is only right for the year of the fflr release.
Integer vector of one or more weeks to score, or
"rest" for the rest of the regular season. Defaults to the current week
(see ffl_week()).
One of "projectedScore" (default) or "actualScore".
If TRUE (default), let every lineup start a
replacement-level stand-in from the waiver wire at each position (see
below). FALSE scores only the players on each roster.
Which available player at each position is the
stand-in: 1 (default) is the best one that week. The best is slightly
optimistic, since only one team can claim them; use 2 or more for a
more conservative baseline.
The alphanumeric espn_s2 cookie string from a signed-in
session, defaulting to ffl_cookie(). Since 2025, this cookie is required
by the leagueHistory endpoint. Past seasons can also be requested without
a cookie by passing an explicit seasonId instead of using
leagueHistory = TRUE.
A tibble with one row per team per scoringPeriodId: the optimal
starting score with the current roster (scoreBefore), with the trade
applied (scoreAfter), and their difference (delta); the players who
move into (startersIn) and out of (startersOut) the optimal starting
lineup; the bench players the team would have to drop to get back under
the roster limit (dropped); and which traded players, on either side,
are on bye that week (byes), from nfl_teams – NA for seasons other
than the one that data covers. Player lists are comma-separated names, NA
when empty. A replacement stand-in in startersIn or startersOut is
named with a " (replacement)" suffix, and the stand-ins each lineup
starts are listed in replacementsBefore and replacementsAfter.
Every receive player must be on another team's roster: the team that
rosters them is the trade partner, and is scored with the same swap in
reverse. If receive players come from more than one team, the partner
side can't be split up and only teamId is scored, with a warning. A free
agent or player on waivers is an error – that's a pickup, not a trade.
Passing more than one scoringPeriodId scores the same swap at each week
separately (rosters, byes, and matchups all change week to week). Use
scoringPeriodId = "rest" to score every week from the current one through
the end of the regular season. That makes one API request per week, so it
takes a few seconds; sum delta by teamId for a rest-of-season total.
If a team ends up with more players than the league's roster limit (not
counting players on IR), its lowest-scoring non-starters are listed in
dropped. Dropping non-starters never changes the starting score, so this
says who you'd have to cut rather than changing the result. A warning is
given if the league's trade deadline has passed.
Scoring only the players already on a roster treats an empty starting slot
– a lone QB on bye, an injured kicker, a thin position – as worth 0, so a
trade that fills it gets credit for points any manager would really pick
up off waivers. With replacement = TRUE (the default), each week's before
and after lineups, for both teams, can also start one stand-in per starting
position (QB, RB, WR, TE, K, D/ST, or whichever single-position slots the
league uses; FLEX-type slots are covered by those stand-ins): an available
player, projected at their own number for that week. A stand-in is on both
sides of the comparison, so it cancels out wherever the roster already has
someone better, and only changes the result where a slot would otherwise
score below waiver level. A trade is then valued above the waiver wire
rather than above zero.
The stand-ins are chosen from the most-rostered players who are available
today (free agents and players on waivers), taking the
replacementRank-th best score at each position for each week. The pool
is today's, not a forecast: nobody knows who will be available in a later
week. There's one stand-in per position rather than per slot, so a team
with two RBs on bye can only fill one of the holes – modeling one
pickup per position per week. The roster spot a pickup costs is ignored:
it would be the worst bench player, who doesn't start, so the lineup score
is unaffected. Stand-ins are never counted towards the roster limit,
dropped, or byes. Fetching the pool adds one request per position,
each covering every scored week.
Other roster functions:
best_roster(),
roster_score(),
start_roster(),
team_roster(),
waiver_upgrades()
if (FALSE) { # \dontrun{
evaluate_trade(teamId = 6, give = 4427366, receive = 4362628)
evaluate_trade(teamId = 6, give = 4427366, receive = 4362628,
scoringPeriodId = "rest")
} # }