Fix detail pricing labels and price semantics tests
This commit is contained in:
@@ -142,6 +142,34 @@ function getSideRow(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDetailSideAsk(
|
||||||
|
scanRow: ScanOpportunityRow | null,
|
||||||
|
marketScan: MarketScan | null | undefined,
|
||||||
|
side: "yes" | "no",
|
||||||
|
) {
|
||||||
|
if (scanRow?.ask != null) return scanRow.ask;
|
||||||
|
if (side === "yes") {
|
||||||
|
if (scanRow?.yes_ask != null) return scanRow.yes_ask;
|
||||||
|
return marketScan?.yes_buy ?? null;
|
||||||
|
}
|
||||||
|
if (scanRow?.no_ask != null) return scanRow.no_ask;
|
||||||
|
return marketScan?.no_buy ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDetailSideBid(
|
||||||
|
scanRow: ScanOpportunityRow | null,
|
||||||
|
marketScan: MarketScan | null | undefined,
|
||||||
|
side: "yes" | "no",
|
||||||
|
) {
|
||||||
|
if (scanRow?.bid != null) return scanRow.bid;
|
||||||
|
if (side === "yes") {
|
||||||
|
if (scanRow?.yes_bid != null) return scanRow.yes_bid;
|
||||||
|
return marketScan?.yes_sell ?? null;
|
||||||
|
}
|
||||||
|
if (scanRow?.no_bid != null) return scanRow.no_bid;
|
||||||
|
return marketScan?.no_sell ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
function buildComparisonBuckets(
|
function buildComparisonBuckets(
|
||||||
marketScan: MarketScan | null | undefined,
|
marketScan: MarketScan | null | undefined,
|
||||||
row: ScanOpportunityRow | null,
|
row: ScanOpportunityRow | null,
|
||||||
@@ -396,24 +424,30 @@ function DetailPanel({
|
|||||||
{isEn ? "Buy Yes" : "买入 Yes"} {displayRow.target_label || ""}
|
{isEn ? "Buy Yes" : "买入 Yes"} {displayRow.target_label || ""}
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
{formatPrice(yesRow?.ask ?? marketScan?.yes_buy)} →{" "}
|
{formatPrice(getDetailSideAsk(yesRow, marketScan, "yes"))} →{" "}
|
||||||
{formatProbability(yesRow?.model_probability)}
|
{formatProbability(yesRow?.model_probability)}
|
||||||
</p>
|
</p>
|
||||||
<p className="positive">{formatPercent(yesRow?.edge_percent, true)} {isEn ? "edge" : "边际优势"}</p>
|
<p className="positive">{formatPercent(yesRow?.edge_percent, true)} {isEn ? "edge" : "边际优势"}</p>
|
||||||
<p>{isEn ? "Spread" : "点差"} {formatPrice(yesRow?.spread)}</p>
|
<p>
|
||||||
|
{isEn ? "Bid / Ask" : "买卖价"} {formatPrice(getDetailSideBid(yesRow, marketScan, "yes"))} /{" "}
|
||||||
|
{formatPrice(getDetailSideAsk(yesRow, marketScan, "yes"))}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="scan-trade-card sell">
|
<div className="scan-trade-card sell">
|
||||||
<div className="scan-trade-card-title">
|
<div className="scan-trade-card-title">
|
||||||
{isEn ? "Buy No" : "买入 No"} {displayRow.target_label || ""}
|
{isEn ? "Buy No" : "买入 No"} {displayRow.target_label || ""}
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
{formatPrice(noRow?.ask ?? marketScan?.no_buy)} →{" "}
|
{formatPrice(getDetailSideAsk(noRow, marketScan, "no"))} →{" "}
|
||||||
{formatProbability(noRow?.model_probability)}
|
{formatProbability(noRow?.model_probability)}
|
||||||
</p>
|
</p>
|
||||||
<p className={Number(noRow?.edge_percent || 0) >= 0 ? "positive" : "negative"}>
|
<p className={Number(noRow?.edge_percent || 0) >= 0 ? "positive" : "negative"}>
|
||||||
{formatPercent(noRow?.edge_percent, true)} {isEn ? "edge" : "边际优势"}
|
{formatPercent(noRow?.edge_percent, true)} {isEn ? "edge" : "边际优势"}
|
||||||
</p>
|
</p>
|
||||||
<p>{isEn ? "Spread" : "点差"} {formatPrice(noRow?.spread)}</p>
|
<p>
|
||||||
|
{isEn ? "Bid / Ask" : "买卖价"} {formatPrice(getDetailSideBid(noRow, marketScan, "no"))} /{" "}
|
||||||
|
{formatPrice(getDetailSideAsk(noRow, marketScan, "no"))}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
@@ -40,8 +40,8 @@ def test_extract_market_bucket_range_supports_fahrenheit_ranges():
|
|||||||
def test_fetch_token_market_data_uses_rest_orderbook_executable_prices():
|
def test_fetch_token_market_data_uses_rest_orderbook_executable_prices():
|
||||||
layer = PolymarketReadOnlyLayer()
|
layer = PolymarketReadOnlyLayer()
|
||||||
payloads = {
|
payloads = {
|
||||||
("/price", "BUY"): {"price": "0.11"},
|
("/price", "BUY"): {"price": "0.27"},
|
||||||
("/price", "SELL"): {"price": "0.88"},
|
("/price", "SELL"): {"price": "0.23"},
|
||||||
("/midpoint", None): {"midpoint": "0.50"},
|
("/midpoint", None): {"midpoint": "0.50"},
|
||||||
("/last-trade-price", None): {"price": "0.49"},
|
("/last-trade-price", None): {"price": "0.49"},
|
||||||
("/book", None): {
|
("/book", None): {
|
||||||
@@ -68,6 +68,30 @@ def test_fetch_token_market_data_uses_rest_orderbook_executable_prices():
|
|||||||
assert data["quote_source"] == "polymarket_clob_rest"
|
assert data["quote_source"] == "polymarket_clob_rest"
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_token_market_data_keeps_buy_sell_semantics_without_orderbook():
|
||||||
|
layer = PolymarketReadOnlyLayer()
|
||||||
|
payloads = {
|
||||||
|
("/price", "BUY"): {"price": "0.23"},
|
||||||
|
("/price", "SELL"): {"price": "0.27"},
|
||||||
|
("/midpoint", None): {"midpoint": "0.25"},
|
||||||
|
("/last-trade-price", None): {"price": "0.24"},
|
||||||
|
("/book", None): None,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _fake_clob_get(path, params):
|
||||||
|
if path == "/price":
|
||||||
|
return payloads[(path, params.get("side"))]
|
||||||
|
return payloads[(path, None)]
|
||||||
|
|
||||||
|
layer._clob_get = _fake_clob_get
|
||||||
|
|
||||||
|
data = layer._fetch_token_market_data("token-1")
|
||||||
|
|
||||||
|
assert data["buy"] == 0.27
|
||||||
|
assert data["sell"] == 0.23
|
||||||
|
assert data["midpoint"] == 0.25
|
||||||
|
|
||||||
|
|
||||||
def test_get_token_market_data_uses_price_cache_within_ttl():
|
def test_get_token_market_data_uses_price_cache_within_ttl():
|
||||||
layer = PolymarketReadOnlyLayer()
|
layer = PolymarketReadOnlyLayer()
|
||||||
calls = []
|
calls = []
|
||||||
|
|||||||
Reference in New Issue
Block a user