GPI開発日誌 Vol.15|30・25・20・15・10は本当に正しい?過去データでMethodologyを疑う

目次

はじめに

こんにちは。

GadgetStreemでは現在、ガジェット価格の上昇圧力を一つの数字で確認できる独自指数、

GPI(Gadget Pressure Index/ガジェット価格圧力指数)

を開発しています。

これまでのVol.13では、ドル円や物価指数など単位の異なる市場データを0〜100へ変換する、

Component Scoring

を紹介しました。

Vol.14では、そのComponent Scoreを、

USD/JPY   30%
DRAM      25%
NAND      20%
GPU       15%
Freight   10%

という固定ウェイトで合成し、一つのGPIを作る、

Composite Engine

を紹介しました。

ここまで読むと、次の疑問が出てきます。

なぜドル円は30%なのか?

DRAMは25%で本当にいいのか?

GPUを20%にした方がよい可能性はないのか?

当然の疑問です。

実は私たち自身も、

最初に30・25・20・15・10と決めたから、そのまま使えばよい

とは考えていません。

そこでGadgetStreem Intelligenceでは、

GPIの計算式そのものを疑うための仕組み

を作りました。

今回のテーマは、

  • Historical Replay
  • Market Regime Backtest
  • Weight Validation

です。


GPIのウェイトは「答え」ではなく仮説

GPIを設計した当初、5つのComponentへ次のウェイトを設定しました。

ComponentWeight
USD/JPY30%
DRAM25%
NAND20%
GPU15%
Freight10%

ドル円を最大にしたのは、日本のガジェット市場にとって為替が広範囲の輸入コストへ影響すると考えたためです。

DRAMとNANDはPCだけでなく、スマートフォン、SSD、ゲーム機など幅広い製品へ影響します。

GPUは対象製品が比較的限定されますが、PC市場では大きな価格要因です。

Freightは直接の部品価格ではありませんが、物流コストとして価格圧力へ影響する可能性があります。

ただし、これらはあくまで、

GPI Ver.0.1を開始するためのMethodology上の仮説

です。

「30%という数字が自然法則として正しい」という意味ではありません。


だからコードに自動最適化させない

ここで、

過去データに一番よく合うウェイトをコンピューターに探させればいいのでは?

とも考えられます。

例えば、

USD/JPY   42%
DRAM      18%
NAND      12%
GPU       23%
Freight    5%

の方が過去データへよく適合するなら、それを採用すればよいという考え方です。

しかしGPIでは、この方法をそのまま採用しません。

過去データだけへ強く合わせると、

過去にだけ都合のよい指数

を作ってしまう危険があるからです。

金融分野のBacktestingでも、

look-ahead biasやsurvivorship biasへの注意が必要とされ、過去の環境で良好だった結果が将来も続くとは限りません。CFA Instituteも、Backtestは「過去に実行していたらどうなったか」を検証する方法であり、構造変化やlook-ahead biasなどに注意する必要があると説明しています。(CFA Institute)

SECに提出された指数関連資料でも、Hypothetical Backtestにはhindsightを含む固有の限界があり、将来結果を示すものではないことが明示されています。

そのためGPIでは、

Backtestで良かった
↓
自動でWeight変更

とはしません。


まず「過去のGPI」を正しく再現する

Weightを検証する前に必要なのが、

Historical Replay

です。

例えば、

2024年6月15日時点のGPIは何点だったのか?

を再計算するとします。

現在のデータベースにある最新値を使えば、計算自体は簡単です。

しかし、それでは正しいBacktestになりません。


現在知っている「訂正後の数字」を過去へ持ち込んではいけない

BLSなどの統計データは、後からRevisionされる場合があります。

例えば、

2024年6月時点の公表値
100.4

後日訂正された最終値
101.1

だったとします。

2024年6月15日時点のGPIを再現するなら、

101.1

ではなく、

当時実際に利用可能だった、

