Cash and GPP are different constraint problems, not different moods

The same player pool and the same projections produce two different rosters because the objective function and the feasible set are different. Here is what each optimizer knob actually changes, with the arithmetic, and why one lineup cannot serve both contests.

"Build it safer for cash" is not a strategy, it is a vibe. The reason a cash lineup and a tournament lineup differ is much more specific and much more useful: they are answers to two different optimization problems over the same data. One maximizes a quantity the optimizer can actually compute. The other maximizes a quantity it cannot, and every knob in a lineup builder exists to approximate that second thing by deliberately deforming the first.

Once you see which knobs change the objective and which change the feasible set, most lineup-building arguments resolve themselves, and the ones that do not at least become arguments about a number you can check.

What the solver is actually doing

A lineup optimizer solves a small integer program. Maximize the sum of the selected players' projections, subject to: exactly nine players in the required roster shape, total salary at or below the cap, total salary at or above a floor, at least two games represented, at least two teams represented, and whatever stacking rules are in force.

Note what the objective is. It is the sum of point estimates — which, for a well-built projection set, is an estimate of the roster's median-ish outcome. Nothing in that formulation knows about variance, ownership, or the shape of a payout table. It produces the single roster most likely to score around a high number.

In a contest paying roughly the top half of entries, that is exactly what you want, and the unmodified solve is the answer worth beating. In a top-heavy tournament it is close to the worst thing you can do, because thousands of other people are running the same solve on similar numbers and arriving at similar rosters.

The knob table

Every lever in a serious builder does one of two things: it changes the number being maximized, or it changes which rosters are legal. The distinction matters because the two fail differently — a bad objective gives you a worse lineup, while an over-tight feasible set gives you no lineup at all.

KnobChangesOff / default on ClassicEffect
salary_floorfeasible set$49,500 of a $50,000 capRejects rosters that leave money unspent
min_unique_playersfeasible set, across lineups1, its weakest legal value; never offCaps overlap with every earlier lineup in the run
randomness_pctobjective0 for one lineup; risk posture for severalAdds noise proportional to each projection
ownership_penalty_weightobjective0, off until you ask for itSubtracts points in proportion to projected ownership
max_total_ownership_pctfeasible setuncappedRejects any roster whose summed ownership exceeds the cap

The defaults are GameScript's, and they are deliberately boring: with nothing set, you get the unmodified optimal build. Both ownership knobs stay off until asked for, and neither is inherited from a previous slate — a leverage posture belongs to a contest, not to an account.

The ownership penalty is an exchange rate

This is the knob most worth understanding precisely, because it is the one people set by feel and then cannot explain. It assumes a projected ownership figure exists, and what that number is worth depends on where it came from.

The penalty is linear in the ownership fraction: a player's objective value is reduced by weight * ownership_pct / 100. That makes the weight readable as a single sentence — projected points given up for a wholly-owned player — and gives you a constant exchange rate rather than a curve you have to integrate.

Weight40% owned25% owned10% owned3% owned
31.200.750.300.09
62.401.500.600.18
124.803.001.200.36
2510.006.252.500.75

Read a row as a decision rule. At weight 6, a 40%-owned player is charged 2.40 points and a 10%-owned alternative is charged 0.60, so the chalk survives only if it outprojects the alternative by more than 1.80 points. That is a sentence you can argue with. "I turned the leverage dial up" is not.

It also shows you where the knob stops being a tilt. GameScript caps the weight at 50, and the cap is not a recommendation — it is the point past which the setting is no longer a leverage tilt at all. At 50, a 30%-owned player gives up 15 projected points, and no NFL projection spread survives a 15-point swing between a 30%-owned player and a 0%-owned one. Past that the solver has stopped comparing players on projection and is sorting them by ownership with projection as a tiebreak, which is a legitimate thing to want and a dishonest thing to call an optimizer.

A penalty prices chalk. A cap refuses it.

The two ownership knobs are not two strengths of the same idea.

ownership_penalty_weight is soft. It puts a price on ownership and lets the solve buy anyway when the projection justifies it. That is usually what you want, because it keeps the lineup an answer to a question about points.

max_total_ownership_pct is hard. It refuses any roster whose summed projected ownership exceeds a number, no matter how good the players are. Nine slots at 20% each sums to 180%, which is a useful anchor: a pure chalk Classic build runs well above that, and GameScript's contrarian playbook targets a mean of 12% per player, or a cumulative 108%.

Use the penalty to express a preference and the cap to express a limit. The cap is the better tool for the tail specifically, because it cuts the tail exactly, as a constraint a run report can state back to you, rather than approximately, as a curve nobody can read. Its failure mode is honest too: set it too low and the solve is infeasible, which is a message rather than a silently bad lineup.

Randomness perturbs, it does not diversify

