3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在进行融资融券(两融)交易时,合理的杠杆控制和单股建仓上限是避免爆仓和过度集中风险的关键。在 ptrade 平台中,我们可以通过以下接口实现动态风控:
get_crdt_fund(cash_group=None):获取当前可融资金信息。返回字典中包含 enable_balance(可用资金/可融资金)。get_margin_assert():获取信用资产信息。返回字典中包含 assure_asset(担保资产总值)和 total_debit(负债总额)。get_margincash_open_amount(security, price=None):查询单只融资标的的最大可买数量。$$\text{当前实际杠杆} = \frac{\text{负债总额 (total_debit)}}{\text{担保资产 (assure_asset)}}$$
通过设定最大允许杠杆(如 1.2 倍)和单股最大持仓比例(如占担保资产的 30%),我们可以在每次建仓前动态计算并限制买入。
以下是一个在 ptrade 交易模块中运行的完整两融风控策略示例:
# -*- coding: utf-8 -*-
def initialize(context):
# 设置操作的融资标的
g.security = '600570.SS' # 恒生电子
set_universe(g.security)
# 风控参数设置
g.MAX_LEVERAGE = 1.2 # 最大允许实际杠杆率
g.SINGLE_STOCK_LIMIT = 0.3 # 单股最大持仓占担保资产的比例
def handle_data(context, data):
# 1. 获取信用资产与负债信息
margin_assert = get_margin_assert()
if not margin_assert:
log.warning("无法获取信用资产信息,暂停交易")
return
assure_asset = margin_assert.get('assure_asset', 0.0) # 担保资产
total_debit = margin_assert.get('total_debit', 0.0) # 负债总额
# 2. 计算当前实际杠杆率
current_leverage = 0.0
if assure_asset > 0:
current_leverage = total_debit / assure_asset
log.info(f"当前担保资产: {assure_asset}, 当前负债: {total_debit}, 当前实际杠杆率: {current_leverage:.2f}")
# 杠杆超限风控:若当前实际杠杆已超过设定阈值,则禁止继续融资买入
if current_leverage >= g.MAX_LEVERAGE:
log.warning(f"当前杠杆率 {current_leverage:.2f} 已达到或超过上限 {g.MAX_LEVERAGE},触发风控,禁止融资买入!")
return
# 3. 获取当前可融资金
crdt_fund = get_crdt_fund(cash_group=1) # 1表示普通头寸
if not crdt_fund:
log.warning("无法获取可融资金信息")
return
enable_balance = crdt_fund.get('enable_balance', 0.0) # 可融资金额
log.info(f"当前可用融资资金: {enable_balance}")
# 4. 单股持仓上限风控
# 获取当前该股的持仓市值
pos = get_position(g.security)
current_pos_value = pos.amount * pos.last_sale_price if pos else 0.0
# 计算单股最大允许持仓市值
max_allowed_value = assure_asset * g.SINGLE_STOCK_LIMIT
# 计算本次最大可买入的市值
allow_buy_value = max_allowed_value - current_pos_value
if allow_buy_value <= 0:
log.warning(f"{g.security} 当前持仓市值 {current_pos_value} 已超过单股上限比例 {g.SINGLE_STOCK_LIMIT*100}%,禁止买入!")
return
# 5. 结合可融资金与单股上限计算最终拟买入金额
# 实际买入金额不能超过可用融资资金,也不能超过单股风控剩余额度
final_buy_value = min(enable_balance, allow_buy_value)
# 获取最新价格并计算买入数量
snapshot = get_snapshot(g.security)
if not snapshot or g.security not in snapshot:
log.warning("获取行情快照失败")
return
last_price = snapshot[g.security].get('last_px', 0.0)
if last_price > 0:
# 理论买入股数(向下取整百股)
target_amount = int(final_buy_value / last_price / 100) * 100
# 6. 查询柜台该标的最大可融资买入数量,进行二次校验
max_open_dict = get_margincash_open_amount(g.security)
max_open_amount = max_open_dict.get(g.security, 0) if max_open_dict else 0
final_amount = min(target_amount, max_open_amount)
if final_amount >= 100:
log.info(f"风控通过。拟融资买入 {g.security} : {final_amount} 股,价格: {last_price}")
margincash_open(g.security, final_amount, limit_price=last_price)
else:
log.info("计算所得买入数量不足100股,不执行委托")
get_crdt_fund 返回的实际可用融资头寸,还通过 get_margin_assert 限制了整体杠杆率,防止在市场波动时因过度授信导致账户整体维持担保比例(MDE)过低。g.SINGLE_STOCK_LIMIT 限制单股持仓比例,避免单一标的暴跌对信用账户造成毁灭性打击。get_margincash_open_amount,确保委托数量不会超过券商柜台允许的单股融资上限,提高报单成功率。