100.4

を使わなければなりません。

現在の確定値を過去の計算へ使えば、

未来の情報を過去の自分へ教える

ことになります。


First RevisionとRecorded Vintage

そこでGSIでは、Historical Replayを大きく2種類に分けています。

First Revision

各観測値について、

最初に公表された値だけを使う

Replayです。

後からどれだけ訂正されても、その後のRevisionは利用しません。


Recorded Vintage

こちらは、

そのHistorical Checkpoint時点までに実際に公表されていたRevision

を使います。

例えば、

6月10日
Revision 0 公表

7月5日
Revision 1 公表

なら、

6月15日のReplayではRevision 0

7月10日のReplayではRevision 1

という具合です。

GSIのHistorical Evidence実装では、このfirst_revisionrecorded_vintageの両方を生成し、後から分かったRevisionを過去へ遡って適用しないことを明示しています。


未来情報の漏洩を禁止する

この問題を、

Future-information Leakage

または、

Look-ahead Bias

と呼びます。

GPIではHistorical Replayにおいて、

後から取得した値を
過去Checkpointへ使用

→ 禁止

です。

さらに、

後から公表されたRevisionを
過去へ遡って使用

→ 禁止

そして、

当時存在しなかった観測値を
補間で生成

→ 禁止

です。

Historical Evidenceの設計では、未来情報Leakage防止、線形補間禁止、Missing Weightの再配分禁止まで明示しています。


土曜日ごとのGPIを再現する

GPIは週次更新を予定しています。

そのためHistorical Replayでは、

毎週のCheckpoint時点で何が利用可能だったか

を再現します。

例えば、

2024-05-04
2024-05-11
2024-05-18
2024-05-25
...

という各週について、

その日に利用可能だった
最新のUSD/JPY

その日に利用可能だった
DRAMデータ

その日に利用可能だった
NANDデータ

その日に利用可能だった
GPUデータ

その日に利用可能だった
Freightデータ

を探します。

重要なのは、

今から見て最新のデータ

ではなく、

その日から見て最新だったデータ

です。


月次データを週ごとに増殖させない

例えば月次統計が、

6月観測:1件

しかない場合。

それを、

6月第1週:1件
6月第2週:1件
6月第3週:1件
6月第4週:1件

という4つのObservationへ増やすことはしません。

同じ1件のObservationを、その時点で利用可能なら参照するだけです。

GSIのMixed-frequency設計でも、QuarterlyやMonthly Observationを週次Checkpointで参照する場合でもCanonical Observation Countを増やしてはいけないと定義しています。


古すぎるデータも「存在するからOK」にはしない

さらに重要なのが、

Freshness

です。

例えばFreightの最新データが3か月前だった場合。

データ自体は存在しています。

しかし、

今週の海上輸送価格圧力を表している

とは言いにくくなります。

そのためGPIでは、

値が存在するか

だけではなく、

その値はまだFreshか

も判定します。

古くなりすぎた値は、

Stale

としてCoverageへ含めません。


実際のFreight Backtestで問題が見つかった

これは設計上の話だけではありません。

BLS Deep Sea Freight候補について実際にHistorical Replayを行ったところ、

Weekly Checkpoints:209
Monthly Observations:48

Covered:
190 / 209

Coverage:
90.9091%

まで到達しました。

一見すると、

90%以上ならかなり良いのでは?

と思えます。

しかし詳細を見ると、

Stale checkpoints:16

Maximum selected age:
131 days

Maximum consecutive missing weeks:
15

Future-information leakage:
0

でした。

そのため判定は、

Historical Coverage:
PASS

Freshness:
FAIL

Common-gap Compatibility:
FAIL

となり、その時点ではProduction Slot Activationを認めませんでした。

これはBacktestを実装した意味がよく分かる例です。


「90%取れている」だけでは足りない

もし単純に、

Coverage > 90%
↓
PASS

