analise-officers

Score e validação

Data de referência (“hoje”): 31/12/2017. As tabelas entre marcadores AUTO são geradas por python -m scorer.docs a partir de solution/data/processed/backtest_metrics.json (que python -m scorer.validate calcula dos dados). Os números do texto são conferidos contra o mesmo arquivo por tests/test_docs_numbers.py. A seção 9 (critério pré-registrado) foi escrita às 16:28 de 25/10/2026, antes de existir o código do backtest; o relato da ordem real está em process-log/03_bloco-3.md. A curva do score foi trocada depois do backtest, a pedido do Rafael: a seção 0 conta o que mudou e a seção 9 declara que é uma mudança pós-backtest.

0. Correção após revisão do Rafael

O Rafael abriu a página publicada como vendedor e viu a chance de ganho constante, de 0 a 95 dias, para todo deal do Foque. Isso contradiz o que o briefing já mostrava (no corte de 30/09/2017, 50% de ganhos até 30 dias, 34% de 31 a 60, 7% de 61 a 90 e 0% acima de 90), e tinha três efeitos na tela dele: o deal do topo da Rosalina Dieter era um GTK 500 com 95 dias e score 100; dentro do Foque a ordem virou uma ordenação por preço; e a caixa “Atenção” do Foque admitia o erro em vez de corrigi-lo. A curva v1 (“platô + queda”, seção 2) foi mantida só para comparação.

Diagnóstico. Dois motivos achatavam a curva. O primeiro é que o treino empilhava fotos de fases diferentes do trimestre, que têm padrões opostos e se cancelam:

Taxa de ganho em 90 dias por idade do deal na foto, com o número de casos entre parênteses. Fotos de treino de hoje (31/12/2017): fim de trimestre = 31/03/2017, 30/06/2017 e 30/09/2017; meio de trimestre = 30/04/2017, 31/05/2017, 31/07/2017 e 31/08/2017.

Idade do deal na foto Fotos de fim de trimestre Fotos de meio de trimestre Todas juntas
0 a 30 dias 49,5% (2.055) 31,7% (2.375) 40,0% (4.430)
31 a 60 dias 41,7% (1.449) 41,9% (1.953) 41,8% (3.402)
61 a 90 dias 15,9% (793) 48,3% (1.541) 37,3% (2.334)
91 a 105 dias 0,0% (153) 39,9% (499) 30,5% (652)
106 a 120 dias 0,0% (138) 22,8% (281) 15,3% (419)

Mesmas fotos, uma coluna por mês do trimestre:

| Idade do deal na foto | 1º mês do trimestre (jan, abr, jul, out) | 2º mês (fev, mai, ago, nov) | 3º mês (mar, jun, set, dez) | | :— | —: | —: | —: | | 0 a 30 dias | 29,5% (1.146) | 33,8% (1.229) | 49,5% (2.055) | | 31 a 60 dias | 52,6% (1.068) | 29,0% (885) | 41,7% (1.449) | | 61 a 90 dias | 47,2% (911) | 49,8% (630) | 15,9% (793) | | 91 a 105 dias | 37,4% (227) | 41,9% (272) | 0,0% (153) | | 106 a 120 dias | 12,3% (114) | 29,9% (167) | 0,0% (138) |

Nas fotos de fim de trimestre (março, junho e setembro) a taxa cai com a idade e chega a zero depois dos 90 dias; nas de meio de trimestre ela sobe até os 90 dias e só cai depois. Juntas, dão uma taxa quase plana. O segundo motivo é o desenho da v1: com logit = b0 + b1 * max(0, idade - joelho) / 30, a chance é constante antes do joelho por construção, mesmo que os dados peçam o contrário. A data de referência (31/12) e os cortes de 30/06 e 30/09 são fins de trimestre.

O que mudou. A curva v2 (seção 2) é monotonicamente não crescente desde o dia 0, por faixas de idade isotônicas, e cada corte treina só com as fotos da mesma fase do trimestre que ele. Os limites das listas saem da curva. Em números:

O que a correção não resolveu (os detalhes estão nas seções 6, 7 e 10): a v2 não é melhor que a v1 na receita média dos cortes de 30/06, 31/07 e 31/08 (empata ou perde por menos de um ponto percentual); a vantagem está no corte de 30/09, que é de fim de trimestre como hoje. Dentro do Foque a AUC continua perto de um sorteio. Três dos quatro cortes têm uma só foto de treino, porque agora só vale a fase do trimestre do corte.

1. Resumo

O score responde a uma pergunta: dos negócios abertos hoje, quais valem a próxima hora do vendedor? Para cada negócio, a ferramenta estima a chance de ele ser ganho nos próximos 90 dias olhando só para a idade dele, isto é, há quanto tempo está aberto. A estimativa vem de como negócios da mesma idade se comportaram no passado, nas fotos do mesmo ponto do trimestre (hoje é o último mês do trimestre). A chance cai com a idade desde o primeiro dia, e o limite do Foque é a idade em que ela chega à metade da de um negócio novo; o Limpe começa quando a chance fica abaixo de 2% ou o negócio passa do maior ciclo já ganho (nenhum negócio do histórico foi ganho depois de 138 dias aberto). A chance multiplicada pelo preço de tabela dá o valor esperado, e o score de 0 a 100 é esse valor numa escala que não deixa o produto mais caro engolir os demais. Para saber se funciona, voltamos no tempo quatro vezes (30/06, 31/07, 31/08 e 30/09/2017), usando em cada uma só o que o CRM sabia naquele dia, e conferimos o que aconteceu depois. Em média, os 20% de negócios no topo do score v2 concentraram 62,5% da receita que foi de fato ganha em seguida (61,1% com a curva v1), contra 48,1% se o time ordenasse só pelo preço e 29,7% se ordenasse pelos mais recentes; um sorteio daria 20,0%. O score ficou à frente dos três nos quatro cortes, pelo critério que fixamos antes de olhar o resultado, mas a curva v2 é uma mudança feita depois do backtest, a pedido do Rafael. Há quatro ressalvas. Primeira: se a pergunta for só “quem vai ganhar”, e não “onde está o dinheiro”, ordenar pelos mais recentes acerta mais em três dos quatro cortes. Segunda: entre os negócios que já foram encerrados (ganhos ou perdidos), o score não é melhor que ordenar pelo preço; a vantagem vem de tirar do topo os negócios parados há muito tempo. Terceira: só entre os negócios de até 90 dias (a ordem dentro do Foque) o score v2 ordena melhor que o preço apenas no corte de fim de trimestre, e a AUC fica perto de um sorteio. Quarta: três dos quatro cortes treinam com uma foto só. Os dados são sintéticos, e parte do padrão que o score usa (o teto de 138 dias e a queda no fim do trimestre) provavelmente é do gerador, não do comércio real.

