Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #73

Merged
merged 11 commits into from
Jul 1, 2024
Merged

Dev #73

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
5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ master

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

2.2.0 (2024-07-01)
------------------
1. 新增:股票:资金流接口。
2. 修复:股票:分红数据api。

2.1.0 (2024-05-05)
------------------
1. 新增:舆情:人气榜单接口。
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ print(res_df)
| 指数行情 | stock.market.get_market_index() | 获取指数的行情信息-日、周、月 k线 | |
| | stock.market.get_market_index_min() | 获取指数的行情-当日分时 | |
| | stock.market.get_market_index_current() | 获取当前的指数行情 | 实时行情 |
| 个股资金流 | stock.market.get_capital_flow_min() | 获取单个股票的今日分时资金流向 | 最新实时数据 |
| | stock.market.get_capital_flow() | 获取单个股票的资金流向 | 历史日度数据 |

**注:概念和指数从本质来看是一样的,所以相关的接口和返回结果是一致的,概念是各个厂商自定义的指数,指数是官方或者权威机构定义的,都是一揽子股票的组合。**

Expand Down Expand Up @@ -279,10 +281,10 @@ print(res_df)

## 欢迎进行交流
<p align="center">
<a href="https://adata.30006124.xyz/" target="_blank">
<a href="https://adata.30006124.xyz/wx.html" target="_blank">
<img width="180" src="./docs/wx.jpg" alt="logo">
</a>
<a href="https://adata.30006124.xyz/" target="_blank">
<a href="https://mp.weixin.qq.com/s/ZQMXgxIYKtfjiPQK-p-aXg" target="_blank">
<img width="400" src="./docs/xyhcl-gzh.png" alt="logo">
</a>
</p>
Expand Down
2 changes: 1 addition & 1 deletion adata/__version__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

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

Expand Down
2 changes: 1 addition & 1 deletion adata/common/utils/code_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
@desc: readme
@author: yinchao
@author: 1nchaos
@time: 2023/12/4
@log: change log
"""
Expand Down
25 changes: 25 additions & 0 deletions adata/common/utils/unit_conver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
@desc: readme
@author: 1nchaos
@time: 2024/7/1
@log: change log
"""

import re


def convert_to_yuan(input_dict):
"""
将字典中特定字段的值从带'亿'或'万'的字符串转换为以元为单位的浮点数。

:param input_dict: 包含待转换值的字典
"""
unit_multipliers = {'亿': 100000000, '万': 10000}

for key, value in input_dict.items():
if isinstance(value, str) and any(unit in value for unit in unit_multipliers.keys()):
number, unit = re.findall(r'([-+]?\d*\.\d+|\d+)([亿万]?)', value)[0]
number = float(number)
input_dict[key] = number * unit_multipliers[unit]
return input_dict
59 changes: 59 additions & 0 deletions adata/sentiment/alist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
"""
@desc: 龙虎榜单

https://data.eastmoney.com/stock/tradedetail.html

@author: 1nchaos
@time: 2024/5/29
@log: change log
"""
import datetime
import json

import pandas as pd

from adata.common.base.base_ths import BaseThs
from adata.common.utils import requests


class AList(BaseThs):
"""龙虎榜单"""

# 东方财富人气榜
def list_a_list_daily(self, report_date=None):
"""
每日龙虎榜,默认为当天
http://guba.eastmoney.com/rank/
:param report_date: 报告日期 格式:YYYY-MM-DD
"""
if report_date is None:
report_date = datetime.datetime.now().strftime("%Y-%m-%d")
# 1.url
url = f"https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery1123047223270591945665_1716975719487&sortColumns=SECURITY_CODE,TRADE_DATE&sortTypes=1,-1&pageSize=500&pageNumber=1&reportName=RPT_DAILYBILLBOARD_DETAILSNEW&columns=SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,TRADE_DATE,EXPLAIN,CLOSE_PRICE,CHANGE_RATE,BILLBOARD_NET_AMT,BILLBOARD_BUY_AMT,BILLBOARD_SELL_AMT,BILLBOARD_DEAL_AMT,ACCUM_AMOUNT,DEAL_NET_RATIO,DEAL_AMOUNT_RATIO,TURNOVERRATE,FREE_MARKET_CAP,EXPLANATION,D1_CLOSE_ADJCHRATE,D2_CLOSE_ADJCHRATE,D5_CLOSE_ADJCHRATE,D10_CLOSE_ADJCHRATE,SECURITY_TYPE_CODE&source=WEB&client=WEB&filter=(TRADE_DATE<='{report_date}')(TRADE_DATE>='{report_date}')"

# 2. 请求数据
text = requests.request(method='post', url=url).text
res = json.loads(text[text.index('{'):-2])
df = pd.DataFrame(res['result']["data"])

