Visualizing Japan's Capital Flight: The "Payday Anomaly" in USD/JPY
The Japanese Yen has been experiencing historic weakness. While many attribute this solely to interest rate differentials or government interventions, I suspected a more mechanical, structural force at play: the automated capital flight by Japanese retail investors.
The Hypothesis: The Payday Effect
In Japan, the 25th of the month is the standard payday for most corporate workers. Recently, due to inflation and the new tax-free investment program (NISA), a massive number of people have set up automated monthly purchases of foreign equity index funds (such as the S&P 500 or All-Country World Index).
I hypothesized that this creates an automatic, system-wide "Sell JPY / Buy USD" order triggered every single month around payday.
The Code
To verify this, I wrote a Python script using yfinance and seaborn to map the average daily return of USD/JPY by the week and day of the month, covering data from 2015 to May 2026.
‘’’Python
import yfinance as yf
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
# 分析期間の設定
dateStart = "2015-01-01"
dateEnd = "2026-05-23"
ticker = "JPY=X" # ドル円
# yfinanceから取得(仕様変更の警告回避のため auto_adjust を明示)
df = yf.download(
ticker,
start=dateStart,
end=dateEnd,
auto_adjust=False,
progress=False
)
# yfinanceの仕様変更(MultiIndex化)に対応して終値を安全に抽出
if isinstance(df.columns, pd.MultiIndex):
close = df["Close"][ticker].dropna()
else:
close = df["Close"].dropna()
# 前日比の変化率(%)を計算
# ドル円の場合、プラス = ドル買い/円売り、マイナス = ドル売り/円買い
daily_return = close.pct_change() * 100
# 分析用のDataFrameを作成
analysis_df = pd.DataFrame({"Return": daily_return})
analysis_df.index = pd.to_datetime(analysis_df.index)
# 「第何週目か」を計算(1日〜7日=第1週、8日〜14日=第2週...)
analysis_df["Day_of_Month"] = analysis_df.index.day
analysis_df["Week_of_Month"] = (analysis_df["Day_of_Month"] - 1) // 7 + 1
# 「何曜日か」を取得 (0=月曜, 1=火曜, ..., 4=金曜)
days_map = {0: "1_Mon", 1: "2_Tue", 2: "3_Wed", 3: "4_Thu", 4: "5_Fri"}
analysis_df["Day_of_Week"] = analysis_df.index.dayofweek.map(days_map)
# 為替市場のメインである平日(月〜金)のみに絞る
analysis_df = analysis_df[analysis_df.index.dayofweek < 5]
# 第何週 × 曜日 ごとの「平均変化率」を集計
pivot_table = analysis_df.pivot_table(
values="Return",
index="Week_of_Month",
columns="Day_of_Week",
aggfunc="mean"
)
# ヒートマップで可視化
plt.figure(figsize=(10, 6))
# ゼロを基準(center=0)にして、赤=ドル買い/円売り、青=ドル売り/円買い
sns.heatmap(pivot_table, annot=True, cmap="coolwarm", center=0, fmt=".3f",
cbar_kws={'label': 'Average Daily Return (%)'})
plt.title("USD/JPY Average Daily Return by Week and Day\n(Positive[Red] = USD Buy / JPY Sell)")
plt.xlabel("Day of the Week")
plt.ylabel("Week of the Month (1st to 5th)")
plt.tight_layout()
plt.show()
‘’’
The Discovery
The resulting heatmap revealed a striking anomaly.
Look at the Thursday of the 5th week. It shows a massive +0.154% average return (indicating strong USD Buy / JPY Sell), flashing deep red and far exceeding any other day on the board.
The Mechanism: Why 4 Days Later?
Why does the anomaly hit at the end of the month rather than exactly on the 25th? It perfectly aligns with the settlement lag of investment trusts:
1. The 25th (Week 4): Payday. Automated fund withdrawals are executed from retail bank accounts.
2. Order Processing: Brokers process the massive wave of mutual fund buy orders.
3. The Settlement Lag (T+3 / T+4): It takes about 3 to 4 business days for the actual currency exchange (selling JPY to buy USD) to hit the forex market.
This delay perfectly lands on the Thursday of the 5th week (around the 29th-31st).
Conclusion
This red square on the heatmap isn't just market noise. It is the footprint of an automated, programmed capital exodus from Japan. No matter how much the government tries to intervene in the forex market, this massive "automatic USD-buying machine" activates like clockwork every month.
