From 3ba2b044d76e3130d42cbd79fc80843cd18492ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Wed, 24 Jun 2026 10:00:52 +0800 Subject: [PATCH] =?UTF-8?q?stale=5Fpush=5Fwlin:=20=E6=8E=A8=E8=8D=90?= =?UTF-8?q?=E5=8A=A0=E7=90=86=E8=AE=BA=E4=BB=93=E4=BD=8D+=E5=BD=93?= =?UTF-8?q?=E5=89=8D=E5=BB=BA=E8=AE=AE=E4=BB=93=E4=BD=8D(=E5=9F=BA?= =?UTF-8?q?=E4=BA=8E=E7=8E=B0=E9=87=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 每只推荐新增第四行: 仓位:理论推荐{theo_pct}% | 当前建议{actual_pct}%({N}手≈预算) 仓位计算: 理论 — 基于RR(8-25%) + 大盘(±20%) + 品种特性(±20%) 当前 — 理论×多只稀释系数 + 按实际现金计算可买手数 兜底 — 预算不够1手时推荐至少1手 Dad要求:买卖不能不写仓位,理论仓位不受现金限制, 当前建议仓位根据portfolio.json实际现金计算 --- scripts/stale_push_wlin.py | 72 ++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/scripts/stale_push_wlin.py b/scripts/stale_push_wlin.py index 78478c7..38b4db9 100644 --- a/scripts/stale_push_wlin.py +++ b/scripts/stale_push_wlin.py @@ -278,8 +278,62 @@ def main(): except Exception: pass - # 标准格式:每个可操作标的 — 大盘/行业/个股三面+消息/基本面/技术面 - lines.append(f"【💡 操作建议】(当前{len(actionable)}只自选可操作)") + # 仓位计算 + n = len(actionable) + def calc_positions(code, price, lot_cost, rr, market_factor, cat): + # 理论推荐仓位(基于RR+市场+品种特性) + if rr >= 5: + theo_pct = 25 + elif rr >= 3: + theo_pct = 18 + elif rr >= 2: + theo_pct = 12 + else: + theo_pct = 8 + if "偏弱" in market_factor: + theo_pct = int(theo_pct * 0.8) + elif "偏强" in market_factor: + theo_pct = int(theo_pct * 1.15) + if cat in ("蓝筹", "白马"): + theo_pct = int(theo_pct * 1.2) + elif cat in ("题材", "短线"): + theo_pct = int(theo_pct * 0.6) + elif cat in ("高波动", "成长"): + 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 + lots = int(budget / lot_cost) if lot_cost > 0 else 0 + if lots == 0 and lot_cost > 0 and budget > 0: + # 预算不够1手 → 推荐至少1手 + lots = 1 + actual_pct = round(lots * lot_cost / cash * 100) if cash > 0 else 0 + else: + actual_pct = round(lots * lot_cost / cash * 100) if cash > 0 else 0 + + if lots == 0: + lots_display = "预算不足1手" + elif budget < lot_cost and lots == 1: + lots_display = f"至少{lots}手" + else: + lots_display = f"{lots}手" + + return theo_pct, actual_pct, lots_display, lots * lot_cost + + # 标准格式:每个可操作标的 — 大盘/行业/个股三面 + 仓位 + lines.append(f"【💡 操作建议】(当前{n}只自选可操作 | 现金{cash:,.0f}元)") for s in actionable: name, code, price, buy_low, buy_high, lot, ratio = s d = code_data.get(code, {}) @@ -289,9 +343,9 @@ def main(): sig = d.get("timing_signal", "") sector = d.get("sector_context", "") tech = d.get("tech_snapshot", "") - factors = d.get("signal_factors", []) - cat = d.get("stock_category", "") note = d.get("note", "") + d_factors = d.get("signal_factors", []) + cat = d.get("stock_category", "") # 提取技术位 ss = {"强撑":"-", "弱撑":"-", "弱压":"-", "强压":"-"} @@ -307,9 +361,9 @@ def main(): pe_str = f"PE{pe:.0f}" if pe else "" eps_str = f"EPS{eps:.2f}" if eps else "" - # 从 signal_factors 或 tag 提取各维度 + # 从 signal_factors 提取各维度 def _match_factor(prefix): - for f in factors: + for f in d_factors: if f.startswith(prefix): return f return "" @@ -335,12 +389,16 @@ 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) + pfx = "" if len(code) == 6 else "HK$" lines.append( f" {name}({code}) {pfx}{price:.2f} 买区{buy_low}~{buy_high} | " f"1手{lot:,.0f}元 RR={rr:.1f} 损{sl} 盈{tp}\n" f" {analysis}\n" - f" 技术{ss['强撑']}→{ss['弱撑']}→{ss['弱压']}→{ss['强压']} | 信号{sig}" + f" 技术{ss['强撑']}→{ss['弱撑']}→{ss['弱压']}→{ss['强压']} | 信号{sig}\n" + f" 仓位:理论推荐{theo_pct}% | 当前建议{actual_pct}%({lots_display}≈{lots_cost_total:,.0f}元)" ) lines.insert(0, f"【知微】自选买入提醒 {now} | 现金{cash:,.0f}元")