2. Fórmula

chance(idade)   = taxa de ganho em 90 dias por faixa de 15 dias de idade, não crescente (PAVA),
                  interpolada linearmente entre os pontos médios das faixas
valor esperado  = chance(idade) * preço de tabela
score           = 100 * ln(1 + VE / VE_min) / ln(1 + VE_max / VE_min)      (arredondado, de 0 a 100)
VE_min / VE_max = chance de um deal novo * menor / maior preço do catálogo

Parâmetros de hoje e a regra das listas (curva v2):

| Lista | Regra | Deals | Valor de tabela | Valor esperado | | :— | :— | —: | —: | —: | | Foque | idade até 61 dias | 60 | US$ 123.253 | US$ 47.500 | | Reative | 62 a 95 dias | 66 | US$ 177.537 | US$ 17.818 | | Limpe | mais de 95 dias | 1.463 | US$ 3.591.439 | US$ 99 | | Qualifique | Prospecting (sem data) | 500 | US$ 1.073.986 | — |

Limpe de hoje Deals Valor de tabela
Acima do maior ciclo já ganho (138 dias) 1.291 US$ 3.198.664
Só pela chance (idade até o maior ciclo, chance abaixo do mínimo) 172 US$ 392.775

| Lista | Faixas fixas do briefing (90 e 138 dias) | Limiares aprendidos pela curva v2 | | :— | —: | —: | | Foque | 110 | 60 | | Reative | 188 | 66 | | Limpe | 1.291 | 1.463 |

Antes e depois da correção, as mesmas listas de hoje:

| Lista | Regra v1 | Deals (v1) | Valor de tabela (v1) | Regra v2 | Deals (v2) | Valor de tabela (v2) | | :— | :— | —: | —: | :— | —: | —: | | Foque | idade até 95 dias | 126 | US$ 300.790 | idade até 61 dias | 60 | US$ 123.253 | | Reative | 96 a 138 dias | 172 | US$ 392.775 | 62 a 95 dias | 66 | US$ 177.537 | | Limpe | mais de 138 dias | 1.291 | US$ 3.198.664 | mais de 95 dias | 1.463 | US$ 3.591.439 | | Qualifique | Prospecting (sem data) | 500 | US$ 1.073.986 | Prospecting (sem data) | 500 | US$ 1.073.986 |

Parâmetros do modelo v2 ajustado em cada corte (cada um vê só os dados até a sua data):

| Modelo ajustado até | Mês do trimestre | Chance de deal novo | Fim do Foque (dias) | Fim do Reative (dias) | O Limpe começa por | Fotos | Linhas de treino | Taxa base de treino | | :— | —: | —: | —: | —: | :— | —: | —: | —: | | 30/06/2017 | 3 | 49,3% | 79 | 95 | chance abaixo de 2% | 1 | 1.330 | 45,8% | | 31/07/2017 | 1 | 46,8% | 109 | 125 | chance abaixo de 2% | 1 | 1.618 | 44,4% | | 31/08/2017 | 2 | 43,4% | 133 | 138 | maior ciclo já ganho | 1 | 1.535 | 40,1% | | 30/09/2017 | 3 | 50,2% | 75 | 95 | chance abaixo de 2% | 2 | 3.016 | 40,0% | | 31/12/2017 (hoje) | 3 | 49,5% | 61 | 95 | chance abaixo de 2% | 3 | 5.425 | 32,2% |

Fim do Foque = última idade em que a chance ainda é pelo menos 50% da de um deal novo. Fim do Reative = o que chegar primeiro: chance abaixo de 2% ou idade acima do maior ciclo já ganho até a data do modelo (138, 138, 138, 138 dias nos quatro cortes e 138 hoje). Casos em que a fase do trimestre não tinha foto elegível e o ajuste usou todas as fotos: 0.

A chance que cada modelo dá por idade:

| Modelo ajustado até | 0 dias | 15 dias | 30 dias | 45 dias | 60 dias | 75 dias | 90 dias | 105 dias | 120 dias | 150 dias | | :— | —: | —: | —: | —: | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 49,3% | 49,3% | 48,9% | 48,5% | 48,5% | 33,1% | 8,8% | 0,0% | 0,0% | 0,0% | | 31/07/2017 | 46,8% | 46,8% | 46,8% | 46,8% | 46,8% | 46,8% | 46,8% | 32,2% | 8,8% | 0,0% | | 31/08/2017 | 43,4% | 43,4% | 43,4% | 43,4% | 43,4% | 43,4% | 43,4% | 39,3% | 35,1% | 1,3% | | 30/09/2017 | 50,2% | 50,2% | 49,6% | 46,5% | 41,3% | 26,0% | 6,6% | 0,0% | 0,0% | 0,0% | | 31/12/2017 (hoje) | 49,5% | 49,5% | 49,0% | 42,3% | 27,0% | 15,5% | 6,6% | 0,0% | 0,0% | 0,0% |

Nos cortes de 31/07 e 31/08 a curva é plana por mais tempo porque, naquela fase do trimestre (1º e 2º mês), os deals de 30 a 100 dias de fato ganharam tanto quanto ou mais que os novos nas fotos de treino. A curva v2 é monotônica desde o dia 0, mas só cai quando os dados mostram a queda; o corte de 30/09 e hoje, ambos de fim de trimestre, caem cedo.

