50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
||
"""参数变更审计:检测 rules.yaml 是否被意外修改"""
|
||
import hashlib
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import yaml
|
||
|
||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||
RULES_PATH = REPO_ROOT / "rules.yaml"
|
||
|
||
def compute_semantic_hash(rules_dict):
|
||
"""语义哈希:忽略格式差异,只对关键参数字段做哈希"""
|
||
import json
|
||
# 只取影响策略行为的字段,排除meta、注释等
|
||
critical = {
|
||
'confirm': rules_dict.get('confirm', {}),
|
||
'screener': rules_dict.get('screener', {}),
|
||
'pa_engine': rules_dict.get('pa_engine', {}),
|
||
'signal_weights': rules_dict.get('signal_weights', {}),
|
||
'tracker': rules_dict.get('tracker', {}),
|
||
'sentiment': rules_dict.get('sentiment', {}),
|
||
'event_driven': rules_dict.get('event_driven', {}),
|
||
'learned_rules': rules_dict.get('learned_rules', []),
|
||
}
|
||
canonical = json.dumps(critical, sort_keys=True, default=str)
|
||
return hashlib.sha256(canonical.encode()).hexdigest()[:16]
|
||
|
||
def main():
|
||
raw = RULES_PATH.read_bytes()
|
||
rules = yaml.safe_load(raw)
|
||
|
||
current_hash = compute_semantic_hash(rules)
|
||
stored_hash = rules.get('meta', {}).get('rules_checksum', '')
|
||
|
||
if not stored_hash:
|
||
print("⚠️ rules.yaml 缺少校验和 — 请在meta.rules_checksum写入当前hash")
|
||
print(f" 当前: {current_hash}")
|
||
return 1
|
||
|
||
if current_hash != stored_hash:
|
||
print(f"🔴 参数被修改! 存储校验: {stored_hash}, 当前: {current_hash}")
|
||
return 2
|
||
|
||
print(f"✅ 参数校验通过 (hash={current_hash})")
|
||
return 0
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(main())
|