Payback month from a cohort
Write the function that finds the month a cohort's expected margin covers its CAC, then read whether a $500 channel ever pays back.
On this page
A payback month computed by dividing CAC by margin assumes nobody leaves. Finance needs the month in which a cohort's expected margin actually covers what it cost, and one channel in this plan never gets there.
The situation
A subscription product acquires customers at $300 each. A customer contributes $40 of gross margin in month 1 and survives each later month with probability 0.9, so expected margin in month n is 40 × 0.9^(n−1): $40, then $36, then $32.40. Finance wants three payback months: for this cohort; for a scenario in which a retention project lifts monthly survival to 0.95; and for a new channel whose CAC is $500 at the same $40 and 0.9. The planning horizon is 36 months, and a cohort that has not paid back by then is treated as one that does not.
Payback is the definition from CAC, LTV and payback: the first month in which cumulative expected margin, margin × survival summed month by month, reaches CAC. That lesson's running numbers, a $521 CAC, $40 of margin and 5% monthly churn, pay back in month 21 by hand: a fourth case to agree with.
The question
Does the $500 channel ever pay back, and what is moving retention from 0.9 to 0.95 worth in months? Answer by writing solve(cac, margin, retention, horizon=36), the first month in which cumulative expected margin reaches CAC or -1 if it does not within the horizon, and reading its three results.
def solve(cac, margin, retention, horizon=36):
"""First month in which cumulative expected margin per customer reaches cac.
cac: acquisition cost per customer, in dollars
margin: gross margin a paying customer contributes in a month
retention: probability that a customer paying this month pays next month
horizon: months to look ahead
Expected margin in month n is margin * retention ** (n - 1).
Returns the month, counting from 1, or -1 if cac is not reached within horizon.
"""
solve(300, 40, 0.9) -> 14
solve(300, 40, 0.95) -> 10
solve(500, 40, 0.9) -> -1
solve(521, 40, 0.95) -> 21
A strong answer · Rubric · Where answers go wrong · Solution
Write your answer first, then open