Modelos v1 (os da curva antiga), para comparação:

| Modelo ajustado até | Joelho (dias) | Chance de deal novo | Inclinação por 30 dias | Meia-vida depois do joelho (dias) | Limite de Limpe (dias) | Fotos | Linhas de treino | Taxa base de treino | | :— | —: | —: | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 70 | 49,0% | -4,71 | 6,9 | 138 | 1 | 1.330 | 45,8% | | 31/07/2017 | 100 | 46,9% | -5,60 | 5,7 | 138 | 2 | 2.948 | 45,0% | | 31/08/2017 | 95 | 46,0% | -1,72 | 18,3 | 138 | 3 | 4.483 | 43,3% | | 30/09/2017 | 90 | 45,6% | -1,96 | 16,0 | 138 | 4 | 6.169 | 41,2% | | 31/12/2017 (hoje) | 95 | 39,9% | -2,59 | 11,3 | 138 | 7 | 13.100 | 33,2% |

3. Por que assim

4. Checagem de vazamento

Para um corte T, o modelo e os scores só podem depender do que um CRM já teria registrado até o fim do dia T. Cada risco abaixo tem uma guarda no código e um teste; a prova central é o teste de mutação do futuro: tudo o que acontece depois de T (desfecho, datas, valores, contas, produtos, vendedores dos deals engajados depois) é trocado por valores aleatórios, e o modelo e os scores dos abertos em T têm de ficar idênticos, bit a bit. Um controle negativo (um modelo de corte posterior tem de mudar com a mutação) garante que a mutação mexe em algo que importa. O teste vale para a curva v2 (o modelo padrão) e para a v1.

# Risco Guarda Teste
1 Estágio final (Won/Lost) usado como estado em T as_of(T) reconstrói o estado a partir das datas test_as_of_hides_every_event_after_T, test_future_mutation_leaves_model_and_scores_unchanged
2 Rótulo de treino com evento depois de T só fotos com S + 90 dias <= T, com assert test_training_set_respects_the_horizon_for_every_cut
3 Conta ausente equivale a “nunca fechou” (os 1.425 sem conta estão todos abertos) has_account fora do modelo; atributos de conta só no subconjunto com conta test_account_columns_do_not_change_the_model_or_scores; auditoria da seção 7
4 close_value usado como valor do deal aberto o valor é sales_price test_close_value_is_never_read
5 Parâmetros (faixas da curva, fim do Foque, fim do Reative, escala) ajustados com dados de depois de T tudo ajustado por corte, a partir de as_of(T) mutação do futuro; test_limpe_limit_comes_from_wins_closed_up_to_T
6 Explicações vindas de um modelo que viu o futuro explain só recebe o modelo do corte test_explanation_uses_the_cut_model_not_a_global_one
7 Prospecting no passado não é reconstruível as_of descarta Prospecting; Qualifique só na data de referência test_prospecting_is_only_scored_when_asked_and_never_gets_a_score (limite de cobertura, não vazamento)
8 Hiperparâmetros (horizonte, primeira foto, largura da faixa, fase do trimestre) escolhidos conhecendo os dados divulgado; sensibilidade em 28/02 e com pseudo-contagem sem teste unitário possível
9 Preço de catálogo estático um preço por produto, premissa documentada test_each_product_has_a_single_list_price
10 Colunas derivadas do arquivo (age_days, cycle_days, is_open) calculadas com a data de referência as_of as recalcula em T test_as_of_recomputes_age_and_cycle_from_dates
11 Vendedor ou manager entrando no score o treino não tem essas colunas test_permuting_sales_agent_changes_no_score, test_training_set_has_no_seller_columns
12 Foto de outra fase do trimestre, ou posterior a T, entrando no treino da curva v2 same_phase filtra depois de training_set, que já exige S + 90 dias <= T test_v2_trains_only_with_photos_of_the_same_phase_and_before_T, test_v2_ignores_the_outcomes_of_photos_from_other_phases

Para ver se os testes pegam o vazamento de verdade, a 3a estragou uma guarda por vez em cópias do pacote (6 sabotagens, sobre o código da v1): todas foram detectadas, por 2 a 9 testes cada. A sabotagem “treino sem a regra S + 90 <= T” não é pega pela mutação (o rótulo vira “não ganho”, que enviesa mas não vaza), só pelos testes de horizonte; por isso as duas guardas do rótulo existem. As sabotagens não foram repetidas para a v2, que reaproveita as mesmas guardas e acrescenta a do risco 12. O que a checagem não cobre: escolher o desenho (horizonte, primeira foto, fase do trimestre) olhando os mesmos cortes que depois avaliam o modelo é um risco de ajuste ao teste que nenhum teste unitário elimina (risco 8). A troca de curva desta correção foi feita depois de ver o backtest da v1, então esse risco é maior para a v2 do que era para a v1 (seção 9).

5. Desenho do backtest e censura

6. Resultados

Receita capturada no top 20%, corte a corte, contra o critério pré-registrado (curva v2; a v1 passou também):

| Corte | Score v2 | Valor | Recência | Aleatório (média) | Aleatório (p95) | Margem sobre o melhor baseline | Vence os 4? | | :— | —: | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 61,0% | 48,6% | 27,7% | 20,0% | 23,4% | +12,4 pp | sim | | 31/07/2017 | 57,4% | 48,7% | 12,8% | 20,1% | 23,4% | +8,7 pp | sim | | 31/08/2017 | 59,9% | 48,2% | 31,6% | 19,8% | 23,0% | +11,8 pp | sim | | 30/09/2017 | 71,7% | 47,1% | 46,8% | 20,3% | 24,4% | +24,7 pp | sim |

Receita capturada no top 20%, curva v2. Empate é diferença de até 0,01 e não vence. Resultado: PASSOU.