Projection jitter is the most misunderstood setting in any builder. It draws a Gaussian for each player and scales it by that player's own projection — specifically, by the magnitude of that projection after your leans and adjustments and before any ownership penalty: noise = gaussian * abs(adjusted_projection) * randomness_pct / 100.

Both halves of that ordering are deliberate, and both matter when you read a build back. Scaling against the leaned number means a boost you applied raises that player's jitter along with his projection, so talking a player up makes him move around more, not less. Scaling against the pre-penalty number keeps randomness and the ownership penalty independent: turning leverage up does not quietly shrink your diversity, and the weight keeps its "points given up at 100% ownership" meaning at every randomness setting.

The scaling is proportional, which has a consequence people rarely notice. At 8%, a quarterback carrying an adjusted 20 points has a one-standard-deviation jitter of 1.6, while a 6-point defense has 0.48. Randomness therefore reshuffles the expensive top of the board far more than the cheap bottom of it, in absolute points. That is defensible — a 20-point projection carries more real uncertainty than a 6-point one — but it is not the flat "shake everything a little" people imagine.

Two rules follow. First, jitter changes solve selection only; it must never change the projections you are shown, or you cannot audit your own build. Second, jitter is not a substitute for a uniqueness constraint. Noise makes lineups different; min_unique_players makes them differently wrong, which is the property a portfolio needs.

Uniqueness is the only knob that knows about your other lineups

min_unique_players is a constraint relating each new lineup to every lineup already solved — the prior lineups you carried in and the ones this run has produced so far. Overlap with each of them is capped at lineup_size - min_unique_players. On a nine-player Classic roster, a minimum of 3 unique allows at most 6 shared players.

Note what happens at the bottom of that range, because it is the opposite of what "default" usually implies. The setting is an integer between 1 and the roster size; it cannot be zero, so the constraint is never absent. At the default of 1 on Classic, overlap is capped at 8 of 9, and every lineup must therefore differ from every earlier one by at least one player. Exact duplicates are structurally impossible whatever else you set.

That is a real guarantee and a thin one, and the thinness is the part worth stating precisely. A one-player floor is satisfied by the cheapest change the pool allows: the solver returns the highest-scoring roster that is not one of the earlier ones, which is usually the previous build with a single substitution — by construction the substitution costing the least projection, and therefore the one least likely to change how the roster does on Sunday. Twenty lineups that differ by one flex apiece are twenty distinct rosters and one bet, and they die on the same afternoon for the same reason.

GameScript hedges that by switching jitter on automatically for multi-lineup builds, which helps and is not the same thing. Noise changes which cheap substitution the solver reaches for, so the twentieth lineup is a slightly different draw from the same distribution. It does not raise the floor on how many players have to differ. Only min_unique_players does that, which is what separates a portfolio that is incidentally varied from one that is structurally diverse.

The countervailing fact: uniqueness is expensive. Every forced swap costs projection, and the cost compounds across a portfolio, so a large minimum on a large build is a real bet that distinctness is worth more than points. Make that bet explicitly.

Why one lineup cannot serve both

Put the two problems side by side and the incompatibility is structural, not stylistic.

QuestionCashTop-heavy tournament
What you are paid forClearing a line a large fraction of entries clearFinishing above nearly all of them
The quantity that mattersMedianThe right tail
Correct ownership postureEat the chalk; it is the market agreeingPrice the chalk; duplication is the cost
Correct lineup countOneMany, with a uniqueness constraint
Correct randomness_pctZeroNon-zero
Correct salary_floorHigh; unspent salary is projection declinedNegotiable, if a shape needs the room
A negative leverage scoreAcceptable — overlap is not a cost hereA warning: owned above what the projection warrants

The middle-ground lineup satisfies neither column. It gives up median for uniqueness it will not be paid for, or gives up uniqueness for median that does not win anything. The reason "one lineup for both" feels reasonable is that it feels efficient, and the reason it is wrong is that efficiency is not the objective in either contest.

There is exactly one best cash lineup under a projection set. A second one is the first with a worse player in it. Diversity settings exist to serve the opposite objective, and running them in cash is paying for something the contest does not sell.

When the solve refuses

One last practical note, because it is where most people's first serious build dies. Constraints compose, and they compose faster than intuition suggests: a high salary floor, a strict stack rule, a low ownership cap, and three locked players can jointly describe a roster that does not exist in the pool.

An infeasible solve is not a bug and not a reason to loosen everything at once. It is the model telling you that your stated preferences are contradictory, and the useful response is to find out which pair contradicts. A good builder should tell you which constraint bound — for instance, naming the lowest total ownership any legal roster can reach when your cap is below it. That message is more informative than the lineup you would have gotten by guessing.

GameScript exposes these five settings by their real names and reports back which ones were in force for a given run, including whether the salary floor was one you chose or a format default. That is deliberate: a lineup you cannot attribute to a stated constraint is a lineup you cannot learn anything from.