88import re
99from typing import Optional
1010
11+ from data_provider .base import is_bse_code
12+
1113
1214# Known exchange prefixes (case-insensitive) and the digit lengths they accept.
1315# e.g. SH600519 -> 600519, HK00700 -> 00700
1416_PREFIX_DIGIT_LENS : dict = {
1517 "SH" : (6 ,),
1618 "SZ" : (6 ,),
1719 "SS" : (6 ,),
20+ "BJ" : (6 ,),
1821 "HK" : (1 , 2 , 3 , 4 , 5 ),
1922}
2023
2124_SUFFIX_DIGIT_LENS : dict = {
2225 ".SH" : (6 ,),
2326 ".SZ" : (6 ,),
2427 ".SS" : (6 ,),
28+ ".BJ" : (6 ,),
2529 ".HK" : (1 , 2 , 3 , 4 , 5 ),
2630}
2731
2832
33+ def _valid_exchange_code (exchange : str , base : str , digit_lens : tuple [int , ...]) -> bool :
34+ if not (base .isdigit () and len (base ) in digit_lens ):
35+ return False
36+ if exchange == "BJ" :
37+ return is_bse_code (base )
38+ return True
39+
40+
2941def _strip_exchange_prefix (text : str ) -> Optional [str ]:
3042 """Strip leading exchange prefix (SH/SZ/HK etc.) and return the bare digits, or None."""
3143 for prefix , digit_lens in _PREFIX_DIGIT_LENS .items ():
3244 if text .startswith (prefix ):
3345 base = text [len (prefix ):]
34- if base . isdigit () and len ( base ) in digit_lens :
46+ if _valid_exchange_code ( prefix , base , digit_lens ) :
3547 return base .zfill (5 ) if prefix == "HK" else base
3648 return None
3749
@@ -41,7 +53,8 @@ def _strip_exchange_suffix(text: str) -> Optional[str]:
4153 for suffix , digit_lens in _SUFFIX_DIGIT_LENS .items ():
4254 if text .endswith (suffix ):
4355 base = text [: - len (suffix )].strip ()
44- if base .isdigit () and len (base ) in digit_lens :
56+ exchange = suffix .lstrip ("." )
57+ if _valid_exchange_code (exchange , base , digit_lens ):
4558 return base .zfill (5 ) if suffix == ".HK" else base
4659 return None
4760
@@ -57,7 +70,7 @@ def is_code_like(value: str) -> bool:
5770 return True
5871 if re .match (r"^[A-Z]{1,5}(?:\.(?:US|[A-Z]))?$" , text ):
5972 return True
60- # Support exchange-prefixed codes: SH600519, SZ000001, HK00700
73+ # Support exchange-prefixed codes: SH600519, SZ000001, BJ920493, HK00700
6174 if _strip_exchange_prefix (text ) is not None :
6275 return True
6376 return False
@@ -68,8 +81,8 @@ def normalize_code(raw: str) -> Optional[str]:
6881
6982 Supports:
7083 - Plain digit codes: 600519, 00700
71- - Suffix format: 600519.SH, 600519.SZ, 00700.HK
72- - Prefix format: SH600519, SZ000001, HK00700 (case-insensitive)
84+ - Suffix format: 600519.SH, 600519.SZ, 920493.BJ, 00700.HK
85+ - Prefix format: SH600519, SZ000001, BJ920493, HK00700 (case-insensitive)
7386 - US ticker symbols: AAPL, TSLA
7487 """
7588 text = raw .strip ().upper ()
@@ -82,7 +95,7 @@ def normalize_code(raw: str) -> Optional[str]:
8295 stripped_suffix = _strip_exchange_suffix (text )
8396 if stripped_suffix is not None :
8497 return stripped_suffix
85- # Support exchange-prefixed codes: SH600519 -> 600519, HK00700 -> 00700
98+ # Support exchange-prefixed codes: SH600519 -> 600519, BJ920493 -> 920493
8699 stripped = _strip_exchange_prefix (text )
87100 if stripped is not None :
88101 return stripped
0 commit comments