Tabela principal (corte × método, com a v1 ao lado):

| Corte | Método | AUC | Ganhos capturados no top 20% | Receita capturada no top 20% | | :— | :— | —: | —: | —: | | 30/06/2017 | Score v2 (valor esperado, curva por faixas) | 0,66 | 25,7% | 61,0% | | 30/06/2017 | Score v1 (platô, antes da correção) | 0,66 | 25,8% | 61,3% | | 30/06/2017 | Ordenar por valor | 0,48 | 19,6% | 48,6% | | 30/06/2017 | Mais recentes primeiro | 0,73 | 29,3% | 27,7% | | 30/06/2017 | Aleatório (média de sorteios) | 0,50 (0,47 a 0,52) | 19,9% (18,1% a 21,8%) | 20,0% (16,8% a 23,4%) | | 30/06/2017 | Só a chance v2 (diagnóstico) | 0,73 | 28,8% | 28,3% | | 31/07/2017 | Score v2 (valor esperado, curva por faixas) | 0,63 | 24,8% | 57,4% | | 31/07/2017 | Score v1 (platô, antes da correção) | 0,64 | 25,1% | 57,9% | | 31/07/2017 | Ordenar por valor | 0,51 | 20,5% | 48,7% | | 31/07/2017 | Mais recentes primeiro | 0,58 | 12,2% | 12,8% | | 31/07/2017 | Aleatório (média de sorteios) | 0,50 (0,48 a 0,52) | 20,0% (18,1% a 22,0%) | 20,1% (17,2% a 23,4%) | | 31/07/2017 | Só a chance v2 (diagnóstico) | 0,64 | 24,8% | 24,7% | | 31/08/2017 | Score v2 (valor esperado, curva por faixas) | 0,63 | 26,1% | 59,9% | | 31/08/2017 | Score v1 (platô, antes da correção) | 0,63 | 26,4% | 60,7% | | 31/08/2017 | Ordenar por valor | 0,50 | 20,4% | 48,2% | | 31/08/2017 | Mais recentes primeiro | 0,66 | 34,0% | 31,6% | | 31/08/2017 | Aleatório (média de sorteios) | 0,50 (0,48 a 0,52) | 19,9% (18,1% a 22,0%) | 19,8% (16,4% a 23,0%) | | 31/08/2017 | Só a chance v2 (diagnóstico) | 0,66 | 25,9% | 26,0% | | 30/09/2017 | Score v2 (valor esperado, curva por faixas) | 0,72 | 32,8% | 71,7% | | 30/09/2017 | Score v1 (platô, antes da correção) | 0,65 | 27,9% | 64,8% | | 30/09/2017 | Ordenar por valor | 0,48 | 19,4% | 47,1% | | 30/09/2017 | Mais recentes primeiro | 0,83 | 43,6% | 46,8% | | 30/09/2017 | Aleatório (média de sorteios) | 0,50 (0,48 a 0,53) | 20,2% (17,5% a 22,5%) | 20,3% (16,1% a 24,4%) | | 30/09/2017 | Só a chance v2 (diagnóstico) | 0,83 | 43,0% | 45,5% |

Em negrito, o melhor entre score v2, score v1, valor, recência e aleatório. No aleatório, entre parênteses, o intervalo de p5 a p95 de 200 sorteios.

Média dos cortes:

| Método | AUC | Ganhos capturados no top 20% | Receita capturada no top 20% | | :— | —: | —: | —: | | Score v2 (valor esperado, curva por faixas) | 0,66 | 27,4% | 62,5% | | Score v1 (platô, antes da correção) | 0,64 | 26,3% | 61,1% | | Ordenar por valor | 0,49 | 20,0% | 48,1% | | Mais recentes primeiro | 0,70 | 29,8% | 29,7% | | Aleatório (média de sorteios) | 0,50 | 20,0% | 20,0% | | Só a chance v2 (diagnóstico) | 0,72 | 30,6% | 31,1% |

Média simples dos 4 cortes. Brier da chance v2: 0,180 (v1: 0,185) contra 0,221 da taxa média de treino (log-loss 0,512, v1: 0,524, contra 0,636), sobre ganhos em 90 dias.

Onde o score v2 ganha. Na receita capturada, em todos os cortes, com folga sobre o melhor baseline. O score troca um pouco de taxa de acerto por mais receita: a chance sozinha, sem o preço, captura bem menos receita que o score. Quem põe a receita é o preço.

v2 contra v1, sem rodeio. Na receita capturada a v2 fica abaixo da v1 por menos de um ponto percentual nos cortes de 30/06, 31/07 e 31/08, e acima por cerca de sete pontos percentuais no de 30/09. A média sobe por causa de um corte. Os três primeiros têm uma foto só de treino, então a v2 e a v1 aprendem quase a mesma coisa neles. A melhora é real onde importa para hoje (um fim de trimestre), mas está apoiada num só corte e esse corte tem poucas fotos.

Onde a recência ganha, sem rodeio. Em AUC e em captura de ganhos, nos cortes de 30/06, 31/08 e 30/09 (a AUC da recência chega a 0,83 em 30/09, contra 0,72 do score v2 e 0,65 do v1). Em receita, a recência perde para o score nos quatro cortes, mas em 30/09 chega a 46,8%, quase igual ao valor (47,1%). A chance v2 sozinha, sem o preço, empata com a recência em AUC nesse corte (0,83): a curva v2 aprendeu o que a recência já sabia. É coerente com o padrão do gerador que o DATA_QUALITY documenta (os deals fecham no trimestre do engajamento ou no seguinte, e os fechamentos rápidos se concentram no primeiro mês do trimestre): num fim de trimestre, quem foi engajado há 61 a 90 dias e continua aberto já passou da janela em que o gerador costuma fechar.

Onde a recência desaba. Em 31/07 ela captura 12,8% da receita, abaixo do sorteio (20,1%), e só 12,2% dos ganhos. Nesse corte, os deals de até 30 dias (engajados em julho) ganharam 24,3% nos 90 dias seguintes, contra 53,8% dos de 31 a 60 dias (tabela da seção 10). Ordenar pelos mais novos põe no topo os que menos ganham.

