Las fechas no son cadenas de texto
Una serie de precios es una serie temporal: lo que importa es cuándo ocurrió cada precio. Las fechas leídas de un archivo son simples cadenas, y una cadena no sabe que marzo viene después de febrero ni que un lunes sigue a un domingo. Conviértelas con pd.to_datetime y usa el resultado como índice: un DatetimeIndex contiene marcas de tiempo reales que pandas puede ordenar, cortar, comparar y descomponer. Ordénalo siempre (sort_index()) para que la observación más antigua venga primero.
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)) # TrueConstruir un calendario
A menudo necesitas fechas que nadie te dio: una cuadrícula para comparar o los días de un backtest. pd.date_range(start, periods=n, freq="D") produce n días naturales consecutivos, y pd.bdate_range omite los fines de semana y da días hábiles. (No sabe nada de festivos.) El argumento freq fija el paso: "D" es un día, "B" un día hábil, "h" una 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']Seleccionar por fecha
Con un DatetimeIndex ordenado, .loc entiende fechas escritas como cadenas. Una cadena parcial como "2026-03" selecciona todo el mes, "2026" todo el año y "2026-03-04" un solo día. Un corte .loc["2026-03-04":"2026-03-06"] selecciona un rango y, a diferencia de un corte por posiciones, ambos extremos están incluidos. Los extremos no necesitan existir en los datos: las fechas de fin de semana simplemente no coinciden con nada, que es lo que quieres cuando pides «todo desde el uno del mes».
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 nothingLas partes de una fecha
Un DatetimeIndex expone las partes de cada fecha como atributos: year, month, day, dayofweek (el lunes es 0, el domingo 6). Cada una es un array con una entrada por fila, así que sirve como máscara o como clave de grupo. Así se pregunta «¿cuántas observaciones caen en cada día de la semana?» o «¿qué pasa los lunes?» sin bucle. Recuerda ordenar el índice antes: cortar un DatetimeIndex desordenado puede dar resultados sorprendentes o un error.
# 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].loc["2026-03-04":"2026-03-06"] incluye el día 6, pero con datos intradía se detiene a las 00:00 del 6 y pierde todo el día. Comprueba la última marca de tiempo del resultado cuando tus datos sean más finos que un día.pd.to_datetime(cadenas)crea un DatetimeIndex;sort_index()pone lo más antiguo primero;date_rangeybdate_rangeconstruyen calendarios..loc["2026-03"]selecciona un mes,.loc["2026-03-04":"2026-03-06"]un rango con ambos extremos incluidos.index.year,index.month,index.dayofweekdan las partes de cada fecha, para filtrar o agrupar sin bucles.
A continuación: el remuestreo, que convierte precios diarios en barras semanales, mensuales o más finas.
Lab: qué se califica
- Construir una serie de precios con fechas con
parse_prices25 pts - Seleccionar un mes con
prices_in_month25 pts - Seleccionar un rango de fechas con
prices_between25 pts - Contar las observaciones por día de la semana con
count_by_weekday25 pts