免责声明本文基于个人使用体验与任何厂商无商业关系。内容仅供技术交流参考不构成投资建议。一、前言量化交易会产生大量数据行情数据、交易记录、策略状态、回测结果等。如何高效存储和查询这些数据2026年了数据库设计在量化交易中越来越重要。今天分享一下我在量化交易数据库设计方面的实践经验。二、数据库需求分析1. 数据类型数据类型特点存储需求行情数据高频、量大时间序列数据库交易记录结构化、查询多关系型数据库策略状态实时更新内存数据库持久化回测结果分析为主关系型数据库2. 查询需求# 常见查询需求queries[查询某品种的历史K线,查询某时间段的交易记录,查询策略的实时状态,查询回测结果对比,统计分析交易表现,]三、数据库选择1. 时间序列数据库适用场景行情数据存储选择数据库特点适用InfluxDB专为时序数据设计高频行情数据TimescaleDBPostgreSQL扩展需要SQL查询ClickHouse列式存储大数据分析示例# 使用InfluxDB存储行情数据frominfluxdbimportInfluxDBClient clientInfluxDBClient(hostlocalhost,port8086,databasetrading)defsave_quote(symbol,quote):保存行情数据json_body[{measurement:quotes,tags:{symbol:symbol},time:quote.datetime,fields:{open:quote.open,high:quote.high,low:quote.low,close:quote.close,volume:quote.volume,}}]client.write_points(json_body)# 查询defquery_quotes(symbol,start_time,end_time):查询行情数据queryf SELECT * FROM quotes WHERE symbol {symbol} AND time {start_time} AND time {end_time} resultclient.query(query)returnresult2. 关系型数据库适用场景交易记录、策略配置选择数据库特点适用MySQL成熟稳定中小规模PostgreSQL功能强大复杂查询SQLite轻量级单机应用示例importsqlite3importpandasaspd# 创建数据库connsqlite3.connect(trading.db)# 创建表defcreate_tables(conn):创建表cursorconn.cursor()# 交易记录表cursor.execute( CREATE TABLE IF NOT EXISTS trades ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, symbol TEXT NOT NULL, direction TEXT NOT NULL, volume INTEGER NOT NULL, price REAL NOT NULL, pnl REAL, order_id TEXT, strategy_name TEXT ) )# 策略配置表cursor.execute( CREATE TABLE IF NOT EXISTS strategies ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, params TEXT, status TEXT, created_at TEXT ) )conn.commit()create_tables(conn)3. 内存数据库适用场景实时状态、缓存选择数据库特点适用Redis高性能缓存、实时状态Memcached简单简单缓存四、数据库设计实践1. 行情数据表设计# K线数据表CREATE TABLE klines(idBIGINT PRIMARY KEY AUTO_INCREMENT,symbol VARCHAR(20)NOT NULL,datetime DATETIME NOT NULL,period INT NOT NULL,--周期秒openDECIMAL(10,2),high DECIMAL(10,2),low DECIMAL(10,2),close DECIMAL(10,2),volume BIGINT,open_interest BIGINT,UNIQUE KEY uk_symbol_datetime_period(symbol,datetime,period),INDEX idx_symbol_datetime(symbol,datetime));# Tick数据表CREATE TABLE ticks(idBIGINT PRIMARY KEY AUTO_INCREMENT,symbol VARCHAR(20)NOT NULL,datetime DATETIME(3)NOT NULL,--毫秒精度 price DECIMAL(10,2),volume INT,bid_price1 DECIMAL(10,2),ask_price1 DECIMAL(10,2),bid_volume1 INT,ask_volume1 INT,UNIQUE KEY uk_symbol_datetime(symbol,datetime),INDEX idx_symbol_datetime(symbol,datetime));2. 交易记录表设计# 交易记录表CREATE TABLE trades(idBIGINT PRIMARY KEY AUTOINCREMENT,timestamp DATETIME NOT NULL,symbol VARCHAR(20)NOT NULL,direction VARCHAR(10)NOT NULL,--BUY/SELL offset VARCHAR(10)NOT NULL,--OPEN/CLOSE volume INT NOT NULL,price DECIMAL(10,2)NOT NULL,commission DECIMAL(10,2),--手续费 slippage DECIMAL(10,2),--滑点 pnl DECIMAL(10,2),--盈亏 order_id VARCHAR(50),strategy_name VARCHAR(50),signal_info TEXT,--信号信息JSON INDEX idx_timestamp(timestamp),INDEX idx_symbol(symbol),INDEX idx_strategy(strategy_name));3. 策略状态表设计# 策略状态表CREATE TABLE strategy_states(idBIGINT PRIMARY KEY AUTOINCREMENT,strategy_name VARCHAR(50)NOT NULL,timestamp DATETIME NOT NULL,equity DECIMAL(12,2),--权益 position_info TEXT,--持仓信息JSON signal_info TEXT,--信号信息JSON error_info TEXT,--错误信息 INDEX idx_strategy_timestamp(strategy_name,timestamp));五、数据操作实践1. 数据写入defsave_trade(conn,trade):保存交易记录cursorconn.cursor()cursor.execute( INSERT INTO trades (timestamp, symbol, direction, offset, volume, price, pnl, order_id, strategy_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ,(trade[timestamp],trade[symbol],trade[direction],trade[offset],trade[volume],trade[price],trade.get(pnl,0),trade.get(order_id),trade.get(strategy_name)))conn.commit()# 批量写入提高性能defsave_trades_batch(conn,trades):批量保存交易记录cursorconn.cursor()cursor.executemany( INSERT INTO trades (timestamp, symbol, direction, offset, volume, price, pnl, order_id, strategy_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ,[(t[timestamp],t[symbol],t[direction],t[offset],t[volume],t[price],t.get(pnl,0),t.get(order_id),t.get(strategy_name))fortintrades])conn.commit()2. 数据查询defquery_trades(conn,symbolNone,start_dateNone,end_dateNone,strategyNone):查询交易记录querySELECT * FROM trades WHERE 11params[]ifsymbol:query AND symbol ?params.append(symbol)ifstart_date:query AND timestamp ?params.append(start_date)ifend_date:query AND timestamp ?params.append(end_date)ifstrategy:query AND strategy_name ?params.append(strategy)query ORDER BY timestampdfpd.read_sql_query(query,conn,paramsparams)returndf# 使用tradesquery_trades(conn,symbolSHFE.rb2505,start_date2025-01-01,end_date2025-01-31)3. 数据分析defanalyze_trades(conn,strategy_nameNone):分析交易记录querySELECT * FROM tradesifstrategy_name:queryf WHERE strategy_name {strategy_name}dfpd.read_sql_query(query,conn)iflen(df)0:returnNoneanalysis{total_trades:len(df),win_rate:(df[pnl]0).sum()/len(df),total_pnl:df[pnl].sum(),avg_profit:df[df[pnl]0][pnl].mean()if(df[pnl]0).any()else0,avg_loss:df[df[pnl]0][pnl].mean()if(df[pnl]0).any()else0,profit_loss_ratio:abs(df[df[pnl]0][pnl].mean()/df[df[pnl]0][pnl].mean())if(df[pnl]0).any()else0,}returnanalysis# 使用analysisanalyze_trades(conn,strategy_namema_cross)print(analysis)六、性能优化1. 索引优化# 为常用查询字段创建索引CREATE INDEX idx_trades_symbol_timestamp ON trades(symbol,timestamp);CREATE INDEX idx_trades_strategy_timestamp ON trades(strategy_name,timestamp);CREATE INDEX idx_klines_symbol_datetime ON klines(symbol,datetime);2. 分区表# 按时间分区MySQL 5.7CREATE TABLE trades_2025_01 PARTITION OF trades FOR VALUES FROM(2025-01-01)TO(2025-02-01);CREATE TABLE trades_2025_02 PARTITION OF trades FOR VALUES FROM(2025-02-01)TO(2025-03-01);3. 数据归档defarchive_old_data(conn,table_name,archive_date):归档旧数据# 导出旧数据queryfSELECT * FROM{table_name}WHERE timestamp ?old_datapd.read_sql_query(query,conn,params[archive_date])# 保存到归档文件old_data.to_csv(farchive_{table_name}_{archive_date}.csv,indexFalse)# 删除旧数据cursorconn.cursor()cursor.execute(fDELETE FROM{table_name}WHERE timestamp ?,[archive_date])conn.commit()七、不同工具的数据库支持工具数据库支持特点TqSdk需自己实现灵活可自定义VnPy有数据库模块内置支持掘金量化平台数据在线存储八、我的数据库设计经验作为一个从业二十年的期货量化交易者分享几点数据库设计经验1. 数据库选择我的选择行情数据使用InfluxDB时序数据库交易记录使用MySQL关系型数据库实时状态使用Redis内存数据库2. 表设计我的设计原则按业务划分表合理使用索引考虑查询性能3. 数据管理我的管理方法定期归档旧数据备份重要数据监控数据库性能我目前使用TqSdk做交易自己设计数据库。虽然多写一些代码但更灵活可以完全控制数据结构。这只是我个人的经验每个人需求不同建议根据自己的情况设计。九、总结2026年期货量化交易数据库设计要点数据库选择根据数据类型选择合适数据库表设计合理设计表结构考虑查询需求性能优化索引、分区、归档数据管理定期备份、归档、监控好的数据库设计是量化交易的重要基础能帮助高效存储和查询数据。本文仅作为技术介绍不代表对任何工具的推荐。实际使用请自行评估。声明本文基于个人学习经验整理仅供技术交流参考不构成任何投资建议。