Ordem dentro do Foque. A pergunta do Rafael foi “dentro do Foque, o score ordena ou só ordena por preço?”. A resposta, para deals de até 90 dias:

População: engaging abertos em T com idade de até 90 dias; mesma população para todos os métodos. Desfecho: ganho até 31/12/2017.

AUC

Corte Deals Score v2 (curva por faixas) Score v1 (platô) Ordenar por valor Mais recentes primeiro Aleatório (referência)
30/06/2017 1.336 0,50 0,50 0,48 0,61 0,50
31/07/2017 1.703 0,51 0,51 0,51 0,39 0,50
31/08/2017 1.566 0,51 0,51 0,51 0,51 0,50
30/09/2017 1.684 0,55 0,50 0,50 0,73 0,50
Média dos 4 cortes — 0,52 0,51 0,50 0,56 0,50

Receita ganha capturada pelo top 20%

Corte Deals Score v2 (curva por faixas) Score v1 (platô) Ordenar por valor Mais recentes primeiro Aleatório (referência)
30/06/2017 1.336 50,5% 50,7% 48,3% 22,2% 20,1%
31/07/2017 1.703 49,2% 49,2% 49,2% 10,2% 20,1%
31/08/2017 1.566 50,4% 50,4% 50,4% 28,0% 20,0%
30/09/2017 1.684 59,9% 48,5% 48,5% 33,7% 20,1%
Média dos 4 cortes — 52,5% 49,7% 49,1% 23,5% 20,1%

Diferença na receita capturada, com IC por bootstrap (pp)

Corte Score v2 menos score v1 Score v2 menos valor
30/06/2017 -0,1 pp (IC -2,5 pp a +2,2 pp) +2,3 pp (IC -0,5 pp a +4,8 pp)
31/07/2017 0,0 pp (IC 0,0 pp a 0,0 pp) 0,0 pp (IC 0,0 pp a 0,0 pp)
31/08/2017 0,0 pp (IC 0,0 pp a 0,0 pp) 0,0 pp (IC 0,0 pp a 0,0 pp)
30/09/2017 +11,4 pp (IC +7,5 pp a +14,8 pp) +11,4 pp (IC +7,5 pp a +14,8 pp)

Em negrito, o melhor entre score v2, score v1, valor e recência (o aleatório é só referência).

Só no corte de 30/09 o score v2 ordena melhor que o preço e que o v1, com um intervalo que não inclui zero; nos de 31/07 e 31/08 os três métodos dão exatamente a mesma ordem, porque a curva v2 desses cortes é plana até além de 90 dias (acima). No de 30/06 a diferença sobre o valor é de 2,3 pontos percentuais, com intervalo que inclui zero. A AUC média do v2 é perto de um sorteio: o ganho de ordem dentro do Foque existe, mas é pequeno e concentrado no fim de trimestre. A recência tem a maior AUC média nessa população e a pior receita, de novo pelo mesmo motivo: ordena os mais novos primeiro, que não são os de maior valor.

Brier e log-loss. A chance v2 supera a constante (a taxa média de treino) nos quatro cortes, tanto em Brier quanto em log-loss. Contra a v1, a v2 melhora no corte de 31/08 e muito no de 30/09 (fim de trimestre), e fica uma fração de milésimo pior nos de 30/06 e 31/07. Isso não decide o critério.

Categorias. Quase toda a receita ganha depois do corte vem do Foque; o Limpe, por construção do dataset, nunca ganha (zero ganhos nos quatro cortes):

| Corte | Lista | Deals | Ganhos até 31/12/2017 | Receita ganha | % da receita | Valor de tabela | Valor esperado | | :— | :— | —: | —: | —: | —: | —: | —: | | 30/06/2017 | Foque | 1.283 | 47,2% | US$ 1.439.736 | 99,9% | US$ 3.202.532 | US$ 1.543.971 | | 30/06/2017 | Reative | 70 | 4,3% | US$ 1.714 | 0,1% | US$ 175.739 | US$ 22.511 | | 30/06/2017 | Limpe | 333 | 0,0% | US$ 0 | 0,0% | US$ 838.536 | US$ 344 | | 31/07/2017 | Foque | 1.848 | 40,0% | US$ 1.791.976 | 99,9% | US$ 4.470.015 | US$ 2.071.386 | | 31/07/2017 | Reative | 75 | 4,0% | US$ 1.714 | 0,1% | US$ 189.545 | US$ 23.646 | | 31/07/2017 | Limpe | 334 | 0,0% | US$ 0 | 0,0% | US$ 839.632 | US$ 100 | | 31/08/2017 | Foque | 1.831 | 34,8% | US$ 1.450.144 | 100,0% | US$ 4.266.512 | US$ 1.817.151 | | 31/08/2017 | Reative | 26 | 0,0% | US$ 0 | 0,0% | US$ 83.815 | US$ 15.094 | | 31/08/2017 | Limpe | 408 | 0,0% | US$ 0 | 0,0% | US$ 1.038.920 | US$ 4.775 | | 30/09/2017 | Foque | 1.626 | 34,1% | US$ 1.243.729 | 99,3% | US$ 3.693.202 | US$ 1.679.751 | | 30/09/2017 | Reative | 77 | 5,2% | US$ 8.199 | 0,7% | US$ 192.165 | US$ 19.864 | | 30/09/2017 | Limpe | 706 | 0,0% | US$ 0 | 0,0% | US$ 1.878.123 | US$ 195 |

Calibração. A chance do modelo agora é a das fotos da mesma fase do trimestre. Nos cortes de fim de trimestre a faixa de 61 a 90 dias deixa de ser a média achatada da v1, mas ainda fica acima do observado no corte de 30/09:

