Skip to content

Commit

Permalink
Dev (#4387)
Browse files Browse the repository at this point in the history
* add interfaces for individual fund by using data from xueqiu/danjuanfunds (#4386)

Co-authored-by: none2003 <[email protected]>

* add version 1.12.9

* add fund_individual_basic_info_xq

* fix get_receipt

* fix reits_realtime_em

* update date

* add fund_individual_basic_info_xq

---------

Co-authored-by: none2003 <[email protected]>
Co-authored-by: none2003 <[email protected]>
  • Loading branch information
3 people authored Jan 3, 2024
1 parent 063988c commit 17e1bec
Show file tree
Hide file tree
Showing 8 changed files with 690 additions and 22 deletions.
14 changes: 13 additions & 1 deletion akshare/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2621,9 +2621,10 @@
1.12.6 fix: fix fund_open_fund_info_em interface
1.12.7 fix: fix option_gfex_daily interface
1.12.8 fix: fix fund_open_fund_info_em interface
1.12.9 add: add fund_individual_basic_info_xq interface
"""

__version__ = "1.12.8"
__version__ = "1.12.9"
__author__ = "AKFamily"

import sys
Expand Down Expand Up @@ -5039,3 +5040,14 @@
get_ine_daily,
get_gfex_daily,
)

"""
雪球基金数据
"""
from akshare.fund.fund_xq import (
fund_individual_basic_info_xq,
fund_individual_achievement_xq,
fund_individual_analysis_xq,
fund_individual_profit_probability_xq,
fund_individual_detail_info_xq,
)
303 changes: 303 additions & 0 deletions akshare/fund/fund_xq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/01/03 15:40
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 = temp_df[
[
"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",
]
]
temp_df.columns = [
"基金代码",
"基金名称",
"基金全称",
"成立时间",
"最新规模",
"基金公司",
"基金经理",
"托管银行",
"基金类型",
"评级机构",
"基金评级",
"投资策略",
"投资目标",
"业绩比较基准",
]

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", indicator: str = "交易规则", timeout: float = None
) -> pd.DataFrame:
"""
雪球基金-详细信息
https://danjuanfunds.com/djapi/fund/detail/675091
:param symbol: 基金代码
:type symbol: str
:param indicator: 信息类型; choice of {"交易规则", "持仓资产比例"}
: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"]

if indicator == "持仓资产比例":
temp_df = pd.DataFrame.from_dict(
json_data["fund_position"]["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
elif indicator == "交易规则":
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([combined_df, temp_df], ignore_index=True)
combined_df['费用'] = pd.to_numeric(combined_df['费用'], errors="coerce")
return combined_df


if __name__ == "__main__":
fund_individual_basic_info_xq_df = fund_individual_basic_info_xq()
print(fund_individual_basic_info_xq_df)

fund_individual_achievement_xq_df = fund_individual_achievement_xq()
print(fund_individual_achievement_xq_df)

fund_individual_analysis_xq_df = fund_individual_analysis_xq()
print(fund_individual_analysis_xq_df)

fund_individual_profit_probability_xq_df = fund_individual_profit_probability_xq()
print(fund_individual_profit_probability_xq_df)

fund_individual_detail_info_xq_df = fund_individual_detail_info_xq(indicator="交易规则")
print(fund_individual_detail_info_xq_df)

fund_individual_detail_info_xq_df = fund_individual_detail_info_xq(indicator="持仓资产比例")
print(fund_individual_detail_info_xq_df)
19 changes: 11 additions & 8 deletions akshare/futures/receipt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/6/21 18:00
Date: 2024/1/3 17:00
Desc: 每日注册仓单数据
大连商品交易所, 上海期货交易所, 郑州商品交易所, 广州期货交易所
"""
Expand Down Expand Up @@ -77,7 +77,7 @@ def get_shfe_receipt_1(date: str = None, vars_list: List = cons.contract_symbols
:rtype: pandas.DataFrame
"""
if not isinstance(vars_list, list):
return warnings.warn(f"symbol_list: 必须是列表")
raise warnings.warn(f"symbol_list: 必须是列表")
date = cons.convert_date(date).strftime('%Y%m%d') if date is not None else datetime.date.today()
if date not in calendar:
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
Expand Down Expand Up @@ -128,10 +128,10 @@ def get_shfe_receipt_2(date: str = None, vars_list: List = cons.contract_symbols
:rtype: pandas.DataFrame
"""
if not isinstance(vars_list, list):
return warnings.warn(f"symbol_list: 必须是列表")
raise warnings.warn(f"symbol_list: 必须是列表")
date = cons.convert_date(date).strftime('%Y%m%d') if date is not None else datetime.date.today()
if date not in calendar:
warnings.warn('%s非交易日' % date.strftime('%Y%m%d'))
warnings.warn('%s 非交易日' % date.strftime('%Y%m%d'))
return None
url = cons.SHFE_RECEIPT_URL_2 % date
r = requests_link(url, encoding='utf-8', headers=cons.shfe_headers)
Expand Down Expand Up @@ -389,15 +389,18 @@ def get_gfex_receipt(date: str = None, vars_list: List = cons.contract_symbols)
result_df = result_df[[
'var', 'receipt', 'receipt_chg', 'date'
]]
result_df.set_index(['var'], inplace=True)
result_df = result_df.loc[vars_list, :]
result_df.reset_index(inplace=True)
return result_df


def get_receipt(start_day: str = None, end_day: str = None, vars_list: List = cons.contract_symbols):
"""
大宗商品-注册仓单数据
:param start_day: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
:param start_day: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date 对象 为空时为当天
:type start_day: str
:param end_day: 结束数据 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
:param end_day: 结束数据 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date 对象 为空时为当天
:type end_day: str
:param vars_list: 合约品种如 RB、AL 等列表为空时为所有商品
:type vars_list: str
Expand All @@ -412,7 +415,7 @@ def get_receipt(start_day: str = None, end_day: str = None, vars_list: List = co
records = pd.DataFrame()
while start_day <= end_day:
if start_day.strftime('%Y%m%d') not in calendar:
warnings.warn(f"{start_day.strftime('%Y%m%d')}非交易日")
warnings.warn(f"{start_day.strftime('%Y%m%d')} 非交易日")
else:
print(start_day)
for market, market_vars in cons.market_exchange_symbols.items():
Expand Down Expand Up @@ -458,5 +461,5 @@ def get_receipt(start_day: str = None, end_day: str = None, vars_list: List = co


if __name__ == '__main__':
get_receipt_df = get_receipt(start_day='20231205', end_day='20231210')
get_receipt_df = get_receipt(start_day='20240103', end_day='20240103', vars_list=['SI'])
print(get_receipt_df)
Loading

0 comments on commit 17e1bec

Please sign in to comment.