daef609e8b
- QmtBridgeSource: provides 增加 index_daily,新增 fetch_index_daily 方法 - task_kline_index: 优先级改为 qmt_bridge → mairui → sina 三级降级 - task_kline_5min: 优先用 qmt_bridge,不可用时降级 mairui - task_kline_daily: 优先级加入 qmt_bridge(首位) - config: 新增 qmt_bridge_url 配置项 - registry: qmt_bridge 注册信息同步更新 - docs: 新增 DATASETS_AND_SOURCES.md,完整说明数据集与数据源依赖关系 - AGENTS.md: 同步更新指数数据源描述
118 lines
3.2 KiB
Python
118 lines
3.2 KiB
Python
"""统一配置:从 .env / 环境变量读 PG、调度器、数据源开关等参数。
|
|
|
|
2026-06-16 重构:项目只支持 PostgreSQL,MySQL 字段全部移除。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
try:
|
|
from dotenv import load_dotenv
|
|
_HAS_DOTENV = True
|
|
except ImportError:
|
|
_HAS_DOTENV = False
|
|
|
|
|
|
_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
|
|
|
|
# 启动时自动把 .env 加载到 os.environ,使下游 `os.environ.get(...)` 代码
|
|
# (如 app/sources/mairui.py / xueqiu.py)能拿到 credentials。
|
|
if _HAS_DOTENV:
|
|
_env_file = _PROJECT_ROOT / ".env"
|
|
if _env_file.exists():
|
|
load_dotenv(_env_file, override=False)
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""应用配置。所有字段都可以通过环境变量或 .env 文件覆盖。"""
|
|
|
|
# Runtime mode: "docker" | "systemd"
|
|
# docker : 单容器运行,依赖进程内 scheduler 触发所有同步任务
|
|
# systemd : Linux 宿主机运行,由 systemd timer/service 触发任务,
|
|
# 进程内 scheduler 必须关闭,避免双调度器重叠
|
|
runtime_mode: str = "docker"
|
|
|
|
# Scheduler
|
|
scheduler_tick_seconds: int = 5
|
|
scheduler_timezone: str = "Asia/Shanghai"
|
|
scheduler_auto_seed: bool = True
|
|
|
|
# API
|
|
api_host: str = "0.0.0.0"
|
|
api_port: int = 8100
|
|
|
|
# Logging
|
|
log_level: str = "INFO"
|
|
log_dir: str = "./logs"
|
|
|
|
# Datasources
|
|
ds_baostock_enabled: bool = True
|
|
ds_sina_enabled: bool = True
|
|
xueqiu_token: str = ""
|
|
|
|
# PostgreSQL — 完整 URL(覆盖下面 PG_HOST 等)
|
|
pg_url: str = ""
|
|
pg_host: str = "127.0.0.1"
|
|
pg_port: int = 5432
|
|
pg_user: str = "market_sync"
|
|
pg_password: str = "market_sync"
|
|
pg_db_name: str = "market_data"
|
|
|
|
# QMT Bridge
|
|
qmt_bridge_url: str = "http://127.0.0.1:8610"
|
|
|
|
# Trading calendar
|
|
trading_holidays: str = ""
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=str(_PROJECT_ROOT / ".env"),
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=False,
|
|
extra="ignore",
|
|
)
|
|
|
|
@property
|
|
def project_root(self) -> Path:
|
|
return _PROJECT_ROOT
|
|
|
|
@property
|
|
def log_path(self) -> Path:
|
|
p = Path(self.log_dir)
|
|
if not p.is_absolute():
|
|
p = _PROJECT_ROOT / p
|
|
p.mkdir(parents=True, exist_ok=True)
|
|
return p
|
|
|
|
@property
|
|
def holidays_list(self) -> list[str]:
|
|
if not self.trading_holidays:
|
|
return []
|
|
return [d.strip() for d in self.trading_holidays.split(",") if d.strip()]
|
|
|
|
def pg_sqlalchemy_url(self) -> str:
|
|
"""构造 PG 的 SQLAlchemy URL(自动剥掉 +psycopg2 让 SQLAlchemy 决定 driver)。"""
|
|
if self.pg_url:
|
|
return self.pg_url
|
|
return (
|
|
f"postgresql+psycopg2://{self.pg_user}:{self.pg_password}"
|
|
f"@{self.pg_host}:{self.pg_port}/{self.pg_db_name}"
|
|
)
|
|
|
|
|
|
_settings: Optional[Settings] = None
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
"""全局单例。"""
|
|
global _settings
|
|
if _settings is None:
|
|
_settings = Settings()
|
|
return _settings
|
|
|
|
|
|
settings = get_settings()
|