Clarify ops market opportunity side probability

This commit is contained in:
2569718930@qq.com
2026-07-04 00:33:51 +08:00
parent f421bc4a24
commit 2bbb040370
4 changed files with 39 additions and 5 deletions
@@ -47,7 +47,7 @@ export function runTests() {
"选项",
"方向",
"买入价",
"模型概率",
"方向概率",
"Edge",
"市场链接",
]) {
@@ -63,4 +63,10 @@ export function runTests() {
client.includes('showAllLowPrice ? "-1" : minEdge'),
"market opportunities filters must label price versus edge and not edge-filter the show-all-low-price view",
);
assert(
client.includes("side_probability") &&
client.includes("yes_probability") &&
client.includes("YES"),
"NO opportunities must show side probability while keeping the underlying YES probability visible",
);
}
@@ -15,6 +15,8 @@ type MarketOpportunityRow = {
side?: string;
ask_price?: number;
model_probability?: number;
yes_probability?: number;
side_probability?: number;
edge?: number;
liquidity?: number | null;
volume?: number | null;
@@ -74,6 +76,19 @@ function sideTone(side?: string) {
: "border-emerald-200 bg-emerald-50 text-emerald-700";
}
function yesProbability(row: MarketOpportunityRow) {
return typeof row.yes_probability === "number" ? row.yes_probability : row.model_probability;
}
function sideProbability(row: MarketOpportunityRow) {
if (typeof row.side_probability === "number") return row.side_probability;
const yes = yesProbability(row);
if (String(row.side).toLowerCase() === "no" && typeof yes === "number") {
return 1 - yes;
}
return yes;
}
function Stat({
label,
value,
@@ -152,9 +167,9 @@ export function MarketOpportunitiesPageClient() {
<div className="grid grid-cols-2 gap-3 md:grid-cols-5">
<Stat label="机会数" value={summary.opportunity_count ?? rows.length} sub="当前筛选结果" />
<Stat label="正边际" value={summary.positive_edge_count ?? 0} sub="模型概率高于买入价" />
<Stat label="正边际" value={summary.positive_edge_count ?? 0} sub="方向概率高于买入价" />
<Stat label="最低价格" value={cents(summary.min_price)} sub="低价合约下限" />
<Stat label="最大 Edge" value={percent(summary.max_edge)} sub="模型概率 - 市场价" />
<Stat label="最大 Edge" value={percent(summary.max_edge)} sub="方向概率 - 市场价" />
<Stat label="报价状态" value={quoteStatus} sub={`${summary.matched_event_count ?? 0}/${summary.scanned_city_count ?? 0} 城市匹配`} />
</div>
@@ -243,7 +258,7 @@ export function MarketOpportunitiesPageClient() {
<th className="px-3 py-2"></th>
<th className="px-3 py-2"></th>
<th className="px-3 py-2 text-right"></th>
<th className="px-3 py-2 text-right"></th>
<th className="px-3 py-2 text-right"></th>
<th className="px-3 py-2 text-right">Edge</th>
<th className="px-3 py-2 text-right"></th>
<th className="px-3 py-2 text-right">DEB</th>
@@ -277,7 +292,14 @@ export function MarketOpportunitiesPageClient() {
</span>
</td>
<td className="px-3 py-2 text-right font-black text-slate-950">{cents(row.ask_price)}</td>
<td className="px-3 py-2 text-right font-bold text-blue-700">{percent(row.model_probability)}</td>
<td className="px-3 py-2 text-right">
<div className="font-bold text-blue-700">{percent(sideProbability(row))}</div>
{String(row.side).toLowerCase() === "no" ? (
<div className="mt-0.5 text-[11px] font-semibold text-slate-400">
YES {percent(yesProbability(row))}
</div>
) : null}
</td>
<td className="px-3 py-2 text-right font-black text-emerald-700">{percent(row.edge)}</td>
<td className="px-3 py-2 text-right font-semibold text-slate-700">{tempLabel(row.current_max_so_far)}</td>
<td className="px-3 py-2 text-right font-semibold text-orange-700">{tempLabel(row.deb_prediction)}</td>
+4
View File
@@ -101,9 +101,13 @@ def test_build_market_opportunities_scans_yes_and_no_low_price_edges():
no = next(row for row in rows if row["bucket_label"] == "31°C" and row["side"] == "no")
assert yes["model_probability"] == 0.46
assert yes["yes_probability"] == 0.46
assert yes["side_probability"] == 0.46
assert yes["ask_price"] == 0.18
assert round(yes["edge"], 2) == 0.28
assert no["model_probability"] == 0.10
assert no["yes_probability"] == 0.10
assert no["side_probability"] == 0.90
assert no["ask_price"] == 0.18
assert round(no["edge"], 2) == 0.72
assert all(row["ask_price"] < 0.20 for row in rows)
+2
View File
@@ -336,6 +336,8 @@ def build_market_opportunity_rows(
"side": option_side,
"ask_price": _round_price(ask_number),
"model_probability": model_probability,
"yes_probability": model_probability,
"side_probability": target_probability,
"edge": edge,
"liquidity": _finite_number(market.get("liquidity")),
"volume": _finite_number(market.get("volume")),