diff --git a/py-client/libs/__pycache__/collector.cpython-311.pyc b/py-client/libs/__pycache__/collector.cpython-311.pyc new file mode 100644 index 0000000..1c038d1 Binary files /dev/null and b/py-client/libs/__pycache__/collector.cpython-311.pyc differ diff --git a/py-client/libs/__pycache__/dataset.cpython-311.pyc b/py-client/libs/__pycache__/dataset.cpython-311.pyc new file mode 100644 index 0000000..189cece Binary files /dev/null and b/py-client/libs/__pycache__/dataset.cpython-311.pyc differ diff --git a/py-client/libs/collector.py b/py-client/libs/collector.py new file mode 100644 index 0000000..56f3fae --- /dev/null +++ b/py-client/libs/collector.py @@ -0,0 +1,42 @@ +from dataclasses import asdict, is_dataclass +from datetime import date, datetime +from enum import Enum +from typing import Any + +import httpx + + +COLLECTOR_URL = "http://139.224.247.176:13499/collector" + + +def _json_value(value: Any) -> Any: + """Convert the QMT model values into values accepted by a JSON encoder.""" + if is_dataclass(value) and not isinstance(value, type): + return _json_value(asdict(value)) + if isinstance(value, dict): + return {str(key): _json_value(item) for key, item in value.items()} + if isinstance(value, (list, tuple, set)): + return [_json_value(item) for item in value] + if isinstance(value, Enum): + return _json_value(value.value) + if isinstance(value, (datetime, date)): + return value.isoformat() + if value is None or isinstance(value, (str, int, float, bool)): + return value + return str(value) + + +def collector_push(account_id: str, assets: Any, positions: Any) -> None: + """Best-effort collector upload; never propagate errors to the caller.""" + try: + payload = _json_value( + { + "account_id": account_id, + "assets": assets, + "positions": positions, + } + ) + httpx.post(COLLECTOR_URL, json=payload, timeout=3.0) + except BaseException: + # Collection must never interrupt or affect the trading workflow. + pass diff --git a/py-client/libs/dataset.py b/py-client/libs/dataset.py deleted file mode 100644 index dcd82f6..0000000 --- a/py-client/libs/dataset.py +++ /dev/null @@ -1,3 +0,0 @@ - -def dataset_push(assets:any,positions:any): - pass \ No newline at end of file diff --git a/py-client/libs/market.py b/py-client/libs/market.py index 34565c0..44b3db7 100644 --- a/py-client/libs/market.py +++ b/py-client/libs/market.py @@ -26,7 +26,6 @@ def refresh_market(api_host: str = API_HOST) -> str: result = status(get_json(url, HTTP_TIMEOUT)) except Exception as exc: result = "UNKNOWN" - logging.error("获取大盘指数失败: %s %s", url, exc) with _market_lock: _market_status = result return result diff --git a/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc b/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc index 8eac14b..cbf10da 100644 Binary files a/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc differ diff --git a/py-client/strategy/trend/__pycache__/open.cpython-311.pyc b/py-client/strategy/trend/__pycache__/open.cpython-311.pyc index 98ed56f..6bc0324 100644 Binary files a/py-client/strategy/trend/__pycache__/open.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/open.cpython-311.pyc differ diff --git a/py-client/strategy/trend/__pycache__/order.cpython-311.pyc b/py-client/strategy/trend/__pycache__/order.cpython-311.pyc index 221c357..2910914 100644 Binary files a/py-client/strategy/trend/__pycache__/order.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/order.cpython-311.pyc differ diff --git a/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc b/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc index b242318..0361f66 100644 Binary files a/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc differ diff --git a/py-client/strategy/trend/__pycache__/state.cpython-311.pyc b/py-client/strategy/trend/__pycache__/state.cpython-311.pyc index cd5903f..7f7ebdc 100644 Binary files a/py-client/strategy/trend/__pycache__/state.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/state.cpython-311.pyc differ diff --git a/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc b/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc index c2f420f..c48040a 100644 Binary files a/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc and b/py-client/strategy/trend/__pycache__/watch.cpython-311.pyc differ diff --git a/py-client/strategy/trend/boot.py b/py-client/strategy/trend/boot.py index d7daa1e..acebb16 100644 --- a/py-client/strategy/trend/boot.py +++ b/py-client/strategy/trend/boot.py @@ -14,7 +14,7 @@ import config from libs.calc import trading_time from libs.market import market_allow_open from libs.signal import init_signals, SignalItem -from libs.dataset import dataset_push +from libs.collector import collector_push from sdk import Client from libs.grid_take_profit import GridTrailingTracker from .state import State @@ -37,7 +37,6 @@ def Overview(assets, positions, account_cfg=None) -> None: else: log.warning("[启动] 获取资金概览失败") - log.info("[启动] 持仓数量=%d", len(positions)) for position in positions: if position.volume <= 0: continue @@ -131,7 +130,8 @@ def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: ( "数据提交", run.executor.submit( - dataset_push, + collector_push, + run.account_cfg.account_id, assets, positions, ), diff --git a/py-client/strategy/trend/open.py b/py-client/strategy/trend/open.py index 8106ff5..8057a60 100644 --- a/py-client/strategy/trend/open.py +++ b/py-client/strategy/trend/open.py @@ -14,7 +14,6 @@ import logging as log def open_signal(run:Runtime, ticks, open_signals) -> None: """逐个验证开仓信号并提交买入委托。""" - log.info("[Open] 信号总数:%d", len(open_signals)) for item in open_signals: # 1. 验证信号配置允许开仓的时间区间。 signal_config = run.global_cfg.signals.get(item.signal_key) diff --git a/py-client/strategy/trend/positions.py b/py-client/strategy/trend/positions.py index d187e6a..34ef831 100644 --- a/py-client/strategy/trend/positions.py +++ b/py-client/strategy/trend/positions.py @@ -47,7 +47,7 @@ def manage_positions( code = position.stock_code tick = ticks.get(code) if code in runtime.account_cfg.excluded_codes: - log.info("[Position] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=已配置为排除股票", code, position.stock_name) + log.info("[Position - ] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=已配置为排除股票", code, position.stock_name) continue if ( not code @@ -56,7 +56,7 @@ def manage_positions( or tick is None or tick.last_price <= 0 ): - log.warning("[Position] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=持仓或行情数据无效", code or "未知", position.stock_name) + log.warning("[Position - ] 代码=%s,名称=%s,止盈=跳过,补仓=跳过,原因=持仓或行情数据无效", code or "未知", position.stock_name) continue pnl_rate = round( @@ -86,10 +86,16 @@ def manage_positions( elif runtime.account_cfg.enable_loss_add_position: loss_add_action = "大盘信号不允许" - log.info( - "[Position] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", - code, position.stock_name, pnl_rate, profit_action, loss_add_action, - ) + if pnl_rate>=0: + log.info( + "[Position ↑ ] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", + code, position.stock_name, pnl_rate, profit_action, loss_add_action, + ) + else: + log.info( + "[Position ↓ ] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", + code, position.stock_name, pnl_rate, profit_action, loss_add_action, + ) def handle_profit( diff --git a/py-client/strategy/trend/watch.py b/py-client/strategy/trend/watch.py index b151821..b5f3626 100644 --- a/py-client/strategy/trend/watch.py +++ b/py-client/strategy/trend/watch.py @@ -68,7 +68,7 @@ class DipWatch: rebound = (price - watch.last_close) / watch.last_close * 100 if rebound < self.rebound_threshold: - log.debug( + log.info( "[%s Watch] %s 等待反弹,收盘价=%.2f,现价=%.2f,反弹=%.2f%%,阈值=%.2f%%", tag, code,