astock-agent/backend/app/config.py
2026-04-08 00:28:01 +08:00

88 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""应用配置管理"""
import os
from datetime import datetime
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# Tushare Pro
tushare_token: str = ""
# 服务配置
host: str = "0.0.0.0"
port: int = 8000
debug: bool = False
# 数据库
database_url: str = "sqlite:///./astock.db"
# 缓存 TTL
cache_ttl_realtime: int = 30 # 实时数据 30 秒
cache_ttl_daily: int = 300 # 日级数据 5 分钟
cache_ttl_sector: int = 300 # 板块数据 5 分钟
cache_ttl_static: int = 86400 # 静态数据 24 小时
# Tushare 限流
tushare_request_delay: float = 0.3 # 请求间隔(秒)
tushare_max_retry: int = 3 # 最大重试次数
# 筛选参数
top_sector_count: int = 5 # 关注板块数量
top_stock_count: int = 20 # 进入技术面筛选的个股数
min_turnover_rate: float = 3.0 # 最小换手率 %
max_turnover_rate: float = 15.0 # 最大换手率 %
min_circ_mv: float = 50.0 # 最小流通市值(亿)
max_circ_mv: float = 500.0 # 最大流通市值(亿)
min_list_days: int = 60 # 最小上市天数
# 买入信号阈值
buy_score_threshold: int = 60 # 买入最低分
buy_min_signals: int = 3 # 最少满足信号数
# 风控
stop_loss_pct: float = 5.0 # 止损比例 %
# LLM (DeepSeek)
deepseek_api_key: str = ""
deepseek_base_url: str = "https://api.deepseek.com/v1"
deepseek_model: str = "deepseek-chat"
llm_max_tokens: int = 2000
llm_temperature: float = 0.3
# 前端
frontend_url: str = "http://localhost:3000"
# JWT 认证
jwt_secret: str = "change-me-in-production"
jwt_expiry_hours: int = 24
jwt_algorithm: str = "HS256"
# 默认管理员(首次启动自动创建)
admin_username: str = "admin"
admin_password: str = "admin123"
model_config = {"env_file": ".env", "env_prefix": "ASTOCK_"}
settings = Settings()
def is_trading_hours() -> bool:
"""判断当前是否在 A 股交易时段9:30-11:30, 13:00-15:00"""
from zoneinfo import ZoneInfo
now = datetime.now(ZoneInfo("Asia/Shanghai"))
weekday = now.weekday() # 0=Mon, 6=Sun
if weekday >= 5:
return False
t = now.hour * 100 + now.minute
return (930 <= t <= 1130) or (1300 <= t <= 1500)
def is_pre_close() -> bool:
"""判断是否在收盘后、数据更新前15:00-15:30 数据尚未完全更新)"""
from zoneinfo import ZoneInfo
now = datetime.now(ZoneInfo("Asia/Shanghai"))
t = now.hour * 100 + now.minute
return 1500 <= t <= 1530