Python中如何实现一个Pythonic的i问财量化策略工具包
项目地址: https://github.com/GraySilver/wencai-master
wencai 是 i 问财的策略回测接口的 Pythonic 工具包,满足量化爱好者和数据分析师在量化方面的需求。
安装方式:
方式 1:pip install wencai
方式 2:python setup.py install
方式 3:访问 https://pypi.python.org/pypi/wencai 下载安装
Python中如何实现一个Pythonic的i问财量化策略工具包
3 回复
要做一个Pythonic的i问财策略工具包,核心是遵循Python的设计哲学(简洁、可读、明确)。下面是一个高度抽象但完整的框架示例,展示了关键组件的实现思路:
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional, Callable
import pandas as pd
import numpy as np
@dataclass
class Stock:
"""股票数据类"""
code: str
name: str
data: pd.DataFrame # 包含日期、开盘、收盘等字段
class DataFetcher:
"""数据获取器 - 负责从i问财获取数据"""
@staticmethod
def fetch_stock_data(query: str, start_date: str, end_date: str) -> List[Stock]:
"""
执行i问财查询并返回股票列表
Args:
query: i问财查询语句,如'pe<20 and roe>15'
start_date: 开始日期 '2023-01-01'
end_date: 结束日期 '2023-12-31'
"""
# 这里应该实现实际的i问财API调用
# 示例返回模拟数据
stocks = []
# 模拟查询结果
results = ['000001.SZ', '000002.SZ'] # 假设查询返回这些股票
for code in results:
# 获取历史数据(这里需要实际实现)
data = pd.DataFrame({
'date': pd.date_range(start_date, end_date),
'close': np.random.randn(100).cumsum() + 100
})
stocks.append(Stock(code=code, name=f"股票{code}", data=data))
return stocks
class Strategy(ABC):
"""策略基类 - 定义策略接口"""
@abstractmethod
def filter(self, stock: Stock) -> bool:
"""过滤股票条件"""
pass
@abstractmethod
def signal(self, stock: Stock) -> Optional[float]:
"""生成交易信号"""
pass
class MeanReversionStrategy(Strategy):
"""均值回归策略示例"""
def __init__(self, window: int = 20, threshold: float = 2.0):
self.window = window
self.threshold = threshold
def filter(self, stock: Stock) -> bool:
"""过滤条件:至少有window+10个数据点"""
return len(stock.data) > self.window + 10
def signal(self, stock: Stock) -> Optional[float]:
"""生成信号:当价格偏离移动平均线超过阈值时发出信号"""
closes = stock.data['close'].values
if len(closes) < self.window:
return None
ma = np.mean(closes[-self.window:])
current = closes[-1]
z_score = (current - ma) / np.std(closes[-self.window:])
if z_score < -self.threshold:
return 1.0 # 买入信号
elif z_score > self.threshold:
return -1.0 # 卖出信号
return 0.0 # 持有
class Backtester:
"""回测引擎"""
def __init__(self, strategy: Strategy):
self.strategy = strategy
def run(self, stocks: List[Stock]) -> pd.DataFrame:
"""运行回测"""
results = []
for stock in stocks:
if not self.strategy.filter(stock):
continue
signal = self.strategy.signal(stock)
if signal is not None:
results.append({
'code': stock.code,
'name': stock.name,
'signal': signal,
'last_close': stock.data['close'].iloc[-1]
})
return pd.DataFrame(results)
# 使用示例
def main():
# 1. 获取数据
fetcher = DataFetcher()
stocks = fetcher.fetch_stock_data('pe<20 and roe>15', '2023-01-01', '2023-12-31')
# 2. 创建策略
strategy = MeanReversionStrategy(window=30, threshold=1.5)
# 3. 回测
backtester = Backtester(strategy)
results = backtester.run(stocks)
# 4. 输出结果
print("策略选股结果:")
print(results.to_string(index=False))
if __name__ == "__main__":
main()
关键设计要点:
- 面向对象设计:使用抽象基类定义接口,具体策略继承实现
- 数据类:用
@dataclass简化数据容器 - 类型提示:全程使用type hints提高代码可读性
- 单一职责:每个类只负责一个明确的功能
- 函数式风格:策略的
filter和signal方法应该是纯函数
扩展建议:
- 添加装饰器实现策略的性能统计
- 使用
__call__方法让策略对象可调用 - 实现策略组合和仓位管理模块
这个框架遵循了Python的"EAFP"(Easier to Ask for Forgiveness than Permission)原则,通过清晰的接口设计和合理的抽象层次,让策略开发变得直观且易于维护。
用dataclass和抽象基类来组织代码结构最Pythonic。
厉害
ths 的 i 问财?

