
Aprenda a calcular, aplicar e visualizar o Tillson T3 com Python, entendendo cada etapa do indicador e o raciocínio por trás das médias suavizadas.
O que é a Média Tillson T3
A Tillson T3 é uma média móvel avançada, desenvolvida para resolver um dos problemas mais antigos da análise técnica: o conflito entre suavização do preço e atraso na resposta (lag).
Diferente das médias móveis tradicionais, que trabalham com uma única camada de suavização, o Tillson T3 utiliza uma estrutura composta de múltiplas médias móveis exponenciais encadeadas, combinadas matematicamente por meio de coeficientes específicos.
O objetivo não é apenas suavizar o preço, mas preservar a estrutura da tendência, reduzindo ruídos sem comprometer excessivamente o tempo de resposta.
Na prática, o Tillson T3 se comporta como um filtro de sinal, mais próximo de conceitos de signal processing do que de uma simples média estatística.
Ele não “segue o preço” de forma ingênua ele modela o movimento.
É justamente essa característica que faz com que o Tillson T3 apresente curvas mais limpas, menos serrilhadas e, ao mesmo tempo, mais confiáveis para leitura de tendência, especialmente em operações de médio prazo.
Quem criou o Tillson T3 e em qual contexto
O Tillson T3 foi criado por Tim Tillson, engenheiro e analista técnico, no final da década de 1990.
Naquele período, o mercado financeiro já enfrentava um problema claro: os mercados estavam se tornando mais rápidos, mais voláteis e mais ruidosos, enquanto os indicadores clássicos permaneciam praticamente inalterados desde décadas anteriores.
Tillson partiu de uma constatação simples, porém profunda:
Não existe média móvel perfeita, existe apenas um compromisso melhor entre atraso e suavidade.
Em vez de tentar eliminar completamente o lag (algo matematicamente impossível sem introduzir ruído), Tillson propôs um modelo que controlasse esse compromisso de forma explícita, permitindo ao analista ajustar o comportamento do indicador conforme o contexto do mercado.
O resultado foi o Tillson T3, um indicador que rapidamente chamou atenção por entregar algo raro:
uma média visualmente suave, mas operacionalmente responsiva.
Onde o Tillson T3 foi utilizado inicialmente
O Tillson T3 ganhou notoriedade inicialmente entre traders profissionais, desenvolvedores de sistemas e analistas quantitativos, muito antes de se popularizar em plataformas gráficas.
Ele foi amplamente estudado e utilizado em:
- Sistemas de tendência (trend-following)
- Modelos de swing trade
- Estratégias sistemáticas baseadas em cruzamento de médias
- Ambientes onde redução de ruído era mais importante do que entradas ultra-precoces
Por muitos anos, o T3 foi considerado um indicador “de nicho”, justamente por sua complexidade matemática e pela dificuldade de implementação correta, algo que afastava o público iniciante, mas atraía profissionais mais técnicos.
Hoje, com linguagens como Python, essa barreira praticamente deixou de existir.
Por que o Tillson T3 é minha média favorita para Swing Trade
Entre dezenas de médias móveis, filtros e indicadores testados ao longo dos anos, o Tillson T3 se tornou minha média favorita para Swing Trade por um motivo muito específico: qualidade estrutural do sinal.
Em operações de swing trade, o objetivo não é capturar o topo ou o fundo exato.
O objetivo é:
- Entrar quando a tendência já se provou
- Permanecer enquanto a estrutura se mantém
- Sair quando a tendência realmente perde força, não por ruído
O Tillson T3 entrega exatamente isso.
Comparado a uma EMA tradicional:
- Ele gera menos falsos cruzamentos
- Filtra melhor movimentos laterais
- Mantém o trader posicionado por mais tempo em tendências reais
Além disso, o uso de duas curvas Tillson T3 (curta e longa) cria uma leitura extremamente limpa de regime de mercado:
- Tendência de alta
- Tendência de baixa
- Consolidação
Essa clareza é essencial para swing trade, onde decisões erradas custam semanas de capital imobilizado.
Visão profissional
O Tillson T3 não é um indicador para quem busca atalhos ou sinais mágicos.
Ele é uma ferramenta para quem entende que mercado é estrutura, não previsão.
Quando bem parametrizado e combinado com leitura de preço, o Tillson T3 se torna um instrumento de alto nível para análise de tendência, especialmente em contextos de médio prazo.
Não é por acaso que ele continua relevante décadas após sua criação.
Quer aprender conceitos das estratégia quantitativa leia eBook Frequência Quants.
Implementando o Tillson T3 em Python: da teoria à prática
Depois de entender o conceito do Tillson T3, o próximo passo é traduzir essa lógica para código.
Aqui, não estamos apenas “calculando uma média”, mas implementando um filtro matemático avançado de suavização com compensação de atraso.
Cada função e cada parâmetro do código abaixo existe para resolver um problema clássico da análise técnica:
Como suavizar o preço sem perder timing operacional.
Leia também: Pairs Trading com Python: Estratégia e Dashboard
Instalação das bibliotecas necessárias
Antes de implementar o Tillson T3 em Python, é necessário garantir que todas as bibliotecas utilizadas estejam instaladas corretamente.
Cada dependência abaixo foi escolhida por um motivo específico dentro da análise.
Comando de instalação (pip)
!pip install pandas yfinance plotly
import pandas as pd
import yfinance as yf
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from datetime import datetime, timedelta
A EMA como base estrutural do Tillson T3
O Tillson T3 é construído sobre a Média Móvel Exponencial (EMA).
Isso não é por acaso.
A EMA é utilizada porque:
- Dá mais peso aos preços recentes
- Reage mais rápido às mudanças de tendência
- Mantém causalidade (não utiliza dados futuros)
No código, isso aparece na função auxiliar:
def ema(series, period):
return series.ewm(span=period, adjust=False).mean()
O parâmetro adjust=False é crítico.
Ele garante que a EMA seja calculada de forma recursiva, exatamente como o mercado se comporta no tempo real.
Sem isso, o Tillson T3 introduziria look-ahead bias e perderia validade operacional.
Por que o Tillson T3 usa seis EMAs encadeadas
Diferente de médias tradicionais, o Tillson T3 não se apoia em uma única suavização.
Ele utiliza seis EMAs aplicadas sequencialmente:
e1 = ema(series, period)
e2 = ema(e1, period)
e3 = ema(e2, period)
e4 = ema(e3, period)
e5 = ema(e4, period)
e6 = ema(e5, period)
Cada camada adicional:
- Reduz ruído
- Aumenta suavidade
- Introduz atraso (lag)
Se usássemos apenas e6, teríamos uma linha extremamente limpa, porém inutilizável para trading, pois chegaria tarde demais.
É exatamente aqui que entra o diferencial do Tillson T3.
A lógica por trás da fórmula
O ponto central do Tillson T3 não é a suavização em si, mas a compensação do atraso.
Tim Tillson resolveu isso criando uma combinação linear ponderada entre diferentes níveis de suavização:
c1 = -vfactor**3
c2 = 3*vfactor**2 + 3*vfactor**3
c3 = -6*vfactor**2 - 3*vfactor - 3*vfactor**3
c4 = 1 + 3*vfactor + vfactor**3 + 3*vfactor**2
Esses coeficientes não são arbitrários.
Eles foram desenhados para:
- Cancelar parte do atraso introduzido pelas EMAs mais profundas
- Preservar a suavidade da curva final
- Controlar a curvatura e a responsividade da média
O vfactor funciona como um botão de ajuste fino:
- Valores menores → mais responsividade
- Valores maiores → mais suavidade
A equação final do Tillson T3 no código
A média final é calculada assim:
T3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3
return T3
Interpretação prática:
e6fornece suavidade extremae3traz resposta mais rápida- Os coeficientes equilibram o peso entre atraso e reação
O resultado é uma curva que:
- Suaviza ruído de mercado
- Mantém estrutura de tendência
- Reduz falsos cruzamentos
É exatamente isso que torna o Tillson T3 tão eficiente para Swing Trade.
Por que usar dois Tillson T3 (curta e longa)
No código, são utilizadas duas médias Tillson T3:
df['T3_curta'] = t3(df['Close'], period=6, vfactor=0.5)
df['T3_longa'] = t3(df['Close'], period=37, vfactor=0.65)
Essa combinação cria:
- Uma média rápida, sensível à mudança de tendência
- Uma média lenta, representando o regime principal do mercado
O cruzamento entre elas não é um simples “sinal mecânico”, mas uma mudança estrutural de momentum.
O Tillson T3 como filtro de regime de mercado
No trecho:
df['Sinal'] = df['T3_curta'] > df['T3_longa']
O Tillson T3 é usado como:
- Filtro de tendência
- Definição de viés operacional
- Identificação de pontos de entrada e saída mais limpos
Por isso, ele funciona melhor em:
- Swing Trade
- Position Trade
- Timeframes diários e semanais
E é exatamente por isso que essa é minha média favorita para Swing Trade:
ela filtra o ruído sem matar o movimento.
Visualização Gráfica

