缓存看股数据

This commit is contained in:
2026-08-16 21:24:41 +08:00
parent 65d2f54d1b
commit f192a08384
5 changed files with 45 additions and 758 deletions

View File

@@ -107,6 +107,8 @@ def _rows_to_bars(rows) -> list[Bar]:
_ADJUST_MODES = ("bfq", "qfq", "hfq")
# MA 全量集合(前端已改为本地计算 MA后端始终返回此集合以保证缓存一致
_FULL_MA_SET = (5, 10, 20, 30, 60, 120, 250)
def _adjust_bars(bars: list[Bar], factors, from_mode: str, to_mode: str) -> list[Bar]:
@@ -814,10 +816,11 @@ async def screener_preview(
symbol = plain_code(ts_code)
# --- Redis 读缓存历史窗口end 翻页)只增不改,最新窗口每日由全市场同步推进;
# 键含 ver:candles 版本号同步完成后自增旧缓存全部失效TTL 兜底cache.py---
# 键含 ver:candles 版本号同步完成后自增旧缓存全部失效TTL 兜底cache.py
# 注ma_periods 不参与缓存键 —— 前端已改为本地计算 MA后端始终返回全量 MA 集合
cache_key = cache.digest(
"preview", ts_code, timeframe, limit, adjust,
end_dt.strftime("%Y-%m-%d") if end_dt else None, ma_periods, zx_periods,
end_dt.strftime("%Y-%m-%d") if end_dt else None,
await cache.get_version("candles"),
)
cached = await cache.cache_get(f"pv:{cache_key}")
@@ -896,7 +899,8 @@ async def screener_preview(
kdj = ind.kdj(highs, lows, closes)
boll = ind.bollinger(closes)
indicators = {
"ma": {f"ma{p}": _series_to_jsonable(ind.ma(closes, p)) for p in ma_periods},
# MA 始终返回全量集合(前端本地计算 MA此处仅保留兼容缓存键不依赖 ma_periods
"ma": {f"ma{p}": _series_to_jsonable(ind.ma(closes, p)) for p in _FULL_MA_SET},
"macd": {
"dif": _series_to_jsonable(macd["macd"]),
"dea": _series_to_jsonable(macd["signal"]),

View File

@@ -1,10 +1,15 @@
"""应用配置pydantic-settings。可由 .env / 环境变量覆盖。"""
from pathlib import Path
from pydantic import model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
# 确保 .env 文件总是相对于 config.py 所在目录加载,无论从哪个目录启动 uvicorn
_ENV_FILE = Path(__file__).resolve().parent.parent / ".env"
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
model_config = SettingsConfigDict(env_file=str(_ENV_FILE) if _ENV_FILE.exists() else ".env", extra="ignore")
app_name: str = "Stock Backtest"

View File

@@ -1,751 +1,6 @@
INFO: Started server process [35612]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: 127.0.0.1:61535 - "GET /api/auth/me HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:61572 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:61574 - "GET /api/screener/preview/000001.SZ?limit=3&adjust=bfq HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:61576 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:61578 - "GET /api/screener/preview/000001.SZ?limit=3 HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:61605 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:61608 - "GET /api/screener/preview/000001.SZ?limit=3&adjust=bfq HTTP/1.1" 200 OK
INFO: 127.0.0.1:62165 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62164 - "GET /api/screener/preview/000001.SZ?limit=500&adjust=qfq&timeframe=1M&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:62194 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62192 - "GET /api/screener/preview/000001.SZ?limit=500&adjust=qfq&timeframe=1M&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:62479 - "GET /api/screener/preview/000001.SZ?limit=3&adjust=bfq HTTP/1.1" 200 OK
INFO: 127.0.0.1:62512 - "GET /api/screener/preview/000001.SZ?limit=2&adjust=bfq HTTP/1.1" 200 OK
INFO: 127.0.0.1:63470 - "GET /api/screener/preview/000001.SZ?limit=2&adjust=qfq&timeframe=1M HTTP/1.1" 200 OK
INFO: 127.0.0.1:58419 - "GET /api/screener/preview/000001.SZ?limit=2800&adjust=bfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:58464 - "GET /api/screener/preview/000001.SZ?limit=4&adjust=bfq&timeframe=1w HTTP/1.1" 200 OK
INFO: 127.0.0.1:58481 - "GET /api/screener/preview/000001.SZ?limit=2800&adjust=bfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:58482 - "GET /api/screener/preview/000001.SZ?limit=4&adjust=bfq&timeframe=1w HTTP/1.1" 200 OK
INFO: 127.0.0.1:58776 - "GET /api/auth/me HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:58819 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:58820 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:58838 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:58855 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:58857 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:58867 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:58829 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:58866 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:58883 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:58881 - "GET /api/screener/preview/000001.SZ?limit=500&adjust=qfq&timeframe=1M&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:58985 - "GET /api/screener/preview/000001.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:58988 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:58991 - "GET /api/screener/preview/000001.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59694 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59696 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59715 - "POST /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:59733 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59743 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59750 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59761 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59767 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59774 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59749 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59773 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59815 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59823 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59828 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59827 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59861 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59865 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59874 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59872 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59889 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59898 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59903 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59902 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59992 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:59990 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59998 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60003 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60018 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60455 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60453 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60458 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60476 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60474 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60478 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60498 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60497 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60501 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60513 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60512 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60515 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60556 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60554 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60559 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61756 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:61755 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61760 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63160 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63182 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63271 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:63290 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:63292 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:63330 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:63341 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:63349 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:63291 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63367 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:63377 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:63384 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:63348 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63380 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63403 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:63410 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:63413 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:63412 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:49400 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:49399 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:49461 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:49469 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:49479 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:49478 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51074 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:51097 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:51100 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:51099 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53759 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:53758 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53768 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53773 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53778 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2021-03-31 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53785 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2016-12-29 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53787 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2012-04-10 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53793 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5%2C10%2C20%2C60&end=2008-10-10 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53832 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53848 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C20%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53859 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53855 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:53852 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d&mas=60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53850 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5%2C60 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53862 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53868 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53870 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53874 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53882 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53879 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53900 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53908 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53915 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53925 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53931 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53934 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53927 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53948 - "GET /api/screener/preview/000007.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53952 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53955 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:53941 - "GET /api/screener/preview/000007.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54082 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:54085 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:54214 - "GET /api/screener/preview/000009.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54216 - "GET /api/screener/preview/000009.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54303 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:54301 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54936 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:54933 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1d&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54943 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1d&mas=5&end=2024-07-17 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54950 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:54947 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:54955 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59351 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59369 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59372 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59371 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60036 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60035 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60042 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60069 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2000-05-15 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60229 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60228 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60245 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60392 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60388 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60395 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60399 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60407 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:60404 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5%2C10 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60412 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60416 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5%2C10%2C20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60419 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:60423 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60537 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60536 - "GET /api/screener/preview/000008.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5%2C10%2C20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60544 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60691 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60702 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:60699 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60695 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60713 - "GET /api/screener/preview/000008.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-09-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60722 - "GET /api/screener/preview/000002.SZ?limit=500&adjust=qfq&timeframe=1w&mas=5%2C10%2C20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60730 - "GET /api/screener/preview/000002.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-12-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60763 - "GET /api/screener/preview/000002.SZ?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2000-11-13 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60775 - "DELETE /api/watchlist/000008.SZ HTTP/1.1" 200 OK
INFO: 127.0.0.1:60778 - "POST /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60783 - "DELETE /api/watchlist/000008.SZ HTTP/1.1" 200 OK
INFO: 127.0.0.1:60797 - "GET /api/screener/sync/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:60898 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:60907 - "GET /api/screener/sync/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:60916 - "GET /api/screener/queries?limit=20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60897 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60914 - "POST /api/screener/run HTTP/1.1" 200 OK
INFO: 127.0.0.1:60972 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:60971 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1w&mas=5%2C10%2C20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:60988 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1w&mas=5%2C10%2C20&end=2016-12-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61042 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61032 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1w&mas=10%2C20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61034 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1w&mas=20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61036 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1w HTTP/1.1" 200 OK
INFO: 127.0.0.1:61048 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1w&end=2016-12-26 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61056 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:61059 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61063 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61075 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61078 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61082 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61106 - "PUT /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61165 - "GET /api/screener/preview/002668.SZ?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:61169 - "GET /api/screener/preview/002668.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:62065 - "GET /api/screener/preview/002668.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:62308 - "GET /api/screener/preview/002668.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "D:\Project\stock\backend\.venv\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 422, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.scope, self.receive, self.send
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 63, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\applications.py", line 1163, in __call__
await super().__call__(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\applications.py", line 90, in __call__
await self.middleware_stack(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\cors.py", line 88, in __call__
await self.app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\exceptions.py", line 63, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\routing.py", line 660, in __call__
await self.middleware_stack(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 2734, in app
await route.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1780, in handle
await self.original_router.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 2789, in handle
await included_router._handle_selected(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1800, in _handle_selected
await original_route.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1279, in handle
await app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 158, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 144, in app
response = await f(request)
^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 481, in app
solved_result = await solve_dependencies(
^^^^^^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\dependencies\utils.py", line 674, in solve_dependencies
solved = await call(**solved_result.values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\app\auth.py", line 102, in require_user
auth_session = await get_auth_session(stock_session, db)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\app\auth.py", line 85, in get_auth_session
auth_session = (await db.execute(stmt)).scalar_one_or_none()
^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\ext\asyncio\session.py", line 448, in execute
result = await greenlet_spawn(
^^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 201, in greenlet_spawn
result = context.throw(*sys.exc_info())
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2373, in execute
return self._execute_internal(
~~~~~~~~~~~~~~~~~~~~~~^
statement,
^^^^^^^^^^
...<4 lines>...
_add_event=_add_event,
^^^^^^^^^^^^^^^^^^^^^^
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2261, in _execute_internal
conn = self._connection_for_bind(bind)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2113, in _connection_for_bind
return trans._connection_for_bind(engine, execution_options)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 2, in _connection_for_bind
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\state_changes.py", line 137, in _go
ret_value = fn(self, *arg, **kw)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 1191, in _connection_for_bind
conn = bind.connect()
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 3295, in connect
return self._connection_cls(self)
~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 144, in __init__
self._dbapi_connection = engine.raw_connection()
~~~~~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 3319, in raw_connection
return self.pool.connect()
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 448, in connect
return _ConnectionFairy._checkout(self)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 1272, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 717, in checkout
with util.safe_reraise():
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 122, in __exit__
raise exc_value.with_traceback(exc_tb)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 715, in checkout
dbapi_connection = rec.get_connection()
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 866, in get_connection
self.__connect()
~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 900, in __connect
with util.safe_reraise():
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 122, in __exit__
raise exc_value.with_traceback(exc_tb)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 896, in __connect
self.dbapi_connection = connection = pool._invoke_creator(self)
~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\create.py", line 667, in connect
return dialect.connect(*cargs_tup, **cparams)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\default.py", line 630, in connect
return self.loaded_dbapi.connect(*cargs, **cparams) # type: ignore[no-any-return] # NOQA: E501
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\dialects\postgresql\asyncpg.py", line 955, in connect
await_only(creator_fn(*arg, **kw)),
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 132, in await_only
return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 196, in greenlet_spawn
value = await result
^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connection.py", line 2443, in connect
return await connect_utils._connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<22 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1249, in _connect
raise last_error or exceptions.TargetServerAttributeNotMatched(
...<2 lines>...
)
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1218, in _connect
conn = await _connect_addr(
^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1054, in _connect_addr
return await __connect_addr(params, True, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1099, in __connect_addr
tr, pr = await connector
^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 969, in _create_ssl_connection
tr, pr = await loop.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>...
host, port)
^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1168, in create_connection
raise exceptions[0]
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1143, in create_connection
sock = await self._connect_sock(
^^^^^^^^^^^^^^^^^^^^^^^^^
exceptions, addrinfo, laddr_infos)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1042, in _connect_sock
await self.sock_connect(sock, address)
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\proactor_events.py", line 728, in sock_connect
return await self._proactor.connect(sock, address)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\windows_events.py", line 804, in _poll
value = callback(transferred, key, ov)
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\windows_events.py", line 600, in finish_connect
ov.getresult()
~~~~~~~~~~~~^^
ConnectionRefusedError: [WinError 1225] 远程计算机拒绝网络连接。
INFO: 127.0.0.1:62317 - "GET /api/screener/preview/002668.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "D:\Project\stock\backend\.venv\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 422, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.scope, self.receive, self.send
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 63, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\applications.py", line 1163, in __call__
await super().__call__(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\applications.py", line 90, in __call__
await self.middleware_stack(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\cors.py", line 88, in __call__
await self.app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\middleware\exceptions.py", line 63, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\routing.py", line 660, in __call__
await self.middleware_stack(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 2734, in app
await route.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1780, in handle
await self.original_router.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 2789, in handle
await included_router._handle_selected(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1800, in _handle_selected
await original_route.handle(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 1279, in handle
await app(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 158, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
raise exc
File "D:\Project\stock\backend\.venv\Lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 144, in app
response = await f(request)
^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\routing.py", line 481, in app
solved_result = await solve_dependencies(
^^^^^^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\fastapi\dependencies\utils.py", line 674, in solve_dependencies
solved = await call(**solved_result.values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\app\auth.py", line 102, in require_user
auth_session = await get_auth_session(stock_session, db)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\app\auth.py", line 85, in get_auth_session
auth_session = (await db.execute(stmt)).scalar_one_or_none()
^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\ext\asyncio\session.py", line 448, in execute
result = await greenlet_spawn(
^^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 201, in greenlet_spawn
result = context.throw(*sys.exc_info())
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2373, in execute
return self._execute_internal(
~~~~~~~~~~~~~~~~~~~~~~^
statement,
^^^^^^^^^^
...<4 lines>...
_add_event=_add_event,
^^^^^^^^^^^^^^^^^^^^^^
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2261, in _execute_internal
conn = self._connection_for_bind(bind)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 2113, in _connection_for_bind
return trans._connection_for_bind(engine, execution_options)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 2, in _connection_for_bind
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\state_changes.py", line 137, in _go
ret_value = fn(self, *arg, **kw)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\orm\session.py", line 1191, in _connection_for_bind
conn = bind.connect()
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 3295, in connect
return self._connection_cls(self)
~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 144, in __init__
self._dbapi_connection = engine.raw_connection()
~~~~~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\base.py", line 3319, in raw_connection
return self.pool.connect()
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 448, in connect
return _ConnectionFairy._checkout(self)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 1272, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 717, in checkout
with util.safe_reraise():
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 122, in __exit__
raise exc_value.with_traceback(exc_tb)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 715, in checkout
dbapi_connection = rec.get_connection()
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 866, in get_connection
self.__connect()
~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 900, in __connect
with util.safe_reraise():
~~~~~~~~~~~~~~~~~^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 122, in __exit__
raise exc_value.with_traceback(exc_tb)
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\pool\base.py", line 896, in __connect
self.dbapi_connection = connection = pool._invoke_creator(self)
~~~~~~~~~~~~~~~~~~~~^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\create.py", line 667, in connect
return dialect.connect(*cargs_tup, **cparams)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\engine\default.py", line 630, in connect
return self.loaded_dbapi.connect(*cargs, **cparams) # type: ignore[no-any-return] # NOQA: E501
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\dialects\postgresql\asyncpg.py", line 955, in connect
await_only(creator_fn(*arg, **kw)),
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 132, in await_only
return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\sqlalchemy\util\_concurrency_py3k.py", line 196, in greenlet_spawn
value = await result
^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connection.py", line 2443, in connect
return await connect_utils._connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<22 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1249, in _connect
raise last_error or exceptions.TargetServerAttributeNotMatched(
...<2 lines>...
)
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1218, in _connect
conn = await _connect_addr(
^^^^^^^^^^^^^^^^^^^^
...<6 lines>...
)
^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1054, in _connect_addr
return await __connect_addr(params, True, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 1099, in __connect_addr
tr, pr = await connector
^^^^^^^^^^^^^^^
File "D:\Project\stock\backend\.venv\Lib\site-packages\asyncpg\connect_utils.py", line 969, in _create_ssl_connection
tr, pr = await loop.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>...
host, port)
^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1168, in create_connection
raise exceptions[0]
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1143, in create_connection
sock = await self._connect_sock(
^^^^^^^^^^^^^^^^^^^^^^^^^
exceptions, addrinfo, laddr_infos)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\base_events.py", line 1042, in _connect_sock
await self.sock_connect(sock, address)
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\proactor_events.py", line 728, in sock_connect
return await self._proactor.connect(sock, address)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\windows_events.py", line 804, in _poll
value = callback(transferred, key, ov)
File "C:\Users\cirry\scoop\apps\python\current\Lib\asyncio\windows_events.py", line 600, in finish_connect
ov.getresult()
~~~~~~~~~~~~^^
ConnectionRefusedError: [WinError 1225] 远程计算机拒绝网络连接。
INFO: 127.0.0.1:62379 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62378 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:62397 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:62416 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62425 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62423 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:62433 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:62415 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:62429 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:62437 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63003 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d&end=2018-10-29 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63007 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2016-10-12 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63659 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2016-10-12 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63684 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2016-10-12 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63711 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2016-10-12 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63732 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2016-10-12 HTTP/1.1" 200 OK
INFO: 127.0.0.1:63759 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:63757 - "GET /api/screener/preview/600529.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:63765 - "GET /api/screener/preview/600529.SH?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:56553 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:56569 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:56572 - "GET /api/screener/sync/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:56582 - "GET /api/screener/queries?limit=20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:56581 - "POST /api/screener/run HTTP/1.1" 200 OK
INFO: 127.0.0.1:56608 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:56617 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:56623 - "GET /api/screener/sync/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:56628 - "GET /api/screener/queries?limit=20 HTTP/1.1" 200 OK
INFO: 127.0.0.1:56627 - "POST /api/screener/run HTTP/1.1" 200 OK
INFO: 127.0.0.1:56694 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:56691 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:56732 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:56744 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:56747 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:56746 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
==== restart 2026-08-15 23:03:42 ====
INFO: Will watch for changes in these directories: ['D:\\Project\\stock\\backend']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [17652] using WatchFiles
INFO: Started server process [23704]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:61442 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:61447 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:61456 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:61453 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:61543 - "GET /api/stocks?limit=1 HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:61544 - "GET /api/stocks?limit=1 HTTP/1.1" 401 Unauthorized
WARNING: WatchFiles detected changes in 'app\api.py'. Reloading...
INFO: 127.0.0.1:65392 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:65410 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:65413 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:65412 - "GET /api/stocks?limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:65424 - "GET /api/stocks?limit=3 HTTP/1.1" 200 OK
==== restart 2026-08-15 23:37:04 ====
INFO: Will watch for changes in these directories: ['D:\\Project\\stock\\backend']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [48108] using WatchFiles
INFO: Started server process [47480]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:49363 - "GET /api/stocks?limit=3 HTTP/1.1" 200 OK
WARNING: WatchFiles detected changes in 'app\api.py'. Reloading...
==== restart 2026-08-15 23:46:54 ====
error: Failed to spawn: `uvicorn`
Caused by: program not found
INFO: Will watch for changes in these directories: ['D:\\Project\\stock\\backend']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [42580] using WatchFiles
INFO: Started server process [46816]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:50670 - "GET /api/stocks?limit=1 HTTP/1.1" 401 Unauthorized
INFO: 127.0.0.1:50683 - "GET /api/stocks?limit=3&sort=total_mv&order=desc HTTP/1.1" 200 OK
INFO: 127.0.0.1:50686 - "GET /api/stocks?limit=3&sort=turnover_rate&order=desc HTTP/1.1" 200 OK
INFO: 127.0.0.1:50687 - "GET /api/stocks?limit=3&sort=pe_ttm&order=asc HTTP/1.1" 200 OK
INFO: 127.0.0.1:50688 - "GET /api/stocks?limit=3& HTTP/1.1" 200 OK
INFO: 127.0.0.1:51208 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:51217 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:51224 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:51223 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51230 - "GET /api/stocks?sort=pe_ttm&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51231 - "GET /api/stocks?sort=pe_ttm&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51241 - "GET /api/stocks?sort=pe_ttm&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51243 - "GET /api/stocks?sort=pe_ttm&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51248 - "GET /api/stocks?sort=total_mv&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51265 - "GET /api/stocks?sort=turnover_rate&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51273 - "GET /api/stocks?sort=total_mv&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51315 - "GET /api/trades?ts_code=688825.SH HTTP/1.1" 200 OK
INFO: 127.0.0.1:51320 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:51319 - "GET /api/screener/preview/688825.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:51368 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:51375 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:51384 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51385 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:51845 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:51843 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:51958 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:51957 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:52092 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:52094 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:52455 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:52453 - "GET /api/trades?ts_code=000001.SZ HTTP/1.1" 200 OK
INFO: 127.0.0.1:52454 - "GET /api/screener/preview/000001.SZ?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:52465 - "GET /api/screener/preview/000001.SZ?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
WARNING: WatchFiles detected changes in 'app\data\market_overview.py'. Reloading...
INFO: 127.0.0.1:53348 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:53466 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53593 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:53600 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53614 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:53616 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:53772 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:54143 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:54156 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:54155 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:54160 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:54166 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:54952 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:55237 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:55254 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:55252 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:55259 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:55269 - "GET /api/screener/sync/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:55280 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:55282 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:55281 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:55286 - "GET /api/stocks?sort=circ_mv&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:55294 - "GET /api/stocks?sort=total_mv&order=desc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:55318 - "GET /api/trades?ts_code=603259.SH HTTP/1.1" 200 OK
INFO: 127.0.0.1:55320 - "GET /api/watchlist HTTP/1.1" 200 OK
INFO: 127.0.0.1:55319 - "GET /api/screener/preview/603259.SH?limit=500&adjust=qfq&timeframe=1d HTTP/1.1" 200 OK
INFO: 127.0.0.1:55330 - "GET /api/screener/preview/603259.SH?limit=800&adjust=qfq&timeframe=1d&end=2024-07-24 HTTP/1.1" 200 OK
INFO: 127.0.0.1:55349 - "GET /api/screener/preview/603259.SH?limit=800&adjust=qfq&timeframe=1d&end=2021-04-07 HTTP/1.1" 200 OK
INFO: 127.0.0.1:55433 - "GET /api/stocks?sort=total_mv&order=desc&limit=100&offset=100 HTTP/1.1" 200 OK
INFO: 127.0.0.1:56175 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:56189 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:56208 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:56204 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:56279 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:56281 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:56621 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:56638 - "GET /api/market/overview HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:56637 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:56644 - "GET /api/market/overview HTTP/1.1" 404 Not Found
==== restart 2026-08-16 20:03:31 ====
INFO: Will watch for changes in these directories: ['D:\\Project\\stock\\backend']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [37952] using WatchFiles
INFO: Started server process [45584]
INFO: Started reloader process [40700] using WatchFiles
INFO: Started server process [42044]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:59228 - "GET /api/health HTTP/1.1" 200 OK
INFO: 127.0.0.1:59686 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59399 - "GET /api/auth/me HTTP/1.1" 200 OK
INFO: 127.0.0.1:59722 - "GET /api/preferences HTTP/1.1" 200 OK
INFO: 127.0.0.1:59723 - "POST /api/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:59725 - "GET /api/stocks/facets HTTP/1.1" 200 OK
INFO: 127.0.0.1:59724 - "GET /api/stocks?sort=symbol&order=asc&limit=100&offset=0 HTTP/1.1" 200 OK
INFO: 127.0.0.1:59733 - "GET /api/trades?ts_code=000006.SZ HTTP/1.1" 200 OK
INFO: 127.0.0.1:59736 - "GET /api/watchlist HTTP/1.1" 200 OK
WARNING: WatchFiles detected changes in 'debug_gaps.py', 'debug_counts.py', 'debug_future.py', 'debug_preview.py', 'debug_live.py', 'debug_md.py'. Reloading...

View File

@@ -129,7 +129,22 @@ const g = (k: string) => (ts: number) => {
};
// 动态 MA按周期组合注册一次figures 的 key 必须静态,故按签名建缓存)
// 前端直接从收盘价计算 MA无需后端重拉数据切换均线周期即时响应
const _maReg = new Set<string>();
/** 滚动均值O(n) 滑动窗口min_periods=1与后端 pandas rolling 行为一致) */
function computeMA(closes: number[], period: number): (number | null)[] {
const n = closes.length;
const result: (number | null)[] = new Array(n);
let sum = 0;
for (let i = 0; i < n; i++) {
sum += closes[i];
if (i >= period) sum -= closes[i - period];
result[i] = sum / Math.min(i + 1, period);
}
return result;
}
function ensureMaIndicator(periods: number[]) {
const sig = [...periods].sort((a, b) => a - b).join('_');
if (_maReg.has(sig)) return `pv-ma-${sig}`;
@@ -140,11 +155,20 @@ function ensureMaIndicator(periods: number[]) {
key: `ma${p}`, title: `MA${p}`, type: 'line',
styles: () => ({ color: MA_COLORS[i % MA_COLORS.length] }),
})),
calc: (d: KLineData[]) => d.map((bar) => {
calc: (d: KLineData[]) => {
// 前端直接按收盘价计算 MA不从后端 PV 读取
const closes = d.map((b) => b.close);
const maValues: Record<string, (number | null)[]> = {};
for (const p of periods) maValues[`ma${p}`] = computeMA(closes, p);
return d.map((_, i) => {
const row: Record<string, number | undefined> = {};
for (const p of periods) row[`ma${p}`] = g(`ma${p}`)(bar.timestamp);
for (const p of periods) {
const v = maValues[`ma${p}`][i];
if (v != null) row[`ma${p}`] = v;
}
return row;
}),
});
},
});
_maReg.add(sig);
return `pv-ma-${sig}`;

View File

@@ -385,8 +385,7 @@ watch(active, (code) => {
}, { immediate: true });
watch(adjust, () => load(active.value));
watch(timeframe, () => load(active.value));
// MA 周期变化也要重拉后端按 mas 计算指标序列
watch(maPeriods, () => load(active.value));
// MA 周期变化:前端直接从收盘价计算,无需重拉后端数据DetailKLine.vue 的 watch 会触发图表重建
// 切股时同步自选状态
watch(active, (code) => {