Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions adata/bond/market/bond_market.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
@time:2023/4/5
@log:
"""
from adata.bond.market.bond_market_baidu import BondMarketBaiDu
from adata.bond.market.bond_market_qq import BondMarketQQ
from adata.bond.market.bond_market_sina import BondMarketSina
from adata.bond.market.bond_market_east import BondMarketEast


class BondMarket(object):
Expand All @@ -16,6 +19,9 @@ class BondMarket(object):
def __init__(self) -> None:
super().__init__()
self.sina = BondMarketSina()
self.baidu_market = BondMarketBaiDu()
self.qq_market = BondMarketQQ()
self.east_market = BondMarketEast()

def list_market_current(self, code_list=None):
"""
Expand All @@ -25,6 +31,37 @@ def list_market_current(self, code_list=None):
_MARKET_CURRENT_COLUMNS
"""
return self.sina.list_market_current(code_list)

def get_market(self, bond_code: str, start_date='1990-01-01', end_date=None, k_type=1, adjust_type: int = 1):
"""
获取单个债券的历史行情
:param bond_code: 债券代码
:param start_date: 开始时间
:param end_date: 结束日期
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权
:return: k线行情数据
"""
df = self.baidu_market.get_market(bond_code=bond_code, start_date=start_date, end_date=end_date,
k_type=k_type, adjust_type=adjust_type)
if df.empty:
df = self.qq_market.get_market(bond_code=bond_code, start_date=start_date, end_date=end_date,
k_type=k_type, adjust_type=adjust_type)
if df.empty:
df = self.east_market.get_market(bond_code=bond_code, start_date=start_date, end_date=end_date,
k_type=k_type, adjust_type=adjust_type)
return df

def get_market_min(self, bond_code: str):
"""
获取单个债券的今日分时行情
:param bond_code: 债券代码
:return: 当日分钟行情数据
"""
df = self.qq_market.get_market_min(bond_code=bond_code)
if df.empty:
df = self.east_market.get_market_min(bond_code=bond_code)
return df


if __name__ == '__main__':
Expand Down
197 changes: 197 additions & 0 deletions adata/bond/market/bond_market_east.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# -*- coding: utf-8 -*-
"""
@desc: 东方财富债券行情
@author: 1nchaos
@time: 2024/05/05
@log: change log
"""
import pandas as pd
from datetime import datetime
from adata.bond.market.bond_market_template import BondMarketTemplate
from adata.common.utils.date_utils import get_n_days_date, get_cur_time
from adata.common.utils.sunrequests import SunRequests


class BondMarketEast(BondMarketTemplate):
"""
东方财富债券行情
"""

def __init__(self) -> None:
super().__init__()
self._requests = SunRequests()

def get_market(self, bond_code: str, start_date='1990-01-01', end_date=None, k_type=1, adjust_type: int = 1):
"""
获取单个债券的历史行情
:param bond_code: 债券代码
:param start_date: 开始时间
:param end_date: 结束日期
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权
:return: k线行情数据
"""
try:
# 1. 参数处理
if end_date is None:
end_date = get_n_days_date(0)

# 2. 构建请求参数
# 债券代码前缀规则:沪市债券以1开头,深市债券以0开头
se_cid = 1 if bond_code.startswith('1') else 0
# 格式化日期,移除横杠
start_date_str = start_date.replace('-', '')
end_date_str = end_date.replace('-', '')
# 处理k_type参数,与股票模块保持一致
k_type_str = f"10{k_type}" if int(k_type) < 5 else k_type

params = {
'fields1': 'f1,f2,f3,f4,f5,f6',
'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116',
'ut': '7eea3edcaed734bea9cbfc24409ed989',
'klt': k_type_str, # k线类型
'fqt': adjust_type, # 复权类型
'secid': f'{se_cid}.{bond_code}',
'beg': start_date_str,
'end': end_date_str,
'_': int(datetime.now().timestamp() * 1000)
}

# 3. 发送请求
url = 'https://push2his.eastmoney.com/api/qt/stock/kline/get'
# 使用与股票模块相同的请求方法
from adata.common.utils import requests as adata_requests
try:
res = adata_requests.request(method='get', url=url, params=params, timeout=10)
except Exception:
# 请求失败,返回空DataFrame
return pd.DataFrame(columns=self._MARKET_COLUMNS)

# 4. 处理响应
if res is None or res.status_code != 200:
return pd.DataFrame(columns=self._MARKET_COLUMNS)

try:
res_json = res.json()
except Exception:
# 解析JSON失败,返回空DataFrame
return pd.DataFrame(columns=self._MARKET_COLUMNS)

if res_json.get('data') is None:
return pd.DataFrame(columns=self._MARKET_COLUMNS)

data = res_json['data']
if not data.get('klines'):
return pd.DataFrame(columns=self._MARKET_COLUMNS)

# 5. 解析数据
klines = data['klines']
rows = []
for kline in klines:
items = kline.split(',')
if len(items) < 11:
continue
try:
row = {
'trade_time': items[0],
'open': float(items[1]),
'close': float(items[2]),
'high': float(items[3]),
'low': float(items[4]),
'volume': float(items[5]),
'amount': float(items[6]),
'pre_close': float(items[7]),
'change': float(items[8]),
'change_pct': float(items[9]),
'bond_code': bond_code,
'trade_date': items[0].split(' ')[0]
}
rows.append(row)
except (ValueError, IndexError):
# 数据解析失败,跳过当前行
continue

# 6. 构建DataFrame
df = pd.DataFrame(rows, columns=self._MARKET_COLUMNS)
return df
except Exception:
# 异常处理,确保返回结构一致
return pd.DataFrame(columns=self._MARKET_COLUMNS)

def get_market_min(self, bond_code: str):
"""
获取单个债券的今日分时行情
:param bond_code: 债券代码
:return: 当日分钟行情数据
"""
try:
# 1. 构建请求参数
# 债券代码前缀规则:沪市债券以1开头,深市债券以0开头
se_cid = 1 if bond_code.startswith('1') else 0
params = {
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58",
"ut": "fa5fd1943c7b386f172d6893dbfba10b",
"ndays": "1", "iscr": "1",
"iscca": "0", "secid": f"{se_cid}.{bond_code}",
"_": int(datetime.now().timestamp() * 1000),
}

# 2. 发送请求
url = "https://push2.eastmoney.com/api/qt/stock/trends2/get"
# 使用与股票模块相同的请求方法
from adata.common.utils import requests as adata_requests
try:
res = adata_requests.request(method='get', url=url, params=params, timeout=10)
except Exception:
# 请求失败,返回空DataFrame
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)

# 3. 处理响应
if res is None or res.status_code != 200:
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)

try:
res_json = res.json()
except Exception:
# 解析JSON失败,返回空DataFrame
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)

if res_json.get('data') is None:
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)

data = res_json['data']
if not data.get('trends'):
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)

# 4. 解析数据
trends = data['trends']
rows = []
for trend in trends:
items = trend.split(',')
if len(items) < 8:
continue
try:
row = {
'time': items[0],
'price': float(items[1]),
'volume': float(items[5]) * 100, # 换算成股
'amount': float(items[6]),
'bond_code': bond_code
}
rows.append(row)
except (ValueError, IndexError):
# 数据解析失败,跳过当前行
continue

# 5. 构建DataFrame
df = pd.DataFrame(rows, columns=self._MARKET_MIN_COLUMNS)
return df
except Exception:
# 异常处理,确保返回结构一致
return pd.DataFrame(columns=self._MARKET_MIN_COLUMNS)


if __name__ == '__main__':
print(BondMarketEast().get_market(bond_code='110044', start_date='2024-07-01', k_type=1))
print(BondMarketEast().get_market_min(bond_code='110044'))
26 changes: 26 additions & 0 deletions adata/bond/market/bond_market_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class BondMarketTemplate(object):
"""
_MARKET_CURRENT_COLUMNS = ['bond_code', 'bond_name', 'price', 'open', 'high', 'low', 'pre_close', 'change',
'change_pct', 'volume', 'amount', 'time']

