Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
469 changes: 469 additions & 0 deletions research/backtest_hybrid_growth_continuous_scaling_followup.py

Large diffs are not rendered by default.

405 changes: 405 additions & 0 deletions research/backtest_hybrid_growth_idle_throttle_followup.py

Large diffs are not rendered by default.

770 changes: 770 additions & 0 deletions research/backtest_hybrid_growth_indicator_variants.py

Large diffs are not rendered by default.

498 changes: 498 additions & 0 deletions research/backtest_hybrid_growth_position_scaling_followup.py

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"baseline_growth_reference": {
"idle_asset": "QQQ",
"oos_cagr": 0.38770315883497886,
"oos_max_drawdown": -0.3211199087725741,
"oos_ulcer": 9.627918627041247,
"oos_ir_vs_qqq": 0.7502300923853346
},
"baseline_defensive_reference": {
"idle_asset": "BOXX",
"oos_cagr": 0.23860213021458554,
"oos_max_drawdown": -0.20112252200733738,
"oos_ulcer": 7.51404066842126
},
"continuous_candidate": {
"scaling": "ma20_gap_trim_only",
"idle_asset": "QQQ",
"oos_cagr": 0.3721585108293748,
"oos_max_drawdown": -0.31763500064867334,
"oos_ulcer": 9.637568131252396,
"oos_ir_vs_qqq": 0.695452288733183,
"turnover_per_year": 2.8632596159147603,
"average_scale_while_invested": 0.9654877542375832
},
"verdict": "The trim-only continuous mapping is cleaner than the earlier score-based variants, but it still does not clearly beat the baseline. It smooths the path mainly by carrying a bit less TQQQ, not by creating a meaningfully better OOS growth profile."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# TQQQ continuous position-scaling follow-up

## Setup
- Keep the existing MA200 + ATR TQQQ entry/exit framework.
- Change only the TQQQ position size while already invested.
- Use one continuous indicator only: QQQ distance vs MA20.
- Compare two idle assets: `BOXX` and `QQQ`.

## OOS 2023+ (5 bps)
| scaling | idle_asset | CAGR | Max Drawdown | Ulcer Index | Information Ratio vs QQQ | Alpha Ann vs QQQ | Turnover/Year | Average TQQQ Weight | Average Scale While Invested |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| baseline | BOXX | 0.238602 | -0.201123 | 7.514041 | -0.187183 | -0.031695 | 1.237510 | 0.457729 | 1.000000 |
| baseline | QQQ | 0.387703 | -0.321120 | 9.627919 | 0.750230 | -0.054166 | 1.138170 | 0.455575 | 1.000000 |
| ma20_gap_linear | BOXX | 0.210636 | -0.199751 | 8.330539 | -0.353209 | -0.050267 | 4.403525 | 0.467389 | 1.020293 |
| ma20_gap_linear | QQQ | 0.365982 | -0.326197 | 10.136864 | 0.645963 | -0.067824 | 4.436067 | 0.466023 | 1.020293 |
| ma20_gap_trim_only | BOXX | 0.218393 | -0.182403 | 7.528751 | -0.341663 | -0.035422 | 2.910826 | 0.442867 | 0.965488 |
| ma20_gap_trim_only | QQQ | 0.372159 | -0.317635 | 9.637568 | 0.695452 | -0.057661 | 2.863260 | 0.440277 | 0.965488 |

## Full Sample (5 bps)
| scaling | idle_asset | CAGR | Max Drawdown | Ulcer Index | Information Ratio vs QQQ | Turnover/Year | Average TQQQ Weight | Average Scale While Invested |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| baseline | BOXX | 0.221402 | -0.454508 | 12.312903 | 0.212472 | 1.270941 | 0.394726 | 1.000000 |
| baseline | QQQ | 0.284755 | -0.499827 | 17.100661 | 0.746109 | 1.240954 | 0.378468 | 1.000000 |
| ma20_gap_linear | BOXX | 0.219139 | -0.394992 | 11.705114 | 0.188906 | 3.749817 | 0.400119 | 1.022352 |
| ma20_gap_linear | QQQ | 0.285719 | -0.461445 | 16.880328 | 0.768228 | 3.672616 | 0.385694 | 1.022352 |
| ma20_gap_trim_only | BOXX | 0.214930 | -0.387385 | 11.232493 | 0.164054 | 2.596423 | 0.379484 | 0.962610 |
| ma20_gap_trim_only | QQQ | 0.283283 | -0.458986 | 16.580457 | 0.779122 | 2.568179 | 0.363742 | 0.962610 |

