Where we start
Business session 1 built the velocity identity: deals times win rate times deal size, divided by cycle length, a convention rather than a law, with its trap in the denominator. Tonight is that denominator, measured properly. Every number on this page comes from the real Olist rows (842 won deals, 5,998 leads from the 2018 cohort) unless it says constructed, and the widget computes all of them in your browser.
★ What you walk out with tonight. A cycle-time report that shows the median and the percentiles instead of one average, a one-line rule for what to do with deals that are still open, and a Kaplan-Meier loop of about twenty lines you can run on your own CRM export. Analyst session 4's history-based forecast reads straight off the curve you build tonight.
A cycle time is a shape, not a number
5 min liveMeasure every won deal from first contact to won date and the 842 real Olist deals do not cluster around a typical value. Half closed within 14 days. A quarter took longer than 54.75 days, a tenth longer than 161.9, and the slowest took 427. The mean, 48.4 days, is 3.5 times the median, because a long right tail drags it up. Put the mean into a velocity formula and you divide by a cycle that most deals never had.
LiveReport the median and the percentiles3 min▶
Median, 14 days. The deal in the middle. It is what a rep means by "a normal deal", and it does not move when one deal takes a year.
p25 5 and p75 54.75. The middle half of won deals closed between 5 and about 55 days. That range is the honest answer to "how long does a deal take".
p90 161.9. One deal in ten took more than five months. Pipeline reviews call these deals stale; Business session 2 asks whether they are slow or dead, and this percentile tells you where "slow" ends for your own history.
Mean 48.4. Real arithmetic, real data, and a misleading summary. Show it beside the median, never alone. If someone asks for "the average cycle", give both and the ratio: 3.5 times is itself a finding about how long the tail is.
Self-studyCheck for a negative cycle before you trust any of it2 min▶
One of the 842 won rows carries a won date 2 days before its first-contact date. A deal cannot close before anyone spoke to the buyer, so this is a logging defect: a back-filled contact date, a lead re-created after the deal, or two systems with different clocks. The widget clips it to 0 so it cannot drag the quantiles below zero, and it sits in the first bar.
Run the same check on your own export: won_date < first_contact_date should return zero rows. If it returns many, the contact date is being overwritten (Analyst session 1's problem again) and your cycle times are measuring the overwrite, not the buyer.
What the mean does to velocity. Velocity divides by cycle length. On the real Olist rows, dividing by the mean (48.4 days) instead of the median (14) makes the same pipeline look 3.5 times slower; dividing by the median makes the typical deal's pace look like the whole pipeline's. Neither is wrong arithmetic. Say which one you used, and show the percentiles so the reader can see the tail you averaged over.
An open deal has not lost yet
5 min liveOn any measurement day, some leads have had months to close and some have had days. A lead first contacted on 28 May and still open on 1 June has not failed; it has been watched for four days. Statisticians call it censored: we know it survived at least that long, and nothing after. Count every open lead as not won and your win rate is too low, worst of all for the newest leads.
LiveWhat censoring does to a win rate3 min▶
The naive share. Wins so far divided by all leads. Every open lead counts as a loss, including one contacted yesterday.
Why it is biased downwards. A lead's chance of having won by the measurement day depends on how long it has been watched. The newer the cohort, the bigger the understatement. Analyst session 2's May 2018 cohort looks weaker partly for this reason, and partly because it really did convert worse; censoring is the reason you cannot tell the two apart on 1 June.
The rule. An open deal contributes the days it was watched, and nothing about the days it was not. It is neither a win nor a loss. Kaplan-Meier, in Part 3, is the bookkeeping that follows this rule.
Self-studyTwo wrong fixes people reach for2 min▶
Drop the open leads. Then the cohort holds only won deals and leads you have already written off, and the win rate jumps far too high. It is survivorship in a different coat, the same trap as Olist's won-only closed-deal table in Analyst session 2.
Wait until everything has closed. Honest, and useless for a forecast: on 1 June 2018 the 13.0% was not knowable for another five months. You need an estimate on the day you have to decide, which is what a survival curve gives you.
The 2018 cohort on 1 June. 5,998 real Olist leads were first contacted from January to May 2018. Seen on 1 June 2018, 10.5% had been won. By November 2018, the same leads had reached 13.0%. Nothing about the buyers changed between those dates; the late-May leads simply had time. A report written on 1 June that called the cohort's win rate 10.5% was not wrong about the past. It was wrong about what the number meant.
The survival curve, without the heavy maths
5 min liveKaplan and Meier published the estimator in 1958 (reported). The idea fits in one line: walk forward day by day; on each day a win happens, multiply the "still not won" share by one minus wins that day over leads still at risk. A censored lead leaves the risk set on its last watched day without counting as a loss. One minus the running product is the cumulative win share. On the real 2018 cohort it climbs to 12.5% by day 150, much closer to the 13.0% known later than the naive 10.5%.
LiveKaplan-Meier on ten leads, by hand4 min▶
Constructed Kettle & Co example. Ten office-tea leads, watched until day 12. Three are won (on days 2, 5 and 10). Three stop being watched early because they arrived late (censored on days 3, 6 and 8). Four are still open at day 12.
Same three wins, two answers. The naive share treats the three late arrivals as losses; Kaplan-Meier lets each of them count only while it was watched. Check the risk set on each line: it shrinks by the wins and the censored leads of earlier days, and nothing else.
Self-studyWhat it fixes, what it cannot, and where Analyst session 4 uses it3 min▶
It fixes unequal follow-up. Leads watched for four days and leads watched for five months sit in one estimate without the short ones counting as losses.
It cannot see past the longest watch. On 1 June 2018 the oldest 2018 lead had been watched about five months, and nobody had been watched for a year. Wins that arrive later than anyone has been observed are invisible, which is why the curve stops at 12.5% by day 150 while the truth was 13.0%. It also assumes censoring tells you nothing about the lead: a lead dropped from the export because the rep gave up on it is not censored, it is a hidden loss.
The question a forecast needs. The same curve answers "an open deal is a days old; what is the chance it closes in the next 91 days?" as (S(a) minus S(a + 91)) divided by S(a), where S is the still-not-won share. In the ten-lead example, a lead aged 3 days has (0.9000 minus 0.6300) / 0.9000 = 30.0% chance of winning by day 10. On the real table, a lead aged 60 days moving to day 150 (90 days, close to a quarter): (0.890 minus 0.875) / 0.890, about 1.7%, our arithmetic on two rows of the widget's table. That is the engine of the history-based forecast in Analyst session 4: old open deals are worth very little, however confident the rep sounds.
Survival models with covariates and time-series forecasting go well beyond this; Timeseries Forecasting owns the models. Here the curve is a shape you can read and a loop you can write.
Three numbers for one cohort. On the same 5,998 real Olist leads, all three answers were available or became available: 10.5% won so far on 1 June 2018, 12.5% by day 150 on the survival curve, 13.0% known by November. The survival curve recovers most of the gap on the day you need the answer. Report it with its blind spot stated: it is a floor for wins that take longer than anyone has yet been watched.
Read the curve, then write the loop
★ 22 min · everyone buildsThe widget holds the real Olist rows and computes two things in your browser: the cycle-time distribution of the 842 won deals, and the Kaplan-Meier curve for the 2018 cohort as seen on 1 June 2018. There is nothing to toggle. Read each block, copy what it prints, and finish by writing the loop yourself.
Step 1 · Read the four tiles. Copy them in order. Then say out loud why the fourth is bigger than the first and what it would do to a velocity figure.
Step 2 · Read the histogram. Seven bars, left to right. Add the first two: that is how many of the 842 won deals closed inside two weeks. Note that the last two buckets are wide, so their bars are not comparable by height with the first.
Step 3 · Read the verdict. Three numbers for one cohort. Write which one you would have put in a 1 June board pack, and the sentence you would put next to it.
Step 4 · Read the Kaplan-Meier table. Copy all six rows. Mark where the curve flattens: the jump from day 7 to day 14 is bigger than the jump from day 90 to day 150.
Step 5 · Write the loop. Plain Python, no survival library, the same bookkeeping as the ten-lead example. Run it first on those ten constructed leads and check you get 37.0% by day 10. Then point it at your own CRM export. Its output on the Olist rows is whatever the widget printed in step 4; do not quote anything else from it until you have run it yourself.
Log the clip. The max(0, ...) in step 5 is there for the one real row won 2 days before its first contact. Keep the clip, but also count how many rows needed it and print that number beside the curve. A clip that hides one row is a footnote; a clip that hides hundreds is a data problem.
Before Analyst session 4
30 min- Profile your own cycle. For every won deal in the last two years, compute days from first contact to won and report p25, median, p75, p90 and mean. Write the mean-to-median ratio next to them.
- Run the defect check. Count rows where the won date is before the first-contact date. Find one and trace why.
- Measure the censoring gap. Pick a cohort at least six months old. Compute its naive win share as of the day it was three months old, its Kaplan-Meier share as of that same day, and its win share today.
- Price an old open deal. With your curve, compute the chance that an open deal aged 60 days closes in the next 91 days, and compare it with what the rep's stage implies. Bring both numbers to Analyst session 4.
Three questions
Clear all three and Analyst session 3 gets stamped in your passport.
1 · On the real won deals the median cycle is 14 days and the mean is 48.4. Why report the median first?
The mean is correct arithmetic but describes no typical deal: it sits in a bucket holding 97 of 842 deals. Show the median, the percentiles, and the mean beside them.
2 · A lead was first contacted on 28 May and is still open on 1 June. How should a win-rate estimate treat it?
Four days of watching says it survived four days, nothing more. Counting it as lost understates (10.5% against 13.0%); dropping it overstates.
3 · Kaplan-Meier gives 12.5% by day 150 for the 2018 cohort; the share known later is 13.0%. What explains the remaining gap?
The estimator recovers most of the gap from 10.5%, and stays a floor for the slowest wins. State that blind spot whenever you report it.
What this session teaches, and where it came from
Every fact on this page, and its verification tier, is recorded in the course's source map.
Analyst session 3 cheat sheet · pin this
You have a cycle-time curve and a rule for open deals. Analyst session 4 puts three forecasts side by side on one quarter of Kettle & Co's pipeline: the reps' commit, a stage-weighted sum, and a history-based forecast that prices every open deal with the curve you built tonight.