Clarify IPO short-exit strategy horizon
Request: - Emphasize that the analyst model is for selling allocated IPO shares in T2 grey market or on D1, not for long-term holding. Changes: - Add explicit T2/D1 sell discipline to the analyst skill. - Update ipo_score_v0 targets and holding policy so D1 sell return is primary and T2 is the intended extension when reliable grey-market data exists. - Clarify that D5/D20/D60 are review labels only, not planned holding targets. - Update the model report, single-ticker report generator, README, and the 06106 report language to reflect the short-exit horizon. Verification: - Rebuilt the model report with the same dataset timestamp and confirmed the analysis dataset did not change. - Ran py_compile for build_analysis_dataset.py and generate_ipo_report.py. - Generated a 06106 dry-run report showing T2/D1 exit discipline. - Ran git diff --check. Next useful context: - T2 is still disabled in v0 until archivist approves a reliable grey-market data source; D1 remains the live modeled sell label.
This commit is contained in:
@@ -611,9 +611,9 @@ def write_report(
|
||||
"",
|
||||
"## What This Model Does",
|
||||
"",
|
||||
"This is the first analyst model built from the downloaded archive. It creates a repeatable feature table, scores each IPO using stage-safe rules, and calibrates the score buckets against archived D1 outcomes. It is intentionally transparent: the output includes every score component and the archived source paths used for each ticker.",
|
||||
"This is the first analyst model built from the downloaded archive. It creates a repeatable feature table, scores each IPO using stage-safe rules, and calibrates the score buckets against archived D1 sell outcomes. It is intentionally transparent: the output includes every score component and the archived source paths used for each ticker.",
|
||||
"",
|
||||
"The model does not use grey-market data in v0 because T2 currently has no approved reproducible source. It also does not use post-listing returns as inputs; returns are labels only.",
|
||||
"The model is built for a short IPO allocation trade: sell in T2 grey market when reliable executable data exists, or sell on D1 otherwise. It does not use grey-market data in v0 because T2 currently has no approved reproducible source. It also does not use post-listing returns as inputs; D1 is the primary sell label, while D5/D20/D60 are review labels only.",
|
||||
"",
|
||||
"## Data Inventory",
|
||||
"",
|
||||
@@ -652,7 +652,8 @@ def write_report(
|
||||
"1. Run `scripts/build_analysis_dataset.py` after archivist updates the database.",
|
||||
"2. Use `t0_score` for prospectus-stage watchlisting.",
|
||||
"3. Use `total_score`, `decision_band`, and `calibrated_d1_positive_rate` for T1-stage subscription cards.",
|
||||
"4. Treat D1/D5/D20/D60 columns as review labels only, never as prediction inputs.",
|
||||
"4. Frame live decisions around a T2 or D1 sell, not long-term holding.",
|
||||
"5. Treat D5/D20/D60 columns as review labels only, never as prediction inputs or holding targets.",
|
||||
"",
|
||||
"## Known Gaps",
|
||||
"",
|
||||
|
||||
@@ -216,13 +216,13 @@ def action_for_decision(decision: str) -> str:
|
||||
actions = {
|
||||
"weak_or_avoid": "Avoid at T0 unless later T1 demand changes the setup.",
|
||||
"neutral": "Wait for T1 allotment demand before subscribing.",
|
||||
"positive_watch": "Watch positively, but wait for T1 confirmation before sizing.",
|
||||
"strong_watch": "Strong watch at T0, still pending T1 demand confirmation.",
|
||||
"positive_watch": "Watch positively, but wait for T1 confirmation before sizing for a T2/D1 exit.",
|
||||
"strong_watch": "Strong watch at T0, still pending T1 demand confirmation for a T2/D1 exit.",
|
||||
"avoid": "Avoid subscription.",
|
||||
"avoid_or_wait": "Avoid or wait; do not size without a stronger catalyst.",
|
||||
"watch_or_small": "Small subscription only if execution constraints are favorable.",
|
||||
"selective_subscribe": "Selective subscription with disciplined sizing.",
|
||||
"high_conviction_subscribe": "Subscribe, subject to allocation and liquidity discipline.",
|
||||
"watch_or_small": "Small subscription only if execution constraints support a T2/D1 exit.",
|
||||
"selective_subscribe": "Selective subscription with disciplined T2/D1 sell sizing.",
|
||||
"high_conviction_subscribe": "Subscribe, subject to allocation, liquidity, and T2/D1 sell discipline.",
|
||||
}
|
||||
return actions[decision]
|
||||
|
||||
@@ -360,6 +360,7 @@ def build_report(record: dict[str, str], rows: list[dict[str, str]], stage: str,
|
||||
f"- Model dataset as of: `{dataset_as_of}`",
|
||||
f"- Rule version: `{model_version}`",
|
||||
f"- Rule path: `{MODEL_RULE_PATH.as_posix()}`",
|
||||
"- Strategy horizon: short IPO subscription trade; intended exit is T2 grey market if reliable, otherwise D1.",
|
||||
f"- Decision: `{decision}`",
|
||||
f"- PM action: {action_for_decision(decision)}",
|
||||
f"- {score_label}: `{score}`",
|
||||
@@ -370,12 +371,14 @@ def build_report(record: dict[str, str], rows: list[dict[str, str]], stage: str,
|
||||
"",
|
||||
facts_table(record, stage),
|
||||
"",
|
||||
"## Model Inference",
|
||||
"## Short-Exit Model Inference",
|
||||
"",
|
||||
f"- D1 positive probability: {fmt_pct_rate(metric.d1_positive_rate)}",
|
||||
f"- D1 >= 10% probability: {fmt_pct_rate(metric.d1_strong_rate)}",
|
||||
f"- Historical average D1 return for bucket: {fmt_num(metric.average_d1_return_pct, '%')}",
|
||||
f"- Historical median D1 return for bucket: {fmt_num(metric.median_d1_return_pct, '%')}",
|
||||
"- T2 sell return is not modeled until an approved grey-market data source exists.",
|
||||
"- D5/D20/D60 outcomes are review labels only, not holding targets.",
|
||||
"",
|
||||
"## Score Breakdown",
|
||||
"",
|
||||
@@ -389,8 +392,8 @@ def build_report(record: dict[str, str], rows: list[dict[str, str]], stage: str,
|
||||
"",
|
||||
*reason_lines(components, positive=False),
|
||||
*missing_field_lines(record, stage),
|
||||
"- T2 grey-market signal is not used because the project has no approved reproducible source.",
|
||||
"- Post-listing D1/D5/D20/D60 outcomes are labels for model calibration only and are not shown as prediction inputs.",
|
||||
"- T2 grey-market signal is not used yet because the project has no approved reproducible source.",
|
||||
"- Post-listing D5/D20/D60 outcomes are labels for later review only and are not holding-period targets.",
|
||||
"",
|
||||
"## Triggers",
|
||||
"",
|
||||
@@ -399,9 +402,10 @@ def build_report(record: dict[str, str], rows: list[dict[str, str]], stage: str,
|
||||
"",
|
||||
"## Exit Plan",
|
||||
"",
|
||||
"- If subscribed and allocated, reassess after allotment and before first trading session using only information available at that stage.",
|
||||
"- For T1 reports without approved T2 data, treat first-day liquidity and position sizing conservatively.",
|
||||
"- Record actual D1/D5/D20/D60 outcomes later as review labels, not as retroactive prediction inputs.",
|
||||
"- If subscribed and allocated, plan to sell in T2 grey market when reliable executable data is available.",
|
||||
"- If T2 is unavailable or unreliable, use D1 as the default exit window.",
|
||||
"- Do not treat D5/D20/D60 as planned holding periods for this model.",
|
||||
"- Record D1/D5/D20/D60 outcomes later as review labels, not as retroactive prediction inputs.",
|
||||
"",
|
||||
"## Source Paths",
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user