refraction-ray / xalpha

基金投资管理回测引擎
MIT License
2.02k stars 437 forks source link

请问是否有api 可以一次获得所有基金编码? #95

Closed bobbypiggy closed 3 years ago

bobbypiggy commented 3 years ago

1.Akshare可以通过api来获得所有基金的编码: import akshare as ak fund_em_fund_name_df = ak.fund_em_fund_name() print(fund_em_fund_name_df)

2.tushare用类似api获得场内或者场外基金所有编码: df = pro.fund_basic(market='E')

3.xalpha我查询了一下api手册,似乎没有找到,只能输入基金编码一个个的查询。tushare和Akshare都有不方便的地方,比如tushare不能查询到指数基金的信息。Akshare我抽查了一下,似乎‘中证红利指数0000922’编码也没有;

原因是我今天计划从tushare选择了2800多条基金,来测试xalpha,早上看有跑出一些异常,抽空我再分析一下: 45 #计算标的和基准沪深300的年化收益率 ---> 46 total_annual_returns = round(fund_info.total_annualized_returns()100, 4) 47 bench_mark_returns = round(fund_info.benchmark_annualized_returns()100, 4)

IndexError: single positional indexer is out-of-bounds

bobbypiggy commented 3 years ago

12%|█▏ | 340/2848 [31:30<3:35:01, 5.14s/it][fund] 004505 12%|█▏ | 341/2848 [31:35<3:28:55, 5.00s/it][fund] 004532 12%|█▏ | 342/2848 [31:40<3:33:59, 5.12s/it][fund] 002319 12%|█▏ | 343/2848 [31:45<3:26:56, 4.96s/it][fund] 004351 12%|█▏ | 344/2848 [31:48<3:10:30, 4.56s/it][fund] 001856 12%|█▏ | 345/2848 [31:53<3:06:36, 4.47s/it][fund] 004533 12%|█▏ | 346/2848 [31:57<3:04:02, 4.41s/it][fund] 001879 12%|█▏ | 347/2848 [32:02<3:09:29, 4.55s/it][fund] 004604 12%|█▏ | 348/2848 [32:06<3:01:45, 4.36s/it][fund] 004605 12%|█▏ | 349/2848 [32:09<2:55:25, 4.21s/it][fund] 004050 12%|█▏ | 350/2848 [32:13<2:50:31, 4.10s/it][fund] 004051 12%|█▏ | 350/2848 [32:15<3:50:17, 5.53s/it]

IndexError Traceback (most recent call last)

in 44 45 #计算标的和基准沪深300的年化收益率 ---> 46 total_annual_returns = round(fund_info.total_annualized_returns()*100, 4) 47 bench_mark_returns = round(fund_info.benchmark_annualized_returns()*100, 4) 48
bobbypiggy commented 3 years ago
4050 006229.OF 中欧医疗创新C 中欧基金 中国工商银行 股票型 20190228
4051 006228.OF 中欧医疗创新A 中欧基金 中国工商银行 股票型 20190228
4052 006522.OF 财通新兴蓝筹A 财通基金 中国工商银行 混合型 20190228

似乎是测试到4052这支出了问题,晚上我再细看下。

refraction-ray commented 3 years ago

想要获取场外全部基金代码可以试试 xa.misc.get_fund_list("all"),基本上是全的。

至于具体基金的报错问题,可以有了更详细的信息我们再讨论

bobbypiggy commented 3 years ago

好,谢谢,我先仔细分析一下再讨论。

bobbypiggy commented 3 years ago

查出来了,是这支基金有问题:

fund_info = xa.fundinfo('004051') print(fund_info.info()) print(fund_info.price.shape[0])

fund name: 华夏新锦升混合C fund code: 004051 fund purchase fee: 0% fund redemption fee info: ['小于7天', '1.50%', '大于等于7天,小于30天', '0.50%', '大于等于30天', '0.00%'] 1

天天基金网http://fundf10.eastmoney.com/jjjz_004051.html 显示交易状态“交易状态:封闭期 ”, 所以查询不到数据,进入下面到处理出异常了。 那我增加一点异常保护好了。

