Trainerflow Docs trainerflow.com
Examples › Madcow 5×5

Examples

Madcow 5×5

An intermediate program split across two files, with ramping sets, weekly progression and a deload between cycles.

Madcow 5×5 is a popular intermediate program. Where Starting Strength adds weight every session, an intermediate lifter can’t keep that up, so Madcow progresses weekly instead and spreads the work over a heavy, a light and a medium day. It is also a good excuse to see how a program can be split across more than one file.

This is what we are building, every week:

Day Work
Monday — heavy Squat, bench press and row: five sets of five, ramping up to the top set
Wednesday — light Squat ramped over three sets plus a back-off set, then press and deadlift ramped over four sets
Friday — medium Squat, bench press and row: four ramping sets, a triple 2.5% over Monday, then a back-off set of eight

The top sets climb 2.5% a week for eight weeks. A deload week follows, and the next cycle starts again 5% under the peak the previous one reached. We will run three cycles.

Unlike Starting Strength, this program doesn’t look at what the athlete reports to decide what comes next: its progression is planned ahead of time. It still logs the reps and weight of every set, so the athlete’s history and insights show what they actually did.

Process

Two files

Every session starts with the same warm-up, so we give it a file of its own. In the explorer, create a new file next to main.cl and call it warmup.cl:

import "coach/strength/squat.cl"

group warmup() {
    goblet_squat([reps: 10, weight: 24|kg|], [reps: true], [location: "Warm-up"])
}

A file that is imported can do everything main.cl can. It imports what it needs itself, here the squat library for goblet_squat, and everything it declares becomes available to the files that import it. Passing a string to location shows that string as the title of the screen instead of the name of the exercise.

Back in main.cl, we import the standard library and our own file in exactly the same way:

import "coach/strength/squat.cl"
import "coach/strength/push.cl"
import "coach/strength/pull.cl"
import "coach/strength/bend.cl"
import "coach/common/rest.cl"
import "warmup.cl"

Both files import the squat library, and that is fine: several files may import the same one. You can read more about this on the imports page.

One set of any lift

Five different lifts appear in this program. Rather than repeating ourselves, we write one group that does a set of any of them:

let logged = [reps: true, weight: true]

group lift(name, reps, weight) {
    let specs = [reps: reps, weight: round(weight, 2.5|kg|)]
    if (name == "squat") {
        squat(specs, logged, [location: true])
    } else if (name == "bench") {
        bench_press(specs, logged, [location: true])
    } else if (name == "row") {
        row(specs, logged, [location: true, gear: "Barbell"])
    } else if (name == "press") {
        press(specs, logged, [location: true, variation: "Strict"])
    } else {
        deadlift(specs, logged, [location: true])
    }
}

Percentages of a weight rarely land on something you can load on a bar. The built-in round takes care of that: round(weight, 2.5|kg|) rounds to the nearest 2.5 kg, so 101.25 kg becomes 102.5 kg.

Ramping

The heart of Madcow is the ramp: sets of five that climb 12.5% at a time up to the top weight of the day. With five sets that is 50%, 62.5%, 75%, 87.5% and finally 100% of the top weight:

// Fives climbing 12.5% a set to the top weight
group ramp(name, top, sets) {
    repeat i:sets {
        lift(name, 5, top * (1 - 12.5 * (5 - i) / 100))
    }
    rest(4|min|)
}

With fewer sets the ramp simply stops short of the top. Three sets, for example, go 50%, 62.5% and 75%. After the ramp the athlete rests for four minutes before the next lift.

The days

Each day is now a handful of lines:

group heavy(squat_top, bench_top, row_top) {
    @title = "Monday — heavy"
    warmup()
    ramp("squat", squat_top, 5)
    ramp("bench", bench_top, 5)
    ramp("row", row_top, 5)
}

group light(squat_top, press_top, deadlift_top) {
    @title = "Wednesday — light"
    warmup()
    ramp("squat", squat_top, 3)
    lift("squat", 5, squat_top * 0.75)
    rest(4|min|)
    ramp("press", press_top, 4)
    ramp("deadlift", deadlift_top, 4)
}

// Four ramping fives, a triple 2.5% over Monday, then a back-off eight
group medium(name, top) {
    ramp(name, top, 4)
    lift(name, 3, top * 102.5 / 100)
    lift(name, 8, top * 0.75)
    rest(4|min|)
}

group deload(squat_top, bench_top, row_top) {
    @title = "Deload"
    warmup()
    ramp("squat", squat_top, 3)
    ramp("bench", bench_top, 3)
    ramp("row", row_top, 3)
}

heavy, light and deload each are a whole session, while medium is one lift of the Friday session; we will call it three times.

Cycles and weeks

Finally, the progression. main keeps the top weight of every lift in a variable and works out each week’s weights from it:

repeat cycle:3 {
    repeat week:8 {
        let k = 1 + 2.5 * (week - 1) / 100
        heavy(squat_top * k, bench_top * k, row_top * k)
        rest(2|day|)
        light(squat_top * k, press_top * k, deadlift_top * k)
        rest(2|day|)
        medium("squat", squat_top * k)
        medium("bench", bench_top * k)
        medium("row", row_top * k)
        rest(3|day|)
    }
    ...
}

