Source code · Python
model.py
"""Twilio (TWLO) owner-FCF DCF. Actuals from the Q2 2026 10-Q and FY2025 release;2026 anchored to company guidance; 2027-2030 are explicit analyst assumptions."""import json # ---- reported facts ($M) ----FY24 = dict(revenue=4458.0, gross_profit=2278.2, gaap_op=-53.7, fcf=657.5)FY25 = dict(revenue=5067.2, gross_profit=2478.7, gaap_op=157.8, nongaap_op=924.0, fcf=945.4)H1_26 = dict(revenue=2905.996, gross_profit=1410.110, gaap_op=192.212, ocf=525.591, cap_sw=33.383, capex=7.218, sbc=278.423)H1_26['fcf'] = H1_26['ocf'] - H1_26['cap_sw'] - H1_26['capex']Q2_26 = dict(revenue=1499.089, gaap_op=84.546, nongaap_op=284.633, fcf=352.645)BAL = dict(cash=823.261, st_securities=1833.069, debt_principal=1000.0, equity_method=250.525)SHARES_OUT, SHARES_DILUTED = 153.575220, 159.708166 # July 24 2026; Q2 weighted dilutedGUIDE_26 = dict(reported_growth=(0.18, 0.185), organic_growth=(0.13, 0.135), fcf=(1135, 1155), nongaap_op=(1135, 1155)) def forecast(c): rev = FY25['revenue'] * (1 + sum(GUIDE_26['reported_growth']) / 2) if c['use_guidance'] else FY25['revenue'] * (1 + c['g26']) rows = [] fcf26 = sum(GUIDE_26['fcf']) / 2 if c['use_guidance'] else rev * c['fcf_m'][0] sbc26 = H1_26['sbc'] * 2 rows.append(dict(year=2026, revenue=rev, fcf=fcf26, sbc=sbc26)) for i, g in enumerate(c['growth']): rev *= 1 + g rows.append(dict(year=2027 + i, revenue=rev, fcf=rev * c['fcf_m'][i + 1], sbc=rev * c['sbc_m'][i])) for r in rows: r['owner_fcf'] = r['fcf'] - r['sbc'] r['fcf_margin'] = r['fcf'] / r['revenue'] return rows def value(c, wacc=None, g=None): wacc = c['wacc'] if wacc is None else wacc g = c['g'] if g is None else g rows = forecast(c) # valuation date 14 Oct 2026; remaining 2026 owner FCF = full-year minus first half, received ~0.1y out rem26 = rows[0]['owner_fcf'] - (H1_26['fcf'] - H1_26['sbc']) pv = rem26 / (1 + wacc) ** 0.1 for k, r in enumerate(rows[1:]): t = 0.71 + k # mid-year of 2027 is 0.71y after 14 Oct 2026 r['pv'] = r['owner_fcf'] / (1 + wacc) ** t pv += r['pv'] last = rows[-1] tv = last['owner_fcf'] * (1 + g) / (wacc - g) pv_tv = tv / (1 + wacc) ** (0.71 + len(rows) - 2) net_cash = BAL['cash'] + BAL['st_securities'] - BAL['debt_principal'] equity = pv + pv_tv + net_cash + BAL['equity_method'] return dict(per_share=equity / SHARES_DILUTED, pv_fcf=pv, pv_tv=pv_tv, tv_share=pv_tv / (pv + pv_tv), net_cash=net_cash, equity=equity, rows=rows, rem26=rem26) BASE = dict(use_guidance=True, growth=[0.12, 0.11, 0.10, 0.09], fcf_m=[None, 0.205, 0.215, 0.225, 0.235], sbc_m=[0.085, 0.080, 0.075, 0.070], wacc=0.10, g=0.03)BEAR = dict(use_guidance=True, growth=[0.08, 0.07, 0.06, 0.05], fcf_m=[None, 0.19, 0.19, 0.19, 0.19], sbc_m=[0.09, 0.09, 0.09, 0.09], wacc=0.105, g=0.025)BULL = dict(use_guidance=True, growth=[0.15, 0.14, 0.13, 0.12], fcf_m=[None, 0.215, 0.235, 0.25, 0.26], sbc_m=[0.08, 0.07, 0.065, 0.06], wacc=0.095, g=0.035) out = {}for name, c in (('base', BASE), ('bear', BEAR), ('bull', BULL)): v = value(c) out[name] = dict(fair_value=round(v['per_share']), tv_share=round(v['tv_share'], 3), pv_fcf=round(v['pv_fcf']), pv_tv=round(v['pv_tv']), assumptions=c, rows=[{k: (round(x, 4) if k == 'fcf_margin' else round(x, 1) if isinstance(x, float) else x) for k, x in r.items()} for r in v['rows']]) print(f"{name}: fair value ${v['per_share']:.0f} | PV FCF {v['pv_fcf']:.0f} PV TV {v['pv_tv']:.0f} (TV {v['tv_share']:.0%}) | net cash {v['net_cash']:.0f}")b = value(BASE)for r in b['rows']: print(f" {r['year']}: revenue {r['revenue']:7.0f} | FCF {r['fcf']:6.0f} ({r['fcf_margin']:.1%}) | SBC {r['sbc']:5.0f} | owner FCF {r['owner_fcf']:6.0f}")grid = {}for w in (0.09, 0.095, 0.10, 0.105, 0.11): grid[str(w)] = {str(g): round(value(BASE, w, g)['per_share']) for g in (0.02, 0.025, 0.03, 0.035, 0.04)}print('sensitivity (rows WACC, cols g):'); [print(' ', k, v) for k, v in grid.items()]out['sensitivity'] = grid# the same base case on company defined free cash flow (stock pay not deducted), for comparison_sbc = H1_26['sbc']; H1_26['sbc'] = 0.0out['base_company_fcf'] = round(value(dict(BASE, sbc_m=[0, 0, 0, 0]))['per_share'])H1_26['sbc'] = _sbcprint('base on company defined FCF:', out['base_company_fcf'])out['facts'] = dict(FY24=FY24, FY25=FY25, H1_26=H1_26, Q2_26=Q2_26, balance=BAL, shares_out=SHARES_OUT, shares_diluted=SHARES_DILUTED, guidance_2026=GUIDE_26)print('H1 2026 FCF', round(H1_26['fcf'], 1), '| remaining 2026 owner FCF', round(b['rem26'], 1))# ---- Street consensus, Koyfin, 14 Oct 2026 (user supplied screenshots) ----STREET = dict( as_of='2026-10-14', source='Koyfin', price=277.38, market_cap_b=42.60, forward_pe=45.0, revenue={'2025': 5070, '2026': 6000, '2027': 6690, '2028': 7420}, ebitda={'2025': 1120, '2026': 1250, '2027': 1480, '2028': 1730}, eps_adj={'2025': 4.89, '2026': 5.93, '2027': 6.80, '2028': 7.77}, eps_gaap={'2025': 0.21, '2026': 8.60, '2027': 3.52, '2028': 5.00}, target=dict(low=165.0, avg=268.39, high=335.0), analysts=30, ratings={'Strong buy': 6, 'Buy': 19, 'Hold': 3, 'Sell': 1, 'Strong sell': 1}, next_earnings='2026-10-29')out['street'] = STREET # ---- reverse DCF: what the market price implies ----def solve(fn, target, lo, hi): for _ in range(80): mid = (lo + hi) / 2 if fn(mid) < target: lo = mid else: hi = mid return midprice = STREET['price']implied_g_owner = solve(lambda g: value(BASE, BASE['wacc'], g)['per_share'], price, 0.0, 0.0999)_sbc = H1_26['sbc']; H1_26['sbc'] = 0.0implied_g_company = solve(lambda g: value(dict(BASE, sbc_m=[0, 0, 0, 0]), BASE['wacc'], g)['per_share'], price, 0.0, 0.0999)H1_26['sbc'] = _sbcimplied_wacc_owner = solve(lambda w: -value(BASE, w, BASE['g'])['per_share'], -price, 0.04, 0.10)out['reverse_dcf'] = dict(price=price, implied_g_owner=round(implied_g_owner, 4), implied_g_company=round(implied_g_company, 4), implied_wacc_owner=round(implied_wacc_owner, 4))print('reverse DCF at', price, '-> terminal growth on owner FCF', round(implied_g_owner * 100, 2), '% | on company FCF', round(implied_g_company * 100, 2), '% | cost of capital at 3% growth', round(implied_wacc_owner * 100, 2), '%')model_rev = {str(r['year']): r['revenue'] for r in forecast(BASE)}print('revenue vs street:', {y: f"{model_rev[y]:.0f} vs {STREET['revenue'][y]} ({model_rev[y]/STREET['revenue'][y]-1:+.1%})" for y in ('2026', '2027', '2028')})# Street check: the cost of capital at which the DCF reaches the Street targets.target = STREET['target']out['street_check'] = dict( wacc_at_avg_owner=round(solve(lambda w: -value(BASE, w, BASE['g'])['per_share'], -target['avg'], 0.04, 0.2), 4), wacc_at_avg_company=round(solve(lambda w: -value(dict(BASE, sbc_m=[0, 0, 0, 0]), w, BASE['g'])['per_share'], -target['avg'], 0.04, 0.2), 4), wacc_at_low_owner=round(solve(lambda w: -value(BASE, w, BASE['g'])['per_share'], -target['low'], 0.04, 0.2), 4), wacc_at_high_owner=round(solve(lambda w: -value(BASE, w, BASE['g'])['per_share'], -target['high'], 0.04, 0.2), 4),)print('street check:', out['street_check'])json.dump(out, open('twlo_model.json', 'w'), indent=1)