Skip to main content
Glama

Financial News and Notes MCP Server

MIT License
129
199
  • Apple
  • Linux
marginTrade.ts16.6 kB
import { TUSHARE_CONFIG } from '../config.js'; export const marginTrade = { name: "margin_trade", description: "获取融资融券相关数据,支持多种数据类型:标的股票、交易汇总、交易明细、转融券汇总等", parameters: { type: "object", properties: { data_type: { type: "string", description: "数据类型,可选值:margin_secs(融资融券标的股票)、margin(融资融券交易汇总)、margin_detail(融资融券交易明细)、slb_len_mm(做市借券交易汇总)" }, ts_code: { type: "string", description: "股票代码,如'000001.SZ'、'600000.SH'等(部分接口可选)" }, start_date: { type: "string", description: "起始日期,格式YYYYMMDD,如'20240101'" }, end_date: { type: "string", description: "结束日期,格式YYYYMMDD,如'20240131'(可选,默认为当前日期)" }, exchange: { type: "string", description: "交易所代码,可选值:SSE(上海证券交易所)、SZSE(深圳证券交易所)、BSE(北京证券交易所),仅margin_secs接口使用" } }, required: ["data_type", "start_date"] }, async run(args: { data_type: string; ts_code?: string; start_date: string; end_date?: string; exchange?: 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环境变量'); } let data; let formattedOutput; switch (args.data_type) { case 'margin_secs': // 融资融券标的(盘前更新) data = await fetchMarginSecs(args, TUSHARE_API_KEY, TUSHARE_API_URL); formattedOutput = formatMarginSecs(data, args); break; case 'margin': // 融资融券交易汇总 if (!args.ts_code) { throw new Error('融资融券交易汇总查询需要提供股票代码(ts_code)'); } data = await fetchMarginSummary(args, TUSHARE_API_KEY, TUSHARE_API_URL); formattedOutput = formatMarginSummary(data, args); break; case 'margin_detail': // 融资融券交易明细 if (!args.ts_code) { throw new Error('融资融券交易明细查询需要提供股票代码(ts_code)'); } data = await fetchMarginDetail(args, TUSHARE_API_KEY, TUSHARE_API_URL); formattedOutput = formatMarginDetail(data, args); break; case 'slb_len_mm': // 做市借券交易汇总 data = await fetchSlbLenMm(args, TUSHARE_API_KEY, TUSHARE_API_URL); formattedOutput = formatSlbLenMm(data, args); break; default: throw new Error(`不支持的数据类型: ${args.data_type}`); } if (!data || data.length === 0) { throw new Error(`未找到相关融资融券数据`); } return { content: [{ type: "text", text: formattedOutput }] }; } catch (error) { console.error('融资融券数据查询错误:', error); return { content: [{ type: "text", text: `查询融资融券数据时发生错误: ${error instanceof Error ? error.message : '未知错误'}` }] }; } } }; // 1. 融资融券标的(盘前更新) async function fetchMarginSecs( args: any, apiKey: string, apiUrl: string ) { const params = { api_name: "margin_secs", token: apiKey, params: { ...(args.ts_code && { ts_code: args.ts_code }), start_date: args.start_date, ...(args.end_date && { end_date: args.end_date }), ...(args.exchange && { exchange: args.exchange }) }, fields: "trade_date,ts_code,name,exchange" }; return await callTushareAPI(params, apiUrl, 'margin_secs'); } // 2. 融资融券交易汇总 async function fetchMarginSummary( args: any, apiKey: string, apiUrl: string ) { const params = { api_name: "margin", token: apiKey, params: { ts_code: args.ts_code, start_date: args.start_date, ...(args.end_date && { end_date: args.end_date }) }, fields: "trade_date,ts_code,rzye,rzmre,rzche,rqye,rqmcl,rqchl,rzrqye" }; return await callTushareAPI(params, apiUrl, 'margin'); } // 3. 融资融券交易明细 async function fetchMarginDetail( args: any, apiKey: string, apiUrl: string ) { const params = { api_name: "margin_detail", token: apiKey, params: { ts_code: args.ts_code, start_date: args.start_date, ...(args.end_date && { end_date: args.end_date }) }, fields: "trade_date,ts_code,rzye,rzmre,rqye,rqmcl,rzrqye" }; return await callTushareAPI(params, apiUrl, 'margin_detail'); } // 4. 做市借券交易汇总 async function fetchSlbLenMm( args: any, apiKey: string, apiUrl: string ) { const params = { api_name: "slb_len_mm", token: apiKey, params: { ...(args.ts_code && { ts_code: args.ts_code }), start_date: args.start_date, ...(args.end_date && { end_date: args.end_date }) }, fields: "trade_date,ts_code,name,ope_inv,lent_qnt,cls_inv,end_bal" }; return await callTushareAPI(params, apiUrl, 'slb_len_mm'); } // 通用API调用函数 async function callTushareAPI(params: any, apiUrl: string, apiName: string) { console.log(`请求${apiName}数据,参数:`, params.params); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TUSHARE_CONFIG.TIMEOUT); try { const response = await fetch(apiUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(params), signal: controller.signal }); clearTimeout(timeoutId); 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}`); } if (!data.data || !data.data.items || data.data.items.length === 0) { return []; } const fieldsArray = data.data.fields; const resultData = data.data.items.map((item: any) => { const result: Record<string, any> = {}; fieldsArray.forEach((field: string, index: number) => { result[field] = item[index]; }); return result; }); console.log(`成功获取到${resultData.length}条${apiName}数据记录`); return resultData; } catch (error) { clearTimeout(timeoutId); throw error; } } // 格式化融资融券标的数据 function formatMarginSecs(data: any[], args: any): string { let output = `# 📋 融资融券标的股票列表\n\n`; output += `📅 查询期间: ${args.start_date}`; if (args.end_date) { output += ` ~ ${args.end_date}`; } output += `\n`; if (args.exchange) { output += `🏛️ 交易所: ${getExchangeName(args.exchange)}\n`; } output += `📊 标的数量: ${data.length}只\n\n`; if (data.length === 0) { output += `ℹ️ 暂无融资融券标的数据\n\n`; return output; } // 按交易所分组统计 const exchangeStats: Record<string, number> = {}; data.forEach(item => { const exchange = item.exchange || '未知'; exchangeStats[exchange] = (exchangeStats[exchange] || 0) + 1; }); output += `## 📈 按交易所统计\n\n`; output += `| 交易所 | 标的数量 | 占比 |\n`; output += `|--------|----------|------|\n`; Object.entries(exchangeStats).forEach(([exchange, count]) => { const percentage = ((count / data.length) * 100).toFixed(2); output += `| ${getExchangeName(exchange)} | ${count}只 | ${percentage}% |\n`; }); // 显示详细列表(前50个) const displayData = data.slice(0, 50); output += `\n## 📋 详细标的列表 (前${displayData.length}条)\n\n`; output += `| 代码 | 名称 | 交易所 | 交易日期 |\n`; output += `|------|------|--------|----------|\n`; displayData.forEach(item => { output += `| ${item.ts_code} | ${item.name} | ${getExchangeName(item.exchange)} | ${item.trade_date} |\n`; }); if (data.length > 50) { output += `\n*显示前50条记录,共${data.length}条数据*\n`; } return output; } // 格式化融资融券交易汇总数据 function formatMarginSummary(data: any[], args: any): string { let output = `# 💰 ${args.ts_code} 融资融券交易汇总\n\n`; output += `📅 查询期间: ${args.start_date} ~ ${args.end_date}\n`; output += `📊 数据条数: ${data.length}条\n\n`; if (data.length === 0) { output += `ℹ️ 暂无融资融券交易汇总数据\n\n`; return output; } const sortedData = data.sort((a, b) => b.trade_date.localeCompare(a.trade_date)); const latestData = sortedData[0]; // 最新数据概览 output += `## 📈 最新数据概览 (${latestData.trade_date})\n\n`; output += `| 项目 | 金额/数量 | 说明 |\n`; output += `|------|----------|------|\n`; output += `| 💼 融资余额 | ${formatNumber(latestData.rzye)}元 | 当日融资买入后的余额 |\n`; output += `| 📊 融券余额 | ${formatNumber(latestData.rqye)}元 | 当日融券卖出后的余额 |\n`; output += `| 💰 融资融券余额 | ${formatNumber(latestData.rzrqye)}元 | 融资余额 + 融券余额 |\n\n`; // 期间统计 let totalRzmre = 0, totalRzche = 0, totalRqmcl = 0, totalRqchl = 0; sortedData.forEach(item => { totalRzmre += parseFloat(item.rzmre || 0); totalRzche += parseFloat(item.rzche || 0); totalRqmcl += parseFloat(item.rqmcl || 0); totalRqchl += parseFloat(item.rqchl || 0); }); output += `## 📊 期间统计汇总\n\n`; output += `| 项目 | 累计金额/数量 | 日均金额/数量 |\n`; output += `|------|-------------|-------------|\n`; output += `| 💵 融资买入额 | ${formatNumber(totalRzmre)}元 | ${formatNumber(totalRzmre / data.length)}元 |\n`; output += `| 💸 融资偿还额 | ${formatNumber(totalRzche)}元 | ${formatNumber(totalRzche / data.length)}元 |\n`; output += `| 📈 融券卖出量 | ${formatNumber(totalRqmcl)} | ${formatNumber(totalRqmcl / data.length)} |\n`; output += `| 📉 融券偿还量 | ${formatNumber(totalRqchl)} | ${formatNumber(totalRqchl / data.length)} |\n\n`; // 详细记录表格 const displayData = sortedData.slice(0, 10); output += `## 📋 详细交易记录 (最近${displayData.length}个交易日)\n\n`; output += `| 交易日期 | 融资余额(万元) | 融资买入(万元) | 融资偿还(万元) | 融券余额(万元) | 融券卖出量 | 融券偿还量 |\n`; output += `|---------|--------------|--------------|--------------|--------------|----------|-----------|\n`; displayData.forEach(item => { const rzye = (parseFloat(item.rzye || 0) / 10000).toFixed(2); const rzmre = (parseFloat(item.rzmre || 0) / 10000).toFixed(2); const rzche = (parseFloat(item.rzche || 0) / 10000).toFixed(2); const rqye = (parseFloat(item.rqye || 0) / 10000).toFixed(2); const rqmcl = formatNumber(item.rqmcl || 0); const rqchl = formatNumber(item.rqchl || 0); output += `| ${item.trade_date} | ${rzye} | ${rzmre} | ${rzche} | ${rqye} | ${rqmcl} | ${rqchl} |\n`; }); return output; } // 格式化融资融券交易明细数据 function formatMarginDetail(data: any[], args: any): string { let output = `# 📊 ${args.ts_code} 融资融券交易明细\n\n`; output += `📅 查询期间: ${args.start_date} ~ ${args.end_date}\n`; output += `📊 数据条数: ${data.length}条\n\n`; if (data.length === 0) { output += `ℹ️ 暂无融资融券交易明细数据\n\n`; return output; } const sortedData = data.sort((a, b) => b.trade_date.localeCompare(a.trade_date)); // 显示详细明细表格 const displayData = sortedData.slice(0, 20); output += `## 📋 交易明细记录 (最近${displayData.length}个交易日)\n\n`; output += `| 交易日期 | 融资余额(万元) | 融资买入(万元) | 融券余额(万元) | 融券卖出量 | 融资融券余额(万元) |\n`; output += `|---------|--------------|--------------|--------------|----------|----------------|\n`; displayData.forEach(item => { const rzye = (parseFloat(item.rzye || 0) / 10000).toFixed(2); const rzmre = (parseFloat(item.rzmre || 0) / 10000).toFixed(2); const rqye = (parseFloat(item.rqye || 0) / 10000).toFixed(2); const rqmcl = formatNumber(item.rqmcl || 0); const rzrqye = (parseFloat(item.rzrqye || 0) / 10000).toFixed(2); output += `| ${item.trade_date} | ${rzye} | ${rzmre} | ${rqye} | ${rqmcl} | ${rzrqye} |\n`; }); if (sortedData.length > 20) { output += `\n*显示最近20条记录,共${sortedData.length}条数据*\n`; } return output; } // 格式化做市借券交易汇总数据 function formatSlbLenMm(data: any[], args: any): string { let output = `# 🏦 做市借券交易汇总\n\n`; output += `📅 查询期间: ${args.start_date}`; if (args.end_date) { output += ` ~ ${args.end_date}`; } output += `\n`; if (args.ts_code) { output += `📈 股票代码: ${args.ts_code}\n`; } output += `📊 数据条数: ${data.length}条\n\n`; if (data.length === 0) { output += `ℹ️ 暂无做市借券交易数据\n\n`; return output; } const sortedData = data.sort((a, b) => b.trade_date.localeCompare(a.trade_date)); // 汇总统计 let totalOpeInv = 0, totalLentQnt = 0, totalClsInv = 0, totalEndBal = 0; sortedData.forEach(item => { totalOpeInv += parseFloat(item.ope_inv || 0); totalLentQnt += parseFloat(item.lent_qnt || 0); totalClsInv += parseFloat(item.cls_inv || 0); totalEndBal += parseFloat(item.end_bal || 0); }); output += `## 📊 汇总统计\n\n`; output += `| 项目 | 数量/金额 |\n`; output += `|------|----------|\n`; output += `| 📦 总期初余量 | ${formatNumber(totalOpeInv)}万股 |\n`; output += `| 🔄 总融出数量 | ${formatNumber(totalLentQnt)}万股 |\n`; output += `| 📦 总期末余量 | ${formatNumber(totalClsInv)}万股 |\n`; output += `| 💰 总期末余额 | ${formatNumber(totalEndBal)}万元 |\n\n`; // 详细记录表格 const displayData = sortedData.slice(0, 15); output += `## 📋 详细交易记录 (前${displayData.length}条)\n\n`; output += `| 交易日期 | 股票代码 | 股票名称 | 期初余量(万股) | 融出数量(万股) | 期末余量(万股) | 期末余额(万元) |\n`; output += `|---------|----------|----------|--------------|--------------|--------------|----------------|\n`; displayData.forEach(item => { const opeInv = parseFloat(item.ope_inv || 0).toFixed(2); const lentQnt = item.lent_qnt ? parseFloat(item.lent_qnt).toFixed(2) : '-'; const clsInv = parseFloat(item.cls_inv || 0).toFixed(2); const endBal = parseFloat(item.end_bal || 0).toFixed(2); output += `| ${item.trade_date} | ${item.ts_code} | ${item.name} | ${opeInv} | ${lentQnt} | ${clsInv} | ${endBal} |\n`; }); if (sortedData.length > 15) { output += `\n*显示前15条记录,共${sortedData.length}条数据*\n`; } // 数据说明 output += `\n## 📝 数据说明\n\n`; output += `- **期初余量**: 交易日开始时的借券余量\n`; output += `- **融出数量**: 当日新增的借券数量\n`; output += `- **期末余量**: 交易日结束时的借券余量\n`; output += `- **期末余额**: 期末借券余量对应的市值金额\n`; return output; } // 辅助函数 function getExchangeName(exchange: string): string { const exchangeMap: Record<string, string> = { 'SSE': '上交所', 'SZSE': '深交所', 'BSE': '北交所', '上交所': '上交所', '深交所': '深交所', '北交所': '北交所' }; return exchangeMap[exchange] || exchange; } function formatNumber(num: any): string { if (num === null || num === undefined || num === '') { return '0'; } const numValue = parseFloat(num); if (isNaN(numValue)) { return '0'; } if (numValue >= 100000000) { return (numValue / 100000000).toFixed(2) + '亿'; } else if (numValue >= 10000) { return (numValue / 10000).toFixed(2) + '万'; } else { return numValue.toLocaleString(); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/guangxiangdebizi/my-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server