| Corte | Deals | Brier da v2 | Brier da v1 | Brier da constante | Log-loss da v2 | Log-loss da v1 | Log-loss da constante | | :— | —: | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 1.686 | 0,189 | 0,189 | 0,239 | 0,530 | 0,529 | 0,672 | | 31/07/2017 | 2.257 | 0,200 | 0,199 | 0,232 | 0,561 | 0,560 | 0,658 | | 31/08/2017 | 2.265 | 0,182 | 0,184 | 0,209 | 0,522 | 0,526 | 0,611 | | 30/09/2017 | 2.409 | 0,151 | 0,169 | 0,205 | 0,435 | 0,483 | 0,602 |

| Corte | Idade | Deals | Chance média da v2 | Chance média da v1 | Ganhos em 90 dias (observado) | | :— | :— | —: | —: | —: | —: | | 30/06/2017 | 0 a 30 dias | 692 | 49,3% | 49,0% | 51,2% | | 30/06/2017 | 31 a 60 dias | 454 | 48,6% | 49,0% | 44,5% | | 30/06/2017 | 61 a 90 dias | 190 | 34,4% | 32,9% | 21,6% | | 30/06/2017 | 91 a 120 dias | 133 | 0,9% | 0,8% | 0,0% | | 30/06/2017 | 121 a 150 dias | 103 | 0,0% | 0,0% | 0,0% | | 30/06/2017 | 151 dias ou mais | 114 | 0,0% | 0,0% | 0,0% | | 31/07/2017 | 0 a 30 dias | 720 | 46,8% | 46,9% | 24,3% | | 31/07/2017 | 31 a 60 dias | 522 | 46,8% | 46,9% | 53,8% | | 31/07/2017 | 61 a 90 dias | 461 | 46,8% | 46,9% | 45,6% | | 31/07/2017 | 91 a 120 dias | 198 | 34,0% | 30,6% | 22,7% | | 31/07/2017 | 121 a 150 dias | 133 | 1,0% | 0,3% | 0,0% | | 31/07/2017 | 151 dias ou mais | 223 | 0,0% | 0,0% | 0,0% | | 31/08/2017 | 0 a 30 dias | 662 | 43,4% | 46,0% | 29,2% | | 31/08/2017 | 31 a 60 dias | 587 | 43,4% | 46,0% | 21,3% | | 31/08/2017 | 61 a 90 dias | 317 | 43,4% | 46,0% | 51,7% | | 31/08/2017 | 91 a 120 dias | 211 | 39,8% | 34,1% | 32,2% | | 31/08/2017 | 121 a 150 dias | 128 | 18,6% | 8,7% | 2,3% | | 31/08/2017 | 151 dias ou mais | 360 | 0,1% | 0,7% | 0,0% | | 30/09/2017 | 0 a 30 dias | 679 | 50,1% | 45,6% | 48,0% | | 30/09/2017 | 31 a 60 dias | 545 | 45,9% | 45,6% | 33,8% | | 30/09/2017 | 61 a 90 dias | 460 | 33,7% | 45,6% | 6,7% | | 30/09/2017 | 91 a 120 dias | 118 | 0,8% | 25,4% | 0,0% | | 30/09/2017 | 121 a 150 dias | 123 | 0,0% | 4,6% | 0,0% | | 30/09/2017 | 151 dias ou mais | 484 | 0,0% | 0,2% | 0,0% |

No corte de 30/09 a chance média de 61 a 90 dias cai de 45,6% (v1) para 33,7% (v2) e o observado foi 6,7%: melhorou, mas a v2 ainda é otimista nessa faixa. Não testei a causa; o modelo desse corte tem só duas fotos de fim de trimestre (março e junho). No corte de 31/08 a v2 fica pior que a v1 nas faixas de 121 a 150 dias (18,6% contra 8,7%, com 2,3% observado), por causa de uma foto só.

Bootstrap. A diferença do score v2 para valor e recência, com intervalo de confiança por reamostragem dos deals:

| Corte | Score v2 menos valor | Score v2 menos recência | | :— | —: | —: | | 30/06/2017 | +12,4 pp (IC +9,3 pp a +15,7 pp) | +33,3 pp (IC +26,7 pp a +40,5 pp) | | 31/07/2017 | +8,7 pp (IC +6,4 pp a +11,3 pp) | +44,6 pp (IC +39,2 pp a +50,1 pp) | | 31/08/2017 | +11,8 pp (IC +9,1 pp a +14,6 pp) | +28,3 pp (IC +22,1 pp a +34,6 pp) | | 30/09/2017 | +24,7 pp (IC +20,3 pp a +30,0 pp) | +24,9 pp (IC +17,8 pp a +32,0 pp) |

Diferença na receita capturada no top 20%, em pontos percentuais; IC de 2,5% a 97,5% por 1.000 reamostragens dos deals do corte (semente 0).

Os intervalos não incluem zero em nenhum corte, mas os quatro cortes usam os mesmos deals em datas diferentes e não são amostras independentes. O bootstrap reamostra deals, não épocas.

7. Sensibilidades e auditoria

Primeira foto de treino em 28/02/2017

Corte Fim do Foque (foto de 28/02) Fim do Foque (principal) Linhas de treino AUC Ganhos no top 20% Receita no top 20% Receita vs. principal
30/06/2017 79 79 1.330 0,66 25,7% 61,0% 0,0 pp
31/07/2017 109 109 1.618 0,63 24,8% 57,4% 0,0 pp
31/08/2017 135 133 2.720 0,63 25,6% 59,0% -1,0 pp
30/09/2017 75 75 3.016 0,72 32,8% 71,7% 0,0 pp

Com a primeira foto em 28/02/2017 o critério passaria; receita média do score v2: 62,3%.

Pseudo-contagem do ajuste único na curva v2

