Add separate kline.db and pre-seed small-account four-product K-lines on startup.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# Copyright (c) 2025-2026 马建军. All rights reserved.
|
||||
# 专有软件 — 未经授权禁止复制、传播、转售。
|
||||
# 详见 LICENSE.zh-CN.txt
|
||||
|
||||
"""20 万以下四品种 K 线预下载(玉米、豆粕、甲醇、螺纹钢)。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
from modules.core.symbols import PRODUCTS, resolve_main_contract
|
||||
from modules.market.kline_chart import fetch_sina_klines, ths_to_sina_chart_symbol
|
||||
from modules.market.kline_store import (
|
||||
connect_kline_db,
|
||||
ensure_kline_tables,
|
||||
load_meta,
|
||||
save_bars,
|
||||
)
|
||||
from modules.trading.product_recommend import (
|
||||
SMALL_ACCOUNT_PRODUCT_THS,
|
||||
normalize_product_ths,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 小账户默认预下载周期(行情页 + 关键位常用)
|
||||
SMALL_ACCOUNT_KLINE_PERIODS = ("5m", "15m", "1h", "d")
|
||||
MIN_SEED_BARS = 30
|
||||
_SEED_LOCK = threading.Lock()
|
||||
_SEED_STARTED = False
|
||||
|
||||
|
||||
def _small_account_products() -> list[dict]:
|
||||
allowed = {x.upper() for x in SMALL_ACCOUNT_PRODUCT_THS}
|
||||
out: list[dict] = []
|
||||
for p in PRODUCTS:
|
||||
root = normalize_product_ths(p.get("ths") or "")
|
||||
if root.upper() in allowed:
|
||||
out.append(p)
|
||||
return out
|
||||
|
||||
|
||||
def _resolve_main_symbol(product: dict) -> Optional[str]:
|
||||
try:
|
||||
from modules.core.symbols import _main_index, _main_index_lock
|
||||
|
||||
with _main_index_lock:
|
||||
cached = (_main_index or {}).get(product.get("sina") or "")
|
||||
if cached and cached.get("ths_code"):
|
||||
return str(cached["ths_code"])
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
main = resolve_main_contract(product)
|
||||
if main and main.get("ths_code"):
|
||||
return str(main["ths_code"])
|
||||
except Exception as exc:
|
||||
logger.debug("resolve main for seed %s: %s", product.get("ths"), exc)
|
||||
try:
|
||||
from modules.core.symbols import _stub_main_contract
|
||||
|
||||
stub = _stub_main_contract(product)
|
||||
if stub and stub.get("ths_code"):
|
||||
return str(stub["ths_code"])
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def seed_small_account_klines(
|
||||
*,
|
||||
db_path: Optional[str] = None,
|
||||
force: bool = False,
|
||||
) -> dict[str, int]:
|
||||
"""下载四品种主力合约 K 线到独立库;已存在且充足时跳过。"""
|
||||
conn = connect_kline_db(db_path)
|
||||
try:
|
||||
ensure_kline_tables(conn)
|
||||
saved: dict[str, int] = {}
|
||||
for product in _small_account_products():
|
||||
sym = _resolve_main_symbol(product)
|
||||
if not sym:
|
||||
continue
|
||||
chart_sym = ths_to_sina_chart_symbol(sym)
|
||||
if not chart_sym:
|
||||
continue
|
||||
for period in SMALL_ACCOUNT_KLINE_PERIODS:
|
||||
key = f"{sym}:{period}"
|
||||
meta = load_meta(conn, chart_sym, period)
|
||||
if (
|
||||
not force
|
||||
and meta
|
||||
and int(meta.get("bar_count") or 0) >= MIN_SEED_BARS
|
||||
):
|
||||
continue
|
||||
try:
|
||||
bars = fetch_sina_klines(sym, period) or []
|
||||
except Exception as exc:
|
||||
logger.warning("seed kline fetch failed %s %s: %s", sym, period, exc)
|
||||
continue
|
||||
if len(bars) < MIN_SEED_BARS:
|
||||
logger.debug(
|
||||
"seed kline too few bars %s %s: %d",
|
||||
sym, period, len(bars),
|
||||
)
|
||||
continue
|
||||
n = save_bars(conn, chart_sym, period, bars)
|
||||
saved[key] = n
|
||||
logger.info("seeded kline %s %s (%d bars)", sym, period, n)
|
||||
return saved
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def start_small_account_kline_seed(*, db_path: Optional[str] = None, delay_sec: float = 8.0) -> None:
|
||||
"""后台预下载(仅执行一次)。"""
|
||||
global _SEED_STARTED
|
||||
with _SEED_LOCK:
|
||||
if _SEED_STARTED:
|
||||
return
|
||||
_SEED_STARTED = True
|
||||
|
||||
def _run() -> None:
|
||||
if delay_sec > 0:
|
||||
time.sleep(delay_sec)
|
||||
try:
|
||||
saved = seed_small_account_klines(db_path=db_path)
|
||||
if saved:
|
||||
logger.info("small-account kline seed done: %s", ", ".join(saved.keys()))
|
||||
else:
|
||||
logger.debug("small-account kline seed: nothing new to download")
|
||||
except Exception as exc:
|
||||
logger.warning("small-account kline seed failed: %s", exc)
|
||||
|
||||
threading.Thread(target=_run, daemon=True, name="kline-seed").start()
|
||||
Reference in New Issue
Block a user