Skip to content

Commit ef685f0

Browse files
committed
Added ak_equity_ownership
1 parent 0a3e42b commit ef685f0

File tree

4 files changed

+123
-2
lines changed

4 files changed

+123
-2
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""AKShare Equity Ownership Model."""
2+
3+
from datetime import (
4+
date as dateType,
5+
datetime,
6+
)
7+
from typing import Any, Dict, List, Optional
8+
9+
from openbb_core.provider.abstract.fetcher import Fetcher
10+
from openbb_core.provider.standard_models.equity_ownership import (
11+
EquityOwnershipData,
12+
EquityOwnershipQueryParams,
13+
)
14+
from mysharelib.tools import most_recent_quarter
15+
from pydantic import field_validator
16+
17+
18+
class AKShareEquityOwnershipQueryParams(EquityOwnershipQueryParams):
19+
"""AKShare Equity Ownership Query.
20+
21+
Source: https://emweb.securities.eastmoney.com/PC_HSF10/ShareholderResearch/Index?type=web&code=SH688686#sdgd-0
22+
"""
23+
24+
@field_validator("date", mode="before", check_fields=True)
25+
@classmethod
26+
def time_validate(cls, v: str):
27+
"""Validate the date."""
28+
if v is None:
29+
v = dateType.today()
30+
if isinstance(v, str):
31+
base = datetime.strptime(v, "%Y-%m-%d").date()
32+
return most_recent_quarter(base)
33+
return most_recent_quarter(v)
34+
35+
36+
class AKShareEquityOwnershipData(EquityOwnershipData):
37+
"""AKShare Equity Ownership Data."""
38+
39+
40+
class AKShareEquityOwnershipFetcher(
41+
Fetcher[
42+
AKShareEquityOwnershipQueryParams,
43+
List[AKShareEquityOwnershipData],
44+
]
45+
):
46+
"""Transform the query, extract and transform the data from the AKShare endpoints."""
47+
48+
@staticmethod
49+
def transform_query(params: Dict[str, Any]) -> AKShareEquityOwnershipQueryParams:
50+
"""Transform the query params."""
51+
return AKShareEquityOwnershipQueryParams(**params)
52+
53+
@staticmethod
54+
def extract_data(
55+
query: AKShareEquityOwnershipQueryParams,
56+
credentials: Optional[Dict[str, str]],
57+
**kwargs: Any,
58+
) -> List[Dict]:
59+
"""Return the raw data from the AKShare endpoint."""
60+
from openbb_akshare.utils.ak_equity_ownership import stock_gdfx_top_10
61+
62+
return stock_gdfx_top_10(query.symbol, query.date).to_dict(orient="records")
63+
64+
@staticmethod
65+
def transform_data(
66+
query: AKShareEquityOwnershipQueryParams, data: List[Dict], **kwargs: Any
67+
) -> List[AKShareEquityOwnershipData]:
68+
"""Return the transformed data."""
69+
own = [AKShareEquityOwnershipData.model_validate(d) for d in data]
70+
own.sort(key=lambda x: x.filing_date, reverse=True)
71+
return own
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from datetime import (
2+
date as dateType,
3+
datetime,
4+
)
5+
import logging
6+
from openbb_akshare import project_name
7+
from mysharelib.tools import setup_logger, normalize_symbol
8+
from mysharelib.em.stock_hk_gdfx_em import stock_hk_gdfx_top_10_em
9+
10+
setup_logger(project_name)
11+
logger = logging.getLogger(__name__)
12+
13+
def stock_gdfx_top_10(symbol:str, date: dateType | str):
14+
import akshare as ak
15+
16+
if isinstance(date, str):
17+
# Assuming date format is 'YYYYMMDD'
18+
try:
19+
# Try parsing as 'YYYY-MM-DD'
20+
date = datetime.strptime(date, "%Y%m%d")
21+
except ValueError:
22+
try:
23+
# Try parsing as 'YYYY-MM-DD'
24+
date = datetime.strptime(date, "%Y-%m-%d")
25+
except ValueError:
26+
raise ValueError("Invalid date format. Use 'YYYY-MM-DD' or 'YYYYMMDD'.")
27+
28+
symbol_b, symbol_f, market = normalize_symbol(symbol)
29+
if market == "HK":
30+
return stock_hk_gdfx_top_10_em(symbol=symbol_f, date=date.strftime("%Y%m%d"))
31+
elif market in ["SH", "SZ", "BJ"]:
32+
return ak.stock_gdfx_free_top_10_em(symbol=f"sh{symbol_b}", date=date.strftime("%Y%m%d"))
33+
else:
34+
raise ValueError("Invalid market. Please use 'HK', 'SH', 'SZ', or 'BJ'.")

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "openbb-akshare"
3-
version = "0.7.8"
3+
version = "0.7.9"
44
description = "AKShare extension for OpenBB"
55
authors = ["Roger Ye <[email protected]>"]
66
license = "AGPL-3.0-only"
@@ -9,7 +9,7 @@ packages = [{ include = "openbb_akshare" }]
99

1010
[tool.poetry.dependencies]
1111
python = ">=3.9.21,<3.13"
12-
akshare = "1.17.31"
12+
akshare = "1.17.39"
1313
openbb-core = { version = "^1.4.7" }
1414
mysharelib = "^0.4.5"
1515
ipywidgets = "^8.1.7"

tests/test_equity_ownership.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import pytest
2+
import pandas as pd
3+
import sqlite3
4+
from pathlib import Path
5+
from datetime import datetime, timezone
6+
from mysharelib.table_cache import TableCache
7+
from openbb_akshare.utils.fetch_equity_info import EQUITY_INFO_SCHEMA
8+
from openbb_akshare import project_name
9+
10+
@pytest.mark.parametrize("symbol", ["00386", "600177"])
11+
12+
def test_ak_equity_ownership(symbol, logger):
13+
from openbb_akshare.utils.ak_equity_ownership import stock_gdfx_top_10
14+
equity_owners_df = stock_gdfx_top_10(symbol, date="20250630")
15+
logger.info(f"obb.equity.ownership:{symbol}, {equity_owners_df}")
16+

0 commit comments

Comments
 (0)