Vibe-Trading:基于Agent架构的Python量化交易框架实战解析

Vibe-Trading:基于Agent架构的Python量化交易框架实战解析 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度如果你正在寻找一个能够自动化交易决策、降低人工干预的开源解决方案那么 HKUDS/Vibe-Trading 可能正是你需要的工具。这个在 GitHub 上拥有近 1.8 万星标的 Python 项目定位为你的个人交易助手但它的价值远不止于此。在传统量化交易中开发者往往需要从零开始搭建数据获取、策略回测、风险控制等复杂模块这不仅耗时耗力还对金融工程背景有较高要求。Vibe-Trading 的核心突破在于将交易流程模块化让开发者能够像搭积木一样快速构建自己的交易系统。更重要的是它采用 Agent 架构设计这意味着系统能够根据市场变化自主调整策略实现了一定程度的智能决策。本文将从实际开发角度深入解析 Vibe-Trading 的架构设计、环境搭建、核心功能实现并通过完整代码示例展示如何构建一个真实的交易策略。无论你是想要入门量化交易的 Python 开发者还是希望优化现有交易系统的金融从业者都能从中获得实用的技术指导。1. Vibe-Trading 解决了什么实际问题1.1 传统量化交易的技术门槛在深入了解 Vibe-Trading 之前我们需要明确传统量化交易面临的核心挑战。一个完整的交易系统通常包含以下模块数据获取与清洗需要对接多个数据源处理不同格式的金融数据策略开发与回测编写交易逻辑并在历史数据上验证效果风险控制设置止损止盈、仓位管理等安全机制订单执行与交易所 API 对接实现自动化交易监控与日志实时跟踪交易表现记录关键指标每个环节都需要深厚的专业知识和大量的开发时间。Vibe-Trading 的价值就在于将这些模块标准化、组件化让开发者可以专注于策略逻辑本身。1.2 Vibe-Trading 的差异化优势与传统的量化交易框架相比Vibe-Trading 在以下几个方面做出了重要改进模块化设计将交易系统拆分为独立的数据模块、策略模块、执行模块支持灵活组合和扩展。这种设计使得代码复用性大大提高新策略的开发时间显著缩短。Agent 架构项目采用智能 Agent 设计交易策略不再是静态的规则集合而是能够根据市场状态动态调整的智能体。这意味着系统可以学习市场模式适应不同的行情环境。开源生态基于 Python 生态可以轻松集成各种数据分析库如 pandas、numpy和机器学习框架如 scikit-learn、TensorFlow。社区活跃问题响应迅速从 GitHub 数据看项目维护质量较高。2. 核心架构与关键技术原理2.1 系统架构概览Vibe-Trading 采用典型的分层架构设计从上到下依次为数据层 → 策略层 → 执行层 → 监控层数据层负责统一的数据接入和标准化处理支持多种数据源股票、加密货币、期货等输出统一格式的行情数据。策略层是核心业务逻辑所在包含信号生成、风险控制、仓位管理等模块。策略以插件形式存在可以热插拔。执行层封装了与交易所的交互逻辑处理订单创建、撤销、查询等操作确保交易指令准确执行。监控层提供实时监控、业绩分析、异常报警等功能保证系统稳定运行。2.2 Agent 决策机制解析Vibe-Trading 的智能体现在其 Agent 决策机制上。与传统规则引擎不同Agent 通过以下方式实现动态决策状态感知Agent 持续监控市场数据、持仓状态、账户信息等多维度数据形成完整的市场状态画像。决策推理基于当前状态Agent 使用预设的策略逻辑或机器学习模型进行推理生成交易决策。动作执行将决策转化为具体的交易指令并通过执行层发送到交易所。反馈学习根据交易结果和市场变化Agent 可以调整策略参数实现持续优化。这种机制使得交易系统能够更好地适应市场变化特别是在高波动性环境中表现更为稳健。3. 环境准备与项目部署3.1 系统要求与依赖环境在开始使用 Vibe-Trading 前需要确保开发环境满足以下要求Python 版本建议使用 Python 3.8 或更高版本这是项目测试最充分的环境。操作系统支持 Windows、Linux、macOS但生产环境推荐 Linux 系统以获得更好的性能表现。内存要求至少 4GB RAM如果处理大量历史数据或复杂策略建议 8GB 以上。网络环境稳定的网络连接用于实时数据获取和交易执行。3.2 项目安装与配置首先克隆项目代码到本地git clone https://github.com/HKUDS/Vibe-Trading.git cd Vibe-Trading创建并激活虚拟环境推荐python -m venv vibe_env source vibe_env/bin/activate # Linux/macOS # 或 vibe_env\Scripts\activate # Windows安装项目依赖pip install -r requirements.txt如果 requirements.txt 文件不存在或需要手动安装核心依赖pip install pandas numpy requests websocket-client sqlalchemy python-dotenv3.3 基础配置设置创建配置文件config.yaml# config.yaml database: url: sqlite:///trading.db # 使用 SQLite 作为默认数据库 logging: level: INFO file: trading.log api: retry_times: 3 timeout: 30 # 交易所配置示例需要填写真实 API 信息 exchange: binance: api_key: your_api_key secret_key: your_secret_key testnet: true # 建议先在测试环境运行环境变量配置创建.env文件# .env TRADING_ENVdevelopment DATABASE_URLsqlite:///trading.db LOG_LEVELINFO4. 核心模块详解与代码实现4.1 数据模块统一数据接口数据模块是交易系统的基础Vibe-Trading 提供了统一的数据接口# data_provider.py import pandas as pd from abc import ABC, abstractmethod class DataProvider(ABC): 数据提供者抽象基类 abstractmethod def get_historical_data(self, symbol, timeframe, limit1000): 获取历史K线数据 pass abstractmethod def get_realtime_data(self, symbol, callback): 订阅实时数据 pass abstractmethod def get_market_depth(self, symbol): 获取市场深度数据 pass class BinanceDataProvider(DataProvider): 币安交易所数据提供者 def __init__(self, api_keyNone, secret_keyNone, testnetTrue): self.base_url https://testnet.binance.vision if testnet else https://api.binance.com self.api_key api_key self.secret_key secret_key def get_historical_data(self, symbol, timeframe, limit1000): 获取币安历史K线数据 import requests import time url f{self.base_url}/api/v3/klines params { symbol: symbol, interval: timeframe, limit: limit } try: response requests.get(url, paramsparams) data response.json() # 转换为DataFrame df pd.DataFrame(data, columns[ open_time, open, high, low, close, volume, close_time, quote_volume, trades, taker_buy_volume, taker_buy_quote_volume, ignore ]) # 数据类型转换 numeric_columns [open, high, low, close, volume] for col in numeric_columns: df[col] pd.to_numeric(df[col]) df[open_time] pd.to_datetime(df[open_time], unitms) df[close_time] pd.to_datetime(df[close_time], unitms) return df except Exception as e: print(f获取历史数据失败: {e}) return pd.DataFrame() # 使用示例 if __name__ __main__: provider BinanceDataProvider(testnetTrue) btc_data provider.get_historical_data(BTCUSDT, 1h, 100) print(btc_data.head())4.2 策略模块实现交易逻辑策略模块是交易系统的核心下面实现一个简单的均线策略# strategies/ma_crossover.py import pandas as pd from abc import ABC, abstractmethod class TradingStrategy(ABC): 交易策略抽象基类 def __init__(self, name, parametersNone): self.name name self.parameters parameters or {} self.position 0 # 当前持仓0-空仓1-多仓 self.signals [] # 信号记录 abstractmethod def generate_signal(self, data): 生成交易信号 pass def update_parameters(self, new_params): 更新策略参数 self.parameters.update(new_params) class MovingAverageCrossoverStrategy(TradingStrategy): 移动平均线交叉策略 def __init__(self, short_window10, long_window30): super().__init__(MA_Crossover, { short_window: short_window, long_window: long_window }) def generate_signal(self, data): 生成均线交叉信号 if len(data) self.parameters[long_window]: return 0 # 数据不足不交易 # 计算移动平均线 short_ma data[close].rolling(windowself.parameters[short_window]).mean() long_ma data[close].rolling(windowself.parameters[long_window]).mean() # 生成交易信号 if short_ma.iloc[-1] long_ma.iloc[-1] and short_ma.iloc[-2] long_ma.iloc[-2]: signal 1 # 金叉买入信号 elif short_ma.iloc[-1] long_ma.iloc[-1] and short_ma.iloc[-2] long_ma.iloc[-2]: signal -1 # 死叉卖出信号 else: signal 0 # 无信号 # 记录信号 self.signals.append({ timestamp: data.index[-1], signal: signal, short_ma: short_ma.iloc[-1], long_ma: long_ma.iloc[-1] }) return signal # 策略回测示例 def backtest_strategy(strategy, data, initial_capital10000): 策略回测函数 capital initial_capital position 0 trades [] for i in range(len(data)): current_data data.iloc[:i1] signal strategy.generate_signal(current_data) price data[close].iloc[i] if signal 1 and position 0: # 买入信号且空仓 position capital / price capital 0 trades.append({type: BUY, price: price, timestamp: data.index[i]}) elif signal -1 and position 0: # 卖出信号且持多仓 capital position * price position 0 trades.append({type: SELL, price: price, timestamp: data.index[i]}) # 计算最终资产 final_value capital (position * data[close].iloc[-1] if position 0 else 0) return_rate (final_value - initial_capital) / initial_capital return { final_value: final_value, return_rate: return_rate, trades: trades, total_trades: len(trades) }4.3 风险控制模块风险控制是交易系统中至关重要的部分# risk_management.py class RiskManager: 风险管理器 def __init__(self, max_position_size0.1, stop_loss0.05, max_drawdown0.2): self.max_position_size max_position_size # 单次最大仓位比例 self.stop_loss stop_loss # 止损比例 self.max_drawdown max_drawdown # 最大回撤限制 self.peak_equity 0 # 权益峰值 self.current_drawdown 0 # 当前回撤 def validate_trade(self, signal, current_price, portfolio_value, position): 验证交易是否满足风控要求 # 检查仓位限制 proposed_position_value abs(signal) * portfolio_value * self.max_position_size if proposed_position_value portfolio_value * self.max_position_size: return False, 超出单次最大仓位限制 # 检查回撤限制 current_equity portfolio_value (position * current_price if position else 0) self.peak_equity max(self.peak_equity, current_equity) drawdown (self.peak_equity - current_equity) / self.peak_equity if self.peak_equity 0 else 0 if drawdown self.max_drawdown: return False, f回撤超过限制: {drawdown:.2%} {self.max_drawdown:.2%} return True, 风控检查通过 def calculate_position_size(self, signal, portfolio_value, current_price, volatility): 计算合理的仓位大小 # 基于波动率调整仓位 volatility_adjustment min(1.0, 0.1 / volatility) if volatility 0 else 1.0 base_size portfolio_value * self.max_position_size # 考虑信号强度 signal_strength abs(signal) # 假设信号值在-1到1之间 adjusted_size base_size * signal_strength * volatility_adjustment # 转换为具体数量 position_size adjusted_size / current_price return int(position_size) # 取整 # 使用示例 risk_manager RiskManager(max_position_size0.1, stop_loss0.05) is_valid, message risk_manager.validate_trade( signal1, current_price50000, portfolio_value10000, position0 ) print(f交易验证: {is_valid}, 消息: {message})5. 完整交易系统集成5.1 主交易引擎实现将各个模块整合成完整的交易系统# trading_engine.py import logging import time from datetime import datetime from data_provider import BinanceDataProvider from strategies.ma_crossover import MovingAverageCrossoverStrategy from risk_management import RiskManager class TradingEngine: 主交易引擎 def __init__(self, config): self.config config self.setup_logging() self.setup_components() self.running False def setup_logging(self): 设置日志系统 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(trading.log), logging.StreamHandler() ] ) self.logger logging.getLogger(__name__) def setup_components(self): 初始化各个组件 # 数据提供者 self.data_provider BinanceDataProvider( testnetself.config.get(testnet, True) ) # 交易策略 self.strategy MovingAverageCrossoverStrategy( short_window10, long_window30 ) # 风险管理者 self.risk_manager RiskManager( max_position_size0.1, stop_loss0.05 ) # 交易状态 self.portfolio { cash: 10000, # 初始资金 positions: {}, # 持仓 total_value: 10000 } self.logger.info(交易引擎组件初始化完成) def run(self): 运行交易引擎 self.running True self.logger.info(交易引擎启动) try: while self.running: self.execute_trading_cycle() time.sleep(60) # 每分钟执行一次 except KeyboardInterrupt: self.logger.info(收到停止信号优雅退出) except Exception as e: self.logger.error(f交易引擎运行异常: {e}) finally: self.stop() def execute_trading_cycle(self): 执行单个交易周期 try: # 获取最新数据 symbol BTCUSDT data self.data_provider.get_historical_data(symbol, 1h, 100) if data.empty: self.logger.warning(获取数据失败跳过本次周期) return # 生成交易信号 signal self.strategy.generate_signal(data) current_price data[close].iloc[-1] # 风险控制检查 is_valid, message self.risk_manager.validate_trade( signal, current_price, self.portfolio[cash], self.portfolio[positions].get(symbol, 0) ) if not is_valid: self.logger.info(f风控拦截: {message}) return # 执行交易逻辑 if signal ! 0: self.execute_trade(signal, symbol, current_price) # 更新投资组合价值 self.update_portfolio_value() self.logger.info(f交易周期完成 - 信号: {signal}, 当前价值: {self.portfolio[total_value]:.2f}) except Exception as e: self.logger.error(f交易周期执行异常: {e}) def execute_trade(self, signal, symbol, price): 执行具体交易 if signal 0: # 买入信号 # 计算买入数量 position_size self.risk_manager.calculate_position_size( signal, self.portfolio[cash], price, volatility0.02 ) cost position_size * price if cost self.portfolio[cash]: self.portfolio[cash] - cost self.portfolio[positions][symbol] self.portfolio[positions].get(symbol, 0) position_size self.logger.info(f买入 {symbol} - 数量: {position_size}, 价格: {price:.2f}) elif signal 0 and symbol in self.portfolio[positions]: # 卖出信号且有持仓 position_size self.portfolio[positions][symbol] revenue position_size * price self.portfolio[cash] revenue del self.portfolio[positions][symbol] self.logger.info(f卖出 {symbol} - 数量: {position_size}, 价格: {price:.2f}) def update_portfolio_value(self): 更新投资组合总价值 positions_value 0 for symbol, quantity in self.portfolio[positions].items(): # 简化处理使用最近价格估算 data self.data_provider.get_historical_data(symbol, 1h, 1) if not data.empty: price data[close].iloc[-1] positions_value quantity * price self.portfolio[total_value] self.portfolio[cash] positions_value def stop(self): 停止交易引擎 self.running False self.logger.info(交易引擎已停止) # 启动交易系统 if __name__ __main__: config { testnet: True, symbols: [BTCUSDT, ETHUSDT] } engine TradingEngine(config) engine.run()5.2 配置文件详解创建完整的配置文件支持# config/trading_config.yaml trading: environment: testnet # testnet 或 live symbols: - BTCUSDT - ETHUSDT base_currency: USDT initial_capital: 10000 strategies: ma_crossover: enabled: true parameters: short_window: 10 long_window: 30 symbols: [BTCUSDT] risk_management: max_position_size: 0.1 stop_loss: 0.05 max_drawdown: 0.2 daily_loss_limit: 0.05 data: providers: binance: enabled: true api_key: ${BINANCE_API_KEY} secret_key: ${BINANCE_SECRET_KEY} testnet: true history_days: 30 logging: level: INFO file: logs/trading.log max_file_size: 10MB backup_count: 5 database: url: sqlite:///data/trading.db echo: false对应的配置加载类# config_loader.py import yaml import os from dotenv import load_dotenv class ConfigLoader: 配置加载器 def __init__(self, config_pathconfig/trading_config.yaml): self.config_path config_path load_dotenv() # 加载环境变量 def load_config(self): 加载配置文件 with open(self.config_path, r) as file: config yaml.safe_load(file) # 替换环境变量 config self._replace_env_vars(config) return config def _replace_env_vars(self, config): 递归替换环境变量 if isinstance(config, dict): return {k: self._replace_env_vars(v) for k, v in config.items()} elif isinstance(config, list): return [self._replace_env_vars(item) for item in config] elif isinstance(config, str) and config.startswith(${) and config.endswith(}): env_var config[2:-1] return os.getenv(env_var, config) else: return config6. 实战演练构建完整的交易策略6.1 策略回测与性能评估在实际投入资金前必须对策略进行充分回测# backtester.py import pandas as pd import numpy as np from datetime import datetime, timedelta class Backtester: 策略回测器 def __init__(self, initial_capital10000): self.initial_capital initial_capital self.results {} def run_backtest(self, strategy, data, commission0.001): 运行回测 capital self.initial_capital position 0 trades [] equity_curve [] for i in range(len(data)): current_data data.iloc[:i1] signal strategy.generate_signal(current_data) price data[close].iloc[i] timestamp data.index[i] # 记录权益曲线 current_equity capital (position * price) equity_curve.append({ timestamp: timestamp, equity: current_equity, price: price }) # 执行交易逻辑 if signal 0 and position 0: # 买入 # 考虑手续费 buy_price price * (1 commission) position capital / buy_price capital 0 trades.append({ type: BUY, price: price, timestamp: timestamp, commission: capital * commission }) elif signal 0 and position 0: # 卖出 # 考虑手续费 sell_price price * (1 - commission) capital position * sell_price position 0 trades.append({ type: SELL, price: price, timestamp: timestamp, commission: position * price * commission }) # 计算最终结果 final_equity capital (position * data[close].iloc[-1] if position 0 else 0) total_return (final_equity - self.initial_capital) / self.initial_capital # 计算风险指标 risk_metrics self.calculate_risk_metrics(equity_curve, trades) self.results { final_equity: final_equity, total_return: total_return, total_trades: len(trades), winning_trades: len([t for t in trades if t.get(profit, 0) 0]), risk_metrics: risk_metrics, trades: trades, equity_curve: equity_curve } return self.results def calculate_risk_metrics(self, equity_curve, trades): 计算风险指标 equities [e[equity] for e in equity_curve] # 最大回撤 peak np.maximum.accumulate(equities) drawdown (peak - equities) / peak max_drawdown np.max(drawdown) # 夏普比率简化版 returns np.diff(equities) / equities[:-1] sharpe_ratio np.mean(returns) / np.std(returns) * np.sqrt(252) if len(returns) 1 else 0 # 交易胜率 winning_trades len([t for t in trades if t.get(profit, 0) 0]) win_rate winning_trades / len(trades) if trades else 0 return { max_drawdown: max_drawdown, sharpe_ratio: sharpe_ratio, win_rate: win_rate, total_trades: len(trades) } def generate_report(self): 生成回测报告 if not self.results: return 暂无回测结果 metrics self.results[risk_metrics] report f 回测报告 基础信息 -------- 初始资金: ${self.initial_capital:,.2f} 最终权益: ${self.results[final_equity]:,.2f} 总收益率: {self.results[total_return]:.2%} 交易统计 -------- 总交易次数: {metrics[total_trades]} 胜率: {metrics[win_rate]:.2%} 风险指标 -------- 最大回撤: {metrics[max_drawdown]:.2%} 夏普比率: {metrics[sharpe_ratio]:.2f} return report # 使用示例 def demo_backtest(): 回测演示 # 生成示例数据 dates pd.date_range(2024-01-01, 2024-06-01, freqD) np.random.seed(42) prices 100 np.cumsum(np.random.randn(len(dates)) * 0.5) data pd.DataFrame({ open: prices * 0.99, high: prices * 1.01, low: prices * 0.98, close: prices, volume: np.random.randint(1000, 10000, len(dates)) }, indexdates) # 创建策略并回测 strategy MovingAverageCrossoverStrategy(short_window10, long_window20) backtester Backtester(initial_capital10000) results backtester.run_backtest(strategy, data) print(backtester.generate_report()) return results if __name__ __main__: demo_backtest()6.2 实盘交易注意事项从回测过渡到实盘交易时需要注意以下关键点数据质量差异回测使用的历史数据通常是清洗过的而实盘数据包含更多噪声和异常值。需要增强数据的鲁棒性处理。交易延迟影响实盘交易存在网络延迟、交易所处理时间等这些在回测中往往被忽略。需要在实际策略中考虑这些因素。市场冲击成本大额订单会影响市场价格回测中假设可以按指定价格成交实盘中需要考虑市场深度。心理因素实盘交易涉及真实资金容易受到情绪影响需要严格遵守预设的交易规则。7. 常见问题与解决方案7.1 安装与环境问题问题现象可能原因解决方案导入模块失败Python路径问题或依赖缺失检查虚拟环境激活重新安装requirements.txt连接交易所超时网络问题或API限制检查网络连接确认API密钥权限使用重试机制数据库连接失败数据库URL配置错误检查config.yaml中的数据库连接字符串7.2 策略执行问题问题现象可能原因解决方案策略不产生信号数据不足或参数不合理检查数据长度是否满足策略要求调整策略参数信号频繁切换策略过于敏感增加信号过滤机制设置最小持仓时间回测过拟合策略在历史数据上过度优化使用样本外测试采用交叉验证方法7.3 风险控制问题问题现象可能原因解决方案仓位过大风控参数设置不当调整max_position_size参数添加动态仓位管理连续亏损市场环境变化或策略失效设置最大连续亏损次数定期评估策略有效性滑点过大流动性不足或订单类型不当使用限价单代替市价单选择流动性好的交易对7.4 性能优化建议数据缓存优化频繁获取的数据应该缓存减少API调用次数。# 使用缓存装饰器 from functools import lru_cache import time lru_cache(maxsize100) def get_cached_data(symbol, timeframe, limit): 带缓存的数据获取函数 # 实际的数据获取逻辑 time.sleep(0.1) # 模拟网络延迟 return fdata_{symbol}_{timeframe}_{limit} # 使用示例 data1 get_cached_data(BTCUSDT, 1h, 100) # 第一次调用会实际获取数据 data2 get_cached_data(BTCUSDT, 1h, 100) # 第二次调用使用缓存异步处理使用异步编程提高IO密集型任务的效率。import asyncio import aiohttp async def fetch_multiple_symbols(symbols): 异步获取多个交易对数据 async with aiohttp.ClientSession() as session: tasks [] for symbol in symbols: task asyncio.create_task(fetch_symbol_data(session, symbol)) tasks.append(task) results await asyncio.gather(*tasks, return_exceptionsTrue) return results async def fetch_symbol_data(session, symbol): 获取单个交易对数据 url fhttps://api.binance.com/api/v3/klines?symbol{symbol}interval1hlimit100 async with session.get(url) as response: return await response.json()8. 生产环境最佳实践8.1 监控与告警在生产环境中运行交易系统时完善的监控体系至关重要系统健康监控定期检查交易引擎状态、API连接、数据库连接等。性能指标监控跟踪策略表现、交易频率、盈亏情况等关键指标。异常告警设置阈值告警当出现异常情况时及时通知。# monitoring.py import logging import smtplib from email.mime.text import MimeText class MonitoringSystem: 监控系统 def __init__(self, alert_emailsNone): self.alert_emails alert_emails or [] self.logger logging.getLogger(__name__) def check_system_health(self, engine): 检查系统健康状态 checks { api_connection: self.check_api_connection(engine), database_connection: self.check_database_connection(engine), strategy_performance: self.check_strategy_performance(engine) } failed_checks {k: v for k, v in checks.items() if not v[healthy]} if failed_checks: self.send_alert(f系统健康检查失败: {failed_checks}) return all(check[healthy] for check in checks.values()) def send_alert(self, message): 发送告警信息 self.logger.error(f告警: {message}) # 邮件告警简化示例 if self.alert_emails: try: self.send_email_alert(message) except Exception as e: self.logger.error(f发送邮件告警失败: {e}) def send_email_alert(self, message): 发送邮件告警 # 实际实现需要配置SMTP服务器 msg MimeText(message) msg[Subject] 交易系统告警 msg[From] alertstrading.com msg[To] , .join(self.alert_emails) # 这里简化处理实际需要配置SMTP # with smtplib.SMTP(smtp.server.com) as server: # server.send_message(msg)8.2 日志与审计完善的日志系统对于问题排查和合规性至关重要# advanced_logging.py import logging import json from datetime import datetime class StructuredLogger: 结构化日志记录器 def __init__(self, name): self.logger logging.getLogger(name) def log_trade(self, action, symbol, quantity, price, reasonNone): 记录交易日志 log_data { timestamp: datetime.utcnow().isoformat(), action: action, symbol: symbol, quantity: quantity, price: price, reason: reason, type: trade } self.logger.info(json.dumps(log_data)) def log_strategy_signal(self, strategy, symbol, signal, dataNone): 记录策略信号 log_data { timestamp: datetime.utcnow().isoformat(), strategy: strategy, symbol: symbol, signal: signal, data: data, type: signal } self.logger.info(json.dumps(log_data)) # 配置详细日志 def setup_detailed_logging(): 设置详细日志配置 logging.basicConfig( levellogging.INFO 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 [点击领海量免费额度](https://taotoken.net/models/detail/chat?modelIddeepseek-v4-proutm_sourcett_blog_mr)