Skip to content

Commit 6e41bb5

Browse files
committed
Added price_performance.py
1 parent 9370d88 commit 6e41bb5

File tree

6 files changed

+131
-16
lines changed

6 files changed

+131
-16
lines changed

openbb_akshare/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from openbb_akshare.models.equity_profile import AKShareEquityProfileFetcher
1515
from openbb_akshare.models.historical_dividends import AKShareHistoricalDividendsFetcher
1616
from openbb_akshare.models.income_statement import AKShareIncomeStatementFetcher
17+
from openbb_akshare.models.price_performance import AKSharePricePerformanceFetcher
1718

1819
# mypy: disable-error-code="list-item"
1920

@@ -38,5 +39,6 @@
3839
"EquityInfo": AKShareEquityProfileFetcher,
3940
"HistoricalDividends": AKShareHistoricalDividendsFetcher,
4041
"IncomeStatement": AKShareIncomeStatementFetcher,
42+
"PricePerformance": AKSharePricePerformanceFetcher,
4143
}
4244
)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""AKShare Price Performance Model."""
2+
3+
# pylint: disable=unused-argument
4+
from typing import Any, Dict, List, Optional
5+
from warnings import warn
6+
7+
from openbb_core.provider.abstract.fetcher import Fetcher
8+
from openbb_core.provider.standard_models.recent_performance import (
9+
RecentPerformanceData,
10+
RecentPerformanceQueryParams,
11+
)
12+
from openbb_fmp.utils.helpers import create_url, get_data_urls
13+
from pydantic import Field, model_validator
14+
15+
16+
class AKSharePricePerformanceQueryParams(RecentPerformanceQueryParams):
17+
"""AKShare Price Performance Query.
18+
19+
Source: https://akshare.akfamily.xyz/data/index/index.html#id3
20+
"""
21+
22+
__json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
23+
24+
25+
class AKSharePricePerformanceData(RecentPerformanceData):
26+
"""AKShare Price Performance Data."""
27+
28+
#symbol: str = Field(description="The ticker symbol.")
29+
30+
__alias_dict__ = {
31+
"one_day": "1D",
32+
"one_week": "5D",
33+
"one_month": "1M",
34+
"three_month": "3M",
35+
"six_month": "6M",
36+
"one_year": "1Y",
37+
"three_year": "3Y",
38+
"five_year": "5Y",
39+
"ten_year": "10Y",
40+
}
41+
42+
@model_validator(mode="before")
43+
@classmethod
44+
def replace_zero(cls, values): # pylint: disable=no-self-argument
45+
"""Replace zero with None and convert percents to normalized values."""
46+
if isinstance(values, dict):
47+
for k, v in values.items():
48+
if k != "symbol":
49+
values[k] = None if v == 0 else float(v) / 100
50+
return values
51+
52+
53+
class AKSharePricePerformanceFetcher(
54+
Fetcher[
55+
AKSharePricePerformanceQueryParams,
56+
List[AKSharePricePerformanceData],
57+
]
58+
):
59+
"""Transform the query, extract and transform the data from the AKShare endpoints."""
60+
61+
@staticmethod
62+
def transform_query(params: Dict[str, Any]) -> AKSharePricePerformanceQueryParams:
63+
"""Transform the query params."""
64+
return AKSharePricePerformanceQueryParams(**params)
65+
66+
@staticmethod
67+
async def extract_data(
68+
query: AKSharePricePerformanceQueryParams,
69+
credentials: Optional[Dict[str, str]],
70+
**kwargs: Any,
71+
) -> List[Dict]:
72+
"""Return the raw data from the AKShare endpoint."""
73+
import pandas as pd
74+
symbols = query.symbol.split(",")
75+
76+
def get_data(code: str) -> dict:
77+
from mysharelib.tools import calculate_price_performance, last_closing_day
78+
from openbb_akshare.utils.helpers import get_list_date, ak_download
79+
80+
df = ak_download(symbol=code, start_date=get_list_date(code), end_date=last_closing_day())
81+
df['date'] = pd.to_datetime(df['date'])
82+
df.set_index('date', inplace=True)
83+
return calculate_price_performance(code, df)
84+
85+
return [get_data(symbol) for symbol in symbols]
86+
87+
@staticmethod
88+
def transform_data(
89+
query: AKSharePricePerformanceQueryParams,
90+
data: List[Dict],
91+
**kwargs: Any,
92+
) -> List[AKSharePricePerformanceData]:
93+
"""Return the transformed data."""
94+
95+
return [AKSharePricePerformanceData.model_validate(i) for i in data]

openbb_akshare/utils/fetch_equity_info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def fetch_equity_info(symbol: str, use_cache: bool = True) -> pd.DataFrame:
6060
data = cache.read_dataframe()
6161
result = data[data["symbol"] == symbol_f]
6262
if not result.empty:
63-
logger.info(f"Using cached equity info for symbol: {symbol_f}")
63+
#logger.info(f"Using cached equity info for symbol: {symbol_f}")
6464
return result
6565

6666
columns = list(EQUITY_INFO_SCHEMA.keys())
@@ -112,6 +112,6 @@ def fetch_equity_info(symbol: str, use_cache: bool = True) -> pd.DataFrame:
112112
result = data[data["symbol"] == symbol_f]
113113
result["listed_date"] = pd.to_datetime(result["listed_date"], unit='ms')
114114
result["established_date"] = pd.to_datetime(result["established_date"], unit='ms')
115-
logger.info(f"Fetched equity info for symbol: {symbol_f}")
115+
# logger.info(f"Fetched equity info for symbol: {symbol_f}")
116116

117117
return result

openbb_akshare/utils/helpers.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ def get_list_date(symbol: str) -> dateType:
5454

5555
def check_cache(symbol: str,
5656
cache: TableCache,
57-
api_key : str = "",
58-
period: str = "daily"
57+
api_key : Optional[str] = "",
58+
period: Optional[str] = "daily"
5959
) -> bool:
6060
"""
6161
Check if the cache contains the latest data for the given symbol.
@@ -79,10 +79,10 @@ def ak_download_without_cache(
7979
symbol: str,
8080
start_date: str,
8181
end_date: str,
82-
period: str = "daily",
83-
use_cache: bool = True,
84-
api_key : str = "",
85-
adjust: str = "",
82+
period: Optional[str] = "daily",
83+
use_cache: Optional[bool] = True,
84+
api_key : Optional[str] = "",
85+
adjust: Optional[str] = "",
8686
) -> DataFrame:
8787
"""
8888
Downloads historical equity data without using cache.
@@ -119,22 +119,25 @@ def ak_download_without_cache(
119119

120120
def ak_download(
121121
symbol: str,
122-
start_date: dateType,
123-
end_date: dateType,
124-
period: str = "daily",
122+
start_date: Optional[dateType] = None,
123+
end_date: Optional[dateType] = None,
124+
period: Optional[str] = "daily",
125125
use_cache: Optional[bool] = True,
126-
adjust: str = "",
126+
adjust: Optional[str] = "",
127127
) -> DataFrame:
128128

129129
from mysharelib.tools import get_valid_date
130130

131+
if start_date is None:
132+
start_date = (datetime.now() - timedelta(days=365)).date()
133+
if end_date is None: end_date = datetime.now().date()
134+
start_dt = get_valid_date(start_date)
135+
end_dt = get_valid_date(end_date)
136+
131137
# Retrieve data from cache first
132138
symbol_b, symbol_f, market = normalize_symbol(symbol)
133139
cache = TableCache(EQUITY_HISTORY_SCHEMA, project=project_name, table_name=f"{market}{symbol_b}", primary_key="date")
134140

135-
start_dt = get_valid_date(start_date)
136-
end_dt = get_valid_date(end_date)
137-
138141
if use_cache:
139142
check_cache(symbol=symbol_b, cache=cache, api_key="", period=period)
140143
data_from_cache = cache.fetch_date_range(start_dt.strftime("%Y-%m-%d"), end_dt.strftime("%Y-%m-%d"))

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "openbb-akshare"
3-
version = "0.5.7"
3+
version = "0.5.9"
44
description = "AKShare extension for OpenBB"
55
authors = ["Roger Ye <shugaoye@yahoo.com>"]
66
license = "AGPL-3.0-only"

tests/test_helpers.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,18 @@ def test_ak_download(logger):
5050
logger.info(f"Downloading data for {symbol} from {start_date} to {end_date}")
5151
df = ak_download(symbol, start_date, end_date)
5252
assert not df.empty
53+
54+
def test_price_performance(logger):
55+
def get_data(code: str) -> dict:
56+
import pandas as pd
57+
from mysharelib.tools import calculate_price_performance, last_closing_day
58+
from openbb_akshare.utils.helpers import get_list_date, ak_download
59+
60+
df = ak_download(symbol=code, start_date=get_list_date(code), end_date=last_closing_day())
61+
df['date'] = pd.to_datetime(df['date'])
62+
df.set_index('date', inplace=True)
63+
return calculate_price_performance(code, df)
64+
65+
symbols = '601919,600028'
66+
symbols = symbols.split(",")
67+
logger.info([get_data(symbol) for symbol in symbols])

0 commit comments

Comments
 (0)