Abaixo Segue o Codigo completo
import pandas as pd
import yfinance as yf
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from datetime import datetime, timedelta
# Funções auxiliares
def ema(series, period):
return series.ewm(span=period, adjust=False).mean()
def t3(series, period=14, vfactor=0.7):
e1 = ema(series, period)
e2 = ema(e1, period)
e3 = ema(e2, period)
e4 = ema(e3, period)
e5 = ema(e4, period)
e6 = ema(e5, period)
c1 = -vfactor**3
c2 = 3*vfactor**2 + 3*vfactor**3
c3 = -6*vfactor**2 - 3*vfactor - 3*vfactor**3
c4 = 1 + 3*vfactor + vfactor**3 + 3*vfactor**2
T3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3
return T3
# Configuração
ticker = 'CMIN3.SA'
anos = 2
end_date = datetime.now()
start_date = end_date - timedelta(days=anos*365)
print(f"Baixando dados de {ticker}...")
print(f"Período: {start_date.date()} até {end_date.date()}")
# Baixar dados diários
dados_diarios = yf.download(ticker, start=start_date, end=end_date, progress=False)
if isinstance(dados_diarios.columns, pd.MultiIndex):
dados_diarios.columns = dados_diarios.columns.get_level_values(0)
if 'Adj Close' in dados_diarios.columns:
dados_diarios['Close'] = dados_diarios['Adj Close']
# Criar dados semanais
dados_semanais = dados_diarios.resample('W-FRI').agg({
'Open': 'first',
'High': 'max',
'Low': 'min',
'Close': 'last',
'Volume': 'sum'
}).dropna()
print(f"\nDados diários: {len(dados_diarios)} candles")
print(f"Dados semanais: {len(dados_semanais)} candles")
# Função para criar gráfico simplificado
def criar_grafico_tillson(df, titulo, periodo):
df = df.copy()
# Calcular médias Tillson T3
df['T3_curta'] = t3(df['Close'], period=6, vfactor=0.5)
df['T3_longa'] = t3(df['Close'], period=37, vfactor=0.65)
df = df.dropna()
# Criar figura
fig = make_subplots(
rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.03,
row_heights=[0.7, 0.3] # 70% para candles, 30% para volume
)
# 1. Gráfico de Candles
fig.add_trace(
go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
name='Preço',
increasing_line_color='#26a69a', # verde
decreasing_line_color='#ef5350', # vermelho
increasing_fillcolor='#26a69a',
decreasing_fillcolor='#ef5350'
),
row=1, col=1
)
# Adicionar médias Tillson T3
fig.add_trace(
go.Scatter(
x=df.index,
y=df['T3_curta'],
name='T3 Curta (6)',
line=dict(color='#2196F3', width=2.5), # azul
opacity=0.9
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df.index,
y=df['T3_longa'],
name='T3 Longa (37)',
line=dict(color='#FF5722', width=2.5, dash='dash'), # laranja
opacity=0.9
),
row=1, col=1
)
# Adicionar área entre as médias (para visualização do cruzamento)
df['T3_min'] = df[['T3_curta', 'T3_longa']].min(axis=1)
df['T3_max'] = df[['T3_curta', 'T3_longa']].max(axis=1)
fig.add_trace(
go.Scatter(
x=df.index,
y=df['T3_max'],
mode='lines',
line=dict(width=0),
showlegend=False,
hoverinfo='skip'
),
row=1, col=1
)
fig.add_trace(
go.Scatter(
x=df.index,
y=df['T3_min'],
mode='lines',
line=dict(width=0),
fill='tonexty',
fillcolor='rgba(100, 100, 100, 0.1)',
showlegend=False,
hoverinfo='skip',
name='Área entre médias'
),
row=1, col=1
)
# 2. Gráfico de Volume
colors_volume = ['#26a69a' if close >= open_ else '#ef5350'
for close, open_ in zip(df['Close'], df['Open'])]
fig.add_trace(
go.Bar(
x=df.index,
y=df['Volume'],
name='Volume',
marker_color=colors_volume,
opacity=0.7,
showlegend=False
),
row=2, col=1
)
# Calcular sinal de compra/venda
df['Sinal'] = df['T3_curta'] > df['T3_longa']
# Adicionar marcadores de sinal
cruzamentos_positivos = df[df['Sinal'] & ~df['Sinal'].shift(1, fill_value=False)]
cruzamentos_negativos = df[~df['Sinal'] & df['Sinal'].shift(1, fill_value=True)]
if len(cruzamentos_positivos) > 0:
fig.add_trace(
go.Scatter(
x=cruzamentos_positivos.index,
y=cruzamentos_positivos['Low'] * 0.99,
mode='markers',
name='Compra',
marker=dict(
symbol='triangle-up',
size=12,
color='#4CAF50',
line=dict(color='white', width=1)
),
hovertemplate='Compra '
),
row=1, col=1
)
if len(cruzamentos_negativos) > 0:
fig.add_trace(
go.Scatter(
x=cruzamentos_negativos.index,
y=cruzamentos_negativos['High'] * 1.01,
mode='markers',
name='Venda',
marker=dict(
symbol='triangle-down',
size=12,
color='#F44336',
line=dict(color='white', width=1)
),
hovertemplate='Venda '
),
row=1, col=1
)
# Layout
fig.update_layout(
title=dict(
text=titulo,
x=0.5,
xanchor='center',
font=dict(size=20, color='black')
),
height=800,
template='plotly_white',
hovermode='x unified',
xaxis_rangeslider_visible=False,
showlegend=True,
legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1,
bgcolor='rgba(255, 255, 255, 0.9)',
bordercolor='lightgray',
borderwidth=1
),
margin=dict(t=100, l=50, r=50, b=50)
)
# Botões de período
if periodo == 'diario':
buttons = [
dict(count=5, label="5 dias", step="day", stepmode="backward"),
dict(count=21, label="1 mês", step="day", stepmode="backward"),
dict(count=63, label="3 meses", step="day", stepmode="backward"),
dict(count=126, label="6 meses", step="day", stepmode="backward"),
dict(count=252, label="1 ano", step="day", stepmode="backward"),
dict(step="all", label="Todo período")
]
else:
buttons = [
dict(count=21, label="3 semanas", step="day", stepmode="backward"),
dict(count=63, label="9 semanas", step="day", stepmode="backward"),
dict(count=126, label="18 semanas", step="day", stepmode="backward"),
dict(count=252, label="36 semanas", step="day", stepmode="backward"),
dict(step="all", label="Todo período")
]
fig.update_xaxes(
rangeselector=dict(
buttons=buttons,
bgcolor="lightgray",
activecolor="#2196F3",
font=dict(color="white", size=10)
),
row=1, col=1
)
# Configurar eixos
fig.update_yaxes(title_text="Preço (R$)", row=1, col=1)
fig.update_yaxes(title_text="Volume", row=2, col=1)
# Adicionar informações no gráfico
ultimo_preco = df['Close'].iloc[-1]
ultimo_t3_curta = df['T3_curta'].iloc[-1]
ultimo_t3_longa = df['T3_longa'].iloc[-1]
sinal_atual = "COMPRA" if ultimo_t3_curta > ultimo_t3_longa else "VENDA"
cor_sinal = "#4CAF50" if sinal_atual == "COMPRA" else "#F44336"
fig.add_annotation(
xref="paper", yref="paper",
x=0.02, y=0.98,
text=f"Último Preço: R$ {ultimo_preco:.2f}
"
f"T3 Curta: R$ {ultimo_t3_curta:.2f}
"
f"T3 Longa: R$ {ultimo_t3_longa:.2f}
"
f"Sinal: {sinal_atual}",
showarrow=False,
align="left",
font=dict(size=12, color="black"),
bgcolor="rgba(255, 255, 255, 0.9)",
bordercolor="lightgray",
borderwidth=1,
borderpad=8
)
return fig
# Criar gráficos
print("\n" + "="*60)
print("Gerando gráfico DIÁRIO...")
print("="*60)
fig_diario = criar_grafico_tillson(
dados_diarios,
f'{ticker} - Análise Diária com Médias Tillson T3
'
f''
f'{dados_diarios.index[0].strftime("%d/%m/%Y")} - {dados_diarios.index[-1].strftime("%d/%m/%Y")}'
f'',
'diario'
)
print("\n" + "="*60)
print("Gerando gráfico SEMANAL...")
print("="*60)
fig_semanal = criar_grafico_tillson(
dados_semanais,
f'{ticker} - Análise Semanal com Médias Tillson T3
'
f''
f'{dados_semanais.index[0].strftime("%d/%m/%Y")} - {dados_semanais.index[-1].strftime("%d/%m/%Y")}'
f'',
'semanal'
)
# Mostrar gráficos
fig_diario.show()
fig_semanal.show()
# Salvar ambos
nome_base = ticker.replace('.SA', '').lower()
fig_diario.write_html(f"{nome_base}_diario_tillson.html")
fig_semanal.write_html(f"{nome_base}_semanal_tillson.html")
print(f"\n✅ Gráficos salvos como HTML interativo:")
print(f" 📊 {nome_base}_diario_tillson.html")
print(f" 📈 {nome_base}_semanal_tillson.html")
print("\n🎯 Instruções de uso:")
print(" • ZOOM: Use a roda do mouse ou selecione uma área")
print(" • NAVEGAÇÃO: Arraste para mover o gráfico")
print(" • RESET: Duplo clique no gráfico")
print(" • VALORES: Passe o mouse sobre os dados")
print(" • PERÍODOS: Use os botões no canto superior direito")
print("\n📊 Legenda:")
print(" • █ Candles verdes/vermelhos: Variação de preço")
print(" • ─ Linha azul: T3 Curta (6 períodos)")
print(" • ─ Linha laranja tracejada: T3 Longa (37 períodos)")
print(" • ▲ Triângulo verde: Sinal de COMPRA")
print(" • ▼ Triângulo vermelho: Sinal de VENDA")
Quer ir além do código?
O código completo acima implementa uma das ferramentas mais sofisticadas de análise técnica o Tillson T3, mas o entendimento de como construir, validar e combinar essa e outras metodologias exige fundamentos matemáticos e estatísticos. Para isso, recomendamos o eBook Frequência Quants, que explora estratégia quantitativa, risco e métricas essenciais que todo analista ou trader quantitativo deve dominar.




