convertible_bond
Query convertible bond non-market data including issuance details by date range or specific bond information by code.
Instructions
获取可转债非行情数据,支持两种查询方式:1)使用issue类型按时间范围查询可转债发行数据;2)使用info类型按代码查询可转债详细信息
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ts_code | No | 可转债代码,如'110001.SH'表示国电转债,'128001.SZ'表示平安转债。配合info类型使用可查询详细信息 | |
| data_type | Yes | 数据类型,可选值:issue(可转债发行数据)、info(可转债详细信息,通过代码查询) | |
| start_date | No | 起始日期,格式为YYYYMMDD,如'20230101'。用于查询发行数据的公告日期范围 | |
| end_date | No | 结束日期,格式为YYYYMMDD,如'20230131'。用于查询发行数据的公告日期范围 |
Implementation Reference
- src/tools/convertibleBond.ts:3-105 (handler)Core tool definition including handler (run function), schema (parameters), name, and description. The run method fetches convertible bond data (basic/issue/info) from Tushare API, handles errors, and formats output as formatted text.export const convertibleBond = { name: "convertible_bond", description: "获取可转债非行情数据,支持两种查询方式:1)使用issue类型按时间范围查询可转债发行数据;2)使用info类型按代码查询可转债详细信息", parameters: { type: "object", properties: { ts_code: { type: "string", description: "可转债代码,如'110001.SH'表示国电转债,'128001.SZ'表示平安转债。配合info类型使用可查询详细信息" }, data_type: { type: "string", description: "数据类型,可选值:issue(可转债发行数据)、info(可转债详细信息,通过代码查询)", enum: ["issue", "info"] }, start_date: { type: "string", description: "起始日期,格式为YYYYMMDD,如'20230101'。用于查询发行数据的公告日期范围" }, end_date: { type: "string", description: "结束日期,格式为YYYYMMDD,如'20230131'。用于查询发行数据的公告日期范围" } }, required: ["data_type"] }, async run(args: { ts_code?: string; data_type: string; start_date?: string; end_date?: string; }) { try { console.log('可转债数据查询参数:', args); const TUSHARE_API_KEY = TUSHARE_CONFIG.API_TOKEN; const TUSHARE_API_URL = TUSHARE_CONFIG.API_URL; if (!TUSHARE_API_KEY) { throw new Error('请配置TUSHARE_TOKEN环境变量'); } // 默认日期设置 const today = new Date(); const currentYear = today.getFullYear(); const defaultEndDate = `${currentYear}1231`; const defaultStartDate = `${currentYear - 1}0101`; const results: any[] = []; // 根据data_type决定要查询的API const dataTypes = args.data_type === 'info' ? ['basic', 'issue'] // info类型查询所有可用数据 : [args.data_type]; for (const dataType of dataTypes) { try { const result = await fetchConvertibleBondData( dataType, args.ts_code, args.start_date || defaultStartDate, args.end_date || defaultEndDate, TUSHARE_API_KEY, TUSHARE_API_URL ); if (result.data && result.data.length > 0) { results.push({ type: dataType, data: result.data, fields: result.fields }); } } catch (error) { console.warn(`获取${dataType}数据失败:`, error); results.push({ type: dataType, error: error instanceof Error ? error.message : '未知错误' }); } } if (results.length === 0) { throw new Error(`未找到相关可转债数据`); } // 格式化输出 const formattedOutput = formatConvertibleBondData(results, args.ts_code); return { content: [{ type: "text", text: formattedOutput }] }; } catch (error) { console.error('可转债数据查询错误:', error); return { content: [{ type: "text", text: `查询可转债数据时发生错误: ${error instanceof Error ? error.message : '未知错误'}` }] }; } }
- src/tools/convertibleBond.ts:109-209 (helper)Helper function to fetch raw data from Tushare API for specific data types (cb_basic, cb_issue), handling parameters mapping and response parsing.async function fetchConvertibleBondData( dataType: string, tsCode?: string, startDate?: string, endDate?: string, apiKey?: string, apiUrl?: string ) { const apiConfigs: Record<string, any> = { basic: { api_name: "cb_basic", default_fields: "ts_code,bond_short_name,stk_code,stk_short_name,maturity,par_value,issue_price,issue_size,remain_size,value_date,maturity_date,list_date,delist_date,exchange,conv_start_date,conv_end_date,first_conv_price,conv_price,rate_clause,put_clause,force_redeem_clause,resale_clause,cross_default_clause" }, issue: { api_name: "cb_issue", default_fields: "ts_code,ann_date,res_ann_date,plan_issue_size,issue_size,issue_price,issue_type,issue_cost,onl_code,onl_name,onl_date,onl_size,onl_pch_vol,onl_pch_num,onl_pch_excess,onl_winning_rate,shd_ration_code,shd_ration_name,shd_ration_date,shd_ration_record_date,shd_ration_pay_date,shd_ration_price,shd_ration_ratio,shd_ration_size,shd_ration_vol,shd_ration_num,shd_ration_excess,offl_size,offl_deposit,offl_pch_vol,offl_pch_num,offl_pch_excess,offl_winning_rate,lead_underwriter,lead_underwriter_vol" } }; const config = apiConfigs[dataType]; if (!config) { throw new Error(`不支持的数据类型: ${dataType}`); } // 构建请求参数 const params: any = { api_name: config.api_name, token: apiKey, params: {}, fields: config.default_fields }; // 根据Tushare文档严格映射参数 if (dataType === 'basic') { // cb_basic接口参数:ts_code, list_date, exchange if (tsCode) params.params.ts_code = tsCode; // 对于basic查询,如果提供了start_date,映射到list_date(上市日期) if (startDate) params.params.list_date = startDate; } else if (dataType === 'issue') { // cb_issue接口参数:ts_code, ann_date, start_date, end_date if (tsCode) params.params.ts_code = tsCode; // 对于issue查询,直接使用start_date和end_date作为公告日期范围 if (startDate) params.params.start_date = startDate; if (endDate) params.params.end_date = endDate; } // 设置请求超时 const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TUSHARE_CONFIG.TIMEOUT); try { console.log(`请求Tushare API: ${params.api_name},参数:`, params.params); // 发送请求 const response = await fetch(apiUrl!, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(params), signal: controller.signal }); if (!response.ok) { throw new Error(`Tushare API请求失败: ${response.status}`); } const data = await response.json(); // 处理响应数据 if (data.code !== 0) { throw new Error(`Tushare API错误: ${data.msg}`); } // 确保data.data和data.data.items存在 if (!data.data || !data.data.items) { throw new Error(`未找到${dataType}数据`); } // 获取字段名 const fields = data.data.fields; // 将数据转换为对象数组 const convertedData = data.data.items.map((item: any) => { const result: Record<string, any> = {}; fields.forEach((field: string, index: number) => { result[field] = item[index]; }); return result; }); return { data: convertedData, fields: fields }; } finally { clearTimeout(timeoutId); } }
- src/tools/convertibleBond.ts:212-244 (helper)Helper function to format fetched results into user-friendly markdown text report, with specialized formatters for basic and issue data.function formatConvertibleBondData(results: any[], tsCode?: string): string { let output = ` 🪙 可转债数据报告${tsCode ? ` - ${tsCode}` : ''}\n\n`; output += `📅 查询时间: ${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}\n\n`; results.forEach((result, index) => { if (result.error) { output += ` ❌ ${getDataTypeName(result.type)}查询失败\n\n`; output += `错误信息: ${result.error}\n\n`; return; } const dataTypeName = getDataTypeName(result.type); output += ` 📊 ${dataTypeName} (${result.data.length}条记录)\n\n`; switch (result.type) { case 'basic': output += formatBasicInfo(result.data); break; case 'issue': output += formatIssueInfo(result.data); break; default: output += formatGenericCBData(result.data, result.fields); break; } if (index < results.length - 1) { output += "\n---\n\n"; } }); return output; }
- src/index.ts:215-217 (registration)Tool registration in listTools handler, exposing name, description, and input schema.name: convertibleBond.name, description: convertibleBond.description, inputSchema: convertibleBond.parameters
- src/index.ts:335-341 (registration)Tool execution handler in callToolRequestSchema switch case, extracting arguments and calling convertibleBond.run.case "convertible_bond": { const ts_code = request.params.arguments?.ts_code ? String(request.params.arguments.ts_code) : undefined; const data_type = String(request.params.arguments?.data_type); const start_date = request.params.arguments?.start_date ? String(request.params.arguments.start_date) : undefined; const end_date = request.params.arguments?.end_date ? String(request.params.arguments.end_date) : undefined; return normalizeResult(await convertibleBond.run({ ts_code, data_type, start_date, end_date })); }