# 3. 解析封装数据 TODO
rename = {'f2': 'price', 'f3': 'change_pct', 'f12': 'stock_code', 'f14': 'short_name', }
rank_df = pd.rename(columns=rename)
rank_df["change_pct"] = pd.to_numeric(rank_df["change_pct"], errors="coerce")
rank_df["price"] = pd.to_numeric(rank_df["price"], errors="coerce")
rank_df["change"] = rank_df["price"] * rank_df["change_pct"] / 100
rank_df["rank"] = range(1, len(rank_df) + 1)
return rank_df[["rank", "stock_code", "short_name", "price", "change", "change_pct"]]

def get_a_list(self, stock_code, report_date=None):
"""
获取单个龙虎榜的数据,买5和卖5
https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112307421020653512591_1716975849191&reportName=RPT_BILLBOARD_DAILYDETAILSBUY&columns=ALL&filter=(TRADE_DATE%3D%272024-05-21%27)(SECURITY_CODE%3D%22000070%22)&pageNumber=1&pageSize=50&sortTypes=-1&sortColumns=BUY&source=WEB&client=WEB&_=1716975849193
https://data.eastmoney.com/stock/tradedetail.html
"""
pass


if __name__ == '__main__':
AList().list_a_list_daily()
2 changes: 1 addition & 1 deletion adata/sentiment/hot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
@desc: 热点榜单 TODO
@desc: 热点榜单

同花顺热点榜单
https://eq.10jqka.com.cn/frontend/thsTopRank/index.html?fontzoom=no&client_userid=ceZLR&share_hxapp=gsc&share_action=webpage_share.hot_list_1714369375634&back_source=wxhy#/
Expand Down
2 changes: 1 addition & 1 deletion adata/stock/info/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
@time: 2023/3/28
@log: change log
"""
from adata.stock.info.stock_code import StockCode
from adata.stock.info.concept.stock_concept import StockConcept
from adata.stock.info.stock_code import StockCode
from adata.stock.info.stock_index import StockIndex
from adata.stock.info.stock_info import StockInfo
from adata.stock.info.trade_calendar import TradeCalendar
Expand Down
5 changes: 3 additions & 2 deletions adata/stock/market/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
@time: 2023/3/29
@log: change log
"""
from adata.stock.market.capital_flow import StockCapitalFlow
from adata.stock.market.concepth_market import StockMarketConcept
from adata.stock.market.index_market.market_index import StockMarketIndex
from adata.stock.market.index_market import StockMarketIndex
from adata.stock.market.stock_dividend import StockDividend
from adata.stock.market.stock_market import StockMarket


class Market(StockMarket, StockMarketConcept, StockDividend, StockMarketIndex):
class Market(StockCapitalFlow, StockMarket, StockMarketConcept, StockDividend, StockMarketIndex):

def __init__(self) -> None:
super().__init__()
Expand Down
8 changes: 8 additions & 0 deletions adata/stock/market/capital_flow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
"""
@desc:
@author: 1nchaos
@time:2023/8/3
@log:
"""
from adata.stock.market.capital_flow.stock_capital_flow import StockCapitalFlow
48 changes: 48 additions & 0 deletions adata/stock/market/capital_flow/stock_capital_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
"""
@desc: 股票资金流向

东方财富:个股
https://data.eastmoney.com/zjlx/000001.html
https://push2his.eastmoney.com/api/qt/stock/fflow/daykline/get?cb=jQuery112303663243111530894_1718714074308&lmt=0&klt=101&fields1=f1%2Cf2%2Cf3%2Cf7&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61%2Cf62%2Cf63%2Cf64%2Cf65&ut=b2884a393a59ad64002292a3e90d46a5&secid=1.600519&_=1718714074309

@author: 1nchaos
@time: 2024/6/7
@log: change log
"""

from adata.stock.market.capital_flow.stock_capital_flow_baidu import StockCapitalFlowBaidu
from adata.stock.market.capital_flow.stock_capital_flow_east import StockCapitalFlowEast


class StockCapitalFlow(object):
"""股票资金流向"""

def __init__(self) -> None:
super().__init__()
self.east_capital_flow = StockCapitalFlowEast()
self.baidu_capital_flow = StockCapitalFlowBaidu()

def get_capital_flow_min(self, stock_code: str = '000001'):
"""
获取单个股票的今日分时资金流向
:param stock_code: 股票代码
:return: 当日分钟资金流向
"""
return self.east_capital_flow.get_capital_flow_min(stock_code)

