Add T0 analyst reports for active IPOs

Request:
- Analyze HK IPO ticker 01392 with the analyst skill.
- Preserve the in-flight 06132 archive/report work already created for the prior request.

Changes:
- Archived official HKEX prospectus PDFs and extracted text for 01392 and 06132.
- Seeded structured T0 facts into the SQLite archive and refreshed CSV snapshots and sync state.
- Rebuilt the v0 analysis dataset and model calibration report.
- Generated Simplified Chinese T0 prospectus-stage analyst reports for 01392 and 06132.
- Adjusted report stage calendars so T2 uses the previous business day before D1 when listing is separated from allocation by a weekend.

Verification:
- Compiled modified Python scripts with in-memory syntax checks.
- Ran SQLite quick_check and foreign_key_check.
- Confirmed DB row counts match CSV snapshots for key tables.
- Verified 01392/06132 source paths are repo-relative, raw files exist, hashes match, and PDF text manifest rows are ok.
- Ran git diff --cached --check.

Next useful context:
- 01392 T1 is due on 2026-06-18; rerun analyst after allotment results are archived.
- 06132 T1 is due on 2026-06-22; rerun analyst after allotment results are archived.
This commit is contained in:
2026-06-15 14:51:44 +00:00
parent 907e30d9da
commit 77b405e4f3
18 changed files with 45869 additions and 2760 deletions
+3 -2
View File
@@ -427,9 +427,10 @@ def parse_prospectus_facts(local_path: str) -> ProspectusFacts:
over_allotment = round(global_shares * 0.15)
public_pct = round(hk_shares / global_shares, 4) if global_shares and hk_shares else None
allotment_date = (
date_after(r"Announcement of.*?Offer Price", text)
or date_after(r"Announcement of", text)
date_after(r"Announcement of the level of indications.*?basis of allocation", text)
or date_after(r"The results of allocations", text)
or date_after(r"Announcement of", text)
or date_after(r"Announcement of.*?Offer Price", text)
)
return ProspectusFacts(
application_start_date=date_after(r"Hong Kong Public Offering commences", text),
+27 -5
View File
@@ -7,7 +7,7 @@ import argparse
import csv
import sys
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import datetime, timedelta, timezone
from pathlib import Path
from statistics import mean, median
from typing import Any
@@ -150,6 +150,22 @@ def fmt_int(value: int | None) -> str:
return f"{value:,}"
def parse_date(value: str) -> datetime | None:
if not value:
return None
try:
return datetime.fromisoformat(value)
except ValueError:
return None
def previous_business_date(value: datetime) -> datetime:
day = value - timedelta(days=1)
while day.weekday() >= 5:
day -= timedelta(days=1)
return day
def determine_stage(record: dict[str, str], requested_stage: str) -> str:
if requested_stage == AUTO_STAGE:
return T1_STAGE if as_bool(record["has_structured_t1"]) else T0_STAGE
@@ -292,10 +308,16 @@ def stage_calendar_table(record: dict[str, str]) -> str:
application_end = fmt_value(record["application_end_date"])
allotment_date = fmt_value(record["allotment_results_expected_date"])
listing_date = fmt_value(record["listing_date"])
if allotment_date != "未记录":
t2_date = f"{allotment_date} 分配结果公布后"
elif listing_date != "未记录":
t2_date = "D1 前一个交易日;精确日期未归档"
listed = parse_date(record["listing_date"])
allotment = parse_date(record["allotment_results_expected_date"])
if listed:
previous = previous_business_date(listed)
if allotment and previous.date() == allotment.date():
t2_date = f"{previous.date().isoformat()} 分配结果公布后 / D1 前一交易日"
else:
t2_date = f"{previous.date().isoformat()},预计 D1 前一交易日"
elif allotment:
t2_date = f"{allotment.date().isoformat()} 分配结果公布后"
else:
t2_date = "未记录"