こんにちは。前回の導入編では、「トレンドの60〜80%程度を機械的に取り続ければ、長期的にBuy & Holdより良い結果になるのか?」という問いを出発点に、BTC-USD・ETH-USDに対してMACD(12,26,9)がBuy & HoldをSharpe・MaxDDで上回る一方、CAGRでは構造的に劣後するという、正直あまり景気の良くない結論をお伝えしました。
今回はその続きです。ざっくりいえば「シグナル(買い/売り)が合っていても、建玉の大きさを間違えたら意味がない」という話で、ポジションサイジング(建玉調整)とストップロス、そしてパラメータの選び方そのものの頑健化を検証しました。結論を先に言ってしまうと、リスクは確かに減らせますが、その代償としてリターンも一緒に削れますし、「最適な設定」を探そうとすればするほど過学習の罠にハマります。今回もあまり都合の良い話ばかりではありませんが、正直にまとめていきます。
① ボラティリティに応じて建玉を増減させる ― VolatilityTargetSizer
MACDが出す売買シグナルは、本来「買い」か「売り」かの0/1でしかありません。これをそのまま使うと、値動きが激しい局面でも常にフルポジションを持ち続けることになり、結果的にドローダウン(高値からの下落幅)が深くなりがちです。そこで導入したのがVolatilityTargetSizerという仕組みで、直近の実現ボラティリティを見ながら「値動きが荒い時期は建玉を減らし、穏やかな時期は増やす」よう建玉比率を連続的に調整します。ここに、高値から一定比率下落したら強制的に手仕舞うストップロスも組み合わせます。
BTC-USDで、目標ボラティリティ40%(年率)+ストップロス15%を適用した結果がこちらです。
| サイジング/ストップロスなし | あり(本番構成) | |
|---|---|---|
| CAGR | 65.75% | 46.88% |
| 年率ボラティリティ | 45.09% | 30.07% |
| Sharpe Ratio | 1.34 | 1.43 |
| Maximum Drawdown | -48.71% | -37.52% |
ボラティリティとMaxDDが大きく縮み、Sharpe(リスク当たりのリターン)も改善しています。ここまでは良い話なのですが、正直にいうと見過ごせない副作用があります。サイジング/ストップロスを適用した本番構成のCAGR(46.88%)は、Buy & HoldのCAGR(51.56%)を下回ってしまうのです。導入編でお伝えした「本番構成はSharpe・MaxDDでは勝つが、CAGRでは負ける」という結論の正体は、まさにこのリスク管理そのものにありました。
理屈で考えると納得できる話ではあります。BTCのように強い片方向トレンドが続きやすい相場では、下落局面でいったん現金化する(=ポジションを減らす)コストは、その後の急反発を取り逃す機会損失として跳ね返ってきます。「多少痛い目を見ても持ち続ける」方が、複利では有利になりやすいというトレンドフォロー戦略共通の弱点が、ここに素直に表れています。
② サイジング・ストップロスのパラメータを最適化してみたら
「目標ボラティリティ40%・ストップロス15%」という数字、正直なところ最初はやや適当に決めた値でした。じゃあちゃんとチューニングすれば良くなるのでは、と考えるのは自然な発想です。そこでMACD(12,26,9)を固定した上で、目標ボラティリティ(20〜60%)×ストップロス幅(10〜25%、なしを含む)の全25通りを、学習期間(train)で最良のSharpeを選び、検証期間(test)に当てはめるという手順で試しました。
| 銘柄 | trainでSharpe最良のパラメータ | train Sharpe | test Sharpe | test CAGR |
|---|---|---|---|---|
| BTC-USD | target_vol=0.2, stop_loss=25%(実質なし) | 1.73 | 0.39 | 4.68% |
| ETH-USD | target_vol=0.2, stop_loss=なし | 1.02 | 0.34 | 4.35% |
見ての通り、学習期間で一番良かったパラメータをそのまま検証期間に当てはめると、成績がガクッと落ちます(BTC: Sharpe 1.73→0.39、ETH: 1.02→0.34)。これは「たまたま学習期間の値動きに都合が良かっただけ」のパラメータを、あたかも普遍的な最適解であるかのように選んでしまう、いわゆるwinner’s curse(勝者の呪い)です。MACDのパラメータ選定で見られた現象と、まったく同じ罠がサイジング側にも潜んでいました。
さらに厄介なのは、BTC-USDとETH-USDで示唆する方向性が真逆だったことです。
- 目標ボラティリティを上げた場合の挙動が逆:BTC-USDは40%→60%と上げるほどtest Sharpeが改善する(0.39→0.50)一方、ETH-USDは逆に上げるほど悪化する(0.34→0.12)
- ストップロスの効き方も逆:BTC-USDは10〜25%のどの幅でもほぼ結果が変わらない一方、ETH-USDは目標ボラティリティが低い場合に限り、ストップロスを10%まで絞るとtest Sharpeが明確に改善する(0.34→0.49)
単一のtrain/test分割・2銘柄という限られたサンプルでは、「銘柄を問わない最適値」は見つかりませんでした。既定の目標ボラティリティ40%・ストップロス15%は、この感応度で見ても極端に悪い値ではなかったため、無難な選択として既定値は変更しないことにしています。中途半端に思われるかもしれませんが、根拠のない微調整に走るより、都合の悪い結果を含めてそのまま記録しておく方が誠実だと考えています。
③ 「賭け金を一律に減らす」だけでは足りない ― 固定比率サイジング
VolatilityTargetSizerは相場環境に応じて建玉比率を日々動かす、いわば「動的な」サイジングです。ここでふと疑問が浮かびます。そんなに凝ったことをしなくても、常に一定の比率(例えば常に50%)だけ建玉を落とすだけで、複利のボラティリティドラッグが減って同じような効果が得られるのではないか、と。そこでFixedFractionSizer(建玉比率を常に一定に固定)を実装し、fraction(50%/75%/100%)×ストップロス幅を検証しました。ストップロス幅を15%(既存の本番構成と同じ)に揃え、fractionだけを動かした検証期間の成績がこちらです。
BTC-USD
| 設定 | test CAGR | test Sharpe | test MaxDD |
|---|---|---|---|
| fraction=50%, stop=15% | 6.61% | 0.49 | -18.46% |
| fraction=75%, stop=15% | 9.10% | 0.49 | -27.00% |
| fraction=100%, stop=15% | 10.99% | 0.49 | -35.01% |
| VolatilityTargetSizer(40%)+stop15%(本番構成) | 8.58% | 0.44 | -30.56% |
ETH-USD
| 設定 | test CAGR | test Sharpe | test MaxDD |
|---|---|---|---|
| fraction=50%, stop=15% | 0.23% | 0.13 | -34.35% |
| fraction=75%, stop=15% | -1.68% | 0.13 | -47.94% |
| fraction=100%, stop=15% | -4.85% | 0.13 | -59.30% |
| VolatilityTargetSizer(40%)+stop15%(本番構成) | 5.09% | 0.31 | -45.22% |
ここでちょっと面白いことが起きています。CAGRとMaxDDはfractionにほぼ比例して縮む(fraction=100%を基準に50%はおおよそ半分程度)のに対し、test Sharpeはfractionを変えてもまったく変化しません(BTC: 常に0.49、ETH: 常に0.13)。これは実装のバグではなく、数学的に必然の結果です。FixedFractionSizerは全期間にわたって一律に「生のポジション × fraction」を掛けるだけなので、リターンの系列全体がfraction倍に一律スケールされます。Sharpe Ratioは「平均 ÷ 標準偏差」で定義されるため、系列全体を同じ定数倍しても平均と標準偏差が同じ比率で動き、比は変わらないのです。つまり「賭け金を一律に減らす」だけの固定比率サイジングは、Sharpe Ratioを原理的に一切改善できません。できるのは、CAGRとMaxDDを比例的に下げることだけです。
対照的に、ストップロスは価格が一定幅下がった時にだけ発動する非線形な仕組みなので、系列全体を一律スケールするわけではなく、Sharpeを変化させ得ます(ETH-USDでストップロスを10%まで絞った時だけtest Sharpeが0.13→0.23に変わったのが好例です)。動的にボラティリティを見ながら建玉を調整するVolatilityTargetSizerも同様で、実際ETH-USDではフルロードや固定比率のどの設定よりもtest Sharpeが高くなっています(0.31 vs 最良でも0.13)。「相場環境に応じて建玉比率の形そのものを変える」ことが、リスク調整後リターンの改善には欠かせないようです。
ちなみに、この「Sharpeがfractionによらず一定」という結果を見て「じゃあ常にフルロードで良いのでは」と考えるのは早計です。Sharpeが不変なのはあくまで数学的な性質であって、fractionを上げればCAGRだけでなくMaxDDも同じ調子で悪化します(BTC test: fraction 50%→100%でMaxDDが-18.5%→-35.0%)。fractionは、Sharpeではなく自分がどこまでのドローダウンに耐えられるかというリスク許容度で決めるべきパラメータです。
④ パラメータ選定方法自体を頑健化する
最後にもう一つ。Walk-forward検証(学習期間でパラメータを選び、検証期間に当てはめる手順)では、従来「学習期間全体でSharpe最大」のパラメータを選んでいましたが、これも②で見たようなwinner’s curseの影響を受けます。そこで学習区間をさらにサブ期間(既定3分割)に分け、「サブ期間ごとの成績の平均 − 標準偏差 × 安定性ペナルティ」が最大のパラメータを選ぶrobust方式を試しました。特定の期間だけ調子が良く、残りはボロボロ、というパラメータより、期間を通して安定して悪くないパラメータを優先する狙いです。
| 銘柄 | 固定12/26/9 | Walk-forward(max) | Walk-forward(robust) | Buy&Hold(同一OOS期間) |
|---|---|---|---|---|
| SPY CAGR / Sharpe / MaxDD | 3.58% / 0.37 / -38.75% | 2.42% / 0.27 / -42.29% | 1.33% / 0.18 / -49.05%(悪化) | 7.48% / 0.47 / -56.47% |
| BTC-USD CAGR / Sharpe / MaxDD | 65.75% / 1.34 / -48.71% | 44.83% / 1.03 / -62.38% | 48.05% / 1.09 / -59.79%(改善) | 38.36% / 0.82 / -83.40% |
結果は銘柄によって正反対に出ました。BTC-USDではrobust方式がSharpe・CAGR・MaxDDすべてで改善しましたが、SPYではむしろmax方式よりさらに悪化しています。この非対称さ自体が示唆的です。「選定方法を工夫すれば必ず良くなる」わけではなく、そもそもトレンドフォローとして機能する構造がある銘柄(BTC)でだけ、選定方法の改善が効くということだと考えられます。SPYはどう頑張って選んでも(適当でも、最大化でも、頑健化でも)Buy & Holdに届かないという、導入編でお伝えした結論が、ここでさらに裏付けられた形です。
検証で気をつけていること
今回の一連の検証を通して、改めて意識しているのはこの3点です。
- winner’s curse:学習期間で一番良かった設定を鵜呑みにしない。②で見た通り、学習Sharpe 1.73が検証では0.39まで落ちるようなことが普通に起きる
- 銘柄間の一致を過信しない:BTC-USDとETH-USDで最適な方向性が逆になるケースが複数回出てきた。「片方の銘柄で効いた調整」をもう片方にそのまま当てはめない
- 数字の意味を取り違えない:Sharpeが同じでもMaxDDやCAGRは全く違う、という③のような場面がある。1つの指標だけで「良い/悪い」を判断しない
正直、「これをやれば必ず良くなる」という都合の良い結論には、今回もたどり着けませんでした。ただ、そういう「効かなかった」検証の記録自体が、次に変な近道をしないための資産になると思っています。
次回予告
次回は「コスト・マルチアセット編」です。ここまでの検証はいったんBTC-USD単体を中心に見てきましたが、実際に取引所で売買するとなると手数料の体系が結果を左右します。GMOコインやcoincheckといった実在の取引所の手数料体系を精緻化した検証と、ETH-USD・SOL-USDなど複数の暗号資産に広げた頑健性チェックについてまとめる予定です。
最後まで読んでいただきありがとうございます。ご質問やコメントはお問い合わせからよろしくおねがいします。