Add weekend open skip, expiry force-close, and Chinese trade labels.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-25 10:28:33 +08:00
parent 826362b556
commit b50c134f5b
19 changed files with 525 additions and 52 deletions
+11
View File
@@ -19,6 +19,7 @@ KEYS = (
"net_profit_target",
"premium_exit_multiple",
"rest_seconds",
"skip_weekends",
"initial_equity",
"leverage",
"min_option_hours",
@@ -36,6 +37,7 @@ class StrategySettingsBody(BaseModel):
net_profit_target: float | None = Field(default=None, ge=0.1, le=1_000_000)
premium_exit_multiple: float | None = Field(default=None, ge=0.1, le=100)
rest_seconds: int | None = Field(default=None, ge=0, le=3600)
skip_weekends: bool | None = None
initial_equity: float | None = Field(default=None, ge=1000)
leverage: float | None = Field(default=None, ge=1, le=125)
min_option_hours: float | None = Field(default=None, ge=1, le=720)
@@ -45,6 +47,12 @@ class StrategySettingsBody(BaseModel):
option_qty_eth: float | None = Field(default=None, ge=0.01, le=100)
def _as_bool(raw: str | None, default: bool) -> bool:
if raw is None or raw == "":
return default
return str(raw).strip().lower() in ("1", "true", "yes", "on")
def _read_settings() -> dict:
db = get_db()
s = get_settings()
@@ -68,6 +76,9 @@ def _read_settings() -> dict:
"rest_seconds": int(
float(db.get_setting("rest_seconds", str(s.rest_seconds)) or s.rest_seconds)
),
"skip_weekends": _as_bool(
db.get_setting("skip_weekends", str(s.skip_weekends)), s.skip_weekends
),
"initial_equity": float(
db.get_setting("initial_equity", str(s.initial_equity)) or s.initial_equity
),
+10 -5
View File
@@ -5,11 +5,12 @@ from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from ..config import get_settings
from ..market import get_gateway
from ..models.db import get_db
from ..sim.ledger import Ledger
from ..sim.matcher import Matcher
from ..strategy.clock import window_key
from ..strategy.clock import can_open_new, window_key
from ..strategy.group import next_group_id
from .auth import require_user
@@ -39,6 +40,13 @@ async def sim_open_group(
) -> dict:
if Matcher().has_open_position():
raise HTTPException(status_code=409, detail="有未平仓,禁止开下一组")
s = get_settings()
skip_weekends = Ledger().get_setting_bool("skip_weekends", s.skip_weekends)
if not can_open_new(skip_weekends=skip_weekends):
raise HTTPException(
status_code=409,
detail="周六/周日跳过开仓(上海时区)",
)
gw = get_gateway()
pick = await gw.pick_for_open_async()
if pick is None:
@@ -53,12 +61,9 @@ async def sim_open_group(
perp_side = "short" if force == "call" else "long"
bias = "manual_" + force
option_ask = pick.call_ask if force == "call" else pick.put_ask
from ..config import get_settings
from ..strategy.selection import option_leverage
from ..sim.ledger import Ledger as Led
s = get_settings()
min_lev = Led().get_setting_float("min_option_leverage", s.min_option_leverage)
min_lev = Ledger().get_setting_float("min_option_leverage", s.min_option_leverage)
lev = option_leverage(pick.underlying_px, option_ask)
if lev is None or lev < min_lev:
raise HTTPException(