日付は文字列ではない
価格の系列は時系列です。大切なのは各価格がいつ起きたかです。ファイルから読んだ日付はただの文字列で、3月が2月の後であることも、月曜日が日曜日の次であることも知りません。pd.to_datetime で変換し、その結果をインデックスにしましょう。DatetimeIndex は本物のタイムスタンプを持ち、pandas が並べ替え・スライス・比較・分解をできます。最も古い観測が先頭に来るよう、必ず sort_index() で並べ替えます。
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カレンダーを作る
誰も用意してくれない日付が必要になることがよくあります。比較用の目盛りや、バックテストの日々などです。pd.date_range(start, periods=n, freq="D") は連続する暦日を n 個作り、pd.bdate_range は週末を飛ばして営業日を作ります(祝日は考慮しません)。freq で間隔を指定します。"D" は1日、"B" は営業日、"h" は1時間です。
# 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']日付で選ぶ
ソートされた DatetimeIndex では、.loc が文字列の日付を理解します。"2026-03" のような部分文字列は1か月全体、"2026" は1年全体、"2026-03-04" は1日を選びます。スライス .loc["2026-03-04":"2026-03-06"] は範囲を選び、位置のスライスと違って両端を含みます。端の日付がデータにある必要はありません。週末の日付は何にも一致しないだけで、「月初から全部」と頼むときにはそれが望む動作です。
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日付の構成要素
DatetimeIndex は各日付の構成要素を属性として持ちます。year、month、day、dayofweek(月曜が0、日曜が6)です。それぞれ行ごとに1つの値を持つ配列なので、マスクやグループのキーとして使えます。「各曜日に何件の観測があるか」「月曜日には何が起きるか」をループなしで調べられます。先にインデックスをソートするのを忘れずに。順序の乱れた DatetimeIndex をスライスすると、意外な結果やエラーになることがあります。
# 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"] は6日を含みますが、日中のデータでは6日の 00:00 で終わり、その日全体を失います。データが1日より細かいときは、結果の最後のタイムスタンプを確認しましょう。pd.to_datetime(文字列)で DatetimeIndex を作り、sort_index()で古い順に並べ、date_rangeとbdate_rangeでカレンダーを作る.loc["2026-03"]は1か月、.loc["2026-03-04":"2026-03-06"]は両端を含む範囲を選ぶindex.year・index.month・index.dayofweekは各日付の構成要素を返し、ループなしで絞り込みや集計ができる
次はリサンプリングです。日次の価格を週次・月次、あるいはより細かい足に変換します。
ラボ:採点される内容
parse_pricesで日付付きの価格系列を作る25点prices_in_monthで1か月分を選ぶ25点prices_betweenで日付の範囲を選ぶ25点count_by_weekdayで曜日ごとの観測数を数える25点