## 2022 (5 bps)
| scaling | idle_asset | Total Return | 2022 Return | Max Drawdown | Ulcer Index | Turnover/Year |
| --- | --- | --- | --- | --- | --- | --- |
| baseline | BOXX | -0.161162 | -0.161162 | -0.173794 | 17.021359 | 0.512380 |
| baseline | QQQ | -0.387752 | -0.387752 | -0.412978 | 31.478228 | 0.505886 |
| ma20_gap_linear | BOXX | -0.136642 | -0.136642 | -0.149992 | 14.721060 | 0.742490 |
| ma20_gap_linear | QQQ | -0.376827 | -0.376827 | -0.402736 | 30.365284 | 0.742490 |
| ma20_gap_trim_only | BOXX | -0.136243 | -0.136243 | -0.149094 | 14.629202 | 0.670105 |
| ma20_gap_trim_only | QQQ | -0.376170 | -0.376170 | -0.401873 | 30.269567 | 0.670105 |

## Recommendation
- The trim-only continuous mapping is cleaner than the earlier score-based variants, but it still does not clearly beat the baseline. It smooths the path mainly by carrying a bit less TQQQ, not by creating a meaningfully better OOS growth profile.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"best_baseline_by_cagr": {
"idle_asset": "QQQ",
"oos_cagr": 0.3865033212434974,
"oos_max_drawdown": -0.32111996059789283,
"oos_ir_vs_qqq": 0.7513739398647076,
"return_2022": null
},
"safest_baseline_idle_asset": {
"idle_asset": "BOXX",
"oos_cagr": 0.2394659221932549,
"oos_max_drawdown": -0.20112252329052704
},
"best_throttle_candidate": {
"idle_asset": "QQQ",
"oos_cagr": 0.37331214938527135,
"oos_max_drawdown": -0.293642217228371,
"oos_ir_vs_qqq": 0.7329349938113593,
"return_2022": null
},
"verdict": "Keep the baseline. The simple MA60 half-throttle improves 2022 and drawdown only when paired with defensive idle assets, but it gives up too much CAGR and still loses to baseline+QQQ on growth metrics."
}
30 changes: 30 additions & 0 deletions research/results/tqqq_hybrid_idle_throttle_followup_summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# TQQQ idle-asset and minimal-throttle follow-up

## Setup
- Attack-only normalization: isolate the TQQQ sleeve and compare idle assets directly.
- Baseline: existing MA200 + ATR staged TQQQ logic.
- Minimal throttle: if QQQ closes below MA60, cut the computed TQQQ target by 50%.
- Idle assets tested: `CASH`, `BOXX`, `QQQ`.

## OOS 2023+ (5 bps)
| throttle | idle_asset | CAGR | Max Drawdown | Information Ratio vs QQQ | Alpha Ann vs QQQ | Turnover/Year | Average TQQQ Weight | Average Idle Asset Weight |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| baseline | BOXX | 0.239466 | -0.201123 | -0.172266 | -0.029705 | 1.241688 | 0.458291 | 0.491709 |
| baseline | CASH | 0.211531 | -0.202525 | -0.338829 | -0.052564 | 1.244173 | 0.458611 | 0.541389 |
| baseline | QQQ | 0.386503 | -0.321120 | 0.751374 | -0.052876 | 1.142013 | 0.456134 | 0.493866 |
| ma60_half | BOXX | 0.223423 | -0.180200 | -0.308919 | -0.010823 | 3.820005 | 0.421460 | 0.528540 |
| ma60_half | CASH | 0.195971 | -0.184140 | -0.473194 | -0.033980 | 3.834373 | 0.422757 | 0.577243 |
| ma60_half | QQQ | 0.373312 | -0.293642 | 0.732935 | -0.041658 | 3.711045 | 0.413514 | 0.536486 |

## 2022 (5 bps)
| throttle | idle_asset | Total Return | 2022 Return | Max Drawdown | Turnover/Year | Average TQQQ Weight | Average Idle Asset Weight |
| --- | --- | --- | --- | --- | --- | --- | --- |
| baseline | BOXX | -0.161162 | -0.161162 | -0.173794 | 0.512380 | 0.027606 | 0.922394 |
| baseline | CASH | -0.161719 | -0.161719 | -0.173794 | 0.512380 | 0.027606 | 0.972394 |
| baseline | QQQ | -0.387752 | -0.387752 | -0.412978 | 0.505886 | 0.027191 | 0.922809 |
| ma60_half | BOXX | -0.117219 | -0.117219 | -0.131439 | 0.550353 | 0.017447 | 0.932553 |
| ma60_half | CASH | -0.117805 | -0.117805 | -0.131439 | 0.550353 | 0.017447 | 0.982553 |
| ma60_half | QQQ | -0.361779 | -0.361779 | -0.388075 | 0.505886 | 0.015588 | 0.934412 |

## Recommendation
- Keep the baseline. The simple MA60 half-throttle improves 2022 and drawdown only when paired with defensive idle assets, but it gives up too much CAGR and still loses to baseline+QQQ on growth metrics.
Loading