だけを見ていたら、このFreight Candidateは通過していた可能性があります。

しかし、

15週間連続で有効な値を持てない期間があるなら、

週次指数としては大きな問題です。

つまり、

平均的にはデータがある

ことと、

実運用で安定して毎週使える

ことは別です。


その後FreightはProductionへ進んだ

ここで時系列を整理しておきます。

Vol.10ではBLS Deep Sea Freightについて、

海上輸送にかなり近いが、まだ10%へ正式採用しない

としました。

Historical Replayでも、先ほど説明したFreshness / Common-gap問題が検出されています。

しかし、そこで開発を止めたわけではありません。

その後、

  • Vintage Reconstruction
  • Freshness検証
  • Methodology Review
  • Qualification
  • Controlled Activation
  • Governance Reconciliation

という追加Gateを進めました。

現在は、

Freight
INCLUDED
10%

まで到達しています。

ただし、

Deep-sea freight price-pressure proxy / benchmarkであり、直接的なFreight Rateではない

というDisclosureを残しています。現在も固定ウェイトは30/25/20/15/10で、Missing Weight RenormalizationはNOです。

つまりBacktestでFAILしたことは、

候補データが永久に不採用になった

という意味ではありません。

問題が見つかったので、その問題を解決する次のGateへ進んだ

ということです。


次に「Market Regime」を検証する

Historical Replayができると、

GPIが過去にどのような状態だったかを時系列で確認できます。

そこで次に検証するのが、

Market Regime

です。

例えば将来GPIを、

LOW PRESSURE

NORMAL

HIGH PRESSURE

のような状態に分類するとします。

この境界値も、

なんとなく60点以上をHIGHにしよう

と決めるだけでは不十分です。


境界線の近くで表示が暴れないか

例えば、

HIGH:60以上
NORMAL:60未満

だった場合、

59.8
60.2
59.7
60.1
59.9
60.3

と動くだけで、

NORMAL
HIGH
NORMAL
HIGH
NORMAL
HIGH

と毎週表示が切り替わります。

これでは利用者から見ると非常に分かりづらい指数になります。

このような短期間の頻繁な切り替わりを、

Whipsaw

として評価します。


Regime Backtestでは何を見るのか

GSIのMarket Regime Threshold Backtestでは、

  • Historical Coverage
  • Regime Transition数
  • Whipsaw
  • Dwell Duration
  • Threshold Boundaryへの近さ

などを診断する仕組みを実装しました。

例えば、

HIGH PRESSUREへ入ったら平均何週間続くのか

や、

境界値付近を行ったり来たりしていないか

を確認できます。


ただしRegime Thresholdも自動変更しない

ここでも方針は同じです。

Backtestで、

このThresholdの方が良さそう

という候補が見つかっても、

自動的にProduction Threshold変更

はしません。

Issue #72の正式結果は、

Candidate Decision:
insufficient_evidence

Automatic Threshold Change:
false

Publishability:
NOT_PUBLISHABLE

Decision:
NO_GO

でした。

つまり、

Thresholdを検証する仕組みは完成したが、変更するだけの証拠はまだ足りない

という結論です。


そして本題のWeight Validation

ここまで整備したHistorical EvidenceとMarket Regimeを使って、

いよいよ、

30
25
20
15
10

というWeightそのものを検証します。

GSIではこれを、

Weight Validation

として独立したGateにしました。

検証対象には、

  • Historical Evidence Coverage
  • Weight Concentration
  • Effective Component Count
  • Composite Index Displacement
  • Market Regime Agreement
  • Dominant Pressure Share

などがあります。


Weight Concentrationを見る

例えば、

USD/JPY 70%
残り4項目 30%

のような構成を考えてみます。

これでは名前はGPIでも、

実態としては、

ほぼ為替指数

になってしまう可能性があります。

そのため、

Maximum Single Weight

や、

Top Two Weight

を確認します。


