Initial commit

This commit is contained in:
wanghep
2026-03-20 21:47:30 +08:00
commit 2eab960303
83 changed files with 51694 additions and 0 deletions

View File

@ -0,0 +1,126 @@
import json
from pathlib import Path
from app.core.config import (
ALERT_TRIGGERS_DIR,
DAILY_STATS_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",
}
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,
]:
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)