Initial commit: stock market platform

This commit is contained in:
admin
2026-06-11 01:41:47 +08:00
commit 63718906e9
62 changed files with 8962 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
import json
from fastapi import APIRouter, Depends, Query
from app.api.deps import get_current_user
from app.models.user import User
from app.core.redis import get_redis
from app.services import stock_service
router = APIRouter(prefix="/stocks", tags=["stocks"])
CACHE_TTL = 30 # seconds
# ── market overview ───────────────────────────────────────────────────────────
@router.get("/market/overview")
async def market_overview(current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = "market:overview"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_market_overview()
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data
# ── heatmap ───────────────────────────────────────────────────────────────────
@router.get("/market/heatmap")
async def market_heatmap(current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = "market:heatmap"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_all_stocks_spot()
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data
# ── sector ────────────────────────────────────────────────────────────────────
@router.get("/market/sectors")
async def market_sectors(current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = "market:sectors"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_sector_spot()
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data
# ── single stock quote ────────────────────────────────────────────────────────
@router.get("/{symbol}/quote")
async def stock_quote(symbol: str, current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = f"quote:{symbol}"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_stock_quote(symbol)
if data:
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data or {}
# ── K-line ────────────────────────────────────────────────────────────────────
@router.get("/{symbol}/kline")
async def stock_kline(
symbol: str,
period: str = Query("daily", pattern="^(daily|weekly|monthly)$"),
adjust: str = Query("qfq", pattern="^(qfq|hfq|)$"),
limit: int = Query(250, ge=10, le=1000),
current_user: User = Depends(get_current_user),
):
redis = await get_redis()
cache_key = f"kline:{symbol}:{period}:{adjust}:{limit}"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_kline(symbol, period, adjust, limit)
await redis.setex(cache_key, 300, json.dumps(data))
return data
# ── intraday ──────────────────────────────────────────────────────────────────
@router.get("/{symbol}/intraday")
async def stock_intraday(symbol: str, current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = f"intraday:{symbol}"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_intraday(symbol)
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data
# ── 5-day ─────────────────────────────────────────────────────────────────────
@router.get("/{symbol}/fiveday")
async def stock_fiveday(symbol: str, current_user: User = Depends(get_current_user)):
redis = await get_redis()
cache_key = f"fiveday:{symbol}"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
data = await stock_service.get_five_day(symbol)
await redis.setex(cache_key, CACHE_TTL, json.dumps(data))
return data
# ── search ────────────────────────────────────────────────────────────────────
@router.get("/search")
async def search(
q: str = Query(..., min_length=1),
limit: int = Query(20, ge=1, le=50),
current_user: User = Depends(get_current_user),
):
return await stock_service.search_stocks(q, limit)