import json from pathlib import Path from app.core.config import ( ALERT_TRIGGERS_DIR, CAPITAL_IMAGE_DIR, CAPITAL_IMAGE_UPLOADS_DIR, DAILY_STATS_DIR, MAIN_CAPITAL_FLOW_DIR, MAIN_CAPITAL_FLOW_UPLOADS_DIR, MINUTE_SNAPSHOTS_DIR, MONTHLY_STATS_DIR, PUSH_RECORDS_DIR, RAW_PAYLOADS_DIR, SOURCE_DIAGNOSTICS_FILE, SYSTEM_CONFIG_FILE, WEEKLY_STATS_DIR, ) DEFAULT_SYSTEM_CONFIG = { "product_name": "南向资金监控平台", "timezone": "Asia/Shanghai", "source_name": "东方财富", "source_strategy": "已接入东方财富历史与实时公开接口;历史来自 datacenter-web,实时来自 push2。", "realtime_collection_interval_seconds": 60, "history_backfill_start_date": "2026-01-01", "threshold_step_hkd_billion": 50, "five_minute_flow_alert_hkd_billion": 15, "five_minute_window_minutes": 5, "five_minute_cooldown_minutes": 5, "email_enabled": False, "sender_email": "alerts@example.com", "smtp_username": "alerts@example.com", "smtp_password": "", "smtp_host": "smtp.example.com", "smtp_port": 465, "recipients": ["ops@example.com"], "storage_backend": "mysql", "mysql_enabled": False, "mysql_host": "127.0.0.1", "mysql_port": 3306, "mysql_database": "southbound_monitor", "mysql_username": "root", "mysql_password": "", "mysql_charset": "utf8mb4", "llm_provider": "openai_compatible", "llm_api_key": "", "llm_base_url": "https://api.openai.com/v1", "llm_vision_model": "gpt-4.1-mini", "etf_enabled": True, "etf_realtime_interval_seconds": 60, "etf_3min_change_alert_percent": 0.8, "etf_alert_cooldown_minutes": 10, } DEFAULT_SOURCE_DIAGNOSTICS = { "source_name": "东方财富", "realtime_available": False, "historical_available": False, "last_success_at": None, "last_failure_at": None, "last_error_reason": "尚未执行东方财富真实同步任务。", "last_success_url": None, "last_persisted_at": None, } DEFAULT_MINUTE_SNAPSHOT = { "trade_date": "2026-03-20", "snapshot_time": None, "market_state": "closed", "total_net_inflow": None, "cumulative_net_inflow": None, "shanghai_net_inflow": None, "shenzhen_net_inflow": None, "buy_amount": None, "sell_amount": None, "net_buy_amount": None, "one_min_change": None, "five_min_change": None, "precision": "unavailable", "source_name": "东方财富", "source_url": None, "updated_at": None, "unavailable_reason": "尚未获取到今天的实时快照数据。", "threshold_progress": 0.0, "next_threshold_hkd_billion": 50, "minute_timeline": [], } DEFAULT_DAILY_STATS = { "start_date": "2026-01-01", "daily": [], "weekly": [], "monthly": [], "cumulative": [], "recent_trade_days": [], "summary": { "cumulative_net_inflow_hkd_billion": 0, "trading_day_count": 0, "max_single_day_inflow_hkd_billion": 0, "max_single_day_outflow_hkd_billion": 0, "longest_inflow_streak": 0, "longest_outflow_streak": 0, }, } DEFAULT_PUSH_RECORDS = {"records": []} def _ensure_json(path: Path, payload: dict) -> None: if path.exists(): return path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") def bootstrap_data() -> None: for directory in [ MINUTE_SNAPSHOTS_DIR, DAILY_STATS_DIR, WEEKLY_STATS_DIR, MONTHLY_STATS_DIR, PUSH_RECORDS_DIR, ALERT_TRIGGERS_DIR, RAW_PAYLOADS_DIR, CAPITAL_IMAGE_DIR, CAPITAL_IMAGE_UPLOADS_DIR, MAIN_CAPITAL_FLOW_DIR, MAIN_CAPITAL_FLOW_UPLOADS_DIR, ]: directory.mkdir(parents=True, exist_ok=True) _ensure_json(SYSTEM_CONFIG_FILE, DEFAULT_SYSTEM_CONFIG) _ensure_json(SOURCE_DIAGNOSTICS_FILE, DEFAULT_SOURCE_DIAGNOSTICS) _ensure_json(MINUTE_SNAPSHOTS_DIR / "2026-03-20.json", DEFAULT_MINUTE_SNAPSHOT) _ensure_json(DAILY_STATS_DIR / "summary.json", DEFAULT_DAILY_STATS) _ensure_json(PUSH_RECORDS_DIR / "records.json", DEFAULT_PUSH_RECORDS)