Python期货数据分析入门_用代码探索市场规律
本文介绍了使用Python进行期货数据分析的常用方法。首先通过TqSdk获取期货历史K线数据并转换为DataFrame格式,然后从价格分布、收益率、成交量等维度进行基础统计分析。文章还展示了技术指标分析方法,包括均线系统(金叉/死叉信号)和波动率计算。这些分析有助于建立期货交易的数据思维框架,为后续策略开发奠定基础。所有代码示例均可直接运行,适合量化交易初学者参考学习。
·
免责声明:本文基于个人使用体验,与任何厂商无商业关系。内容仅供技术交流参考,不构成投资建议。
一、前言
很多人学量化交易一上来就想写策略、跑回测,其实第一步应该是学会用数据说话。Python在数据分析领域的生态非常成熟,pandas、numpy、matplotlib这些库足以应对大部分期货数据分析需求。
今天分享一下我用Python做期货数据分析的常用方法,帮助入门的朋友建立数据分析的思维框架。
二、数据获取
分析的第一步是获取数据。以下用TqSdk获取历史K线数据:
from tqsdk import TqApi, TqAuth
import pandas as pd
import numpy as np
api = TqApi(auth=TqAuth("账户", "密码"))
# 获取螺纹钢日线数据
symbol = "SHFE.rb2510"
klines = api.get_kline_serial(symbol, 86400, 500) # 日线,500根
# 转为DataFrame方便分析
df = pd.DataFrame({
'datetime': pd.to_datetime(klines['datetime']),
'open': klines['open'],
'high': klines['high'],
'low': klines['low'],
'close': klines['close'],
'volume': klines['volume'],
'open_interest': klines['open_interest']
})
df = df.set_index('datetime')
print(f"数据量: {len(df)} 条")
print(df.tail())
api.close()
三、基础统计分析
1. 价格分布分析
import matplotlib.pyplot as plt
def analyze_price_distribution(df):
"""分析价格分布"""
close = df['close']
stats = {
'均值': close.mean(),
'中位数': close.median(),
'标准差': close.std(),
'最大值': close.max(),
'最小值': close.min(),
'偏度': close.skew(),
'峰度': close.kurtosis()
}
for key, value in stats.items():
print(f"{key}: {value:.2f}")
return stats
# 使用示例
stats = analyze_price_distribution(df)
2. 收益率分析
def analyze_returns(df):
"""分析收益率特征"""
# 计算日收益率
returns = df['close'].pct_change().dropna()
print("=== 收益率统计 ===")
print(f"日均收益率: {returns.mean():.4%}")
print(f"年化收益率: {returns.mean() * 252:.2%}")
print(f"日波动率: {returns.std():.4%}")
print(f"年化波动率: {returns.std() * np.sqrt(252):.2%}")
print(f"最大日涨幅: {returns.max():.2%}")
print(f"最大日跌幅: {returns.min():.2%}")
print(f"正收益天数: {(returns > 0).sum()}")
print(f"负收益天数: {(returns < 0).sum()}")
print(f"胜率: {(returns > 0).sum() / len(returns):.2%}")
return returns
returns = analyze_returns(df)
3. 成交量分析
def analyze_volume(df):
"""分析成交量特征"""
volume = df['volume']
# 成交量统计
print("=== 成交量统计 ===")
print(f"日均成交量: {volume.mean():.0f}")
print(f"成交量标准差: {volume.std():.0f}")
print(f"最大成交量: {volume.max():.0f}")
print(f"最小成交量: {volume.min():.0f}")
# 量价关系
price_change = df['close'].pct_change()
vol_change = volume.pct_change()
# 计算量价相关性
correlation = price_change.corr(vol_change)
print(f"\n量价相关性: {correlation:.4f}")
# 分析放量上涨/缩量下跌等模式
vol_avg = volume.rolling(20).mean()
high_vol = volume > vol_avg * 1.5 # 放量
low_vol = volume < vol_avg * 0.5 # 缩量
up = price_change > 0
down = price_change < 0
patterns = {
'放量上涨': (high_vol & up).sum(),
'放量下跌': (high_vol & down).sum(),
'缩量上涨': (low_vol & up).sum(),
'缩量下跌': (low_vol & down).sum()
}
print("\n量价模式统计:")
for pattern, count in patterns.items():
print(f" {pattern}: {count}次")
return patterns
patterns = analyze_volume(df)
四、技术指标分析
1. 均线系统分析
def analyze_moving_averages(df, short_period=5, long_period=20):
"""分析均线系统"""
close = df['close']
# 计算均线
ma_short = close.rolling(short_period).mean()
ma_long = close.rolling(long_period).mean()
# 金叉死叉统计
golden_cross = (ma_short > ma_long) & (ma_short.shift(1) <= ma_long.shift(1))
death_cross = (ma_short < ma_long) & (ma_short.shift(1) >= ma_long.shift(1))
print(f"=== MA{short_period}/MA{long_period} 均线分析 ===")
print(f"金叉次数: {golden_cross.sum()}")
print(f"死叉次数: {death_cross.sum()}")
# 分析金叉后N天的收益
golden_dates = df.index[golden_cross]
forward_returns = []
for date in golden_dates:
idx = df.index.get_loc(date)
if idx + 10 < len(df):
ret_5d = (df['close'].iloc[idx + 5] - df['close'].iloc[idx]) / df['close'].iloc[idx]
ret_10d = (df['close'].iloc[idx + 10] - df['close'].iloc[idx]) / df['close'].iloc[idx]
forward_returns.append({
'date': date,
'5日收益': ret_5d,
'10日收益': ret_10d
})
if forward_returns:
fr_df = pd.DataFrame(forward_returns)
print(f"\n金叉后平均5日收益: {fr_df['5日收益'].mean():.2%}")
print(f"金叉后平均10日收益: {fr_df['10日收益'].mean():.2%}")
print(f"金叉后5日正收益比例: {(fr_df['5日收益'] > 0).sum() / len(fr_df):.2%}")
return forward_returns
ma_results = analyze_moving_averages(df, 5, 20)
2. 波动率分析
def analyze_volatility(df, window=20):
"""分析波动率特征"""
returns = df['close'].pct_change().dropna()
# 历史波动率(滚动)
rolling_vol = returns.rolling(window).std() * np.sqrt(252)
# ATR计算
high = df['high']
low = df['low']
close_prev = df['close'].shift(1)
tr = pd.concat([
high - low,
(high - close_prev).abs(),
(low - close_prev).abs()
], axis=1).max(axis=1)
atr = tr.rolling(window).mean()
# 波动率区间分析
print("=== 波动率分析 ===")
print(f"当前年化波动率: {rolling_vol.iloc[-1]:.2%}")
print(f"平均年化波动率: {rolling_vol.mean():.2%}")
print(f"最高年化波动率: {rolling_vol.max():.2%}")
print(f"最低年化波动率: {rolling_vol.min():.2%}")
print(f"当前ATR: {atr.iloc[-1]:.2f}")
print(f"平均ATR: {atr.mean():.2f}")
# 波动率聚集性分析
vol_autocorr = rolling_vol.autocorr(lag=1)
print(f"\n波动率自相关(lag=1): {vol_autocorr:.4f}")
if vol_autocorr > 0.5:
print("波动率存在明显聚集性")
return rolling_vol, atr
vol, atr = analyze_volatility(df)
五、市场规律探索
1. 日内时间效应
def analyze_intraday_pattern(api, symbol):
"""分析日内时间效应"""
# 获取分钟K线
klines = api.get_kline_serial(symbol, 60, 5000) # 1分钟线
df = pd.DataFrame({
'datetime': pd.to_datetime(klines['datetime']),
'close': klines['close'],
'volume': klines['volume']
})
# 提取小时
df['hour'] = df['datetime'].dt.hour
df['minute'] = df['datetime'].dt.minute
df['time_slot'] = df['hour'].astype(str) + ':' + df['minute'].astype(str).str.zfill(2)
# 按小时统计
hourly_stats = df.groupby('hour').agg({
'volume': 'mean',
'close': lambda x: x.pct_change().std() # 波动率
})
print("=== 日内时间效应 ===")
print("各小时平均成交量和波动率:")
print(hourly_stats)
return hourly_stats
2. 星期效应
def analyze_weekday_effect(df):
"""分析星期效应"""
returns = df['close'].pct_change().dropna()
# 按星期分组
df_with_returns = df.copy()
df_with_returns['return'] = returns
df_with_returns['weekday'] = df_with_returns.index.dayofweek
weekday_names = {0: '周一', 1: '周二', 2: '周三', 3: '周四', 4: '周五'}
print("=== 星期效应分析 ===")
for day in range(5):
day_returns = df_with_returns[df_with_returns['weekday'] == day]['return']
if len(day_returns) > 0:
print(f"{weekday_names[day]}: "
f"均值={day_returns.mean():.4%}, "
f"波动={day_returns.std():.4%}, "
f"胜率={((day_returns > 0).sum() / len(day_returns)):.2%}")
analyze_weekday_effect(df)
3. 持仓量与价格关系
def analyze_oi_price_relationship(df):
"""分析持仓量与价格的关系"""
price_change = df['close'].pct_change()
oi_change = df['open_interest'].pct_change()
# 相关性
correlation = price_change.corr(oi_change)
print(f"=== 持仓量与价格关系 ===")
print(f"相关系数: {correlation:.4f}")
# 四象限分析
up_price = price_change > 0
down_price = price_change < 0
up_oi = oi_change > 0
down_oi = oi_change < 0
patterns = {
'价涨+持仓增(多头增仓)': (up_price & up_oi).sum(),
'价涨+持仓减(空头减仓)': (up_price & down_oi).sum(),
'价跌+持仓增(空头增仓)': (down_price & up_oi).sum(),
'价跌+持仓减(多头减仓)': (down_price & down_oi).sum()
}
total = sum(patterns.values())
print("\n持仓量-价格四象限:")
for pattern, count in patterns.items():
print(f" {pattern}: {count}次 ({count/total:.1%})")
analyze_oi_price_relationship(df)
六、数据分析工具对比
做这些分析不一定非要用某一个特定工具,但数据获取方式有差异:
| 工具 | 数据获取便利性 | 分析灵活性 | 适合场景 |
|---|---|---|---|
| TqSdk + pandas | ★★★★★ | ★★★★★ | 期货数据分析 |
| VnPy + pandas | ★★★ | ★★★★★ | 需自建数据库 |
| 聚宽/米筐 | ★★★★ | ★★★★ | 主要面向股票 |
| 文华财经 | ★★★★ | ★★ | 简单看图分析 |
我个人习惯用TqSdk获取数据,然后用pandas做深度分析。主要是因为数据获取方便,不需要额外配置数据库。
七、总结
数据分析是量化交易的基础功课。通过系统的数据分析,你可以:
- 了解品种特性:波动率、成交量分布、趋势特征
- 发现市场规律:时间效应、量价关系、持仓量信号
- 验证交易想法:用数据而非直觉来判断策略可行性
- 优化策略参数:基于统计分析选择合理的参数范围
建议每个做量化交易的人都花时间做一遍自己交易品种的数据分析,这对后续的策略开发会有很大帮助。
这只是我个人的分析方法和工具选择,每个人可以根据自己的需求调整。
声明:本文基于个人学习经验整理,仅供技术交流参考,不构成任何投资建议。文中提及的工具和方法请自行评估是否适合自己的需求。
更多推荐
所有评论(0)