こんにちは、ぼっちbotterよだかです。
前回は、利回り付きステーブルコイン周辺の仮説を監査し、主線から外すもの・背景観測に落とすもの・未確定枝として保留するものを整理しました。今回はその続きとして、残した枝を本当に観測できる形に落とし込むため、Ethena を本命に絞った最小観測機を実装し、1時間ごとの定期実行まで通しました。まだエッジの白黒を再判定できる段階ではありませんが、少なくとも「live で見続けて検証できる状態」には一歩進めたので、その内容をまとめます。
-
-
🛠️開発記録#516(2026/4/16)DeFi研究ログ ― 利回り付きステーブルコイン周辺の仮説を監査し、残す枝と切る線を分けた話
続きを見る
1. 前回どこまで白黒をつけて、今回はそこから何を進めたのか
前回までの自分は、利回り付きステーブルコイン周辺をかなり広い主語で見ていました。Ethena 系の需要変化、Pendle における将来利回りの織り込み、Sky 系の基準レートとの差分。こうしたものをまとめて観測すれば、Hyperliquid 側の funding や volume、ひいては perp 市場の地合いに何らかの先行性を持つのではないか、という見立てです。これは単に「利回りが高い商品を探す」という話ではなく、利回り付きステーブルコインを資本需要のセンサーとして使えないかを見る試みでした。前提に置いていた問いもかなり明確で、「どこで資本コストが発生し、その変化がどの順番で他市場へ波及するのかを、観測可能な形にできるかどうか」でした。Ethena は funding や basis にかなり近い場所を触っている。Pendle は将来利回りや需要の期待を価格へ比較的露骨に落とす。Sky は勝ち筋そのものというより、他を測るための比較軸になりうる。そう考えていたので、当時の自分にとってこのテーマは、それなりに筋が良く見えていました。
ただし、前回の時点で、私はその期待をかなり強く削るところまでは進めています。H1 を「Ethena 系の需要変化は perp activity に先行するか」、H2 を「Pendle の spread / implied は Hyperliquid 指標に先行するか」、H3 を「Sky-Ethena APY spread は Pendle implied APY を見るための比較軸になるか」と定義し、さらに価格影響まで切り出したうえで、raw 相関、差分、detrended、前半後半 split、rolling corr、TVL 集約の偏り、正ラグ優位の有無までかなり機械的に通しました。その結果、最終的には「利回り付きステーブルコイン全体 → HL perp」という太い主語は切り、Pendle spread と Hyperliquid funding の関係は背景観測に格下げし、sUSDe 個別市場の枝だけを未確定保留に置き、価格影響仮説も主線から外すところまで落としています。つまり前回の収穫は、何かを見つけたことではなく、主線から降ろすもの、背景観測に落とすもの、保留箱に入れるものをはっきり分けたことでした。ここは今回の出発点としてかなり重要です。今回の研究は、真っ白な状態から始まっているのではなく、「何を mainline に置かないか」をすでにかなり厳しく決めた状態から始まっています。
そのうえで今回進んだのは、研究の結論そのものというより、研究を live で観測し続けられる形に落とし込んだことです。ここは自分でも意識して区別しておきたいところです。前回までにやったのは、仮説の監査と地位整理でした。今回はそこからさらに一歩進めて、Ethena と Hyperliquid を対象に、ローカル Mac 上で動く最小観測機を作りました。Ethena の公開 API から USDe supply、yield / staking、collateral snapshot を取得し、Hyperliquid から BTC / ETH の funding、open interest、rolling 24h volume を取る。生データは JSON と gzip で残し、SQLite には append-only で保存し、正規化した metrics と最小特徴量、さらに event study の結果まで更新する。しかもこの構成は、Docker も Postgres も Grafana も入れず、Ethena + Hyperliquid に絞った最小構成です。ここでやりたかったのは「すごい機械」を作ることではなく、自分で中身を追えて、あとから raw に戻って再検証できる研究機を小さく立ち上げることでした。 README にまで、取得対象、保存形式、時刻解釈、まだ取っていないもの、日次運用、正常 / 異常判定を書いたのは、そのためです。つまり今回は、研究テーマを前に進めるための実装であると同時に、自分の理解を壊さないための実装でもありました。
この「小さく作る」という判断にも、かなり明確な理由がありました。もともとの候補は Ethena、Sky、Pendle、Maple、OpenEden などかなり広く、利回り付き安定資産の family を全部並べて見ること自体はできました。ただ、それを最初から全部 live 実装しようとすると、実装負荷だけでなく、自分の思考リソースまで散るのはほぼ確実でした。しかも前回までの監査で、全体先行優位仮説はすでに切っている。そうであれば、次にやるべきことは「全部を薄く見る」ことではなく、「いま残している枝のうち、perp との因果距離が最も短く、観測可能性も比較的高いものを本命として絞る」ことです。その条件で見たとき、Ethena を先に掘るのは自然でした。実際、候補ユニバース整理の段階でも、Ethena は利回り源泉が funding / basis に直結していて 6H〜72H の仮説と整合し、供給量、ステーキング、DeFi 利用、CEX funding / OI を比較的取りやすく、RWA 系より反応速度も短期寄りだと考えていました。逆に Sky は比較軸としては重要だが短期先行性そのものの本命ではなく、Pendle は期待形成を映す場として魅力はあるが、前回の時点で background observation に格下げしている。だから今回は、研究として Pendle / Sky を永久に捨てたのではなく、live 実装の初手では Ethena + Hyperliquid に絞り込んだ、というのが正確な表現になります。
さらに今回、Ethena を採る理由は、単なる「雰囲気」ではなく、一度大きめの実測でも支えられています。4/17 に行った検証では、day1 収集と 180 日バックフィルを再実行し、Ethena 公式 API と Hyperliquid 1h を結合して 6H / 24H / 72H の再計算までやっています。その結果、Ethena フローは価格方向の直接予測よりも、perp の参加度や混雑度、つまり volume や funding regime の検知に使う方が妥当という読みが強まりました。強かったのは方向ではなく絶対フローで、特に |ΔUSDe(24h)| と forward volume は一貫して正、redeem 側ショック後の funding 上昇にも有意な偏りが見えています。一方で価格リターンは弱く、APY 系列は高頻度説明変数としてはあまり強くありませんでした。この結果は、前回の「全体先行優位は切るが、Ethena 系には観測価値が残る」という整理とかなり整合しています。今回 live 実装の本命を Ethena にしたのは、単に作りやすかったからではなく、少なくとも一度は「ここなら観測を続ける意味がある」と言えるだけの材料があったからです。
とはいえ、ここで勘違いしたくないのは、今回の進展はまだ「エッジが確認できた」ことではないという点です。ここはかなり大事です。いまの観測機には、build_features と event_study まで入っていますが、現時点の状態は README にも記した通り、sample_insufficient_present=True と still_data_hungry=True が正常です。shock decile がまだ成立しておらず、6H / 24H / 72H の forward 比較に使えるだけの event も不足している。だから今は、研究的にはまだ未達です。進んだのは、仮説が強まったことではなく、仮説を live で観測し、欠損なく母数を育て、あとから自分で検証できる状態にしたことです。この区別はかなり重要で、ここを雑に書くと「観測機が動き始めたこと」と「エッジが再確認されたこと」を混同してしまいます。今の自分が得たのは、勝ち筋ではなく、勝ち筋かどうかを後で白黒判定できるための土台です。しかも、その土台は 1 時間ごとの run_all.py と、1 日 1 回の check_status.py、さらに launchd まで通して運用に乗せています。観測を 3 日間放置ではなく、軽い定期実行 + 人間の日次確認で回す方がよいと判断したのも、今の課題が機能不足ではなく、母数不足だからです。
ここまでを自分向けに整理すると、今回の到達点はかなり明確です。前回は、「利回り付きステーブルコイン周辺の flow が HL perp に先行する」という広い仮説を監査し、かなりの部分を主線から外しました。今回は、そのうえで「では何も残らないのか」で止まらず、残した枝のうち最も本命に近い Ethena を live で追える最小研究機へ落とし込み、定期実行まで通しました。つまり、仮説の地位整理から、観測機の運用開始へ進んだわけです。ただし、研究の問いそのものはまだ終わっていません。いまはまだ母数育成中であり、結論は先送りです。だからこの章で置いておきたいのは、「前回より大きく進んだか」と聞かれたら答えは yes だが、その進展の中身はエッジの発見ではなく、研究を live で回せる状態にしたことだ、という一点です。これを取り違えないことが、今回の記事全体でもかなり大事になると思っています。
2. 今回あらためて固定した研究の主線
今回、実装に入る前に自分の中であらためて固定したかったのは、「今この研究で何を mainline として追うのか」です。ここが曖昧なまま実装に入ると、観測対象も増え、スクリプトも増え、見たい指標も増え、最終的には「何のために動かしている機械なのか」が分からなくなります。特に今回は、すでに前回までの監査でかなり多くの枝を切っています。全体先行優位仮説は切り、Pendle spread と Hyperliquid funding の関係は背景観測へ格下げし、sUSDe 個別市場の枝だけを未確定として保留し、価格影響仮説も主線から外した。つまり、「利回り付きステーブルコイン周辺なら何かあるだろう」という広い期待を、そのまま残してよい段階ではありませんでした。今回の主線固定は、その前提の上で、「では何を live で見続ける価値があるのか」をもう一度決め直す作業でした。
そのときに自分の中でかなりはっきりしていたのは、今回のテーマを「利回り付きステーブルコインを投資対象として選ぶ研究」にしたくない、ということでした。これは前回の記事でもかなり強く意識していた点です。自分が見たいのは、どの銘柄が伸びるか、どの APY が魅力的か、という話ではありません。そうではなく、利回り付き安定資産を 資本需要・担保需要・市場の混雑度を映すセンサー として見たときに、どの系列が、どの順番で、どの市場へ波及するのかを観測可能な形にしたい、というのが本筋でした。前回の時点でも、このテーマは「利回りが高い商品を探す」話ではなく、「どこで資本コストが発生し、その変化がどの順番で他市場へ波及するのか」を見に行くものだと整理しています。今回その本筋を維持するためには、まず実装を「儲かりそうな商品を並べる機械」ではなく、「センサー候補を継続観測する機械」として作る必要がありました。
その観点で候補を見直したとき、最初から全部を同じ深さで追うのは違う、という判断はかなり明確でした。候補ユニバースとしては、sUSDS、sUSDe、syrupUSDC / syrupUSDT、USDY / rUSDY、BFUSD、sUSDD、sDAI、USDO / cUSDO、stUSDT / wstUSDT、sfrxUSD などを並べていましたし、実際に各銘柄について、どこから資金が入り、どこへ流れ、利回りがどこから来るかを調べています。その整理を通して見えてきたのは、利回り源泉が大きく RWA 金利、funding / basis、機関向け貸付 の三系統に分かれること、そして「どれも同じ利回り付き安定資産」に見えても、perp との距離や観測しやすさはかなり違う、ということでした。ここを一度整理したことで、主線を「全部」ではなく「family 単位で絞る」方が自然になりました。
そのうえで、まず何を残し、何を薄くし、何を切るか、というかなり実務的な整理もしました。ここは後から見返したときに分かりやすいよう、簡単に表にしておきます。
| 区分 | 今回の扱い | 理由 |
|---|---|---|
| 本命 | Ethena | perp との因果距離が最短、観測データが多い、短期の regime 変化に接続しやすい |
| 次候補 | Sky / Maple / OpenEden | 比較軸・信用需要・RWA需要の文脈として有用。ただし初手の live 実装には広すぎる |
| 影監視候補 | Ondo / Frax | 比較対象としては面白いが、今の段階で深掘りすると実装と解釈が散りやすい |
| いったん切る | BFUSD / sUSDD / stUSDT / sDAI / USDM | 透明性・観測性・冗長性・wind-down などの理由で初手の主戦場にしない |
この整理のポイントは、「何が良い商品か」ではなく、「何がいまの研究の主戦場にふさわしいか」で見ていることです。たとえば BFUSD は規模が大きくても、CeFi 内部資産でオフチェーン比率が高く、オンチェーン観測前提の研究対象としては弱い。sDAI は悪いわけではなく、sUSDS と比較すると冗長で、最初の比較軸としては sUSDS で十分です。USDM はすでに wind-down 寄りなので forward research の主対象からは外れる。つまり、今回の「切る」は、その商品に価値がないと言いたいのではなく、今の自分が白黒をつけたい問いに対して、投入コストに見合わない という意味です。このあたりは、前回の記事でかなり強く意識していた「何でもかんでも残して延命しない」という態度の延長線上にあります。
その中で、Ethena を本命として固定した理由は、今回かなりはっきり言語化できるようになりました。以前もざっくりと「Ethena から始めるのがよさそう」と思ってはいましたが、今回はそれをもう少し具体的に切っています。第一に、Ethena の利回り源泉は funding / basis に直結していて、今回の「6H〜72H で perp 側の funding や volume に何か先行するか」という問いに最も近い場所を触っています。第二に、USDe supply、staking / protocol yield、collateral snapshot、さらには Hyperliquid の funding / OI / volume と組み合わせた検証がしやすく、観測可能性が高い。第三に、RWA 系より反応速度が短期寄りで、前回の大きめの再検証でも「価格方向の直接予測より、perp 参加度や混雑度の regime 検知に効きやすい」という結果が出ていた。つまり Ethena は、「雰囲気的に良さそう」だからではなく、研究目的とデータ取得性と実測結果の三つが、いまの段階で最もきれいに揃っていた family でした。
逆に、Pendle / Sky 軸をいったん live 実装から外した理由も、ここでかなり明確にしておきたいです。これは「研究対象から捨てた」わけではありません。むしろ前回の記事では、Pendle spread と Hyperliquid funding の関係は lead としては弱いが background observation としては残し、Sky 系は比較軸として置いていました。つまり研究上の地位としては、いずれもゼロではありません。今回 live 実装から外したのは、あくまで 最小構成で Ethena + Hyperliquid を先に成立させるため です。自分の感覚としても、ここで Pendle と Sky まで一気に実装へ入れると、見たいものが増えすぎて思考リソースが壊れる、という危機感がありました。実際、README でもこのプロジェクトは “Ethena + Hyperliquid 最小観測機” と明示していて、複数 family への一般化や過度な抽象化を非スコープにしています。だから、ここでの縮退は 研究放棄 ではなく 実装スコープの限定 です。将来、Ethena 単体の live 観測だけでは解釈が曖昧なときには Sky を対照群として戻し、funding 背景軸の説明補助が必要なら Pendle を背景軸として戻す。その条件付きで一旦外している、というのがいちばん正確です。
この判断に関して、自分の中では「研究の本筋からずれていないか」という不安も少しありました。前回の記事では、Pendle implied や Sky-Ethena APY spread のような比較軸も、研究の中ではそれなりに重要な位置にありました。なので、今 live 実装が Ethena + Hyperliquid に細っているように見えるのは事実です。ただ、ここで自分が確認しておきたいのは、「主語が細くなったこと」と「本筋が変わったこと」は別だということです。今回も、目的は依然として 資本需要や担保需要、perp activity のセンサーを live で見続けること にあります。Ethena を本命に絞ったのは、その問いをより短い距離で白黒つけるためであって、商品人気を見る研究に移ったわけではありません。むしろ、広い主語で入って false positive に苦しんだ前回の経験を踏まえるなら、主語を絞るのはかなり健全な方向転換です。ぶれているのは本筋ではなく、実装スコープの大きさの方でした。そこを今回は意識的に小さく戻しました。
主線を Ethena に固定したあと、もう一つ決めたかったのは、「今回は何をゴールにしないのか」です。ここがないと、観測機が動き始めた瞬間に、また勝ち筋探しの熱が前に出てしまうからです。今回のゴールは、まだシグナル売買でも、執行レイヤー接続でも、ML 導入でもありません。README にも、今回あえてやっていないこととして、機械学習モデル、自動売買、本格監視ダッシュボード、ハイパーパラメータ最適化などを明示しています。つまり今は、「何かすごいものを作る」のではなく、Ethena の live 観測を 1 時間ごとに欠損なく回し、sample_insufficient が解消するところまで母数を育てることが主目的です。この線を引いておくと、今やっている作業が「勝てる機械の実装」ではなく「研究をちゃんと白黒つけるための運用土台づくり」だと自分に言い聞かせやすくなります。ここは、前回の記事の最後で自分がかなり警戒していた「分析を増やして安心しようとしているだけではないか」という違和感への、実装上の答えでもありました。
その結果として、今回の主線はかなりシンプルになりました。
Ethena を本命 family とし、Hyperliquid を被説明側の最小文脈として置き、まずは live でデータを溜め続ける。
これが今の研究の mainline です。Sky / Pendle / Maple / OpenEden は、「意味がないから捨てた」のではなく、「いまの主線を濁らせないために、まだ live 実装へは入れない」。そしてその判断の基準は、商品そのものへの好悪ではなく、perp との因果距離、観測可能性、前回までの監査結果、そして自分の思考リソースを壊さないこと。この4つでした。ここまで固定できたことで、今回ようやく「なぜ今この構成で実装しているのか」をかなり自分で説明できるようになったと思います。次章では、その主線を前提に、実際に何をどこまで実装したのか、そしてなぜそこまでに留めたのかを書いていきます。
3. なぜ Pendle / Sky 軸はいったん live 実装から外したのか
今回、自分の中でかなり重要だった判断の一つが、Pendle / Sky 軸を研究テーマそのものから捨てるのではなく、いったん live 実装のスコープから外すと決めたことでした。ここは後で読み返したときに誤解しやすいので、かなり丁寧に整理しておきたいです。結論から言えば、この判断は「Pendle や Sky に意味がない」と見なしたからではありません。そうではなく、前回までの監査でそれぞれの地位がすでに mainline から下がっていたこと、そして今の自分にとっては “まず Ethena + Hyperliquid の最小 live 観測機を成立させること” の方が優先順位が高かったからです。つまり、これは研究上の全面否定ではなく、実装と運用の初手をどこまで細くするか、という判断でした。
まず前提として確認しておきたいのは、4/16 時点で自分が Pendle / Sky をどう位置づけていたかです。あの記事の段階で、Pendle spread / implied を使った H2、Sky-Ethena APY spread を比較軸とする H3 は、かなり厳しく監査されています。そこで見えていたのは、Pendle spread と Hyperliquid funding の間には raw ではそれっぽい関係が見える場面があるものの、正ラグ優位がきれいに成立するわけではなく、負ラグ側が強い箇所もあること、そして volume 側は符号も安定性も弱いことでした。Sky-Ethena spread についても、raw lag7 ではそこそこの相関が見えたものの、diff や detrended に落とすとかなり弱まり、split すると後半ではほぼ崩れ、実質的には低分散な Sky 系列を含んだ見かけの相関に近かった。つまり、4/16 の時点で Pendle / Sky は、少なくとも「強い先行優位の mainline」としてはかなり下がっていたわけです。Pendle 側は funding 背景軸としてだけ残し、Sky は比較軸としての価値を再点検すべき対象になっていました。今回それらを live 実装の最初の対象から外したのは、この地位整理とかなり整合しています。主線から降ろしたものを、いきなり実装の mainline に戻す理由はありませんでした。
そのうえで、今回の live 実装の目的もかなり限定的でした。README に書いた通り、このプロジェクトは “Ethena + Hyperliquid 最小観測機” として設計していて、スコープもかなり強く絞っています。実装済みなのは、Ethena の公開データ取得、Hyperliquid の公開データ取得、生データ保存、SQLite append-only 保存、最小 notebook、最小特徴量、event study、status 確認、そして launchd による毎時運用です。一方で、複数 family への一般化、過度な抽象化、大きな監視基盤、売買ロジックなどは明確に非スコープに置いています。ここで重要だったのは、「何でも入れられるなら入れる」ではなく、**“最小構成で自分が理解できるものだけを残す”**ことでした。そう考えると、Pendle / Sky を初手から同居させるのは、データ系列、時刻解釈、比較窓、監視すべき変数、そして何より自分の認知負荷を一気に増やす方向です。前回までの研究で false positive にかなり苦しんでいた以上、ここで live 実装の側まで広くすると、また「何かありそう」を支える作業に戻ってしまう危険がありました。
実際、自分の感覚としてもかなり明確だったのは、色々追いすぎると自分の思考リソースが壊れるという危機感でした。これは単なる気分の話ではなく、研究の質に直結する実務的な問題です。利回り付き安定資産は、一見すると全部「ドル近傍で利回りが乗るもの」に見えますが、実際には利回り源泉も、データの取りやすさも、perp との距離もかなり違います。Ethena は funding / basis にかなり近く、供給量、staking / yield、collateral snapshot、そして Hyperliquid の funding / OI / volume と接続しやすい。一方で Pendle は implied / underlying / spread の定義や市場寿命差があり、Sky は比較軸としての意味はあっても、短期先行性の本命ではない。これらを全部同時に追い始めると、「どの系列が mainline で、どれが背景観測で、どれが比較軸なのか」がまた曖昧になります。前回の記事でも、自分は主語を広く取りすぎると見たいものが多くなりすぎて、どこで何が効いているのかがぼやけると反省していました。だから今回は、研究上の期待値だけでなく、自分の処理能力を壊さずに白黒をつけられるかも明確に判断基準へ入れています。これは甘えではなく、むしろ false positive を減らすための制約として必要でした。
では、なぜその中で Ethena を残し、Pendle / Sky をいったん外したのか。ここもかなり具体的に整理できます。Ethena を本命にした理由は、前章で書いた通り、perp との因果距離が最短で、観測可能性も高く、しかも一度大きめの再検証で「価格方向の直接予測より participation / funding regime の検知に効きやすい」という結果が出ていたからです。そこに対して Pendle / Sky はどうかというと、前回の時点で、Pendle は funding 背景軸としては残るが主線ではなく、Sky は比較軸としては有用でも、短期先行性そのものの本命ではない、という地位まで下がっていました。つまり、Ethena は “残した枝の中で最も live 実装の優先度が高いもの” であり、Pendle / Sky は “研究としてはまだ残るが、実装の第一手ではないもの” だったわけです。この順番はかなり自然で、むしろ逆に Pendle / Sky から実装に入る方が理由を説明しづらかったと思います。
ここで、自分向けに一度表にしておきます。今後また「なんで入れていないんだっけ?」となった時のための整理です。
| 軸 | 研究上の地位 | 今回の live 実装での扱い | 外した / 残した理由 |
|---|---|---|---|
| Ethena | 本命候補 | 実装した | perp に最も近く、観測可能性が高く、前回の実測でも regime 検知価値が残った |
| Pendle | 背景観測 | 未実装 | 先行優位の mainline ではなく、background observation に格下げ済み。今は複雑性の方が勝つ |
| Sky | 比較軸 | 未実装 | 比較軸としての意味はあるが、初手の live 実装で同時に入れると解釈と運用が散る |
| Maple / OpenEden | 次候補 | 未実装 | 比較対象としては強いが、まず Ethena 単体の live 観測を成立させる方が先 |
| Ondo / Frax | 影監視候補 | 未実装 | いまの段階では情報密度より負荷の方が大きい |
この表で大事なのは、Pendle / Sky に「不要」「否定済み」とは書いていないことです。
研究としての地位はゼロではなく、あくまで “今の live 実装の主戦場には置いていない” という整理です。
では、この前提が崩れる条件は何か。つまり、今はいったん外している Pendle / Sky を、どうなったら戻すのか。ここも今回、かなり重要な論点でした。
一つ目の条件は、Ethena 単体の live 観測だけでは解釈が曖昧になったときです。たとえば Ethena 側の供給変化や yield / collateral 変化と Hyperliquid 側の funding / OI / volume に何か動きが見え始めたとしても、それが Ethena 固有の現象なのか、単なる stable parking 全般の動きなのかが分からない場合、Sky を対照群として戻す意味が立ちます。Sky はもともと比較軸としての地位を持っていたので、Ethena live 観測を解釈するための control として追加するのはかなり自然です。逆に言えば、Ethena 側にまだ何も見えていない段階で Sky まで入れると、情報量だけ増えて解釈の重心が定まらない可能性が高い。だから今はまだ戻していません。
二つ目の条件は、background observation としての補助説明が必要になったときです。Pendle は前回の時点で mainline ではなく背景観測に格下げしていましたが、それでも「利回り期待の織り込み」を比較的露骨に映す場であること自体は変わっていません。もし Ethena live 観測を続ける中で、funding regime や activity の変化が見え始め、それをもう一段説明したい、あるいは「これは期待形成のズレまで含む現象なのか」を確認したくなった場合、Pendle を背景軸として戻す意味はあります。逆に、Ethena 単体ですらまだ何も見えていない段階では、Pendle を足すのはただ複雑さを増やすだけです。ここでも順序は重要で、Ethena で何かが見えてから Pendle を補助線として戻すのが自然です。
三つ目の条件は、live 運用フェーズを一段抜けたときです。いま README でも sample_insufficient_present=True と still_data_hungry=True は正常であり、まずは母数育成中と明示しています。つまり、今は研究の白黒をつける以前に、観測点を欠損なく増やす段階です。この段階で比較軸を増やしても、判定しきれない系列が増えるだけです。逆に、usde_supply や funding_rate などが 30 点以上たまり、shock decile や forward event が成立し、Ethena 単体の live 観測でようやく何かを読みに行ける段階になったときには、「背景軸を戻して比較した方がいいか」は再評価に値します。だから、Pendle / Sky は「いつか入れるかもしれない」曖昧な候補ではなく、Ethena 単体観測の母数と解釈が一定水準に達したら再判定するものとして理解した方が、自分の中でもかなり整理しやすいです。
ここまで書いておくと、自分の判断の中身はかなりはっきりします。
今回、Pendle / Sky をいったん live 実装から外したのは、研究テーマを捨てたからではありません。前回までの監査でそれぞれの地位が mainline から下がっていたこと、そのうえで Ethena の方が因果距離・観測可能性・実測結果の面で優先度が高かったこと、そして何より、今の自分には “一度に追う軸が多すぎると判断の質が落ちる” というかなり現実的な制約があったからです。この判断は、研究の本筋を細くしたのであって、曲げたわけではありません。むしろ、前回の「主語を広げすぎると false positive を生む」という反省に対して、ちゃんと実装レベルで答えを出したとも言えます。次章では、その細くした主線を前提に、実際にどんな観測機をどこまで作ったのか、そしてどこで止めたのかを、実装の話として整理していきます。
4. 今回実装したもの ― Ethena + Hyperliquid 最小観測機
今回の実装で自分がいちばん大事にしたのは、「ちゃんと動くものを作る」ことよりも先に、自分で理解できるものだけを作ることでした。これは言葉で言うと簡単ですが、実際にはかなり意識してブレーキを踏まないと崩れます。特に今回は、最初の構想をそのまま広げれば、Ubuntu、Docker、Postgres、Grafana、複数サービス分離、専用サーバといった方向へいくらでも進められました。けれど、自分は途中ではっきり「それは今のフェーズには重すぎる」「このままだと理解できない機械ができる」と感じて止めています。これはかなり良い判断だったと思います。今回の研究で本当に必要だったのは、立派な基盤ではなく、Ethena と Hyperliquid の最小観測機を Mac mini 上で理解可能な形で回し始めることでした。だから最終的な構成も、macOS のまま、Python 仮想環境、SQLite、CSV / JSON、Jupyter Notebook というかなり軽い形に落としました。ここで捨てたのは「本格性」ではなく、今の自分にとっての過剰です。
この「軽くする」判断は、単なる楽をしたい気持ちではありませんでした。前回までの研究でかなり強く意識したのは、見かけの相関や“何かありそう”を延命しないことです。そうであれば、実装側でも同じ態度を取る必要があります。つまり、「将来必要になるかもしれないから今のうちに作る」はやらない。実際、Codex に渡した実装書でも、絶対にやってはいけないこととして Docker、Postgres、Redis、MinIO、Airflow、Prefect、Grafana、Web アプリ化、自動売買、複数 family への一般化、複雑な plugin 機構、非同期処理などをかなり明示的に禁止しています。ここは自分でもかなり良かったと思っていて、単に「最小構成で」と言うより、“何を作らないか” を先に決めたのが効きました。結果として、完成したものは本当に薄い観測機になっていて、理解不能な framework 化には進みませんでした。
最初に作ったリポジトリは、かなりシンプルです。yield-observer/ 配下に README、requirements、config、data、scripts、notebooks、SQLite の observer.db があり、scripts には collect_ethena.py、collect_hyperliquid.py、normalize_data.py、run_all.py、shared.py が置かれました。この段階での目的ははっきりしていて、Ethena の公開 API から USDe supply、yield / staking、collateral snapshot を取り、Hyperliquid から BTC / ETH の funding、open interest、rolling 24h volume、mark price を取る。その raw JSON を data/raw/ に保存し、SQLite に append-only で蓄積し、Notebook で最低限の時系列を可視化する、というところまでです。ここではまだ「賢い特徴量」や「シグナル売買」は目的ではなく、本当に欲しいデータが定期的に取れ、あとから raw に戻って見返せるか を確認することが中心でした。
実装の中身を見ても、この方針はかなり守れています。shared.py は、時刻文字列の生成、JSON / CSV の gzip 圧縮、SQLite テーブル初期化、HTTP JSON 取得、数値変換といった本当に共通の雑務だけに留められていて、collector framework 化していません。これは自分が途中でいちばん気にしていた部分でもありました。共通化は簡単に「小さな framework」へ膨らむからです。けれど今回の shared.py はまだ薄く、将来の一般化を先回りしていません。ここは Phase 1 のレビューでも、「太りすぎていない」「本当にユーティリティ層に収まっている」と確認できました。この安心感は大きいです。早い段階で shared 層が抽象化しすぎると、後から何をしているのか分からなくなるので、今回はかなり良い止め方ができています。
collect_ethena.py と collect_hyperliquid.py も、かなり素直です。Ethena 側は https://app.ethena.fi/api/solvency/usde-supply、/api/yields/protocol-and-staking-yield、/api/positions/current/collateral の3 endpoint を叩き、そのときの observed_at と endpoint 情報をまとめた raw JSON を timestamp 付きで保存してから、SQLite の raw_observations に 3 行追加します。Hyperliquid 側は POST https://api.hyperliquid.xyz/info に {"type":"metaAndAssetCtxs"} を送り、BTC / ETH だけを選び出して、同じく raw JSON 保存 → DB 追加を行います。この構造の良いところは、「その時点で何をどこから取ったか」がかなりそのまま残ることです。あとで何かがおかしいと思った時に、normalized metrics や feature だけを見るのではなく、元の payload まで戻って確認できる。今回、自分が「生データから再検証できること」をかなり重視していたのは、前回までの false positive 監査の流れと繋がっています。見かけの相関に騙されないためには、変換後の表だけでなく元データへ戻れることが重要だからです。
その raw を整形する normalize_data.py も、今の段階ではちょうどいい薄さです。Ethena 側では usde_supply、staking_yield_apy、protocol_yield_apy、avg30d_*、avg90d_*、collateral_total_backing_usd、collateral_sum_usd、collateral_entry_count を抜き、Hyperliquid 側では funding_rate、open_interest_contracts、open_interest_usd、volume_24h_usd、mark_px を平坦化しています。ここでもポイントは、「取れるものを全部取っている」わけではなく、いまの主線に説明可能なものだけ を並べていることです。さらに、Phase 2 ではこの normalize に metric_timestamp の扱いまで足しています。usde_supply は payload 内 timestamp を優先し、Hyperliquid snapshot 系は observed_at ベース、その他は payload 時刻がなければ observed_at を使う、というルールです。これはかなり重要で、時刻解釈を曖昧にしたまま lag 検証に進むと、簡単に見かけの lead / lag を作ってしまうからです。今回そこを一歩だけでも前に進められたのは、かなり大きいです。
ただ、ここで一つ大事だったのは、実装したからといって、すぐに高度化しなかったことです。Phase 1 が通った時点で、Codex 側からは「次フェーズに進んでよい」という自己判定が出ていました。けれど、そのまま雑に特徴量を増やすのではなく、Phase 2 でもかなり意識的にブレーキをかけています。特徴量は 10〜12 個程度に制限し、機械学習モデル、XGBoost、LSTM、Transformer、最適化、Web ダッシュボード化、自動売買は全部禁止したままにしました。最終的に作った特徴量も、usde_supply_level、usde_supply_diff_1obs、usde_supply_diff_6obs、usde_supply_diff_24obs、usde_supply_zscore_24obs、staking_yield_apy_level、collateral_total_backing_usd_level、collateral_gap_usd、funding_rate_level、funding_rate_diff_1obs、open_interest_usd_level、volume_24h_usd_change_6obs に抑えています。ここで効いたのは、「意味が説明できるものだけ」というルールです。逆に言えば、複雑なモデルや大量特徴量は、今の段階ではまだ “研究している感” を生みやすいだけでした。前回の記事で自分がかなり警戒していた「作業で安心しようとしていないか」という違和感に対して、実装でもちゃんと回答できたのがこの部分だと思います。
event study の設計も、かなり意識的に最小にしました。ここでやりたかったのは、立派な学術推定ではなく、Ethena 側に shock があったときに、その後の Hyperliquid 指標がどう動いたかを人間が読める形で確認することです。だから、shock 定義も usde_supply_zscore_24obs の上位 10% / 下位 10% を基本にし、z-score が足りない場合は usde_supply_diff_1obs の decile にフォールバックする、というかなり単純なものにしています。対象指標も funding_rate、open_interest_usd、volume_24h_usd、mark_px に絞り、出力も shock_events_latest.csv と event_study_results_latest.csv だけです。この設計の良かったところは、サンプルが足りない時にちゃんと sample_insufficient と出して止まるところでした。実際、最初の段階では usde_supply が 3 点、funding_rate 系が 6 点程度しかなく、shock decile は成立せず、event study も sample_insufficient 行だけを出力しています。ここで無理に「何か見えた」と言わなかったのはかなり大事で、研究態度としても実装姿勢としても、一貫して false positive を避ける方向に動けています。
今回、自分にとって特に大きかったのは、実装を作って終わりにしなかったことです。Phase 2.5 では新しい研究機能を増やすのではなく、既存の観測機を数日〜数週間安定して回せるようにするための運用整備に絞りました。ここでも、launchd や check_status.py の位置づけをかなり強く限定しています。run_all.py は collect_ethena → collect_hyperliquid → normalize_data → build_features → event_study を一括直列実行し、各ステップの START / OK / FAIL を標準出力に出して、最後に件数と sample_insufficient の有無をまとめます。check_status.py は DB 件数、最新時刻、source 別最新 observed_at、metric 別件数、latest CSV の存在、sample_insufficient_present、shock_decile_ready、forward_event_ready、still_data_hungry を CLI に出して、notebook を開かなくても今の運用状態が分かるようにしています。ここでやりたかったのは、「研究機を前進させること」ではなく、「観測を育てること」を日々判断可能にすることでした。README にも、何が正常で何が異常か、sample_insufficient=True は現段階では正常であること、3日後までに何を見るか、launchd の開始・停止・確認コマンドまで書き足しています。この “意味づけまで README に残す” ところまでやったのは、自分の将来の混乱を減らす意味でもかなり効いています。
その後、launchd による毎時実行まで実際に通したのも大きかったです。正直ここは、最初は「変にいじってバックグラウンドで走りっぱなしになったら嫌だ」という不安がありました。けれど今回の設定は常駐ループではなく、1 時間ごとに単発で run_all.py を起動して終わる方式です。実際、launchctl print の結果では run interval = 3600 seconds、last exit code = 0、state = not running となっていて、これは「今その瞬間は待機中で、直近実行は成功した」という正常状態でした。ログでも、06:04 に run_all が起動し、raw_observations が 30 → 35 に増え、normalize → build_features → event_study まで completed していることが確認できています。このあたりは、自分で一度 bootout して止め、bootstrap / enable / kickstart で再開し、ログを tail して確認するところまでやったので、「何かよくわからないものが勝手に動いている」感覚がかなり薄れました。自分で一度止めて、再開して、挙動を見たのは、運用を理解可能なものに保つ上でとても良かったと思います。
ここまでの実装と運用を、自分向けに整理するとこうなります。
| 層 | 今回作ったもの | 役割 |
|---|---|---|
| 観測 | collect_ethena.py / collect_hyperliquid.py | 最新データを取って raw JSON と DB に蓄積する |
| 整形 | normalize_data.py | raw を比較可能な metric へ平坦化する |
| 研究補助 | build_features.py / event_study.py | 最小特徴量と簡易 shock 検証を更新する |
| 運用 | run_all.py / check_status.py / launchd | 1時間ごとに更新し、日次で正常 / 異常と母数不足を確認する |
| 可視化 / 理解 | notebooks / README | 人間が中身を見て、判断と運用を追えるようにする |
この表で分かる通り、今回作ったのはまだ「勝つ機械」ではありません。
どちらかと言えば、“Ethena を live で継続観測し、あとから自分で白黒をつけられる研究機” です。ここを取り違えないことが本当に大事です。今進んだのは事実ですが、その中身は新しい alpha の発見ではなく、観測可能性、再現性、運用継続性がかなり前に進んだということでした。だから、この章で自分が覚えておきたいのは、「今回はすごいインフラを作った」のでも「勝ち筋が確定した」のでもなく、仮説の残り枝を live で観測できる最小構成を、自分が理解できる範囲で通したという一点です。ここまで来られたなら、少なくとも「研究機械を作る前に構想だけが膨らんでいく」という状態からは抜けられたと思っています。次章では、そのうえで今の段階で何が見えていて、何がまだ全く見えていないのかを、かなり厳しめに整理していきます。
5. 実装して終わりではなく、1時間ごとの定期観測まで通した
今回、自分の中でかなり大きかったのは、観測機を「作って終わり」にしなかったことです。ここは見た目以上に重要でした。最小観測機をローカルで動かせるようになった時点で、技術的には一段落したようにも見えます。けれど、今回のボトルネックは最初から実装不足ではなく、母数不足でした。実際、Phase 2 を通した時点でも sample_insufficient_present=True、still_data_hungry=True で、shock decile も forward event もまだ成立していませんでした。つまり、この段階で必要だったのは新しい機能ではなく、同じ定義で観測点を欠損なく増やすことだったわけです。ここを雑にすると、「せっかく作ったのに、結局データが足りなくて何も判断できない」という、かなりしょうもない終わり方になります。だから今回は、機能追加より先に運用整備へ進みました。
そのとき、自分の中で一度かなりはっきりしたのは、「人間の手動実行だけではたぶん取りこぼす」という感覚でした。これは怠けるとかいう話ではなく、単純に 1 時間ごとの定期反復を 3 日間続けるのは、人間の運用として不安定です。しかも今回見たいのは 6H / 24H / 72H の forward window で、時間間隔のばらつきがそのまま解釈ノイズになります。そうであれば、やるべきことは明確で、自動で毎時 run_all.py を回し、人間は 1 日 1 回だけ check_status.py で状態を確認するという役割分担に寄せた方がいい。ここは Codex 側とのやり取りの中でもかなり明示的に整理されていて、3 日運用なら「今 1 回実行して放置」ではだめ、長時間ループをターミナルで走らせ続けるのもだめ、最適は軽い定期起動 + 人間の日次確認、という結論に落ちています。実際、この判断はかなり妥当だったと思っています。今回の研究で欲しかったのは、常駐し続ける何かではなく、1 時間ごとに単発で同じ観測処理を呼ぶだけの軽い仕組みでした。
その実装として採ったのが launchd です。最初、自分の中ではここに少し抵抗がありました。変にいじって、よく分からないものがバックグラウンドで走りっぱなしになるのは嫌だったからです。だからここは、自分でも一度立ち止まって「launchd とは何か」を確認しています。結局のところ、今回使った launchd は、Mac に「このコマンドを 1 時間ごとに定期実行しておいて」と頼むための標準機能であり、常駐ループを作るためのものではありません。実際の設定も、com.masudakanato.yield-observer.run_all_hourly という Label で、StartInterval = 3600、つまり 1 時間ごとに run_all.py --db observer.db を単発起動するものです。ここで重要なのは、ずっと何かが CPU を使って走り続けているわけではないということです。launchctl print の出力でも state = not running、run interval = 3600 seconds、last exit code = 0 が見えていて、これは「今この瞬間は待機中で、直近実行は成功している」という意味でした。この感覚を自分の中で掴めたのは大きかったです。launchd を“謎の常駐化装置”として怖がるのではなく、“単発コマンドを定期的に呼ぶ係”として理解できたので、運用への心理的抵抗がかなり下がりました。
しかも今回は、その理解を頭の中だけで済ませず、自分で一度止めて、再開して、ログを見て確認しています。これもかなり良かったです。まず launchctl bootout ... で停止し、Could not find service が出ることを確認する。次に bootstrap、enable、kickstart -k で再開し、その後 tail -n 40 run_logs/launchd_run_all.log で、実際に 06:04 に run_all が走り、collect_ethena → collect_hyperliquid → normalize_data → build_features → event_study まで完走し、raw / normalized / feature の件数が増えているところまで見た。さらに launchctl print ... | grep -E "state =|run interval|last exit code|pid =" で run interval = 3600 seconds と last exit code = 0 を確認した。ここまでやったことで、自分の中では「よく分からない自動実行」ではなく、何をどう止めて、どう再開して、どこを見れば正常と判断できるかが分かっている運用になりました。この一手間はかなり重要で、もしここを飛ばしていたら、あとで少し何かおかしくなった時に、不安だけが膨らんでいたと思います。
また、今回かなり良かったのは、定期実行と人間の役割を README にまで落とし込んだことです。ここを曖昧にしておくと、数日後に自分で「何を見るんだっけ?」となります。README には、毎時の run_all.py は 収集 → 正規化 → 特徴量 → event study までを一括で更新するコマンド であり、日次の check_status.py は 定期実行がちゃんと回って、母数が増えているかを人間が確認するためのコマンド だとはっきり書き足しました。さらに、正常 / 異常判定もかなり実務的に整理しています。files がすべて ok、latest_observed_at_by_source の Ethena / Hyperliquid が更新されている、件数が前日より増えている、last exit code = 0、ログに FAIL step= や Traceback がない、こういう状態なら正常。一方で sample_insufficient_present=True と still_data_hungry=True は、今の段階では異常ではなく正常で、単にまだ母数育成中だという意味です。この distinction を README に書けたのは大きいです。うまく言えない不安を減らし、「いま不足しているのは機能ではなく件数だ」と自分に言い聞かせやすくなりました。
自分向けに、ここは簡単に表にしておいた方が後で助かると思うので、いまの運用を整理するとこうなります。
| 役割 | コマンド | 目的 | 正常の見方 |
|---|---|---|---|
| 毎時の自動収集 | python scripts/run_all.py --db observer.db | 最新データ取得、正規化、特徴量更新、event study 更新 | 最後まで completed、件数増加、last exit code = 0 |
| 日次の人間確認 | python scripts/check_status.py --db observer.db | 母数不足か、欠損がないか、source が止まっていないか確認 | latest 時刻更新、point 数増加、files all ok |
| 問題がある日の補助確認 | tail -n 80 run_logs/launchd_run_all.log / ...err.log | 実行途中の FAIL や Traceback を確認 | FAIL や Traceback がない |
| 3日後の停止 | launchctl bootout ... | 定期実行を止める | Could not find service なら停止完了 |
この表で見ると、いまの運用はかなり小さいです。
人間が毎時何かする必要はなく、毎日 1 回状態を見て、問題がある日だけログを確認し、3 日後に止めればよい。ここまで単純化できたことで、実装と運用の境界もだいぶ明確になりました。
この章で自分が特に覚えておきたいのは、今回の進展は「launchd を入れたこと」そのものではない、ということです。そうではなく、観測機を live で回す責任を、人間の気合いではなく、軽い仕組みと日次確認の組み合わせへ移したことが重要でした。ここで重い監視基盤へ行かなかったのも良かったです。cron 自動登録、常駐 daemon、外部通知、notebook 自動実行などはあえてやっていません。理由もかなり明確で、いま必要なのは複雑な運用ではなく、数日間の母数育成を欠損なく進めるための最小整備だったからです。実際、ここで余計なものを足していたら、また実装している感覚だけが増えて、本来の課題である「まだ件数が足りない」という事実から目を逸らしやすくなっていたと思います。今回の自分は、そこをかなりうまく避けられた気がします。次章では、そのうえで今の時点で何が見えていて、何がまだ全然見えていないのかを、sample_insufficient も含めてかなり事実ベースで整理します。
6. 現時点で何が分かっていて、何がまだ分からないのか
ここまで実装と運用を進めてきて、いま自分がいちばん意識しておきたいのは、「進んだこと」と「まだ白黒がついていないこと」を混同しないことです。今回の作業はかなり前に進んでいます。前回は仮説の地位整理までで、主線から外すもの、背景観測に落とすもの、未確定枝として凍結するものを切り分けるところが中心でした。今回はそこからさらに進んで、Ethena + Hyperliquid の live 観測機を立て、raw 保存、SQLite append-only、最小特徴量、event study、check_status.py、launchd による毎時実行まで通しています。これはたしかに大きい進展です。けれど、その進展の中身は 「エッジが見えた」ことではなく、「エッジがあるかどうかを live で継続観測できる状態になった」こと です。ここを間違えると、観測機が動いたこと自体を勝ち筋の発見と錯覚してしまうので、かなり意識的に切り分けておきたいです。
まず、現時点で分かっていることははっきりしています。
一つ目は、Ethena を本命として最小観測機を作る判断は、いまのところ妥当だったということです。これは単なる感覚ではなく、ここまでの研究の流れとかなり整合しています。前回の監査では、利回り付きステーブルコイン全体 → HL perp のような太い全体仮説は切り、Pendle spread と Hyperliquid funding は背景観測に格下げし、sUSDe 個別市場の枝だけを未確定保留にしました。つまり、残ったものの中で最も live 観測に値する family を選ぶ必要がありました。その条件で見ると、Ethena は funding / basis と直結し、perp との因果距離が比較的短く、公開 API と Hyperliquid データを使って比較的軽く観測を始められる。ここは、前回の研究で思考上整理したことと、今回実装に落としたことがきれいに繋がっています。少なくとも、mainline を絞った方向自体はぶれていません。
二つ目は、live 観測機そのものは、現時点でかなり健全に動いていることです。
run_all.py は collect_ethena → collect_hyperliquid → normalize_data → build_features → event_study を最後まで直列実行し、raw / normalized / feature / event study の出力を更新します。さらに launchd による 1 時間ごとの単発起動も、少なくとも直近では正常に機能しています。実際、launchd のログでは completed まで通り、raw_observations や normalized_metrics の件数は増えていますし、last exit code = 0 も確認できています。README にも、何が正常で何が異常か、どう止めてどう再開するかが明文化されている。つまり、少なくとも「研究機として運用できる土台」はかなりできています。ここは、自分が最初に嫌がっていた「理解不能な機械が勝手に裏で動く」状態とはかなり違います。今の機械は、自分で止められて、再開できて、ログを見て、状態を判定できるものになっています。
三つ目は、時刻解釈や volume 解釈のような、後で事故になりやすい部分に早めに手を入れられたことです。
これは地味ですが、かなり大きいです。Ethena の usde_supply は payload 内 timestamp を優先し、Hyperliquid snapshot 系は observed_at ベース、その他は取れなければ observed_at を使う、というルールを normalize 側で持たせました。また、Hyperliquid 側の volume_24h_usd は rolling 24h 指標であって、1 時間出来高ではない、という点も README と特徴量名の両方でかなり強く明示しています。こうした定義が曖昧なまま特徴量や lag 検証へ進むと、簡単に見かけの相関や都合の良い解釈が入り込みます。前回の false positive 監査でかなり痛感したのは、結果の面白さより前提の正しさの方が簡単に壊れる、ということでした。だから、この段階で metric_timestamp や rolling volume の意味まで固定できたのは、かなり重要な前進です。
ただし、ここからが本題で、まだ全く分かっていないこともかなり多いです。
そして今の時点では、むしろこちらの方を強く意識しておく必要があります。
最大の未確定点は、当然ながら Ethena の live フローが、今の定義で本当に Hyperliquid 側へ先行しているかどうか です。
これはまだ白黒がついていません。理由は単純で、サンプルが足りないからです。check_status.py が返している通り、現時点では sample_insufficient_present=True、still_data_hungry=True が正常で、usde_supply や funding / OI / volume の点数も、README に置いている暫定ライン 30+ にはまだ届いていません。shock decile も forward event も未成立、あるいは成立しても統計的な意味づけができるほどではない。つまり、現時点では 「何も起きていない」のではなく、「判断できるほど溜まっていない」 だけです。ここを、つい「見えないから弱い」と読みたくなるのですが、それはまだ早いです。逆に、ここで「ちょっと反応があったからありそう」と読むのも早い。いまは本当に、保留が正しい段階です。
二つ目の未確定点は、Ethena 単体で見えているものが、Ethena 固有の現象なのか、より広い stable parking / yield demand の一部なのか です。
これは今回、Pendle / Sky を live 実装から外したこととも繋がっています。いまは Ethena に絞る判断が合理的でしたが、逆に言うと、解釈の比較軸はまだ薄いです。たとえば数日後に usde_supply の shock と funding / OI の変化に何かが見え始めたとしても、それが Ethena だから起きているのか、単に stable 需要全般の揺れなのかは、Ethena 単体だけではすぐには言えません。この時に比較軸として Sky を戻すか、背景軸として Pendle を再投入するか、という論点が出てきます。つまり、今の live 実装は「主線を細くする」意味では良いのですが、その代わり 解釈の補助線はまだ弱い。この弱さは、現段階では意図的なものですが、今後の判断ではかなり重要になります。
三つ目の未確定点は、たとえ regime や activity の説明力が見えても、それが執行コストを跨ぐ収益源泉になるかは別問題だということです。
ここは最初の問題設定に照らしてかなり重要です。自分が欲しいのは、最終的には「金を稼ぐ源泉」かどうかです。ところが前回の大きめの Ethena 再検証でも、読みとして強かったのは価格方向そのものではなく、perp の参加度や混雑度でした。つまり、Ethena 系のフローがもし live でも見えてくるとして、それはまず trade / no-trade の gate や size 調整 の材料として効く可能性が高く、いきなり「これだけで方向を当てて取れる」という話ではないかもしれません。この distinction はかなり大事で、もし数日後に何らかの関係が見えても、それをそのまま “勝ち筋確定” に読み替えないようにしたいです。むしろ、「regime detector として効くのか」「方向器として効くのか」「背景フィルタに留まるのか」を分けて見る必要があります。ここは、前回の記事でも自分がかなり厳しく false positive を潰していた部分と同じで、意味の地位を雑に上げないことが必要です。
自分向けに、いまの時点で見えていることと見えていないことを表にしておきます。
| 区分 | いま言えること | まだ言えないこと |
|---|---|---|
| 研究主線 | Ethena を本命に絞る判断は妥当 | Ethena だけで十分かは未確定 |
| 観測機 | live 観測機は正常に動いている | 長期運用で欠損なく安定するかはまだ母数不足 |
| 時刻 / 定義 | metric_timestamp と volume 解釈を固定できた | その定義で十分かどうかは live 運用で再検証が必要 |
| シグナル候補 | 最小特徴量と event study の枠組みは作れた | 先行性が本当にあるかはまだ未判定 |
| 研究結論 | 母数不足の間は保留が正しい | エッジ有無、収益化可否、比較軸の必要性はまだ未確定 |
この表を見ると、いまの自分がどこまで進んでいるかがかなり冷静に見えます。
枠組みと観測機はできた。だが、研究の白黒はまだほぼ何もついていない。
これがいまの正確な状態です。
そして、ここで自分に一番言い聞かせたいのは、sample_insufficient は敗北ではないということです。
ここはかなり大事です。定期実行を始めて、check_status.py を毎日見るようになると、つい「まだ insufficient か」「まだ hungry か」とネガティブに感じやすい。けれど README にも書いた通り、今の段階では sample_insufficient_present=True と still_data_hungry=True は異常ではなく正常です。異常なのは files が missing だったり、latest 時刻が止まったり、件数が前日から増えなかったり、ログに FAIL や Traceback が出たりする方です。つまり、足りていないことそのものは、今のフェーズでは失敗ではない。ここをちゃんと認識しておかないと、母数が足りないだけなのに、必要以上に研究テーマや実装方針を揺らしてしまいます。いま必要なのは、新しいことを足すことではなく、観測点を増やして “判断可能な状態” に持っていくことです。
最後に、この章で一番残しておきたい自分向けのフィードバックを書くとしたら、たぶんこうなります。
いま見えているのは、希望ではなく運用状態である。
そして、いま見えていないのは、エッジがないからではなく、まだそれを判定できるだけの母数がないからである。
この二つを混同しないこと。実装が動き始めると、つい「何か掴めた気」がしてしまうし、逆に sample_insufficient が続くと「何もないのでは」と焦りたくもなる。けれど、今の段階で一番正しい態度は、そのどちらにも寄らず、観測機が正常に回っているか、件数が増えているか、定義が壊れていないかを日々確認することです。次章では、その前提の上で、ではこれから何日までに何が見えたら次を掘るのか、何が未達なら方針修正や凍結を考えるのか、というフローチャートを具体的に整理して締めたいと思います。
7. 今後3日間の運用条件と、その先の分岐条件
ここまで来たので、最後にいちばん大事なことをかなり明確に書いておきます。今回のテーマで今やるべきことは、もう仮説を増やすことでも、分析を細かくすることでも、対象プロトコルを追加することでもありません。今やるべきことは、いま作った最小観測機を3日間きちんと回し、母数を増やし、その結果を見て次の分岐を決めることです。ここを曖昧にすると、「何となく回した」「何となく様子を見た」「何となく次に行った」という、いちばん危ない進み方になります。前回の研究でかなり痛感したのは、作業を積み増すことと判断を作ることは別だ、ということでした。だから今回は、実装したものをどう使うか、どの状態なら正常で、どの状態なら異常で、何が見えたら次を掘って、何が未達なら凍結や修正に入るのかまで、かなり具体的に固定しておきます。これは今回の記事の中でも、いちばん未来の自分に効く部分だと思っています。
まず前提として、今回すでに launchd で 1 時間ごとの定期実行は通しています。run_all.py は collect_ethena → collect_hyperliquid → normalize_data → build_features → event_study を直列で実行する単発コマンドで、launchd はこれを 3600 秒ごとに呼ぶだけです。つまり今の運用は、常駐プログラムを育てているのではなく、1 時間ごとに「最新データを取って、整形して、特徴量を更新して、event study を回す」処理を一回ずつ増やしている状態です。そして人間が毎日やることは、check_status.py を 1 回見ることだけです。この役割分担をかなり単純にしたのは、いまの主課題が機能不足ではなく、母数不足だからです。ここで人間が毎時いじり始めたり、新しいものを足したりすると、本来見るべき「ちゃんと増えているか」が見えにくくなります。
では、その 3 日間で何を見るのか。これはかなり明確です。
自分が毎日 1 回 check_status.py で見るべきなのは、次の4点です。
| 見る項目 | 何を意味するか | 正常 | 異常 |
|---|---|---|---|
latest_observed_at_by_source | Ethena / Hyperliquid の更新が続いているか | 当日中に更新されている | 片方だけ長時間止まる |
usde_supply_points / funding_rate_points / open_interest_usd_points / volume_24h_usd_points | 母数が増えているか | 前日より増える | 増えない |
files | latest 出力が揃っているか | すべて ok | missing がある |
sample_insufficient_present / still_data_hungry | まだ母数育成中か | 現段階では True でも正常 | 点数十分なのに長期で変化なしなら要確認 |
ここで大事なのは、sample_insufficient_present=True は異常ではないことです。ここは本当に混同しやすい。今の段階では、shock decile や forward event が未成立でも、件数が増え続けているなら正常です。逆に、見た目上 sample_insufficient が出ていなくても、source の片方が止まっていたり、点数が増えていなかったり、ログに Traceback が出ていたら異常です。つまり今の運用で最重要なのは、「何か見えたか」ではなく、“観測機が欠損なく回っているか” と “母数が育っているか” です。ここを毎日確認するだけで十分ですし、それ以上に毎日細かい分析を増やす必要はありません。
このとき、自分の中で分岐をかなり明示的に持っておきたいので、フローチャートっぽく書くとこうなります。
フェーズA:3日間の最小運用
- 1時間ごとに
run_all.py - 1日1回
check_status.py - 異常がある日だけ
run_logs/launchd_run_all.logと.err.logを確認する - それ以外は何も足さない
3日後の判定①:運用は正常か
- files が全部 ok
- Ethena / Hyperliquid の latest 時刻が更新されている
- 各 points が増えている
last exit code = 0FAIL step=やTracebackがない
これを満たさない場合
→ 研究を掘る前に、実装 / 運用修正へ戻る
→ launchd、collector、DB、ログ確認、スリープ影響などを先に見直す
これを満たす場合
→ 次に「研究上の母数が足りているか」を見る
3日後の判定②:母数は足りているか
README では暫定目安として、
usde_supplyが 30+funding_rate / open_interest_usd / volume_24h_usdが各 30+- shock decile 成立
- 6H / 24H / 72H の forward 比較に使える event が最低限存在
を置いています。ここは厳密な統計閾値ではないですが、少なくとも「もう少し見てもよさそうか」を判断するラインとしては十分です。
これを満たす場合
→ Ethena live 観測の再点検へ進む
→ 何が効いていそうか、何が効かなそうかを、今の定義のまま event study と時系列の両方で見直す
→ ここで初めて、Sky や Pendle を比較軸 / 背景軸として戻す必要があるかを再評価する
これを満たさない場合
→ すぐに「弱い」と結論しない
→ まずは 3 日延長するか、あるいは live だけでは遅いと判断して、過去データ backfill を再投入するかを選ぶ
→ ただし、その前に「時刻解釈」「収集頻度」「Mac スリープの影響」など、観測条件に穴がないかを点検する
この “正常だが未達” と “異常” を分けて考えるのは、今回かなり大事です。もしここを一緒くたにすると、単に母数不足なだけなのに「この仮説は弱いのでは」と余計に悲観したり、逆に少し event が出たからといって「何かありそう」と期待を戻したりしやすくなります。今回はそういうブレを避けるためにも、異常は「動いていないこと」、未達は「まだ足りていないこと」 と分けて扱う必要があります。
次に、その先の分岐、つまり 3 日後以降に何を掘るのかも、かなり明示しておいた方がいいです。
ここでも、自分の中では少なくとも 3 パターンあります。
| 3日後の状態 | 次にやること | どういう意味か |
|---|---|---|
| 運用正常 / 母数も一定水準 | Ethena live 先行性を再点検 | いまの定義で少なくとも再判定可能な状態に来た |
| 運用正常 / でも母数未達 | 追加で数日延長、または backfill 再検討 | 仮説が弱いとはまだ言えない。観測期間が足りないだけの可能性が高い |
| 運用異常 | 実装 / 運用修正へ戻る | 研究以前に観測が壊れている |
この表で重要なのは、「母数未達」だからといってすぐ凍結しないことです。いまの段階で仮説を切る条件は、「件数が足りない」ことではありません。切るべきなのは、十分な母数と適切な定義が揃ったうえで、なお lead / lag や direction / regime の形が見えない場合です。いまはまだそこまで行っていません。だから、未達ならまず延長か backfill 再検討であって、即凍結ではない。ただし、延長するときも「何となく」延ばすのではなく、なぜ延ばすのか、live だけで足りないのか、比較軸が足りないのか を一度必ず言語化する必要があります。ここを雑にすると、また作業で安心する方向へ戻りやすいからです。
一方で、明確に凍結や方針修正を考えるべき条件もあります。
これは自分向けにかなり厳しく書いておきたいところです。
たとえば、
- 数日観測しても source の更新が不安定で、時系列が実務的に育たない
- 時刻解釈や volume 解釈の問題で、live だけでは研究の前提が保てない
- Ethena 単体の観測で、比較軸がないせいにする前に、そもそも何の signal も出ない
- 母数を増やしても、shock decile や forward event が全く成立しない
- Pendle / Sky を戻してまで見る価値があるほどの動きが Ethena 側にも見えない
こういう状態なら、いったんこの live 実装の研究線は凍結か、方針修正を考えた方がいいです。
言い換えると、Ethena live 監視を mainline に置く判断の前提 は、
- 観測が実務的に回ること
- 母数が育つこと
- そのうえで最低限の signal 候補が見えること
です。
このうち 1 と 2 が崩れたら運用修正、3 まで届かず、しかも比較軸を戻す理由も立たないなら、この線は一度冷やすべきです。ここは「せっかく作ったからもう少し」で延命しやすい部分なので、自分向けにはかなり強めに書いておいた方がいいと思っています。
逆に、掘ってよい条件もかなり具体的にしておきたいです。
今の文脈で「掘る」と言うなら、最低でも次のどれかが必要です。
usde_supplyと Hyperliquid 側の funding / OI / volume の間で、shock 後の偏りが event study で繰り返し見える- 価格方向そのものではなくても、regime detector として一貫した偏りが見える
- Ethena 単体では解釈が曖昧だが、Sky や Pendle を戻すことで比較が成立しそうだという根拠が出る
- live 観測だけでは足りないが、今の定義なら backfill に戻しても解釈事故が起きにくいところまで整理できている
このどれかが満たされるなら、Ethena の live 監視を継続しつつ、比較軸を戻すか、backfill へ戻るかを検討してよいと思います。大事なのは、「何か気になるから掘る」ではなく、掘る前提条件を満たしたから掘る にすることです。前回までの研究で、自分はそこをかなり学んだはずです。
最後に、この章を自分向けに一文でまとめるなら、こうなります。
今後3日間は、新しいことを増やす期間ではなく、観測機が正常に回り、母数が育ち、研究の次の分岐条件を満たすかどうかを見る期間である。
そしてその先の分岐は、
- 正常で十分なら再点検
- 正常だが未達なら延長か backfill 再検討
- 異常なら運用修正
というかなり単純な形にしておく。
このくらい単純でいいと思っています。研究は複雑ですが、いま自分が次にやるべき行動は複雑である必要がありません。むしろ複雑にすると、また分析や実装を増やして安心する方向へ逃げやすい。だから今回は、次の数日間の動き方そのものをかなり細く固定しておきます。そこまでできれば、今回の記事は単なる進捗報告ではなく、次の判断を支える実務メモとしてかなり意味があるはずです。