KIS Open API 조회전용 연동 + 직접매매 절대금지 안전게이트
매수/매도 주문 및 계좌 잔고조회를 API로 직접 실행하지 않는다는 원칙을 코드 레벨에서 강제하는 안전게이트(governance/rules/06, 07)와 함께, 시세/호가/공매도거래비중 등 조회전용 KIS Open API 연동 및 SQLite 수집 파이프라인을 추가한다. - kis_api_client_v1: 모든 요청이 _assert_read_only를 통과해야 하며 /trading/ 경로·주문 TR_ID는 RuntimeError로 즉시 차단 - kis_data_collection_v1: KIS 우선 + Naver 폴백, 네트워크 실패는 개별 ticker 단위로 흡수(배치 전체 중단 없음) - data_collection_store_v1 / storage_backend_v1: SQLite 캐노니컬 저장소, PostgreSQL 전환 대비 백엔드 추상화 - Gitea 영업일 스케줄(2시간 간격) + CI 강제 게이트 (validate_no_direct_api_trading_v1, validate_kis_api_credentials_v1)
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
REQUIRED_PATTERNS = {
|
||||
".gitea/workflows/kis_data_collection.yml": [
|
||||
"secrets.KIS_APP_KEY_TEST",
|
||||
"secrets.KIS_APP_SECRET_TEST",
|
||||
"secrets.KIS_APP_KEY",
|
||||
"secrets.KIS_APP_SECRET",
|
||||
],
|
||||
".gitea/workflows/qualitative_sell_strategy.yml": [
|
||||
"secrets.KIS_APP_KEY_TEST",
|
||||
"secrets.KIS_APP_SECRET_TEST",
|
||||
"secrets.KIS_APP_KEY",
|
||||
"secrets.KIS_APP_SECRET",
|
||||
],
|
||||
".gitea/workflows/ci.yml": [
|
||||
"secrets.KIS_APP_KEY_TEST",
|
||||
"secrets.KIS_APP_SECRET_TEST",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
errors: list[str] = []
|
||||
evidence: dict[str, dict[str, bool]] = {}
|
||||
|
||||
for rel, patterns in REQUIRED_PATTERNS.items():
|
||||
path = ROOT / rel
|
||||
text = path.read_text(encoding="utf-8") if path.exists() else ""
|
||||
file_evidence: dict[str, bool] = {}
|
||||
if not path.exists():
|
||||
errors.append(f"missing:{rel}")
|
||||
evidence[rel] = file_evidence
|
||||
continue
|
||||
for pattern in patterns:
|
||||
found = pattern in text
|
||||
file_evidence[pattern] = found
|
||||
if not found:
|
||||
errors.append(f"{rel}:{pattern}")
|
||||
evidence[rel] = file_evidence
|
||||
|
||||
result = {
|
||||
"formula_id": "GITEA_SECRETS_CONTRACT_V1",
|
||||
"gate": "PASS" if not errors else "FAIL",
|
||||
"evidence": evidence,
|
||||
"errors": errors,
|
||||
}
|
||||
out = ROOT / "Temp" / "gitea_secrets_contract_v1.json"
|
||||
out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 0 if not errors else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user