頻度を変える
データが必要な頻度で届くことはまれです。ティックはミリ秒単位で届き、モデルは日足を、レポートは月次を求めます。リサンプリングは時系列を新しい期間に再編成します。細かい頻度から粗い頻度へ(日次から月次)はダウンサンプリングで、新しい期間に複数の古い観測が入るため、まとめ方を指定する必要があります。粗い頻度から細かい頻度へ(週次から日次)はアップサンプリングで、データのない新しい期間ができるため、何を入れるかを指定する必要があります。
import pandas as pd
daily = pd.Series(
[100.0, 101, 103, 102, 104, 105, 103, 106],
index=pd.bdate_range("2026-02-25", periods=8), # Wed 25 Feb ... Fri 6 Mar
name="close",
)
print(daily.resample("ME").last()) # the last price of each month ("ME" = month end)
# 2026-02-28 103.0
# 2026-03-31 106.0
# Freq: ME, Name: close, dtype: float64
print(daily.resample("W-FRI").last()) # the last price of each week, weeks ending on Friday
# 2026-02-27 103.0
# 2026-03-06 106.0
# Freq: W-FRI, Name: close, dtype: float64集計方法を選ぶ
series.resample("ME") だけでは何も起きません。期間を記述しているだけです。続く集計が値を決めるので、データの意味に合うものを選びます。価格はスナップショットなので、月は last(または first)の値で表します。出来高は取引量なので、月は sum です。値幅には max と min を使います。ラベルはルールに従い、"ME" は月を暦の最終日(土曜日でも)で、"W-FRI" は週をその金曜日で表します。
volume = pd.Series([10, 20, 30, 40, 50, 60, 70, 80], index=daily.index)
print(volume.resample("ME").sum().to_dict())
# {Timestamp('2026-02-28 00:00:00'): 60, Timestamp('2026-03-31 00:00:00'): 300}
# Several summaries at once
print(daily.resample("ME").agg(["first", "last", "max"]))
# first last max
# 2026-02-28 100.0 103.0 103.0
# 2026-03-31 102.0 106.0 106.0ティックから足を作る、アップサンプリング
チャートやモデルはOHLC足を使います。各期間の始値(最初の価格)、高値、安値、終値(最後の価格)です。resample("D").ohlc() は日中の価格から1回の呼び出しでそれを作ります。週末のように取引が1件もない暦日も NaN の行として残るので、取引のあった日だけが欲しいときは最後に dropna() を付けます。アップサンプリングは逆方向です。resample("D").ffill() はデータのない日に直近の既知の値を繰り返し、これが週次で公表される価格の本来の意味です。価格に bfill は決して使わないでください。未来の値を過去へコピーし、明日の情報が今日に漏れてしまいます。
times = ["2026-03-05 09:30", "2026-03-05 11:00", "2026-03-05 15:59",
"2026-03-09 09:30", "2026-03-09 12:00", "2026-03-09 15:59"]
ticks = pd.Series([100.0, 101.5, 99.8, 100.7, 102.0, 101.0], index=pd.to_datetime(times))
bars = ticks.resample("D").ohlc()
print(bars)
# open high low close
# 2026-03-05 100.0 101.5 99.8 99.8
# 2026-03-06 NaN NaN NaN NaN
# 2026-03-07 NaN NaN NaN NaN
# 2026-03-08 NaN NaN NaN NaN
# 2026-03-09 100.7 102.0 100.7 101.0
print(bars.dropna().index.strftime("%d %b").tolist()) # ['05 Mar', '09 Mar'] only the days that traded# Upsampling: observations on the 2nd, 6th and 10th, spread over every day with ffill
weekly = pd.Series([100.0, 103.0, 101.0], index=pd.to_datetime(["2026-03-02", "2026-03-06", "2026-03-10"]))
print(weekly.resample("D").ffill().tolist())
# [100.0, 100.0, 100.0, 100.0, 103.0, 103.0, 103.0, 103.0, 101.0]
print(int(weekly.resample("D").mean().isna().sum())) # 6 without a fill rule the new days are empty"ME" のようにラベルは期間の末尾に置き、アップサンプリングには ffill(bfill は不可)を使い、月次のシグナルは日次データに使う前に前方へずらしましょう。series.resample(ルール)が期間("D"・"W-FRI"・"ME"・"h")を表し、続く集計が値を計算する- 価格は
lastかohlc()、出来高はsum。空の期間はNaNになり、dropna()で取り除ける - アップサンプリングには補完ルールが必要:
ffill()は直近の値を繰り返す。価格にbfill()は未来が漏れるので使わない
次はローリングウィンドウです。直近の期間をスライドする窓で、移動平均などの統計量を計算します。
ラボ:採点される内容
month_end_closeで各月の最後の価格を取る25点weekly_volumeで週ごとの出来高を合計する25点daily_ohlcで日中の価格から日足を作る25点fill_to_dailyで不規則な観測を毎日に広げる25点