【期货量化进阶】期货Tick数据分析与应用:高频数据入门(TqSdk完整教程)

一、前言

Tick数据是期货市场最精细的数据,记录了每一笔成交的价格、数量和时间。相比K线数据,Tick数据能够揭示更多市场微观结构信息,是高频交易和精细化分析的基础。

本文将介绍:

  • Tick数据的概念与结构
  • 如何获取和处理Tick数据
  • Tick数据分析方法
  • 基于Tick的交易策略

二、为什么选择天勤量化(TqSdk)

在众多期货量化工具中,**天勤量化(TqSdk)**是目前国内最受欢迎的开源期货量化框架之一:

特点 说明
完全免费 开源免费,无需付费即可获取实时行情
数据全面 支持国内所有期货交易所的实时行情和历史数据
上手简单 几行Python代码即可获取数据
文档完善 官方文档详细,示例代码丰富

安装方法:

bash 复制代码
pip install tqsdk

三、Tick数据基础

3.1 什么是Tick数据

概念 说明
Tick 每次行情变动产生的一条记录
频率 约500毫秒推送一次(交易所限制)
内容 价格、成交量、买卖盘口等
用途 高频分析、微观结构研究

3.2 Tick数据字段

字段 说明
datetime 时间戳
last_price 最新价
volume 累计成交量
amount 累计成交额
open_interest 持仓量
bid_price1 买一价
bid_volume1 买一量
ask_price1 卖一价
ask_volume1 卖一量

3.3 Tick vs K线

对比项 Tick数据 K线数据
精度 毫秒级 秒/分钟级
数据量 大 小
信息量 丰富 压缩
适用场景 高频、微观分析 趋势、技术分析
处理难度 高 低

四、获取Tick数据

4.1 实时Tick数据

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:获取期货实时Tick数据
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
from datetime import datetime

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

SYMBOL = "SHFE.rb2510"
quote = api.get_quote(SYMBOL)

print("=" * 70)
print(f"Tick数据实时监控 - {SYMBOL}")
print("=" * 70)
print(f"{'时间':<15} {'最新价':<10} {'成交量':<10} {'买一':<10} {'卖一':<10} {'持仓':<10}")
print("-" * 70)

last_volume = 0
tick_count = 0

while tick_count < 100:  # 收集100个Tick
    api.wait_update()
    
    if api.is_changing(quote, "last_price"):
        now = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        
        # 计算本次成交量
        tick_volume = quote.volume - last_volume if last_volume > 0 else 0
        last_volume = quote.volume
        
        print(f"{now:<15} {quote.last_price:<10.0f} {tick_volume:<10} "
              f"{quote.bid_price1:<10.0f} {quote.ask_price1:<10.0f} {quote.open_interest:<10.0f}")
        
        tick_count += 1

api.close()

4.2 Tick数据收集器

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:Tick数据收集器
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
from datetime import datetime
import pandas as pd
import time

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

SYMBOL = "SHFE.rb2510"
quote = api.get_quote(SYMBOL)

print("=" * 60)
print(f"Tick数据收集器 - {SYMBOL}")
print("=" * 60)

# 存储Tick数据
tick_data = []
last_volume = 0
collect_seconds = 60  # 收集60秒

start_time = time.time()

while time.time() - start_time < collect_seconds:
    api.wait_update()
    
    if api.is_changing(quote):
        tick_volume = quote.volume - last_volume if last_volume > 0 else 0
        last_volume = quote.volume
        
        tick = {
            "datetime": datetime.now(),
            "last_price": quote.last_price,
            "tick_volume": tick_volume,
            "bid_price1": quote.bid_price1,
            "bid_volume1": quote.bid_volume1,
            "ask_price1": quote.ask_price1,
            "ask_volume1": quote.ask_volume1,
            "open_interest": quote.open_interest,
        }
        tick_data.append(tick)
        
        print(f"\r收集中... {len(tick_data)} ticks", end="")

# 转换为DataFrame
df = pd.DataFrame(tick_data)

print(f"\n\n收集完成!共 {len(df)} 条Tick数据")
print("\n数据预览:")
print(df.head(10))

# 保存到CSV
filename = f"tick_{SYMBOL.replace('.', '_')}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
df.to_csv(filename, index=False)
print(f"\n数据已保存: {filename}")

api.close()

五、Tick数据分析

5.1 成交量分析

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:Tick数据成交量分析
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
from datetime import datetime
from collections import deque

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

SYMBOL = "SHFE.rb2510"
quote = api.get_quote(SYMBOL)

print("=" * 60)
print("Tick成交量分析")
print("=" * 60)

# 使用滑动窗口统计
WINDOW_SIZE = 50  # 50个Tick的窗口
tick_volumes = deque(maxlen=WINDOW_SIZE)
tick_prices = deque(maxlen=WINDOW_SIZE)

last_volume = 0
last_price = 0

# 统计变量
buy_volume = 0   # 主买量
sell_volume = 0  # 主卖量

