244 lines
7.4 KiB
Python
244 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
股票代码格式转换工具类
|
||
|
||
提供多种股票代码格式之间的转换功能
|
||
"""
|
||
|
||
import re
|
||
from typing import Optional
|
||
|
||
|
||
class StockCodeFormatter:
|
||
"""股票代码格式转换器"""
|
||
|
||
def __init__(self):
|
||
"""初始化"""
|
||
pass
|
||
|
||
def _parse_stock_code(self, stock_code: str) -> tuple:
|
||
"""
|
||
解析股票代码,提取代码和市场信息
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码
|
||
|
||
Returns:
|
||
tuple: (代码数字, 市场标识) 如 ('688008', 'SH')
|
||
"""
|
||
if not stock_code:
|
||
return None, None
|
||
|
||
stock_code = stock_code.strip().upper()
|
||
|
||
# 处理 688008.SH 格式
|
||
if '.' in stock_code:
|
||
parts = stock_code.split('.')
|
||
if len(parts) == 2:
|
||
code, market = parts[0], parts[1]
|
||
return code, market
|
||
|
||
# 处理 SH688008 格式
|
||
elif stock_code.startswith(('SZ', 'SH', 'BJ')):
|
||
market = stock_code[:2]
|
||
code = stock_code[2:]
|
||
return code, market
|
||
|
||
# 处理纯数字 688008 格式
|
||
elif stock_code.isdigit():
|
||
# 根据数字前缀自动判断市场
|
||
if stock_code.startswith(('60', '68')):
|
||
return stock_code, 'SH'
|
||
elif stock_code.startswith(('00', '30', '20')):
|
||
return stock_code, 'SZ'
|
||
elif stock_code.startswith(('8', '43', '87')):
|
||
return stock_code, 'BJ'
|
||
else:
|
||
return stock_code, None
|
||
|
||
return None, None
|
||
|
||
def to_dot_format(self, stock_code: str) -> Optional[str]:
|
||
"""
|
||
转换为点分格式 (如: 688008.SH)
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码,支持多种格式
|
||
|
||
Returns:
|
||
str: 点分格式的股票代码,如果无法转换则返回None
|
||
|
||
Examples:
|
||
>>> formatter = StockCodeFormatter()
|
||
>>> formatter.to_dot_format('SH688008')
|
||
'688008.SH'
|
||
>>> formatter.to_dot_format('688008')
|
||
'688008.SH'
|
||
>>> formatter.to_dot_format('688008.SH')
|
||
'688008.SH'
|
||
"""
|
||
code, market = self._parse_stock_code(stock_code)
|
||
|
||
if code and market:
|
||
return f"{code}.{market}"
|
||
|
||
return None
|
||
|
||
def to_prefix_format(self, stock_code: str) -> Optional[str]:
|
||
"""
|
||
转换为前缀格式 (如: SH688008)
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码,支持多种格式
|
||
|
||
Returns:
|
||
str: 前缀格式的股票代码,如果无法转换则返回None
|
||
|
||
Examples:
|
||
>>> formatter = StockCodeFormatter()
|
||
>>> formatter.to_prefix_format('688008.SH')
|
||
'SH688008'
|
||
>>> formatter.to_prefix_format('688008')
|
||
'SH688008'
|
||
>>> formatter.to_prefix_format('SH688008')
|
||
'SH688008'
|
||
"""
|
||
code, market = self._parse_stock_code(stock_code)
|
||
|
||
if code and market:
|
||
return f"{market}{code}"
|
||
|
||
return None
|
||
|
||
def to_number_only(self, stock_code: str) -> Optional[str]:
|
||
"""
|
||
转换为纯数字格式 (如: 688008)
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码,支持多种格式
|
||
|
||
Returns:
|
||
str: 纯数字格式的股票代码,如果无法转换则返回None
|
||
|
||
Examples:
|
||
>>> formatter = StockCodeFormatter()
|
||
>>> formatter.to_number_only('688008.SH')
|
||
'688008'
|
||
>>> formatter.to_number_only('SH688008')
|
||
'688008'
|
||
>>> formatter.to_number_only('688008')
|
||
'688008'
|
||
"""
|
||
code, market = self._parse_stock_code(stock_code)
|
||
|
||
if code:
|
||
return code
|
||
|
||
return None
|
||
|
||
def get_market(self, stock_code: str) -> Optional[str]:
|
||
"""
|
||
获取股票代码对应的市场标识
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码,支持多种格式
|
||
|
||
Returns:
|
||
str: 市场标识 ('SH', 'SZ', 'BJ'),如果无法识别则返回None
|
||
"""
|
||
code, market = self._parse_stock_code(stock_code)
|
||
return market
|
||
|
||
def is_valid_stock_code(self, stock_code: str) -> bool:
|
||
"""
|
||
验证股票代码是否有效
|
||
|
||
Args:
|
||
stock_code: 输入的股票代码
|
||
|
||
Returns:
|
||
bool: 是否为有效的股票代码
|
||
"""
|
||
code, market = self._parse_stock_code(stock_code)
|
||
return code is not None and market is not None
|
||
|
||
def batch_convert(self, stock_codes: list, target_format: str = 'dot') -> dict:
|
||
"""
|
||
批量转换股票代码格式
|
||
|
||
Args:
|
||
stock_codes: 股票代码列表
|
||
target_format: 目标格式 ('dot', 'prefix', 'number')
|
||
|
||
Returns:
|
||
dict: {原始代码: 转换后代码} 的映射字典
|
||
"""
|
||
result = {}
|
||
|
||
for stock_code in stock_codes:
|
||
if target_format == 'dot':
|
||
converted = self.to_dot_format(stock_code)
|
||
elif target_format == 'prefix':
|
||
converted = self.to_prefix_format(stock_code)
|
||
elif target_format == 'number':
|
||
converted = self.to_number_only(stock_code)
|
||
else:
|
||
converted = None
|
||
|
||
result[stock_code] = converted
|
||
|
||
return result
|
||
|
||
|
||
def main():
|
||
"""示例用法"""
|
||
print("=== 股票代码格式转换工具示例 ===")
|
||
|
||
# 创建格式转换器
|
||
formatter = StockCodeFormatter()
|
||
|
||
# 测试用例
|
||
test_codes = [
|
||
'688008.SH', # 沪市科创板
|
||
'SH688008', # 前缀格式
|
||
'688008', # 纯数字
|
||
'300661.SZ', # 深市创业板
|
||
'SZ300661', # 前缀格式
|
||
'300661', # 纯数字
|
||
'000858.SZ', # 深市主板
|
||
'600519.SH', # 沪市主板
|
||
'430123.BJ', # 北交所
|
||
'BJ430123', # 北交所前缀格式
|
||
]
|
||
|
||
print("\n原始代码 -> 点分格式 -> 前缀格式 -> 纯数字格式 -> 市场")
|
||
print("-" * 70)
|
||
|
||
for code in test_codes:
|
||
dot_format = formatter.to_dot_format(code)
|
||
prefix_format = formatter.to_prefix_format(code)
|
||
number_format = formatter.to_number_only(code)
|
||
market = formatter.get_market(code)
|
||
is_valid = formatter.is_valid_stock_code(code)
|
||
|
||
status = "✓" if is_valid else "✗"
|
||
print(f"{code:12} -> {dot_format or 'None':12} -> {prefix_format or 'None':12} -> {number_format or 'None':8} -> {market or 'None':4} {status}")
|
||
|
||
# 批量转换示例
|
||
print(f"\n=== 批量转换示例 ===")
|
||
batch_codes = ['SH688008', '300661', 'BJ430123']
|
||
|
||
dot_results = formatter.batch_convert(batch_codes, 'dot')
|
||
print("转换为点分格式:")
|
||
for original, converted in dot_results.items():
|
||
print(f" {original} -> {converted}")
|
||
|
||
prefix_results = formatter.batch_convert(batch_codes, 'prefix')
|
||
print("转换为前缀格式:")
|
||
for original, converted in prefix_results.items():
|
||
print(f" {original} -> {converted}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |