stale_push_wlin: 仓位分母改为总资产,输出具体手数/股数
仓位计算:
分母:总资产(持仓市值+现金),从portfolio.json+strategy_staleness_report.json读取
非之前用的现金总额
理论仓位:仅基于RR+大盘+品种特性,不受现金限制,纯% of 总资产
当前建议:理论占总资产%→按现金锁死→输出具体手数和股数
报告最终一行:
仓位:理论{theo}%×总资产 | 建议{act}%({N}手({M}股,{cost}元))
Dad要求:仓位是本次操作的仓位,分母是总资产不是现金,
给出仓位后要能直接按手/股操作
This commit is contained in:
+47
-29
@@ -278,10 +278,29 @@ def main():
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 仓位计算
|
||||
# 仓位计算:读取总资产和现金
|
||||
n = len(actionable)
|
||||
def calc_positions(code, price, lot_cost, rr, market_factor, cat):
|
||||
# 理论推荐仓位(基于RR+市场+品种特性)
|
||||
total_assets = 0
|
||||
available_cash = 0
|
||||
try:
|
||||
with open("/home/hmo/web-dashboard/data/strategy_staleness_report.json") as f:
|
||||
sr = json.load(f)
|
||||
port = sr.get("portfolio", {})
|
||||
available_cash = port.get("cash", 0) or 0
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
with open("/home/hmo/web-dashboard/data/portfolio.json") as f:
|
||||
pf = json.load(f)
|
||||
for h in pf.get("holdings", []):
|
||||
mv = h.get("shares", 0) * h.get("price", 0)
|
||||
total_assets += mv
|
||||
total_assets += available_cash
|
||||
except Exception:
|
||||
total_assets = available_cash * 5 # fallback
|
||||
|
||||
def calc_position(lot_cost, rr, market_factor, cat, code=""):
|
||||
# 理论推荐仓位(% of 总资产) — 仅基于RR+市场+品种,不受现金限制
|
||||
if rr >= 5:
|
||||
theo_pct = 25
|
||||
elif rr >= 3:
|
||||
@@ -302,38 +321,35 @@ def main():
|
||||
theo_pct = int(theo_pct * 0.85)
|
||||
theo_pct = max(5, min(30, theo_pct))
|
||||
|
||||
# 当前推荐仓位(基于实际现金)
|
||||
# 可操作多只时,每只分配比例降低
|
||||
if n >= 5:
|
||||
share_pct = theo_pct * 0.5
|
||||
elif n >= 3:
|
||||
share_pct = theo_pct * 0.7
|
||||
elif n >= 2:
|
||||
share_pct = theo_pct * 0.85
|
||||
else:
|
||||
share_pct = theo_pct
|
||||
share_pct = max(5, min(theo_pct, share_pct))
|
||||
|
||||
budget = cash * share_pct / 100
|
||||
# 当前建议仓位:理论占总资产% → 按现金锁死
|
||||
ideal_budget = total_assets * theo_pct / 100
|
||||
# 可操作N只时,现金分配不超过 available_cash / n * 1.5
|
||||
max_use_cash = (available_cash / max(n, 1)) * 1.5
|
||||
budget = min(ideal_budget, max_use_cash, available_cash)
|
||||
lots = int(budget / lot_cost) if lot_cost > 0 else 0
|
||||
if lots == 0 and lot_cost > 0 and budget > 0:
|
||||
# 预算不够1手 → 推荐至少1手
|
||||
|
||||
if lots == 0 and lot_cost > 0 and budget > lot_cost * 0.5:
|
||||
# 预算超过半手 → 至少1手
|
||||
lots = 1
|
||||
actual_pct = round(lots * lot_cost / cash * 100) if cash > 0 else 0
|
||||
|
||||
lot_cost_total = lots * lot_cost
|
||||
if lots == 0:
|
||||
pct_actual = 0
|
||||
elif total_assets > 0:
|
||||
pct_actual = round(lot_cost_total / total_assets * 100)
|
||||
else:
|
||||
actual_pct = round(lots * lot_cost / cash * 100) if cash > 0 else 0
|
||||
pct_actual = 0
|
||||
|
||||
if lots == 0:
|
||||
lots_display = "预算不足1手"
|
||||
elif budget < lot_cost and lots == 1:
|
||||
lots_display = f"至少{lots}手"
|
||||
details = f"预算不足1手({budget:,.0f}/{lot_cost:,.0f}元)"
|
||||
else:
|
||||
lots_display = f"{lots}手"
|
||||
shares = lots * (200 if code.startswith("688") else 100)
|
||||
details = f"{lots}手({shares}股,{lot_cost_total:,.0f}元)"
|
||||
|
||||
return theo_pct, actual_pct, lots_display, lots * lot_cost
|
||||
return theo_pct, pct_actual, details, lots, lot_cost_total
|
||||
|
||||
# 标准格式:每个可操作标的 — 大盘/行业/个股三面 + 仓位
|
||||
lines.append(f"【💡 操作建议】(当前{n}只自选可操作 | 现金{cash:,.0f}元)")
|
||||
lines.append(f"【💡 操作建议】(当前{n}只自选可操作 | 总资产{total_assets:,.0f}元 现金{available_cash:,.0f}元)")
|
||||
for s in actionable:
|
||||
name, code, price, buy_low, buy_high, lot, ratio = s
|
||||
d = code_data.get(code, {})
|
||||
@@ -390,7 +406,9 @@ def main():
|
||||
analysis = " | ".join(p for p in parts if p)
|
||||
|
||||
# 仓位计算
|
||||
theo_pct, actual_pct, lots_display, lots_cost_total = calc_positions(code, price, lot, rr, market_factor, cat)
|
||||
theo_pct, actual_pct, details, lots, lot_cost_total = calc_position(
|
||||
lot, rr, market_factor, cat, code
|
||||
)
|
||||
|
||||
pfx = "" if len(code) == 6 else "HK$"
|
||||
lines.append(
|
||||
@@ -398,10 +416,10 @@ def main():
|
||||
f"1手{lot:,.0f}元 RR={rr:.1f} 损{sl} 盈{tp}\n"
|
||||
f" {analysis}\n"
|
||||
f" 技术{ss['强撑']}→{ss['弱撑']}→{ss['弱压']}→{ss['强压']} | 信号{sig}\n"
|
||||
f" 仓位:理论推荐{theo_pct}% | 当前建议{actual_pct}%({lots_display}≈{lots_cost_total:,.0f}元)"
|
||||
f" 仓位:理论{theo_pct}%×总资产 | 建议{actual_pct}%({details})"
|
||||
)
|
||||
|
||||
lines.insert(0, f"【知微】自选买入提醒 {now} | 现金{cash:,.0f}元")
|
||||
lines.insert(0, f"【知微】自选买入提醒 {now} | 总资产{total_assets:,.0f}元")
|
||||
out = "\n".join(lines)
|
||||
print(out)
|
||||
push_to_xmpp(out)
|
||||
|
||||
Reference in New Issue
Block a user