#!/usr/bin/env python # -*- coding:utf-8 -*- """ Date: 2024/6/27 16:00 Desc: 收盘收益率曲线历史数据 https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1 """ from functools import lru_cache import pandas as pd import requests from akshare.utils.tqdm import get_tqdm def __bond_register_service() -> requests.Session: """ 将服务注册到网站中,则该 IP 在 24 小时内可以直接访问 https://www.chinamoney.com.cn :return: 访问过的 Session :rtype: requests.Session """ session = requests.Session() headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/108.0.0.0 Safari/537.36", } session.get( url="https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1", headers=headers, ) cookies_dict = session.cookies.get_dict() cookies_str = "; ".join(f"{k}={v}" for k, v in cookies_dict.items()) # 此处需要通过未访问的游览器,首次打开 # https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1 # 页面进行人工获取 data = {"key": "TThwSjc2NWkzV0VSOVRzOA=="} headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en", "Cache-Control": "no-cache", "Connection": "keep-alive", "Content-Length": "22", "Cookie": cookies_str, "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Host": "www.chinamoney.com.cn", "Origin": "https://www.chinamoney.com.cn", "Pragma": "no-cache", "Referer": "https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/108.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest", } session.post( url="https://www.chinamoney.com.cn/dqs/rest/cm-u-rbt/apply", data=data, headers=headers, ) # 20231127 新增部分 https://github.com/akfamily/akshare/issues/4299 cookies_dict = session.cookies.get_dict() cookies_str = "; ".join(f"{k}={v}" for k, v in cookies_dict.items()) headers = { "Accept": "application/json, text/javascript, /; q=0.01", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en", "Connection": "keep-alive", "Content-Length": "0", "Cookie": cookies_str, "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Host": "www.chinamoney.com.cn", "Origin": "https://www.chinamoney.com.cn", "Referer": "https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/108.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest", } session.post( url="https://www.chinamoney.com.cn/lss/rest/cm-s-account/getSessionUser", headers=headers, ) return session @lru_cache() def bond_china_close_return_map() -> pd.DataFrame: """ 收盘收益率曲线历史数据 https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1 :return: 收盘收益率曲线历史数据 :rtype: pandas.DataFrame """ headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Cache-Control": "no-cache", "Connection": "keep-alive", "Content-Length": "0", "Host": "www.chinamoney.com.cn", "Origin": "https://www.chinamoney.com.cn", "Pragma": "no-cache", "Referer": "https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/108.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest", } url = "https://www.chinamoney.com.cn/ags/ms/cm-u-bk-currency/ClsYldCurvCurvGO" try: r = requests.get(url, headers=headers) data_json = r.json() except: # noqa: E722 session = __bond_register_service() r = session.get(url, headers=headers) data_json = r.json() temp_df = pd.DataFrame(data_json["records"]) return temp_df def bond_china_close_return( symbol: str = "国债", period: str = "1", start_date: str = "20231101", end_date: str = "20231101", ) -> pd.DataFrame: """ 收盘收益率曲线历史数据 https://www.chinamoney.com.cn/chinese/bkcurvclosedyhis/?bondType=CYCC000&reference=1 :param symbol: 需要获取的指标 :type period: choice of {'0.1', '0.5', '1'} :param period: 期限间隔 :type symbol: str :param start_date: 开始日期, 结束日期和开始日期不要超过 1 个月 :type start_date: str :param end_date: 结束日期, 结束日期和开始日期不要超过 1 个月 :type end_date: str :return: 收盘收益率曲线历史数据 :rtype: pandas.DataFrame """ name_code_df = bond_china_close_return_map() symbol_code = name_code_df[name_code_df["cnLabel"] == symbol]["value"].values[0] url = "https://www.chinamoney.com.cn/ags/ms/cm-u-bk-currency/ClsYldCurvHis" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/108.0.0.0 Safari/537.36", } params = { "lang": "CN", "reference": "1,2,3", "bondType": symbol_code, "startDate": "-".join([start_date[:4], start_date[4:6], start_date[6:]]), "endDate": "-".join([end_date[:4], end_date[4:6], end_date[6:]]), "termId": period, "pageNum": "1", "pageSize": "50", } r = requests.get(url, params=params, headers=headers) data_json = r.json() temp_df = pd.DataFrame(data_json["records"]) del temp_df["newDateValue"] temp_df.columns = [ "日期", "期限", "到期收益率", "即期收益率", "远期收益率", ] temp_df = temp_df[ [ "日期", "期限", "到期收益率", "即期收益率", "远期收益率", ] ] temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date temp_df["期限"] = pd.to_numeric(temp_df["期限"], errors="coerce") temp_df["到期收益率"] = pd.to_numeric(temp_df["到期收益率"], errors="coerce") temp_df["即期收益率"] = pd.to_numeric(temp_df["即期收益率"], errors="coerce") temp_df["远期收益率"] = pd.to_numeric(temp_df["远期收益率"], errors="coerce") return temp_df def macro_china_swap_rate( start_date: str = "20231101", end_date: str = "20231204" ) -> pd.DataFrame: """ FR007 利率互换曲线历史数据; 只能获取近一年的数据 https://www.chinamoney.com.cn/chinese/bkcurvfxhis/?cfgItemType=72&curveType=FR007 :param start_date: 开始日期, 开始和结束日期不得超过一个月 :type start_date: str :param end_date: 结束日期, 开始和结束日期不得超过一个月 :type end_date: str :return: FR007利率互换曲线历史数据 :rtype: pandas.DataFrame """ bond_china_close_return_map() start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]]) end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]]) url = "https://www.chinamoney.com.cn/ags/ms/cm-u-bk-shibor/IfccHis" params = { "cfgItemType": "72", "interestRateType": "0", "startDate": start_date, "endDate": end_date, "bidAskType": "", "lang": "CN", "quoteTime": "全部", "pageSize": "5000", "pageNum": "1", } headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Cache-Control": "no-cache", "Connection": "keep-alive", "Content-Length": "0", "Host": "www.chinamoney.com.cn", "Origin": "https://www.chinamoney.com.cn", "Pragma": "no-cache", "Referer": "https://www.chinamoney.com.cn/chinese/bkcurvfxhis/?cfgItemType=72&curveType=FR007", "sec-ch-ua": '"Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/107.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest", } r = requests.post(url, data=params, headers=headers) data_json = r.json() temp_df = pd.DataFrame(data_json["records"]) temp_df.columns = [ "日期", "_", "_", "时刻", "_", "_", "_", "_", "_", "价格类型", "_", "曲线名称", "_", "_", "_", "_", "data", ] price_df = pd.DataFrame([item for item in temp_df["data"]]) price_df.columns = [ "1M", "3M", "6M", "9M", "1Y", "2Y", "3Y", "4Y", "5Y", "7Y", "10Y", ] big_df = pd.concat(objs=[temp_df, price_df], axis=1) big_df = big_df[ [ "日期", "曲线名称", "时刻", "价格类型", "1M", "3M", "6M", "9M", "1Y", "2Y", "3Y", "4Y", "5Y", "7Y", "10Y", ] ] big_df["日期"] = pd.to_datetime(big_df["日期"], errors="coerce").dt.date big_df["1M"] = pd.to_numeric(big_df["1M"], errors="coerce") big_df["3M"] = pd.to_numeric(big_df["3M"], errors="coerce") big_df["6M"] = pd.to_numeric(big_df["6M"], errors="coerce") big_df["9M"] = pd.to_numeric(big_df["9M"], errors="coerce") big_df["1Y"] = pd.to_numeric(big_df["1Y"], errors="coerce") big_df["2Y"] = pd.to_numeric(big_df["2Y"], errors="coerce") big_df["3Y"] = pd.to_numeric(big_df["3Y"], errors="coerce") big_df["4Y"] = pd.to_numeric(big_df["4Y"], errors="coerce") big_df["5Y"] = pd.to_numeric(big_df["5Y"], errors="coerce") big_df["7Y"] = pd.to_numeric(big_df["7Y"], errors="coerce") big_df["10Y"] = pd.to_numeric(big_df["10Y"], errors="coerce") big_df.sort_values(["日期"], inplace=True, ignore_index=True) return big_df def macro_china_bond_public() -> pd.DataFrame: """ 中国-债券信息披露-债券发行 https://www.chinamoney.com.cn/chinese/xzjfx/ :return: 债券发行 :rtype: pandas.DataFrame """ bond_china_close_return_map() url = "https://www.chinamoney.com.cn/ags/ms/cm-u-bond-an/bnBondEmit" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/107.0.0.0 Safari/537.36", } payload = { "enty": "", "bondType": "", "bondNameCode": "", "leadUnderwriter": "", "pageNo": "1", "pageSize": "10", "limit": "1", } r = requests.post(url, data=payload, headers=headers) data_json = r.json() total_page = int(data_json["data"]["pageTotalSize"]) + 1 big_df = pd.DataFrame() tqdm = get_tqdm() for page in tqdm(range(1, total_page), leave=False): payload.update({"pageNo": page}) r = requests.post(url, data=payload, headers=headers) data_json = r.json() temp_df = pd.DataFrame(data_json["records"]) big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True) big_df.columns = [ "债券全称", "债券类型", "-", "发行日期", "-", "计息方式", "-", "债券期限", "-", "债券评级", "-", "价格", "计划发行量", ] big_df = big_df[ [ "债券全称", "债券类型", "发行日期", "计息方式", "价格", "债券期限", "计划发行量", "债券评级", ] ] big_df["价格"] = pd.to_numeric(big_df["价格"], errors="coerce") big_df["计划发行量"] = pd.to_numeric(big_df["计划发行量"], errors="coerce") return big_df if __name__ == "__main__": bond_china_close_return_df = bond_china_close_return( symbol="同业存单(AAA)", period="1", start_date="20240607", end_date="20240607" ) print(bond_china_close_return_df) macro_china_swap_rate_df = macro_china_swap_rate( start_date="20251010", end_date="20251208" ) print(macro_china_swap_rate_df) macro_china_bond_public_df = macro_china_bond_public() print(macro_china_bond_public_df)