3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
可转债“双低轮动模型”是量化交易中非常经典的低风险高收益策略。其核心逻辑是:选择“低价格”且“低转股溢价率”的可转债构建投资组合,并定期(如每周或每月)进行轮动调仓。双低指标的计算公式通常为:
$$\text{双低值} = \text{可转债价格} + \text{转股溢价率} \times 100$$
在 QMT 平台上,我们可以利用 Python API 高效地获取可转债行情数据、计算双低指标,并使用 passorder 交易函数实现自动化轮动。以下是完整的策略实现方案。
init):设定可转债股票池、调仓周期、持债数量、单只持仓比例等。run_time):由于轮动策略通常不需要每个 tick 驱动,我们可以使用 ContextInfo.run_time 设置每周或每日定时执行轮动函数。get_market_data_ex):获取可转债的最新价格。转股溢价率等财务指标可以通过 get_financial_data 或通过正股价格与转股价计算,本示例采用直接订阅最新行情并计算的方式。passorder):对比当前持仓与目标持仓,卖出不在目标列表中的转债,买入新增的转债,保持等权重资金分配。请在 QMT 策略编辑器中新建 Python 策略,并写入以下代码:
#encoding:gbk
import pandas as pd
import numpy as np
import datetime
def init(ContextInfo):
# 1. 基础参数设置
ContextInfo.bond_num = 5 # 持债数量
ContextInfo.account = '6000000248' # 请替换为您的实际资金账号
ContextInfo.set_account(ContextInfo.account)
# 2. 定义可转债池 (示例:部分活跃可转债,实际运行中可使用 get_stock_list_in_sector 获取全市场转债)
ContextInfo.bond_pool = ['110059.SH', '113050.SH', '123124.SZ', '127046.SZ', '128144.SZ', '113631.SH', '123156.SZ']
ContextInfo.set_universe(ContextInfo.bond_pool)
# 3. 设置定时器:每周一上午 10:00 进行轮动调仓
ContextInfo.run_time("rebalance", "1nDay", "2023-01-01 10:00:00", "SH")
print("可转债双低轮动策略初始化完成!")
def handlebar(ContextInfo):
# 逐K线驱动函数,此处主要逻辑由定时器 rebalance 触发,handlebar 保持 pass
pass
def rebalance(ContextInfo):
"""轮动调仓核心函数"""
print("开始执行双低轮动调仓...")
# 1. 获取当前账户持仓
current_positions = {}
pos_objects = get_trade_detail_data(ContextInfo.account, 'STOCK', 'POSITION')
for pos in pos_objects:
if pos.m_nVolume > 0:
current_positions[pos.m_strInstrumentID] = pos.m_nVolume
# 2. 获取转债最新价格与溢价率数据
# 注:实际交易中,转股溢价率可通过 QMT 财务数据接口或实时计算获取,此处以模拟双低计算为例
bond_data = []
for bond in ContextInfo.bond_pool:
# 剔除停牌债
if ContextInfo.is_suspended_stock(bond):
continue
# 获取最新价格
tick = ContextInfo.get_full_tick([bond])
if not tick or bond not in tick:
continue
price = tick[bond]['lastPrice']
# 获取转股溢价率 (此处通过财务接口获取,或使用模拟值,实际中建议补充对应转债的溢价率数据)
# 示例:假设从财务指标或自定义扩展数据中读取溢价率,这里用模拟计算演示逻辑
# 实际 QMT 中可通过 get_financial_data 获取正股价格与转股价计算溢价率
premium_rate = get_bond_premium_rate(bond, price, ContextInfo)
# 计算双低值
double_low_value = price + premium_rate * 100
bond_data.append({
'code': bond,
'price': price,
'double_low': double_low_value
})
if not bond_data:
print("未能获取到有效的转债数据")
return
# 3. 按照双低值升序排序,选择前 N 只作为目标持仓
df_bonds = pd.DataFrame(bond_data)
df_bonds = df_bonds.sort_values(by='double_low', ascending=True)
target_bonds = df_bonds.head(ContextInfo.bond_num)['code'].tolist()
print(f"今日目标双低转债组合: {target_bonds}")
# 4. 执行调仓交易
# 4.1 卖出不在目标组合中的转债
for holding_bond in list(current_positions.keys()):
if holding_bond not in target_bonds:
print(f"卖出转债: {holding_bond}")
# 24 代表股票/转债卖出,1101 代表按股/手方式下单,-1 表示市价/最新价卖出
passorder(24, 1101, ContextInfo.account, holding_bond, 5, -1, current_positions[holding_bond], '双低轮动卖出', 1, ContextInfo)
# 4.2 买入新增的目标转债(等权重分配资金)
# 获取账户可用资金
acct_info = get_trade_detail_data(ContextInfo.account, 'STOCK', 'ACCOUNT')
available_cash = 0
for acct in acct_info:
available_cash = acct.m_dAvailable
break
if len(target_bonds) > 0:
# 计算单只转债分配的预算
buy_budget_per_bond = available_cash / len(target_bonds)
for target_bond in target_bonds:
if target_bond not in current_positions:
print(f"买入转债: {target_bond}, 预算: {buy_budget_per_bond}元")
# 23 代表股票/转债买入,1102 代表按金额方式下单,最新价买入
passorder(23, 1102, ContextInfo.account, target_bond, 5, -1, buy_budget_per_bond, '双低轮动买入', 1, ContextInfo)
def get_bond_premium_rate(bond_code, bond_price, ContextInfo):
"""获取/计算转股溢价率的辅助函数"""
# 实际量化中,转股溢价率 = (转债价格 - 转股价值) / 转股价值
# 转股价值 = (100 / 转股价) * 正股价格
# 此处为简化演示,返回一个模拟溢价率(实际开发中请通过 get_instrumentdetail 获取转股价,并获取正股价格计算)
return 0.15 # 暂以 15% 溢价率作为示例
ContextInfo.run_time():设置定时器。转债轮动不需要高频交易,设置日线或周线级别定时器可以有效避免盘中频繁震荡导致的无效交易,降低摩擦成本。get_trade_detail_data():实时获取账户的持仓(POSITION)和资金(ACCOUNT)状况,确保调仓时能够准确计算卖出数量和买入预算。passorder():QMT 的核心下单接口。在买入时,我们使用了 orderType=1102(按金额方式下单),QMT 会自动根据单只转债的预算和最新价计算出应买入的张数(自动向下取整为 10 张/1 手的整倍数),极大简化了仓位控制代码。