perf: prepare_sector_context ADX计算O(N^2)修复——calc_trend_strength移到板块外层只算一次(296板块x490天卡死), _get_external_factors补conn连接
This commit is contained in:
+22
-19
@@ -681,36 +681,39 @@ def _get_external_factors(code, dt):
|
||||
return _EXTERNAL_CACHE[key]
|
||||
result = {}
|
||||
try:
|
||||
import sqlite3
|
||||
_conn = sqlite3.connect(DB_PATH)
|
||||
# 行业动量 sec_ret20(sector_index_daily 20日涨跌)
|
||||
_srow = conn.execute("SELECT sector_name FROM stock_sectors WHERE code=? LIMIT 1", (code,)).fetchone()
|
||||
_srow = _conn.execute("SELECT sector_name FROM stock_sectors WHERE code=? LIMIT 1", (code,)).fetchone()
|
||||
if _srow and _srow[0]:
|
||||
_sector = _srow[0]
|
||||
_prev = conn.execute(
|
||||
_prev = _conn.execute(
|
||||
"SELECT close FROM sector_index_daily WHERE sector=? AND date<=? ORDER BY date DESC LIMIT 21",
|
||||
(_sector, dt)).fetchall()
|
||||
if len(_prev) >= 20 and _prev[-1][0] and _prev[-1][0] > 0:
|
||||
result['sec_ret20'] = round((_prev[0][0] - _prev[-1][0]) / _prev[-1][0] * 100, 2)
|
||||
# 新闻 3 日计数 news3
|
||||
_nrow = conn.execute(
|
||||
_nrow = _conn.execute(
|
||||
"SELECT COUNT(*) FROM stock_news WHERE code=? AND date>? AND date<=?",
|
||||
(code, _days_ago(dt, 3), dt)).fetchone()
|
||||
if _nrow:
|
||||
result['news3'] = _nrow[0]
|
||||
# 基本面分位 mcap_q/pe_q
|
||||
_frow = conn.execute(
|
||||
_frow = _conn.execute(
|
||||
"SELECT mcap_total, pe FROM stock_fundamentals WHERE code=?", (code,)).fetchone()
|
||||
if _frow and _frow[0]:
|
||||
_mcap = _frow[0]
|
||||
_t = conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE mcap_total>0 AND mcap_total<?", (_mcap,)).fetchone()[0]
|
||||
_tot = conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE mcap_total>0").fetchone()[0]
|
||||
_t = _conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE mcap_total>0 AND mcap_total<?", (_mcap,)).fetchone()[0]
|
||||
_tot = _conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE mcap_total>0").fetchone()[0]
|
||||
if _tot:
|
||||
result['mcap_q'] = round(_t / _tot, 3)
|
||||
if _frow and _frow[1]:
|
||||
_pe = _frow[1]
|
||||
_t = conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE pe>0 AND pe<?", (_pe,)).fetchone()[0]
|
||||
_tot = conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE pe>0").fetchone()[0]
|
||||
_t = _conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE pe>0 AND pe<?", (_pe,)).fetchone()[0]
|
||||
_tot = _conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE pe>0").fetchone()[0]
|
||||
if _tot:
|
||||
result['pe_q'] = round(_t / _tot, 3)
|
||||
_conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
_EXTERNAL_CACHE[key] = result
|
||||
@@ -744,6 +747,16 @@ def prepare_sector_context(start_date, end_date):
|
||||
sec_hl[sec].append((d, row[4], row[5]))
|
||||
for sec, series in by_sector.items():
|
||||
closes = [c for _, c, _ in series]
|
||||
# 2026-08-11 性能修复:ADX 全序列只算一次(原代码内层每天重算=O(N²),296板块×490天卡死)
|
||||
from backtest_framework import calc_trend_strength
|
||||
_hl = sec_hl.get(sec, [])
|
||||
_av = None
|
||||
if len(_hl) >= 20:
|
||||
_hs = [x[1] for x in _hl]
|
||||
_ls = [x[2] for x in _hl]
|
||||
_cs = [c for _, c, _ in series]
|
||||
if len(_cs) == len(_hl):
|
||||
_av = calc_trend_strength(_hs, _ls, _cs, 14)
|
||||
for i, (d, close, chg) in enumerate(series):
|
||||
above = slope = None
|
||||
if i >= 19:
|
||||
@@ -753,17 +766,7 @@ def prepare_sector_context(start_date, end_date):
|
||||
ma20_5 = sum(closes[i-24:i-4]) / 20
|
||||
if ma20_5 > 0:
|
||||
slope = round((ma20 - ma20_5) / ma20_5 * 100, 3)
|
||||
_adx = None
|
||||
_hl = sec_hl.get(sec, [])
|
||||
if len(_hl) >= 20 and i >= 14:
|
||||
from backtest_framework import calc_trend_strength
|
||||
_hs = [x[1] for x in _hl]
|
||||
_ls = [x[2] for x in _hl]
|
||||
_cs = [c for _, c, _ in series]
|
||||
if len(_cs) == len(_hl):
|
||||
_av = calc_trend_strength(_hs, _ls, _cs, 14)
|
||||
if i < len(_av):
|
||||
_adx = _av[i]
|
||||
_adx = _av[i] if (_av is not None and i < len(_av)) else None
|
||||
_SECTOR_CTX.setdefault(d, {})[sec] = {
|
||||
'change': chg, 'above_ma20': above, 'slope': slope, 'adx': _adx,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user