Hide manual trade by default, block open while running, auto-refresh auth token.
Also fix flat-side reconcile to check both long and short residuals; document in 更新说明. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -89,6 +89,22 @@ async def me(
|
||||
}
|
||||
|
||||
|
||||
@router.post("/refresh", response_model=LoginResponse)
|
||||
async def refresh_token(
|
||||
username: Annotated[str, Depends(require_user)],
|
||||
settings: Annotated[Settings, Depends(get_settings)],
|
||||
) -> LoginResponse:
|
||||
"""用仍有效的 Bearer 换发新 HMAC token(自动轮换,无需重登)。"""
|
||||
token, ttl = issue_token(username, settings)
|
||||
return LoginResponse(
|
||||
token=token,
|
||||
username=username,
|
||||
expires_in=ttl,
|
||||
env_name=settings.env_name,
|
||||
mode=settings.mode,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/change-credentials", response_model=LoginResponse)
|
||||
async def change_credentials(
|
||||
body: ChangeCredentialsRequest,
|
||||
|
||||
@@ -44,6 +44,7 @@ KEYS = (
|
||||
"close_bid_mark_max_pct",
|
||||
"perp_qty_eth",
|
||||
"option_qty_eth",
|
||||
"show_manual_trade_buttons",
|
||||
)
|
||||
|
||||
|
||||
@@ -65,6 +66,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)
|
||||
show_manual_trade_buttons: bool | None = None
|
||||
exchange: str | None = Field(default=None, pattern="^(okx|binance|bn)$")
|
||||
|
||||
|
||||
@@ -139,6 +141,9 @@ def _read_settings() -> dict:
|
||||
"option_qty_eth": float(
|
||||
db.get_setting("option_qty_eth", str(s.option_qty_eth)) or s.option_qty_eth
|
||||
),
|
||||
"show_manual_trade_buttons": _as_bool(
|
||||
db.get_setting("show_manual_trade_buttons", "0"), False
|
||||
),
|
||||
"exchange": rt.exchange,
|
||||
"perp_inst_id": rt.perp_inst_id,
|
||||
"option_inst_family": rt.option_inst_family,
|
||||
|
||||
@@ -42,6 +42,19 @@ async def sim_open_group(
|
||||
ok, reason = live_ready()
|
||||
if not get_settings().is_sim and not ok:
|
||||
raise HTTPException(status_code=400, detail=reason)
|
||||
from ..strategy import get_engine
|
||||
|
||||
st = get_engine().state()
|
||||
if st.get("running"):
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail="策略自动运行中,禁止手动开仓;请先暂停",
|
||||
)
|
||||
if not Ledger().get_setting_bool("show_manual_trade_buttons", False):
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="未开启「显示手动开仓」;请在策略设置中开启后再用",
|
||||
)
|
||||
ex = get_executor()
|
||||
if ex.has_open_position():
|
||||
raise HTTPException(status_code=409, detail="有未平仓,禁止开下一组")
|
||||
@@ -115,6 +128,11 @@ async def sim_open_group(
|
||||
|
||||
@router.post("/close-group")
|
||||
async def sim_close_group(_user: Annotated[str, Depends(require_user)]) -> dict:
|
||||
if not Ledger().get_setting_bool("show_manual_trade_buttons", False):
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="未开启「显示手动开仓」;请在策略设置中开启后再用",
|
||||
)
|
||||
r = get_executor().close_group(reason="manual")
|
||||
if not r.ok and not r.liquidity_wait:
|
||||
raise HTTPException(status_code=400, detail=r.detail)
|
||||
|
||||
Reference in New Issue
Block a user