PáginasDados de calendário · 13 / 29
Módulo de calendário
O módulo de calendário dá à sua estratégia o histórico de dividendos, o histórico de desdobramentos, as datas de resultados, a data do IPO e os arquivamentos recentes na SEC de uma empresa — e permite que o backtest aplique desdobramentos e dividendos às suas posições automaticamente.
Ative Include calendar data na aba Symbol & data da caixa Run backtest. Ele vem ativado por padrão, e a sua escolha (mais as duas subopções) é lembrada para a próxima execução. Os calendários são carregados automaticamente para cada símbolo que a execução negocia, inclusive um universo resolvido por um screener — não há seletor por ticker. A caixa Test de um agente tem a mesma opção — Include calendar data (dividends, splits) (veja Agentes).
Somente backtests. Os dados de calendário são carregados para backtests, Debug Test e testes de agentes. As execuções forward — chart forward tests, execuções bulk do AutoTrading e QuantCloud — nunca recebem um calendário, portanto calendar é sempre None nelas.
Por que importa: as barras de preço são brutas
As velas do backtest não são ajustadas. Sem dados de calendário:
- Um desdobramento 4 por 1 parece um colapso de 75% do preço da noite para o dia, e a sua posição simulada colapsa junto.
- Os dividendos nunca chegam, o que subestima discretamente o retorno total de qualquer posição mantida por muito tempo — cerca de 2% ao ano para um pagador de dividendos típico.
As duas subopções corrigem ambos os problemas sem exigir nenhuma alteração de código.
O parâmetro de callback calendar
Adicione um parâmetro calendar a qualquer callback e o handle é passado a você:
def on_bar(bar_index, bar, calendar=None, symbol=None):
if calendar is None: # always guard — not every run enables calendar data
return
days = calendar.days_to_earnings(bar["t"], symbol)
if days is not None and days <= 2:
return # sit out the earnings print
divs = calendar.dividends(bar["t"], symbol)
if divs and (divs[-1].amount or 0) > 0.5: # amount can be None
...Funciona em on_bar, on_tick e on_timer. O argumento calendar é associado pelo nome, então um script sem parâmetro calendar se comporta exatamente como antes, e um calendar declarado recebe o handle ou None — nunca outro objeto, seja o que for que o restante da sua assinatura receba. Se você também lê dados fundamentalistas, a assinatura recomendada é def on_bar(bar_index, bar, fundamentals=None, calendar=None, symbol=None).
Você também pode alcançar o mesmo handle sem parâmetro: a variável global do script qc_calendar, ou quantcraft.process.runtime.qc_calendar.
Métodos
| Método | Retorna |
|---|---|
dividends(bar_time, symbol=None) | Dividendos públicos naquela barra |
splits(bar_time, symbol=None) | Desdobramentos anunciados até aquela barra |
filings(bar_time, symbol=None) | Arquivamentos na SEC públicos naquela barra |
next_earnings(bar_time, symbol=None) | {date, basis, estimated, …} ou None |
days_to_earnings(bar_time, symbol=None) | int ou None |
ipo_date(symbol=None) | date ou None |
current(bar_time, symbol=None) | Um dicionário instantâneo de tudo o que foi listado acima naquela barra, ou None |
dividends_between(start, end, symbol=None) | Dividendos cuja data ex cai em (start, end] |
splits_between(start, end, symbol=None) | Desdobramentos cuja data de vigência cai em (start, end] |
has(symbol=None) | Se este símbolo tem algum dado de calendário |
symbols / primary_symbol() / get(symbol=None) | Os símbolos carregados, o padrão e o calendário bruto por símbolo (ou None) |
Os métodos _between usam as datas de efeito (“quando isso atinge a minha posição?”), diferentemente dos métodos por horário de barra acima, que usam as datas de “eu poderia saber?” — veja a próxima seção.
bar_time aceita bar["t"], bar.t[0], um datetime, um date ou segundos epoch.
As listas são da mais antiga para a mais recente — dividends(...)[-1] é a mais recente. Isso é o oposto dos dados fundamentalistas, em que o índice 0 é o período mais novo.
Um símbolo sem dados de calendário retorna [] ou None, nunca um erro. A maioria dos tickers fora das grandes empresas não tem calendário no servidor; portanto, verifique se está vazio em vez de esperar exceções.
Duas datas por evento — use a correta
Cada dividendo e cada desdobramento carrega duas datas, e escolher a errada introduz viés de antecipação:
| “Eu poderia saber?” | “Quando isso afeta a minha posição?” | |
|---|---|---|
| Dividendo | declaration_date | ex_date |
| Desdobramento | filing_date | effective_date |
dividends() / splits() / filings() filtram pela primeira coluna — retornam apenas o que era público na sua barra. Um desdobramento costuma ficar visível semanas antes de entrar em vigor, porque o 8-K é arquivado com antecedência:
from datetime import date
bar_date = date.fromisoformat(str(bar["t"])[:10])
splits = calendar.splits(bar["t"], symbol)
upcoming = [s for s in splits
if s.effective_date and s.effective_date > bar_date] # announced, not yet effectiveCampos dos eventos
DividendEvent: ex_date, amount, estimated, type, declaration_date,
record_date, payment_date, period_end
SplitEvent: effective_date, ratio, type ("forward" | "reverse"), filing_date, form
FilingEvent: form, filing_date, report_date, items, category,
accession_number, primary_document, primary_document_description
IpoInfo: date, first_trade_date, sourceamount (dividendos) e effective_date (desdobramentos) podem ser None — verifique antes de comparar.
A category de um arquivamento é uma de earnings, acquisition, officer-director, charter-amendment, agreement, regulation-fd, auditor-change, shareholder-vote, cybersecurity, other.
O indicador estimated
O EDGAR não publica as datas ex-dividendo. A menos que houvesse dados da bolsa, a data ex é estimada como a data de declaração + 10 dias e tem precisão de cerca de ±7 dias, com estimated is True. Por padrão, a simulação ainda credita os dividendos estimados (política best_available); uma predefinição de execução (.qcs) pode definir dividendDatePolicy como exact_only (ignorar os estimados) ou off — não há controle na caixa para isso. Filtre por ele na sua própria lógica se a sua estratégia for sensível à data ex:
exact = [d for d in calendar.dividends(bar["t"], symbol) if not d.estimated]Eventos corporativos na simulação
Ambas as subopções ficam ativadas por padrão quando os dados de calendário estão ativados, e ambas são executadas antes dos seus callbacks em cada barra — assim, on_bar sempre vê uma posição já ajustada.
Ajustar as posições por desdobramentos de ações — na data de vigência, a quantidade de ações é multiplicada pela razão e o custo base é dividido por ela. Os preços de stop e de alvo também são reescalados. Como qty × entry_price não muda, a sua curva de patrimônio permanece contínua ao longo do desdobramento.
As barras de preço ficam propositalmente sem ajuste, então bar["close"] é o preço histórico real. Um indicador calculado sobre a série bruta de fechamentos ainda verá a lacuna do desdobramento — ajuste a sua própria série com calendar.splits(...) se isso importar.
Creditar dividendos em dinheiro — na data ex, qty × amount é somado ao caixa nas posições compradas e subtraído nas vendidas (quem vende a descoberto deve o dividendo ao emprestador). Isso flui para o patrimônio e para todas as métricas de retorno, mas não para realized_pnl, que continua sendo apenas de operações. Leia os totais nas métricas da conta:
def on_finish(bars, symbol=None, bars_by_symbol=None):
from quantcraft.process.runtime import account
m = account.refresh_metrics({})
print(m["total_dividend_income"], m["total_splits_applied"])Onde você vê os eventos corporativos
Nada altera a sua posição ou o seu caixa em silêncio:
- Painel de saída — uma linha
[calendar]por evento corporativo aplicado, mais um resumo no final:[calendar] 2024-01-10 AAPL — SPLIT 4:1 applied to 1 position(s): 100 -> 400 shares (cost basis unchanged; bars stay unadjusted) [calendar] 2024-02-09 AAPL — DIVIDEND $0.2400/share on 400 share(s): +$96.00 cash … [calendar] corporate actions — 1 split(s) applied; 1 dividend(s) applied (0 exact ex-date, 1 estimated +/-7d) - Test Results — uma linha Split ou Dividend aparece intercalada com as operações encerradas (o cartão passa então a se chamar Closed trades & events), mostrando a razão ou o valor por ação e o impacto em dinheiro. Uma data ex estimada é marcada com
est.Essas linhas não têm marcador#no gráfico e são excluídas da exportação CSV.
next_earnings é pontual no tempo
Em um backtest, next_earnings nunca retorna a “próxima data de resultados” do servidor calculada a partir de hoje — isso seria viés de antecipação em uma barra histórica. Ela é reconstruída a partir do último arquivamento de resultados visível na sua barra mais a cadência de divulgação da empresa, então basis == "filing-cadence" e estimated is True.
Retorna None quando nenhum arquivamento de resultados está visível ainda — no início de uma execução, ou para um símbolo cujo histórico de arquivamentos não volta tão longe. Sempre verifique isso.
Quando você não vê dividendos
Uma execução que não aplica nada explica o motivo no painel de saída:
| O log diz | Significado |
|---|---|
loaded 3/5 symbol(s); 2 without calendar data | Impresso no início: quantos símbolos receberam um calendário |
none of 5 symbol(s) returned calendar data: … | Nenhum símbolo da execução tem dados de calendário — nada pode ser aplicado |
no calendar data on the server | A tarefa de calendário não foi executada para esse símbolo |
calendar has no dividend or split history | Não paga dividendos, sem desdobramentos registrados |
… ex-dates 2019-05-10..2020-05-08 | Paga, mas não dentro do seu intervalo de datas testado |
N with no ex-date, which can never be applied | Existe histórico, mas não pode ser posicionado no relógio |
no positions were held … | Nada estava aberto quando um evento venceu |
Se nenhuma linha [calendar] aparecer, os dados de calendário não foram anexados à execução — verifique a alternância Include calendar data na aba Symbol & data.
Veja também
- Backtests — a caixa Run backtest e a opção Include calendar data
- Ciclo de vida da estratégia — parâmetro de callback
calendar, variável global de execuçãoqc_calendar - Modelo de conta — onde caem o dinheiro dos dividendos e os ajustes de desdobramento
- Screener — como os calendários são carregados quando um screener resolve a lista de tickers
- Resultados dos testes — linhas Split / Dividend na tabela de operações encerradas
- Painel de saída — linhas de log
[calendar]

