3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 Ptrade 量化交易平台中,由于模拟交易和实盘交易通常共享同一个底层资金账户,当多个策略同时运行时,极易出现资金抢占和持仓逻辑冲突的问题。特别是当多个策略操作同一只股票,或者使用了依赖全局持仓的下单函数时,干扰尤为严重。
order_target 和 order_target_value 函数会读取账户的总持仓。如果策略 A 买入了 100 股,策略 B 想要买入到 100 股,策略 B 发现账户里已经有 100 股了,就不会再买入,导致策略 B 逻辑失效。最直接的方法是让不同的策略操作完全不同的股票池。例如,策略 A 专门做沪深 300 成分股,策略 B 专门做中证 500 成分股。只要标的不重合,就不会出现持仓冲突。
在多策略环境下,强烈建议不要使用 order_target 和 order_target_value。请改用 order(按数量买卖)或 order_value(按金额买卖)。
如果多个策略必须操作同一只股票,就必须在策略内部(通过全局变量 g)维护该策略专属的虚拟资金和虚拟持仓,并结合 pickle 模块进行持久化保存,防止重启丢失。
以下示例展示了如何在策略内部维护专属的持仓记录,避免受账户真实总持仓的影响:
import pickle
from collections import defaultdict
NOTEBOOK_PATH = get_research_path()
PKL_FILE = NOTEBOOK_PATH + 'strategy_A_positions.pkl'
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 尝试加载策略专属的虚拟持仓
try:
with open(PKL_FILE, 'rb') as f:
g.my_positions = pickle.load(f)
except:
# 如果没有记录,初始化为空字典
g.my_positions = defaultdict(int)
# 为本策略分配虚拟初始资金
if 'virtual_cash' not in g.my_positions:
g.my_positions['virtual_cash'] = 100000.0
def handle_data(context, data):
security = g.security
current_price = data[security]['close']
# 获取策略专属持仓和资金
my_amount = g.my_positions.get(security, 0)
my_cash = g.my_positions['virtual_cash']
# 简单的买入逻辑:如果没有持仓且虚拟资金充足
if my_amount == 0 and my_cash > current_price * 100:
order(security, 100)
# 更新虚拟持仓和资金
g.my_positions[security] += 100
g.my_positions['virtual_cash'] -= current_price * 100
log.info("策略A买入 %s 100股" % security)
# 简单的卖出逻辑:如果有持仓
elif my_amount > 0 and current_price > 50: # 假设50为卖出条件
order(security, -my_amount)
# 更新虚拟持仓和资金
g.my_positions['virtual_cash'] += current_price * my_amount
g.my_positions[security] = 0
log.info("策略A卖出 %s 全部专属持仓" % security)
# 每天收盘前持久化保存虚拟持仓状态
with open(PKL_FILE, 'wb') as f:
pickle.dump(g.my_positions, f, -1)
initialize 中为每个策略硬编码分配最大可用资金,并在下单前校验,防止单个策略耗尽账户资金。on_order_response 或 on_trade_response,请注意 Ptrade 默认可能会推送非本策略产生的订单(可通过 set_parameters(receive_other_response="0") 关闭),务必通过维护策略自身的 order_id 列表来过滤属于本策略的订单。