while True:
    api.wait_update()
    
    if api.is_changing(quote, "last_price"):
        # 计算本Tick成交量
        tick_vol = quote.volume - last_volume if last_volume > 0 else 0
        price_change = quote.last_price - last_price if last_price > 0 else 0
        
        last_volume = quote.volume
        last_price = quote.last_price
        
        if tick_vol > 0:
            tick_volumes.append(tick_vol)
            tick_prices.append(quote.last_price)
            
            # 判断主买主卖(简化:价格上涨为主买,下跌为主卖)
            if price_change > 0:
                buy_volume += tick_vol
            elif price_change < 0:
                sell_volume += tick_vol
        
        # 统计
        if len(tick_volumes) >= 10:
            avg_vol = sum(tick_volumes) / len(tick_volumes)
            max_vol = max(tick_volumes)
            total_vol = sum(tick_volumes)
            
            # 大单判断(超过平均3倍)
            is_big_order = tick_vol > avg_vol * 3
            
            # 买卖力量对比
            total_bs = buy_volume + sell_volume
            buy_ratio = buy_volume / total_bs * 100 if total_bs > 0 else 50
            
            big_mark = " ★大单★" if is_big_order else ""
            print(f"\r价格={quote.last_price:.0f} 本笔={tick_vol:>5} "
                  f"均量={avg_vol:>5.0f} 最大={max_vol:>5} "
                  f"买/卖={buy_ratio:>5.1f}%{big_mark}      ", end="")

5.2 盘口分析

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:盘口数据分析
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
from datetime import datetime
from collections import deque

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

SYMBOL = "SHFE.rb2510"
quote = api.get_quote(SYMBOL)

print("=" * 70)
print("盘口分析")
print("=" * 70)

# 盘口历史
bid_history = deque(maxlen=100)
ask_history = deque(maxlen=100)
spread_history = deque(maxlen=100)

while True:
    api.wait_update()
    
    if api.is_changing(quote):
        bid1 = quote.bid_price1
        ask1 = quote.ask_price1
        bid_vol = quote.bid_volume1
        ask_vol = quote.ask_volume1
        
        # 计算买卖盘口比
        total_vol = bid_vol + ask_vol
        bid_ratio = bid_vol / total_vol * 100 if total_vol > 0 else 50
        
        # 价差
        spread = ask1 - bid1
        spread_history.append(spread)
        
        # 盘口失衡度
        imbalance = (bid_vol - ask_vol) / (bid_vol + ask_vol) if total_vol > 0 else 0
        
        # 统计
        avg_spread = sum(spread_history) / len(spread_history) if spread_history else 0
        
        # 判断盘口状态
        if imbalance > 0.3:
            status = "买盘强势"
        elif imbalance < -0.3:
            status = "卖盘强势"
        else:
            status = "均衡"
        
        print(f"\r买一={bid1:.0f}({bid_vol:>5}) | 卖一={ask1:.0f}({ask_vol:>5}) "
              f"价差={spread:.1f}(均{avg_spread:.1f}) 失衡={imbalance:+.2f} [{status}]    ", end="")

5.3 成交速度分析

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:成交速度分析
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth
from datetime import datetime
import time

api = TqApi(auth=TqAuth("快期账户", "快期密码"))

SYMBOL = "SHFE.rb2510"
quote = api.get_quote(SYMBOL)

print("=" * 60)
print("成交速度分析")
print("=" * 60)

# 统计周期(秒)
PERIOD = 5

last_volume = 0
period_start = time.time()
period_volume = 0
tick_count = 0

# 历史记录
speed_history = []

while True:
    api.wait_update()
    
    if api.is_changing(quote, "volume"):
        tick_vol = quote.volume - last_volume if last_volume > 0 else 0
        last_volume = quote.volume
        
        period_volume += tick_vol
        tick_count += 1
        
        # 每个周期统计
        elapsed = time.time() - period_start
        if elapsed >= PERIOD:
            speed = period_volume / elapsed  # 手/秒
            speed_history.append(speed)
            
            # 与历史对比
            if len(speed_history) > 1:
                avg_speed = sum(speed_history) / len(speed_history)
                speed_ratio = speed / avg_speed if avg_speed > 0 else 1
                
                if speed_ratio > 1.5:
                    status = "🔥 成交加速"
                elif speed_ratio < 0.5:
                    status = "❄️ 成交减速"
                else:
                    status = "📊 正常"
                
                print(f"\n[{datetime.now().strftime('%H:%M:%S')}] "
                      f"速度={speed:.1f}手/秒 均速={avg_speed:.1f} "
                      f"比值={speed_ratio:.2f}x {status}")
            
            # 重置
            period_start = time.time()
            period_volume = 0
            tick_count = 0

六、基于Tick的交易策略

