Add Binance SIM market adapter and exchange switch in settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-25 12:02:36 +08:00
parent 5dcec0fde0
commit 78fd046fb6
25 changed files with 879 additions and 45 deletions
+1 -2
View File
@@ -14,8 +14,7 @@ router = APIRouter(prefix="/api/market", tags=["market"])
async def market_snapshot(_user: Annotated[str, Depends(require_user)]) -> dict:
gw = get_gateway()
snap = gw.snapshot_dict()
if snap.get("pair") is None:
raise HTTPException(status_code=503, detail="market not aligned yet")
# 切换交易所后短时可能尚未对齐 ATM;仍返回结构便于前端展示交易所
return snap
+40
View File
@@ -6,6 +6,12 @@ from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from ..config import get_settings
from ..exchange.runtime import (
load_runtime_settings,
normalize_exchange_name,
persist_exchange_choice,
reload_market_session,
)
from ..models.db import get_db
from ..sim.ledger import Ledger
from ..sim.matcher import Matcher
@@ -46,6 +52,7 @@ class StrategySettingsBody(BaseModel):
close_bid_mark_max_pct: float | None = Field(default=None, ge=1, le=100)
perp_qty_eth: float | None = Field(default=None, ge=0.01, le=100)
option_qty_eth: float | None = Field(default=None, ge=0.01, le=100)
exchange: str | None = Field(default=None, pattern="^(okx|binance|bn)$")
def _as_bool(raw: str | None, default: bool) -> bool:
@@ -57,6 +64,7 @@ def _as_bool(raw: str | None, default: bool) -> bool:
def _read_settings() -> dict:
db = get_db()
s = get_settings()
rt = load_runtime_settings()
mode = str(db.get_setting("exit_mode", s.exit_mode) or s.exit_mode)
if mode not in ("fixed_usdt", "premium_multiple"):
mode = "fixed_usdt"
@@ -102,6 +110,10 @@ def _read_settings() -> dict:
"option_qty_eth": float(
db.get_setting("option_qty_eth", str(s.option_qty_eth)) or s.option_qty_eth
),
"exchange": rt.exchange,
"perp_inst_id": rt.perp_inst_id,
"option_inst_family": rt.option_inst_family,
"index_inst_id": rt.index_inst_id,
"ledger": Ledger(db).snapshot(),
}
@@ -120,6 +132,21 @@ async def put_strategy_settings(
s = get_settings()
data = body.model_dump(exclude_none=True)
equity_to_apply: float | None = None
switch_to: str | None = None
if "exchange" in data:
new_ex = normalize_exchange_name(str(data.pop("exchange")))
old_ex = normalize_exchange_name(
db.get_setting("exchange", s.exchange) or s.exchange
)
if new_ex != old_ex:
if Matcher(db).has_open_position():
raise HTTPException(
status_code=409,
detail="有未平仓,无法切换交易所;请先平仓后再改",
)
switch_to = new_ex
if "initial_equity" in data:
new_eq = float(data["initial_equity"])
old_eq = float(
@@ -132,12 +159,25 @@ async def put_strategy_settings(
detail="有未平仓,无法重置模拟资金;请先平仓后再改",
)
equity_to_apply = new_eq
for k, v in data.items():
if k in KEYS:
db.set_setting(k, str(v))
if equity_to_apply is not None:
Ledger(db).reset_equity(
equity_to_apply,
note=f"设置模拟资金={equity_to_apply:.2f}",
)
if switch_to is not None:
rt = persist_exchange_choice(switch_to)
try:
await reload_market_session(rt)
except Exception as e:
raise HTTPException(
status_code=502,
detail=f"交易所已切换为 {switch_to},但行情重连失败: {e}",
) from e
return _read_settings()