Prefer stock display names in IPO reports
Request: Rename the report display-name rule from 中文名 to 股票名, prefer Chinese stock-style short names, and allow sourced English stock names such as MERDEKAGOLD-DRS when no Chinese short name exists. Changes: - Update the hk-ipo-analyst skill to require a 股票名 column and document English stock-name fallback. - Derive missing stock_short_name values from archived market-heat source-page stock names in the analysis dataset. - Preserve source-page stock names into ipo_master when future market-heat archives encounter blank stock_short_name values. - Rename the single-ticker report display helper to stock_display_name. - Refresh the latest report and README so 06228 displays as MERDEKAGOLD-DRS and tables use 股票名. Verification: - python3 /root/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/hk-ipo-analyst - git diff --check - .venv/bin/python -m py_compile scripts/archive_t0_5_market_heat.py scripts/build_analysis_dataset.py scripts/generate_ipo_report.py - Rebuilt analysis_model_v0_dataset.csv for 2026-06-23T10:59:36Z - Verified 06228 stock_short_name is MERDEKAGOLD-DRS and latest README matches the dated report
This commit is contained in:
@@ -306,6 +306,16 @@ def upsert_rows(
|
||||
f"Stock name on source page: {row.stock_name}. Prospectus URL shown by source: {row.prospectus_url}",
|
||||
),
|
||||
)
|
||||
if row.stock_name:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE ipo_master
|
||||
SET stock_short_name = ?, data_as_of = ?
|
||||
WHERE ticker = ?
|
||||
AND (stock_short_name IS NULL OR TRIM(stock_short_name) = '')
|
||||
""",
|
||||
(row.stock_name, as_of, row.ticker),
|
||||
)
|
||||
written += 1
|
||||
return written
|
||||
|
||||
@@ -325,6 +335,7 @@ def main() -> int:
|
||||
selected = selected_tickers(args.tickers, parsed_rows, conn)
|
||||
written = upsert_rows(conn, parsed_rows, selected, local_path, file_sha256, args.url, as_of, args.stage)
|
||||
export_snapshot(conn, "ipo_market_heat", "ticker, observed_at")
|
||||
export_snapshot(conn, "ipo_master", "ticker")
|
||||
export_snapshot(conn, "source_refs", "source_id")
|
||||
|
||||
subprocess.run(
|
||||
|
||||
@@ -71,6 +71,14 @@ def offer_size_hkd_m(row: sqlite3.Row) -> float | None:
|
||||
return None
|
||||
|
||||
|
||||
def stock_name_from_market_heat_notes(notes: str | None) -> str | None:
|
||||
if not notes or "Stock name on source page:" not in notes:
|
||||
return None
|
||||
value = notes.split("Stock name on source page:", 1)[1].strip()
|
||||
value = value.split(". Prospectus URL shown by source:", 1)[0].strip()
|
||||
return value or None
|
||||
|
||||
|
||||
def success_rate(row: sqlite3.Row) -> float | None:
|
||||
valid = as_int(row["valid_applications"])
|
||||
successful = as_int(row["successful_applications"])
|
||||
@@ -420,6 +428,7 @@ def fetch_rows(conn: sqlite3.Connection) -> list[sqlite3.Row]:
|
||||
h.provider AS t0_5_provider,
|
||||
h.margin_subscription_multiple AS t0_5_margin_subscription_multiple,
|
||||
h.source_id AS t0_5_source_id,
|
||||
h.notes AS market_heat_notes,
|
||||
eh.one_hand_win_rate_pct AS external_one_hand_win_rate_pct,
|
||||
eh.public_oversubscription_times AS external_public_oversubscription_times,
|
||||
eh.grey_market_return_pct AS external_grey_market_return_pct,
|
||||
@@ -461,13 +470,14 @@ def build_records(rows: list[sqlite3.Row], as_of: str) -> list[dict[str, Any]]:
|
||||
total_score = t0_score_value + (t1_score_value if structured_t1 else 0)
|
||||
t0_plus_t0_5_score = t0_score_value + t0_5_score_value if t0_5_score_value is not None else None
|
||||
size = offer_size_hkd_m(row)
|
||||
stock_short_name = row["stock_short_name"] or stock_name_from_market_heat_notes(row["market_heat_notes"])
|
||||
record: dict[str, Any] = {
|
||||
"model_version": MODEL_VERSION,
|
||||
"analysis_as_of": as_of,
|
||||
"ticker": row["ticker"],
|
||||
"company_name_en": row["company_name_en"],
|
||||
"company_name_zh": row["company_name_zh"],
|
||||
"stock_short_name": row["stock_short_name"],
|
||||
"stock_short_name": stock_short_name,
|
||||
"board": row["board"],
|
||||
"status": row["status"],
|
||||
"listing_date": row["listing_date"],
|
||||
|
||||
@@ -150,8 +150,8 @@ def fmt_int(value: int | None) -> str:
|
||||
return f"{value:,}"
|
||||
|
||||
|
||||
def chinese_display_name(record: dict[str, str]) -> str:
|
||||
return record.get("stock_short_name") or record.get("company_name_zh") or ""
|
||||
def stock_display_name(record: dict[str, str]) -> str:
|
||||
return record.get("stock_short_name") or record.get("company_name_zh") or record.get("company_name_en") or ""
|
||||
|
||||
|
||||
def company_display_name(record: dict[str, str]) -> str:
|
||||
@@ -425,7 +425,7 @@ def build_report(record: dict[str, str], rows: list[dict[str, str]], stage: str,
|
||||
paths = source_paths(record, stage)
|
||||
source_lines = [f"- `{path}`" for path in paths] or ["- 本阶段没有记录来源路径。"]
|
||||
company_name = company_display_name(record)
|
||||
title_name = chinese_display_name(record) or record.get("company_name_en") or ""
|
||||
title_name = stock_display_name(record)
|
||||
title_prefix = f"{ticker} {title_name}" if title_name else ticker
|
||||
|
||||
lines = [
|
||||
|
||||
Reference in New Issue
Block a user