lección 7
Día 5 -- A/B testing y la presentación a Meridian Capital
Diseñas el framework de A/B testing con significancia estadística. Acompañas a Marta a la presentación y el dashboard cuenta la historia correcta.
⏱ 40 min
### Viernes, 7:30 AM -- El día de la verdad
El framework de A/B testing de hoy funciona sobre parámetros (baseline, efecto mínimo detectable, DAU) y no lee ficheros directamente. Esos parámetros salen de las métricas que calculaste antes con `datos/reproducciones_eventos.parquet` y `datos/suscripciones.csv`: el baseline de completion (~55%) y el DAU (~2100) son las entradas que usarás. Si quieres recalcularlos para tu propio experimento, parte de esos ficheros guardados en `datos/`.
Hoy es viernes. A las 11:00 Marta se sienta frente a tres partners de Meridian Capital con tu dashboard proyectado en la pantalla. Pero antes de eso, tienes 3 horas para completar la última pieza del puzzle: un framework de A/B testing que demuestre a los inversores que StreamVibe no solo mide -- sino que experimenta de forma rigurosa para mejorar.
Los VCs sofisticados ya no se conforman con métricas bonitas. Quieren ver que el equipo tiene una cultura de experimentación: "¿Cómo sabéis que las mejoras son reales y no ruido estadístico?" Si puedes mostrar un framework de A/B testing funcionando -- aunque sea con un solo experimento -- demuestras madurez analítica que poca startup pre-Serie A tiene.
### ¿Por qué A/B testing en una startup de 15K usuarios?
La objeción habitual es "somos muy pequeños para hacer A/B tests". Es falsa. Con 15K MAU y ~2.100 DAU, puedes hacer tests que alcanzan significancia estadística en 7-14 días para efectos del 10% o más. No es Netflix con millones de usuarios donde puedes detectar mejoras del 0.5% -- pero sí puedes validar decisiones grandes como "¿el onboarding nuevo retiene más?" o "¿el autoplay entre episodios aumenta el watch time?"
La razón estratégica para tener A/B testing desde el día 1 es cultural, no técnica. Si el equipo de producto se acostumbra a lanzar features sin validar, cuando tengan 150K usuarios seguirán sin validar -- pero ahora con consecuencias mucho mayores. Establecer la cultura de "medimos antes de decidir" cuando eres pequeño es infinitamente más fácil que implantarla después.
Además, los inversores lo saben. Cuando Meridian Capital pregunta "¿hacéis A/B testing?", no preguntan si podéis detectar efectos del 0.1%. Preguntan: "¿tenéis una cultura de experimentación? ¿tomáis decisiones de producto basadas en evidencia o en opinión del fundador?" Tener un framework funcionando, aunque sea simple, demuestra madurez analítica.
### El framework de A/B testing
El framework tiene 4 componentes: asignación de usuarios a variantes, recolección de métricas por variante, cálculo de significancia estadística y decisión (ship/kill/continue). Lo implementas como un módulo Python que puede correr manualmente o integrase con el pipeline diario.
1# Framework de A/B Testing para StreamVibe2# Componente 1: Diseño del experimento34from dataclasses import dataclass5from typing import Optional6import hashlib789@dataclass10class Experiment:11 """Definición de un experimento A/B."""12 id: str13 name: str14 description: str15 metric: str # La métrica principal que mides16 hypothesis: str # "Si hacemos X, entonces Y aumentará en Z%"17 min_sample_size: int # Usuarios mínimos por variante18 min_days: int # Duración mínima19 variants: list[str] # ['control', 'treatment'] o más20 traffic_split: list[float] # [0.5, 0.5] para 50/50212223def assign_user_to_variant(24 user_id: int,25 experiment_id: str,26 variants: list[str],27 traffic_split: list[float]28) -> str:29 """Asigna un usuario a una variante de forma determinística.3031 Usa hash(user_id + experiment_id) para que:32 - El mismo usuario siempre vea la misma variante33 - La asignación sea uniforme sin base de datos34 - Diferentes experimentos tengan asignaciones independientes35 """36 hash_input = f"{user_id}:{experiment_id}"37 hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)38 normalized = (hash_value % 10000) / 10000.0 # 0.0 a 1.03940 cumulative = 0.041 for i, split in enumerate(traffic_split):42 cumulative += split43 if normalized < cumulative:44 return variants[i]4546 return variants[-1] # Fallback al último
Asignación determinística con hash: sin base de datos, sin estado, reproducible.
1# Componente 2: Análisis de significancia estadística23import numpy as np4from scipy import stats5from dataclasses import dataclass678@dataclass9class ABTestResult:10 """Resultado del análisis de un A/B test."""11 experiment_id: str12 control_mean: float13 treatment_mean: float14 relative_lift: float # (treatment - control) / control * 10015 p_value: float16 confidence_level: float # 1 - p_value17 is_significant: bool # p_value < 0.0518 sample_size_control: int19 sample_size_treatment: int20 recommendation: str # 'ship', 'kill', 'continue'212223def analyze_continuous_metric(24 control_values: list[float],25 treatment_values: list[float],26 alpha: float = 0.0527) -> ABTestResult:28 """Analiza un A/B test para métricas continuas (watch_time, sessions).29 Usa t-test de Welch (no asume varianzas iguales).30 """31 control = np.array(control_values)32 treatment = np.array(treatment_values)3334 control_mean = control.mean()35 treatment_mean = treatment.mean()36 relative_lift = (treatment_mean - control_mean) / control_mean * 1003738 # Welch's t-test (dos colas)39 t_stat, p_value = stats.ttest_ind(control, treatment, equal_var=False)4041 is_significant = p_value < alpha4243 # Recomendación44 if not is_significant:45 recommendation = 'continue' if len(control) < 1000 else 'kill'46 elif relative_lift > 0:47 recommendation = 'ship'48 else:49 recommendation = 'kill'5051 return ABTestResult(52 experiment_id="",53 control_mean=round(control_mean, 3),54 treatment_mean=round(treatment_mean, 3),55 relative_lift=round(relative_lift, 2),56 p_value=round(p_value, 4),57 confidence_level=round((1 - p_value) * 100, 1),58 is_significant=is_significant,59 sample_size_control=len(control),60 sample_size_treatment=len(treatment),61 recommendation=recommendation,62 )636465def analyze_conversion_metric(66 control_conversions: int,67 control_total: int,68 treatment_conversions: int,69 treatment_total: int,70 alpha: float = 0.0571) -> ABTestResult:72 """Analiza un A/B test para métricas de conversión (% que completa, % que vuelve).73 Usa chi-squared test.74 """75 # Tabla de contingencia76 table = np.array([77 [control_conversions, control_total - control_conversions],78 [treatment_conversions, treatment_total - treatment_conversions]79 ])8081 chi2, p_value, dof, expected = stats.chi2_contingency(table)8283 control_rate = control_conversions / control_total84 treatment_rate = treatment_conversions / treatment_total85 relative_lift = (treatment_rate - control_rate) / control_rate * 1008687 is_significant = p_value < alpha8889 if not is_significant:90 recommendation = 'continue' if control_total < 500 else 'kill'91 elif relative_lift > 0:92 recommendation = 'ship'93 else:94 recommendation = 'kill'9596 return ABTestResult(97 experiment_id="",98 control_mean=round(control_rate, 4),99 treatment_mean=round(treatment_rate, 4),100 relative_lift=round(relative_lift, 2),101 p_value=round(p_value, 4),102 confidence_level=round((1 - p_value) * 100, 1),103 is_significant=is_significant,104 sample_size_control=control_total,105 sample_size_treatment=treatment_total,106 recommendation=recommendation,107 )
Análisis estadístico: t-test de Welch para métricas continuas, chi-squared para conversión.
### El primer experimento: autoplay entre episodios
Daniel ya tenía implementado un feature flag para autoplay (reproducir el siguiente episodio automáticamente tras 5 segundos de cuenta atrás). Estaba desactivado porque "no sabíamos si los usuarios lo querían o les molestaba". Perfecto: es tu primer A/B test. Hipótesis: "Si activamos autoplay entre episodios de series, el watch time por sesión aumentará al menos un 15% porque reduce la fricción entre episodios."
Configuras el experimento: 50% de usuarios (asignados por hash) ven autoplay activado, 50% siguen con el comportamiento actual. Métricas que rastrear: watch_time por sesión (primaria), completion_rate de series (secundaria), tasa de skip del autoplay (guardrail -- si > 60% de skips, el feature molesta).
### 10:30 AM -- Preparando la presentación
Marta te pide 10 minutos para repasar el dashboard antes de la reunión. Te sientas con ella en la sala y recorren las 3 pantallas:
- 01.Pantalla 1 -- KPIs Hero: "15.100 MAU, creciendo al 11% mensual. Stickiness del 14%. Retención D7 del 38%." Marta práctica: "Nuestros usuarios vuelven. No es crecimiento inflado con marketing -- es producto."
- 02.Pantalla 2 -- Engagement: "El 55% de nuestros usuarios son regulars o power users. Watch time medio de 31 minutos por sesión. El contenido se termina en un 42% de los casos -- vs. 30% de media en plataformas generalistas." Marta práctica: "Nuestra curación funciona. La gente no hace zapping -- se sienta a ver."
- 03.Pantalla 3 -- Contenido: "Los documentales de true crime y series cortas son nuestro sweet spot: 68% de completion, 3x más ROI por euro de licencia. Nuestra estrategia de contenido está validada con datos." Marta práctica: "Sabemos exactamente qué contenido comprar y por qué."
Marta te mira y dice: "Hace 5 días no teníamos ni un número real. Ahora tengo una historia completa que contar con datos de 14 meses detrás. Si no cierro está ronda, no es por falta de métricas." Se levanta, se alisa la chaqueta y se va a la sala de reuniones.
### 11:00 AM -- La presentación a Meridian Capital
No estás en la sala (Marta decidió que era mejor ir sola con Daniel), pero a las 12:15 te llega un mensaje por Slack:
Marta (Slack, 12:15): "Han pedido ver el dashboard EN VIVO. Les he enseñado las cohortes y el crecimiento MoM y se han mirado entre ellos con cara de aprobación. Preguntas: cómo calculamos retention (les he dicho ventana +-1 día y han asentido), qué stack usamos (les ha encantado que gastemos 12 EUR/mes en vez de 400), y si tenemos A/B testing (les he enseñado el framework del autoplay). Nos han pedido un data room para la due diligence. Esto pinta MUY bien. Gracias."
A las 14:00 Marta sale de la sala con una sonrisa: "No es oficial todavía, pero me han dicho que van a preparar un term sheet la semana que viene. Serie A de 4M EUR. La mitad del mérito es del dashboard -- han visto que tomamos decisiones con datos, no con intuición. Exactamente la señal que buscaban."
Lo que acabas de hacer en 5 días: pasar de CERO infraestructura de datos a un dashboard que ayuda a cerrar una ronda de 4M EUR. No porque el dashboard sea bonito -- sino porque los datos cuentan una historia real, verificable, y que demuestra que el producto funciona. Eso es lo que un senior data engineer aporta a una startup.
### Lo que viene: la hoja de ruta de datos post-Serie A
- 01.Semana 2: Event tracking real en el reproductor (ya no dependemos de la tabla playbacks legacy)
- 02.Mes 1: Contratar un analista de datos -- Sofía necesita soporte continuo para decisiones de contenido
- 03.Mes 2: Migrar cron -> Airflow cuando tengamos > 10 pipelines
- 04.Mes 3: Implementar el A/B testing como parte del ciclo de producto (1 test por sprint)
- 05.Mes 4: Evaluar DuckDB -> Redshift Serverless si el volumen lo justifica
- 06.Mes 6: Recomendaciones v2 con modelo de embeddings (si contratamos ML engineer)
### Resumen del Día 5
- Diseñaste framework de A/B testing con asignación determinística y análisis estadístico
- Configuraste el primer experimento: autoplay entre episodios (t-test + chi-squared)
- Preparaste a Marta para la presentación: 3 pantallas con narrativa secuencial
- La presentación a Meridian Capital fue un éxito: term sheet para Serie A de 4M EUR
- Documentaste hoja de ruta de datos para los próximos 6 meses post-ronda
- En 5 días fuiste de CERO a una infraestructura de datos que aportó valor directo al negocio
## ejercicios
Framework completo de A/B testing
Implementa el framework de A/B testing para StreamVibe: asignación determinística de usuarios a variantes, cálculo de tamaño de muestra necesario, y análisis de resultados con chi-squared test para métricas de conversión.
Diseñar el experimento de autoplay
Diseña el experimento completo de autoplay: hipótesis, métricas, tamaño de muestra, duración estimada y criterios de éxito/fallo. Genera el documento de diseño que presentarías a Marta y Daniel.
Calculadora de tamaño de muestra y viabilidad
Implementa una herramienta que calcule cuántos usuarios necesitas y cuántos días tardará un A/B test dado el DAU de StreamVibe, el baseline y el efecto mínimo detectable.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...