k is the factor for the week: 1 in week 1, 1.025 in week 2, up to 1.175 in week 8. So with a 100 kg squat, Monday’s top set is 100 kg in the first week, 102.5 kg in the second and 117.5 kg in the eighth. Friday’s triple is always 2.5% over Monday, i.e. exactly next Monday’s top set.

When a cycle ends, the next one starts 5% under the peak it reached:

    let peak = 1 + 2.5 * 7 / 100
    squat_top = squat_top * peak * 0.95
    bench_top = bench_top * peak * 0.95
    row_top = row_top * peak * 0.95
    press_top = press_top * peak * 0.95
    deadlift_top = deadlift_top * peak * 0.95

and, except after the last cycle, a deload week of three light sessions at 90% gives the athlete a break before the climb starts again:

    if (cycle < 3) {
        repeat 3 {
            deload(squat_top * 0.9, bench_top * 0.9, row_top * 0.9)
            rest(2|day|)
        }
        rest(1|day|)
    }

Three rests of 2|day| and one extra 1|day| make the deload week seven days long, just like the rest.

The whole program

warmup.cl:

import "coach/strength/squat.cl"

group warmup() {
    goblet_squat([reps: 10, weight: 24|kg|], [reps: true], [location: "Warm-up"])
}

main.cl:

import "coach/strength/squat.cl"
import "coach/strength/push.cl"
import "coach/strength/pull.cl"
import "coach/strength/bend.cl"
import "coach/common/rest.cl"
import "warmup.cl"

let logged = [reps: true, weight: true]

group lift(name, reps, weight) {
    let specs = [reps: reps, weight: round(weight, 2.5|kg|)]
    if (name == "squat") {
        squat(specs, logged, [location: true])
    } else if (name == "bench") {
        bench_press(specs, logged, [location: true])
    } else if (name == "row") {
        row(specs, logged, [location: true, gear: "Barbell"])
    } else if (name == "press") {
        press(specs, logged, [location: true, variation: "Strict"])
    } else {
        deadlift(specs, logged, [location: true])
    }
}

// Fives climbing 12.5% a set to the top weight
group ramp(name, top, sets) {
    repeat i:sets {
        lift(name, 5, top * (1 - 12.5 * (5 - i) / 100))
    }
    rest(4|min|)
}

group heavy(squat_top, bench_top, row_top) {
    @title = "Monday — heavy"
    warmup()
    ramp("squat", squat_top, 5)
    ramp("bench", bench_top, 5)
    ramp("row", row_top, 5)
}

group light(squat_top, press_top, deadlift_top) {
    @title = "Wednesday — light"
    warmup()
    ramp("squat", squat_top, 3)
    lift("squat", 5, squat_top * 0.75)
    rest(4|min|)
    ramp("press", press_top, 4)
    ramp("deadlift", deadlift_top, 4)
}

// Four ramping fives, a triple 2.5% over Monday, then a back-off eight
group medium(name, top) {
    ramp(name, top, 4)
    lift(name, 3, top * 102.5 / 100)
    lift(name, 8, top * 0.75)
    rest(4|min|)
}

group deload(squat_top, bench_top, row_top) {
    @title = "Deload"
    warmup()
    ramp("squat", squat_top, 3)
    ramp("bench", bench_top, 3)
    ramp("row", row_top, 3)
}

group main() {
    @title = "Madcow 5×5"
    @description = "Three 8-week cycles of Madcow 5×5. Top sets climb 2.5% a week; a deload week follows each cycle, and the next restarts 5% under the last peak."

    let squat_top = 100|kg|
    let bench_top = 75|kg|
    let row_top = 65|kg|
    let press_top = 47.5|kg|
    let deadlift_top = 120|kg|

    repeat cycle:3 {
        repeat week:8 {
            let k = 1 + 2.5 * (week - 1) / 100
            heavy(squat_top * k, bench_top * k, row_top * k)
            rest(2|day|)
            light(squat_top * k, press_top * k, deadlift_top * k)
            rest(2|day|)
            medium("squat", squat_top * k)
            medium("bench", bench_top * k)
            medium("row", row_top * k)
            rest(3|day|)
        }

        let peak = 1 + 2.5 * 7 / 100
        squat_top = squat_top * peak * 0.95
        bench_top = bench_top * peak * 0.95
        row_top = row_top * peak * 0.95
        press_top = press_top * peak * 0.95
        deadlift_top = deadlift_top * peak * 0.95

        if (cycle < 3) {
            repeat 3 {
                deload(squat_top * 0.9, bench_top * 0.9, row_top * 0.9)
                rest(2|day|)
            }
            rest(1|day|)
        }
    }
}

main()

Try it

Run the program in the simulator and step through the first Monday. The squat ramps 50, 62.5, 75, 87.5 and 100 kg, the bench press 37.5, 47.5, 57.5, 65 and 75 kg.

Stepping through 24 weeks of sessions one set at a time is not much fun, so press Plan in the header to swap the simulator for the plan. There you can scroll week by week and check that Monday’s top squat reaches 117.5 kg in week 8, with a 120 kg triple on the Friday, and that the second cycle starts at 112.5 kg after the deload week.