Corte Fim do Foque (com pseudo-contagem) Fim do Foque (principal) Chance aos 730 dias (com pseudo-contagem) Chance aos 730 dias (principal) AUC (com pseudo-contagem) AUC (principal) Receita no top 20% (com pseudo-contagem) Receita vs. principal
30/06/2017 730 79 26,9% 0,0% 0,54 0,66 60,6% -0,4 pp
31/07/2017 730 109 26,2% 0,0% 0,55 0,63 57,0% -0,4 pp
31/08/2017 142 133 21,3% 0,0% 0,55 0,63 59,6% -0,3 pp
30/09/2017 77 75 13,1% 0,0% 0,59 0,72 70,1% -1,7 pp

Com 20 deals de pseudo-contagem por faixa o critério passaria; receita média do score v2: 61,8%.

Só deals resolvidos (fechados até 31/12/2017)

| Corte | Abertos no corte | Resolvidos até 31/12 | Ainda abertos em 31/12 | Desses, com idade em 31/12 dentro do maior ciclo ganho até o corte | Receita no top 20%: score v2 / valor / recência / aleatório | AUC: score v2 / valor / recência | | :— | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 1.686 | 970 | 716 | 0 | 49,1% / 49,9% / 17,7% / 19,9% | 0,49 / 0,49 / 0,50 | | 31/07/2017 | 2.257 | 1.139 | 1.118 | 0 | 48,4% / 48,8% / 19,9% / 19,9% | 0,51 / 0,51 / 0,53 | | 31/08/2017 | 2.265 | 893 | 1.372 | 81 | 48,9% / 49,1% / 17,0% / 19,9% | 0,50 / 0,50 / 0,44 | | 30/09/2017 | 2.409 | 935 | 1.474 | 183 | 49,2% / 48,2% / 19,4% / 19,8% | 0,48 / 0,48 / 0,50 |

Modelo ajustado com o futuro (VAZADO; nunca é resultado)

Corte Rótulo Fim do Foque do modelo vazado AUC vazado Receita vazada AUC honesto Receita honesta Receita: vazado menos honesto
30/06/2017 VAZADO 61 0,67 62,0% 0,66 61,0% +1,0 pp
31/07/2017 VAZADO 107 0,63 58,1% 0,63 57,4% +0,6 pp
31/08/2017 VAZADO 123 0,64 60,3% 0,63 59,9% +0,4 pp
30/09/2017 VAZADO 61 0,73 79,0% 0,72 71,7% +7,2 pp

has_account sozinho (proibido como variável)

| Corte | Com conta | Sem conta | AUC de has_account sozinho | Ganhos depois (com conta) | Ganhos depois (sem conta) | Ganhos entre os sem conta | | :— | —: | —: | —: | —: | —: | —: | | 30/06/2017 | 1.202 | 484 | 0,72 | 50,7% | 0,0% | 0 | | 31/07/2017 | 1.497 | 760 | 0,75 | 49,6% | 0,0% | 0 | | 31/08/2017 | 1.331 | 934 | 0,79 | 47,9% | 0,0% | 0 | | 30/09/2017 | 1.401 | 1.008 | 0,77 | 39,9% | 0,0% | 0 |

8. Atributos testados e descartados

Um atributo por vez, sobre a curva de idade com o joelho fixo, com one-hot (categoria de referência a mais frequente) e penalidade L2 de 1,0 só nos coeficientes do atributo. Produto e região usam todos os deals; setor e porte (tercil de funcionários, calculado nas contas) só os deals com conta, no treino e na avaliação, contra a curva só de idade ajustada no mesmo subconjunto. Regra pré-registrada: entra só se melhorar o log-loss em todos os cortes e não piorar a receita no top 20% em nenhum. O vendedor não é testado. O teste foi feito sobre a curva v1 e não foi repetido sobre a v2 (o desenho com um joelho fixo não se aplica à curva por faixas); é uma limitação (seção 11).

Δ log-loss negativo é melhora (log-loss de 90 dias, contra a curva só de idade no mesmo subconjunto). Teste feito sobre a curva v1 (joelho fixo), antes da correção.

Atributo Subconjunto Níveis Δ log-loss 30/06/2017 Δ log-loss 31/07/2017 Δ log-loss 31/08/2017 Δ log-loss 30/09/2017 Melhora em todos?
produto todos os deals 7 0,0060 0,0017 -0,0003 0,0007 não
região todos os deals 3 -0,0158 0,0321 0,0596 0,0645 não
setor só deals com conta 10 0,0061 0,0039 0,0029 0,0028 não
porte só deals com conta 3 -0,0007 -0,0004 -0,0001 0,0004 não
Atributo Subconjunto Níveis Δ receita top 20% 30/06/2017 Δ receita top 20% 31/07/2017 Δ receita top 20% 31/08/2017 Δ receita top 20% 30/09/2017 Não piora em nenhum? Entra?
produto todos os deals 7 -0,5 pp +0,2 pp -0,3 pp -0,1 pp não não
região todos os deals 3 +2,5 pp -4,7 pp -4,2 pp -6,1 pp não não
setor só deals com conta 10 -0,8 pp -0,8 pp +0,2 pp -0,3 pp não não
porte só deals com conta 3 +1,3 pp +0,8 pp +0,0 pp -0,1 pp não não

Diagnóstico, que não decide: o mesmo Δ log-loss medido dentro da amostra de treino.

| Atributo | Subconjunto | Δ log-loss no treino 30/06/2017 | Δ log-loss no treino 31/07/2017 | Δ log-loss no treino 31/08/2017 | Δ log-loss no treino 30/09/2017 | | :— | :— | —: | —: | —: | —: | | produto | todos os deals | -0,0057 | -0,0030 | -0,0006 | -0,0004 | | região | todos os deals | -0,0191 | -0,0237 | -0,0305 | -0,0288 | | setor | só deals com conta | -0,0048 | -0,0038 | -0,0030 | -0,0018 | | porte | só deals com conta | -0,0003 | -0,0002 | -0,0004 | -0,0005 |

