手动打分页改为按品种选择,日期限定主力合约范围,结果自动滚动到视图

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fish
2026-05-03 16:40:15 +08:00
parent fd1c1c7330
commit 44909f04e2
6 changed files with 167 additions and 65 deletions

View File

@@ -1,5 +1,7 @@
from typing import Optional
from datetime import date
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
@@ -133,6 +135,20 @@ def list_contracts():
conn.close()
@app.get("/api/v1/contracts/active")
def get_active_contract(symbol: str = Query(...)):
"""返回某品种当前主力合约及可选打分日期范围。"""
if symbol not in contracts.ROLLOVER_RULES:
raise HTTPException(status_code=400, detail=f"未配置 {symbol} 的主力轮换规则")
today = date.today()
return {
"symbol": symbol,
"ts_code": contracts.active_contract(symbol, today),
"min_date": contracts.active_contract_start(symbol, today).isoformat(),
"max_date": today.isoformat(),
}
@app.get("/api/v1/candles")
def list_candles(
ts_code: str = Query(...),

View File

@@ -1,6 +1,10 @@
from datetime import date
from typing import Optional
def _prev_month(year: int, month: int) -> tuple[int, int]:
return (year - 1, 12) if month == 1 else (year, month - 1)
# 品种主力合约轮换规则。
# 每个品种维护:
# exchange: tushare 合约后缀(交易所)
@@ -72,3 +76,21 @@ def active_contract(symbol: str, today: Optional[date] = None) -> str:
contract_month, year_offset = rule["active"][today.month]
year = today.year + year_offset
return f"{symbol}{year % 100:02d}{contract_month:02d}.{rule['exchange']}"
def active_contract_start(symbol: str, today: Optional[date] = None) -> date:
"""当前主力合约首次成为主力的日期(月初)。
从今天向前回溯日历月,只要 active_contract 仍指向同一合约就继续往前。
例如今天 2026-05,FG 的 09 合约活跃月份为 4-7 月,则返回 2026-04-01。
"""
today = today or date.today()
target = active_contract(symbol, today)
year, month = today.year, today.month
for _ in range(12):
py, pm = _prev_month(year, month)
if active_contract(symbol, date(py, pm, 1)) != target:
return date(year, month, 1)
year, month = py, pm
return date(year, month, 1)