3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 ptrade 量化交易平台中,由于券商底层的资金和持仓通常是统一计算的,如果在一个账户中同时运行模拟策略(或多个不同的实盘子策略),直接使用 context.portfolio 获取的资金和持仓数据会发生混淆。为了实现资金和持仓的有效隔离,我们需要在策略内部构建**“虚拟子账户”,并结合持久化技术(pickle)**来管理状态。
context.portfolio.cash 和 context.portfolio.positions 作为交易决策的唯一依据。g 中定义字典来记录当前策略专属的虚拟资金(g.virtual_cash)和虚拟持仓(g.virtual_positions)。on_trade_response(成交主推回调)来精准更新虚拟资金和持仓,确保与实际成交一致。pickle 模块将虚拟账户数据落地保存,防止策略重启或服务器升级导致数据丢失。以下是一个完整的代码框架,展示如何实现资金与持仓的隔离管理:
import pickle
import os
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 定义持久化文件路径
g.save_path = get_research_path() + 'virtual_account.pkl'
# 尝试加载历史虚拟账户数据
if os.path.exists(g.save_path):
try:
with open(g.save_path, 'rb') as f:
account_data = pickle.load(f)
g.virtual_cash = account_data.get('cash', 100000.0) # 默认初始资金10万
g.virtual_positions = account_data.get('positions', {})
log.info("成功加载虚拟账户数据")
except Exception as e:
log.error("加载虚拟账户失败: %s" % e)
init_virtual_account()
else:
init_virtual_account()
def init_virtual_account():
# 初始化虚拟账户
g.virtual_cash = 100000.0
g.virtual_positions = {}
save_virtual_account()
def save_virtual_account():
# 保存虚拟账户数据到本地
account_data = {
'cash': g.virtual_cash,
'positions': g.virtual_positions
}
try:
with open(g.save_path, 'wb') as f:
pickle.dump(account_data, f, -1)
except Exception as e:
log.error("保存虚拟账户失败: %s" % e)
def handle_data(context, data):
security = g.security
current_price = data[security]['close']
# 示例买入逻辑:如果虚拟资金充足,买入100股
cost = current_price * 100
if g.virtual_cash >= cost:
order(security, 100)
log.info("触发买入委托")
# 示例卖出逻辑:如果虚拟持仓中有该股票,全部卖出
virtual_amount = g.virtual_positions.get(security, 0)
if virtual_amount >= 100:
order(security, -100)
log.info("触发卖出委托")
def on_trade_response(context, trade_list):
# 接收成交主推,精准更新虚拟账户
for trade in trade_list:
# 仅处理已成状态 (status == '8')
if trade.get('status') == '8':
stock = trade['stock_code']
amount = trade['business_amount']
balance = trade['business_balance']
direction = trade['entrust_bs'] # 1-买,2-卖
if direction == '1': # 买入成交
g.virtual_cash -= balance
g.virtual_positions[stock] = g.virtual_positions.get(stock, 0) + amount
elif direction == '2': # 卖出成交
g.virtual_cash += balance
g.virtual_positions[stock] = g.virtual_positions.get(stock, 0) - amount
if g.virtual_positions[stock] <= 0:
del g.virtual_positions[stock]
log.info("虚拟账户更新 -> 资金: %.2f, 持仓: %s" % (g.virtual_cash, g.virtual_positions))
# 每次成交后持久化保存
save_virtual_account()
on_trade_response 中根据券商费率(如万分之三佣金+印花税等)额外扣除 g.virtual_cash 中的手续费。on_order_response 监控废单或撤单情况,避免虚拟资金被长期“冻结”。order 接口返回的 order_id,在全局维护一个 g.my_order_ids 列表。在主推回调中,只处理属于本策略的 order_id,从而实现多策略间的完美隔离。