Bot CEX 開発ログ

🛠️開発記録#499(2026/4/1)multi_market_probe開発ログ ― short側60秒までの判定機を一旦完成させ、エッジの有無を事実ベースで切り出せるようにした話

こんにちは、ぼっちbotterよだかです。

今回は、binance_perp→bitFlyer FX の LeadLag 研究において、short側の10〜60秒を事実ベースで判定できる状態まで一旦持っていった話を書きます。やったこと自体は新しいシグナルを足すことではなく、むしろ「今見ている表示や集計が、本当に見たい事実と一致しているのか」を詰め直す作業でした。結果として、見かけ上の優位性を削ぎ落とし、少なくとも現時点では short 側に明確なエッジは確認できない、というところまで読み取れるようになりました。勝ち筋を見つけた話ではありませんが、判定機をちゃんと判定機として使える形へ寄せた、という意味ではかなり重要な一歩だったと思っています。

前回の話
🛠️開発記録#498(2026/3/31)LeadLagの主仮説を7.6bps込みで見直し、この線はいったん下ろすと決めた話

続きを見る

ゴールを絞る:short 10〜60秒を判定できる状態まで持っていく

今回まずやりたかったのは、LeadLag研究を大きく前進させることではなく、short側の10〜60秒について「今この構造にエッジがあるのか、ないのか」を、少なくとも判定器の側でまともに読める状態まで持っていくことでした。

対象は、binance_perp から bitFlyer FX への short 側です。ここは直近の観測や過去データの見え方から、完全に無視するには惜しい一方で、主仮説として強く握るにはまだ根拠が薄い、という微妙な位置にありました。だからこそ今回は、ロング側まで一気に広げたり、比較市場を増やしたり、判定条件を複雑にしたりするのではなく、あくまで short だけ、しかも horizon も 10/20/30/40/50/60 秒に絞って、「この帯域で事実として何が残っているのか」を切り出せるようにすることを開発目標に置きました。

ここで重要だったのは、何か新しいロジックを足して強そうに見せることではありません。むしろ逆で、いま見えている数値やパネルが、本当に自分の見たい事実を示しているのかを厳しく問い直すことでした。研究の途中では、表示されているグラフや集計値がそれっぽく見えるだけで、つい「何かありそうだ」と感じてしまうことがあります。でも、そこで表示の定義と判定の定義がズレていたら、そこから先の解釈や判断も全部ズレていきます。今回はその危険が実際に出てきたので、まずはそこを整える必要がありました。

要するに、今回のゴールは「short側10〜60秒で勝てるようにする」ことではなく、「short側10〜60秒について、勝てるかどうかを少なくとも事実ベースで読める判定機にする」ことです。勝ち筋を作る前に、見ているものの意味を固定する。そこを曖昧にしたまま先へ進むと、たまたま都合よく見えた数値を追いかけるだけになってしまうので、今回は意識的にそこへブレーキをかけました。

この時点での自分の狙いはかなりシンプルでした。short側の60秒までを一旦ひと区切りの対象として整備し、見かけの優位性ではなく、実際に残っている事実だけを読める状態にすること。もしそこでエッジが見えなければ、それはそれで十分に意味があります。むしろ、その「見えなかった」をちゃんと出せる判定機の方が、研究を次に進めるうえでは価値があると思っています。

考え方と実装:表示の定義を揃え、負の増分も捨てないようにした

今回いちばん大事だったのは、単にパネルの見た目を直すことではなく、「何を判定値として扱うのか」を実装レベルで揃えることでした。最初に違和感が出たのは、short 10〜60秒を見ているはずの DECISION パネルで、20秒や40〜60秒は正寄りなのに、10秒と30秒だけが負に沈んで見えたことです。こういうとき、最初はつい「市場構造がそうなのかもしれない」と読みたくなるのですが、今回はそこで立ち止まりました。なぜなら、表示の定義と判定ロジックの定義が一致していない可能性があったからです。

