Skip to content

Commit 9cf409a

Browse files
committed
Load semiconductor rotation income from UsEquityStrategies
1 parent 372862b commit 9cf409a

3 files changed

Lines changed: 14 additions & 155 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Quant system on LongPort OpenAPI and Google Cloud Run.
1111

1212
This strategy repo now depends on `QuantPlatformKit` for LongPort token handling, context bootstrap, account snapshot access, market-data access, and order submission. Cloud Run still deploys this strategy repo only.
13+
The current `semiconductor_rotation_income` allocation logic is loaded from `UsEquityStrategies`. LongBridgePlatform keeps the LongPort runtime, token refresh, execution, and notification flow.
1314

1415
**Layers**
1516

@@ -178,6 +179,7 @@ IAM: the Cloud Run service account needs **Secret Manager Admin** (or Secret Acc
178179
基于 LongPort OpenAPI 和 Google Cloud Run 的量化交易系统。
179180

180181
这个策略仓库现在通过 `QuantPlatformKit` 复用 LongPort token 处理、上下文初始化、账户快照、行情读取和下单逻辑。Cloud Run 仍然只部署这个策略仓库本身。
182+
当前 `semiconductor_rotation_income` 的仓位与调仓计算逻辑已经改为从 `UsEquityStrategies` 加载;LongBridgePlatform 继续保留 LongPort 运行时、token 刷新、执行和通知流程。
181183

182184
**层级**
183185

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
flask
22
gunicorn
33
quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@v0.5.0
4+
us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@v0.4.0
45
pandas
56
requests
67
pytz

strategy/allocation.py

Lines changed: 11 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,13 @@
11
"""Allocation and plan helpers for LongBridgePlatform."""
22

3-
from __future__ import annotations
4-
5-
import numpy as np
6-
7-
8-
def get_dynamic_allocation(
9-
total_equity_usd,
10-
*,
11-
small_account_deploy_ratio,
12-
mid_account_deploy_ratio,
13-
large_account_deploy_ratio,
14-
trade_layer_decay_coeff,
15-
):
16-
if total_equity_usd <= 10000:
17-
return small_account_deploy_ratio
18-
19-
if total_equity_usd <= 80000:
20-
return float(
21-
np.interp(
22-
total_equity_usd,
23-
[10000, 80000],
24-
[small_account_deploy_ratio, mid_account_deploy_ratio],
25-
)
26-
)
27-
28-
if total_equity_usd <= 180000:
29-
return float(
30-
np.interp(
31-
total_equity_usd,
32-
[80000, 180000],
33-
[mid_account_deploy_ratio, large_account_deploy_ratio],
34-
)
35-
)
36-
37-
decayed_ratio = large_account_deploy_ratio - (
38-
trade_layer_decay_coeff * np.log10(total_equity_usd / 180000)
39-
)
40-
return max(0.0, decayed_ratio)
41-
42-
43-
def get_income_layer_ratio(
44-
total_equity_usd,
45-
*,
46-
income_layer_start_usd,
47-
income_layer_max_ratio,
48-
):
49-
if total_equity_usd <= income_layer_start_usd:
50-
return 0.0
51-
52-
if total_equity_usd <= (income_layer_start_usd * 2):
53-
return float(
54-
np.interp(
55-
total_equity_usd,
56-
[income_layer_start_usd, income_layer_start_usd * 2],
57-
[0.0, income_layer_max_ratio],
58-
)
59-
)
60-
61-
return income_layer_max_ratio
62-
63-
64-
def build_rebalance_plan(
65-
indicators,
66-
account_state,
67-
*,
68-
trend_ma_window,
69-
translator,
70-
cash_reserve_ratio,
71-
min_trade_ratio,
72-
min_trade_floor,
73-
rebalance_threshold_ratio,
74-
small_account_deploy_ratio,
75-
mid_account_deploy_ratio,
76-
large_account_deploy_ratio,
77-
trade_layer_decay_coeff,
78-
income_layer_start_usd,
79-
income_layer_max_ratio,
80-
income_layer_qqqi_weight,
81-
income_layer_spyi_weight,
82-
):
83-
strategy_assets = ["SOXL", "SOXX", "BOXX", "QQQI", "SPYI"]
84-
available_cash = account_state["available_cash"]
85-
market_values = account_state["market_values"]
86-
quantities = account_state["quantities"]
87-
sellable_quantities = account_state["sellable_quantities"]
88-
total_strategy_equity = account_state["total_strategy_equity"]
89-
current_min_trade = max(min_trade_floor, total_strategy_equity * min_trade_ratio)
90-
91-
current_income_layer_value = market_values["QQQI"] + market_values["SPYI"]
92-
income_layer_ratio = get_income_layer_ratio(
93-
total_strategy_equity,
94-
income_layer_start_usd=income_layer_start_usd,
95-
income_layer_max_ratio=income_layer_max_ratio,
96-
)
97-
desired_income_layer_value = total_strategy_equity * income_layer_ratio
98-
locked_income_layer_value = max(current_income_layer_value, desired_income_layer_value)
99-
income_layer_add_value = max(0.0, locked_income_layer_value - current_income_layer_value)
100-
core_equity = max(0.0, total_strategy_equity - locked_income_layer_value)
101-
deploy_ratio = get_dynamic_allocation(
102-
core_equity,
103-
small_account_deploy_ratio=small_account_deploy_ratio,
104-
mid_account_deploy_ratio=mid_account_deploy_ratio,
105-
large_account_deploy_ratio=large_account_deploy_ratio,
106-
trade_layer_decay_coeff=trade_layer_decay_coeff,
107-
)
108-
deployed_capital = core_equity * deploy_ratio
109-
deploy_ratio_text = f"{deploy_ratio * 100:.1f}%"
110-
income_ratio_text = f"{income_layer_ratio * 100:.1f}%"
111-
income_locked_ratio_text = (
112-
f"{(locked_income_layer_value / total_strategy_equity) * 100:.1f}%"
113-
if total_strategy_equity > 0
114-
else "0.0%"
115-
)
116-
117-
soxl_price = indicators["soxl"]["price"]
118-
soxl_ma_trend = indicators["soxl"]["ma_trend"]
119-
active_risk_asset = "SOXL" if soxl_price > soxl_ma_trend else "SOXX"
120-
market_status = (
121-
f"🚀 RISK-ON ({active_risk_asset})"
122-
if active_risk_asset == "SOXL"
123-
else "🛡️ DE-LEVER (SOXX)"
124-
)
125-
signal_message = (
126-
translator("signal_risk_on", window=trend_ma_window, ratio=deploy_ratio_text)
127-
if active_risk_asset == "SOXL"
128-
else translator("signal_delever", window=trend_ma_window, ratio=deploy_ratio_text)
129-
)
130-
131-
targets = {
132-
"SOXL": deployed_capital if active_risk_asset == "SOXL" else 0.0,
133-
"SOXX": deployed_capital if active_risk_asset == "SOXX" else 0.0,
134-
"QQQI": market_values["QQQI"] + (income_layer_add_value * income_layer_qqqi_weight),
135-
"SPYI": market_values["SPYI"] + (income_layer_add_value * income_layer_spyi_weight),
136-
"BOXX": max(0.0, core_equity - deployed_capital),
137-
}
138-
139-
return {
140-
"strategy_assets": strategy_assets,
141-
"available_cash": available_cash,
142-
"market_values": market_values,
143-
"quantities": quantities,
144-
"sellable_quantities": sellable_quantities,
145-
"total_strategy_equity": total_strategy_equity,
146-
"current_min_trade": current_min_trade,
147-
"targets": targets,
148-
"market_status": market_status,
149-
"signal_message": signal_message,
150-
"deploy_ratio_text": deploy_ratio_text,
151-
"income_ratio_text": income_ratio_text,
152-
"income_locked_ratio_text": income_locked_ratio_text,
153-
"active_risk_asset": active_risk_asset,
154-
"investable_cash": max(0, available_cash - (total_strategy_equity * cash_reserve_ratio)),
155-
"threshold_value": total_strategy_equity * rebalance_threshold_ratio,
156-
}
157-
3+
from us_equity_strategies.strategies.semiconductor_rotation_income import (
4+
build_rebalance_plan,
5+
get_dynamic_allocation,
6+
get_income_layer_ratio,
7+
)
8+
9+
__all__ = [
10+
"build_rebalance_plan",
11+
"get_dynamic_allocation",
12+
"get_income_layer_ratio",
13+
]

0 commit comments

Comments
 (0)