From eb86a9091ef0e3a3f1c7576101f99ecb2178d748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Wed, 24 Jun 2026 10:08:05 +0800 Subject: [PATCH] =?UTF-8?q?stale=5Fpush=5Fwlin:=20=E4=BB=93=E4=BD=8D?= =?UTF-8?q?=E5=88=86=E6=AF=8D=E6=94=B9=E4=B8=BA=E6=80=BB=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=EF=BC=8C=E8=BE=93=E5=87=BA=E5=85=B7=E4=BD=93=E6=89=8B=E6=95=B0?= =?UTF-8?q?/=E8=82=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仓位计算: 分母:总资产(持仓市值+现金),从portfolio.json+strategy_staleness_report.json读取 非之前用的现金总额 理论仓位:仅基于RR+大盘+品种特性,不受现金限制,纯% of 总资产 当前建议:理论占总资产%→按现金锁死→输出具体手数和股数 报告最终一行: 仓位:理论{theo}%×总资产 | 建议{act}%({N}手({M}股,{cost}元)) Dad要求:仓位是本次操作的仓位,分母是总资产不是现金, 给出仓位后要能直接按手/股操作 --- scripts/stale_push_wlin.py | 76 +++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/scripts/stale_push_wlin.py b/scripts/stale_push_wlin.py index 38b4db9..9767756 100644 --- a/scripts/stale_push_wlin.py +++ b/scripts/stale_push_wlin.py @@ -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)