実際に確認してみると、解析スクリプト側では C方式、つまり window_incremental を使って「窓内で新たに成熟したサンプル差分だけ」を集計していた一方で、Grafana の DECISION パネルは cumulative mean を avg_over_time で読んでいました。見た目としてはどちらも「24h の short 判定」のように見えるのですが、中身はまるで別物です。これでは、パネルを見ながら判定しているつもりでも、実際には別定義の値を眺めていることになります。まず直すべきはここでした。

そこで今回は、DECISION 層が C方式を直接見るように修正しました。解析スクリプトだけが正しくても意味がなく、日常的に見るダッシュボード側も同じ定義を参照していないと、実運用ではまた同じ混乱が起きます。なので、判定器の一次ソースを C方式に寄せ、その値をそのまま読めるように配線し直しました。これは、ロジックを強くする修正ではなく、「見ているものの意味を固定する」ための修正です。

ただ、ここで終わりではありませんでした。さらに確認を進めると、window_incremental の集計関数側にも、事実ベースという観点から見ると少し危うい点がありました。差分計算では dnds を作っていて、dn < 0 なら累積サンプル数が減っているので、再起動や系列断絶の検知として自然です。問題は ds < 0 まで reset 扱いしていたことでした。

この ds は、累積サンプル数と平均リターンから作った「合計リターンの増分」に相当します。なので、新しく成熟したサンプル群の成績が悪ければ、普通に負になります。つまり ds < 0 は、異常系だけでなく正常な負けでも起こりうる値です。にもかかわらず、それを reset 扱いしてしまうと、負の寄与だけを系列断絶として捨てる形になりかねません。これは防御ロジックとして入っていたのだと思いますが、事実ベースの判定器として見るなら、少なくともそのままでは甘い。結果として、負けを取りこぼして上振れした見え方になる可能性がありました。

そこで、この reset 条件も見直しました。dn < 0 は維持しつつ、ds < 0 は reset 条件から外し、負の増分もそのまま集計に含めるようにしたのです。ここで意識したのは、何かを良く見せることではありません。むしろ逆で、「負けもちゃんと負けとして入れる」方向に揃えることでした。見栄えのいい判定器ではなく、都合の悪い事実まで含めて読める判定器に寄せる。今回の修正の本質はそこにあります。

要するに、判定器の表示と中身を一致させ、しかも中身の側でも楽観に寄りうる部分を削った、ということです。この実装は派手さはありませんが、研究の足場としてはかなり重要でした。勝ち筋を作る前に、負けをちゃんと負けとして出せる状態にする。その順番を守れたのは大きかったと思います。

見えているもの:整った判定機で見ると、優位性はまだ確認できなかった

ここまで修正を入れたうえで改めて見えてきたのは、少なくとも現時点の short 10〜60秒には、明確な優位性はまだ確認できない、というかなり地味な事実でした。

これは、単に「何となくグラフが弱そうに見えた」という話ではありません。むしろ今回は、表示の定義と判定ロジックを揃え、さらに負の増分も捨てないようにしたあとで、なお short 側の window_incremental net return が全体として負寄りに出ていました。つまり、「見かけ上は良さそうに見えていたもの」を削ぎ落とした結果として、少なくとも今の観測範囲では short 側に取りに行ける地形は見えていない、ということです。

この点は、自分の中でもかなり重要でした。というのも、修正前には 40秒や50秒、60秒あたりがプラス圏に見える瞬間もあり、少し掘れば何か出るのではないか、という期待を持ちたくなる形だったからです。でも、そこに集計上の楽観バイアスが混ざっていたなら、その期待は事実ベースではなくなります。今回、ds < 0 を reset 扱いしないように直したことで、そのあたりの見え方はかなり変わりました。そして変わった先で見えたのは、「以前より悪く見えるようになった」のではなく、「以前は少し良く見えすぎていた可能性が高い」ということでした。

