/ 投資インサイト ← インサイト一覧

KSTモードで土曜が空白に見える理由 — 米国金曜セッション・マッピングの秘密

2026.05.17 · カレンダー · KST · データモデリング · 한국어 ↗

韓国や日本に住みながら米国株を保有すると、ひとつ厄介な問いが生まれます。米国市場が引ける時刻は、KST(韓国標準時。日本時間と同じUTC+9)で土曜の早朝5〜6時。その変動をカレンダーに表示するとき、「米国金曜(現地日付)」の枠に入れるべきでしょうか、それとも「土曜(ユーザーが眠りから覚めた日)」の枠に入れるべきでしょうか。本稿では、この決定が単なる表示の違いではなく、「今日のリターン」が誠実かどうかを左右する問題であることを、コードレベルで解き明かします。

発見された症状

実際のユーザーからの報告で始まった話です。「カレンダーの土曜のセルにSOXL +16.33%がはっきり表示されているのに、合計は−0.49%と出ます。マイナスなのが信じられません。」

SOXLは米国金曜セッションで16%超上昇し、ユーザーはKST(日本時間と同じ)の土曜の朝にそのデータを確認しました。ところがポートフォリオの合計は、まるで米国金曜セッションが存在しなかったかのように、直前の取引日の数値だけを表示していたのです。

この一行の報告が、数日がかりのデータモデル整理につながりました。結論を先に言うと — これは単純なバグではなく、「米国終値をどの日付にマッピングするか」という方針そのものが揺らいでいた問題でした。

2つのマッピングモード

Multifoliosの設定には「カレンダー日付基準」というオプションがあります。2つのモード:

モード米国終値をどこに表示このモードを使うユーザー
マーケット基準 (Market)米国現地日付。Yahoo Finance の原データのまま。米国の証券会社を直接使うユーザー、米国現地の報道と一致させたい場合。
KST基準米国終値を+1日シフト。米国金曜 → KST土曜。韓国・日本で米国株を保有するユーザー。「目覚めたその日」の変動を見たい場合。

デフォルトは、韓国語ユーザーにはKST、日本語・英語ユーザーにはMarket。この選択は単なる表示オプションではありません。カレンダーセルの数値、資産推移グラフの段差、「今日の要約」の日次変動率 — これらすべてが、同じデータをどの日付にマッピングするかによって変わります。

データモデル — 日付はどこに住むのか

カレンダースナップショットをビルドする関数は、次のような流れで動作します:

// pseudocode
for each holding:
  history = fetchYahooHistory(symbol)  // 日次終値の配列
  for each (date, close) in history:
    if mode === 'kst' && isUSSymbol(symbol):
      // 米国銘柄のみ+1日シフト
      priceMap[symbol][shiftByOne(date)] = close
    else:
      priceMap[symbol][date] = close

for each calendar day d:
  for each holding:
    price = priceMap[symbol][d] || forwardFill(...)
    total += price * shares
  snapshot[d] = total

要点: shiftByOneは米国銘柄にのみ適用されます。韓国・日本の銘柄はそのまま。この非対称性こそがKSTモードの本質です。

具体的に追ってみましょう。2026年5月8日(米国金曜):

バグが潜んでいた場所

ユーザーが報告した−0.49%の問題は、2箇所で発生していました。

1) 週末lookupの過剰な一般化

「今日の要約」は今日の日付に該当するカレンダーセルを探して変動率を表示します。週末は市場の活動がないため、直前の金曜に繰り戻して表示するロジックが入っていました。コードは単純でした:

while (lookup.getDay() === 0 || lookup.getDay() === 6) {
  lookup.setDate(lookup.getDate() - 1);
}

マーケット基準モードでは、これで正しい。土曜・日曜にはどの市場も新しいデータを生み出しません。しかしKSTモードの土曜は違います。米国金曜セッションがKST土曜にマッピングされているのです。土曜を金曜に戻してしまうと、そのシフトされたデータを取りこぼします。結果: ユーザーが土曜の朝に見た変動率は「米国木曜セッション + 韓国金曜セッション」 — 米国金曜が抜け落ちたマイナスでした。