bobbypiggy commented 3 years ago

修改后的测试源码,读入tushare后的数据调用xalpha测试: df_out = pd.read_csv("fund_out_20210206.csv")

将trade_date一列设置为time index

df_out['found_date'] = pd.to_datetime(df_out['found_date'], format="%Y%m%d")

重新设置index

df_out = df_out.set_index(['found_date']) df_out['ts_code'] = df_out['ts_code'].str.strip('.OF')

df_report = pd.DataFrame(columns=('基金名称','基金代码','基金类型', '累计收益率', '年化收益率', '基准年化收益率','年化波动率', '夏普比率', '信息比率', 'alpha', 'beta'))

start_time = '2018-03-17' end_time = '2021-01-01'

except_list = ['003244',"003245"]

for i in tqdm(range(df_out.shape[0])):

遍历基金编码

fund_num = df_out['ts_code'].iloc[i]

if fund_num in except_list:
    continue

#获得基金基本信息,即标的
fund_temp = df_out.iloc[i]

if fund_temp['fund_type'] =="指数型":
    fund_info = xa.indexinfo(fund_num)
else:
    fund_info = xa.fundinfo(fund_num)

print("[fund]:", fund_num, fund_info.name)

if fund_info.price.shape[0] < 10:
    print("[Abnormal] fund{}, {} has no data now.".format(fund_num, fund_info.name))
    continue

# 按照每周三定额定投1000,生成交易单
auto = xa.policy.scheduled(fund_info, 1000, pd.date_range(start_time, end_time,                                    freq='W-THU'))

# 按上面的策略单子交易下
fund_final = xa.trade(fund_info, auto.status)

# 设定比较基准为沪深300指数,以便于接下来更多量化分析
fund_info.bcmkset(xa.indexinfo('SH000300'), start = start_time) 

#计算整体累计收益率
xirrrate = round(fund_final.xirrrate(end_time)*100, 4)

#计算标的和基准沪深300的年化收益率
total_annual_returns = round(fund_info.total_annualized_returns()*100, 4)
bench_mark_returns = round(fund_info.benchmark_annualized_returns()*100, 4) 

# 计算截止目前的年化波动率 
volatility = round(fund_info.algorithm_volatility(), 4)

#计算夏普比率
sharp_ratio = round(fund_info.sharpe(end_time), 4)

#计算最大回撤
max_drawdown = round(fund_info.max_drawdown(end_time)[2]*100, 4)

#计算信息比率
information_ratio = round(fund_info.information_ratio(end_time), 4)

#计算alpha, beta
alpha = round(fund_info.alpha(), 4)
beta = round(fund_info.beta(), 4)

df_line = pd.Series(
        {
            "基金名称": fund_info.name,
            "基金代码": "\t"+fund_num.zfill(6),
            "基金类型": fund_temp['fund_type'],
            "累计收益率": xirrrate,
            '年化收益率': total_annual_returns,
            '基准年化收益率': bench_mark_returns,
            '年化波动率': volatility,
            '夏普比率': sharp_ratio,
            '最大回撤': max_drawdown,
            '信息比率': information_ratio,
            'alpha': alpha,
            'beta': beta,
        }
      ) 

#按照行进行插入合并
df_report = df_report.append(df_line, ignore_index=True)
print("cal succ...", fund_num, fund_info.name)

df_report.to_csv("analysis-fund.csv")

bobbypiggy commented 3 years ago

看见了版主在去年的答复:

refraction-ray commented on 22 May 2020 跟进一下获取相关基金列表的这个问题。现在我在 misc 里有两个函数。一个是 xa.misc.get_ttjj_suggestion("基建") 会返回一个关键字有基建的基金及元信息的字典。 另一个是 xa.misc.get_fund_list("hh") 自变量可以是 hh,zq, zs, gp, qdii, fof 分别对应混合,债券,指数,股票型的全部基金列表。具体接口怎么改善,怎么将这些返回基金列表类的功能并入主线,我还是没想好。