もちろん、これで LeadLag の short 側が完全に死んだ、とまではまだ言いません。観測時間はまだ長くないですし、24時間窓の中に設定変更直後のデータが混ざるような過渡期の読み取りには慎重であるべきです。だから、今ここで下すべき判断は「永久に無し」ではなく、「少なくとも今は、short 10〜60秒に明確なエッジがあるとは言えない」です。この違いはかなり大事だと思っています。強い否定ではなく、いま見えている事実をそのまま置く、という態度です。

ただ、その留保を置いたとしても、今回の意味は薄くありません。むしろ、整った判定機で見たときに優位性が確認できなかった、というのは、研究としては十分に前進です。ここが曖昧なままだと、「たまたま良く見えた瞬間」を掘り続けることになりやすいですが、今回は少なくともその誘惑を一度は切れました。short 側の 10〜60秒に関しては、今のところ「あるかもしれない」ではなく「まだ無い寄り」と言える。これは、次の判断をするうえでかなり大きい材料です。

今回見えたのは勝ち筋ではありませんでした。でも、それは失敗というより、判定器がちゃんと仕事をした結果だと思っています。都合のいい数字ではなく、都合の悪い数字まで含めて出せるようになった。そのうえでなお優位性が見えないなら、そこを素直に受け取れる方が次に進みやすい。この観測機で見たいのは、まさにその一点です。

ここからどう進むか:short側は一旦区切り、観測継続と次候補へ進む

今回の着地点としては、short 側 10〜60秒の判定機は一旦完成と見なしてよいと思っています。ここでいう完成とは、勝てるシグナルができたという意味ではなく、「少なくとも何を見て、何をもって優位性の有無を読むのか」が実装と表示の両方で揃った、という意味です。判定器としての土台が整い、そのうえで今のところ優位性は確認できない、という事実まで出せたのであれば、short 側をこのままずるずる掘り続けるよりも、いったん区切りをつける方が自然です。

ただし、ここで完全に捨てるつもりもありません。今回整えた判定機は、少なくとも short 側 60秒までの観測を継続する土台としては十分に機能します。だから次の方針としては、まず観測自体は続けます。そのうえで、均質な窓がもう少し溜まった状態でもなお同じように負寄りなのか、それとも時間帯や地合いによって見え方が変わるのかを確認していくつもりです。今回の時点では「今は無い寄り」までは言えても、「完全に無い」まではまだ断定しません。その意味で、観測継続は残します。

一方で、研究の重心まで short 側に置き続けるつもりもありません。今回見えたのは、少なくともこの定義・この horizon 群では、強く掘り下げるだけの地形はまだ見えていない、ということでした。ならば次は、long 側や別の horizon、あるいは LeadLag の切り方そのものを含めて、次候補を見に行く方が合理的です。ここで大事なのは、short 側を未練で延命しないことだと思っています。観測は続ける、でも主戦場に据えるかどうかは別問題。その線引きを曖昧にしないようにしたいです。

今回の経験から改めて思ったのは、研究では「何を作ったか」以上に、「どこで一度区切るか」が大事だということです。まだ可能性がゼロではないからといって同じ仮説に居座り続けると、どうしても都合のいい見え方を拾いにいきやすくなります。逆に、整えた判定機で見てもなお優位性が確認できないなら、その時点で一度区切る。今回の short 側は、まさにそのラインに来たのだと思います。

なので、ここからの方針はかなりシンプルです。short 10〜60秒の判定機は一旦完成として固定する。観測は継続する。ただし、研究の次の一手としては short 側をさらに掘ることに固執せず、別候補も並行して見ていく。そのうえで、もし後から short 側に地形が見えてくるなら、そのとき改めて戻ればよい。今回はそうやって、一度ちゃんと閉じるところまで持っていけたのが収穫だったと思っています。

-Bot, CEX, 開発ログ