mseep-a-share-mcp 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tools/date_utils.py ADDED
@@ -0,0 +1,180 @@
1
+ """
2
+ Date utility tools for MCP server.
3
+ Contains tools for retrieving current date and latest trading date.
4
+ """
5
+ import logging
6
+ from datetime import datetime, timedelta
7
+ import calendar
8
+
9
+ from mcp.server.fastmcp import FastMCP
10
+ from src.data_source_interface import FinancialDataSource
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def register_date_utils_tools(app: FastMCP, active_data_source: FinancialDataSource):
16
+ """
17
+ Register date utility tools with the MCP app.
18
+
19
+ Args:
20
+ app: The FastMCP app instance
21
+ active_data_source: The active financial data source
22
+ """
23
+
24
+ # @app.tool()
25
+ # def get_current_date() -> str:
26
+ # """
27
+ # 获取当前日期,可用于查询最新数据。
28
+
29
+ # Returns:
30
+ # 当前日期,格式为'YYYY-MM-DD'。
31
+ # """
32
+ # logger.info("Tool 'get_current_date' called")
33
+ # current_date = datetime.now().strftime("%Y-%m-%d")
34
+ # logger.info(f"Returning current date: {current_date}")
35
+ # return current_date
36
+
37
+ @app.tool()
38
+ def get_latest_trading_date() -> str:
39
+ """
40
+ 获取最近的交易日期。如果当天是交易日,则返回当天日期;否则返回最近的交易日。
41
+
42
+ Returns:
43
+ 最近的交易日期,格式为'YYYY-MM-DD'。
44
+ """
45
+ logger.info("Tool 'get_latest_trading_date' called")
46
+ try:
47
+ today = datetime.now().strftime("%Y-%m-%d")
48
+ # 获取当前日期前后一周的交易日历
49
+ start_date = (datetime.now().replace(day=1)).strftime("%Y-%m-%d")
50
+ end_date = (datetime.now().replace(day=28)).strftime("%Y-%m-%d")
51
+
52
+ df = active_data_source.get_trade_dates(
53
+ start_date=start_date, end_date=end_date)
54
+
55
+ # 筛选出最近的交易日
56
+ valid_trading_days = df[df['is_trading_day']
57
+ == '1']['calendar_date'].tolist()
58
+
59
+ # 找出小于等于今天的最大日期
60
+ latest_trading_date = None
61
+ for date in valid_trading_days:
62
+ if date <= today and (latest_trading_date is None or date > latest_trading_date):
63
+ latest_trading_date = date
64
+
65
+ if latest_trading_date:
66
+ logger.info(
67
+ f"Latest trading date found: {latest_trading_date}")
68
+ return latest_trading_date
69
+ else:
70
+ logger.warning(
71
+ "No trading dates found before today, returning today's date")
72
+ return today
73
+
74
+ except Exception as e:
75
+ logger.exception(f"Error determining latest trading date: {e}")
76
+ return datetime.now().strftime("%Y-%m-%d")
77
+
78
+ @app.tool()
79
+ def get_market_analysis_timeframe(period: str = "recent") -> str:
80
+ """
81
+ 获取适合市场分析的时间范围,基于当前真实日期而不是训练数据。
82
+ 这个工具应该在进行市场分析或大盘分析时首先调用,以确保使用最新的实际数据。
83
+
84
+ Args:
85
+ period: 时间范围类型,可选值:
86
+ "recent": 最近1-2个月(默认)
87
+ "quarter": 最近一个季度
88
+ "half_year": 最近半年
89
+ "year": 最近一年
90
+
91
+ Returns:
92
+ 包含分析时间范围的详细描述字符串,格式为"YYYY年M月-YYYY年M月"。
93
+ """
94
+ logger.info(
95
+ f"Tool 'get_market_analysis_timeframe' called with period={period}")
96
+
97
+ now = datetime.now()
98
+ end_date = now
99
+
100
+ # 根据请求的时间段确定开始日期
101
+ if period == "recent":
102
+ # 最近1-2个月
103
+ if now.day < 15:
104
+ # 如果当前是月初,看前两个月
105
+ if now.month == 1:
106
+ start_date = datetime(now.year - 1, 11, 1) # 前年11月
107
+ middle_date = datetime(now.year - 1, 12, 1) # 前年12月
108
+ elif now.month == 2:
109
+ start_date = datetime(now.year, 1, 1) # 今年1月
110
+ middle_date = start_date
111
+ else:
112
+ start_date = datetime(now.year, now.month - 2, 1) # 两个月前
113
+ middle_date = datetime(now.year, now.month - 1, 1) # 上个月
114
+ else:
115
+ # 如果当前是月中或月末,看前一个月到现在
116
+ if now.month == 1:
117
+ start_date = datetime(now.year - 1, 12, 1) # 前年12月
118
+ middle_date = start_date
119
+ else:
120
+ start_date = datetime(now.year, now.month - 1, 1) # 上个月
121
+ middle_date = start_date
122
+
123
+ elif period == "quarter":
124
+ # 最近一个季度 (约3个月)
125
+ if now.month <= 3:
126
+ start_date = datetime(now.year - 1, now.month + 9, 1)
127
+ else:
128
+ start_date = datetime(now.year, now.month - 3, 1)
129
+ middle_date = start_date
130
+
131
+ elif period == "half_year":
132
+ # 最近半年
133
+ if now.month <= 6:
134
+ start_date = datetime(now.year - 1, now.month + 6, 1)
135
+ else:
136
+ start_date = datetime(now.year, now.month - 6, 1)
137
+ middle_date = datetime(start_date.year, start_date.month + 3, 1) if start_date.month <= 9 else \
138
+ datetime(start_date.year + 1, start_date.month - 9, 1)
139
+
140
+ elif period == "year":
141
+ # 最近一年
142
+ start_date = datetime(now.year - 1, now.month, 1)
143
+ middle_date = datetime(start_date.year, start_date.month + 6, 1) if start_date.month <= 6 else \
144
+ datetime(start_date.year + 1, start_date.month - 6, 1)
145
+ else:
146
+ # 默认为最近1个月
147
+ if now.month == 1:
148
+ start_date = datetime(now.year - 1, 12, 1)
149
+ else:
150
+ start_date = datetime(now.year, now.month - 1, 1)
151
+ middle_date = start_date
152
+
153
+ # 格式化为用户友好的显示
154
+ def get_month_end_day(year, month):
155
+ return calendar.monthrange(year, month)[1]
156
+
157
+ # 确保结束日期不超过当前日期
158
+ end_day = min(get_month_end_day(
159
+ end_date.year, end_date.month), end_date.day)
160
+ end_display_date = f"{end_date.year}年{end_date.month}月"
161
+ end_iso_date = f"{end_date.year}-{end_date.month:02d}-{end_day:02d}"
162
+
163
+ # 开始日期显示
164
+ start_display_date = f"{start_date.year}年{start_date.month}月"
165
+ start_iso_date = f"{start_date.year}-{start_date.month:02d}-01"
166
+
167
+ # 如果跨年或时间段较长,添加年份显示
168
+ if start_date.year != end_date.year:
169
+ date_range = f"{start_date.year}年{start_date.month}月-{end_date.year}年{end_date.month}月"
170
+ elif middle_date.month != start_date.month and middle_date.month != end_date.month:
171
+ # 如果是季度或半年,显示中间月份
172
+ date_range = f"{start_date.year}年{start_date.month}月-{middle_date.month}月-{end_date.month}月"
173
+ elif start_date.month != end_date.month:
174
+ date_range = f"{start_date.year}年{start_date.month}月-{end_date.month}月"
175
+ else:
176
+ date_range = f"{start_date.year}年{start_date.month}月"
177
+
178
+ result = f"{date_range} (ISO日期范围: {start_iso_date} 至 {end_iso_date})"
179
+ logger.info(f"Generated market analysis timeframe: {result}")
180
+ return result
@@ -0,0 +1,201 @@
1
+ """
2
+ Financial report related tools for MCP server.
3
+ """
4
+ import logging
5
+ from typing import List, Optional
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+ from src.data_source_interface import FinancialDataSource
9
+ from src.tools.base import call_financial_data_tool
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def register_financial_report_tools(app: FastMCP, active_data_source: FinancialDataSource):
15
+ """
16
+ Register financial report related tools with the MCP app.
17
+
18
+ Args:
19
+ app: The FastMCP app instance
20
+ active_data_source: The active financial data source
21
+ """
22
+
23
+ @app.tool()
24
+ def get_profit_data(code: str, year: str, quarter: int) -> str:
25
+ """
26
+ Fetches quarterly profitability data (e.g., ROE, net profit margin) for a stock.
27
+
28
+ Args:
29
+ code: The stock code (e.g., 'sh.600000').
30
+ year: The 4-digit year (e.g., '2023').
31
+ quarter: The quarter (1, 2, 3, or 4).
32
+
33
+ Returns:
34
+ Markdown table with profitability data or an error message.
35
+ """
36
+ return call_financial_data_tool(
37
+ "get_profit_data",
38
+ active_data_source.get_profit_data,
39
+ "Profitability",
40
+ code, year, quarter
41
+ )
42
+
43
+ @app.tool()
44
+ def get_operation_data(code: str, year: str, quarter: int) -> str:
45
+ """
46
+ Fetches quarterly operation capability data (e.g., turnover ratios) for a stock.
47
+
48
+ Args:
49
+ code: The stock code (e.g., 'sh.600000').
50
+ year: The 4-digit year (e.g., '2023').
51
+ quarter: The quarter (1, 2, 3, or 4).
52
+
53
+ Returns:
54
+ Markdown table with operation capability data or an error message.
55
+ """
56
+ return call_financial_data_tool(
57
+ "get_operation_data",
58
+ active_data_source.get_operation_data,
59
+ "Operation Capability",
60
+ code, year, quarter
61
+ )
62
+
63
+ @app.tool()
64
+ def get_growth_data(code: str, year: str, quarter: int) -> str:
65
+ """
66
+ Fetches quarterly growth capability data (e.g., YOY growth rates) for a stock.
67
+
68
+ Args:
69
+ code: The stock code (e.g., 'sh.600000').
70
+ year: The 4-digit year (e.g., '2023').
71
+ quarter: The quarter (1, 2, 3, or 4).
72
+
73
+ Returns:
74
+ Markdown table with growth capability data or an error message.
75
+ """
76
+ return call_financial_data_tool(
77
+ "get_growth_data",
78
+ active_data_source.get_growth_data,
79
+ "Growth Capability",
80
+ code, year, quarter
81
+ )
82
+
83
+ @app.tool()
84
+ def get_balance_data(code: str, year: str, quarter: int) -> str:
85
+ """
86
+ Fetches quarterly balance sheet / solvency data (e.g., current ratio, debt ratio) for a stock.
87
+
88
+ Args:
89
+ code: The stock code (e.g., 'sh.600000').
90
+ year: The 4-digit year (e.g., '2023').
91
+ quarter: The quarter (1, 2, 3, or 4).
92
+
93
+ Returns:
94
+ Markdown table with balance sheet data or an error message.
95
+ """
96
+ return call_financial_data_tool(
97
+ "get_balance_data",
98
+ active_data_source.get_balance_data,
99
+ "Balance Sheet",
100
+ code, year, quarter
101
+ )
102
+
103
+ @app.tool()
104
+ def get_cash_flow_data(code: str, year: str, quarter: int) -> str:
105
+ """
106
+ Fetches quarterly cash flow data (e.g., CFO/Operating Revenue ratio) for a stock.
107
+
108
+ Args:
109
+ code: The stock code (e.g., 'sh.600000').
110
+ year: The 4-digit year (e.g., '2023').
111
+ quarter: The quarter (1, 2, 3, or 4).
112
+
113
+ Returns:
114
+ Markdown table with cash flow data or an error message.
115
+ """
116
+ return call_financial_data_tool(
117
+ "get_cash_flow_data",
118
+ active_data_source.get_cash_flow_data,
119
+ "Cash Flow",
120
+ code, year, quarter
121
+ )
122
+
123
+ @app.tool()
124
+ def get_dupont_data(code: str, year: str, quarter: int) -> str:
125
+ """
126
+ Fetches quarterly DuPont analysis data (ROE decomposition) for a stock.
127
+
128
+ Args:
129
+ code: The stock code (e.g., 'sh.600000').
130
+ year: The 4-digit year (e.g., '2023').
131
+ quarter: The quarter (1, 2, 3, or 4).
132
+
133
+ Returns:
134
+ Markdown table with DuPont analysis data or an error message.
135
+ """
136
+ return call_financial_data_tool(
137
+ "get_dupont_data",
138
+ active_data_source.get_dupont_data,
139
+ "DuPont Analysis",
140
+ code, year, quarter
141
+ )
142
+
143
+ @app.tool()
144
+ def get_performance_express_report(code: str, start_date: str, end_date: str) -> str:
145
+ """
146
+ Fetches performance express reports (业绩快报) for a stock within a date range.
147
+ Note: Companies are not required to publish these except in specific cases.
148
+
149
+ Args:
150
+ code: The stock code (e.g., 'sh.600000').
151
+ start_date: Start date (for report publication/update) in 'YYYY-MM-DD' format.
152
+ end_date: End date (for report publication/update) in 'YYYY-MM-DD' format.
153
+
154
+ Returns:
155
+ Markdown table with performance express report data or an error message.
156
+ """
157
+ logger.info(
158
+ f"Tool 'get_performance_express_report' called for {code} ({start_date} to {end_date})")
159
+ try:
160
+ # Add date validation if desired
161
+ df = active_data_source.get_performance_express_report(
162
+ code=code, start_date=start_date, end_date=end_date)
163
+ logger.info(
164
+ f"Successfully retrieved performance express reports for {code}.")
165
+ from src.formatting.markdown_formatter import format_df_to_markdown
166
+ return format_df_to_markdown(df)
167
+
168
+ except Exception as e:
169
+ logger.exception(
170
+ f"Exception processing get_performance_express_report for {code}: {e}")
171
+ return f"Error: An unexpected error occurred: {e}"
172
+
173
+ @app.tool()
174
+ def get_forecast_report(code: str, start_date: str, end_date: str) -> str:
175
+ """
176
+ Fetches performance forecast reports (业绩预告) for a stock within a date range.
177
+ Note: Companies are not required to publish these except in specific cases.
178
+
179
+ Args:
180
+ code: The stock code (e.g., 'sh.600000').
181
+ start_date: Start date (for report publication/update) in 'YYYY-MM-DD' format.
182
+ end_date: End date (for report publication/update) in 'YYYY-MM-DD' format.
183
+
184
+ Returns:
185
+ Markdown table with performance forecast report data or an error message.
186
+ """
187
+ logger.info(
188
+ f"Tool 'get_forecast_report' called for {code} ({start_date} to {end_date})")
189
+ try:
190
+ # Add date validation if desired
191
+ df = active_data_source.get_forecast_report(
192
+ code=code, start_date=start_date, end_date=end_date)
193
+ logger.info(
194
+ f"Successfully retrieved performance forecast reports for {code}.")
195
+ from src.formatting.markdown_formatter import format_df_to_markdown
196
+ return format_df_to_markdown(df)
197
+
198
+ except Exception as e:
199
+ logger.exception(
200
+ f"Exception processing get_forecast_report for {code}: {e}")
201
+ return f"Error: An unexpected error occurred: {e}"
tools/indices.py ADDED
@@ -0,0 +1,103 @@
1
+ """
2
+ Index related tools for MCP server.
3
+ Contains tools for fetching index constituent stocks.
4
+ """
5
+ import logging
6
+ from typing import Optional
7
+
8
+ from mcp.server.fastmcp import FastMCP
9
+ from src.data_source_interface import FinancialDataSource
10
+ from src.tools.base import call_index_constituent_tool
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def register_index_tools(app: FastMCP, active_data_source: FinancialDataSource):
16
+ """
17
+ Register index related tools with the MCP app.
18
+
19
+ Args:
20
+ app: The FastMCP app instance
21
+ active_data_source: The active financial data source
22
+ """
23
+
24
+ @app.tool()
25
+ def get_stock_industry(code: Optional[str] = None, date: Optional[str] = None) -> str:
26
+ """
27
+ Fetches industry classification for a specific stock or all stocks on a given date.
28
+
29
+ Args:
30
+ code: Optional. The stock code (e.g., 'sh.600000'). If None, fetches for all stocks.
31
+ date: Optional. The date in 'YYYY-MM-DD' format. If None, uses the latest available date.
32
+
33
+ Returns:
34
+ Markdown table with industry classification data or an error message.
35
+ """
36
+ log_msg = f"Tool 'get_stock_industry' called for code={code or 'all'}, date={date or 'latest'}"
37
+ logger.info(log_msg)
38
+ try:
39
+ # Add date validation if desired
40
+ df = active_data_source.get_stock_industry(code=code, date=date)
41
+ logger.info(
42
+ f"Successfully retrieved industry data for {code or 'all'}, {date or 'latest'}.")
43
+ from src.formatting.markdown_formatter import format_df_to_markdown
44
+ return format_df_to_markdown(df)
45
+
46
+ except Exception as e:
47
+ logger.exception(
48
+ f"Exception processing get_stock_industry: {e}")
49
+ return f"Error: An unexpected error occurred: {e}"
50
+
51
+ @app.tool()
52
+ def get_sz50_stocks(date: Optional[str] = None) -> str:
53
+ """
54
+ Fetches the constituent stocks of the SZSE 50 Index for a given date.
55
+
56
+ Args:
57
+ date: Optional. The date in 'YYYY-MM-DD' format. If None, uses the latest available date.
58
+
59
+ Returns:
60
+ Markdown table with SZSE 50 constituent stocks or an error message.
61
+ """
62
+ return call_index_constituent_tool(
63
+ "get_sz50_stocks",
64
+ active_data_source.get_sz50_stocks,
65
+ "SZSE 50",
66
+ date
67
+ )
68
+
69
+ @app.tool()
70
+ def get_hs300_stocks(date: Optional[str] = None) -> str:
71
+ """
72
+ Fetches the constituent stocks of the CSI 300 Index for a given date.
73
+
74
+ Args:
75
+ date: Optional. The date in 'YYYY-MM-DD' format. If None, uses the latest available date.
76
+
77
+ Returns:
78
+ Markdown table with CSI 300 constituent stocks or an error message.
79
+ """
80
+ return call_index_constituent_tool(
81
+ "get_hs300_stocks",
82
+ active_data_source.get_hs300_stocks,
83
+ "CSI 300",
84
+ date
85
+ )
86
+
87
+ @app.tool()
88
+ def get_zz500_stocks(date: Optional[str] = None) -> str:
89
+ """
90
+ Fetches the constituent stocks of the CSI 500 Index for a given date.
91
+
92
+ Args:
93
+ date: Optional. The date in 'YYYY-MM-DD' format. If None, uses the latest available date.
94
+
95
+ Returns:
96
+ Markdown table with CSI 500 constituent stocks or an error message.
97
+ """
98
+ return call_index_constituent_tool(
99
+ "get_zz500_stocks",
100
+ active_data_source.get_zz500_stocks,
101
+ "CSI 500",
102
+ date
103
+ )
tools/macroeconomic.py ADDED
@@ -0,0 +1,146 @@
1
+ """
2
+ Macroeconomic data tools for MCP server.
3
+ Contains tools for fetching interest rates, money supply data, and more.
4
+ """
5
+ import logging
6
+ from typing import Optional
7
+
8
+ from mcp.server.fastmcp import FastMCP
9
+ from src.data_source_interface import FinancialDataSource
10
+ from src.tools.base import call_macro_data_tool
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def register_macroeconomic_tools(app: FastMCP, active_data_source: FinancialDataSource):
16
+ """
17
+ Register macroeconomic data tools with the MCP app.
18
+
19
+ Args:
20
+ app: The FastMCP app instance
21
+ active_data_source: The active financial data source
22
+ """
23
+
24
+ @app.tool()
25
+ def get_deposit_rate_data(start_date: Optional[str] = None, end_date: Optional[str] = None) -> str:
26
+ """
27
+ Fetches benchmark deposit rates (活期, 定期) within a date range.
28
+
29
+ Args:
30
+ start_date: Optional. Start date in 'YYYY-MM-DD' format.
31
+ end_date: Optional. End date in 'YYYY-MM-DD' format.
32
+
33
+ Returns:
34
+ Markdown table with deposit rate data or an error message.
35
+ """
36
+ return call_macro_data_tool(
37
+ "get_deposit_rate_data",
38
+ active_data_source.get_deposit_rate_data,
39
+ "Deposit Rate",
40
+ start_date, end_date
41
+ )
42
+
43
+ @app.tool()
44
+ def get_loan_rate_data(start_date: Optional[str] = None, end_date: Optional[str] = None) -> str:
45
+ """
46
+ Fetches benchmark loan rates (贷款利率) within a date range.
47
+
48
+ Args:
49
+ start_date: Optional. Start date in 'YYYY-MM-DD' format.
50
+ end_date: Optional. End date in 'YYYY-MM-DD' format.
51
+
52
+ Returns:
53
+ Markdown table with loan rate data or an error message.
54
+ """
55
+ return call_macro_data_tool(
56
+ "get_loan_rate_data",
57
+ active_data_source.get_loan_rate_data,
58
+ "Loan Rate",
59
+ start_date, end_date
60
+ )
61
+
62
+ @app.tool()
63
+ def get_required_reserve_ratio_data(start_date: Optional[str] = None, end_date: Optional[str] = None, year_type: str = '0') -> str:
64
+ """
65
+ Fetches required reserve ratio data (存款准备金率) within a date range.
66
+
67
+ Args:
68
+ start_date: Optional. Start date in 'YYYY-MM-DD' format.
69
+ end_date: Optional. End date in 'YYYY-MM-DD' format.
70
+ year_type: Optional. Year type for date filtering. '0' for announcement date (公告日期, default),
71
+ '1' for effective date (生效日期).
72
+
73
+ Returns:
74
+ Markdown table with required reserve ratio data or an error message.
75
+ """
76
+ # Basic validation for year_type
77
+ if year_type not in ['0', '1']:
78
+ logger.warning(f"Invalid year_type requested: {year_type}")
79
+ return "Error: Invalid year_type '{year_type}'. Valid options are '0' (announcement date) or '1' (effective date)."
80
+
81
+ return call_macro_data_tool(
82
+ "get_required_reserve_ratio_data",
83
+ active_data_source.get_required_reserve_ratio_data,
84
+ "Required Reserve Ratio",
85
+ start_date, end_date,
86
+ yearType=year_type # Pass the extra arg correctly named for Baostock
87
+ )
88
+
89
+ @app.tool()
90
+ def get_money_supply_data_month(start_date: Optional[str] = None, end_date: Optional[str] = None) -> str:
91
+ """
92
+ Fetches monthly money supply data (M0, M1, M2) within a date range.
93
+
94
+ Args:
95
+ start_date: Optional. Start date in 'YYYY-MM' format.
96
+ end_date: Optional. End date in 'YYYY-MM' format.
97
+
98
+ Returns:
99
+ Markdown table with monthly money supply data or an error message.
100
+ """
101
+ # Add specific validation for YYYY-MM format if desired
102
+ return call_macro_data_tool(
103
+ "get_money_supply_data_month",
104
+ active_data_source.get_money_supply_data_month,
105
+ "Monthly Money Supply",
106
+ start_date, end_date
107
+ )
108
+
109
+ @app.tool()
110
+ def get_money_supply_data_year(start_date: Optional[str] = None, end_date: Optional[str] = None) -> str:
111
+ """
112
+ Fetches yearly money supply data (M0, M1, M2 - year end balance) within a date range.
113
+
114
+ Args:
115
+ start_date: Optional. Start year in 'YYYY' format.
116
+ end_date: Optional. End year in 'YYYY' format.
117
+
118
+ Returns:
119
+ Markdown table with yearly money supply data or an error message.
120
+ """
121
+ # Add specific validation for YYYY format if desired
122
+ return call_macro_data_tool(
123
+ "get_money_supply_data_year",
124
+ active_data_source.get_money_supply_data_year,
125
+ "Yearly Money Supply",
126
+ start_date, end_date
127
+ )
128
+
129
+ @app.tool()
130
+ def get_shibor_data(start_date: Optional[str] = None, end_date: Optional[str] = None) -> str:
131
+ """
132
+ Fetches SHIBOR (Shanghai Interbank Offered Rate) data within a date range.
133
+
134
+ Args:
135
+ start_date: Optional. Start date in 'YYYY-MM-DD' format.
136
+ end_date: Optional. End date in 'YYYY-MM-DD' format.
137
+
138
+ Returns:
139
+ Markdown table with SHIBOR data or an error message.
140
+ """
141
+ return call_macro_data_tool(
142
+ "get_shibor_data",
143
+ active_data_source.get_shibor_data,
144
+ "SHIBOR",
145
+ start_date, end_date
146
+ )