Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cce836cc6 |
@@ -8,7 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
daily-backup:
|
||||
runs-on: act-runner
|
||||
runs-on: ubuntu-latest
|
||||
name: Daily Backup
|
||||
|
||||
steps:
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
ls -lh backups/ | tail -5
|
||||
|
||||
weekly-full-backup:
|
||||
runs-on: act-runner
|
||||
runs-on: ubuntu-latest
|
||||
name: Weekly Full Backup
|
||||
|
||||
# 매주 월요일 1:00 UTC
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
df -h | grep -E "Filesystem|data"
|
||||
|
||||
backup-health-check:
|
||||
runs-on: act-runner
|
||||
runs-on: ubuntu-latest
|
||||
name: Backup Health Check
|
||||
|
||||
# 매일 12:00 UTC
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
du -sh backups/ | awk '{print "Total size: " $1}'
|
||||
|
||||
test-recovery:
|
||||
runs-on: act-runner
|
||||
runs-on: ubuntu-latest
|
||||
name: Monthly Recovery Test
|
||||
|
||||
# 매월 1일 2:00 UTC
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
backup:
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run backup
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build-calibration-backlog:
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
|
||||
@@ -20,7 +20,7 @@ on:
|
||||
|
||||
jobs:
|
||||
validate-core:
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
@@ -154,7 +154,7 @@ jobs:
|
||||
run: python3 tools/validate_snapshot_admin_workflow_v1.py
|
||||
|
||||
validate-ui-and-storage:
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
needs: validate-core
|
||||
if: github.event_name != 'push'
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ on:
|
||||
jobs:
|
||||
validate-kis-config-smoke:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
run: |
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
|
||||
collect-kis-data-live:
|
||||
if: github.event_name == 'schedule'
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
evaluate-qualitative-sell:
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
# Push-only smoke gate: no deployment, no web UI smoke, no long-running side effects.
|
||||
validate-snapshot-admin-smoke:
|
||||
if: github.event_name == 'push'
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
run: |
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
# Manual dispatch gate: full workflow + web UI validation only.
|
||||
validate-snapshot-admin-full:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: self-hosted
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
run: |
|
||||
|
||||
@@ -9,7 +9,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
deploy-snapshot-admin:
|
||||
runs-on: [self-hosted, snapshot-admin-host]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
|
||||
@@ -14,7 +14,7 @@ on:
|
||||
|
||||
jobs:
|
||||
null-policy-validation:
|
||||
runs-on: act-runner
|
||||
runs-on: ubuntu-latest
|
||||
name: NULL Policy Validation
|
||||
|
||||
steps:
|
||||
|
||||
@@ -168,16 +168,13 @@ def _issue_or_reuse_token(creds: KisCredentials) -> str:
|
||||
|
||||
# 2. 토큰이 만료되었거나 없을 시 KIS API로 새로 발급 요청
|
||||
requests = _requests()
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{creds.domain}/oauth2/tokenP",
|
||||
json={"grant_type": "client_credentials", "appkey": creds.app_key, "appsecret": creds.app_secret},
|
||||
timeout=15,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
body = resp.json()
|
||||
except Exception as exc:
|
||||
raise RuntimeError("KIS token refresh failed; check credentials and API availability.") from exc
|
||||
resp = requests.post(
|
||||
f"{creds.domain}/oauth2/tokenP",
|
||||
json={"grant_type": "client_credentials", "appkey": creds.app_key, "appsecret": creds.app_secret},
|
||||
timeout=15,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
body = resp.json()
|
||||
access_token = body["access_token"]
|
||||
expires_in_sec = int(body.get("expires_in", 86400))
|
||||
expires_at = dt.datetime.now(dt.timezone.utc) + dt.timedelta(seconds=expires_in_sec)
|
||||
@@ -212,12 +209,9 @@ def _send_request(creds: KisCredentials, path: str, tr_id: str, params: dict[str
|
||||
"custtype": "P",
|
||||
}
|
||||
requests = _requests()
|
||||
try:
|
||||
resp = requests.get(f"{creds.domain}{path}", headers=headers, params=params, timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
except Exception as exc:
|
||||
raise RuntimeError(f"KIS read-only request failed for {path} / {tr_id}.") from exc
|
||||
resp = requests.get(f"{creds.domain}{path}", headers=headers, params=params, timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
# ── 조회(read-only) 함수 — 전부 GET, 전부 quotations/ranking 카테고리 (실측 확인) ──────────
|
||||
|
||||
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
"""KIS-first data collector for the CI scheduler.
|
||||
|
||||
The collector treats SQLite as the canonical persistence layer.
|
||||
`GatherTradingData.json` is emitted only after the DB-backed collection run
|
||||
finishes, so the JSON acts as a derived reporting artifact rather than the
|
||||
source of truth.
|
||||
The collector uses the existing `GatherTradingData.json` snapshot as the seed
|
||||
universe, then enriches Korean tickers with read-only KIS quotations and
|
||||
orderbook data, while retaining Naver/Yahoo fallbacks when available.
|
||||
The canonical persistence target is SQLite.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user