6.1 大单跟踪策略

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:大单跟踪策略
说明:本代码仅供学习参考
"""

from tqsdk import TqApi, TqAuth, TqSim
from tqsdk.lib import TargetPosTask
from collections import deque
from datetime import datetime

# ============ 策略参数 ============
SYMBOL = "SHFE.rb2510"
BIG_ORDER_THRESHOLD = 50    # 大单阈值(手)
FOLLOW_SECONDS = 30         # 跟随时间窗口(秒)
MIN_BIG_ORDERS = 3          # 最少大单数量
LOTS = 1

# ============ 初始化 ============
api = TqApi(TqSim(init_balance=500000), auth=TqAuth("快期账户", "快期密码"))

quote = api.get_quote(SYMBOL)
position = api.get_position(SYMBOL)
target_pos = TargetPosTask(api, SYMBOL)

print("=" * 60)
print("大单跟踪策略")
print("=" * 60)
print(f"大单阈值: {BIG_ORDER_THRESHOLD}手")
print(f"跟随窗口: {FOLLOW_SECONDS}秒")
print("-" * 60)

# 大单记录
big_orders = deque()  # (timestamp, volume, direction)
last_volume = 0
last_price = 0
current_pos = 0

while True:
    api.wait_update()
    
    if api.is_changing(quote, "last_price"):
        tick_vol = quote.volume - last_volume if last_volume > 0 else 0
        price_change = quote.last_price - last_price if last_price > 0 else 0
        
        last_volume = quote.volume
        last_price = quote.last_price
        
        now = datetime.now()
        
        # 检测大单
        if tick_vol >= BIG_ORDER_THRESHOLD:
            direction = 1 if price_change >= 0 else -1
            big_orders.append((now, tick_vol, direction))
            print(f"\n[大单] {'买' if direction > 0 else '卖'} {tick_vol}手 @ {quote.last_price:.0f}")
        
        # 清理过期大单
        while big_orders and (now - big_orders[0][0]).seconds > FOLLOW_SECONDS:
            big_orders.popleft()
        
        # 统计窗口内大单
        if len(big_orders) >= MIN_BIG_ORDERS:
            buy_volume = sum(v for t, v, d in big_orders if d > 0)
            sell_volume = sum(v for t, v, d in big_orders if d < 0)
            
            # 判断信号
            net_direction = 0
            if buy_volume > sell_volume * 1.5:
                net_direction = 1
            elif sell_volume > buy_volume * 1.5:
                net_direction = -1
            
            # 执行交易
            current_pos = position.pos_long - position.pos_short
            if net_direction != 0 and current_pos != net_direction * LOTS:
                target_pos.set_target_volume(net_direction * LOTS)
                print(f"\n[跟随] {'做多' if net_direction > 0 else '做空'} "
                      f"买单={buy_volume} 卖单={sell_volume}")
        
        # 无信号时平仓
        elif len(big_orders) == 0 and current_pos != 0:
            target_pos.set_target_volume(0)
            print("\n[平仓] 大单信号消失")
        
        print(f"\r价格={quote.last_price:.0f} 大单数={len(big_orders)} "
              f"持仓={position.pos_long - position.pos_short}    ", end="")

七、Tick数据存储

7.1 保存到数据库

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:Tick数据存储到SQLite
说明:本代码仅供学习参考
"""

import sqlite3
from datetime import datetime

def create_tick_table(conn, symbol):
    """创建Tick数据表"""
    table_name = symbol.replace(".", "_")
    cursor = conn.cursor()
    cursor.execute(f"""
        CREATE TABLE IF NOT EXISTS {table_name} (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            datetime TEXT,
            last_price REAL,
            volume INTEGER,
            bid_price1 REAL,
            ask_price1 REAL,
            open_interest INTEGER
        )
    """)
    conn.commit()
    return table_name

def save_tick(conn, table_name, tick_data):
    """保存Tick数据"""
    cursor = conn.cursor()
    cursor.execute(f"""
        INSERT INTO {table_name} 
        (datetime, last_price, volume, bid_price1, ask_price1, open_interest)
        VALUES (?, ?, ?, ?, ?, ?)
    """, (
        tick_data["datetime"],
        tick_data["last_price"],
        tick_data["volume"],
        tick_data["bid_price1"],
        tick_data["ask_price1"],
        tick_data["open_interest"],
    ))
    conn.commit()

# 使用示例
# conn = sqlite3.connect("tick_data.db")
# table = create_tick_table(conn, "SHFE.rb2510")
# save_tick(conn, table, tick_data)

八、总结

要点 内容
Tick定义 每次行情变动的记录
更新频率 约500毫秒
核心字段 价格、成交量、盘口
分析维度 成交量、盘口、速度
适用策略 大单跟踪、盘口分析
数据存储 CSV、SQLite

免责声明:本文仅供学习交流使用,不构成任何投资建议。期货交易有风险,入市需谨慎。

更多资源:

相关推荐
Zootopia6269 分钟前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan15 分钟前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
Y38153266217 分钟前
搜索 API 延迟优化:并发数、超时与超时的真实代价
python·搜索引擎
wangqiaowq40 分钟前
PII 脱敏指的是:把个人身份信息(PII)中能识别到具体个人的敏感部分,用替换、遮蔽、变形等方式处理掉,使得数据在保留可用性的同时,不再直接暴露个人身份。
python
风早爽太1 小时前
Python 学习笔记:SQLModel 使用外键关联查询数据
python·fastapi·sqlmodel
专业程序开发源1 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
2601_960356381 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
在世修行2 小时前
干货:左右分栏调试工具设计
python·调试设计
h_a_o777oah2 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO92 小时前
指针的算术运算详解
java·数据结构·算法