stock-tracker

This commit is contained in:
C菌
2026-07-04 00:17:11 +08:00
commit 6087341a48
6463 changed files with 1929869 additions and 0 deletions
@@ -0,0 +1,6 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2019/9/30 13:58
Desc:
"""
@@ -0,0 +1,911 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/4/29 16:00
Desc: 中国证券投资基金业协会-信息公示数据
中国证券投资基金业协会-新版: https://gs.amac.org.cn
"""
import pandas as pd
import requests
from akshare.utils.tqdm import get_tqdm
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/123.0.0.0 Safari/537.36",
"Content-Type": "application/json",
}
def _get_pages(url: str = "", payload: str = "") -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-私募基金管理人公示 页数
暂时不使用本函数, 直接可以获取所有数据
"""
res = requests.post(url=url, json=payload, headers=headers)
res.encoding = "utf-8"
json_df = res.json()
return json_df["totalPages"]
def get_data(url: str = "", payload: str = "") -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-私募基金管理人公示
"""
res = requests.post(url=url, json=payload, headers=headers)
res.encoding = "utf-8"
json_df = res.json()
return json_df
# 中国证券投资基金业协会-信息公示-会员信息
# 中国证券投资基金业协会-信息公示-会员信息-会员机构综合查询
def amac_member_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-会员信息-会员机构综合查询
https://gs.amac.org.cn/amac-infodisc/res/pof/member/index.html
:return: 会员机构综合查询
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/pofMember"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "20",
}
r = requests.post(url, params=params, json={}, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"managerName",
"memberBehalf",
"memberType",
"memberCode",
"memberDate",
"primaryInvestType",
"markStar",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"机构(会员)名称",
"会员代表",
"会员类型",
"会员编号",
"入会时间",
"机构类型",
"是否星标",
]
manager_data_out["入会时间"] = pd.to_datetime(
manager_data_out["入会时间"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-从业人员信息
# 中国证券投资基金业协会-信息公示-从业人员信息-基金从业人员资格注册信息
def amac_person_fund_org_list(symbol: str = "公募基金管理公司") -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-从业人员信息-基金从业人员资格注册信息
https://gs.amac.org.cn/amac-infodisc/res/pof/person/personOrgList.html
:param symbol: choice of {"公募基金管理公司", "公募基金管理公司资管子公司", "商业银行", "证券公司", "证券公司子公司",
"私募基金管理人", "保险公司子公司", "保险公司", "外包服务机构", "期货公司", "期货公司资管子公司", "媒体机构",
"证券投资咨询机构", "评价机构", "外资私募证券基金管理人", "支付结算", "独立服务机构", "地方自律组织", "境外机构",
"律师事务所", "会计师事务所", "交易所", "独立第三方销售机构", "证券公司资管子公司", "证券公司私募基金子公司", "其他"}
:type symbol: str
:return: 基金从业人员资格注册信息
:rtype: pandas.DataFrame
"""
symbol_map = {
"保险公司子公司": "bxgszgs",
"期货公司资管子公司": "qhgszgzgs",
"公募基金管理公司资管子公司": "gmjjglgszgzgs",
"商业银行": "syyh",
"交易所": "jys",
"证券公司私募基金子公司": "zqgssmjjzgs",
"地方自律组织": "dfzlzz",
"证券公司": "zqgs",
"评价机构": "pjjg",
"独立第三方销售机构": "dldsfxsjg",
"证券投资咨询机构": "zqtzzxjg",
"外资私募证券基金管理人": "wzsmzqjjglr",
"境外机构": "jwjg",
"证券公司子公司": "zqgszgs",
"公募基金管理公司": "gmjjglgs",
"媒体机构": "mtjg",
"支付结算": "zfjs",
"证券公司资管子公司": "zqgszgzgs",
"会计师事务所": "kjssws",
"独立服务机构": "dlfwjg",
"律师事务所": "lssws",
"期货公司": "qhgs",
"保险公司": "bxgs",
"其他": "qt",
"外包服务机构": "wbfwjg",
"私募基金管理人": "smjjglr",
}
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/personOrg"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "20",
}
r = requests.post(
url,
params=params,
json={"orgType": symbol_map[symbol], "page": "1"},
headers=headers,
)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(
url,
params=params,
json={"orgType": symbol_map[symbol], "page": "1"},
verify=False,
headers=headers,
)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"orgName",
"orgType",
"workerTotalNum",
"operNum",
"salesmanNum",
"investmentManagerNum",
"fundManagerNum",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.reset_index(inplace=True)
manager_data_out["index"] = manager_data_out.index + 1
manager_data_out.columns = [
"序号",
"机构名称",
"机构类型",
"员工人数",
"基金从业资格",
"基金销售业务资格",
"基金经理",
"投资经理",
]
manager_data_out["员工人数"] = pd.to_numeric(manager_data_out["员工人数"])
manager_data_out["基金从业资格"] = pd.to_numeric(manager_data_out["基金从业资格"])
manager_data_out["基金销售业务资格"] = pd.to_numeric(
manager_data_out["基金销售业务资格"]
)
manager_data_out["基金经理"] = pd.to_numeric(manager_data_out["基金经理"])
manager_data_out["投资经理"] = pd.to_numeric(manager_data_out["投资经理"])
return manager_data_out
# 中国证券投资基金业协会-信息公示-从业人员信息-债券投资交易相关人员公示
def amac_person_bond_org_list() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-从业人员信息-债券投资交易相关人员公示
https://human.amac.org.cn/web/org/personPublicity.html
:return: 债券投资交易相关人员公示
:rtype: pandas.DataFrame
"""
import urllib3
import ssl
ctx = ssl.create_default_context()
ctx.options |= ssl.OP_LEGACY_SERVER_CONNECT
# 使用自定义的 SSL 上下文发起 HTTPS 请求
http = urllib3.PoolManager(ssl_context=ctx)
url = "https://human.amac.org.cn/web/api/publicityAddress?rand=0.6288001872566391&pageNum=1&pageSize=5000"
r = http.request(method="GET", url=url)
data_json = r.json()
temp_df = pd.DataFrame(data_json["list"])
temp_df.reset_index(inplace=True)
temp_df["index"] = range(1, len(temp_df) + 1)
temp_df.columns = [
"序号",
"_",
"_",
"机构名称",
"机构类型",
"公示网址",
]
temp_df = temp_df[
[
"序号",
"机构类型",
"机构名称",
"公示网址",
]
]
return temp_df
# 中国证券投资基金业协会-信息公示-私募基金管理人公示
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人综合查询
def amac_manager_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人综合查询
https://gs.amac.org.cn/amac-infodisc/res/pof/manager/index.html
:return: 私募基金管理人综合查询
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/manager"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"managerName",
"artificialPersonName",
"primaryInvestType",
"registerProvince",
"registerNo",
"establishDate",
"registerDate",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"私募基金管理人名称",
"法定代表人/执行事务合伙人(委派代表)姓名",
"机构类型",
"注册地",
"登记编号",
"成立时间",
"登记时间",
]
manager_data_out["成立时间"] = pd.to_datetime(
manager_data_out["成立时间"], unit="ms"
).dt.date
manager_data_out["登记时间"] = pd.to_datetime(
manager_data_out["登记时间"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人分类公示
def amac_manager_classify_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人分类公示
https://gs.amac.org.cn/amac-infodisc/res/pof/manager/managerList.html
:return: 私募基金管理人分类公示
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/manager"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"managerName",
"artificialPersonName",
"primaryInvestType",
"registerNo",
"registerProvince",
"officeAdrAgg",
"establishDate",
"registerDate",
"fundCount",
"memberType",
"hasSpecialTips",
"hasCreditTips",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"私募基金管理人名称",
"法定代表人/执行事务合伙人(委派代表)姓名",
"机构类型",
"登记编号",
"注册地",
"办公地",
"成立时间",
"登记时间",
"在管基金数量",
"会员类型",
"是否有提示信息",
"是否有诚信信息",
]
manager_data_out["成立时间"] = pd.to_datetime(
manager_data_out["成立时间"], unit="ms"
).dt.date
manager_data_out["登记时间"] = pd.to_datetime(
manager_data_out["登记时间"], unit="ms"
).dt.date
manager_data_out["在管基金数量"] = pd.to_numeric(manager_data_out["在管基金数量"])
manager_data_out["是否有提示信息"] = manager_data_out["是否有提示信息"].map(
{True: "", False: ""}
)
manager_data_out["是否有诚信信息"] = manager_data_out["是否有诚信信息"].map(
{True: "", False: ""}
)
return manager_data_out
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-证券公司私募基金子公司管理人信息公示
def amac_member_sub_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-私募基金管理人公示-证券公司私募基金子公司管理人信息公示
https://gs.amac.org.cn/amac-infodisc/res/pof/member/index.html?primaryInvestType=private
:return: 证券公司私募基金子公司管理人信息公示
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/pofMember"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"managerName",
"memberBehalf",
"memberType",
"memberCode",
"memberDate",
"primaryInvestType",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"机构(会员)名称",
"会员代表",
"会员类型",
"会员编号",
"入会时间",
"公司类型",
]
manager_data_out["入会时间"] = pd.to_datetime(
manager_data_out["入会时间"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品
# 中国证券投资基金业协会-信息公示-基金产品-私募基金管理人基金产品
def amac_fund_info(start_page: str = "1", end_page: str = "2000") -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品-私募基金管理人基金产品
https://gs.amac.org.cn/amac-infodisc/res/pof/fund/index.html
:param start_page: 开始页码, 获取指定页码直接的数据
:type start_page: str
:param end_page: 结束页码, 获取指定页码直接的数据
:type end_page: str
:return: 私募基金管理人基金产品
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/fund"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = int(data_json["totalPages"])
if total_page > int(end_page):
real_end_page = int(end_page)
else:
real_end_page = total_page
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(int(start_page) - 1, real_end_page), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"fundName",
"managerName",
"managerType",
"workingState",
"putOnRecordDate",
"establishDate",
"mandatorName",
] # 定义要取的 value 的 keys
manager_data_out = big_df[keys_list].copy()
manager_data_out.columns = [
"基金名称",
"私募基金管理人名称",
"私募基金管理人类型",
"运行状态",
"备案时间",
"建立时间",
"托管人名称",
]
manager_data_out["建立时间"] = pd.to_datetime(
manager_data_out["建立时间"], unit="ms"
).dt.date
manager_data_out["备案时间"] = pd.to_datetime(
manager_data_out["备案时间"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品-证券公司集合资管产品公示
def amac_securities_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-证券公司集合资管产品公示
https://gs.amac.org.cn/amac-infodisc/res/pof/securities/index.html
:return: 证券公司集合资管产品公示
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/securities"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"cpmc",
"cpbm",
"gljg",
"slrq",
"dqr",
"tzlx",
"sffj",
"tgjg",
"barq",
"yzzt",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"产品名称",
"产品编码",
"管理人名称",
"成立日期",
"到期时间",
"投资类型",
"是否分级",
"托管人名称",
"备案日期",
"运作状态",
]
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品-证券公司直投基金
def amac_aoin_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-证券公司直投基金
https://gs.amac.org.cn/amac-infodisc/res/aoin/product/index.html
:return: 证券公司直投基金
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/aoin/product"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"code",
"name",
"aoinName",
"managerName",
"createDate",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"产品编码",
"产品名称",
"直投子公司",
"管理机构",
"设立日期",
]
manager_data_out["设立日期"] = pd.to_datetime(
manager_data_out["设立日期"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品公示-证券公司私募投资基金
def amac_fund_sub_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-证券公司私募投资基金
https://gs.amac.org.cn/amac-infodisc/res/pof/subfund/index.html
:return: 证券公司私募投资基金
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/subfund"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"productCode",
"productName",
"mgrName",
"trustee",
"foundDate",
"registeredDate",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"产品编码",
"产品名称",
"私募基金管理人名称",
"托管人名称",
"成立日期",
"备案日期",
]
manager_data_out["备案日期"] = pd.to_datetime(
manager_data_out["备案日期"], unit="ms"
).dt.date
manager_data_out["成立日期"] = pd.to_datetime(
manager_data_out["成立日期"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品公示-基金公司及子公司集合资管产品公示
def amac_fund_account_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-基金公司及子公司集合资管产品公示
https://gs.amac.org.cn/amac-infodisc/res/fund/account/index.html
:return: 基金公司及子公司集合资管产品公示
:rtype: pandas.DataFrame
"""
import warnings
warnings.filterwarnings(action="ignore", category=FutureWarning)
url = "https://gs.amac.org.cn/amac-infodisc/api/fund/account"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"registerDate",
"registerCode",
"name",
"manager",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"成立日期",
"产品编码",
"产品名称",
"管理人名称",
]
manager_data_out["成立日期"] = pd.to_datetime(
manager_data_out["成立日期"], unit="ms"
).dt.date
return manager_data_out
# 中国证券投资基金业协会-信息公示-基金产品公示-资产支持专项计划
def amac_fund_abs() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-资产支持专项计划公示信息
https://gs.amac.org.cn/amac-infodisc/res/fund/abs/index.html
:return: 资产支持专项计划公示信息
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/fund/abs"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = range(1, len(big_df) + 1)
big_df.columns = [
"编号",
"_",
"_",
"专项计划全称",
"备案编号",
"管理人",
"托管人",
"备案通过时间",
"成立日期",
"预期到期时间",
]
big_df["备案通过时间"] = pd.to_datetime(big_df["备案通过时间"], unit="ms").dt.date
big_df["成立日期"] = pd.to_datetime(big_df["成立日期"], unit="ms").dt.date
big_df["预期到期时间"] = pd.to_datetime(
big_df["预期到期时间"], unit="ms", errors="coerce"
).dt.date
big_df = big_df[
[
"编号",
"备案编号",
"专项计划全称",
"管理人",
"托管人",
"成立日期",
"预期到期时间",
"备案通过时间",
]
]
return big_df
# 中国证券投资基金业协会-信息公示-基金产品公示-期货公司集合资管产品公示
def amac_futures_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-基金产品公示-期货公司集合资管产品公示
https://gs.amac.org.cn/amac-infodisc/res/pof/futures/index.html
:return: 期货公司集合资管产品公示
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/pof/futures"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"mpiName",
"mpiProductCode",
"aoiName",
"mpiTrustee",
"mpiCreateDate",
"tzlx",
"sfjgh",
"registeredDate",
"dueDate",
"fundStatus",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"产品名称",
"产品编码",
"管理人名称",
"托管人名称",
"成立日期",
"投资类型",
"是否分级",
"备案日期",
"到期日",
"运作状态",
]
return manager_data_out
# 中国证券投资基金业协会-信息公示-诚信信息
# 中国证券投资基金业协会-信息公示-诚信信息-已注销私募基金管理人名单
def amac_manager_cancelled_info() -> pd.DataFrame:
"""
中国证券投资基金业协会-信息公示-诚信信息公示-已注销私募基金管理人名单
https://gs.amac.org.cn/amac-infodisc/res/cancelled/manager/index.html
主动注销: 100
依公告注销: 200
协会注销: 300
:return: 已注销私募基金管理人名单
:rtype: pandas.DataFrame
"""
url = "https://gs.amac.org.cn/amac-infodisc/api/cancelled/manager"
params = {
"rand": "0.7665138514630696",
"page": "1",
"size": "100",
}
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
total_page = data_json["totalPages"]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(0, int(total_page)), leave=False):
params.update({"page": page})
r = requests.post(url, params=params, json={}, verify=False, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["content"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
keys_list = [
"orgName",
"orgCode",
"orgSignDate",
"cancelDate",
"status",
] # 定义要取的 value 的 keys
manager_data_out = pd.DataFrame(big_df)
manager_data_out = manager_data_out[keys_list]
manager_data_out.columns = [
"管理人名称",
"统一社会信用代码",
"登记时间",
"注销时间",
"注销类型",
]
manager_data_out["登记时间"] = pd.to_datetime(
manager_data_out["登记时间"], unit="ms"
).dt.date
manager_data_out["注销时间"] = pd.to_datetime(
manager_data_out["注销时间"], unit="ms"
).dt.date
manager_data_out.sort_values(["注销时间"], ignore_index=True, inplace=True)
return manager_data_out
if __name__ == "__main__":
# 中国证券投资基金业协会-信息公示-会员信息
# 中国证券投资基金业协会-信息公示-会员信息-会员机构综合查询
amac_member_info_df = amac_member_info()
print(amac_member_info_df)
# 中国证券投资基金业协会-信息公示-从业人员信息
# 中国证券投资基金业协会-信息公示-从业人员信息-基金从业人员资格注册信息
amac_person_fund_org_list_df = amac_person_fund_org_list(symbol="公募基金管理公司")
print(amac_person_fund_org_list_df)
# 中国证券投资基金业协会-信息公示-从业人员信息
# 中国证券投资基金业协会-信息公示-从业人员信息-债券投资交易相关人员公示
amac_person_bond_org_list_df = amac_person_bond_org_list()
print(amac_person_bond_org_list_df)
# 中国证券投资基金业协会-信息公示-私募基金管理人公示
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人综合查询
amac_manager_info_df = amac_manager_info()
print(amac_manager_info_df)
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-私募基金管理人分类公示
amac_manager_classify_info_df = amac_manager_classify_info()
print(amac_manager_classify_info_df)
# 中国证券投资基金业协会-信息公示-私募基金管理人公示-证券公司私募基金子公司管理人信息公示
amac_member_sub_info_df = amac_member_sub_info()
print(amac_member_sub_info_df)
# 中国证券投资基金业协会-信息公示-基金产品
# 中国证券投资基金业协会-信息公示-基金产品-私募基金管理人基金产品
amac_fund_info_df = amac_fund_info(start_page="1", end_page="100")
print(amac_fund_info_df)
example_df = amac_fund_info_df[
amac_fund_info_df["私募基金管理人名称"].str.contains("聚宽")
]
print(example_df)
# 中国证券投资基金业协会-信息公示-基金产品-证券公司集合资管产品公示
amac_securities_info_df = amac_securities_info()
print(amac_securities_info_df)
# 中国证券投资基金业协会-信息公示-基金产品-证券公司直投基金
amac_aoin_info_df = amac_aoin_info()
print(amac_aoin_info_df)
# 中国证券投资基金业协会-信息公示-基金产品公示-证券公司私募投资基金
amac_fund_sub_info_df = amac_fund_sub_info()
print(amac_fund_sub_info_df)
# 中国证券投资基金业协会-信息公示-基金产品公示-基金公司及子公司集合资管产品公示
amac_fund_account_info_df = amac_fund_account_info()
print(amac_fund_account_info_df)
# 中国证券投资基金业协会-信息公示-基金产品公示-资产支持专项计划
amac_fund_abs_df = amac_fund_abs()
print(amac_fund_abs_df)
# 中国证券投资基金业协会-信息公示-基金产品公示-期货公司集合资管产品公示
amac_futures_info_df = amac_futures_info()
print(amac_futures_info_df)
# 中国证券投资基金业协会-信息公示-诚信信息
# 中国证券投资基金业协会-信息公示-诚信信息-已注销私募基金管理人名单
amac_manager_cancelled_info_df = amac_manager_cancelled_info()
print(amac_manager_cancelled_info_df)
@@ -0,0 +1,145 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/9/20 17:40
Desc: 东方财富网站-天天基金网-基金档案-基金公告
https://fundf10.eastmoney.com/jjgg_000001.html
"""
import time
import pandas as pd
import requests
def fund_announcement_dividend_em(symbol: str = "000001") -> pd.DataFrame:
"""
东方财富网站-天天基金网-基金档案-基金公告-分红配送
https://fundf10.eastmoney.com/jjgg_000001_2.html
:param symbol: 基金代码; 可以通过调用 ak.fund_name_em() 接口获取
:type symbol: str
:return: 分红配送-公告列表
:rtype: pandas.DataFrame
"""
url = "http://api.fund.eastmoney.com/f10/JJGG"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36",
"Referer": f"http://fundf10.eastmoney.com/jjgg_{symbol}_2.html",
}
params = {
"fundcode": symbol,
"pageIndex": "1",
"pageSize": "1000",
"type": "2",
"_": round(time.time() * 1000),
}
r = requests.get(url, params=params, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["Data"])
temp_df.columns = [
"基金代码",
"公告标题",
"基金名称",
"_",
"_",
"公告日期",
"_",
"报告ID",
]
temp_df = temp_df[["基金代码", "公告标题", "基金名称", "公告日期", "报告ID"]]
temp_df.sort_values(by=["公告日期"], inplace=True, ignore_index=True)
temp_df["公告日期"] = pd.to_datetime(temp_df["公告日期"], errors="coerce").dt.date
return temp_df
def fund_announcement_report_em(symbol: str = "000001") -> pd.DataFrame:
"""
东方财富网站-天天基金网-基金档案-基金公告-定期报告
https://fundf10.eastmoney.com/jjgg_000001_3.html
:param symbol: 基金代码; 可以通过调用 ak.fund_name_em() 接口获取
:type symbol: str
:return: 定期报告-公告列表
:rtype: pandas.DataFrame
"""
url = "http://api.fund.eastmoney.com/f10/JJGG"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36",
"Referer": f"http://fundf10.eastmoney.com/jjgg_{symbol}_3.html",
}
params = {
"fundcode": symbol,
"pageIndex": "1",
"pageSize": "1000",
"type": "3",
"_": round(time.time() * 1000),
}
r = requests.get(url, params=params, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["Data"])
temp_df.columns = [
"基金代码",
"公告标题",
"基金名称",
"_",
"_",
"公告日期",
"_",
"报告ID",
]
temp_df = temp_df[["基金代码", "公告标题", "基金名称", "公告日期", "报告ID"]]
temp_df.sort_values(by=["公告日期"], inplace=True, ignore_index=True)
temp_df["公告日期"] = pd.to_datetime(temp_df["公告日期"], errors="coerce").dt.date
return temp_df
def fund_announcement_personnel_em(symbol: str = "000001") -> pd.DataFrame:
"""
东方财富网站-天天基金网-基金档案-基金公告-人事调整
https://fundf10.eastmoney.com/jjgg_000001_4.html
:param symbol: 基金代码; 可以通过调用 ak.fund_name_em() 接口获取
:type symbol: str
:return: 人事调整-公告列表
:rtype: pandas.DataFrame
"""
url = "http://api.fund.eastmoney.com/f10/JJGG"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
"Referer": f"http://fundf10.eastmoney.com/jjgg_{symbol}_4.html",
}
params = {
"fundcode": symbol,
"pageIndex": "1",
"pageSize": "1000",
"type": "4",
"_": round(time.time() * 1000),
}
r = requests.get(url, params=params, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["Data"])
temp_df.columns = [
"基金代码",
"公告标题",
"基金名称",
"_",
"_",
"公告日期",
"_",
"报告ID",
]
temp_df = temp_df[["基金代码", "公告标题", "基金名称", "公告日期", "报告ID"]]
temp_df.sort_values(by=["公告日期"], inplace=True, ignore_index=True)
temp_df["公告日期"] = pd.to_datetime(temp_df["公告日期"], errors="coerce").dt.date
return temp_df
if __name__ == "__main__":
fund_announcement_dividend_em_df = fund_announcement_dividend_em(symbol="000001")
print(fund_announcement_dividend_em_df)
fund_announcement_report_em_df = fund_announcement_report_em(symbol="000001")
print(fund_announcement_report_em_df)
fund_announcement_personnel_em_df = fund_announcement_personnel_em(symbol="000001")
print(fund_announcement_personnel_em_df)
@@ -0,0 +1,106 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/11/11 16:30
Desc: 东方财富-基金
"""
from io import StringIO
import pandas as pd
import requests
def fund_aum_em() -> pd.DataFrame:
"""
东方财富-基金-基金公司排名列表
https://fund.eastmoney.com/Company/lsgm.html
:return: 基金公司排名列表
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/Company/home/gspmlist"
params = {"fundType": "0"}
r = requests.get(url, params=params)
temp_df = pd.read_html(StringIO(r.text))[0]
del temp_df["相关链接"]
del temp_df["天相评级"]
temp_df.columns = [
"序号",
"基金公司",
"成立时间",
"全部管理规模",
"全部基金数",
"全部经理数",
]
expanded_df = temp_df["全部管理规模"].str.split(" ", expand=True)
temp_df["全部管理规模"] = expanded_df.iloc[:, 0].str.replace(",", "")
temp_df["更新日期"] = expanded_df.iloc[:, 1]
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_datetime(temp_df["成立时间"], errors="coerce").dt.date
return temp_df
def fund_aum_trend_em() -> pd.DataFrame:
"""
东方财富-基金-基金市场管理规模走势图
https://fund.eastmoney.com/Company/default.html
:return: 基金市场管理规模走势图
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/Company/home/GetFundTotalScaleForChart"
payload = {"fundType": "0"}
r = requests.get(url, data=payload)
data_json = r.json()
temp_df = pd.DataFrame()
temp_df["date"] = data_json["x"]
temp_df["value"] = data_json["y"]
temp_df["date"] = pd.to_datetime(temp_df["date"], errors="coerce").dt.date
temp_df["value"] = pd.to_numeric(temp_df["value"], errors="coerce")
return temp_df
def fund_aum_hist_em(year: str = "2023") -> pd.DataFrame:
"""
东方财富-基金-基金公司历年管理规模排行列表
https://fund.eastmoney.com/Company/lsgm.html
:param year: query year
:type year: str
:return: 基金公司历年管理规模排行列表
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/Company/home/HistoryScaleTable"
params = {"year": year}
r = requests.get(url, params=params)
temp_df = pd.read_html(StringIO(r.text))[0]
temp_df.columns = [
"序号",
"基金公司",
"总规模",
"股票型",
"混合型",
"债券型",
"指数型",
"QDII",
"货币型",
]
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")
temp_df["指数型"] = pd.to_numeric(temp_df["指数型"], errors="coerce")
temp_df["QDII"] = pd.to_numeric(temp_df["QDII"], errors="coerce")
temp_df["货币型"] = pd.to_numeric(temp_df["货币型"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_aum_em_df = fund_aum_em()
print(fund_aum_em_df)
fund_aum_trend_em_df = fund_aum_trend_em()
print(fund_aum_trend_em_df)
fund_em_aum_hist_df = fund_aum_hist_em(year="2023")
print(fund_em_aum_hist_df)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,497 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/4/27 00:00
Desc: 东方财富-ETF行情
https://quote.eastmoney.com/sh513500.html
"""
from functools import lru_cache
import pandas as pd
import requests
from akshare.utils.func import fetch_paginated_data
@lru_cache()
def _fund_etf_code_id_map_em() -> dict:
"""
东方财富-ETF代码和市场标识映射
https://quote.eastmoney.com/center/gridlist.html#fund_etf
:return: ETF 代码和市场标识映射
:rtype: dict
"""
url = "https://88.push2.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "100",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f3",
"fs": "b:MK0021,b:MK0022,b:MK0023,b:MK0024",
"fields": "f3,f12,f13",
}
temp_df = fetch_paginated_data(url, params)
temp_dict = dict(zip(temp_df["f12"], temp_df["f13"]))
return temp_dict
def fund_etf_spot_em() -> pd.DataFrame:
"""
东方财富-ETF 实时行情
https://quote.eastmoney.com/center/gridlist.html#fund_etf
:return: ETF 实时行情
:rtype: pandas.DataFrame
"""
url = "https://push2delay.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "100",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f12",
"fs": "b:MK0021,b:MK0022,b:MK0023,b:MK0024,b:MK0827",
"fields": (
"f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,"
"f12,f13,f14,f15,f16,f17,f18,f20,f21,"
"f23,f24,f25,f22,f11,f30,f31,f32,f33,"
"f34,f35,f38,f62,f63,f64,f65,f66,f69,"
"f72,f75,f78,f81,f84,f87,f115,f124,f128,"
"f136,f152,f184,f297,f402,f441"
),
}
temp_df = fetch_paginated_data(url, params)
temp_df.rename(
columns={
"f12": "代码",
"f14": "名称",
"f2": "最新价",
"f4": "涨跌额",
"f3": "涨跌幅",
"f5": "成交量",
"f6": "成交额",
"f7": "振幅",
"f17": "开盘价",
"f15": "最高价",
"f16": "最低价",
"f18": "昨收",
"f8": "换手率",
"f10": "量比",
"f30": "现手",
"f31": "买一",
"f32": "卖一",
"f33": "委比",
"f34": "外盘",
"f35": "内盘",
"f62": "主力净流入-净额",
"f184": "主力净流入-净占比",
"f66": "超大单净流入-净额",
"f69": "超大单净流入-净占比",
"f72": "大单净流入-净额",
"f75": "大单净流入-净占比",
"f78": "中单净流入-净额",
"f81": "中单净流入-净占比",
"f84": "小单净流入-净额",
"f87": "小单净流入-净占比",
"f38": "最新份额",
"f21": "流通市值",
"f20": "总市值",
"f402": "基金折价率",
"f441": "IOPV实时估值",
"f297": "数据日期",
"f124": "更新时间",
},
inplace=True,
)
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"IOPV实时估值",
"基金折价率",
"涨跌额",
"涨跌幅",
"成交量",
"成交额",
"开盘价",
"最高价",
"最低价",
"昨收",
"振幅",
"换手率",
"量比",
"委比",
"外盘",
"内盘",
"主力净流入-净额",
"主力净流入-净占比",
"超大单净流入-净额",
"超大单净流入-净占比",
"大单净流入-净额",
"大单净流入-净占比",
"中单净流入-净额",
"中单净流入-净占比",
"小单净流入-净额",
"小单净流入-净占比",
"现手",
"买一",
"卖一",
"最新份额",
"流通市值",
"总市值",
"数据日期",
"更新时间",
]
]
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")
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")
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")
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")
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")
temp_df["最新份额"] = pd.to_numeric(temp_df["最新份额"], errors="coerce")
temp_df["IOPV实时估值"] = pd.to_numeric(temp_df["IOPV实时估值"], 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"
)
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"
)
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"
)
temp_df["数据日期"] = pd.to_datetime(
temp_df["数据日期"], format="%Y%m%d", errors="coerce"
)
temp_df["更新时间"] = (
pd.to_datetime(temp_df["更新时间"], unit="s", errors="coerce")
.dt.tz_localize("UTC")
.dt.tz_convert("Asia/Shanghai")
)
return temp_df
def get_market_id(symbol: str) -> int:
"""
东方财富-ETF市场标识判断
:param symbol: ETF 代码
:type symbol: str
:return: ETF 代码和市场标识(1:上证 0:深证)
:rtype: int
"""
if symbol.startswith(("0", "1", "3", "2", "5", "6")):
if symbol.startswith(("5", "6")):
return 1
else:
return 0
else:
return 1
def fund_etf_hist_em(
symbol: str = "159707",
period: str = "daily",
start_date: str = "19700101",
end_date: str = "20500101",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-ETF行情
https://quote.eastmoney.com/sz159707.html
:param symbol: ETF 代码
:type symbol: str
:param period: choice of {'daily', 'weekly', 'monthly'}
:type period: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
:type adjust: str
:return: 每日行情
:rtype: pandas.DataFrame
"""
# code_id_dict = _fund_etf_code_id_map_em()
adjust_dict = {"qfq": "1", "hfq": "2", "": "0"}
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period_dict[period],
"fqt": adjust_dict[adjust],
"beg": start_date,
"end": end_date,
}
try:
# market_id = code_id_dict[symbol]
market_id = get_market_id(symbol)
params.update({"secid": f"{market_id}.{symbol}"})
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
except KeyError:
market_id = 1
params.update({"secid": f"{market_id}.{symbol}"})
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
if not data_json["data"]:
market_id = 0
params.update({"secid": f"{market_id}.{symbol}"})
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
if not (data_json["data"] and data_json["data"]["klines"]):
return pd.DataFrame()
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
temp_df.columns = [
"日期",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["日期"], errors="coerce")
temp_df.reset_index(inplace=True, drop=True)
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")
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")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
return temp_df
def fund_etf_hist_min_em(
symbol: str = "159707",
start_date: str = "1979-09-01 09:32:00",
end_date: str = "2222-01-01 09:32:00",
period: str = "5",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-ETF 行情
https://quote.eastmoney.com/sz159707.html
:param symbol: ETF 代码
:type symbol: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param period: choice of {"1", "5", "15", "30", "60"}
:type period: str
:param adjust: choice of {'', 'qfq', 'hfq'}
:type adjust: str
:return: 每日分时行情
:rtype: pandas.DataFrame
"""
# code_id_dict = _fund_etf_code_id_map_em()
# 商品期货类 ETF
# code_id_dict.update(
# {
# "159980": "0",
# "159981": "0",
# "159985": "0",
# "511090": "1",
# "511220": "1",
# "511380": "1",
# }
# )
adjust_map = {
"": "0",
"qfq": "1",
"hfq": "2",
}
if period == "1":
url = "https://push2his.eastmoney.com/api/qt/stock/trends2/get"
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": "7eea3edcaed734bea9cbfc24409ed989",
"ndays": "5",
"iscr": "0",
"secid": f"{get_market_id(symbol)}.{symbol}",
}
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["trends"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"均价",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
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")
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_datetime(temp_df["时间"]).astype(str)
return temp_df
else:
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period,
"fqt": adjust_map[adjust],
"secid": f"{get_market_id(symbol)}.{symbol}",
"beg": "0",
"end": "20500000",
}
r = requests.get(url, timeout=15, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["klines"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
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")
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")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
temp_df = temp_df[
[
"时间",
"开盘",
"收盘",
"最高",
"最低",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
]
]
return temp_df
if __name__ == "__main__":
fund_etf_spot_em_df = fund_etf_spot_em()
print(fund_etf_spot_em_df)
fund_etf_hist_hfq_em_df = fund_etf_hist_em(
symbol="513500",
period="daily",
start_date="20000101",
end_date="20230201",
adjust="hfq",
)
print(fund_etf_hist_hfq_em_df)
fund_etf_hist_qfq_em_df = fund_etf_hist_em(
symbol="511010",
period="daily",
start_date="20000101",
end_date="20230718",
adjust="",
)
print(fund_etf_hist_qfq_em_df)
fund_etf_hist_em_df = fund_etf_hist_em(
symbol="159985",
period="daily",
start_date="20000101",
end_date="20231211",
adjust="",
)
print(fund_etf_hist_em_df)
fund_etf_hist_min_em_df = fund_etf_hist_min_em(
symbol="511380",
period="1",
adjust="",
start_date="2025-04-10 09:30:00",
end_date="2025-04-10 17:40:00",
)
print(fund_etf_hist_min_em_df)
@@ -0,0 +1,205 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/11/10 15:30
Desc: 新浪财经-基金行情
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
"""
import pandas as pd
import py_mini_racer
import requests
from akshare.stock.cons import hk_js_decode
from akshare.utils import demjson
def fund_etf_category_sina(symbol: str = "LOF基金") -> pd.DataFrame:
"""
新浪财经-基金列表
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
:param symbol: choice of {"封闭式基金", "ETF基金", "LOF基金"}
:type symbol: str
:return: 指定 symbol 的基金列表
:rtype: pandas.DataFrame
"""
fund_map = {
"封闭式基金": "close_fund",
"ETF基金": "etf_hq_fund",
"LOF基金": "lof_hq_fund",
}
url = (
"https://vip.stock.finance.sina.com.cn/quotes_service/api/jsonp.php/"
"IO.XSRV2.CallbackList['da_yPT46_Ll7K6WD']/Market_Center.getHQNodeDataSimple"
)
params = {
"page": "1",
"num": "5000",
"sort": "symbol",
"asc": "0",
"node": fund_map[symbol],
"[object HTMLDivElement]": "qvvne",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("([") + 1 : -2])
temp_df = pd.DataFrame(data_json)
if symbol == "封闭式基金":
temp_df.columns = [
"代码",
"名称",
"最新价",
"涨跌额",
"涨跌幅",
"买入",
"卖出",
"昨收",
"今开",
"最高",
"最低",
"成交量",
"成交额",
"_",
"_",
]
else:
temp_df.columns = [
"代码",
"名称",
"最新价",
"涨跌额",
"涨跌幅",
"买入",
"卖出",
"昨收",
"今开",
"最高",
"最低",
"成交量",
"成交额",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌额",
"涨跌幅",
"买入",
"卖出",
"昨收",
"今开",
"最高",
"最低",
"成交量",
"成交额",
]
]
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")
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")
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 fund_etf_hist_sina(symbol: str = "sh510050") -> pd.DataFrame:
"""
新浪财经-基金-ETF 基金-日行情数据
https://finance.sina.com.cn/fund/quotes/159996/bc.shtml
:param symbol: 基金名称, 可以通过 ak.fund_etf_category_sina() 函数获取
:type symbol: str
:return: 日行情数据
:rtype: pandas.DataFrame
"""
url = (
f"https://finance.sina.com.cn/realstock/company/{symbol}/hisdata_klc2/klc_kl.js"
)
r = requests.get(url)
js_code = py_mini_racer.MiniRacer()
js_code.eval(hk_js_decode)
dict_list = js_code.call(
"d", r.text.split("=")[1].split(";")[0].replace('"', "")
) # 执行js解密代码
temp_df = pd.DataFrame(dict_list)
if temp_df.empty: # 处理获取数据为空的问题
return pd.DataFrame()
temp_df["date"] = pd.to_datetime(temp_df["date"], errors="coerce").dt.tz_localize(
None
)
temp_df["open"] = pd.to_numeric(temp_df["open"], errors="coerce")
temp_df["high"] = pd.to_numeric(temp_df["high"], errors="coerce")
temp_df["low"] = pd.to_numeric(temp_df["low"], errors="coerce")
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["volume"] = pd.to_numeric(temp_df["volume"], errors="coerce")
# 转换日期列为日期类型
temp_df["date"] = temp_df["date"].dt.date
temp_df = temp_df.sort_values(by="date", ascending=True)
return temp_df
def fund_etf_dividend_sina(symbol: str = "sh510050") -> pd.DataFrame:
"""
新浪财经-基金-ETF 基金-累计分红
https://finance.sina.com.cn/fund/quotes/510050/bc.shtml
:param symbol: 基金名称, 可以通过 ak.fund_etf_category_sina() 函数获取
:type symbol: str
:return: 累计分红
:rtype: pandas.DataFrame
"""
# 构建复权数据URL
factor_url = f"https://finance.sina.com.cn/realstock/company/{symbol}/hfq.js"
r = requests.get(factor_url)
text = r.text
if text.startswith("var"):
json_str = text.split("=")[1].strip().rsplit("}", maxsplit=1)[0].strip()
data = eval(json_str + "}") # 这里使用eval而不是json.loads因为数据格式特殊
if isinstance(data, dict) and "data" in data:
df = pd.DataFrame(data["data"])
# 重命名列
df.columns = ["date", "f", "s", "u"] if len(df.columns) == 4 else df.columns
# 移除1900-01-01的数据
df = df[df["date"] != "1900-01-01"]
# 转换日期
df["date"] = pd.to_datetime(df["date"])
# 转换数值类型
df[["f", "s", "u"]] = df[["f", "s", "u"]].astype(float)
# 按日期排序
df = df.sort_values(by="date", ascending=True, ignore_index=True)
temp_df = df[["date", "u"]].copy()
temp_df.columns = ["日期", "累计分红"]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
return temp_df
else:
return pd.DataFrame()
else:
return pd.DataFrame()
if __name__ == "__main__":
fund_etf_category_sina_df = fund_etf_category_sina(symbol="封闭式基金")
print(fund_etf_category_sina_df)
fund_etf_category_sina_df = fund_etf_category_sina(symbol="ETF基金")
print(fund_etf_category_sina_df)
fund_etf_category_sina_df = fund_etf_category_sina(symbol="LOF基金")
print(fund_etf_category_sina_df)
fund_etf_hist_sina_df = fund_etf_hist_sina(symbol="sh510050")
print(fund_etf_hist_sina_df)
fund_etf_dividend_sina_df = fund_etf_dividend_sina(symbol="sh510050")
print(fund_etf_dividend_sina_df)
@@ -0,0 +1,71 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/1/20 15:00
Desc: 上海证券交易所-ETF基金份额数据
https://www.sse.com.cn/assortment/fund/etf/list/scale/
"""
import pandas as pd
import requests
def fund_etf_scale_sse(date: str = "20250115") -> pd.DataFrame:
"""
上海证券交易所-产品-基金产品-ETF产品-ETF产品列表-基金规模
https://www.sse.com.cn/assortment/fund/etf/list/scale/
:param date: 统计日期, 默认为空返回最新数据, 格式如 "20250115"
:type date: str
:return: ETF基金份额数据
:rtype: pandas.DataFrame
"""
data_str = "-".join([date[:4], date[4:6], date[6:]])
url = "https://query.sse.com.cn/commonQuery.do"
params = {
"isPagination": "true",
"pageHelp.pageSize": "10000",
"pageHelp.pageNo": "1",
"pageHelp.beginPage": "1",
"pageHelp.cacheSize": "1",
"pageHelp.endPage": "1",
"sqlId": "COMMON_SSE_ZQPZ_ETFZL_XXPL_ETFGM_SEARCH_L",
"STAT_DATE": data_str,
}
headers = {
"Referer": "https://www.sse.com.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/88.0.4324.150 Safari/537.36",
}
r = requests.get(url, params=params, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"])
temp_df.rename(
columns={
"NUM": "序号",
"SEC_CODE": "基金代码",
"SEC_NAME": "基金简称",
"ETF_TYPE": "ETF类型",
"STAT_DATE": "统计日期",
"TOT_VOL": "基金份额",
},
inplace=True,
)
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"ETF类型",
"统计日期",
"基金份额",
]
]
temp_df["序号"] = pd.to_numeric(temp_df["序号"], errors="coerce")
temp_df["统计日期"] = pd.to_datetime(temp_df["统计日期"], errors="coerce").dt.date
temp_df["基金份额"] = pd.to_numeric(temp_df["基金份额"], errors="coerce") * 10000
return temp_df
if __name__ == "__main__":
fund_etf_scale_sse_df = fund_etf_scale_sse(date="20250115")
print(fund_etf_scale_sse_df)
@@ -0,0 +1,69 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/1/20 15:00
Desc: 深圳证券交易所-ETF基金份额数据
https://fund.szse.cn/marketdata/fundslist/index.html
"""
import warnings
import pandas as pd
import requests
def fund_etf_scale_szse() -> pd.DataFrame:
"""
深圳证券交易所-基金产品-基金列表-ETF基金份额
https://fund.szse.cn/marketdata/fundslist/index.html
:return: ETF基金份额数据
:rtype: pandas.DataFrame
"""
url = "https://fund.szse.cn/api/report/ShowReport"
params = {
"SHOWTYPE": "xlsx",
"CATALOGID": "1000_lf",
"TABKEY": "tab1",
"random": "0.07610353191740105",
}
headers = {
"Referer": "https://fund.szse.cn/marketdata/fundslist/index.html",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/88.0.4324.150 Safari/537.36",
}
r = requests.get(url, params=params, headers=headers)
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
temp_df = pd.read_excel(r.content, engine="openpyxl", dtype={"基金代码": str})
temp_df.rename(
columns={
"当前规模(份)": "基金份额",
},
inplace=True,
)
temp_df = temp_df[
[
"基金代码",
"基金简称",
"基金类别",
"投资类别",
"上市日期",
"基金份额",
"基金管理人",
"基金发起人",
"基金托管人",
"净值",
]
]
temp_df["上市日期"] = pd.to_datetime(temp_df["上市日期"], errors="coerce").dt.date
temp_df["基金份额"] = (
temp_df["基金份额"].astype(str).str.replace(",", "", regex=False)
)
temp_df["基金份额"] = pd.to_numeric(temp_df["基金份额"], errors="coerce")
temp_df["净值"] = pd.to_numeric(temp_df["净值"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_etf_scale_szse_df = fund_etf_scale_szse()
print(fund_etf_scale_szse_df)
@@ -0,0 +1,151 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/2/10 16:00
Desc: 同花顺理财-基金数据-每日净值-ETF
https://fund.10jqka.com.cn/datacenter/jz/kfs/etf/
"""
import json
import pandas as pd
import requests
def fund_etf_category_ths(symbol: str = "ETF", date: str = "") -> pd.DataFrame:
"""
同花顺理财-基金数据-每日净值-实时行情
https://fund.10jqka.com.cn/datacenter/jz/
:param symbol: 基金类型; choice of {"股票型", "债券型", "混合型", "ETF", "LOF", "QDII", "保本型", "指数型", ""}; "" 表示全部
:type symbol: str
:param date: 查询日期
:type date: str
:return: 基金实时行情
:rtype: pandas.DataFrame
"""
symbol_map = {
"股票型": "gpx",
"债券型": "zqx",
"混合型": "hhx",
"ETF": "ETF",
"LOF": "LOF",
"QDII": "QDII",
"保本型": "bbx",
"指数型": "zsx",
"": "all",
}
inner_symbol = symbol_map.get(symbol, "ETF")
inner_date = "-".join([date[:4], date[4:6], date[6:]]) if date != "" else 0
url = (
f"https://fund.10jqka.com.cn/data/Net/info/"
f"{inner_symbol}_rate_desc_{inner_date}_0_1_9999_0_0_0_jsonp_g.html"
)
r = requests.get(url, timeout=15)
data_text = r.text[2:-1]
data_json = json.loads(data_text)
temp_df = pd.DataFrame(data_json["data"]["data"]).T
temp_df.reset_index(inplace=True, drop=True)
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df["index"] + 1
temp_df.rename(
columns={
"index": "序号",
"code": "基金代码",
"typename": "基金类型",
"net": "当前-单位净值",
"name": "基金名称",
"totalnet": "当前-累计净值",
"newnet": "最新-单位净值",
"newtotalnet": "最新-累计净值",
"newdate": "最新-交易日",
"net1": "前一日-单位净值",
"totalnet1": "前一日-累计净值",
"ranges": "增长值",
"rate": "增长率",
"shstat": "赎回状态",
"sgstat": "申购状态",
},
inplace=True,
)
temp_df = temp_df[
[
"序号",
"基金代码",
"基金名称",
"当前-单位净值",
"当前-累计净值",
"前一日-单位净值",
"前一日-累计净值",
"增长值",
"增长率",
"赎回状态",
"申购状态",
"最新-交易日",
"最新-单位净值",
"最新-累计净值",
"基金类型",
]
]
query_date = inner_date if inner_date != 0 else temp_df["最新-交易日"][0]
temp_df["查询日期"] = query_date
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"
)
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")
temp_df["最新-交易日"] = pd.to_datetime(
temp_df["最新-交易日"], errors="coerce"
).dt.date
return temp_df
def fund_etf_spot_ths(date: str = "") -> pd.DataFrame:
"""
同花顺理财-基金数据-每日净值-ETF-实时行情
https://fund.10jqka.com.cn/datacenter/jz/kfs/etf/
:param date: 查询日期
:type date: str
:return: ETF 实时行情
:rtype: pandas.DataFrame
"""
return fund_etf_category_ths(date=date, symbol="ETF")
if __name__ == "__main__":
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="股票型")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="债券型")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="混合型")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="ETF")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="LOF")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="QDII")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="保本型")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="指数型")
print(fund_etf_category_ths_df)
fund_etf_category_ths_df = fund_etf_category_ths(date="20240620", symbol="")
print(fund_etf_category_ths_df)
fund_etf_spot_ths_df = fund_etf_spot_ths(date="20240620")
print(fund_etf_spot_ths_df)
@@ -0,0 +1,167 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/12/22 17:00
Desc: 天天基金-基金档案
https://fundf10.eastmoney.com/jjfl_015641.html
"""
import re
from io import StringIO
import pandas as pd
import requests
from bs4 import BeautifulSoup
def fund_fee_em(symbol: str = "015641", indicator: str = "认购费率") -> pd.DataFrame:
"""
天天基金-基金档案-购买信息
https://fundf10.eastmoney.com/jjfl_015641.html
:param symbol: 基金代码
:type symbol: str
:param indicator: choice of {"交易状态", "申购与赎回金额", "交易确认日", "运作费用", "认购费率(前端)", "认购费率(后端)","申购费率(前端)", "赎回费率"}
:type indicator: str
:return: 交易规则
:rtype: pandas.DataFrame
"""
url = f"https://fundf10.eastmoney.com/jjfl_{symbol}.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, features="html.parser")
tables_dict = {}
title_elements = soup.find_all(name="h4", class_="t")
for title_elem in title_elements:
title_text = title_elem.get_text(strip=True)
title_text = re.sub(r"\s+", " ", title_text).strip()
if title_text == "申购与赎回金额":
next_table = title_elem.find_all_next("table")[0]
next_next_table = title_elem.find_all_next("table")[1]
table_html = str(next_table)
next_table_html = str(next_next_table)
df_1 = pd.read_html(StringIO(table_html))[0]
df_2 = pd.read_html(StringIO(next_table_html))[0]
df = pd.concat(objs=[df_1, df_2], ignore_index=True)
tables_dict[title_text] = df
continue
else:
next_table = title_elem.find_next("table")
if next_table:
try:
# 将表格转换为HTML字符串,然后使用pd.read_html读取
table_html = str(next_table)
df = pd.read_html(StringIO(table_html))[0]
tables_dict[title_text] = df
except Exception as e:
print("Error:", e)
continue
if indicator == "交易状态":
temp_df = tables_dict[indicator]
elif indicator == "申购与赎回金额":
temp_df = tables_dict[indicator]
elif indicator == "交易确认日":
temp_df = tables_dict[indicator]
elif indicator == "运作费用":
temp_df = tables_dict[indicator]
elif indicator == "认购费率(后端)":
temp_df = tables_dict[indicator]
elif indicator == "认购费率(前端)":
temp_df = tables_dict[indicator]
temp_df[["原费率", "天天基金优惠费率"]] = temp_df[
"原费率|天天基金优惠费率"
].str.split("|", expand=True)
del temp_df["原费率|天天基金优惠费率"]
temp_df.loc[3, "天天基金优惠费率"] = temp_df.loc[3, "原费率"]
temp_df["原费率"] = temp_df["原费率"].str.strip()
temp_df["天天基金优惠费率"] = temp_df["天天基金优惠费率"].str.strip()
elif indicator == "申购费率(前端)":
temp_df = tables_dict[indicator]
if "原费率|天天基金优惠费率 银行卡购买|活期宝购买" not in temp_df.columns:
# assert temp_df.columns.tolist() == ["适用金额", "适用期限", "费率"]
return temp_df
splited = temp_df["原费率|天天基金优惠费率 银行卡购买|活期宝购买"].str.split(
"|", expand=True
)
if splited.shape[1] == 1:
temp_df.rename(
columns={"原费率|天天基金优惠费率 银行卡购买|活期宝购买": "原费率"},
inplace=True,
)
temp_df["天天基金优惠费率-银行卡购买"] = temp_df["原费率"]
temp_df["天天基金优惠费率-活期宝购买"] = temp_df["原费率"]
else:
temp_df[
["原费率", "天天基金优惠费率-银行卡购买", "天天基金优惠费率-活期宝购买"]
] = splited
temp_df["天天基金优惠费率-银行卡购买"] = temp_df[
"天天基金优惠费率-银行卡购买"
].fillna(temp_df["原费率"])
temp_df["天天基金优惠费率-活期宝购买"] = temp_df[
"天天基金优惠费率-活期宝购买"
].fillna(temp_df["原费率"])
del temp_df["原费率|天天基金优惠费率 银行卡购买|活期宝购买"]
temp_df["原费率"] = temp_df["原费率"].str.strip()
temp_df["天天基金优惠费率-银行卡购买"] = temp_df[
"天天基金优惠费率-银行卡购买"
].str.strip()
temp_df["天天基金优惠费率-活期宝购买"] = temp_df[
"天天基金优惠费率-活期宝购买"
].str.strip()
elif indicator in ("赎回费率", "赎回费率(前端)", "赎回费率(后端)"):
temp_df = tables_dict[indicator]
if "原费率|天天基金优惠费率" in temp_df.columns:
temp_df[["原费率", "天天基金优惠费率"]] = temp_df[
"原费率|天天基金优惠费率"
].str.split("|", expand=True)
del temp_df["原费率|天天基金优惠费率"]
else:
temp_df = pd.DataFrame([])
return temp_df
if __name__ == "__main__":
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="交易状态")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="申购与赎回金额")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="交易确认日")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="运作费用")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="认购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="019005", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="000011", indicator="赎回费率")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="018403", indicator="赎回费率")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="100035", indicator="赎回费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="022364", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="022365", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="006030", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="022568", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="960029", indicator="申购费率(前端)")
print(fund_fee_em_df)
fund_fee_em_df = fund_fee_em(symbol="000011", indicator="认购费率(后端)")
print(fund_fee_em_df)
@@ -0,0 +1,263 @@
# -*- coding:utf-8 -*-
# !/usr/bin/env python
"""
Date: 2026/2/22 13:00
Desc: 天天基金网-基金数据-分红送配
https://fund.eastmoney.com/data/fundfenhong.html
"""
import pandas as pd
import requests
from akshare.utils.tqdm import get_tqdm
def fund_fh_em(
year: str = "2025",
typ: str = "",
rank: str = "BZDM",
sort: str = "asc",
page: int = -1,
) -> pd.DataFrame:
"""
天天基金网-基金数据-分红送配-基金分红
https://fund.eastmoney.com/data/fundfenhong.html#DJR,desc,1,,,
:param year: 查询年份
:type year: str
:param typ: 基金类型;空串表示全部; choice of {"指数型-其他", "指数型-海外股票", "指数型-固收", "指数型-股票", "债券型-中短债",
"债券型-长债", "债券型-理财", "债券型-混合债", "债券型-混合一级", "债券型-混合二级", "货币型-普通货币", "货币型-浮动净值",
"混合型-平衡", "混合型-偏债", "混合型-偏股", "混合型-灵活", "混合型-绝对收益", "股票型", "REITs", "Reits", "QDII-商品",
"QDII-普通股票", "QDII-混合债", "QDII-混合偏股", "QDII-纯债", "QDII-REITs", "FOF"}
:type typ: str
:param rank: 排序字段;choice of {"BZDM", "ABBNAME", "DJR", "FSRQ", "FHFCZ", "FFR"}; "BZDM": 基金代码,
"ABBNAME": 基金简称, "DJR": 权益登记日, "FSRQ": 除息日期, "FHFCZ": 分红(元/份), "FFR": 分红发放日
:type rank: str
:param sort: 排序方向;排序方式; choice of {"asc", "desc"}
:type sort: str
:param page: 查询页数;请求第page页数据; -1 表示全部页面
:type page: int
:return: 基金分红
:rtype: pandas.DataFrame
"""
def get_df_from_response(response):
text = response.text
return pd.DataFrame(eval(text[text.find("[["): text.find(";var jjfh_jjgs")]))
url = "https://fund.eastmoney.com/Data/funddataIndex_Interface.aspx"
params = {
"dt": "8",
"page": "1" if page == -1 else str(page),
"rank": rank,
"sort": sort,
"gs": "",
"ftype": typ,
"year": year,
}
r = requests.get(url, params=params)
data_list = [get_df_from_response(r)]
if page == -1:
data_text = r.text
total_page = eval(data_text[data_text.find("=") + 1: data_text.find(";")])[0]
tqdm = get_tqdm()
for p in tqdm(range(2, total_page + 1), leave=False):
params.update({"page": str(p)})
r = requests.get(url, params=params)
data_list.append(get_df_from_response(r))
big_df = pd.concat(objs=data_list, ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
# 处理空数据时报错的问题
if big_df.empty:
big_df = big_df.reindex(
columns=[
"序号",
"基金代码",
"基金简称",
"权益登记日",
"除息日期",
"分红",
"分红发放日",
"-",
]
)
big_df.columns = [
"序号",
"基金代码",
"基金简称",
"权益登记日",
"除息日期",
"分红",
"分红发放日",
"-",
]
big_df = big_df[
["序号", "基金代码", "基金简称", "权益登记日", "除息日期", "分红", "分红发放日"]
]
big_df["权益登记日"] = pd.to_datetime(big_df["权益登记日"]).dt.date
big_df["除息日期"] = pd.to_datetime(big_df["除息日期"]).dt.date
big_df["分红发放日"] = pd.to_datetime(big_df["分红发放日"]).dt.date
big_df["分红"] = pd.to_numeric(big_df["分红"])
return big_df
def fund_cf_em(
year: str = "2025",
typ: str = "",
rank: str = "FSRQ",
sort: str = "desc",
page: int = -1,
) -> pd.DataFrame:
"""
天天基金网-基金数据-分红送配-基金拆分
https://fund.eastmoney.com/data/fundchaifen.html#FSRQ,desc,1,,,
:param year: 查询年份
:type year: str
:param typ: 基金类型;空串表示全部; choice of {"", "指数型-其他", "指数型-海外股票", "指数型-固收", "指数型-股票",
"债券型-中短债", "债券型-长债", "债券型-可转债", "债券型-混合债", "债券型-混合一级", "债券型-混合二级",
"商品(不含QDII", "货币型", "混合型-平衡", "混合型-偏债", "混合型-偏股", "混合型-灵活", "股票型", "QDII", "FOF"}
:type typ: str
:param rank: 排序字段;choice of {"BZDM", "ABBNAME", "FSRQ", "FHFCZ"}; "BZDM": 基金代码,
"ABBNAME": 基金简称, "FSRQ": 拆分折算日, "FHFCZ": 拆分折算(每份)
:type rank: str
:param sort: 排序方向;choice of {"asc", "desc"}
:type sort: str
:param page: 查询页数;请求第page页数据; -1 表示全部页面
:type page: int
:return: 基金拆分
:rtype: pandas.DataFrame
"""
def get_df_from_response(response):
text = response.text
code = text[text.find("[["): text.find(";var jjcf_jjgs")]
if code:
return pd.DataFrame(eval(code))
return pd.DataFrame()
url = "https://fund.eastmoney.com/Data/funddataIndex_Interface.aspx"
params = {
"dt": "9",
"page": "1" if page == -1 else str(page),
"rank": rank,
"sort": sort,
"gs": "",
"ftype": typ,
"year": year,
}
r = requests.get(url, params=params)
data_list = [get_df_from_response(r)]
if page == -1:
data_text = r.text
total_page = eval(data_text[data_text.find("=") + 1: data_text.find(";")])[0]
tqdm = get_tqdm()
for p in tqdm(range(2, total_page + 1), leave=False):
params.update({"page": str(p)})
r = requests.get(url, params=params)
data_list.append(get_df_from_response(r))
big_df = pd.concat(objs=data_list, ignore_index=True)
big_df.reset_index(inplace=True)
big_df.loc[:, "index"] = big_df["index"] + 1
# 处理空数据时报错的问题
if big_df.empty:
big_df = big_df.reindex(
columns=[
"序号",
"基金代码",
"基金简称",
"拆分折算日",
"拆分类型",
"拆分折算",
"-",
]
)
big_df.columns = [
"序号",
"基金代码",
"基金简称",
"拆分折算日",
"拆分类型",
"拆分折算",
"-",
]
big_df = big_df[
["序号", "基金代码", "基金简称", "拆分折算日", "拆分类型", "拆分折算"]
]
big_df["拆分折算日"] = pd.to_datetime(big_df["拆分折算日"]).dt.date
big_df["拆分折算"] = pd.to_numeric(big_df["拆分折算"], errors="coerce")
return big_df
def fund_fh_rank_em() -> pd.DataFrame:
"""
天天基金网-基金数据-分红送配-基金分红排行
https://fund.eastmoney.com/data/fundleijifenhong.html
:return: 基金分红排行
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/Data/funddataIndex_Interface.aspx"
params = {
"dt": "10",
"page": "1",
"rank": "FHFCZ",
"sort": "desc",
"gs": "",
"ftype": "",
}
r = requests.get(url, params=params)
data_text = r.text
total_page = eval(data_text[data_text.find("=") + 1: data_text.find(";")])[0]
big_df = pd.DataFrame()
tqdm = get_tqdm()
for page in tqdm(range(1, total_page + 1), leave=False):
params.update({"page": str(page)})
r = requests.get(url, params=params)
data_text = r.text
temp_list = eval(
data_text[data_text.find("[["): data_text.find(";var fhph_jjgs")]
)
temp_df = pd.DataFrame(temp_list)
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
# 处理空数据时报错的问题
if big_df.empty:
big_df = big_df.reindex(
columns=[
"序号",
"基金代码",
"基金简称",
"累计分红",
"累计次数",
"成立日期",
"-",
]
)
big_df.columns = [
"序号",
"基金代码",
"基金简称",
"累计分红",
"累计次数",
"成立日期",
"-",
]
big_df = big_df[
["序号", "基金代码", "基金简称", "累计分红", "累计次数", "成立日期"]
]
big_df["成立日期"] = pd.to_datetime(big_df["成立日期"]).dt.date
big_df["累计分红"] = pd.to_numeric(big_df["累计分红"], errors="coerce")
big_df["累计次数"] = pd.to_numeric(big_df["累计次数"], errors="coerce")
return big_df
if __name__ == "__main__":
fund_fh_em_df = fund_fh_em(year="2025")
print(fund_fh_em_df)
fund_cf_em_df = fund_cf_em(year="2025")
print(fund_cf_em_df)
fund_fh_rank_em_df = fund_fh_rank_em()
print(fund_fh_rank_em_df)
@@ -0,0 +1,54 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/05/01
Desc: 同花顺-基金基本信息
https://fund.10jqka.com.cn/161130/interduce.html
"""
import pandas as pd
import requests
from bs4 import BeautifulSoup
from akshare.utils.cons import headers
def fund_info_ths(symbol: str = "161130") -> pd.DataFrame:
"""
同花顺-基金数据-基金基本信息
https://fund.10jqka.com.cn/161130/interduce.html
:param symbol: 基金代码
:type symbol: str
:return: 基金基本信息
:rtype: pandas.DataFrame
"""
url = f"https://fund.10jqka.com.cn/{symbol}/interduce.html"
r = requests.get(url, headers=headers, timeout=15)
soup = BeautifulSoup(r.content, features="lxml", from_encoding="utf-8")
# 查找基金信息对话框
g_dialog = soup.find("ul", class_="g-dialog")
if not g_dialog:
raise ValueError("未找到基金信息,可能网页结构已变化")
# 提取所有基金信息
fund_data = {}
lis = g_dialog.find_all("li")
for li in lis:
key_elem = li.find("span", class_="key")
value_elem = li.find("span", class_="value")
if key_elem and value_elem:
key = key_elem.get_text(strip=True)
value = value_elem.get_text(strip=True)
fund_data[key] = value
# 转换为DataFrame
temp_df = pd.DataFrame(list(fund_data.items()), columns=["字段", ""])
return temp_df
if __name__ == "__main__":
# 测试获取基金基本信息
fund_info_ths_df = fund_info_ths(symbol="161130")
print(fund_info_ths_df)
@@ -0,0 +1,83 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/11/7 18:30
Desc: 基金数据-新发基金-新成立基金
https://fund.eastmoney.com/data/xinfound.html
"""
import pandas as pd
import requests
from akshare.utils import demjson
def fund_new_found_em() -> pd.DataFrame:
"""
基金数据-新发基金-新成立基金
https://fund.eastmoney.com/data/xinfound.html
:return: 新成立基金
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/FundNewIssue.aspx"
params = {
"t": "xcln",
"sort": "jzrgq,desc",
"y": "",
"page": "1,50000",
"isbuy": "1",
"v": "0.4069919776543214",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text.strip("var newfunddata="))
temp_df = pd.DataFrame(data_json["datas"])
temp_df.columns = [
"基金代码",
"基金简称",
"发行公司",
"_",
"基金类型",
"募集份额",
"成立日期",
"成立来涨幅",
"基金经理",
"申购状态",
"集中认购期",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"优惠费率",
]
temp_df = temp_df[
[
"基金代码",
"基金简称",
"发行公司",
"基金类型",
"集中认购期",
"募集份额",
"成立日期",
"成立来涨幅",
"基金经理",
"申购状态",
"优惠费率",
]
]
temp_df["募集份额"] = pd.to_numeric(temp_df["募集份额"], errors="coerce")
temp_df["成立日期"] = pd.to_datetime(temp_df["成立日期"], errors="coerce").dt.date
temp_df["成立来涨幅"] = pd.to_numeric(
temp_df["成立来涨幅"].str.replace(",", ""), errors="coerce"
)
temp_df["优惠费率"] = temp_df["优惠费率"].str.strip("%")
temp_df["优惠费率"] = pd.to_numeric(temp_df["优惠费率"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_new_found_em_df = fund_new_found_em()
print(fund_new_found_em_df)
@@ -0,0 +1,139 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/2/27
Desc: 同花顺-新发基金
https://fund.10jqka.com.cn/datacenter/xfjj/
"""
import json
import pandas as pd
import requests
def fund_new_found_ths(symbol: str = "全部") -> pd.DataFrame:
"""
同花顺-基金数据-新发基金
https://fund.10jqka.com.cn/datacenter/xfjj/
:param symbol: 选择基金类型; choice of {"全部", "发行中", "将发行"}
:type symbol: str
:return: 新发基金数据
:rtype: pandas.DataFrame
"""
url = "https://fund.10jqka.com.cn/datacenter/xfjj/"
r = requests.get(url, timeout=15)
r.encoding = "utf-8"
# 从页面中提取 jsonData
# 找到 jsonData= 的位置
start_idx = r.text.find("jsonData=")
if start_idx == -1:
raise ValueError("未找到 jsonData,可能页面结构已变化")
# 找到第一个 {
start_bracket = r.text.find("{", start_idx)
if start_bracket == -1:
raise ValueError("未找到 JSON 开始括号")
# 通过计数括号找到完整的JSON对象
count = 0
end_idx = start_bracket
for i in range(start_bracket, len(r.text)):
if r.text[i] == "{":
count += 1
elif r.text[i] == "}":
count -= 1
if count == 0:
end_idx = i + 1
break
if end_idx == start_bracket:
raise ValueError("未找到完整的 JSON 对象")
json_str = r.text[start_bracket:end_idx]
data_json = json.loads(json_str)
# 转换为 DataFrame
temp_df = pd.DataFrame(data_json).T
temp_df.reset_index(inplace=True, drop=True)
# 根据 symbol 筛选数据
if symbol == "发行中":
# 发行中: zzfx=1
temp_df = temp_df[temp_df["zzfx"] == 1]
elif symbol == "将发行":
# 将发行: zzfx != 1 (即 buy=0 且起始日在未来)
temp_df = temp_df[temp_df["zzfx"] != 1]
# 提取 manager 字段(可能是数组)
if "manager" in temp_df.columns:
temp_df["manager"] = temp_df["manager"].apply(
lambda x: x[0] if isinstance(x, list) and len(x) > 0 else (x if pd.notna(x) else "")
)
# 重命名列
temp_df.rename(
columns={
"code": "基金代码",
"name": "基金名称",
"type": "投资类型",
"jjlx": "基金类型",
"tzfg": "投资风格",
"start": "募集起始日",
"end": "募集终止日",
"orgname": "管理人",
"manager": "基金经理",
"zgrgfl": "认购费率",
"zdrg": "最低认购",
"zdje": "认购金额",
"zzfx": "发行中",
"buy": "可购买",
},
inplace=True,
)
# 选择需要的列
columns_order = [
"基金代码",
"基金名称",
"投资类型",
"募集起始日",
"募集终止日",
"管理人",
"基金经理",
"认购费率",
"最低认购",
"基金类型",
"投资风格",
]
# 只保留存在的列
existing_columns = [col for col in columns_order if col in temp_df.columns]
temp_df = temp_df[existing_columns]
# 数据类型转换
if "募集起始日" in temp_df.columns:
temp_df["募集起始日"] = pd.to_datetime(temp_df["募集起始日"], errors="coerce").dt.date
if "募集终止日" in temp_df.columns:
temp_df["募集终止日"] = pd.to_datetime(temp_df["募集终止日"], errors="coerce").dt.date
if "认购费率" in temp_df.columns:
temp_df["认购费率"] = pd.to_numeric(temp_df["认购费率"], errors="coerce")
if "最低认购" in temp_df.columns:
temp_df["最低认购"] = pd.to_numeric(temp_df["最低认购"], errors="coerce")
return temp_df
if __name__ == "__main__":
# 测试获取全部新发基金
fund_new_found_ths_df = fund_new_found_ths(symbol="全部")
print(fund_new_found_ths_df)
# 测试获取发行中的基金
fund_new_found_ths_issue_df = fund_new_found_ths(symbol="发行中")
print(fund_new_found_ths_issue_df)
# 测试获取将发行的基金
fund_new_found_ths_future_df = fund_new_found_ths(symbol="将发行")
print(fund_new_found_ths_future_df)
@@ -0,0 +1,356 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/3/11 17:00
Desc: 东方财富-LOF 行情
https://quote.eastmoney.com/center/gridlist.html#fund_lof
https://quote.eastmoney.com/sz166009.html
"""
from functools import lru_cache
import pandas as pd
import requests
from akshare.utils.func import fetch_paginated_data
@lru_cache()
def _fund_lof_code_id_map_em() -> dict:
"""
东方财富-LOF 代码和市场标识映射
https://quote.eastmoney.com/center/gridlist.html#fund_lof
:return: LOF 代码和市场标识映射
:rtype: pandas.DataFrame
"""
url = "https://2.push2.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "100",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f12",
"fs": "b:MK0404,b:MK0405,b:MK0406,b:MK0407",
"fields": "f3,f12,f13",
}
temp_df = fetch_paginated_data(url, params)
temp_dict = dict(zip(temp_df["f12"], temp_df["f13"]))
return temp_dict
def fund_lof_spot_em() -> pd.DataFrame:
"""
东方财富-LOF 实时行情
https://quote.eastmoney.com/center/gridlist.html#fund_lof
:return: LOF 实时行情
:rtype: pandas.DataFrame
"""
url = "https://88.push2.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "100",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f3",
"fs": "b:MK0404,b:MK0405,b:MK0406,b:MK0407",
"fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,"
"f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152",
}
temp_df = fetch_paginated_data(url, params)
temp_df.rename(
columns={
"f12": "代码",
"f14": "名称",
"f2": "最新价",
"f4": "涨跌额",
"f3": "涨跌幅",
"f5": "成交量",
"f6": "成交额",
"f17": "开盘价",
"f15": "最高价",
"f16": "最低价",
"f18": "昨收",
"f8": "换手率",
"f21": "流通市值",
"f20": "总市值",
},
inplace=True,
)
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌额",
"涨跌幅",
"成交量",
"成交额",
"开盘价",
"最高价",
"最低价",
"昨收",
"换手率",
"流通市值",
"总市值",
]
]
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")
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")
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 fund_lof_hist_em(
symbol: str = "166009",
period: str = "daily",
start_date: str = "19700101",
end_date: str = "20500101",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-LOF 行情
https://quote.eastmoney.com/sz166009.html
:param symbol: LOF 代码
:type symbol: str
:param period: choice of {'daily', 'weekly', 'monthly'}
:type period: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
:type adjust: str
:return: 每日行情
:rtype: pandas.DataFrame
"""
code_id_dict = _fund_lof_code_id_map_em()
adjust_dict = {"qfq": "1", "hfq": "2", "": "0"}
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period_dict[period],
"fqt": adjust_dict[adjust],
"secid": f"{code_id_dict[symbol]}.{symbol}",
"beg": start_date,
"end": end_date,
}
r = requests.get(url, params=params)
data_json = r.json()
if not (data_json["data"] and data_json["data"]["klines"]):
return pd.DataFrame()
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
temp_df.columns = [
"日期",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["日期"])
temp_df.reset_index(inplace=True, drop=True)
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")
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")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
return temp_df
def fund_lof_hist_min_em(
symbol: str = "166009",
start_date: str = "1979-09-01 09:32:00",
end_date: str = "2222-01-01 09:32:00",
period: str = "5",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-LOF 分时行情
https://quote.eastmoney.com/sz166009.html
:param symbol: LOF 代码
:type symbol: str
:param start_date: 开始日期时间
:type start_date: str
:param end_date: 结束日期时间
:type end_date: str
:param period: choice of {"1", "5", "15", "30", "60"}
:type period: str
:param adjust: choice of {'', 'qfq', 'hfq'}
:type adjust: str
:return: 每日分时行情
:rtype: pandas.DataFrame
"""
code_id_dict = _fund_lof_code_id_map_em()
adjust_map = {
"": "0",
"qfq": "1",
"hfq": "2",
}
if period == "1":
url = "https://push2his.eastmoney.com/api/qt/stock/trends2/get"
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": "7eea3edcaed734bea9cbfc24409ed989",
"ndays": "5",
"iscr": "0",
"secid": f"{code_id_dict[symbol]}.{symbol}",
}
r = requests.get(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["trends"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"均价",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
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")
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_datetime(temp_df["时间"]).astype(str)
return temp_df
else:
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period,
"fqt": adjust_map[adjust],
"secid": f"{code_id_dict[symbol]}.{symbol}",
"beg": "0",
"end": "20500000",
}
r = requests.get(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["klines"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
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")
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")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
temp_df = temp_df[
[
"时间",
"开盘",
"收盘",
"最高",
"最低",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
]
]
return temp_df
if __name__ == "__main__":
fund_lof_spot_em_df = fund_lof_spot_em()
print(fund_lof_spot_em_df)
fund_lof_hist_em_df = fund_lof_hist_em(
symbol="166009",
period="daily",
start_date="20000101",
end_date="20230703",
adjust="",
)
print(fund_lof_hist_em_df)
fund_lof_hist_qfq_em_df = fund_lof_hist_em(
symbol="166009",
period="daily",
start_date="20000101",
end_date="20230703",
adjust="qfq",
)
print(fund_lof_hist_qfq_em_df)
fund_lof_hist_em_df = fund_lof_hist_em(
symbol="166009",
period="daily",
start_date="20000101",
end_date="20250311",
adjust="hfq",
)
print(fund_lof_hist_em_df)
fund_lof_hist_min_em_df = fund_lof_hist_min_em(
symbol="166009",
period="1",
adjust="",
start_date="2025-03-11 09:30:00",
end_date="2025-03-11 14:40:00",
)
print(fund_lof_hist_min_em_df)
@@ -0,0 +1,101 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/9/14 18:00
Desc: 基金经理大全
https://fund.eastmoney.com/manager/default.html
"""
import pandas as pd
import requests
from akshare.utils import demjson
from akshare.utils.tqdm import get_tqdm
def fund_manager_em() -> pd.DataFrame:
"""
天天基金网-基金数据-基金经理大全
https://fund.eastmoney.com/manager/default.html
:return: 基金经理大全
:rtype: pandas.DataFrame
"""
big_df = pd.DataFrame()
url = "https://fund.eastmoney.com/Data/FundDataPortfolio_Interface.aspx"
params = {
"dt": "14",
"mc": "returnjson",
"ft": "all",
"pn": "500",
"pi": "1",
"sc": "abbname",
"st": "asc",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text.strip("var returnjson= "))
total_page = data_json["pages"]
tqdm = get_tqdm()
for page in tqdm(range(1, total_page + 1), leave=False):
params.update(
{
"pi": page,
}
)
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text.strip("var returnjson= "))
temp_df = pd.DataFrame(data_json["data"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = range(1, len(big_df) + 1)
big_df.columns = [
"序号",
"_",
"姓名",
"_",
"所属公司",
"现任基金代码",
"现任基金",
"累计从业时间",
"现任基金最佳回报",
"_",
"_",
"现任基金资产总规模",
"_",
]
big_df = big_df[
[
"序号",
"姓名",
"所属公司",
"现任基金代码",
"现任基金",
"累计从业时间",
"现任基金资产总规模",
"现任基金最佳回报",
]
]
big_df["现任基金最佳回报"] = (
big_df["现任基金最佳回报"].str.split("%", expand=True).iloc[:, 0]
)
big_df["现任基金资产总规模"] = (
big_df["现任基金资产总规模"].str.split("亿元", expand=True).iloc[:, 0]
)
big_df["累计从业时间"] = pd.to_numeric(big_df["累计从业时间"], errors="coerce")
big_df["现任基金最佳回报"] = pd.to_numeric(
big_df["现任基金最佳回报"], errors="coerce"
)
big_df["现任基金资产总规模"] = pd.to_numeric(
big_df["现任基金资产总规模"], errors="coerce"
)
big_df["现任基金代码"] = big_df["现任基金代码"].apply(lambda x: x.split(","))
big_df["现任基金"] = big_df["现任基金"].apply(lambda x: x.split(","))
big_df = big_df.explode(column=["现任基金代码", "现任基金"])
big_df.reset_index(drop=True, inplace=True)
return big_df
if __name__ == "__main__":
fund_manager_em_df = fund_manager_em()
print(fund_manager_em_df)
@@ -0,0 +1,43 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/9/16 21:00
Desc: 天天基金-基金档案
https://fundf10.eastmoney.com/jbgk_015641.html
"""
from io import StringIO
import pandas as pd
import requests
def fund_overview_em(symbol: str = "015641") -> pd.DataFrame:
"""
天天基金-基金档案-基本概况
https://fundf10.eastmoney.com/jbgk_015641.html
:param symbol: 基金代码
:type symbol: str
:return: 基本概况
:rtype: pandas.DataFrame
"""
url = f"https://fundf10.eastmoney.com/jbgk_{symbol}.html"
r = requests.get(url)
html_content = pd.read_html(StringIO(r.text))
if len(html_content) == 0:
temp_df = pd.DataFrame([])
else:
df_dict = {}
# 最后一个表格的数据是我们想要的,按照Key-Value的形式存储
for _, row in html_content[-1].iterrows():
df_dict[row[0]] = row[1]
df_dict[row[2]] = row[3]
temp_df = pd.DataFrame([df_dict])
return temp_df
if __name__ == "__main__":
fund_overview_em_df = fund_overview_em(symbol="015641")
print(fund_overview_em_df)
@@ -0,0 +1,336 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/6/7 20:00
Desc: 天天基金网-基金档案-投资组合
https://fundf10.eastmoney.com/ccmx_000001.html
"""
from io import StringIO
import pandas as pd
import requests
from bs4 import BeautifulSoup
from akshare.utils import demjson
def fund_portfolio_hold_em(symbol: str = "000001", date: str = "2024") -> pd.DataFrame:
"""
天天基金网-基金档案-投资组合-基金持仓
https://fundf10.eastmoney.com/ccmx_000001.html
:param symbol: 基金代码
:type symbol: str
:param date: 查询年份
:type date: str
:return: 基金持仓
:rtype: pandas.DataFrame
"""
url = "https://fundf10.eastmoney.com/FundArchivesDatas.aspx"
params = {
"type": "jjcc",
"code": symbol,
"topline": "10000",
"year": date,
"month": "",
"rt": "0.913877030254846",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
soup = BeautifulSoup(data_json["content"], features="lxml")
item_label = [
item.text.split("\xa0\xa0")[1]
for item in soup.find_all(name="h4", attrs={"class": "t"})
]
column_name = [
"序号",
"股票代码",
"股票名称",
"占净值比例",
"持股数",
"持仓市值",
"季度",
]
big_df = pd.DataFrame(columns=column_name)
for item in range(len(item_label)):
temp_df = pd.read_html(
StringIO(data_json["content"]), converters={"股票代码": str}
)[item]
del temp_df["相关资讯"]
temp_df.rename(columns={"占净值 比例": "占净值比例"}, inplace=True)
temp_df["占净值比例"] = (
temp_df["占净值比例"].str.split("%", expand=True).iloc[:, 0]
)
temp_df.rename(
columns={"持股数(万股)": "持股数", "持仓市值(万元)": "持仓市值"},
inplace=True,
)
temp_df.rename(
columns={"持股数 (万股)": "持股数", "持仓市值 (万元)": "持仓市值"},
inplace=True,
)
temp_df.rename(
columns={"持股数(万股)": "持股数", "持仓市值(万元人民币)": "持仓市值"},
inplace=True,
)
temp_df.rename(
columns={
"持股数 (万股)": "持股数",
"持仓市值 (万元人民币)": "持仓市值",
},
inplace=True,
)
temp_df["季度"] = item_label[item]
temp_df = temp_df[column_name]
big_df = (
pd.concat(objs=[temp_df, big_df], ignore_index=True)
if not big_df.empty
else temp_df
)
if not big_df.empty:
big_df["占净值比例"] = pd.to_numeric(big_df["占净值比例"], errors="coerce")
big_df["持股数"] = pd.to_numeric(big_df["持股数"], errors="coerce")
big_df["持仓市值"] = pd.to_numeric(big_df["持仓市值"], errors="coerce")
del big_df["序号"]
big_df.reset_index(inplace=True, drop=False)
big_df["index"] = big_df["index"] + 1
big_df.rename(columns={"index": "序号"}, inplace=True)
return big_df
def fund_portfolio_bond_hold_em(
symbol: str = "000001", date: str = "2023"
) -> pd.DataFrame:
"""
天天基金网-基金档案-投资组合-债券持仓
https://fundf10.eastmoney.com/ccmx1_000001.html
:param symbol: 基金代码
:type symbol: str
:param date: 查询年份
:type date: str
:return: 债券持仓
:rtype: pandas.DataFrame
"""
url = "https://fundf10.eastmoney.com/FundArchivesDatas.aspx"
params = {
"type": "zqcc",
"code": symbol,
"year": date,
"rt": "0.913877030254846",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
soup = BeautifulSoup(data_json["content"], features="lxml")
item_label = [
item.text.split("\xa0\xa0")[1]
for item in soup.find_all(name="h4", attrs={"class": "t"})
]
big_df = pd.DataFrame()
for item in range(len(item_label)):
temp_df = pd.read_html(
StringIO(data_json["content"]), converters={"债券代码": str}
)[item]
temp_df["占净值比例"] = (
temp_df["占净值比例"].str.split("%", expand=True).iloc[:, 0]
)
temp_df.rename(columns={"持仓市值(万元)": "持仓市值"}, inplace=True)
temp_df["季度"] = item_label[item]
temp_df = temp_df[
[
"序号",
"债券代码",
"债券名称",
"占净值比例",
"持仓市值",
"季度",
]
]
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df["占净值比例"] = pd.to_numeric(big_df["占净值比例"], errors="coerce")
big_df["持仓市值"] = pd.to_numeric(big_df["持仓市值"], errors="coerce")
big_df["序号"] = range(1, len(big_df) + 1)
return big_df
def fund_portfolio_industry_allocation_em(
symbol: str = "000001", date: str = "2023"
) -> pd.DataFrame:
"""
天天基金网-基金档案-投资组合-行业配置
https://fundf10.eastmoney.com/hytz_000001.html
:param symbol: 基金代码
:type symbol: str
:param date: 查询年份
:type date: str
:return: 行业配置
:rtype: pandas.DataFrame
"""
url = "https://api.fund.eastmoney.com/f10/HYPZ/"
headers = {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Host": "api.fund.eastmoney.com",
"Pragma": "no-cache",
"Referer": "https://fundf10.eastmoney.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/99.0.4844.82 Safari/537.36",
}
params = {
"fundCode": symbol,
"year": date,
"callback": "jQuery183006997159478989867_1648016188499",
}
r = requests.get(url, params=params, headers=headers)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
temp_list = []
for item in data_json["Data"]["QuarterInfos"]:
temp_list.extend(item["HYPZInfo"])
temp_df = pd.DataFrame(temp_list)
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df.index + 1
temp_df.columns = [
"序号",
"-",
"截止时间",
"-",
"行业类别",
"市值",
"-",
"占净值比例",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
]
temp_df = temp_df[
[
"序号",
"行业类别",
"占净值比例",
"市值",
"截止时间",
]
]
temp_df["市值"] = pd.to_numeric(temp_df["市值"], errors="coerce")
temp_df["占净值比例"] = pd.to_numeric(temp_df["占净值比例"], errors="coerce")
return temp_df
def fund_portfolio_change_em(
symbol: str = "003567", indicator: str = "累计买入", date: str = "2023"
) -> pd.DataFrame:
"""
天天基金网-基金档案-投资组合-重大变动
https://fundf10.eastmoney.com/ccbd_000001.html
:param symbol: 基金代码
:type symbol: str
:param indicator: choice of {"累计买入", "累计卖出"}
:type indicator: str
:param date: 查询年份
:type date: str
:return: 重大变动
:rtype: pandas.DataFrame
"""
indicator_map = {
"累计买入": "1",
"累计卖出": "2",
}
url = "https://fundf10.eastmoney.com/FundArchivesDatas.aspx"
params = {
"type": "zdbd",
"code": symbol,
"zdbd": indicator_map[indicator],
"year": date,
"rt": "0.913877030254846",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
soup = BeautifulSoup(data_json["content"], features="lxml")
item_label = [
item.text.split("\xa0\xa0")[1]
for item in soup.find_all(name="h4", attrs={"class": "t"})
]
big_df = pd.DataFrame()
for item in range(len(item_label)):
temp_df = pd.read_html(
StringIO(data_json["content"]), converters={"股票代码": str}
)[item]
del temp_df["相关资讯"]
temp_df["占期初基金资产净值比例(%"] = (
temp_df["占期初基金资产净值比例(%"]
.str.split("%", expand=True)
.iloc[:, 0]
)
temp_df["季度"] = item_label[item]
temp_df.columns = [
"序号",
"股票代码",
"股票名称",
"本期累计买入金额",
"占期初基金资产净值比例",
"季度",
]
temp_df = temp_df[
[
"序号",
"股票代码",
"股票名称",
"本期累计买入金额",
"占期初基金资产净值比例",
"季度",
]
]
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
del big_df["序号"]
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.rename(columns={"index": "序号"}, inplace=True)
big_df["本期累计买入金额"] = pd.to_numeric(
big_df["本期累计买入金额"], errors="coerce"
)
big_df["占期初基金资产净值比例"] = pd.to_numeric(
big_df["占期初基金资产净值比例"], errors="coerce"
)
return big_df
if __name__ == "__main__":
fund_portfolio_hold_em_df = fund_portfolio_hold_em(symbol="000001", date="2024")
print(fund_portfolio_hold_em_df)
fund_portfolio_bond_hold_em_df = fund_portfolio_bond_hold_em(
symbol="000001", date="2023"
)
print(fund_portfolio_bond_hold_em_df)
fund_portfolio_industry_allocation_em_df = fund_portfolio_industry_allocation_em(
symbol="000001", date="2023"
)
print(fund_portfolio_industry_allocation_em_df)
fund_portfolio_change_em_df = fund_portfolio_change_em(
symbol="003567", indicator="累计买入", date="2023"
)
print(fund_portfolio_change_em_df)
fund_portfolio_change_em_df = fund_portfolio_change_em(
symbol="003567", indicator="累计卖出", date="2023"
)
print(fund_portfolio_change_em_df)
@@ -0,0 +1,135 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/4/5 22:05
Desc: 乐咕乐股-基金仓位
https://legulegu.com/stockdata/fund-position/pos-stock
"""
import pandas as pd
import requests
from akshare.stock_feature.stock_a_indicator import get_token_lg, get_cookie_csrf
def fund_stock_position_lg() -> pd.DataFrame:
"""
乐咕乐股-基金仓位-股票型基金仓位
https://legulegu.com/stockdata/fund-position/pos-stock
:return: 股票型基金仓位
:rtype: pandas.DataFrame
"""
url = "https://legulegu.com/api/stockdata/fund-position"
token = get_token_lg()
params = {
"token": token,
"type": "pos_stock",
"category": "总仓位",
"marketId": "5",
}
r = requests.get(
url,
params=params,
**get_cookie_csrf(url="https://legulegu.com/stockdata/fund-position/pos-stock"),
)
data_json = r.json()
temp_df = pd.DataFrame(data_json)
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df = temp_df[
[
"date",
"close",
"position",
]
]
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["position"] = pd.to_numeric(temp_df["position"], errors="coerce")
return temp_df
def fund_balance_position_lg() -> pd.DataFrame:
"""
乐咕乐股-基金仓位-平衡混合型基金仓位
https://legulegu.com/stockdata/fund-position/pos-pingheng
:return: 平衡混合型基金仓位
:rtype: pandas.DataFrame
"""
url = "https://legulegu.com/api/stockdata/fund-position"
token = get_token_lg()
params = {
"token": token,
"type": "pos_pingheng",
"category": "总仓位",
"marketId": "5",
}
r = requests.get(
url,
params=params,
**get_cookie_csrf(
url="https://legulegu.com/stockdata/fund-position/pos-pingheng"
),
)
data_json = r.json()
temp_df = pd.DataFrame(data_json)
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df = temp_df[
[
"date",
"close",
"position",
]
]
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["position"] = pd.to_numeric(temp_df["position"], errors="coerce")
return temp_df
def fund_linghuo_position_lg() -> pd.DataFrame:
"""
乐咕乐股-基金仓位-灵活配置型基金仓位
https://legulegu.com/stockdata/fund-position/pos-linghuo
:return: 灵活配置型基金仓位
:rtype: pandas.DataFrame
"""
url = "https://legulegu.com/api/stockdata/fund-position"
token = get_token_lg()
params = {
"token": token,
"type": "pos_linghuo",
"category": "总仓位",
"marketId": "5",
}
r = requests.get(
url,
params=params,
**get_cookie_csrf(
url="https://legulegu.com/stockdata/fund-position/pos-linghuo"
),
)
data_json = r.json()
temp_df = pd.DataFrame(data_json)
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df = temp_df[
[
"date",
"close",
"position",
]
]
temp_df["date"] = pd.to_datetime(temp_df["date"]).dt.date
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["position"] = pd.to_numeric(temp_df["position"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_stock_position_lg_df = fund_stock_position_lg()
print(fund_stock_position_lg_df)
fund_balance_position_lg_df = fund_balance_position_lg()
print(fund_balance_position_lg_df)
fund_linghuo_position_lg_df = fund_linghuo_position_lg()
print(fund_linghuo_position_lg_df)
@@ -0,0 +1,555 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/7/24 13:00
Desc: 东方财富网-数据中心-开放基金排行
https://fund.eastmoney.com/data/fundranking.html
名词解释
https://help.1234567.com.cn/list_236.html
"""
from datetime import datetime, date
import pandas as pd
import requests
from akshare.utils import demjson
def __one_year_ago(date_str: str) -> date:
# 将字符串格式的日期转换为date对象
given_date = date(int(date_str[0:4]), int(date_str[4:6]), int(date_str[6:8]))
try:
# 尝试直接设置为前一年,保持相同的月和日
one_year_before = given_date.replace(year=given_date.year - 1)
except ValueError:
# 如果前一年没有相同的月和日(比如2月29日),则设置为2月28日
one_year_before = given_date.replace(year=given_date.year - 1, day=28)
return one_year_before
def fund_open_fund_rank_em(symbol: str = "全部") -> pd.DataFrame:
"""
东方财富网-数据中心-开放基金排行
https://fund.eastmoney.com/data/fundranking.html
:param symbol: choice of {"全部", "股票型", "混合型", "债券型", "指数型", "QDII", "FOF"}
:type symbol: str
:return: 开放基金排行
:rtype: pandas.DataFrame
"""
current_date = datetime.now().date().isoformat()
last_date = __one_year_ago(current_date.replace("-", "")).isoformat()
url = "https://fund.eastmoney.com/data/rankhandler.aspx"
type_map = {
"全部": ["all", "1nzf"],
"股票型": ["gp", "1nzf"],
"混合型": ["hh", "1nzf"],
"债券型": ["zq", "1nzf"],
"指数型": ["zs", "1nzf"],
"QDII": ["qdii", "1nzf"],
"LOF": ["lof", "1nzf"],
"FOF": ["fof", "1nzf"],
}
params = {
"op": "ph",
"dt": "kf",
"ft": type_map[symbol][0],
"rs": "",
"gs": "0",
"sc": type_map[symbol][1],
"st": "desc",
"sd": last_date,
"ed": current_date,
"qdii": "",
"tabSubtype": ",,,,,",
"pi": "1",
"pn": "30000",
"dx": "1",
"v": "0.1591891419018292",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/81.0.4044.138 Safari/537.36",
"Referer": "https://fund.eastmoney.com/fundguzhi.html",
}
r = requests.get(url, params=params, headers=headers)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
temp_df = pd.DataFrame(data_json["datas"])
temp_df = temp_df.iloc[:, 0].str.split(",", expand=True)
temp_df.reset_index(inplace=True)
temp_df["index"] = list(range(1, len(temp_df) + 1))
temp_df.columns = [
"序号",
"基金代码",
"基金简称",
"_",
"日期",
"单位净值",
"累计净值",
"日增长率",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"_",
"_",
"自定义",
"_",
"手续费",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"日期",
"单位净值",
"累计净值",
"日增长率",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"自定义",
"手续费",
]
]
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["近1周"] = pd.to_numeric(temp_df["近1周"], errors="coerce")
temp_df["近1月"] = pd.to_numeric(temp_df["近1月"], errors="coerce")
temp_df["近3月"] = pd.to_numeric(temp_df["近3月"], errors="coerce")
temp_df["近6月"] = pd.to_numeric(temp_df["近6月"], errors="coerce")
temp_df["近1年"] = pd.to_numeric(temp_df["近1年"], errors="coerce")
temp_df["近2年"] = pd.to_numeric(temp_df["近2年"], errors="coerce")
temp_df["近3年"] = pd.to_numeric(temp_df["近3年"], 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 fund_exchange_rank_em() -> pd.DataFrame:
"""
东方财富网-数据中心-场内交易基金排行
https://fund.eastmoney.com/data/fbsfundranking.html
:return: 场内交易基金数据
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/rankhandler.aspx"
params = {
"op": "ph",
"dt": "fb",
"ft": "ct",
"rs": "",
"gs": "0",
"sc": "1nzf",
"st": "desc",
"pi": "1",
"pn": "30000",
"v": "0.1591891419018292",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/81.0.4044.138 Safari/537.36",
"Referer": "https://fund.eastmoney.com/fundguzhi.html",
}
r = requests.get(url, params=params, headers=headers)
text_data = r.text
json_data = demjson.decode(text_data[text_data.find("{") : -1])
temp_df = pd.DataFrame(json_data["datas"])
temp_df = temp_df.iloc[:, 0].str.split(",", expand=True)
temp_df.reset_index(inplace=True)
temp_df["index"] = list(range(1, len(temp_df) + 1))
temp_df.columns = [
"序号",
"基金代码",
"基金简称",
"_",
"日期",
"单位净值",
"累计净值",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"成立日期",
"_",
"_",
"_",
"_",
"_",
"类型",
"_",
]
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"类型",
"日期",
"单位净值",
"累计净值",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"成立日期",
]
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["成立日期"] = pd.to_datetime(temp_df["成立日期"]).dt.date
temp_df["单位净值"] = pd.to_numeric(temp_df["单位净值"], errors="coerce")
temp_df["累计净值"] = pd.to_numeric(temp_df["累计净值"], errors="coerce")
temp_df["近1周"] = pd.to_numeric(temp_df["近1周"], errors="coerce")
temp_df["近1月"] = pd.to_numeric(temp_df["近1月"], errors="coerce")
temp_df["近3月"] = pd.to_numeric(temp_df["近3月"], errors="coerce")
temp_df["近6月"] = pd.to_numeric(temp_df["近6月"], errors="coerce")
temp_df["近1年"] = pd.to_numeric(temp_df["近1年"], errors="coerce")
temp_df["近2年"] = pd.to_numeric(temp_df["近2年"], errors="coerce")
temp_df["近3年"] = pd.to_numeric(temp_df["近3年"], errors="coerce")
temp_df["今年来"] = pd.to_numeric(temp_df["今年来"], errors="coerce")
temp_df["成立来"] = pd.to_numeric(temp_df["成立来"], errors="coerce")
return temp_df
def fund_money_rank_em() -> pd.DataFrame:
"""
东方财富网-数据中心-货币型基金排行
https://fund.eastmoney.com/data/hbxfundranking.html
:return: 货币型基金排行
:rtype: pandas.DataFrame
"""
url = "https://api.fund.eastmoney.com/FundRank/GetHbRankList"
params = {
"intCompany": "0",
"MinsgType": "",
"IsSale": "1",
"strSortCol": "SYL_1N",
"orderType": "desc",
"pageIndex": "1",
"pageSize": "10000",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/81.0.4044.138 Safari/537.36",
"Referer": "https://fund.eastmoney.com/fundguzhi.html",
}
r = requests.get(url, params=params, headers=headers)
json_data = r.json()
temp_df = pd.DataFrame(json_data["Data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = list(range(1, len(temp_df) + 1))
temp_df.columns = [
"序号",
"近1年",
"近2年",
"近3年",
"近5年",
"_",
"_",
"基金代码",
"基金简称",
"日期",
"万份收益",
"年化收益率7日",
"_",
"年化收益率14日",
"年化收益率28日",
"近1月",
"近3月",
"近6月",
"今年来",
"成立来",
"_",
"手续费",
"_",
"_",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"日期",
"万份收益",
"年化收益率7日",
"年化收益率14日",
"年化收益率28日",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"近5年",
"今年来",
"成立来",
"手续费",
]
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["万份收益"] = pd.to_numeric(temp_df["万份收益"], errors="coerce")
temp_df["年化收益率7日"] = pd.to_numeric(temp_df["年化收益率7日"], errors="coerce")
temp_df["年化收益率14日"] = pd.to_numeric(
temp_df["年化收益率14日"], errors="coerce"
)
temp_df["年化收益率28日"] = pd.to_numeric(
temp_df["年化收益率28日"], errors="coerce"
)
temp_df["近1月"] = pd.to_numeric(temp_df["近1月"], errors="coerce")
temp_df["近3月"] = pd.to_numeric(temp_df["近3月"], errors="coerce")
temp_df["近6月"] = pd.to_numeric(temp_df["近6月"], errors="coerce")
temp_df["近1年"] = pd.to_numeric(temp_df["近1年"], errors="coerce")
temp_df["近2年"] = pd.to_numeric(temp_df["近2年"], errors="coerce")
temp_df["近3年"] = pd.to_numeric(temp_df["近3年"], errors="coerce")
temp_df["近5年"] = pd.to_numeric(temp_df["近5年"], errors="coerce")
temp_df["今年来"] = pd.to_numeric(temp_df["今年来"], errors="coerce")
temp_df["成立来"] = pd.to_numeric(temp_df["成立来"], errors="coerce")
return temp_df
def fund_lcx_rank_em() -> pd.DataFrame:
"""
东方财富网-数据中心-理财基金排行
# 该接口暂时没有数据
https://fund.eastmoney.com/data/lcxfundranking.html#t;c0;r;sSYL_Z;ddesc;pn50;f;os1;
:return: 理财基金排行
:rtype: pandas.DataFrame
"""
url = "https://api.fund.eastmoney.com/FundRank/GetLcRankList"
params = {
"intCompany": "0",
"MinsgType": "undefined",
"IsSale": "1",
"strSortCol": "SYL_Z",
"orderType": "desc",
"pageIndex": "1",
"pageSize": "50",
"FBQ": "",
"callback": "jQuery18303264654966943197_1603867158043",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/81.0.4044.138 Safari/537.36",
"Referer": "https://fund.eastmoney.com/fundguzhi.html",
}
r = requests.get(url, params=params, headers=headers)
try:
data_json = r.json()
except: # noqa: E722
return pd.DataFrame()
temp_df = pd.DataFrame(data_json["Data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = list(range(1, len(temp_df) + 1))
temp_df.columns = [
"序号",
"近1周",
"基金代码",
"基金简称",
"日期",
"万份收益",
"年化收益率-7日",
"_",
"年化收益率-14日",
"年化收益率-28日",
"近1月",
"近3月",
"近6月",
"今年来",
"成立来",
"可购买",
"手续费",
"_",
"_",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"日期",
"万份收益",
"年化收益率-7日",
"年化收益率-14日",
"年化收益率-28日",
"近1周",
"近1月",
"近3月",
"近6月",
"今年来",
"成立来",
"可购买",
"手续费",
]
]
return temp_df
def fund_hk_rank_em() -> pd.DataFrame:
"""
东方财富网-数据中心-香港基金排行
https://overseas.1234567.com.cn/FundList
:return: 香港基金排行
:rtype: pandas.DataFrame
"""
format_date = datetime.now().date().isoformat()
url = "https://overseas.1234567.com.cn/overseasapi/OpenApiHander.ashx"
params = {
"api": "HKFDApi",
"m": "MethodFundList",
"action": "1",
"pageindex": "0",
"pagesize": "5000",
"dy": "1",
"date1": format_date,
"date2": format_date,
"sortfield": "Y",
"sorttype": "-1",
"isbuy": "0",
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/81.0.4044.138 Safari/537.36",
"Referer": "https://fund.eastmoney.com/fundguzhi.html",
}
r = requests.get(url, params=params, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["Data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = list(range(1, len(temp_df) + 1))
temp_df.columns = [
"序号",
"_",
"香港基金代码",
"基金代码",
"_",
"基金简称",
"可购买",
"日期",
"单位净值",
"日增长率",
"_",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"币种",
]
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"币种",
"日期",
"单位净值",
"日增长率",
"近1周",
"近1月",
"近3月",
"近6月",
"近1年",
"近2年",
"近3年",
"今年来",
"成立来",
"可购买",
"香港基金代码",
]
]
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["近1周"] = pd.to_numeric(temp_df["近1周"], errors="coerce")
temp_df["近1月"] = pd.to_numeric(temp_df["近1月"], errors="coerce")
temp_df["近3月"] = pd.to_numeric(temp_df["近3月"], errors="coerce")
temp_df["近6月"] = pd.to_numeric(temp_df["近6月"], errors="coerce")
temp_df["近1年"] = pd.to_numeric(temp_df["近1年"], errors="coerce")
temp_df["近2年"] = pd.to_numeric(temp_df["近2年"], errors="coerce")
temp_df["近3年"] = pd.to_numeric(temp_df["近3年"], 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")
temp_df["可购买"] = temp_df["可购买"].map(
lambda x: "可购买" if x == "1" else "不可购买"
)
return temp_df
if __name__ == "__main__":
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="全部")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="股票型")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="混合型")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="债券型")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="指数型")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="QDII")
print(fund_open_fund_rank_em_df)
fund_open_fund_rank_em_df = fund_open_fund_rank_em(symbol="FOF")
print(fund_open_fund_rank_em_df)
fund_exchange_rank_em_df = fund_exchange_rank_em()
print(fund_exchange_rank_em_df)
fund_money_rank_em_df = fund_money_rank_em()
print(fund_money_rank_em_df)
fund_lcx_rank_em_df = fund_lcx_rank_em()
print(fund_lcx_rank_em_df)
fund_hk_rank_em_df = fund_hk_rank_em()
print(fund_hk_rank_em_df)
@@ -0,0 +1,375 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/12/12 16:30
Desc: 基金评级
https://fund.eastmoney.com/data/fundrating.html
"""
import pandas as pd
import requests
from bs4 import BeautifulSoup
def fund_rating_all() -> pd.DataFrame:
"""
天天基金网-基金评级-基金评级总汇
https://fund.eastmoney.com/data/fundrating.html
:return: 基金评级总汇
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/fundrating.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, features="lxml")
data_text = soup.find(name="div", attrs={"id": "fundinfo"}).find("script").string
data_content = [
item.split("|")
for item in data_text.split("var")[6]
.split("=")[1]
.strip()
.strip(";")
.strip('"')
.strip("|")
.split("|_")
]
temp_df = pd.DataFrame(data_content)
temp_df.columns = [
"代码",
"简称",
"类型",
"基金经理",
"-",
"基金公司",
"-",
"5星评级家数",
"-",
"-",
"招商证券",
"-",
"上海证券",
"-",
"晨星评级",
"-",
"济安金信",
"-",
"手续费",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
]
temp_df = temp_df[
[
"代码",
"简称",
"基金经理",
"基金公司",
"5星评级家数",
"上海证券",
"招商证券",
"济安金信",
"晨星评级",
"手续费",
"类型",
]
]
temp_df["5星评级家数"] = pd.to_numeric(temp_df["5星评级家数"], 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")
temp_df["晨星评级"] = pd.to_numeric(temp_df["晨星评级"], errors="coerce")
temp_df["手续费"] = (
pd.to_numeric(temp_df["手续费"].str.strip("%"), errors="coerce") / 100
)
return temp_df
def fund_rating_sh(date: str = "20230630") -> pd.DataFrame:
"""
天天基金网-基金评级-上海证券评级
https://fund.eastmoney.com/data/fundrating_3.html
:param date: 日期; https://fund.eastmoney.com/data/fundrating_3.html 获取查询日期
:type date: str
:return: 上海证券评级
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/fundrating_3.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
date_list = [
item["value"] for item in soup.find("select", attrs={"id": "rqoptions"})
]
date_format = "-".join([date[:4], date[4:6], date[6:]])
if date_format not in date_list:
raise "请访问 https://fund.eastmoney.com/data/fundrating_3.html 获取查询日期"
url = f"https://fund.eastmoney.com/data/fundrating_3_{'-'.join([date[:4], date[4:6], date[6:]])}.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
data_text = soup.find("div", attrs={"id": "fundinfo"}).find("script").string
data_content = [
item.split("|")
for item in data_text.split("var")[1]
.split("=")[1]
.strip()
.strip(";")
.strip('"')
.strip("|")
.split("|_")
]
temp_df = pd.DataFrame(data_content)
temp_df.columns = [
"代码",
"简称",
"类型",
"基金经理",
"_",
"基金公司",
"_",
"3年期评级-3年评级",
"3年期评级-较上期",
"5年期评级-5年评级",
"5年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"简称",
"基金经理",
"基金公司",
"3年期评级-3年评级",
"3年期评级-较上期",
"5年期评级-5年评级",
"5年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
"类型",
]
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["3年期评级-3年评级"] = pd.to_numeric(
temp_df["3年期评级-3年评级"], errors="coerce"
)
temp_df["3年期评级-较上期"] = pd.to_numeric(
temp_df["3年期评级-较上期"], errors="coerce"
)
temp_df["5年期评级-5年评级"] = pd.to_numeric(
temp_df["5年期评级-5年评级"], errors="coerce"
)
temp_df["5年期评级-较上期"] = pd.to_numeric(
temp_df["5年期评级-较上期"], errors="coerce"
)
temp_df["单位净值"] = pd.to_numeric(temp_df["单位净值"], errors="coerce")
temp_df["日增长率"] = pd.to_numeric(temp_df["日增长率"], errors="coerce")
temp_df["近1年涨幅"] = pd.to_numeric(temp_df["近1年涨幅"], errors="coerce")
temp_df["近3年涨幅"] = pd.to_numeric(temp_df["近3年涨幅"], errors="coerce")
temp_df["近5年涨幅"] = pd.to_numeric(temp_df["近5年涨幅"], errors="coerce")
return temp_df
def fund_rating_zs(date: str = "20230331") -> pd.DataFrame:
"""
天天基金网-基金评级-招商证券评级
https://fund.eastmoney.com/data/fundrating_2.html
:param date: 日期; https://fund.eastmoney.com/data/fundrating_2.html 获取查询日期
:type date: str
:return: 招商证券评级-混合型
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/fundrating_2.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
date_list = [
item["value"] for item in soup.find("select", attrs={"id": "rqoptions"})
]
date_format = "-".join([date[:4], date[4:6], date[6:]])
if date_format not in date_list:
raise "请访问 https://fund.eastmoney.com/data/fundrating_2.html 获取查询日期"
url = f"https://fund.eastmoney.com/data/fundrating_2_{'-'.join([date[:4], date[4:6], date[6:]])}.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
data_text = soup.find("div", attrs={"id": "fundinfo"}).find("script").string
data_content = [
item.split("|")
for item in data_text.split("var")[1]
.split("=")[1]
.strip()
.strip(";")
.strip('"')
.strip("|")
.split("|_")
]
temp_df = pd.DataFrame(data_content)
temp_df.columns = [
"代码",
"简称",
"_",
"基金经理",
"_",
"基金公司",
"_",
"3年期评级-3年评级",
"3年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"简称",
"基金经理",
"基金公司",
"3年期评级-3年评级",
"3年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
]
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["3年期评级-3年评级"] = pd.to_numeric(
temp_df["3年期评级-3年评级"], errors="coerce"
)
temp_df["3年期评级-较上期"] = pd.to_numeric(
temp_df["3年期评级-较上期"], errors="coerce"
)
temp_df["单位净值"] = pd.to_numeric(temp_df["单位净值"], errors="coerce")
temp_df["日增长率"] = pd.to_numeric(temp_df["日增长率"], errors="coerce")
temp_df["近1年涨幅"] = pd.to_numeric(temp_df["近1年涨幅"], errors="coerce")
temp_df["近3年涨幅"] = pd.to_numeric(temp_df["近3年涨幅"], errors="coerce")
temp_df["近5年涨幅"] = pd.to_numeric(temp_df["近5年涨幅"], errors="coerce")
return temp_df
def fund_rating_ja(date: str = "20230331") -> pd.DataFrame:
"""
天天基金网-基金评级-济安金信评级
https://fund.eastmoney.com/data/fundrating_4.html
:param date: 日期; https://fund.eastmoney.com/data/fundrating_4.html 获取查询日期
:type date: str
:return: 济安金信评级
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/fundrating_4.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
date_list = [
item["value"] for item in soup.find("select", attrs={"id": "rqoptions"})
]
date_format = "-".join([date[:4], date[4:6], date[6:]])
if date_format not in date_list:
raise "请访问 http://fund.eastmoney.com/data/fundrating_4.html 获取查询日期"
url = f"https://fund.eastmoney.com/data/fundrating_4_{'-'.join([date[:4], date[4:6], date[6:]])}.html"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
data_text = soup.find("div", attrs={"id": "fundinfo"}).find("script").string
data_content = [
item.split("|")
for item in data_text.split("var")[1]
.split("=")[1]
.strip()
.strip(";")
.strip('"')
.strip("|")
.split("|_")
]
temp_df = pd.DataFrame(data_content)
temp_df.columns = [
"代码",
"简称",
"类型",
"基金经理",
"_",
"基金公司",
"_",
"3年期评级-3年评级",
"3年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
"_",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"简称",
"基金经理",
"基金公司",
"3年期评级-3年评级",
"3年期评级-较上期",
"单位净值",
"日期",
"日增长率",
"近1年涨幅",
"近3年涨幅",
"近5年涨幅",
"手续费",
"类型",
]
]
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df["3年期评级-3年评级"] = pd.to_numeric(
temp_df["3年期评级-3年评级"], errors="coerce"
)
temp_df["3年期评级-较上期"] = pd.to_numeric(
temp_df["3年期评级-较上期"], errors="coerce"
)
temp_df["单位净值"] = pd.to_numeric(temp_df["单位净值"], errors="coerce")
temp_df["日增长率"] = pd.to_numeric(temp_df["日增长率"], errors="coerce")
temp_df["近1年涨幅"] = pd.to_numeric(temp_df["近1年涨幅"], errors="coerce")
temp_df["近3年涨幅"] = pd.to_numeric(temp_df["近3年涨幅"], errors="coerce")
temp_df["近5年涨幅"] = pd.to_numeric(temp_df["近5年涨幅"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_rating_all_df = fund_rating_all()
print(fund_rating_all_df)
fund_rating_sh_df = fund_rating_sh(date="20230630")
print(fund_rating_sh_df)
fund_rating_zs_df = fund_rating_zs(date="20230331")
print(fund_rating_zs_df)
fund_rating_ja_df = fund_rating_ja(date="20230331")
print(fund_rating_ja_df)
@@ -0,0 +1,240 @@
# -*- coding:utf-8 -*-
# !/usr/bin/env python
"""
Date: 2024/7/24 23:30
Desc: 巨潮资讯-数据中心-专题统计-基金报表
https://webapi.cninfo.com.cn/#/thematicStatistics
"""
import pandas as pd
import py_mini_racer
import requests
from akshare.datasets import get_ths_js
def _get_file_content_cninfo(file: str = "cninfo.js") -> str:
"""
获取 JS 文件的内容
:param file: JS 文件名
:type file: str
:return: 文件内容
:rtype: str
"""
setting_file_path = get_ths_js(file)
with open(setting_file_path, encoding="utf-8") as f:
file_data = f.read()
return file_data
def fund_report_stock_cninfo(date: str = "20210630") -> pd.DataFrame:
"""
巨潮资讯-数据中心-专题统计-基金报表-基金重仓股
https://webapi.cninfo.com.cn/#/thematicStatistics
:param date: 报告时间; choice of {"XXXX0331", "XXXX0630", "XXXX0930", "XXXX1231"}
:type date: str
:return: 基金重仓股
:rtype: pandas.DataFrame
"""
url = "https://webapi.cninfo.com.cn/api/sysapi/p_sysapi1112"
js_code = py_mini_racer.MiniRacer()
js_content = _get_file_content_cninfo("cninfo.js")
js_code.eval(js_content)
mcode = js_code.call("getResCode1")
headers = {
"Accept": "*/*",
"Accept-Enckey": mcode,
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cache-Control": "no-cache",
"Content-Length": "0",
"Host": "webapi.cninfo.com.cn",
"Origin": "https://webapi.cninfo.com.cn",
"Pragma": "no-cache",
"Proxy-Connection": "keep-alive",
"Referer": "https://webapi.cninfo.com.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/93.0.4577.63 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
}
params = {
"rdate": "-".join([date[:4], date[4:6], date[6:]]),
}
r = requests.post(url, headers=headers, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["records"])
temp_df.rename(
columns={
"F003N": "持股总市值",
"F002N": "持股总数",
"F001N": "基金覆盖家数",
"SECNAME": "股票简称",
"ID": "序号",
"SECCODE": "股票代码",
"ENDDATE": "报告期",
},
inplace=True,
)
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["序号"] = range(1, len(temp_df) + 1)
return temp_df
def fund_report_industry_allocation_cninfo(date: str = "20210630") -> pd.DataFrame:
"""
巨潮资讯-数据中心-专题统计-基金报表-基金行业配置
https://webapi.cninfo.com.cn/#/thematicStatistics
:param date: 报告时间; choice of {"XXXX0331", "XXXX0630", "XXXX0930", "XXXX1231"}, 从 2017 年开始
:type date: str
:return: 基金行业配置
:rtype: pandas.DataFrame
"""
url = "https://webapi.cninfo.com.cn/api/sysapi/p_sysapi1113"
js_code = py_mini_racer.MiniRacer()
js_content = _get_file_content_cninfo("cninfo.js")
js_code.eval(js_content)
mcode = js_code.call("getResCode1")
headers = {
"Accept": "*/*",
"Accept-Enckey": mcode,
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cache-Control": "no-cache",
"Content-Length": "0",
"Host": "webapi.cninfo.com.cn",
"Origin": "https://webapi.cninfo.com.cn",
"Pragma": "no-cache",
"Proxy-Connection": "keep-alive",
"Referer": "https://webapi.cninfo.com.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/93.0.4577.63 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
}
params = {
"rdate": "-".join([date[:4], date[4:6], date[6:]]),
}
r = requests.post(url, headers=headers, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["records"])
temp_df.rename(
columns={
"F004N": "行业规模",
"F003N": "基金覆盖家数",
"F002V": "证监会行业名称",
"F001V": "行业编码",
"ENDDATE": "报告期",
"F005N": "占净资产比例",
},
inplace=True,
)
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")
return temp_df
def fund_report_asset_allocation_cninfo() -> pd.DataFrame:
"""
巨潮资讯-数据中心-专题统计-基金报表-基金资产配置
https://webapi.cninfo.com.cn/#/thematicStatistics
:return: 基金资产配置
:rtype: pandas.DataFrame
"""
url = "https://webapi.cninfo.com.cn/api/sysapi/p_sysapi1114"
js_code = py_mini_racer.MiniRacer()
js_content = _get_file_content_cninfo("cninfo.js")
js_code.eval(js_content)
mcode = js_code.call("getResCode1")
headers = {
"Accept": "*/*",
"Accept-Enckey": mcode,
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cache-Control": "no-cache",
"Content-Length": "0",
"Host": "webapi.cninfo.com.cn",
"Origin": "https://webapi.cninfo.com.cn",
"Pragma": "no-cache",
"Proxy-Connection": "keep-alive",
"Referer": "https://webapi.cninfo.com.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/93.0.4577.63 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
}
r = requests.post(url, headers=headers)
data_json = r.json()
temp_df = pd.DataFrame(data_json["records"])
temp_df.rename(
columns={
"F001N": "基金覆盖家数",
"F008N": "现金货币类占净资产比例",
"F007N": "债券固定收益类占净资产比例",
"F006N": "股票权益类占净资产比例",
"ENDDATE": "报告期",
"F005N": "基金市场净资产规模",
},
inplace=True,
)
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"
)
temp_df["基金市场净资产规模"] = pd.to_numeric(
temp_df["基金市场净资产规模"], errors="coerce"
)
return temp_df
if __name__ == "__main__":
fund_report_stock_cninfo_df = fund_report_stock_cninfo(date="20210630")
print(fund_report_stock_cninfo_df)
fund_report_industry_allocation_cninfo_df = fund_report_industry_allocation_cninfo(
date="20210930"
)
print(fund_report_industry_allocation_cninfo_df)
fund_report_asset_allocation_cninfo_df = fund_report_asset_allocation_cninfo()
print(fund_report_asset_allocation_cninfo_df)
@@ -0,0 +1,126 @@
# -*- coding:utf-8 -*-
# !/usr/bin/env python
"""
Date: 2023/10/27 20:30
Desc: 天天基金网-基金数据-规模份额
https://fund.eastmoney.com/data/cyrjglist.html
"""
import pandas as pd
import requests
from akshare.utils import demjson
def fund_scale_change_em() -> pd.DataFrame:
"""
天天基金网-基金数据-规模份额-规模变动
https://fund.eastmoney.com/data/gmbdlist.html
:return: 规模变动
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/FundDataPortfolio_Interface.aspx"
params = {
"dt": "9",
"pi": "1",
"pn": "50",
"mc": "hypzDetail",
"st": "desc",
"sc": "reportdate",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
total_page = data_json["pages"]
big_df = pd.DataFrame()
for page in range(1, int(total_page) + 1):
params.update({"pi": page})
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
temp_df = pd.DataFrame(data_json["data"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df["index"] + 1
big_df.columns = [
"序号",
"截止日期",
"基金家数",
"期间申购",
"期间赎回",
"期末总份额",
"期末净资产",
]
big_df["截止日期"] = pd.to_datetime(big_df["截止日期"], errors="coerce").dt.date
big_df["基金家数"] = pd.to_numeric(big_df["基金家数"], errors="coerce")
big_df["期间申购"] = pd.to_numeric(
big_df["期间申购"].str.replace(",", ""), errors="coerce"
)
big_df["期间赎回"] = pd.to_numeric(
big_df["期间赎回"].str.replace(",", ""), errors="coerce"
)
big_df["期末总份额"] = pd.to_numeric(
big_df["期末总份额"].str.replace(",", ""), errors="coerce"
)
big_df["期末净资产"] = pd.to_numeric(
big_df["期末净资产"].str.replace(",", ""), errors="coerce"
)
return big_df
def fund_hold_structure_em() -> pd.DataFrame:
"""
天天基金网-基金数据-规模份额-持有人结构
https://fund.eastmoney.com/data/cyrjglist.html
:return: 持有人结构
:rtype: pandas.DataFrame
"""
url = "https://fund.eastmoney.com/data/FundDataPortfolio_Interface.aspx"
params = {
"dt": "11",
"pi": "1",
"pn": "50",
"mc": "hypzDetail",
"st": "desc",
"sc": "reportdate",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
total_page = data_json["pages"]
big_df = pd.DataFrame()
for page in range(1, int(total_page) + 1):
params.update({"pi": page})
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("{") : -1])
temp_df = pd.DataFrame(data_json["data"])
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df["index"] + 1
big_df.columns = [
"序号",
"截止日期",
"基金家数",
"机构持有比列",
"个人持有比列",
"内部持有比列",
"总份额",
]
big_df["截止日期"] = pd.to_datetime(big_df["截止日期"], errors="coerce").dt.date
big_df["基金家数"] = pd.to_numeric(big_df["基金家数"], errors="coerce")
big_df["机构持有比列"] = pd.to_numeric(big_df["机构持有比列"], errors="coerce")
big_df["个人持有比列"] = pd.to_numeric(big_df["个人持有比列"], errors="coerce")
big_df["内部持有比列"] = pd.to_numeric(big_df["内部持有比列"], errors="coerce")
big_df["总份额"] = pd.to_numeric(
big_df["总份额"].str.replace(",", ""), errors="coerce"
)
return big_df
if __name__ == "__main__":
fund_scale_change_em_df = fund_scale_change_em()
print(fund_scale_change_em_df)
fund_hold_structure_em_df = fund_hold_structure_em()
print(fund_hold_structure_em_df)
@@ -0,0 +1,248 @@
# -*- coding:utf-8 -*-
# !/usr/bin/env python
"""
Date: 2024/9/1 16:20
Desc: 新浪财经-基金规模
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjgmall
"""
import pandas as pd
import requests
from akshare.utils import demjson
def fund_scale_open_sina(symbol: str = "股票型基金") -> pd.DataFrame:
"""
新浪财经-基金数据中心-基金规模-开放式基金
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
:param symbol: choice of {"股票型基金", "混合型基金", "债券型基金", "货币型基金", "QDII基金"}
:type symbol: str
:return: 基金规模
:rtype: pandas.DataFrame
"""
fund_map = {
"股票型基金": "2",
"混合型基金": "1",
"债券型基金": "3",
"货币型基金": "5",
"QDII基金": "6",
}
url = (
"http://vip.stock.finance.sina.com.cn/fund_center/data/jsonp.php/IO.XSRV2."
"CallbackList['J2cW8KXheoWKdSHc']/NetValueReturn_Service.NetValueReturnOpen"
)
params = {
"page": "1",
"num": "10000",
"sort": "zmjgm",
"asc": "0",
"ccode": "",
"type2": fund_map[symbol],
"type3": "",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("({") + 1 : -2])
temp_df = pd.DataFrame(data_json["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = range(1, len(temp_df) + 1)
temp_df.rename(
columns={
"index": "序号",
"symbol": "基金代码",
"sname": "基金简称",
"per_nav": "-",
"total_nav": "-",
"three_month": "-",
"six_month": "-",
"one_year": "-",
"form_year": "-",
"form_start": "-",
"name": "-",
"zmjgm": "总募集规模",
"clrq": "成立日期",
"jjjl": "基金经理",
"dwjz": "单位净值",
"ljjz": "-",
"jzrq": "更新日期",
"zjzfe": "最近总份额",
"jjglr_code": "-",
},
inplace=True,
)
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"单位净值",
"总募集规模",
"最近总份额",
"成立日期",
"基金经理",
"更新日期",
]
]
temp_df["成立日期"] = pd.to_datetime(temp_df["成立日期"], errors="coerce").dt.date
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")
return temp_df
def fund_scale_close_sina() -> pd.DataFrame:
"""
新浪财经-基金数据中心-基金规模-封闭式基金
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
:return: 基金规模
:rtype: pandas.DataFrame
"""
url = (
"http://vip.stock.finance.sina.com.cn/fund_center/data/jsonp.php/IO.XSRV2."
"CallbackList['_bjN6KvXOkfPy2Bu']/NetValueReturn_Service.NetValueReturnClose"
)
params = {
"page": "1",
"num": "1000",
"sort": "zmjgm",
"asc": "0",
"ccode": "",
"type2": "",
"type3": "",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("({") + 1 : -2])
temp_df = pd.DataFrame(data_json["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = range(1, len(temp_df) + 1)
temp_df.rename(
columns={
"index": "序号",
"symbol": "基金代码",
"sname": "基金简称",
"per_nav": "-",
"total_nav": "-",
"three_month": "-",
"six_month": "-",
"one_year": "-",
"form_year": "-",
"form_start": "-",
"name": "-",
"zmjgm": "总募集规模",
"clrq": "成立日期",
"jjjl": "基金经理",
"dwjz": "单位净值",
"ljjz": "-",
"jzrq": "更新日期",
"zjzfe": "最近总份额",
"jjglr_code": "-",
},
inplace=True,
)
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"单位净值",
"总募集规模",
"最近总份额",
"成立日期",
"基金经理",
"更新日期",
]
]
temp_df["成立日期"] = pd.to_datetime(temp_df["成立日期"], errors="coerce").dt.date
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")
return temp_df
def fund_scale_structured_sina() -> pd.DataFrame:
"""
新浪财经-基金数据中心-基金规模-分级子基金
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjgmfjall
:return: 基金规模
:rtype: pandas.DataFrame
"""
url = (
"http://vip.stock.finance.sina.com.cn/fund_center/data/jsonp.php/IO.XSRV2."
"CallbackList['cRrwseM7NWX68rDa']/NetValueReturn_Service.NetValueReturnCX"
)
params = {
"page": "1",
"num": "1000",
"sort": "zmjgm",
"asc": "0",
"ccode": "",
"type2": "",
"type3": "",
}
r = requests.get(url, params=params)
data_text = r.text
data_json = demjson.decode(data_text[data_text.find("({") + 1 : -2])
temp_df = pd.DataFrame(data_json["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = range(1, len(temp_df) + 1)
temp_df.rename(
columns={
"index": "序号",
"symbol": "基金代码",
"sname": "基金简称",
"per_nav": "-",
"total_nav": "-",
"three_month": "-",
"six_month": "-",
"one_year": "-",
"form_year": "-",
"form_start": "-",
"name": "-",
"zmjgm": "总募集规模",
"clrq": "成立日期",
"jjjl": "基金经理",
"dwjz": "单位净值",
"ljjz": "-",
"jzrq": "更新日期",
"zjzfe": "最近总份额",
"jjglr_code": "-",
},
inplace=True,
)
temp_df = temp_df[
[
"序号",
"基金代码",
"基金简称",
"单位净值",
"总募集规模",
"最近总份额",
"成立日期",
"基金经理",
"更新日期",
]
]
temp_df["成立日期"] = pd.to_datetime(temp_df["成立日期"], errors="coerce").dt.date
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")
return temp_df
if __name__ == "__main__":
fund_scale_open_sina_df = fund_scale_open_sina(symbol="股票型基金")
print(fund_scale_open_sina_df)
fund_scale_close_sina_df = fund_scale_close_sina()
print(fund_scale_close_sina_df)
fund_scale_structured_sina_df = fund_scale_structured_sina()
print(fund_scale_structured_sina_df)
fund_scale_open_sina_df = fund_scale_open_sina(symbol="股票型基金")
print(fund_scale_open_sina_df)
@@ -0,0 +1,130 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2026/4/2 22:00
Desc: 深圳证券交易所-基金规模日频数据
https://www.szse.cn/market/fund/volume/etf/index.html
"""
import io
import random
import warnings
from datetime import date, datetime
import pandas as pd
import requests
def _parse_date(date_str: str) -> date:
if len(date_str) != 8 or not date_str.isdigit():
raise ValueError("start_date 和 end_date 格式应为 YYYYMMDD")
try:
return datetime.strptime(date_str, "%Y%m%d").date()
except ValueError as err:
raise ValueError("start_date 和 end_date 应为有效日期") from err
def fund_scale_daily_szse(
start_date: str = "20260401", end_date: str = "20260401", symbol: str = "ETF"
) -> pd.DataFrame:
"""
深圳证券交易所-基金产品-基金规模-日频数据
https://www.szse.cn/market/fund/volume/etf/index.html
:param start_date: 开始日期, 格式如 "20260401"
:type start_date: str
:param end_date: 结束日期, 格式如 "20260401"
:type end_date: str
:param symbol: 基金类别, choice of {"ETF", "LOF", "REITS"}
:type symbol: str
:return: 深交所基金规模日频数据;
日期范围不能超过 6 个月, 否则返回带表头的空 DataFrame
:rtype: pandas.DataFrame
"""
columns = ["日期", "基金代码", "基金简称", "基金份额"]
symbol_map = {
"ETF": {
"jjlb": "ETF",
"referer": "https://www.szse.cn/market/fund/volume/etf/index.html",
},
"LOF": {
"jjlb": "LOF",
"referer": "https://www.szse.cn/market/fund/volume/lof/index.html",
},
"REITS": {
"jjlb": "不动产基金",
"referer": "https://www.szse.cn/market/fund/volume/reits/index.html",
},
}
if symbol not in symbol_map:
raise ValueError("symbol 应为 {'ETF', 'LOF', 'REITS'}")
start = _parse_date(start_date)
end = _parse_date(end_date)
if start > end:
raise ValueError("start_date 不能大于 end_date")
url = "https://www.szse.cn/api/report/ShowReport"
headers = {
"Host": "www.szse.cn",
"Referer": symbol_map[symbol]["referer"],
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
}
params = {
"SHOWTYPE": "xlsx",
"CATALOGID": "scsj_fund_jjgm",
"TABKEY": "tab1",
"txtStart": start.strftime("%Y-%m-%d"),
"txtEnd": end.strftime("%Y-%m-%d"),
"jjlb": symbol_map[symbol]["jjlb"],
"random": str(random.random()),
}
r = requests.get(url, params=params, headers=headers, timeout=15)
r.raise_for_status()
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
temp_df = pd.read_excel(io.BytesIO(r.content), engine="openpyxl")
temp_df = temp_df.dropna(how="all")
if temp_df.empty:
return pd.DataFrame(columns=columns)
temp_df.rename(
columns={
"基金规模(份)": "基金份额",
},
inplace=True,
)
if "基金代码" in temp_df.columns:
code_series = pd.to_numeric(temp_df["基金代码"], errors="coerce")
temp_df = temp_df[code_series.notna()].copy()
temp_df["基金代码"] = (
code_series[code_series.notna()].astype(int).astype(str).str.zfill(6)
)
if "日期" in temp_df.columns:
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
temp_df = temp_df[temp_df["日期"].notna()]
if temp_df.empty:
return pd.DataFrame(columns=columns)
for item in ["基金份额"]:
if item in temp_df.columns:
temp_df[item] = temp_df[item].astype(str).str.replace(",", "", regex=False)
temp_df[item] = pd.to_numeric(temp_df[item], errors="coerce")
for item in columns:
if item not in temp_df.columns:
temp_df[item] = pd.NA
temp_df = temp_df[columns]
return temp_df
if __name__ == "__main__":
for item_symbol in ["ETF", "LOF", "REITS"]:
fund_scale_daily_szse_df = fund_scale_daily_szse(
start_date="20260401", end_date="20260402", symbol=item_symbol
)
print(item_symbol)
print(fund_scale_daily_szse_df)
@@ -0,0 +1,332 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/10/27 22:30
Desc: 雪球基金-基金详情
https://danjuanfunds.com/funding/003545
"""
import pandas as pd
import requests
def fund_individual_basic_info_xq(
symbol: str = "000001", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-基金详情
https://danjuanfunds.com/djapi/fund/675091
:param symbol: 基金代码
:type symbol: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 基金信息
:rtype: pandas.DataFrame
"""
url = f"https://danjuanfunds.com/djapi/fund/{symbol}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
r = requests.get(url, headers=headers, timeout=timeout)
json_data = r.json()["data"]
temp_df = pd.json_normalize(json_data)
temp_df.rename(
columns={
"fd_code": "基金代码",
"fd_name": "基金名称",
"fd_full_name": "基金全称",
"found_date": "成立时间",
"totshare": "最新规模",
"keeper_name": "基金公司",
"manager_name": "基金经理",
"trup_name": "托管银行",
"type_desc": "基金类型",
"rating_source": "评级机构",
"rating_desc": "基金评级",
"invest_orientation": "投资策略",
"invest_target": "投资目标",
"performance_bench_mark": "业绩比较基准",
},
inplace=True,
)
if "评级机构" not in temp_df.columns:
temp_df["评级机构"] = pd.NA
temp_df = temp_df[
[
"基金代码",
"基金名称",
"基金全称",
"成立时间",
"最新规模",
"基金公司",
"基金经理",
"托管银行",
"基金类型",
"评级机构",
"基金评级",
"投资策略",
"投资目标",
"业绩比较基准",
]
]
temp_df = temp_df.T.reset_index()
temp_df.columns = ["item", "value"]
return temp_df
def fund_individual_achievement_xq(
symbol: str = "000001", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-基金业绩
https://danjuanfunds.com/djapi/fundx/base/fund/achievement/675091
:param symbol: 基金代码
:type symbol: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 基金业绩
:rtype: pandas.DataFrame
"""
url = f"https://danjuanfunds.com/djapi/fundx/base/fund/achievement/{symbol}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
r = requests.get(url, headers=headers, timeout=timeout)
json_data = r.json()["data"]
combined_df = None
type_dict = {
"annual_performance_list": "年度业绩",
"stage_performance_list": "阶段业绩",
}
for k, v in type_dict.items():
temp_df = pd.DataFrame.from_dict(json_data[k], orient="columns")
temp_df["type"] = v
temp_df = temp_df[
[
"type",
"period_time",
"self_nav",
"self_max_draw_down",
"self_nav_rank",
]
]
temp_df.columns = [
"业绩类型",
"周期",
"本产品区间收益",
"本产品最大回撒",
"周期收益同类排名",
]
combined_df = pd.concat([combined_df, temp_df], ignore_index=True)
combined_df = combined_df.map(
lambda x: x if "%" not in str(x) else x.replace("%", "")
)
combined_df[["本产品区间收益", "本产品最大回撒"]] = combined_df[
["本产品区间收益", "本产品最大回撒"]
].astype(float)
return combined_df
def fund_individual_analysis_xq(
symbol: str = "000001", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-基金数据分析
https://danjuanfunds.com/djapi/fund/base/quote/data/index/analysis/675091
:param symbol: 基金代码
:type symbol: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 基金数据分析
:rtype: pandas.DataFrame
"""
url = f"https://danjuanfunds.com/djapi/fund/base/quote/data/index/analysis/{symbol}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
r = requests.get(url, headers=headers, timeout=timeout)
json_data = r.json()["data"]["index_data_list"]
temp_df = pd.json_normalize(json_data)
temp_df = temp_df[
[
"index_time_period",
"investment_cost_performance",
"risk_control",
"self_index.volatility_rank",
"self_index.sharpe_rank",
"self_index.max_draw_down",
]
]
temp_df.columns = [
"周期",
"较同类风险收益比",
"较同类抗风险波动",
"年化波动率",
"年化夏普比率",
"最大回撤",
]
temp_df = temp_df.map(lambda x: x if "%" not in str(x) else x.replace("%", ""))
temp_df[["年化波动率", "最大回撤"]] *= 100
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")
temp_df["最大回撤"] = pd.to_numeric(temp_df["最大回撤"], errors="coerce")
return temp_df
def fund_individual_profit_probability_xq(
symbol: str = "000001", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-盈利概率-历史任意时点买入,持有满 X 年,盈利概率 Y%
https://danjuanfunds.com/djapi/fundx/base/fund/profit/ratio/675091
:param symbol: 基金代码
:type symbol: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 盈利概率
:rtype: pandas.DataFrame
"""
url = f"https://danjuanfunds.com/djapi/fundx/base/fund/profit/ratio/{symbol}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
r = requests.get(url, headers=headers, timeout=timeout)
json_data = r.json()["data"]["data_list"]
temp_df = pd.DataFrame.from_dict(json_data, orient="columns")
temp_df = temp_df[
[
"holding_time",
"profit_ratio",
"average_income",
]
]
temp_df.columns = [
"持有时长",
"盈利概率",
"平均收益",
]
temp_df = temp_df.map(lambda x: x if "%" not in str(x) else x.replace("%", ""))
temp_df["盈利概率"] = pd.to_numeric(temp_df["盈利概率"], errors="coerce")
temp_df["平均收益"] = pd.to_numeric(temp_df["平均收益"], errors="coerce")
return temp_df
def fund_individual_detail_info_xq(
symbol: str = "000001", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-交易规则
https://danjuanfunds.com/djapi/fund/detail/675091
:param symbol: 基金代码
:type symbol: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 交易规则
:rtype: pandas.DataFrame
"""
url = f"https://danjuanfunds.com/djapi/fund/detail/{symbol}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
r = requests.get(url, headers=headers, timeout=timeout)
json_data = r.json()["data"]
combined_df = None
rate_type_dict = {
"declare_rate_table": "买入规则",
"withdraw_rate_table": "卖出规则",
"other_rate_table": "其他费用",
}
for k, v in rate_type_dict.items():
temp_df = pd.DataFrame.from_dict(json_data["fund_rates"][k], orient="columns")
temp_df["rate_type"] = v
temp_df = temp_df[
[
"rate_type",
"name",
"value",
]
]
temp_df.columns = [
"费用类型",
"条件或名称",
"费用",
]
combined_df = pd.concat(objs=[combined_df, temp_df], ignore_index=True)
combined_df["费用"] = pd.to_numeric(combined_df["费用"], errors="coerce")
return combined_df
def fund_individual_detail_hold_xq(
symbol: str = "002804", date: str = "20231231", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-持仓
https://danjuanfunds.com/rn/fund-detail/archive?id=103&code=002804
:param symbol: 基金代码
:type symbol: str
:param date: 财报日期
:type date: str
:param timeout: choice of None or a positive float number
:type timeout: float
:return: 雪球基金-持仓
:rtype: pandas.DataFrame
"""
url = "https://danjuanfunds.com/djapi/fundx/base/fund/record/asset/percent"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.149 Safari/537.36"
}
params = {
"fund_code": f"{symbol}",
"report_date": f"{'-'.join([date[:4], date[4:6], date[6:]])}",
}
r = requests.get(url, headers=headers, params=params, timeout=timeout)
data_json = r.json()
temp_df = pd.DataFrame.from_dict(data_json["data"]["chart_list"], orient="columns")
temp_df = temp_df[
[
"type_desc",
"percent",
]
]
temp_df.columns = [
"资产类型",
"仓位占比",
]
temp_df["仓位占比"] = pd.to_numeric(temp_df["仓位占比"], errors="coerce")
return temp_df
if __name__ == "__main__":
fund_individual_basic_info_xq_df = fund_individual_basic_info_xq(symbol="000005")
print(fund_individual_basic_info_xq_df)
fund_individual_achievement_xq_df = fund_individual_achievement_xq(symbol="000001")
print(fund_individual_achievement_xq_df)
fund_individual_analysis_xq_df = fund_individual_analysis_xq(symbol="000001")
print(fund_individual_analysis_xq_df)
fund_individual_profit_probability_xq_df = fund_individual_profit_probability_xq(
symbol="000001"
)
print(fund_individual_profit_probability_xq_df)
fund_individual_detail_info_xq_df = fund_individual_detail_info_xq(symbol="000001")
print(fund_individual_detail_info_xq_df)
fund_individual_detail_hold_xq_df = fund_individual_detail_hold_xq(
symbol="002804", date="20231231"
)
print(fund_individual_detail_hold_xq_df)