fix:优化参数指数
This commit is contained in:
Binary file not shown.
BIN
crawler/__pycache__/indicator_smooth.cpython-311.pyc
Normal file
BIN
crawler/__pycache__/indicator_smooth.cpython-311.pyc
Normal file
Binary file not shown.
@@ -14,6 +14,13 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from crawler.indicator_smooth import (
|
||||
clamp as _indicator_clamp,
|
||||
smooth_retaliation as _smooth_retaliation,
|
||||
smooth_wall_street as _smooth_wall_street,
|
||||
wall_street_should_append as _wall_street_should_append,
|
||||
)
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
DB_PATH = os.environ.get("DB_PATH", str(PROJECT_ROOT / "server" / "data.db"))
|
||||
|
||||
@@ -26,8 +33,7 @@ MAX_DELTA_PER_MERGE = {
|
||||
"civilian_ships": 20, "airport_port": 10,
|
||||
}
|
||||
|
||||
# 反击情绪 / 华尔街:合理区间,避免爬虫单条提取 0 或 100 导致指标归零或打满
|
||||
RETALIATION_SMOOTH_WEIGHT = 0.6 # 当前值权重,1 - 此值为新值权重,使更新平滑
|
||||
# 反击情绪 / 华尔街:限幅与平滑见 crawler.indicator_smooth
|
||||
RETALIATION_HISTORY_MAX_ROWS = 300 # 反击历史条数上限,供前端曲线与回放使用
|
||||
WALL_STREET_TREND_MAX_ROWS = 200 # 趋势表保留最近条数,避免无限增长
|
||||
VALUE_CLAMP_MIN, VALUE_CLAMP_MAX = 1, 99 # 0/100 视为异常,写入前夹在 [1,99]
|
||||
@@ -206,17 +212,13 @@ def merge(extracted: Dict[str, Any], db_path: Optional[str] = None) -> bool:
|
||||
updated = True
|
||||
except Exception:
|
||||
pass
|
||||
# retaliation:平滑更新,避免单条新闻 0/100 导致指标归零或打满
|
||||
# retaliation:由 indicator_smooth 计算平滑值 + 单步变化上限,避免爬虫连续更新导致剧烈波动
|
||||
if "retaliation" in extracted:
|
||||
r = extracted["retaliation"]
|
||||
raw = max(VALUE_CLAMP_MIN, min(VALUE_CLAMP_MAX, int(r.get("value", 50))))
|
||||
raw = _indicator_clamp(int(r.get("value", 50)))
|
||||
row = conn.execute("SELECT value FROM retaliation_current WHERE id = 1").fetchone()
|
||||
current = int(row[0]) if row else 50
|
||||
current = max(VALUE_CLAMP_MIN, min(VALUE_CLAMP_MAX, current))
|
||||
new_val = round(
|
||||
RETALIATION_SMOOTH_WEIGHT * current + (1 - RETALIATION_SMOOTH_WEIGHT) * raw
|
||||
)
|
||||
new_val = max(VALUE_CLAMP_MIN, min(VALUE_CLAMP_MAX, new_val))
|
||||
new_val = _smooth_retaliation(raw, current)
|
||||
ts = (r.get("time") or datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z"))[:25]
|
||||
conn.execute("INSERT OR REPLACE INTO retaliation_current (id, value) VALUES (1, ?)", (new_val,))
|
||||
conn.execute("INSERT INTO retaliation_history (time, value) VALUES (?, ?)", (ts, new_val))
|
||||
@@ -227,13 +229,19 @@ def merge(extracted: Dict[str, Any], db_path: Optional[str] = None) -> bool:
|
||||
(n_ret - RETALIATION_HISTORY_MAX_ROWS,),
|
||||
)
|
||||
updated = True
|
||||
# wall_street_trend:限幅后写入,并保留最近 N 条避免表无限增长
|
||||
# wall_street_trend:由 indicator_smooth 与上一点平滑 + 最小写入间隔,抑制密集报道导致的锯齿
|
||||
if "wall_street" in extracted:
|
||||
w = extracted["wall_street"]
|
||||
raw = int(w.get("value", 50))
|
||||
val = max(VALUE_CLAMP_MIN, min(VALUE_CLAMP_MAX, raw))
|
||||
ts = (w.get("time") or datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z"))[:25]
|
||||
conn.execute("INSERT INTO wall_street_trend (time, value) VALUES (?, ?)", (ts, val))
|
||||
last_row = conn.execute(
|
||||
"SELECT time, value FROM wall_street_trend ORDER BY time DESC LIMIT 1"
|
||||
).fetchone()
|
||||
last_time = last_row[0] if last_row else None
|
||||
last_val = int(last_row[1]) if last_row else None
|
||||
if _wall_street_should_append(last_time, ts):
|
||||
val = _smooth_wall_street(raw, last_val)
|
||||
conn.execute("INSERT INTO wall_street_trend (time, value) VALUES (?, ?)", (ts, val))
|
||||
n = conn.execute("SELECT COUNT(*) FROM wall_street_trend").fetchone()[0]
|
||||
if n > WALL_STREET_TREND_MAX_ROWS:
|
||||
conn.execute(
|
||||
|
||||
83
crawler/indicator_smooth.py
Normal file
83
crawler/indicator_smooth.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
华尔街财团投入指数 & 反击情绪指数:从爬虫实时数据计算稳定指标,抑制单条报道导致的剧烈波动。
|
||||
供 db_merge.merge() 调用,写入同一批 DB 表,前端契约不变。
|
||||
"""
|
||||
from typing import Optional, Tuple
|
||||
|
||||
VALUE_CLAMP_MIN = 1
|
||||
VALUE_CLAMP_MAX = 99
|
||||
|
||||
# 华尔街:与上一点平滑,新点权重
|
||||
WALL_STREET_NEW_WEIGHT = 0.35 # raw 权重;1 - 此值 = 上一点权重,越大曲线越平滑
|
||||
# 华尔街:两次写入最小间隔(分钟),避免短时间多条报道造成密集锯齿
|
||||
WALL_STREET_MIN_INTERVAL_MINUTES = 20
|
||||
|
||||
# 反击情绪:当前值权重(1 - 此值 = 新 raw 权重)
|
||||
RETALIATION_CURRENT_WEIGHT = 0.8
|
||||
# 反击情绪:单次更新相对当前值的最大变化幅度(绝对值)
|
||||
RETALIATION_MAX_STEP = 5
|
||||
|
||||
|
||||
def clamp(value: int) -> int:
|
||||
return max(VALUE_CLAMP_MIN, min(VALUE_CLAMP_MAX, int(value)))
|
||||
|
||||
|
||||
def smooth_wall_street(
|
||||
raw_value: int,
|
||||
last_value: Optional[int],
|
||||
*,
|
||||
new_weight: float = WALL_STREET_NEW_WEIGHT,
|
||||
) -> int:
|
||||
"""
|
||||
华尔街投入指数:用上一点做平滑,避免单条报道 30/80 导致曲线骤变。
|
||||
若尚无上一点,直接使用限幅后的 raw。
|
||||
"""
|
||||
raw = clamp(raw_value)
|
||||
if last_value is None:
|
||||
return raw
|
||||
w = 1.0 - new_weight
|
||||
return clamp(round(w * last_value + new_weight * raw))
|
||||
|
||||
|
||||
def wall_street_should_append(
|
||||
last_time_iso: Optional[str],
|
||||
new_time_iso: str,
|
||||
min_interval_minutes: int = WALL_STREET_MIN_INTERVAL_MINUTES,
|
||||
) -> bool:
|
||||
"""
|
||||
是否应追加一条华尔街趋势点。若与上一条间隔不足 min_interval_minutes 则跳过,
|
||||
减少因爬虫短时间多篇报道导致的密集锯齿。
|
||||
"""
|
||||
if not last_time_iso:
|
||||
return True
|
||||
try:
|
||||
from datetime import datetime
|
||||
last = datetime.fromisoformat(last_time_iso.replace("Z", "+00:00"))
|
||||
new = datetime.fromisoformat(new_time_iso.replace("Z", "+00:00"))
|
||||
delta_min = (new - last).total_seconds() / 60
|
||||
return delta_min >= min_interval_minutes
|
||||
except Exception:
|
||||
return True
|
||||
|
||||
|
||||
def smooth_retaliation(
|
||||
raw_value: int,
|
||||
current_value: int,
|
||||
*,
|
||||
current_weight: float = RETALIATION_CURRENT_WEIGHT,
|
||||
max_step: int = RETALIATION_MAX_STEP,
|
||||
) -> int:
|
||||
"""
|
||||
反击情绪指数:先与当前值平滑,再限制单步变化幅度,避免连续多条报道导致快速漂移或抖动。
|
||||
"""
|
||||
raw = clamp(raw_value)
|
||||
cur = clamp(current_value)
|
||||
smoothed = round(current_weight * cur + (1.0 - current_weight) * raw)
|
||||
smoothed = clamp(smoothed)
|
||||
# 单步变化上限
|
||||
delta = smoothed - cur
|
||||
if abs(delta) > max_step:
|
||||
step = max_step if delta > 0 else -max_step
|
||||
smoothed = clamp(cur + step)
|
||||
return smoothed
|
||||
Reference in New Issue
Block a user