日志展示优化

This commit is contained in:
ddrwode
2026-02-06 16:36:36 +08:00
parent e4db999ad9
commit 1ff12eaba3

View File

@@ -1,6 +1,7 @@
import sys
import time
from datetime import datetime
from collections import deque
from tqdm import tqdm
from loguru import logger
@@ -40,7 +41,7 @@ LOG_SYSTEM = _tag("系统", _M)
if not USE_RICH_DASHBOARD:
logger.remove()
logger.add(sys.stderr, format="\033[2m│\033[0m {message}", colorize=False)
logger.add(sys.stderr, format="\033[2m│\033[0m {message}", colorize=False, level="INFO")
def log_kline_header(kline_id):
"""新 K 线分块头(仅非 Rich 模式使用)"""
@@ -81,7 +82,8 @@ def make_metrics_panel(state: dict) -> Panel:
return Panel(t, title="[bold]价格 / 指标[/bold]", border_style="magenta")
def make_logs_panel(logs: list) -> Panel:
body = "\n".join(logs[-12:]) if logs else "等待日志..."
recent = list(logs)[-16:] if logs else []
body = "\n".join(recent) if recent else "等待日志..."
text = Text.from_ansi(body) if body else Text("等待日志...", style="dim")
return Panel(text, title="[bold]状态 / 日志[/bold]", border_style="green")
@@ -166,8 +168,10 @@ class BitmartFuturesTransaction:
self.current_open = None
# Rich 仪表盘:状态与日志(供 build_dashboard_layout 使用)
self._display_state = {}
self._display_logs = []
self._display_logs = deque(maxlen=120)
self._display_triggers = {}
self._last_signal_log_kline_id = None
self._log_throttle_at = {}
def get_klines(self):
"""获取最近2根K线当前K线和上一根K线"""
@@ -424,6 +428,15 @@ class BitmartFuturesTransaction:
else:
logger.info(text)
def _log_throttled(self, key, text, interval=1.0, level="info"):
"""同类日志限频,避免 0.1 秒循环刷屏。"""
now = time.time()
last = self._log_throttle_at.get(key, 0)
if now - last < interval:
return
self._log_throttle_at[key] = now
getattr(logger, level)(text)
def calculate_entity(self, kline):
"""计算K线实体大小绝对值"""
return abs(kline['close'] - kline['open'])
@@ -458,12 +471,17 @@ class BitmartFuturesTransaction:
检查交易信号
返回: ('long', trigger_price) / ('short', trigger_price) / None
"""
current_kline_id = current_kline.get('id')
should_log_snapshot = self._last_signal_log_kline_id != current_kline_id
# 计算上一根K线实体
prev_entity = self.calculate_entity(prev_kline)
# 实体过小不交易(实体 < 0.1
if prev_entity < 0.1:
logger.info(LOG_PRICE + f"上一根K线实体过小: {prev_entity:.4f},跳过信号检测")
if should_log_snapshot:
logger.info(LOG_PRICE + f"上一根K线实体过小: {prev_entity:.4f},跳过信号检测")
self._last_signal_log_kline_id = current_kline_id
return None
# 获取上一根K线的实体上下边
@@ -504,17 +522,19 @@ class BitmartFuturesTransaction:
current_is_bearish = current_kline['close'] < current_kline['open']
skip_long_by_lower_third = prev_is_bullish and current_is_bearish
if use_current_open_as_base:
if prev_is_bullish_for_calc and current_open_above_prev_close:
logger.info(LOG_PRICE + f"上一根阳线且当前开盘价({current_kline['open']:.2f})>上一根收盘价({prev_kline['close']:.2f}),以当前开盘价为基准计算")
else:
logger.info(LOG_PRICE + f"上一根阴线且当前开盘价({current_kline['open']:.2f})<上一根收盘价({prev_kline['close']:.2f}),以当前开盘价为基准计算")
logger.info(LOG_PRICE + f"当前价: {current_price:.2f} | 上一根实体: {prev_entity:.4f} | 实体上边: {prev_entity_upper:.2f} 下边: {prev_entity_lower:.2f}")
logger.info(LOG_PRICE + f"做多触发(下1/4): {long_trigger:.2f} | 做空触发(上1/4): {short_trigger:.2f} | 突破做多: {long_breakout:.2f} | 突破做空: {short_breakout:.2f}")
if skip_short_by_upper_third:
logger.info(LOG_PRICE + "上一根阴+当前阳(做多形态)不按上1/4做空")
if skip_long_by_lower_third:
logger.info(LOG_PRICE + "上一根阳+当前阴(做空形态)不按下1/4做多")
if should_log_snapshot:
if use_current_open_as_base:
if prev_is_bullish_for_calc and current_open_above_prev_close:
logger.info(LOG_PRICE + f"上一根阳线且当前开盘价({current_kline['open']:.2f})>上一根收盘价({prev_kline['close']:.2f}),以当前开盘价为基准计算")
else:
logger.info(LOG_PRICE + f"上一根阴线且当前开盘价({current_kline['open']:.2f})<上一根收盘价({prev_kline['close']:.2f}),以当前开盘价为基准计算")
logger.info(LOG_PRICE + f"当前价: {current_price:.2f} | 上一根实体: {prev_entity:.4f} | 实体上边: {prev_entity_upper:.2f} 下边: {prev_entity_lower:.2f}")
logger.info(LOG_PRICE + f"做多触发(下1/4): {long_trigger:.2f} | 做空触发(上1/4): {short_trigger:.2f} | 突破做多: {long_breakout:.2f} | 突破做空: {short_breakout:.2f}")
if skip_short_by_upper_third:
logger.info(LOG_PRICE + "上一根阴+当前阳(做多形态)不按上1/4做空")
if skip_long_by_lower_third:
logger.info(LOG_PRICE + "上一根阳+当前阴(做空形态)不按下1/4做多")
self._last_signal_log_kline_id = current_kline_id
self._display_triggers = {"long_trigger": long_trigger, "short_trigger": short_trigger, "long_breakout": long_breakout, "short_breakout": short_breakout}
@@ -553,7 +573,7 @@ class BitmartFuturesTransaction:
now = time.time()
if self.last_open_time is not None and now - self.last_open_time < self.open_cooldown_seconds:
remain = self.open_cooldown_seconds - (now - self.last_open_time)
logger.info(LOG_SYSTEM + f"开仓冷却中,剩余 {remain:.0f}")
self._log_throttled("open_cooldown", LOG_SYSTEM + f"开仓冷却中,剩余 {remain:.0f}", interval=1.0)
return False
return True
@@ -562,13 +582,13 @@ class BitmartFuturesTransaction:
now = time.time()
if self.last_reverse_time and now - self.last_reverse_time < self.reverse_cooldown_seconds:
remain = self.reverse_cooldown_seconds - (now - self.last_reverse_time)
logger.info(LOG_SYSTEM + f"反手冷却中,剩余 {remain:.0f}")
self._log_throttled("reverse_cooldown", LOG_SYSTEM + f"反手冷却中,剩余 {remain:.0f}", interval=1.0)
return False
if trigger_price and trigger_price > 0:
move_pct = abs(current_price - trigger_price) / trigger_price * 100
if move_pct < self.reverse_min_move_pct:
logger.info(LOG_SYSTEM + f"反手价差不足: {move_pct:.4f}% < {self.reverse_min_move_pct}%")
self._log_throttled("reverse_move_small", LOG_SYSTEM + f"反手价差不足: {move_pct:.4f}% < {self.reverse_min_move_pct}%", interval=1.0)
return False
return True
@@ -733,13 +753,25 @@ class BitmartFuturesTransaction:
page_start = True
if USE_RICH_DASHBOARD:
self._display_logs = []
self._display_logs.clear()
logger.remove()
level_color = {
"DEBUG": "\033[2m",
"INFO": "\033[36m",
"SUCCESS": "\033[32m",
"WARNING": "\033[33m",
"ERROR": "\033[31m",
"CRITICAL": "\033[35m",
}
def _sink(msg):
self._display_logs.append(msg.record["message"])
if len(self._display_logs) > 50:
self._display_logs.pop(0)
logger.add(_sink, format="{message}")
record = msg.record
ts = record["time"].strftime("%H:%M:%S")
level = record["level"].name
color = level_color.get(level, "\033[37m")
line = f"\033[2m{ts}\033[0m {color}{level:<7}\033[0m {record['message']}"
self._display_logs.append(line)
logger.add(_sink, format="{message}", level="INFO")
live = None
if USE_RICH_DASHBOARD:
@@ -783,8 +815,11 @@ class BitmartFuturesTransaction:
current_kline_time = current_kline['id']
if self.last_kline_time != current_kline_time:
self.last_kline_time = current_kline_time
logger.info("")
log_kline_header(current_kline_time)
if USE_RICH_DASHBOARD:
logger.info(LOG_SYSTEM + f"进入新K线: {current_kline_time}")
else:
logger.info("")
log_kline_header(current_kline_time)
# 2. 获取当前价格
current_price = self.get_current_price()
@@ -799,7 +834,12 @@ class BitmartFuturesTransaction:
time.sleep(2)
continue
logger.debug(f"当前持仓状态: {self.start} (0=无, 1=多, -1=空)")
self._log_throttled(
"position_state",
f"当前持仓状态: {self.start} (0=无, 1=多, -1=空)",
interval=2.0,
level="debug",
)
# 更新仪表盘左侧数据(供 Rich 展示)
try:
@@ -984,7 +1024,7 @@ class BitmartFuturesTransaction:
if USE_RICH_DASHBOARD:
logger.remove()
logger.add(sys.stderr, format="{message}")
logger.add(sys.stderr, format="{message}", level="INFO")
if __name__ == '__main__':