def get_capital_flow(self, stock_code: str = '000001', start_date=None, end_date=None):
"""
获取单个股票的资金流向-日度
只能获取最近2年多的数据
:param end_date: 结束日期
:param start_date: 开始日期
:param stock_code: 股票代码
:return: 资金流向-日度
"""
return self.baidu_capital_flow.get_capital_flow(stock_code, start_date=start_date, end_date=end_date)


if __name__ == '__main__':
print(StockCapitalFlow().get_capital_flow_min(stock_code='300059'))
print(StockCapitalFlow().get_capital_flow(stock_code='000001'))
105 changes: 105 additions & 0 deletions adata/stock/market/capital_flow/stock_capital_flow_baidu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
"""
@desc: 股票资金流向

东方财富:个股
https://data.eastmoney.com/zjlx/000001.html
https://push2his.eastmoney.com/api/qt/stock/fflow/daykline/get?cb=jQuery112303663243111530894_1718714074308&lmt=0&klt=101&fields1=f1%2Cf2%2Cf3%2Cf7&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61%2Cf62%2Cf63%2Cf64%2Cf65&ut=b2884a393a59ad64002292a3e90d46a5&secid=1.600519&_=1718714074309

@author: 1nchaos
@time: 2024/6/7
@log: change log
"""
import datetime

import pandas as pd

from adata.common.headers import baidu_headers
from adata.common.utils import requests
from adata.common.utils.unit_conver import convert_to_yuan
from adata.stock.market.capital_flow.stock_capital_flow_template import StockCapitalFlowTemplate


class StockCapitalFlowBaidu(StockCapitalFlowTemplate):

def get_capital_flow_min(self, stock_code: str = '000001'):
"""
获取单个股票的今日分时资金流向
:param stock_code: 股票代码
:return: 当日分钟资金流向
"""
url = f"https://finance.pae.baidu.com/vapi/v1/fundflow?finance_type=stock&fund_flow_type=&" \
f"type=stock&market=ab&code={stock_code}&belongs=stocklevelone&finClientType=pc"
res = requests.request('get', url, headers=baidu_headers.json_headers, proxies={})
data_str = res.json()["Result"]["content"]["fundFlowMinute"]["data"]
data_list = data_str.split(';')
data = []
for row_str in data_list:
row = row_str.split(',')
data.append({
"stock_code": stock_code,
"trade_time": row[0],
"main_net_inflow": float(row[2]) * 10000 * 10000,
"sm_net_inflow": float(row[7]) * 10000 * 10000,
"mid_net_inflow": float(row[6]) * 10000 * 10000,
"lg_net_inflow": float(row[5]) * 10000 * 10000,
"max_net_inflow": float(row[4]) * 10000 * 10000
})
# 2024-07-01 9:30, 0.00, -0.08, 0.08, -0.05, -0.03, 0.02, 0.06, 10.48, -0.76 %;
df = pd.DataFrame(data, columns=self._FLOW_MIN_COLUMNS)
return df

def get_capital_flow(self, stock_code: str = '000001', start_date=None, end_date=None):
"""
获取单个股票的资金流向-日度
:param end_date: 开始日期
:param start_date: 结束日期
:param stock_code: 股票代码
:return: 资金流向-日度
"""
# 1. 日期处理
if end_date is None:
now = datetime.datetime.now()
end_date = now.strftime('%Y%m%d')
else:
end_date = end_date.replace('-', '')

if start_date is not None:
start_date = start_date.replace('-', '')

# 2. 循环请求数据
data = []
is_end = False
for i in range(0, 500):
url = f"https://finance.pae.baidu.com/vapi/v1/fundsortlist?" \
f"code={stock_code}&market=ab&finance_type=stock&tab=day&" \
f"from=history&date={end_date}&pn=0&rn=20&finClientType=pc"
res = requests.request('get', url, headers= baidu_headers.json_headers, proxies={})
data_list = res.json()["Result"]["content"]
if len(data_list) == 0:
break
for row in data_list:
row = convert_to_yuan(row)
# 日期范围判断
if start_date is not None and row["date"].replace('/', '') < start_date:
is_end = True
break
data.append({
"stock_code": stock_code,
"trade_date": row["date"].replace("/", '-'),
"main_net_inflow": row["extMainIn"],
"sm_net_inflow": row["littleNetIn"],
"mid_net_inflow": row["mediumNetIn"],
"lg_net_inflow": row["largeNetIn"],
"max_net_inflow": row["superNetIn"]
})
if is_end:
break
end_date = data[-1]["trade_date"].replace('-', '')
df = pd.DataFrame(data, columns=self._FLOW_COLUMNS)
return df


if __name__ == '__main__':
print(StockCapitalFlowBaidu().get_capital_flow_min(stock_code='300059'))
print(StockCapitalFlowBaidu().get_capital_flow(stock_code='300059'))
Loading
Loading