Web 加上资金面/情绪叠图,并收紧默认图面。

默认主/次/次次改为 45m/15m/5m、开始时间一周;SD/CD 按 hist 摆位置和箭头;去掉笔线段背驰与第四类勾选。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-09-12 02:25:44 +08:00
co-authored by Cursor
parent b301ad22c9
commit c22cd48f36
24 changed files with 1200 additions and 306 deletions
+3
View File
@@ -54,6 +54,9 @@ from .market_data import ( # noqa: F401
get_crypto_kl_data,
get_a_stock_kl_data,
load_crypto_symbols,
fetch_derivatives,
fetch_sentiment_metrics,
fetch_sentiment_latest,
)
from .indicators import ( # noqa: F401
add_indicators,
+31
View File
@@ -319,3 +319,34 @@ def load_crypto_symbols(limit=200):
except Exception:
return DEFAULT_SYMBOLS[:limit]
def _provider_get(path, params, timeout=8):
resp = requests.get(f"{DATA_SERVICE_URL}{path}", params=params, timeout=timeout)
resp.raise_for_status()
return resp.json()
def fetch_derivatives(symbol, exchange=None):
"""当前资金面快照。只打 data_provider,不打交易所。"""
params = {"symbol": symbol}
if exchange:
params["exchange"] = exchange
return _provider_get("/api/derivatives", params)
def fetch_sentiment_metrics(metric, symbol, start=None, end=None, limit=None):
"""情绪/资金面序列。只打 data_provider。"""
params = {"metric": metric, "symbol": symbol}
if start is not None:
params["start"] = int(start)
if end is not None:
params["end"] = int(end)
if limit is not None:
params["limit"] = int(limit)
return _provider_get("/api/sentiment/metrics", params)
def fetch_sentiment_latest(symbol):
"""情绪面最新快照。只打 data_provider。"""
return _provider_get("/api/sentiment/latest", {"symbol": symbol})
+1
View File
@@ -46,6 +46,7 @@ DEFAULT_TIMEFRAME_LABELS = OrderedDict([
("5m", "5分钟"),
("15m", "15分钟"),
("30m", "30分钟"),
("45m", "45分钟"),
("1h", "1小时"),
("2h", "2小时"),
("4h", "4小时"),
+4 -4
View File
@@ -94,19 +94,19 @@ def _prefer_smaller(candidates, labels_ordered, ceiling_tf, timeframe_keys):
def compute_timeframe_defaults(labels_ordered):
"""
根据已排序的「周期 → 中文标签」映射,计算主 / 次 / 次次周期默认值。
默认偏好:主 4h、次 1h、次次 15m。
默认偏好:主 45m、次 15m、次次 5m。
labels_ordered: OrderedDict 或按插入顺序排列的 dict。
"""
if not labels_ordered:
labels_ordered = DEFAULT_TIMEFRAME_LABELS.copy()
timeframe_keys = list(labels_ordered.keys())
preferred_main = next((tf for tf in ['4h', '1h', '15m'] if tf in labels_ordered), None)
preferred_main = next((tf for tf in ['45m', '30m', '1h'] if tf in labels_ordered), None)
default_main = preferred_main or (timeframe_keys[0] if timeframe_keys else '1m')
if default_main not in labels_ordered and timeframe_keys:
default_main = timeframe_keys[0]
default_element = _prefer_smaller(['1h', '15m'], labels_ordered, default_main, timeframe_keys)
default_sub_sub = _prefer_smaller(['15m', '5m'], labels_ordered, default_element, timeframe_keys)
default_element = _prefer_smaller(['15m', '5m', '30m'], labels_ordered, default_main, timeframe_keys)
default_sub_sub = _prefer_smaller(['5m', '1m', '15m'], labels_ordered, default_element, timeframe_keys)
return default_main, default_element, default_sub_sub, timeframe_keys