你的策略"知道自己赚多少"吗?
很多人写策略的时候只关心信号:什么时候买、什么时候卖。
但实盘里有一个更核心的问题:
你的策略实时知道自己赚多少钱吗?
你可能会说:"我可以打开券商 APP 看啊"。
实盘里这种思路有 3 个问题:
APP 看的是延迟数据——不是毫秒级
APP 不能触发自动操作——你得人工盯
APP 看不到"策略层"的 PnL——比如某一组持仓的整体盈亏
5.4 这一节,就教你做一个比 APP 更好用的实时盈亏看板——而且能触发自动止盈止损。
一、PnL 监控的 4 个维度
PnL = Profit and Loss,简单说就是"赚和亏"。
| 维度 | 说明 | 实战意义 |
|---|---|---|
| 账户总盈亏 | 当前总资产 vs 初始总资产 | 策略整体表现 |
| 单股浮动盈亏 | 当前价 vs 成本价 | 触发个股止盈止损 |
| 日内实现盈亏 | 当天已成交的实际盈亏 | 算今天的"战绩" |
| 持仓浮动盈亏 | 所有持仓的未实现盈亏 | 行情波动的影响 |
这 4 个数随时都要能拿到。
二、获取账户盈亏
直接从 query_stock_asset 拿:
defget_account_pnl(trader, acc):
asset = trader.query_stock_asset(acc)
ifnotasset:
returnNone
return {
'total_asset': asset.total_asset,
'cash': asset.cash,
'market_value': asset.market_value,
'frozen_cash': asset.frozen_cash,
}
关键公式:当前总资产 - 开盘时总资产 = 日内盈亏
所以你的程序启动时要先记一下初始总资产,否则没法算日内盈亏。
三、获取持仓盈亏
defget_position_pnl(trader, acc):
positions = trader.query_stock_positions(acc)
ifnotpositions:
return []
return [{
'stock_code': p.stock_code,
'name': p.instrument_name,
'volume': p.volume,
'avg_price': p.avg_price, # 成本价
'last_price': p.last_price, # 当前价
'market_value': p.market_value, # 市值
'float_profit': p.float_profit, # 浮动盈亏 ⭐
'profit_rate': p.profit_rate, # 盈亏比例 ⭐
} forpinpositions]
两个关键字段:
float_profit—— 浮动盈亏的金额(正数=赚,负数=亏)profit_rate—— 盈亏比例(0.05 = 赚5%)
这两个字段是 xtdata 直接给的,你不用自己算。
四、实时 PnL 监控器
把"定时查询 + 数据聚合 + 告警判断"封装在一起:
importthreading
importtime
classPnLMonitor:
"""实时盈亏监控"""
def__init__(self, trader, acc, interval=5):
self.trader = trader
self.acc = acc
self.interval = interval
self.running = False
self.initial_asset = None# 启动时的总资产
self.current_pnl = {}
self.pnl_history = []
self.alert_threshold = 0.05# 盈亏告警阈值
defstart(self):
# 记录初始资产
asset = self.trader.query_stock_asset(self.acc)
ifasset:
self.initial_asset = asset.total_asset
self.running = True
self.thread = threading.Thread(target=self._monitor_loop, daemon=True)
self.thread.start()
print(f"📊 PnL监控启动,间隔 {self.interval}s")
defstop(self):
self.running = False
def_monitor_loop(self):
whileself.running:
self._update_pnl()
time.sleep(self.interval)
def_update_pnl(self):
asset = self.trader.query_stock_asset(self.acc)
positions = self.trader.query_stock_positions(self.acc)
ifnotasset:
return
# 日内盈亏
day_pnl = asset.total_asset-self.initial_assetifself.initial_assetelse0
day_rate = day_pnl/self.initial_assetifself.initial_assetelse0
# 浮动盈亏
total_float = 0
pos_pnl = []
ifpositions:
forpinpositions:
total_float += p.float_profitor0
pos_pnl.append({
'code': p.stock_code,
'pnl': p.float_profit,
'rate': p.profit_rate,
})
self.current_pnl = {
'timestamp': time.time(),
'total_asset': asset.total_asset,
'day_pnl': day_pnl,
'day_pnl_rate': day_rate,
'float_pnl': total_float,
'positions': pos_pnl,
}
self.pnl_history.append(self.current_pnl.copy())
self._check_alert()
def_check_alert(self):
rate = self.current_pnl.get('day_pnl_rate', 0)
ifabs(rate) >= self.alert_threshold:
ifrate>0:
print(f"📈 盈利告警: 今日 +{rate:.2%}")
else:
print(f"📉 亏损告警: 今日 {rate:.2%}")
defget_current_pnl(self):
returnself.current_pnl
defprint_pnl(self):
pnl = self.current_pnl
ifnotpnl:
return
print("\n"+"="*50)
print("实时盈亏报告")
print("="*50)
print(f"总资产: {pnl['total_asset']:,.2f}")
print(f"今日盈亏: {pnl['day_pnl']:+,.2f} ({pnl['day_pnl_rate']:+.2%})")
print(f"浮动盈亏: {pnl['float_pnl']:+,.2f}")
ifpnl['positions']:
print("\n持仓:")
forpinpnl['positions']:
rate = (p['rate'] or0) *100
val = p['pnl'] or0
print(f" {p['code']}: {val:+,.2f} ({rate:+.2f}%)")
print("="*50)
五、酷炫看板——用终端做一个"自动刷新"的UI
每秒清屏 + 重绘,模拟交易终端:
importos
classPnLDashboard:
"""实时盈亏看板"""
def__init__(self, pnl_monitor):
self.monitor = pnl_monitor
self.running = False
defstart(self):
self.running = True
self.thread = threading.Thread(target=self._display_loop, daemon=True)
self.thread.start()
defstop(self):
self.running = False
def_display_loop(self):
whileself.running:
self._refresh()
time.sleep(1)
def_refresh(self):
pnl = self.monitor.get_current_pnl()
ifnotpnl:
return
# 清屏
os.system('cls'ifos.name == 'nt'else'clear')
# 渲染
print("╔"+"═"*48+"╗")
print("║"+" 实时盈亏看板 ".center(44) +"║")
print("╠"+"═"*48+"╣")
print(f"║ 总资产: {pnl['total_asset']:>20,.2f} 元 ║")
day_pnl = pnl['day_pnl']
day_rate = pnl['day_pnl_rate'] *100
icon = '📈'ifday_pnl>= 0else'📉'
print(f"║ 今日盈亏: {icon} {day_pnl:>+14,.2f} ({day_rate:+.2f}%) ║")
float_pnl = pnl['float_pnl']
print(f"║ 浮动盈亏: {float_pnl:>+18,.2f} 元 ║")
print("╠"+"═"*48+"╣")
print("║ 持仓盈亏明细 ║")
forpinpnl.get('positions', [])[:5]:
rate = (p['rate'] or0) *100
val = p['pnl'] or0
print(f"║ {p['code']}: {val:>+12,.2f} ({rate:>+6.2f}%) ║")
print("╚"+"═"*48+"╝")
print(f"\n更新时间: {time.strftime('%H:%M:%S')}")
跑起来之后,比券商 APP 还直观——盘中扫一眼就知道仓位状况。
六、PnL 触发器——自动止盈止损
监控有了,下一步就是触发动作:
classPnLTrigger:
"""盈亏触发器:达到阈值自动平仓"""
def__init__(self, trader, acc, pnl_monitor):
self.trader = trader
self.acc = acc
self.monitor = pnl_monitor
self.take_profit = 0.10# 盈利 10% 止盈
self.stop_loss = -0.05# 亏损 5% 止损
self.triggered = set() # 已触发的股票
defcheck_and_trigger(self):
pnl = self.monitor.get_current_pnl()
ifnotpnl:
return
forpinpnl.get('positions', []):
code = p['code']
rate = p['rate'] or0
ifcodeinself.triggered:
continue
ifrate>= self.take_profit:
print(f"🎯 触发止盈: {code} +{rate:.2%}")
self._sell_position(code)
self.triggered.add(code)
elifrate<= self.stop_loss:
print(f"🛑 触发止损: {code} {rate:.2%}")
self._sell_position(code)
self.triggered.add(code)
def_sell_position(self, stock_code):
"""市价清仓"""
pos = self.trader.query_stock_position(self.acc, stock_code)
ifnotposorpos.can_use_volume<= 0:
return
fromxtquantimportxtconstant
pt = (xtconstant.MARKET_SH_CONVERT_5_CANCEL
ifstock_code.endswith('.SH')
elsextconstant.MARKET_SZ_CONVERT_5_CANCEL)
self.trader.order_stock_async(
self.acc, stock_code, xtconstant.STOCK_SELL,
pos.can_use_volume, pt, 0,
'pnl_trigger', '止盈止损',
)
第6章 6.2 节会专门做一个完整版的"止盈止损机器人",这里先把核心逻辑展示。
七、四个监控指标的速查表
| 指标 | 来源 | 说明 |
|---|---|---|
total_asset | asset.total_asset | 总资产(现金 + 市值) |
float_profit | position.float_profit | 单股浮动盈亏 |
profit_rate | position.profit_rate | 单股盈亏比例 |
day_pnl | 计算得出 | 当前总资产 - 初始总资产 |
实战提醒:
profit_rate是小数,不是百分数。0.05 = 5%。打印的时候记得* 100或者用{:.2%}。
八、小结
PnL 监控四维度:总资产、浮动盈亏、日内盈亏、单股盈亏
float_profit/profit_rate是 xtdata 直接给的看板用"清屏+重绘"模拟实时刷新
PnL 触发器结合止盈止损是最实用的风控组合
启动时记一下初始资产,否则算不出日内盈亏
写在最后
实盘里你的"心里有数",比策略本身还重要。
知道自己赚多少、亏多少、波动有多大——这些数据让你能理性决策:何时加仓、何时减仓、何时止损。
一个实时盈亏看板,不会让你的策略更聪明,但会让你做出更好的人为干预。
下一篇预告
PnL 监控的是自己的状态。但实盘里还有一个外部威胁——大盘。
下一篇 5.5 大盘熔断引擎——暴跌时刻锁仓保命:
大盘指数实时监控(上证、深证、创业板)
暴跌阈值的设定(-3%、-5%、-7%)
熔断时一键锁仓 / 一键清仓
熔断状态的"冷却时间"机制
你的策略有实时 PnL 监控吗?盈亏告警阈值设的多少?
评论区聊聊——你的止盈止损阈值是怎么定的?固定百分比还是动态调整?
如果这一篇对你有帮助:
点个 在看 让我知道这种"看板级"的内容你需要 👍
转给一个还在用券商 APP 看盈亏的朋友 🔁
关注 + 星标 ⭐ 第一时间看下一篇
风险提示:本文仅作技术分享与教学用途,不构成任何投资建议。量化交易有风险,实盘需谨慎。

研报速递
发表评论
发表评论: