DataSource Adapters 模块 - 最佳实践
概述
本最佳实践指南帮助开发者高效、稳定地使用 Adapters 模块。
TDX 适配器最佳实践
连接池使用
推荐做法:
python
from FQData.DataSource.adapters.tdx import TdxConnectionPool
pool = TdxConnectionPool(max_size=10, min_size=2)
with pool.acquire() as connector:
data = adapter.get_security_bars(connector, code, category, start, count)不推荐做法:
python
# 每次请求都创建新连接
for i in range(100):
adapter = TdxStockAdapter() # 错误!
data = adapter.get_security_bars(...)IP 选择
推荐做法:
python
from FQData.DataSource.adapters.tdx import TdxIPSelector
selector = TdxIPSelector()
best_ips = selector.get_best_ip(count=5)
for ip in best_ips:
if selector.validate_ip(ip, 7709):
print(f"Using IP: {ip}")
breakAkShare 适配器最佳实践
限速控制
推荐做法:
python
adapter = AkShareAdapter()
adapter.rate_limit = 5 # 5 请求/秒
for code in codes:
data = adapter.get_stock_day(code)
time.sleep(0.2) # 额外等待不推荐做法:
python
# 无限制请求会被封禁
for code in codes:
adapter = AkShareAdapter() # 每次新建
adapter.get_stock_day(code) # 快速请求东方财富适配器最佳实践
批量请求
推荐做法:
python
from FQData.DataSource.adapters.eastmoney import get_stock_fund_flow_batch
codes = ['600000', '000001', '000002', ...]
dfs = get_stock_fund_flow_batch(codes) # 批量获取不推荐做法:
python
# 逐个请求效率低
for code in codes:
df = get_stock_fund_flow(code) # 低效缓存结果
python
from functools import lru_cache
from FQData.DataSource.adapters.eastmoney import get_stock_fund_flow
@lru_cache(maxsize=100)
def cached_fund_flow(code: str) -> pd.DataFrame:
return get_stock_fund_flow(code)集思录适配器最佳实践
复用浏览器实例
推荐做法:
python
browser = create_browser()
try:
login(browser, username, password)
for i in range(10):
data = get_cbnewlist(browser)
# 处理数据
finally:
browser.quit() # 确保关闭不推荐做法:
python
# 每次都创建新浏览器
for i in range(10):
browser = create_browser() # 资源浪费
data = get_cbnewlist(browser)
browser.quit()无头模式
python
def create_browser(headless=True):
options = webdriver.ChromeOptions()
if headless:
options.add_argument('--headless')
return webdriver.Chrome(options=options)错误处理最佳实践
重试机制
python
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def fetch_with_retry(adapter, code):
return adapter.get_security_bars(code, 9, 0, 100)优雅降级
python
try:
from FQData.DataSource.adapters.tdx import TdxStockAdapter
adapter = TdxStockAdapter()
data = adapter.get_security_bars(...)
except Exception as e:
logger.warning(f"TDX failed, fallback to AkShare: {e}")
from FQData.DataSource.adapters.akshare import AkShareAdapter
adapter = AkShareAdapter()
data = adapter.get_stock_day(...)性能优化
1. 并行请求
python
from concurrent.futures import ThreadPoolExecutor
def fetch_parallel(codes, adapter_class):
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(adapter_class().get_stock_day, code) for code in codes]
return [f.result() for f in futures]2. 数据缓存
python
from functools import lru_cache
@lru_cache(maxsize=1000)
def get_cached_stock_info(code: str):
return adapter.get_stock_info(code)3. 批量操作
python
# 好:一次性获取多只股票
adapter.get_security_list(market=1, start=0, count=1000)
# 差:循环获取
for i in range(100):
adapter.get_security_bars(...)安全最佳实践
凭证管理
python
# 好:使用环境变量
import os
username = os.environ.get('JISILU_USERNAME')
password = os.environ.get('JISILU_PASSWORD')
# 差:硬编码
username = 'my_username' # 危险!
password = 'my_password'请求验证
python
def validate_response(response):
if response.status_code != 200:
raise DataSourceAPIError(f"HTTP {response.status_code}")
if not response.json():
raise DataNotFoundError("Empty response")
return response.json()