586469482e
Startup ignored DB exchange choice and kept OKX ATM ids under a Binance health label, so option bid/ask stayed empty. Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
"""币安符号解析与中性到期工具测试。"""
|
|
|
|
from app.exchange.binance.parse import parse_option_symbol, rows_to_option_contracts
|
|
from app.exchange.expiry import expiry_ms_from_ymd, ymd_from_expiry_ms
|
|
from app.exchange.runtime import normalize_exchange_name
|
|
|
|
|
|
def test_binance_parse_option_symbol() -> None:
|
|
y, stk, side = parse_option_symbol("ETH-250726-1860-C")
|
|
assert y == "250726"
|
|
assert stk == 1860.0
|
|
assert side == "C"
|
|
y2, _, side2 = parse_option_symbol("ETH-250726-1860-P")
|
|
assert y2 == "250726" and side2 == "P"
|
|
assert parse_option_symbol("ETHUSDT")[0] is None
|
|
|
|
|
|
def test_binance_rows_to_contracts() -> None:
|
|
rows = [
|
|
{
|
|
"symbol": "ETH-250726-1860-C",
|
|
"status": "TRADING",
|
|
"strikePrice": "1860",
|
|
"side": "CALL",
|
|
"expiryDate": expiry_ms_from_ymd("250726"),
|
|
"unit": "1",
|
|
"underlying": "ETHUSDT",
|
|
},
|
|
{
|
|
"symbol": "ETH-250726-1860-P",
|
|
"status": "TRADING",
|
|
"strikePrice": "1860",
|
|
"side": "PUT",
|
|
"expiryDate": expiry_ms_from_ymd("250726"),
|
|
"unit": 1,
|
|
"underlying": "ETHUSDT",
|
|
},
|
|
]
|
|
out = rows_to_option_contracts(rows)
|
|
assert len(out) == 2
|
|
assert out[0]["expiry_ymd"] == "250726"
|
|
assert out[0]["ct_mult"] == 1.0
|
|
assert out[0]["side"] in ("C", "P")
|
|
|
|
|
|
def test_expiry_ms_roundtrip() -> None:
|
|
ms = expiry_ms_from_ymd("250726")
|
|
assert ymd_from_expiry_ms(ms) == "250726"
|
|
# UTC 08:00
|
|
from datetime import datetime, timezone
|
|
|
|
dt = datetime.fromtimestamp(ms / 1000, tz=timezone.utc)
|
|
assert dt.hour == 8 and dt.minute == 0
|
|
|
|
|
|
def test_normalize_exchange() -> None:
|
|
assert normalize_exchange_name("BN") == "binance"
|
|
assert normalize_exchange_name("okx") == "okx"
|
|
assert normalize_exchange_name(None) == "okx"
|
|
|
|
|
|
def test_binance_maps_okx_family_name() -> None:
|
|
"""误传 OKX family 时不应按 startswith(ETH) 乱匹配,应映射到 ETHUSDT。"""
|
|
from app.exchange.binance.rest import BinanceRestClient
|
|
|
|
cli = BinanceRestClient.__new__(BinanceRestClient)
|
|
cli._exchange_info = {
|
|
"optionSymbols": [
|
|
{
|
|
"symbol": "ETH-260726-1860-C",
|
|
"underlying": "ETHUSDT",
|
|
"status": "TRADING",
|
|
"strikePrice": "1860",
|
|
"side": "CALL",
|
|
"expiryDate": 1785052800000,
|
|
"unit": "1",
|
|
},
|
|
{
|
|
"symbol": "BTC-260726-100000-C",
|
|
"underlying": "BTCUSDT",
|
|
"status": "TRADING",
|
|
"strikePrice": "100000",
|
|
"side": "CALL",
|
|
"expiryDate": 1785052800000,
|
|
"unit": "1",
|
|
},
|
|
]
|
|
}
|
|
rows = BinanceRestClient.fetch_option_instruments(cli, "ETH-USD_UM")
|
|
assert len(rows) == 1
|
|
assert rows[0]["symbol"] == "ETH-260726-1860-C"
|