Effective Component Count

さらに、

Effective Component Count

も確認します。

これは簡単に言えば、

実質的に何個のComponentへ分散している指数なのか

を見る指標です。

5Componentを均等に使えば、実質的なComponent Countは5へ近づきます。

一つに強く偏れば、1へ近づきます。

現在の固定Weight、

30 / 25 / 20 / 15 / 10

では、検証用シナリオ上のEffective Component Countは、

4.444444

でした。

かなり5に近く、

一つだけに極端に依存する構成ではありません。


わざと「ドル円70%」も試した

Weight Validationでは、

極端なCandidateも意図的に作ります。

その一つが、

fx-heavy-v0.1

です。

このシナリオでは最大Weightを、

70%

まで増やしました。

結果は、

Maximum Single Weight:
0.70

Top Two Weight:
0.80

Effective Component Count:
1.946283

Mean Dominant Pressure Share:
0.694357

Maximum Index Delta:
1.71

でした。

そして判定は、

reject_unstable

です。

理由として、

  • Single Weightが大きすぎる
  • Top-two Concentrationが大きすぎる
  • Effective Component Countが小さすぎる

ことが明示されています。


「ドル円を増やせば良い」と単純にはいかない

これは興味深い結果です。

日本のガジェット価格にとって為替は重要です。

だからといって、

なら70%でいい

とはなりません。

あまり大きくするとGPIが、

Gadget Pressure Index

ではなく、

ほぼUSD/JPY Pressure Index

になってしまいます。

Weight Validationは、

それぞれの要素が重要であること

と、

一つの要素が指数全体を支配しないこと

の両方を見るための仕組みです。


では30・25・20・15・10は合格したのか?

ここは非常に重要です。

検証用の8観測シナリオでは、現在の固定Weight、

gpi-fixed-v0.1

について、

Maximum Single Weight:
0.30

Top Two Weight:
0.55

Effective Component Count:
4.444444

Regime Agreement:
8 / 8

Mean Dominant Pressure Share:
0.379087

となり、

review_candidate

という判定になりました。

しかし、

これで現在のWeightが最適だと証明された

という意味ではありません。


本番相当のWeight Validation判定は「証拠不足」

Weight Validationを実装した時点では、Production相当のEligible Historical Evidenceが十分ではありませんでした。

そのため正式なCurrent Evaluationは、

decision:
insufficient_evidence

automatic_weight_change:
false

missing_weight_renormalization:
false

public_numeric_release:
false

effective decision:
NO_GO

でした。

つまり、

今のWeightを変える根拠もないし、今のWeightが最適だと断定する根拠もまだ足りない

という結論です。

これはかなり重要な違いです。


Equal Weightもまだ「負けた」わけではない

比較シナリオには、

20 / 20 / 20 / 20 / 20

に相当するEqual Weight Candidateもあります。

しかし、このシナリオの判定は、

insufficient_evidence

です。

Eligible Historical Evidenceが0だったためです。

したがって、

「Equal Weightを検証したら悪かった」

とは言えません。

正確には、

そのテスト条件では判断するためのEvidenceが不足していた

です。

GPIではこの、

悪い

と、

分からない

を区別します。


「分からない」は正式な結果

データ分析では、

結論が出ない

という結果は扱いづらいものです。

しかしGPIでは、

INSUFFICIENT_EVIDENCE

を正式な判定として扱います。

証拠がないのに、

30/25/20/15/10が正しい

と断言するより、

現時点では変更するだけのEvidenceがない

とする方が正確です。


ではなぜ今も30・25・20・15・10なのか

現在のGPIでもWeightは、

30 / 25 / 20 / 15 / 10

のままです。

理由は、

Backtestでこの比率が絶対最適だと証明されたから

ではありません。

現在のMethodology Contractとして固定されており、

変更を正当化する十分なEvidenceがまだ承認されていないから

です。

そして、変更する場合も、

