Skip to content
Merged

Dev #60

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
Release History
===============

![logo](https://adata.1nchaos.com/favicon.ico)[AData](https://github.com/1nchaos/adata)
![logo](https://adata.30006124.xyz/favicon.ico)[AData](https://github.com/1nchaos/adata)

master
------
开放、纯净、持续

专注股票量化数据,为Ai(爱)发电,向阳而生。

2.0.0b0 (2024-04-17)
------------------
1. 新增:基金ETF行情接口。


1.2.4 (2024-02-02)
------------------
1. 修复:修复概念返回为空bug。
Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ print(res_df)

**注:**

- v0.0.027b0 及以上版本支持;
- proxy_url: 获取代理Ip的链接;ip和proxy_url方式选择其一;
- 每次请求获取一次,为节省ip资源建议使用自建的代理池。

Expand Down Expand Up @@ -177,10 +176,19 @@ print(res_df)

### (2)基金-ETF

| 数据 | API | 说明 | 备注 |
| -------------- | ---------------------------------------- | ------------------------------ | ------------------------------------------------------------ |
| ETF(场内) | fund.info.all_etf_exchange_traded_info() | 获取所有A股市场的ETF信息 | 来源:1. [东方财富](http://quote.eastmoney.com/center/gridlist.html#fund_etf) |
| 其它数据排期中 | TODO | 若您有相关资源可以一起参与贡献 | |
#### 1. 基本信息

| 数据 | API | 说明 | 备注 |
| ----------- | ---------------------------------------- | ------------------------ | ------------------------------------------------------------ |
| ETF(场内) | fund.info.all_etf_exchange_traded_info() | 获取所有A股市场的ETF信息 | 来源:1. [东方财富](http://quote.eastmoney.com/center/gridlist.html#fund_etf) |

#### 2. 行情信息

| 数据 | API | 说明 | 备注 |
| ------- | ------------------------------------ | -------------------------------- | ---------------------------------------- |
| ETF行情 | fund.market.get_market_etf() | 获取ETF的行情信息-日、周、月 k线 | 来源:[同花顺](https://m.10jqka.com.cn/) |
| | fund.market.get_market_etf_min() | 获取ETF的行情-当日分时 | |
| | fund.market.get_market_etf_current() | 获取当前的ETF行情 | 实时行情 |

### (3)债券-Bond

Expand Down Expand Up @@ -226,7 +234,7 @@ print(res_df)
| ---- | ------ | ---- | ------------ | ------------------------------ |
| ✅ | 0.x.x | 股票 | 2023-04-05 ~ | 预览版本 |
| ✅ ️ | 1.x.x | 股票 | 2023-10-01 | 中国Ai股 |
| ☑️ | 2.x.x | 基金、债券 | 2024-01-01 | 场内可交易基金:ETF、可转债 |
| ☑️ | 2.x.x | 基金、债券 | 开发中 | 场内可交易基金:ETF、可转债 |
| ☑️ | 3.x.x | xxx | 排期中 | |

## 六、理念
Expand Down Expand Up @@ -273,5 +281,5 @@ print(res_df)
</p>

- 添加wx好友,备注:Adata量化进交流群;
- 群最近建立人较少,意在提供一个交流的平台;
- 一起保卫3000点
- 群最近建立,意在提供一个交流的平台,欢迎讨论交流
- 一起保卫3000点直到突破6124点
4 changes: 2 additions & 2 deletions adata/__version__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-

VERSION = (1, 2, 4)
PRERELEASE = None # alpha, beta or rc
VERSION = (2, 0, 0)
PRERELEASE = 'beta' # alpha, beta or rc
REVISION = None


Expand Down
2 changes: 2 additions & 0 deletions adata/fund/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
"""

from adata.fund.info import info
from adata.fund.market import market


class Fund(object):

def __init__(self) -> None:
self.info = info
self.market = market


fund = Fund()
10 changes: 10 additions & 0 deletions adata/fund/market/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,13 @@
@time: 2023/6/5
@log: change log
"""
from adata.fund.market.etf_market import ETFMarket


class Market(ETFMarket):

def __init__(self) -> None:
super().__init__()


market = Market()
41 changes: 40 additions & 1 deletion adata/fund/market/etf_market.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
# -*- coding: utf-8 -*-
"""
@desc:
@desc: ETF 行情
@author: 1nchaos
@time:2023/4/5
@log:
"""
from adata.fund.market.etf_market_ths import ETFMarketThs


class ETFMarket(object):
"""ETF 行情"""

def __init__(self) -> None:
super().__init__()
self.ths = ETFMarketThs()

def get_market_etf(self, fund_code: str = '512880', k_type: int = 1, start_date='', end_date=''):
"""
获取ETF的行情
:param start_date: 开始时间
:param end_date: 结束时间
:param fund_code: ETF代码
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:return: k线行情数据 [日期,开,高,低,收,成交量,成交额]
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000
成交量:股 820953530 821万手
成交额:元 16959251000.000 169.6亿
"""
return self.ths.get_market_etf_ths(fund_code, k_type, start_date, end_date)

def get_market_etf_min(self, fund_code='512880'):
"""
获取etf行情当日分时
:param fund_code: ETF代码
:return 时间,现价,成交额(元),均价,成交量(股) 涨跌额,涨跌幅
'index_code', 'trade_time', 'price', 'change', 'change_pct', 'volume', 'pre_close', 'amount'
"""
return self.ths.get_market_etf_min_ths(fund_code)

def get_market_etf_current(self, fund_code: str = '512880', k_type: int = 1):
"""
获取同花顺当前的概念行情

:param fund_code: ETF代码
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:return: k线行情数据 [ETF代码,交易时间,交易日期,开,高,低,当前价格,成交量,成交额]
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000,存储芯片
k: 1, 7, 8, 9, 11, 13, 19, name
成交量:股 820953530 821万手
成交额:元 16959251000.000 169.6亿
"""
return self.ths.get_market_etf_current_ths(fund_code, k_type)
16 changes: 16 additions & 0 deletions adata/fund/market/etf_market_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
"""
@summary: etf 行情
"""


class ETFMarketTemplate(object):
"""
etf 行情
"""
_MARKET_COLUMNS = ['index_code', 'trade_time', 'trade_date', 'open', 'high', 'low', 'close', 'volume', 'amount',
'change', 'change_pct']
_MARKET_ETF_MIN_COLUMNS = ['index_code', 'trade_time', 'trade_date', 'price', 'avg_price', 'volume', 'amount',
'change', 'change_pct']
_MARKET_ETF_CURRENT_COLUMNS = ['index_code', 'trade_time', 'trade_date', 'open', 'high', 'low', 'price', 'volume',
'amount', 'change', 'change_pct']
155 changes: 155 additions & 0 deletions adata/fund/market/etf_market_ths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
"""
@summary: ETF 行情
https://d.10jqka.com.cn/v6/line/hs_512880/11/last360.js

@author: 1nchaos
@date: 2023/3/30 16:17
"""
import json

import numpy as np
import pandas as pd

from adata.common.base.base_ths import BaseThs
from adata.common.exception.exception_msg import *
from adata.fund.market.etf_market_template import ETFMarketTemplate


class ETFMarketThs(BaseThs, ETFMarketTemplate):
"""
股票概念 行情
"""

def get_market_etf_ths(self, fund_code: str = '512880', k_type: int = 1, start_date='', end_date=''):
"""
获取同花顺的ETF的行情
app: https://d.10jqka.com.cn/v6/line/hs_512880/01/last36000.js
00 日k不复权;01日k前复权;02日k后复权;11周k前复权;21月k前复权
:param start_date: 开始时间
:param end_date: 结束时间
:param fund_code: ETF代码
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:return: k线行情数据 [日期,开,高,低,收,成交量,成交额]
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000
成交量:股 820953530 821万手
成交额:元 16959251000.000 169.6亿
"""
# 0.参数校验
# 1.接口 url
api_url = f"http://d.10jqka.com.cn/v6/line/hs_{fund_code}/{k_type - 1}1/last36000.js"
# 同花顺可能ip限制,降低请求次数
text = self._get_text(api_url, fund_code)
if THS_IP_LIMIT_RES in text:
return Exception(THS_IP_LIMIT_MSG)
result_text = text[text.index('{'):-1]
data_list = json.loads(result_text)['data'].split(';')
data = []
for d in data_list:
data.append(str(d).split(',')[0:7])
result_df = pd.DataFrame(data=data, columns=['trade_date', 'open', 'high', 'low', 'close', 'volume', 'amount'])
result_df['index_code'] = fund_code
result_df['trade_time'] = pd.to_datetime(result_df['trade_date']).dt.strftime('%Y-%m-%d %H:%M:%S')
result_df['trade_date'] = pd.to_datetime(result_df['trade_date'], format='%Y%m%d').dt.strftime('%Y-%m-%d')
result_df['close'] = result_df['close'].astype(float)
result_df['change'] = result_df['close'] - result_df['close'].shift(1)
result_df['change_pct'] = result_df['change'] / result_df['close'].shift(1) * 100

# 3. 清洗数据
result_df = result_df.round(3)
result_df['close'] = result_df['close'].apply(lambda x: format(x, '.3f'))
result_df.replace('--', None, inplace=True)
result_df.replace('', None, inplace=True)
result_df.replace(np.nan, None, inplace=True)
# 4. 时间范围
start_date = start_date if start_date else '1990-01-01'
end_date = end_date if end_date else '2099-01-01'
result_df = result_df[(result_df['trade_date'] >= start_date) & (result_df['trade_date'] <= end_date)]
return result_df[self._MARKET_COLUMNS]

def get_market_etf_min_ths(self, fund_code='512880'):
"""
获取etf行情当日分时
web: https://d.10jqka.com.cn/v6/time/hs_512880/last.js
0930,958.901,74456973,36.807,2022925; "pre": "960.374",
:param fund_code: ETF代码
:return 时间,现价,成交额(元),均价,成交量(股) 涨跌额,涨跌幅
'index_code', 'trade_time', 'price', 'change', 'change_pct', 'volume', 'pre_close', 'amount'
"""
# 0.参数校验
# 1.接口 url
api_url = f"http://d.10jqka.com.cn/v6/time/hs_{fund_code}/last.js"
text = self._get_text(api_url, fund_code)
if THS_IP_LIMIT_RES in text:
return Exception(THS_IP_LIMIT_MSG)
# 2. 解析数据
result_json = json.loads(text[text.index('{'):-1])[f"hs_{fund_code}"]
pre_price = result_json['pre']
trade_date = result_json['date']
data_list = result_json['data'].split(';')
data = []
for d in data_list:
data.append(str(d).split(','))
# 3. 封装数据
result_df = pd.DataFrame(data=data, columns=['trade_time', 'price', 'amount', 'avg_price', 'volume'])
result_df['index_code'] = fund_code
result_df['trade_time'] = trade_date + result_df['trade_time']
result_df['trade_date'] = pd.to_datetime(trade_date, format='%Y%m%d').strftime('%Y-%m-%d')
result_df['trade_time'] = pd.to_datetime(result_df['trade_time'], format='%Y%m%d%H%M').dt.strftime(
'%Y-%m-%d %H:%M:%S')
result_df['price'] = result_df['price']
result_df['change'] = result_df['price'].astype(float) - float(pre_price)
result_df['change_pct'] = result_df['change'] / float(pre_price) * 100
result_df.replace('--', None, inplace=True)
result_df.replace('', None, inplace=True)
result_df.replace(np.nan, None, inplace=True)
return result_df[self._MARKET_ETF_MIN_COLUMNS]

def get_market_etf_current_ths(self, fund_code: str = '512880', k_type: int = 1):
"""
获取同花顺当前的概念行情
web: https://d.10jqka.com.cn/v6/line/hs_512880/01/today.js
quotebridge_v6_line_hs_512880_01_today({
"hs_512880": { "1": "20240417", "7": "0.810", "8": "0.827", "9": "0.806","11": "0.825", "13": 1336243640,
"19": "1092886150.000", "74": "","1968584": "3.727","66": "","open": 1,"dt": "1751","name": "\u8bc1\u5238ETF",
"marketType": "" }})

:param fund_code: ETF代码
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
:return: k线行情数据 [ETF代码,交易时间,交易日期,开,高,低,当前价格,成交量,成交额]
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000,存储芯片
k: 1, 7, 8, 9, 11, 13, 19, name
成交量:股 820953530 821万手
成交额:元 16959251000.000 169.6亿
"""
# 0.参数校验
# 1.接口 url
api_url = f"http://d.10jqka.com.cn/v6/line/hs_{fund_code}/{k_type - 1}1/today.js"
# 同花顺可能ip限制,降低请求次数
text = self._get_text(api_url, fund_code)
if THS_IP_LIMIT_RES in text:
return Exception(THS_IP_LIMIT_MSG)
result_text = text[text.index('{'):-1]
data_list = [json.loads(result_text)[f"hs_{fund_code}"]]
rename = {'1': 'trade_date', '7': 'open', '8': 'high', '9': 'low', '11': 'price', '13': 'volume',
'19': 'amount', 'open': 'status'}
result_df = pd.DataFrame(data=data_list).rename(columns=rename)
result_df['trade_time'] = result_df['trade_date'] + result_df['dt']
result_df['trade_time'] = pd.to_datetime(result_df['trade_time'], format='%Y%m%d%H%M').dt.strftime(
'%Y-%m-%d %H:%M:%S')
columns = ['trade_time', 'trade_date', 'open', 'high', 'low', 'price', 'volume', 'amount']
result_df = result_df[columns]
result_df['index_code'] = fund_code
result_df['trade_date'] = pd.to_datetime(result_df['trade_date'], format='%Y%m%d').dt.strftime('%Y-%m-%d')
result_df['change'] = None
result_df['change_pct'] = None
return result_df[self._MARKET_ETF_CURRENT_COLUMNS]


if __name__ == '__main__':
print(ETFMarketThs().get_market_etf_ths(fund_code='512880', start_date='2024-01-01'))
print(ETFMarketThs().get_market_etf_ths(fund_code='159841', start_date='2024-01-01'))
print(ETFMarketThs().get_market_etf_min_ths(fund_code='512880'))
print(ETFMarketThs().get_market_etf_min_ths(fund_code='159841'))
print(ETFMarketThs().get_market_etf_current_ths(fund_code='512880'))
print(ETFMarketThs().get_market_etf_current_ths(fund_code='513800'))
2 changes: 1 addition & 1 deletion docs/web.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

免费开源A股量化数据库; 专注A股,专注量化,向阳而生; 开放、纯净、持续、为Ai(爱)发电。为个人量化交易而生,保卫3000点......【股票数据,股票行情数据,股票量化数据,k线行情数据,股票概念数据】

## 官网:[AData](https://adata.1nchaos.com/)
## 官网:[AData](https://adata.30006124.xyz/)
18 changes: 18 additions & 0 deletions tests/adata_test/fund/fund_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ def test_all_etf_exchange_traded_info(self):
print(df)
self.assertEqual(True, len(df) > 200)

def test_get_market_etf(self):
print("开始测试:get_market_etf")
df = adata.fund.market.get_market_etf()
print(df)
self.assertEqual(True, len(df) > 200)

def test_get_market_etf_min(self):
print("开始测试:get_market_etf_min")
df = adata.fund.market.get_market_etf_min()
print(df)
self.assertEqual(True, len(df) > 120)

def test_get_market_etf_current(self):
print("开始测试:get_market_etf_current")
df = adata.fund.market.get_market_etf_current()
print(df)
self.assertEqual(True, len(df) == 1)


if __name__ == '__main__':
unittest.main()