问题描述
解决方案
在PTrade中,查询信用账户(融资融券账户)资产的核心函数是 get_margin_assert()。
为了实现一个自动风控策略,我们需要关注维持担保比例(Maintenance Guarantee Ratio)。通常券商会在维持担保比例低于一定阈值(如130%)时进行强制平仓。
以下是一个完整的策略示例,它包含两个主要功能:
- 资产查询:实时获取信用账户的总资产、总负债和可用保证金。
- 自动风控:计算维持担保比例。如果比例低于预警线(例如150%),停止开仓;如果低于平仓线(例如140%),则自动卖出持仓以偿还负债,提升担保比例。
策略代码
def initialize(context):
"""
初始化函数
"""
# 设置我们要操作的股票池(此处仅为示例,风控是对全账户生效)
g.security = ['600570.SS', '000001.SZ']
set_universe(g.security)
# --- 风控参数设置 ---
# 预警线:维持担保比例低于此值(150%),禁止开新仓(仅打印日志,需配合开仓逻辑使用)
g.warning_ratio = 1.50
# 平仓线:维持担保比例低于此值(140%),触发自动卖出平仓
g.liquidation_ratio = 1.40
# 开启交易(此处仅为演示,实际交易中请谨慎)
g.trade_allowed = True
def handle_data(context, data):
"""
盘中运行函数,建议在分钟级别回测或交易中运行
"""
# 1. 查询信用资产信息
# 注意:get_margin_assert 仅在两融交易模块可用
margin_assets = get_margin_assert()
if not margin_assets:
log.info("未获取到信用资产信息,请确认账号类型或连接状态。")
return
# 获取关键资产数据
# 担保资产 (总资产)
total_asset = margin_assets.get('assure_asset', 0.0)
# 负债总额
total_debit = margin_assets.get('total_debit', 0.0)
# 可用保证金
enable_bail = margin_assets.get('enable_bail_balance', 0.0)
# 2. 计算维持担保比例
# 维持担保比例 = (现金 + 信用证券账户内证券市值总和) / (融资买入金额 + 融券卖出证券数量×当前市价 + 利息及费用总和)
# 即:总资产 / 总负债
if total_debit > 0:
current_ratio = total_asset / total_debit
else:
# 如果没有负债,比例视为无穷大,设为一个安全的高值
current_ratio = 999.0
# 打印当前账户状态
log.info("当前总资产: %.2f, 总负债: %.2f, 维持担保比例: %.2f%%" % (total_asset, total_debit, current_ratio * 100))
# 3. 执行风控逻辑
check_risk_management(context, current_ratio)
# 4. 正常的交易逻辑(示例)
# 只有在允许交易且资金充足时才开仓
if g.trade_allowed and current_ratio > g.warning_ratio:
# 示例:简单的买入逻辑
for stock in g.security:
# 如果没有持仓且资金足够,融资买入
if get_position(stock).amount == 0:
# 简单的资金分配逻辑
margincash_open(stock, 100)
def check_risk_management(context, current_ratio):
"""
风控检查与执行函数
"""
# 情况A:低于平仓线,必须紧急处理
if current_ratio < g.liquidation_ratio:
log.error("【严重警告】维持担保比例 %.2f%% 低于平仓线 %.2f%%,触发自动平仓风控!" % (current_ratio * 100, g.liquidation_ratio * 100))
g.trade_allowed = False # 禁止开新仓
# 执行平仓逻辑:卖出持仓偿还负债
# 策略:遍历持仓,卖出股票。这里简单演示卖出所有持仓,实际可根据市值大小排序卖出
positions = get_positions()
for stock in positions:
pos = positions[stock]
if pos.amount > 0:
# 获取卖券还款最大可卖数量(确保卖出是为了还款)
# 注意:get_margincash_close_amount 返回的是字典
amount_dict = get_margincash_close_amount(stock)
if amount_dict:
max_amount = amount_dict.get(stock, 0)
if max_amount > 0:
log.info("风控平仓:卖券还款 %s, 数量 %s" % (stock, max_amount))
# 卖券还款
margincash_close(stock, max_amount)
# 如果有现金,也可以选择直接还款
# margincash_direct_refund(10000)
# 情况B:低于预警线,但高于平仓线
elif current_ratio < g.warning_ratio:
log.warning("【警告】维持担保比例 %.2f%% 低于预警线 %.2f%%,停止开新仓。" % (current_ratio * 100, g.warning_ratio * 100))
g.trade_allowed = False
# 情况C:安全
else:
g.trade_allowed = True
代码解析
-
get_margin_assert():- 这是核心API。它返回一个字典,包含了信用账户的关键信息。
assure_asset: 担保资产(即账户总资产)。total_debit: 负债总额(融资+融券+利息费用)。enable_bail_balance: 可用保证金(可用于新开仓的资金)。
-
维持担保比例计算:
- 公式为
total_asset / total_debit。 - 代码中处理了
total_debit为 0 的情况,防止除以零错误。
- 公式为
-
风控逻辑 (
check_risk_management):- 预警阶段: 当比例低于
g.warning_ratio时,将全局变量g.trade_allowed设为False,阻止策略继续开仓。 - 平仓阶段: 当比例低于
g.liquidation_ratio时,触发强平逻辑。- 使用
get_positions()获取当前所有持仓。 - 使用
get_margincash_close_amount(stock)查询该股票可用于“卖券还款”的最大数量。 - 使用
margincash_close(stock, amount)执行卖出并直接偿还融资负债。
- 使用
- 预警阶段: 当比例低于
-
注意事项:
- Python版本兼容性: 代码使用了
%格式化字符串,兼容 Python 3.5 及以上版本。 - 交易频率: 此代码在
handle_data中运行。如果是分钟级别回测,它每分钟检查一次。如果是实盘,建议配合run_interval使用以获得更快的响应速度(例如每3秒检查一次)。 - API 权限:
get_margin_assert和margincash_close等函数仅在开通了融资融券权限的交易环境中有效,普通股票回测中调用会报错或返回空。
- Python版本兼容性: 代码使用了
Q&A
Q: 如何将风控检查频率提高到秒级?
A: 可以在 initialize 中使用 run_interval 函数。例如:
def initialize(context):
# ... 其他初始化 ...
# 每 5 秒执行一次风控检查
run_interval(context, risk_control_func, seconds=5)
def risk_control_func(context):
# 在这里放入获取资产和判断比例的逻辑
pass
Q: margincash_close 和 order 有什么区别?
A: order 是普通买卖或担保品买卖(在两融账户中通常指担保品卖出,资金回到余额)。而 margincash_close 是卖券还款,卖出股票获得的资金会优先直接偿还融资负债,这对于提升维持担保比例是最直接有效的方式。
Q: 为什么计算比例时要判断负债是否为0?
A: 如果您没有进行融资或融券,负债为0。在数学上除以0是非法的,会导致程序报错停止运行。因此必须处理这种情况,通常将无负债时的风险视为0(即安全比例无限大)。