Weight Validation
↓
Human Review
↓
Methodology Version Change
↓
Revalidation

という工程が必要です。

自動的にProduction Weightを書き換えることは禁止されています。


Weightを変えたらMethodology Versionも変える

例えば将来、

十分なEvidenceが蓄積され、

USD/JPY
30% → 25%

GPU
15% → 20%

の方が妥当だという判断になったとします。

その場合、

こっそりWeightを書き換えることはしません。

これはMethodology Changeです。

例えば概念的には、

GPI Methodology v0.1.x
↓
GPI Methodology v0.2

のようにVersionを変更し、

旧GPIと新GPIの違いを記録する必要があります。

そうしなければ、

先週 62
今週 67

という差が、

市場変化なのかMethodology変更なのか分からなくなります。


Backtestの目的は「一番きれいな結果を探す」ことではない

GPIにおけるBacktestは、

過去のガジェット価格へ一番よく合うパラメーターを探す大会

ではありません。

むしろ、

Methodologyが壊れやすい場所を探す

ために使っています。

例えば、

データがStaleになる

一つのComponentが支配する

Regimeが毎週切り替わる

Revisionで過去結果が大きく変わる

特定期間だけCoverageが消える

Weightを少し変えるだけで
GPIが大きく動く

といった問題を見つけます。


相関が高くても「予測できる」とは限らない

将来的にはGPIと、

  • メモリ小売価格
  • SSD価格
  • GPU価格
  • ノートPC価格
  • スマートフォン価格

などを比較することも考えています。

そのとき、

GPIが上昇した後
小売価格も上昇した

という関係が見つかる可能性があります。

しかし、

相関がある

ことと、

将来価格を正確に予測できる

ことは別です。

Backtestはあくまで、

過去の環境でMethodologyがどう動いたか

を見るためのものです。

CFA Instituteも、Backtestだけでは歴史に存在しなかった将来環境を十分表せず、Structural RegimeごとのScenario Analysisを併用する重要性を説明しています。(CFA Institute)

そのためGPIは、

「来週○%値上がりする」

という予測モデルとは分けて考えています。


現在のProduction状態

ここで現在地も整理します。

GPIはその後の開発で、

USD/JPY
INCLUDED

DRAM
INCLUDED

NAND
INCLUDED
※Storage-device price proxy

Freight
INCLUDED
※Deep-sea freight price-pressure proxy

GPU
HISTORY_ACCUMULATION

となっています。

GPUは、

Raw observations:
24

Transformed samples:
23 / 36

です。

Production Coverageは、

85%

Required Coverageは、

100%

です。

そして現在も、

Composite Numeric GPI:
WITHHELD / NULL

Public Numeric Release:
NOT_PUBLISHABLE

です。


Historical Backtestがあるから85%を100%にしない

Vol.14でも説明したとおり、

GPU15%が欠けているからといって、

残り85%を100%へ再配分することはありません。

Historical Replayでも、

Missing Weight Redistribution
→ 禁止

です。

もしBacktest期間中だけWeightを再配分していたら、

現在のProduction Methodologyとは別の指数を検証することになるためです。


GPIのMethodologyは「変更しない」のではなく「勝手に変更しない」

ここまで読むと、

それではWeightは永遠に30/25/20/15/10なのでは?

と思うかもしれません。

そうではありません。

Evidenceが十分に揃い、

  • Historical Stability
  • Concentration
  • Regime Behavior
  • Data Coverage
  • Semantic Fit
  • Sensitivity
  • Human Review

を通過すれば、

Methodologyを更新する可能性はあります。

ただし、

データ不足を理由にその場でWeightを変更する

ことと、

検証結果に基づいて新Methodologyを正式採用する

ことを分けています。


今回できるようになったこと

ここまでの開発によってGPIでは、

Historical Observations
        ↓
Publication Vintage Reconstruction
        ↓
Historical Checkpoints
        ↓