Nenhum atributo entra. Produto, setor e porte pioram o log-loss em pelo menos um corte (porte melhora em três de quatro por margens de milésimos), e todos pioram a receita no top 20% em algum corte. A região é o caso instrutivo: dentro da amostra de treino ela parece ajudar (o Δ log-loss no treino é o mais negativo da tabela de diagnóstico), mas fora da amostra piora em três dos quatro cortes. No treino do corte de 30/09, a região Central ganhava bem mais que as outras entre os deals jovens; depois do corte, a diferença desapareceu e até se inverteu. É a razão de a validação ser sempre temporal (CLAUDE.md, decisão 6).

9. Critério pré-registrado e se houve ajuste

Escrito antes do backtest (25/10/2026, 16:28; o primeiro número de desempenho só apareceu às 19:05, depois de uma interrupção por limite de uso da API, registrada em process-log/03_bloco-3.md).

Métrica primária. Receita capturada no top 20%: fração da receita ganha (o close_value dos Won) que cai nos 20% de maior score, por contagem de deals, com empates tratados pelo valor esperado sob desempate aleatório.

O score vence se, em cada um dos 4 cortes (30/06, 31/07, 31/08 e 30/09/2017), a receita capturada no top 20% for maior que a de ordenar por valor, maior que a de ordenar pelos mais recentes, e maior que a média e o percentil 95 de 200 sorteios aleatórios (sementes 0 a 199).

Empate. Diferença de até 0,01 (1 ponto percentual) é empate, e empate não vence.

Não decidem. AUC, captura de ganhos e Brier são reportados, mas não entram na decisão.

Ajuste único, só se o critério falhar. Trocar a curva “platô + queda” por faixas de 15 dias de idade, com a taxa de cada faixa suavizada por uma pseudo-contagem de 20 deals rumo à taxa média de treino, forçada a não crescer (algoritmo PAVA, pesos = n + 20) e interpolada linearmente entre os pontos médios das faixas. Mesma janela, mesmo horizonte de 90 dias, nada mais muda. Roda-se uma vez.

Se ainda falhar. Fica o modelo de melhor média na métrica primária e a falha é documentada com números. Sem novas tentativas e sem trocar de métrica.

Regra para atributos. Um atributo só entra no score se melhorar o log-loss da chance de ganho em 90 dias em todos os cortes e não piorar a receita capturada no top 20% em nenhum. O vendedor não é testado.

Resultado original: PASSOU com a curva v1, e o ajuste não foi aplicado. O critério passou na primeira rodada; o ajuste único (faixas de 15 dias e PAVA) estava implementado e testado, mas não foi rodado, porque a regra só o autoriza se o critério falhar.

Mudança pós-backtest: a curva v2. Depois de publicada, o Rafael usou a ferramenta como vendedor, viu a chance constante no Foque e pediu a correção. Esta é uma mudança feita depois de ver o resultado do backtest, pedida por ele depois de revisar a ferramenta, e não faz parte do pré-registro. A mudança tem duas partes que o pré-registro não previa: (a) as faixas isotônicas treinadas só com fotos da mesma fase do trimestre, e (b) a retirada da pseudo-contagem do ajuste único, escolhida por um motivo medido (a cauda sem ganhos subia a 13% a 27%), não pelo backtest. O critério pré-registrado, a métrica primária, o empate de 1 ponto percentual e os quatro cortes foram mantidos, e o resultado é reportado para a v2 e para a v1 (seção 6): PASSOU nas duas. Como a v2 foi desenhada sabendo o que o backtest da v1 mostrou (a queda no fim do trimestre), o PASSOU da v2 não tem o valor de um teste às cegas; vale como verificação de que a correção não estragou o que já funcionava, e o corte de 30/09 (onde a v2 mais melhora) é justamente o que inspirou o desenho.

O que o pré-registro garante, e o que não. A regra, o desempate e o ajuste único não mudaram depois de ver o resultado. Mas o critério não foi fixado às cegas: o planejador tinha rodado um protótipo e o plano trazia valores esperados próximos dos obtidos, então já se sabia que o score tendia a passar. A métrica primária foi escolhida porque a dor é onde pôr a hora do vendedor, e não por ser a que o score ganha (a recência ganha em AUC).

10. O que não funcionou e por quê

Foque do corte por idade, com a chance da v2 (a comparação entre a chance que o modelo deu e o que de fato aconteceu dentro do Foque de cada corte):

| Corte | Idade (dentro do Foque do corte) | Deals | Chance do modelo (v2) | Ganhos em 90 dias (observado) | | :— | :— | —: | —: | —: | | 30/06/2017 | 0 a 30 dias | 692 | 49,3% | 51,2% | | 30/06/2017 | 31 a 60 dias | 454 | 48,6% | 44,5% | | 30/06/2017 | 61 dias ou mais | 137 | 42,3% | 27,7% | | 31/07/2017 | 0 a 30 dias | 720 | 46,8% | 24,3% | | 31/07/2017 | 31 a 60 dias | 522 | 46,8% | 53,8% | | 31/07/2017 | 61 dias ou mais | 606 | 45,5% | 41,6% | | 31/08/2017 | 0 a 30 dias | 662 | 43,4% | 29,2% | | 31/08/2017 | 31 a 60 dias | 587 | 43,4% | 21,3% | | 31/08/2017 | 61 dias ou mais | 582 | 41,1% | 40,4% | | 30/09/2017 | 0 a 30 dias | 679 | 50,1% | 48,0% | | 30/09/2017 | 31 a 60 dias | 545 | 45,9% | 33,8% | | 30/09/2017 | 61 dias ou mais | 402 | 36,6% | 6,7% |

Foque de hoje (60 deals) por idade: 0 a 30 dias: 18, 31 a 60 dias: 39, 61 dias ou mais: 3.

Com a v2 o Foque é mais curto nos fins de trimestre e a chance dentro dele cai com a idade (45,9% de 31 a 60 dias e 36,6% a partir de 61 dias, no corte de 30/09), mas continua otimista para os deals de 61 dias ou mais (6,7% observado). O resíduo vem de o modelo de 30/09 ter só duas fotos de treino de fim de trimestre.

11. Limitações