auto: 일일 백업 2026-06-11 02:00
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -88,14 +88,19 @@ def _flow_cache_path(code: str):
|
||||
|
||||
|
||||
def investor_flow(code: str, days: int = config.FLOW_DAYS) -> list[dict]:
|
||||
"""최근 days 일 외국인·기관·개인 순매수 (최신순). 60분 TTL 캐시."""
|
||||
"""최근 days 일 외국인·기관·개인 순매수 (최신순). 60분 TTL 캐시 + 스캔 내 메모."""
|
||||
mk = (code, days)
|
||||
if mk in _FLOW_MEMO_SCAN:
|
||||
return _FLOW_MEMO_SCAN[mk]
|
||||
path = _flow_cache_path(code)
|
||||
now = time.time()
|
||||
if path.exists():
|
||||
try:
|
||||
cached = json.loads(path.read_text())
|
||||
if now - cached.get('ts', 0) < FLOW_TTL_SEC:
|
||||
return cached.get('rows', [])[:days]
|
||||
rows = cached.get('rows', [])[:days]
|
||||
_FLOW_MEMO_SCAN[mk] = rows
|
||||
return rows
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
@@ -105,6 +110,7 @@ def investor_flow(code: str, days: int = config.FLOW_DAYS) -> list[dict]:
|
||||
return []
|
||||
FLOW_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps({'ts': now, 'rows': rows}, ensure_ascii=False))
|
||||
_FLOW_MEMO_SCAN[mk] = rows[:days]
|
||||
return rows[:days]
|
||||
|
||||
|
||||
@@ -116,11 +122,15 @@ def flow_net(rows: list[dict]) -> dict:
|
||||
|
||||
|
||||
def analyst(code: str, price: int) -> dict | None:
|
||||
"""애널 게이트/가점용. 캐시 미스(네트워크 발생) 시에만 페이싱 — 연속 크롤링 차단 회피."""
|
||||
"""애널 게이트/가점용. 캐시 미스(네트워크 발생) 시에만 페이싱 + 스캔 내 메모."""
|
||||
if code in _ANL_MEMO_SCAN:
|
||||
return _ANL_MEMO_SCAN[code]
|
||||
fresh = (_cache_fresh(FNGUIDE_CACHE_DIR / f'{code}.json')
|
||||
and _cache_fresh(WISEREPORT_CACHE_DIR / f'{code}.json'))
|
||||
try:
|
||||
return _analyst_query(code, price)
|
||||
out = _analyst_query(code, price)
|
||||
_ANL_MEMO_SCAN[code] = out
|
||||
return out
|
||||
finally:
|
||||
if not fresh:
|
||||
time.sleep(ANALYST_PACING_SEC)
|
||||
@@ -168,10 +178,27 @@ def _analyst_query(code: str, price: int) -> dict | None:
|
||||
}
|
||||
|
||||
|
||||
# 스캔 1회 동안 호가 공유 — 같은 스캔에서 같은 종목은 같은 체결가 (선수 간 체결 공정성 + API 절감).
|
||||
# engine._gather 가 스캔 시작마다 reset.
|
||||
_BOOK_MEMO: dict = {}
|
||||
_FLOW_MEMO_SCAN: dict = {} # 스캔 1회 동안 종목별 수급 공유 (파라미터 무관)
|
||||
_ANL_MEMO_SCAN: dict = {} # 스캔 1회 동안 종목별 애널 공유 (파라미터 무관)
|
||||
|
||||
|
||||
def reset_book_memo():
|
||||
_BOOK_MEMO.clear()
|
||||
_FLOW_MEMO_SCAN.clear()
|
||||
_ANL_MEMO_SCAN.clear()
|
||||
|
||||
|
||||
def quote_book(code: str) -> dict | None:
|
||||
"""체결가용 호가 (매도1/매수1). 실패 시 None."""
|
||||
"""체결가용 호가 (매도1/매수1). 스캔 내 종목당 1회 조회 후 공유. 실패 시 None."""
|
||||
if code in _BOOK_MEMO:
|
||||
return _BOOK_MEMO[code]
|
||||
try:
|
||||
return kc.get_quote_book(code)
|
||||
book = kc.get_quote_book(code)
|
||||
except Exception as e:
|
||||
sys.stderr.write(f'[data] quote_book {code} 실패: {e}\n')
|
||||
return None
|
||||
book = None
|
||||
_BOOK_MEMO[code] = book
|
||||
return book
|
||||
|
||||
Reference in New Issue
Block a user