问题描述
解决方案
在 PTrade 量化交易平台中,打印日志是调试策略最主要的方式。平台提供了专门的 log 对象来记录不同级别的日志信息。
以下是关于如何在 PTrade 中使用日志功能的详细说明和代码示例。
1. 使用 log 对象
PTrade 不推荐使用 Python 原生的 print() 函数,而是推荐使用内置的 log 接口。这可以确保日志正确地显示在回测或交易终端的“日志”面板中,并且带有时间戳。
支持的日志级别
根据调试需求,可以使用以下不同级别的日志函数:
log.info(content):最常用。用于输出一般性的信息,如当前的股价、资金、买卖操作记录等。log.debug(content):用于输出详细的调试信息。log.warning(content):用于输出警告信息,表明出现非预期情况但策略仍可运行。log.error(content):用于输出错误信息,通常在try...except捕获异常时使用。log.critical(content):用于输出严重错误信息。
2. 格式化输出变量
在打印日志时,通常需要将字符串与变量(如价格、股票代码)结合。PTrade 环境支持 Python 标准的字符串格式化方式。为了保持对 Python 3.5 的最佳兼容性,建议使用 % 操作符。
- 打印字符串与数字:
log.info("当前价格: %s" % price) - 打印多个变量:
log.info("股票: %s, 数量: %s" % (security, amount)) - 打印对象/字典:
log.info(context.portfolio)
3. 完整代码示例
以下是一个完整的策略示例,展示了如何在 initialize(初始化)、handle_data(盘中运行)以及异常处理中使用日志。
def initialize(context):
# 初始化日志
g.security = '600570.SS'
set_universe(g.security)
# 打印初始化信息
log.info("策略初始化完成,股票池设置为: %s" % g.security)
def handle_data(context, data):
# 获取当前回测/交易时间
current_time = context.blotter.current_dt
# 获取最新价格
# 注意:data[g.security] 返回的是对象,需要获取具体属性如 .price 或 .close
current_price = data[g.security].price
# 1. 打印简单的文本信息
log.info("--------------------------------")
log.info("开始执行 handle_data")
# 2. 打印变量(时间与价格)
log.info("当前时间: %s, 标的: %s, 最新价: %s" % (current_time, g.security, current_price))
# 3. 打印账户资金信息 (打印对象)
cash = context.portfolio.cash
log.info("当前可用资金: %s" % cash)
# 4. 结合逻辑判断打印日志
if current_price > 0:
log.info("价格正常,准备检查买入条件...")
# 模拟买入操作日志
# order(g.security, 100)
# log.info("执行买入: %s, 数量: 100" % g.security)
else:
log.warning("警告:获取到的价格异常 (Price: %s)" % current_price)
# 5. 异常捕获中的日志使用
try:
# 模拟一个除以零的错误
x = 1 / 0
except Exception as e:
# 使用 log.error 打印错误堆栈或提示
log.error("计算过程中发生错误: %s" % e)
4. 调试建议
- 不要过度打印:在
handle_data或tick_data这种高频运行的函数中,如果每一行都打印日志,会导致回测速度变慢,且日志文件过大难以阅读。建议配合if条件语句,仅在关键节点(如发生交易、信号触发、资金不足时)打印。 - 查看位置:
- 回测模式:日志会显示在回测界面的下方“日志”标签页中。
- 交易模式:日志会显示在交易终端的运行日志窗口中,通常也会保存到本地的日志文件中。
- 对象检查:如果你不确定一个对象(如
context或data)里有什么属性,可以直接log.info(dir(data))或log.info(data)来查看其结构。
Q&A
Q: 为什么我的策略里 print() 函数的内容在日志面板里看不到?
A: 虽然 Python 支持 print(),但在 PTrade 的某些运行环境(特别是服务器端运行或实盘托管)中,标准输出(stdout)可能不会被重定向到前端日志面板。因此,始终建议使用 log.info() 等专用接口来确保日志可见。
Q: log.info 支持 f-string (如 f"价格: {price}") 吗?
A: PTrade 的 Python 环境通常支持 Python 3,因此支持 f-string。但是,为了确保在旧版本环境(如 Python 3.5)中的最大兼容性,官方文档和示例通常使用 %s 格式化。如果确认环境是 Python 3.6+,可以使用 f-string。
Q: 如何在日志中查看我的持仓详情?
A: 你可以直接打印 context.portfolio.positions。例如:log.info(context.portfolio.positions)。这将输出一个字典,包含所有持仓标的及其详细信息(如成本、数量、盈亏等)。
Q: 日志报错 "TypeError: not all arguments converted during string formatting" 是什么原因?
A: 这通常是因为 % 格式化符号后面的参数数量与字符串中的 %s 占位符数量不匹配。例如 log.info("价格: %s, 数量: %s" % price) 就会报错,因为有两个 %s 但只提供了一个变量。正确的写法是 log.info("价格: %s, 数量: %s" % (price, amount))。