各位期友们,如果问你们对哪个期货品种记忆犹新,锰硅(SM888)绝对能排进前三!这个品种平时像个“佛系青年”,不温不火,可一旦行情启动,那简直是“平地惊雷”,涨跌都能让你怀疑人生。比如2024年4月初到5月底,锰硅从6000点一路狂飙到近10000点,仿佛坐上了火箭。然而,好景不长,接下来的一个半月,它又从高点跌回6000点,简直是“过山车”行情。最近,由于锰矿原产地的供应问题,锰硅又上演了一波“旱地拔葱”,短短几个交易日拉高了1400点,结果传闻被证伪后,又迅速打回原形,真是让人哭笑不得。
很多散户朋友在这波行情中可能经历了“多空双杀”,苦不堪言。由于信息不对称,散户常常被大行情“玩弄于股掌之间”。那么,有没有一种方法可以帮助我们识别行情的引爆点呢?今天,我们就从量价关系的角度,带大家一探究竟。
我们经常在期货行情软件上看到“量增价减”、“量减价减”、“量减价增”、“量增价增”这些术语。听起来很高大上,但它们到底是什么意思?这些现象出现后,期货行情会不会迎来大爆发?今天,我们就用量化研究的方法,在优宽量化平台上为大家揭开这些术语背后的秘密。
首先,我们来看一下代码的逻辑。这段代码的核心是通过分析历史数据,识别四种量价关系,并跟踪这些事件发生后的市场表现。以下是代码的主要步骤:
初始化数据结构:我们创建了一个tracking_events
队列,用于存储正在跟踪的事件。同时,定义了一个followup_days
变量,表示我们需要跟踪事件发生后的5天内的市场表现。
获取历史数据:通过exchange.GetRecords
函数获取锰硅(SM888)的历史数据。如果数据不足22根K线,程序会暂停1秒后重新尝试。
检测量价关系:代码会检测四种量价关系:
每种量价关系的判断标准都基于当前K线与前一根K线的收盘价、成交量和持仓量的变化。
跟踪事件:一旦检测到某种量价关系,代码会将该事件加入tracking_events
队列,并开始跟踪该事件发生后的市场表现。跟踪的时间长度为followup_days
(5天)。
计算波动幅度:在跟踪期间,代码会记录价格的最高点、最低点,并计算相对于事件发生时的波动幅度。
保存结果:最终,所有检测到的事件及其后续表现会被保存到一个CSV文件中,方便后续分析。
'''backtest
start: 2020-01-03 00:00:00
end: 2025-02-12 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''
import pandas as pd
def main():
# 初始化数据结构
tracking_events = [] # 正在跟踪的事件队列
followup_days = 5 # 需要跟踪的天数
symbol = 'SM888'
markTime = 0
# 创建用于存储结果的DataFrame
results_df = pd.DataFrame(columns=[
'EventType',
'StartDate',
'OpenPrice',
'MaxHigh',
'MinLow',
'MaxAmplitude',
'MinAmplitude'
])
while True:
# 获取当前交易对的历史数据
records = exchange.GetRecords(symbol, PERIOD_D1)
# 如果数据为空或不足22根K线,则跳过当前循环
if not records or len(records) < 22:
Sleep(1000) # 暂停1秒
continue
# 检查数据时间是否更新,如果更新则继续处理
if markTime != records[-2].Time:
markTime = records[-2].Time
# 将数据转换为DataFrame,方便后续处理
data = [{
'Time': record.Time,
'Open': record.Open,
'High': record.High,
'Low': record.Low,
'Close': record.Close,
'Volume': record.Volume,
'OpenInterest': record.OpenInterest
} for record in records]
try:
df = pd.DataFrame(data)
except Exception as e:
Log(f"创建DataFrame时出错: {e}")
continue
df = df[-22:-1] # 取最近20根有效K线
# 获取当前与前一根K线的各项统计指标
current_close, prev_close = df.iloc[-1]['Close'], df.iloc[-2]['Close']
current_volume, prev_volume = df.iloc[-1]['Volume'], df.iloc[-2]['Volume']
current_int, prev_int = df.iloc[-1]['OpenInterest'], df.iloc[-2]['OpenInterest']
# 检测四种量价关系
events = []
# 量减价跌
if (current_close / prev_close < 0.9925 and
current_volume / prev_volume < 0.8 and
current_int / prev_int < 0.95):
Log('量减价减')
events.append('numMinpriMin')
# 量减价涨
if (current_close / prev_close > 1.0075 and
current_volume / prev_volume < 0.8 and
current_int / prev_int < 0.95):
Log('量减价增')
events.append('numMinpriAdd')
# 量增价跌
if (current_close / prev_close < 0.9925 and
current_volume / prev_volume > 1.3 and
current_int / prev_int > 1.1):
Log('量增价减')
events.append('numAddpriMin')
# 量增价增
if (current_close / prev_close > 1.0075 and
current_volume / prev_volume > 1.3 and
current_int / prev_int > 1.1):
Log('量增价增')
events.append('numAddpriAdd')
# 将新检测到的事件添加到跟踪队列中
for event_type in events:
tracking_events.append({
'type': event_type,
'start_time': records[-1]['Time'],
'opens': [records[-1]['Open']],
'highs': [records[-1]['Open']],
'lows': [records[-1]['Open']],
'days_collected': 0
})
# 处理正在跟踪的事件,逐天收集数据
for event in tracking_events[:]: # 使用副本避免在循环中修改原列表
# 获取事件发生后的后续数据
if event['days_collected'] == 0:
event['days_collected'] = 1
break
if event['days_collected'] < followup_days + 1:
event['days_collected'] += 1
event['opens'].append(records[-1]['Open'])
event['highs'].append(records[-2]['High'])
event['lows'].append(records[-2]['Low'])
# 如果已收集足够天数,处理并移除事件
if event['days_collected'] >= followup_days + 1:
first_close = event['opens'][0]
max_high = max(event['highs'])
min_low = min(event['lows'])
# 计算波动幅度
max_amplitude = (max_high - first_close) / first_close * 100
min_amplitude = (first_close - min_low) / first_close * 100
# 存入结果
# 创建一个新的行数据
new_row = pd.DataFrame({
'EventType': [event['type']],
'StartDate': [pd.to_datetime(event['start_time'], unit='ms')],
'OpenPrice': [first_close],
'MaxHigh': [max_high],
'MinLow': [min_low],
'MaxAmplitude': [f"{max_amplitude:.2f}%"],
'MinAmplitude': [f"{min_amplitude:.2f}%"]
})
# 使用 pd.concat 添加新行
results_df = pd.concat([results_df, new_row], ignore_index=True)
# 移除已完成的事件
tracking_events.remove(event)
# 每轮循环结束后,将结果保存到CSV文件
results_df.to_csv('量价关系.csv', index=False)
# 等待下一根K线
Sleep(1000 * 60 * 5) # 5分钟周期调整为对应时间
数据回测事件为2020年1月至2025年2月,各事件类型的出现频率,涨跌幅统计特征值在下面表格中进行呈现。根据我们的量化研究,我们得到了以下结果:
事件类型 | 计数 | 涨幅最大值 | 涨幅最小值 | 跌幅最大值 | 跌幅最小值 | 涨幅均值 | 跌幅均值 |
---|---|---|---|---|---|---|---|
量增价增 | 25 | 17.77% | 0.00% | 7.84% | 0.06% | 4.94% | 2.86% |
量增价减 | 21 | 8.59% | 0.05% | 5.53% | 0.00% | 2.65% | 1.84% |
量减价增 | 12 | 8.64% | 0.28% | 8.22% | 0.28% | 2.94% | 3.41% |
量减价减 | 12 | 6.45% | 0.35% | 25.98% | 0.44% | 2.62% | 5.77% |
数据回测事件为2020年1月至2025年2月,各事件类型的出现频率
通过这次量化研究,我们发现,量价关系确实是期货行情的“晴雨表”。不同的量价组合,往往预示着不同的市场走势。对于散户朋友来说,掌握这些规律,可以帮助你更好地识别行情的引爆点,避免被大行情“玩弄”。
当然,市场永远是复杂多变的,量价关系只是其中的一个参考指标。在实际操作中,还需要结合其他技术指标和基本面分析,才能做出更准确的判断。希望这篇文章能为大家提供一些有用的参考,祝各位期友在期货市场中乘风破浪,不受庄家摆布!
温馨提示:期货市场风险较大,入市需谨慎。量价关系虽好,但不可盲目依赖哦!