22"""
33Cross-strategy comparison for:
44- russell_1000_multi_factor_defensive
5- - hybrid_growth_income
6- - semiconductor_rotation_income
5+ - tqqq_growth_income
6+ - soxl_soxx_trend_income
77- qqq_plus_stock_alpha_v1 (research-only)
88
99The script keeps the defensive baseline frozen, compares it fairly against the
6262
6363
6464SAFE_HAVEN = "BOXX"
65- HYBRID_SAFE_CASH = "CASH"
65+ TQQQ_GROWTH_SAFE_CASH = "CASH"
6666OFFENSIVE_NAME = "qqq_plus_stock_alpha_v1"
6767
6868DEFENSIVE_NAME = "russell_1000_multi_factor_defensive"
69- HYBRID_FULL_NAME = "hybrid_growth_income "
70- HYBRID_NORMALIZED_NAME = "hybrid_growth_income_no_income "
71- SEMICONDUCTOR_FULL_NAME = "semiconductor_rotation_income "
72- SEMICONDUCTOR_NORMALIZED_NAME = "semiconductor_rotation_income_no_income "
69+ TQQQ_GROWTH_FULL_NAME = "tqqq_growth_income "
70+ TQQQ_GROWTH_NORMALIZED_NAME = "tqqq_growth_income_no_income "
71+ SOXL_SOXX_TREND_FULL_NAME = "soxl_soxx_trend_income "
72+ SOXL_SOXX_TREND_NORMALIZED_NAME = "soxl_soxx_trend_income_no_income "
7373
7474FULL_COMPARISON_LAYER = "full_strategy"
7575NORMALIZED_COMPARISON_LAYER = "normalized"
@@ -573,7 +573,7 @@ def build_period_summary_rows(
573573 benchmark_returns ,
574574 start = start ,
575575 end = end ,
576- safe_haven_symbols = (SAFE_HAVEN , HYBRID_SAFE_CASH ),
576+ safe_haven_symbols = (SAFE_HAVEN , TQQQ_GROWTH_SAFE_CASH ),
577577 full_returns_reference = net_returns ,
578578 )
579579 rows .append (
@@ -620,7 +620,7 @@ def compute_rolling_36m_capm_alpha(strategy_returns: pd.Series, benchmark_return
620620 )
621621
622622
623- def run_hybrid_growth_income_backtest (
623+ def run_tqqq_growth_income_backtest (
624624 qqq_ohlc : pd .DataFrame ,
625625 asset_returns : pd .DataFrame ,
626626 * ,
@@ -643,12 +643,12 @@ def run_hybrid_growth_income_backtest(
643643 entry_line_floor : float ,
644644 entry_line_cap : float ,
645645) -> tuple [pd .Series , pd .DataFrame , pd .Series ]:
646- strategy_symbols = ["TQQQ" , SAFE_HAVEN , "SPYI" , "QQQI" , HYBRID_SAFE_CASH ]
646+ strategy_symbols = ["TQQQ" , SAFE_HAVEN , "SPYI" , "QQQI" , TQQQ_GROWTH_SAFE_CASH ]
647647 index = asset_returns .index .intersection (qqq_ohlc .index )
648648 qqq_history = qqq_ohlc .loc [index ].copy ()
649649 returns = asset_returns .reindex (index ).fillna (0.0 )
650650 weights_history = pd .DataFrame (0.0 , index = index , columns = strategy_symbols )
651- portfolio_returns = pd .Series (0.0 , index = index , name = HYBRID_FULL_NAME )
651+ portfolio_returns = pd .Series (0.0 , index = index , name = TQQQ_GROWTH_FULL_NAME )
652652 turnover_history = pd .Series (0.0 , index = index , name = "turnover" )
653653
654654 current_weights : dict [str , float ] = {SAFE_HAVEN : 1.0 }
@@ -712,15 +712,15 @@ def run_hybrid_growth_income_backtest(
712712 SAFE_HAVEN : target_boxx_value ,
713713 "SPYI" : target_spyi_value ,
714714 "QQQI" : target_qqqi_value ,
715- HYBRID_SAFE_CASH : reserved ,
715+ TQQQ_GROWTH_SAFE_CASH : reserved ,
716716 }
717717 target_weights = {
718718 symbol : value / current_equity
719719 for symbol , value in target_values .items ()
720720 if value > 1e-12 and current_equity > 0
721721 }
722722 if not target_weights :
723- target_weights = {HYBRID_SAFE_CASH : 1.0 }
723+ target_weights = {TQQQ_GROWTH_SAFE_CASH : 1.0 }
724724
725725 threshold_weight = rebalance_threshold_ratio
726726 rebalance_needed = any (
@@ -738,7 +738,7 @@ def run_hybrid_growth_income_backtest(
738738 portfolio_returns .at [next_date ] = sum (
739739 weight * float (next_returns .get (symbol , 0.0 ))
740740 for symbol , weight in current_weights .items ()
741- if symbol != HYBRID_SAFE_CASH
741+ if symbol != TQQQ_GROWTH_SAFE_CASH
742742 )
743743 current_equity *= 1.0 + float (portfolio_returns .at [next_date ])
744744
@@ -748,7 +748,7 @@ def run_hybrid_growth_income_backtest(
748748 return portfolio_returns , weights_history , turnover_history
749749
750750
751- def run_semiconductor_rotation_income_backtest (
751+ def run_soxl_soxx_trend_income_backtest (
752752 soxl_prices : pd .Series ,
753753 asset_returns : pd .DataFrame ,
754754 * ,
@@ -772,7 +772,7 @@ def run_semiconductor_rotation_income_backtest(
772772 soxl_series = soxl_prices .loc [index ].copy ()
773773 returns = asset_returns .reindex (index ).fillna (0.0 )
774774 weights_history = pd .DataFrame (0.0 , index = index , columns = strategy_symbols )
775- portfolio_returns = pd .Series (0.0 , index = index , name = SEMICONDUCTOR_FULL_NAME )
775+ portfolio_returns = pd .Series (0.0 , index = index , name = SOXL_SOXX_TREND_FULL_NAME )
776776 turnover_history = pd .Series (0.0 , index = index , name = "turnover" )
777777
778778 current_weights : dict [str , float ] = {SAFE_HAVEN : 1.0 }
@@ -1367,7 +1367,7 @@ def build_strategy_runs(
13671367 ).reindex (master_index )
13681368 soxl_close = etf_frames ["close" ]["SOXL" ].reindex (master_index )
13691369
1370- hybrid_full_returns , hybrid_full_weights , hybrid_full_turnover = run_hybrid_growth_income_backtest (
1370+ hybrid_full_returns , hybrid_full_weights , hybrid_full_turnover = run_tqqq_growth_income_backtest (
13711371 qqq_ohlc ,
13721372 etf_returns_matrix ,
13731373 starting_equity = full_account_equity ,
@@ -1389,7 +1389,7 @@ def build_strategy_runs(
13891389 entry_line_floor = 1.02 ,
13901390 entry_line_cap = 1.08 ,
13911391 )
1392- hybrid_normalized_returns , hybrid_normalized_weights , hybrid_normalized_turnover = run_hybrid_growth_income_backtest (
1392+ hybrid_normalized_returns , hybrid_normalized_weights , hybrid_normalized_turnover = run_tqqq_growth_income_backtest (
13931393 qqq_ohlc ,
13941394 etf_returns_matrix ,
13951395 starting_equity = normalized_account_equity ,
@@ -1412,7 +1412,7 @@ def build_strategy_runs(
14121412 entry_line_cap = 1.08 ,
14131413 )
14141414
1415- semiconductor_full_returns , semiconductor_full_weights , semiconductor_full_turnover = run_semiconductor_rotation_income_backtest (
1415+ semiconductor_full_returns , semiconductor_full_weights , semiconductor_full_turnover = run_soxl_soxx_trend_income_backtest (
14161416 soxl_close ,
14171417 etf_returns_matrix ,
14181418 starting_equity = full_account_equity ,
@@ -1430,7 +1430,7 @@ def build_strategy_runs(
14301430 income_layer_qqqi_weight = 0.70 ,
14311431 income_layer_spyi_weight = 0.30 ,
14321432 )
1433- semiconductor_normalized_returns , semiconductor_normalized_weights , semiconductor_normalized_turnover = run_semiconductor_rotation_income_backtest (
1433+ semiconductor_normalized_returns , semiconductor_normalized_weights , semiconductor_normalized_turnover = run_soxl_soxx_trend_income_backtest (
14341434 soxl_close ,
14351435 etf_returns_matrix ,
14361436 starting_equity = normalized_account_equity ,
@@ -1524,17 +1524,17 @@ def build_strategy_runs(
15241524 strategy_runs = [
15251525 defensive_run ,
15261526 StrategyRun (
1527- strategy_name = HYBRID_FULL_NAME ,
1528- display_name = "hybrid_growth_income ::full" ,
1527+ strategy_name = TQQQ_GROWTH_FULL_NAME ,
1528+ display_name = "tqqq_growth_income ::full" ,
15291529 comparison_layer = FULL_COMPARISON_LAYER ,
15301530 gross_returns = hybrid_full_returns ,
15311531 weights_history = hybrid_full_weights ,
15321532 turnover_history = hybrid_full_turnover ,
15331533 metadata = {"research_group" : "etf_full" , "starting_equity" : full_account_equity , "income_layer" : "on" },
15341534 ),
15351535 StrategyRun (
1536- strategy_name = SEMICONDUCTOR_FULL_NAME ,
1537- display_name = "semiconductor_rotation_income ::full" ,
1536+ strategy_name = SOXL_SOXX_TREND_FULL_NAME ,
1537+ display_name = "soxl_soxx_trend_income ::full" ,
15381538 comparison_layer = FULL_COMPARISON_LAYER ,
15391539 gross_returns = semiconductor_full_returns ,
15401540 weights_history = semiconductor_full_weights ,
@@ -1552,17 +1552,17 @@ def build_strategy_runs(
15521552 metadata = {"research_group" : "baseline" , "group_normalization" : "sector" , "data_assumption" : "official_monthly_v2_alias" },
15531553 ),
15541554 StrategyRun (
1555- strategy_name = HYBRID_NORMALIZED_NAME ,
1556- display_name = "hybrid_growth_income ::no_income" ,
1555+ strategy_name = TQQQ_GROWTH_NORMALIZED_NAME ,
1556+ display_name = "tqqq_growth_income ::no_income" ,
15571557 comparison_layer = NORMALIZED_COMPARISON_LAYER ,
15581558 gross_returns = hybrid_normalized_returns ,
15591559 weights_history = hybrid_normalized_weights ,
15601560 turnover_history = hybrid_normalized_turnover ,
15611561 metadata = {"research_group" : "etf_normalized" , "starting_equity" : normalized_account_equity , "income_layer" : "off" },
15621562 ),
15631563 StrategyRun (
1564- strategy_name = SEMICONDUCTOR_NORMALIZED_NAME ,
1565- display_name = "semiconductor_rotation_income ::no_income" ,
1564+ strategy_name = SOXL_SOXX_TREND_NORMALIZED_NAME ,
1565+ display_name = "soxl_soxx_trend_income ::no_income" ,
15661566 comparison_layer = NORMALIZED_COMPARISON_LAYER ,
15671567 gross_returns = semiconductor_normalized_returns ,
15681568 weights_history = semiconductor_normalized_weights ,
0 commit comments