Skip to content

DataStruct Mixin 模式分析

概述

本文档分析了 FQuant DataStruct 模块中 Mixin 模式的使用情况,探讨了为什么某些类未使用 Mixin 模式的设计决策。

Mixin 模式简介

什么是 Mixin?

Mixin 是一种代码复用模式,通过多重继承来实现功能组合。Mixin 本质上是一个不单独使用的类,它提供一组可组合的方法。

核心特点

python
class MixinA:
    def method_a(self):
        print("A")

class MixinB:
    def method_b(self):
        print("B")

class Base:
    def base_method(self):
        print("Base")

# 组合使用
class MyClass(Base, MixinA, MixinB):
    pass

Mixin vs 普通继承

特性普通继承Mixin
用途"是" 关系 (IS-A)"有" 关系 (HAS-A)
单独使用✅ 可以❌ 不应该
多重继承通常单继承核心模式
职责扩展父类组合功能

DataStruct 中的 Mixin 实践

当前 Mixin 类

DataStruct 模块定义了 3 个 Mixin 类:

Mixin 类职责
QuotationIndicatorsMixin统计指标计算 (max, min, mean, amplitude 等)
QuotationOperationsMixin数据筛选操作 (select_code, select_time 等)
QuotationIOSMixin数据序列化导出 (to_csv, to_json 等)

标准继承模式

python
class StockDayData(
    QuotationDataStructBase,      # 基类
    QuotationIndicatorsMixin,    # 指标计算
    QuotationOperationsMixin,    # 数据操作
    QuotationIOSMixin           # IO 导出
):
    pass

Mixin 约束

DataStruct 的 Mixin 实现遵循以下约束:

  1. 不直接实例化 - Mixin 类只能通过多重继承使用
  2. 不定义 init - 避免与基类构造函数冲突
  3. 放在基类之后 - 确保 MRO 正确

未使用 Mixin 的类分析

1. RealtimeBase (实时行情数据)

文件: realtime.py

类结构:

  • RealtimeBase - 实时行情基类
  • StockRealtimeData - 股票实时数据
  • FutureRealtimeData - 期货实时数据
  • RealtimeSeries - 实时数据序列
  • FutureTickData - 期货 Tick 数据

数据模型对比:

特性批量数据 (StockDayData)实时数据 (RealtimeBase)
数据结构pd.DataFrame (多行)dict (单条)
数据量历史数据 (大量)实时推送 (单条)
操作模式批量处理实时更新
时间维度多时间点当前时刻
核心接口筛选、计算、导出字段访问

字段差异:

python
# 实时数据特有的档口数据字段
@property
def bid1(self) -> Optional[float]:    # 买一价
@property
def bid_vol1(self) -> Optional[int]  # 买一量
@property
def ask1(self) -> Optional[float]    # 卖一价
# ... bid2-5, ask2-5

结论:这是合理的设计决策

理由:

  1. 字段不同 - 实时数据有档口数据,批量数据没有
  2. 操作不同 - 实时数据不需要筛选/重采样/指标计算
  3. 数据来源不同 - 批量数据来自数据库,实时数据来自 WebSocket

2. SecurityListData (证券列表数据)

文件: security_list.py

类职责:

python
class SecurityListData:
    """证券列表 - 基本信息管理"""
    
    def get_stock(self, option=None)   # 股票筛选
    def get_index(self)               # 指数获取
    def get_etf(self)                 # ETF 获取
    def filter_by_name(self, keyword)  # 名称筛选
    def filter_by_code(self, prefix)   # 代码筛选

数据特点:

  • 字段简单:sse, code, name
  • 操作独特:无通用的"指标计算"需求
  • 不需要 Mixin 功能

结论:这是合理的设计决策


3. FinancialData (财务数据)

文件: financial.py

类职责:

python
class FinancialData:
    """财务数据 - 报表指标"""
    
    def get_report_by_date(code, date)  # 按日期查询
    def get_key(code, date, key)       # 按指标查询
    def get_financial(code, start, end) # 按时间范围查询

数据特点:

  • 数据来源:财务报表(非行情)
  • 操作模式:查询为主(非计算)
  • 字段特殊:ROE, EPS, PE, PB, 资产负债率等

结论:这是合理的设计决策


4. 其他独立数据类

类名文件是否需要 Mixin理由
IndicatorDataindicator.py❌ 不需要指标数据,自成体系
SeriesDataseries.py❌ 不需要序列封装,操作独特
StockTransactionDatatransaction.py❌ 不需要逐笔数据,操作特殊
IndexTransactionDatatransaction.py❌ 不需要指数逐笔,操作特殊
StockBlockDatablock.py❌ 不需要板块数据,结构独特

Mixin 使用决策矩阵

场景推荐模式示例
多数据类需要相同操作(筛选/计算/导出)Mixin 模式StockDayData, IndexDayData
数据字段不同但操作相似Mixin + 自定义-
数据和操作都独特独立类SecurityListData, FinancialData
实时数据 vs 批量数据分离设计RealtimeBase vs StockDayData

总结

设计原则

  1. 职责分离 - Mixin 将不同职责分离到独立类
  2. 组合灵活 - 通过继承组合需要的特性
  3. 避免过度设计 - 不强行抽象,保持简单

设计决策总结

使用 Mixin理由
行情数据类 (Stock, Index, Future, Bond)✅ 是操作通用,字段一致
实时数据类 (RealtimeBase)❌ 否字段和操作都不同
证券列表 (SecurityListData)❌ 否字段简单,操作独特
财务数据 (FinancialData)❌ 否查询为主,无指标计算
指标数据 (IndicatorData)❌ 否数据类型特殊

结论

DataStruct 模块的 Mixin 模式使用是合理的:

  • 使用的类:需要共享指标计算、数据筛选、IO 导出等通用操作
  • 未使用的类:数据字段或操作与其他类差异较大,独立实现更合适

这种设计遵循了"简单优于复杂"的原则,避免了过度抽象带来的维护成本。


附录:Mixin 优缺点

优点

  • 代码复用
  • 职责分离
  • 灵活组合
  • 符合开闭原则

缺点

  • MRO 复杂性
  • 属性冲突风险
  • 调试困难(多层继承)

最佳实践

  1. Mixin 不定义 __init__
  2. Mixin 不直接实例化
  3. 明确继承顺序
  4. 避免属性冲突

相关文档

类型文档链接
模块首页DataStruct 首页README
快速入门快速入门quick-start
核心概念核心概念concepts
架构设计技术架构architecture
API 参考API 参考api
案例库案例库examples