_MARKET_COLUMNS = ['trade_time', 'open', 'close', 'high', 'low', 'volume', 'amount', 'pre_close', 'change', 'change_pct', 'bond_code', 'trade_date']

_MARKET_MIN_COLUMNS = ['time', 'price', 'volume', 'amount', 'bond_code']

def list_market_current(self, code_list=None):
"""
Expand All @@ -22,3 +26,25 @@ def list_market_current(self, code_list=None):
_MARKET_CURRENT_COLUMNS
"""
pass

def get_market(self, bond_code: str, start_date='1990-01-01', end_date=None, k_type=1, adjust_type: int = 1):
"""
获取单个债券的历史行情
:param bond_code: 债券代码
:param start_date: 开始时间
:param end_date: 结束日期
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权
:return: k线行情数据
_MARKET_COLUMNS
"""
pass

def get_market_min(self, bond_code: str):
"""
获取单个债券的今日分时行情
:param bond_code: 债券代码
:return: 当日分钟行情数据
_MARKET_MIN_COLUMNS
"""
pass
16 changes: 16 additions & 0 deletions tests/other/test_bond_market.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import adata

bond_code = "110100"

df1 = adata.bond.market.get_market(
bond_code=bond_code,
start_date="2026-03-01",
end_date="2026-03-31",
k_type=1
)
print("history rows:", len(df1))
print(df1.head())

df2 = adata.bond.market.get_market_min(bond_code=bond_code)
print("min rows:", len(df2))
print(df2.head())