σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
Roteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Python›Módulo 2 · NumPy e pandas para dados de mercado›Tópico 2.12·~40 minIntermediário

DatetimeIndex e indexação temporal

Posição no roteiroMódulo 2 de 11 · Tópico 12 de 20
2.12 DatetimeIndex e indexação temporal
—Nota do lab— / 100XP total—Sequência—

Datas não são strings

Uma série de preços é uma série temporal: o que importa é quando cada preço ocorreu. Datas lidas de um arquivo são strings simples, e uma string não sabe que março vem depois de fevereiro nem que uma segunda-feira segue um domingo. Converta-as com pd.to_datetime e use o resultado como índice: um DatetimeIndex guarda carimbos de tempo reais que o pandas sabe ordenar, fatiar, comparar e decompor. Ordene-o sempre (sort_index()) para que a observação mais antiga venha primeiro.

import pandas as pd

raw_dates = ["2026-03-04", "2026-03-02", "2026-03-03"]      # strings, in a messy order
closes = [102.0, 100.0, 101.0]

series = pd.Series(closes, index=pd.to_datetime(raw_dates), name="close").sort_index()
print(series)
# 2026-03-02    100.0
# 2026-03-03    101.0
# 2026-03-04    102.0
# Name: close, dtype: float64

print(isinstance(series.index, pd.DatetimeIndex))   # True

Construir um calendário

Muitas vezes você precisa de datas que ninguém lhe deu: uma grade para comparar ou os dias de um backtest. pd.date_range(start, periods=n, freq="D") produz n dias corridos consecutivos, e pd.bdate_range pula os fins de semana e dá dias úteis. (Ele não sabe nada de feriados.) O argumento freq define o passo: "D" é um dia, "B" um dia útil, "h" uma hora.

# Four calendar days, then six business days (the weekend is skipped)
print(pd.date_range("2026-03-01", periods=4, freq="D").strftime("%a %d %b").tolist())
# ['Sun 01 Mar', 'Mon 02 Mar', 'Tue 03 Mar', 'Wed 04 Mar']

days = pd.bdate_range("2026-02-26", periods=6)
print(days.strftime("%a %d %b").tolist())
# ['Thu 26 Feb', 'Fri 27 Feb', 'Mon 02 Mar', 'Tue 03 Mar', 'Wed 04 Mar', 'Thu 05 Mar']

Selecionar por data

Com um DatetimeIndex ordenado, .loc entende datas escritas como strings. Uma string parcial como "2026-03" seleciona o mês inteiro, "2026" o ano inteiro e "2026-03-04" um único dia. Uma fatia .loc["2026-03-04":"2026-03-06"] seleciona um intervalo e, ao contrário de uma fatia de posições, os dois extremos são incluídos. Os extremos não precisam existir nos dados: datas de fim de semana simplesmente não casam com nada, que é o que se quer ao pedir "tudo desde o dia primeiro".

prices = pd.Series(
    [float(i) for i in range(20)],
    index=pd.bdate_range("2026-02-23", periods=20),   # Mon 23 Feb ... Fri 20 Mar
)

print(len(prices.loc["2026-03"]))      # 15   the business days of March in the data
print(prices.loc["2026-03-04"])        # 7.0  a single day

print(prices.loc["2026-03-04":"2026-03-06"])
# 2026-03-04    7.0
# 2026-03-05    8.0
# 2026-03-06    9.0
# Freq: B, dtype: float64

print(prices.loc["2026-03-01":"2026-03-03"].tolist())   # [5.0, 6.0]   Sunday the 1st matches nothing

As partes de uma data

Um DatetimeIndex expõe as partes de cada data como atributos: year, month, day, dayofweek (segunda-feira é 0, domingo é 6). Cada uma é um array com uma entrada por linha, então serve como máscara ou chave de grupo. É assim que se pergunta "quantas observações caem em cada dia da semana?" ou "o que acontece às segundas?" sem laço. Lembre-se de ordenar o índice antes: fatiar um DatetimeIndex fora de ordem pode dar resultados surpreendentes ou um erro.

# The parts of the dates, one entry per row
print(prices.index.dayofweek[:7].tolist())   # [0, 1, 2, 3, 4, 0, 1]   Monday is 0
print(prices.index.month[:7].tolist())       # [2, 2, 2, 2, 2, 3, 3]

# How many observations fall on each weekday?
print(prices.groupby(prices.index.dayofweek).size().to_dict())   # {0: 4, 1: 4, 2: 4, 3: 4, 4: 4}

# What do the Mondays look like?
print(prices[prices.index.dayofweek == 0].tolist())   # [0.0, 5.0, 10.0, 15.0]
Cuidado com o fim do intervaloUma string de data sem hora significa meia-noite. Com dados diários, .loc["2026-03-04":"2026-03-06"] inclui o dia 6, mas com dados intradiários ele para às 00:00 do dia 6 e perde o dia inteiro. Verifique o último carimbo de tempo do resultado quando seus dados forem mais finos que um dia.
  • pd.to_datetime(strings) cria um DatetimeIndex; sort_index() põe o mais antigo primeiro; date_range e bdate_range constroem calendários.
  • .loc["2026-03"] seleciona um mês, .loc["2026-03-04":"2026-03-06"] um intervalo com os dois extremos incluídos.
  • index.year, index.month, index.dayofweek dão as partes de cada data, para filtrar ou agrupar sem laços.

A seguir: a reamostragem, que transforma preços diários em barras semanais, mensais ou mais finas.

Lab: o que é avaliado

  • Construir uma série de preços com datas com parse_prices25 pts
  • Selecionar um mês com prices_in_month25 pts
  • Selecionar um intervalo de datas com prices_between25 pts
  • Contar as observações por dia da semana com count_by_weekday25 pts
Explorador · lab-45-1
▾ lab-45-1
…
bash · no navegador
learner@quantcraft:~/lab-45-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-45-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações

Entre para executar o seu código.

Todas as aulas são gratuitas para ler. Crie uma conta ou entre para executar código, rodar os testes e enviar este lab.

  • IDE no navegador com terminal bash — nada para instalar
  • Correção instantânea, XP e o seu lugar no roteiro
Criar uma contaEntrar
OU
Continuar com o GitHub