stale_push_wlin: 仓位分母改为总资产,输出具体手数/股数

仓位计算:
  分母:总资产(持仓市值+现金),从portfolio.json+strategy_staleness_report.json读取
          非之前用的现金总额
  理论仓位:仅基于RR+大盘+品种特性,不受现金限制,纯% of 总资产
  当前建议:理论占总资产%→按现金锁死→输出具体手数和股数

报告最终一行:
  仓位:理论{theo}%×总资产 | 建议{act}%({N}手({M}股,{cost}元))

Dad要求:仓位是本次操作的仓位,分母是总资产不是现金,
给出仓位后要能直接按手/股操作
This commit is contained in:
知微
2026-06-24 10:08:05 +08:00
parent 3ba2b044d7
commit eb86a9091e
+47 -29
View File
@@ -278,10 +278,29 @@ def main():
except Exception: except Exception:
pass pass
# 仓位计算 # 仓位计算:读取总资产和现金
n = len(actionable) n = len(actionable)
def calc_positions(code, price, lot_cost, rr, market_factor, cat): total_assets = 0
# 理论推荐仓位(基于RR+市场+品种特性) 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: if rr >= 5:
theo_pct = 25 theo_pct = 25
elif rr >= 3: elif rr >= 3:
@@ -302,38 +321,35 @@ def main():
theo_pct = int(theo_pct * 0.85) theo_pct = int(theo_pct * 0.85)
theo_pct = max(5, min(30, theo_pct)) theo_pct = max(5, min(30, theo_pct))
# 当前推荐仓位(基于实际现金) # 当前建议仓位:理论占总资产% → 按现金锁死
# 可操作多只时,每只分配比例降低 ideal_budget = total_assets * theo_pct / 100
if n >= 5: # 可操作N只时,现金分配不超过 available_cash / n * 1.5
share_pct = theo_pct * 0.5 max_use_cash = (available_cash / max(n, 1)) * 1.5
elif n >= 3: budget = min(ideal_budget, max_use_cash, available_cash)
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
lots = int(budget / lot_cost) if lot_cost > 0 else 0 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 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: else:
actual_pct = round(lots * lot_cost / cash * 100) if cash > 0 else 0 pct_actual = 0
if lots == 0: if lots == 0:
lots_display = "预算不足1手" details = f"预算不足1手{budget:,.0f}/{lot_cost:,.0f}元)"
elif budget < lot_cost and lots == 1:
lots_display = f"至少{lots}"
else: 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: for s in actionable:
name, code, price, buy_low, buy_high, lot, ratio = s name, code, price, buy_low, buy_high, lot, ratio = s
d = code_data.get(code, {}) d = code_data.get(code, {})
@@ -390,7 +406,9 @@ def main():
analysis = " | ".join(p for p in parts if p) 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$" pfx = "" if len(code) == 6 else "HK$"
lines.append( lines.append(
@@ -398,10 +416,10 @@ def main():
f"1手{lot:,.0f}元 RR={rr:.1f}{sl}{tp}\n" f"1手{lot:,.0f}元 RR={rr:.1f}{sl}{tp}\n"
f" {analysis}\n" f" {analysis}\n"
f" 技术{ss['强撑']}{ss['弱撑']}{ss['弱压']}{ss['强压']} | 信号{sig}\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) out = "\n".join(lines)
print(out) print(out)
push_to_xmpp(out) push_to_xmpp(out)