First Revision Replay
        +
Recorded Vintage Replay
        ↓
Coverage / Freshness
        ↓
Component Scoring
        ↓
Composite Replay
        ↓
Market Regime Analysis
        ↓
Weight Validation
        ↓
Human Review
        ↓
Methodology Decision

という検証経路を持つようになりました。

単に、

今日のデータ
↓
今日のGPI

を計算するだけのシステムではなくなってきています。


次のVol.16では「数字を出さないPublic API」を紹介

ここまでで、

  • データ取得
  • Validation
  • Component Scoring
  • Composite Engine
  • Historical Replay
  • Weight Validation
  • Governance

まで進みました。

次に必要なのは、

これを利用者へどう見せるか

です。

実際のGadgetStreem Intelligenceでは現在すでに、

GPI Public Status Preview

まで開発が進んでいます。

ただし、現在Public APIへ出しているのは、

Production Coverage:85%

USD/JPY:INCLUDED
DRAM:INCLUDED
NAND:INCLUDED
GPU:HISTORY_ACCUMULATION
Freight:INCLUDED

Composite GPI:
WITHHELD

というStatusのみです。

Component Score、Weighted Contribution、Raw ObservationなどはPublic Payloadから明示的に除外しています。

次回のVol.16では、

「まだGPI数値を公開できないのに、なぜPublic APIとDashboardを先に作ったのか?」

を取り上げます。

  • Status-only API
  • Public Preview UI
  • Production Coverage表示
  • Numeric Leakage防止
  • APIとWordPressの役割分担
  • なぜPostgreSQLへWordPressを直接接続しないのか
  • WITHHELDをどうUIで伝えるのか

という、GPIを実際のWebサービスへする部分へ進みます。


まとめ

Vol.14では、

30%
25%
20%
15%
10%

という固定Weightで5つのComponent Scoreを統合するComposite Engineを紹介しました。

今回のVol.15では、

そのWeightやMethodology自体をどう検証するのか

をご紹介しました。

GPIでは、

  • First Revision Replay
  • Recorded Vintage Replay
  • Future-information Leakage防止
  • Freshness
  • Coverage
  • Market Regime Backtest
  • Weight Concentration
  • Effective Component Count
  • Dominant Pressure Share

などを使い、

Methodologyそのものを検証します。

実際のWeight Validationでは、

現在の固定Weightを用いるテストシナリオはreview_candidateとなった一方、

ドル円へ70%を集中させたCandidateは、

reject_unstable

となりました。

ただし、

30/25/20/15/10が最適だと証明された

わけではありません。

正式なWeight ValidationではHistorical Evidence不足により、

insufficient_evidence

という判断も記録しています。

そのため、

Automatic Weight Change:
false

です。

これが現在もWeightを固定している理由です。

GPIでは、

過去によく合う数字を探して採用する

のではなく、

現在のMethodologyを壊すだけの十分な証拠があるのかを確認する

という考え方を採っています。

Backtestの目的は、未来を当てた気になることではありません。

GPI自身が、どこで壊れるのかを先に探すことです。

現在もProduction Coverageは85%。

GPUは23/36。

Composite Numeric GPIはWITHHELDです。

まだ公開する数字はありません。

しかし、数字を公開する前に、

その数字を作るルールまで検証できるシステム

には着実に近づいています。

次回は、現在実際に稼働しているGPI Public Status Previewと、Public APIの設計へ進みます。


※GPIは現在開発中の実験的な市場分析指標です。Historical Backtestの結果は将来のガジェット価格を保証・予測するものではありません。また、本記事で扱ったWeight Validationの結果は、現在の30/25/20/15/10というWeightが統計的に最適であることを証明するものではありません。現在のPublic Numeric GPIは未公開であり、個別製品の購入・投資判断を目的とするものでもありません。


この記事が気に入ったら
フォローしてね!

コメント

コメントする

目次