2) directDayPctのマーケット基準前提

2つ目はもっと微妙でした。今日の変動率を精密に計算するための別経路があったのです — 各銘柄のcurrentPriceprevCloseを直接引き算して合算する方式。普段は正確ですが、KSTモードの土曜では誤った答えを返します。

なぜか。Yahoo Finance APIが返すregularMarketPreviousClose各銘柄自身の直前取引セッションの終値です。SOXLの場合、土曜に照会するとprevClose = 米国木曜終値。ところがKST土曜のスナップショットはすでに「米国金曜終値」を抱えているため、currentPrice (Fri) − prevClose (Thu) = 金曜セッションの変動を二重計上(over-count)してしまいます。

韓国銘柄はさらに深刻です。KST土曜のサムスンはcurrentPrice = 金曜終値、prevClose = 木曜終値。しかしKST 5/9スナップとKST 5/8スナップの両方が韓国金曜終値をforward-fillで保持しているため、韓国側から見た5/9 → 5/8の変動は本来0のはず。directDayPctは韓国のFri−Thu変動までもう一度紛れ込ませてしまいます。

「同じ変動率の式が、モード次第で嘘をつく」 — この気付きが修正の方向を決めました。

修正の原則

2つの原則を立てました。

  1. 週末lookupはモードを認識する。マーケット基準モードは土・日ともに直前の金曜へ繰り戻すが、KSTモードは土曜を保持。日曜はどちらのモードでも直前の取引日へ繰り戻す(KSTの日曜は本当に新しいデータがないので)。
  2. KSTモードではdirectDayPctを使わない。代わりにスナップショット基準のdayRet(今日のtotal − 昨日のtotal)を使用。これはKSTシフトが既に反映されたデータをそのまま引き算するため、すべての曜日・時間帯で一貫して正確です。

結果的に、KSTモードはよりシンプルになりました。「今日のKST合計 − 昨日のKST合計」の一行で、すべてのケースが解けます。マーケット基準モードは既存のdirectDayPct経路を維持(韓国・日本のユーザーが米国現地時刻で見たい場合、それが意味を持つため)。

他のトラッカーはこれをどう扱っているのか

海外製ポートフォリオトラッカーの大半は米国ユーザー基準なので、この問題自体がそもそも浮上しません。米国銘柄 → 米国日付。以上。韓国銘柄があってもマーケット基準で表示して終わりです。

韓国製トラッカーは韓国銘柄だけを深く扱い、米国・日本は補助機能程度のことが多く、「複数市場の終値をKSTカレンダーに一貫して表示する」という要件自体があまり取り上げられません。

MultifoliosがあえてKSTモードを作った理由は — 韓国・日本で米国株を保有するユーザーが実際に生きている時間感覚を、データモデルに反映するためです。米国金曜セッションの急落(あるいは急騰)を土曜の朝のコーヒーとともに確認する人にとって、その変動は土曜の枠にあってこそ誠実なのです。

実際のユーザーへの示唆

誠実な数字のためのコード

「今日のリターン」のような些細に見える数字が正確であるためには、そのユーザーがどのタイムゾーンに住み、どの市場を保有しているかをデータモデルが知っている必要があります。一般的なトラッカーが扱わない領域なので、きれいな正解はありません — モードの選択権を与え、各モードで一貫した意味を保証するのが現実的な解法です。

本稿で扱ったデータモデルは、Multifoliosのカレンダーと「今日の要約」にそのまま実装されています。設定 → カレンダー日付基準で2つのモードを切り替えれば、同じ資産がどう異なってマッピングされるかを直接確認できます。

Multifolios 運営者
個人投資家・開発者 · Multifolios 制作・運営
複数の証券会社・通貨に散らばった資産を自分で追跡するうちに不便を感じ、Multifolios を作りました。実際に運用しながら直面したリターン計算・為替分離・リバランスの問題を記事にまとめています。お問い合わせ: 紹介・連絡先