【维克】多时间框架分析:如何在日线、小时线、分钟线间切换?

0 阅读20分钟

系列:量化笔记 · 第61篇

关键词:#多时间框架 #时间分析 #图表分析 #交易周期 #多周期

上一篇讲了怎么把Tick数据聚合成分钟K线。

数据有了,但怎么用?

只看1分钟线?容易被噪音淹没。只看日线?又太粗糙,错过日内机会。

专业交易员的答案是:多个时间框架同时看,大周期定方向,小周期找入场。

这就是今天的主角——多时间框架分析(Multiple Time Frame Analysis)。

WHY:一个因为"只看一个周期"亏掉40万的故事

老赵的"精准入场"是怎么变成"精准被套"的

老赵做了两年量化,水平不差。

他写了一个基于5分钟MACD的策略,逻辑简单:金叉买入,死叉卖出。

回测了半年,胜率58%,盈亏比1.5:1,年化25%。

他投了40万实盘。

第一个月,赚了5万。他觉得稳了。

第二个月,亏了15万。

第三个月,又亏了25万。

三个月总亏损35万。

他崩溃了:"回测好好的,怎么实盘就崩了?"

我让他把实盘的交易记录给我看。

一看,问题很明显——

他只看了5分钟线,没有看更大周期的趋势方向。

具体来看几个典型案例:

案例一:逆势做多

2024年3月,某只股票日线连续下跌,从15元跌到12元,日线趋势明确向下。

但某天上午,5分钟MACD出现了金叉。

老赵的策略信号是"买入"。

他买了。

结果?5分钟金叉只是日线下跌趋势中的一个反弹。反弹了半小时就继续跌。

他50手买入,亏了12个点止损。

如果他在5分钟买入之前,先看一眼日线——日线明确下跌,就不应该做多。

案例二:在大级别震荡区反复被打脸

2024年5月,某只股票在13-14元之间横盘震荡了两周。

日线没有方向,小时线也没有方向。

但5分钟线上,MACD金叉死叉交替出现——一会儿"买入",一会儿"卖出"。

老赵的策略在两周内交易了35次。

胜率52%——看起来还行?

但每次"买入"只赚一点小利润(因为大级别没方向,涨不上去),每次"卖出"止损都亏不少(因为偶尔的突破又会拉回来)。

盈亏比从回测的1.5:1降到了实盘的0.6:1。

如果他在日线/小时线震荡时,暂停5分钟策略——就不会在"没方向"的行情里反复被割。

案例三:错过了大级别的趋势反转

2024年7月,某只股票在日线上形成了双底形态,即将突破。

小时线也出现了明显的上升趋势。

但5分钟线上,刚好有一次回调,MACD死叉。

老赵的策略信号是"卖出"。

他不仅没买入,还平掉了之前的多单。

然后股票大涨15%。

他本应在那个大级别看涨的时刻,积极做多。但他的5分钟策略告诉他"卖出"。

三个案例的共同问题

只用一个时间框架做决策,就像只看后视镜开车。

5分钟线告诉你"现在这一秒的动量方向",但不告诉你"大趋势在哪"。

日线告诉你"大趋势在哪",但不告诉你"现在是不是好的入场点"。

只有把多个时间框架结合起来,才能既看清大方向,又找到精确入场点。

WHAT:多时间框架分析的核心理念

用"看地图"理解多时间框架

想象你在开车去一个陌生城市。

你需要三层地图:

1. 全国地图(大周期):确定你要去的城市在哪个方向。往北还是往南?

2. 城市地图(中周期):确定你要去的区域。走哪条高速?从哪个出口下?

3. 街道地图(小周期):确定具体的路线。哪个路口左转?哪个停车场入口?

如果你只看街道地图——你能走对每条小路,但可能整体方向就是反的。越努力,离目标越远。

如果你只看全国地图——你知道大方向,但到了城市里不知道怎么走。

三层地图配合使用,才能又快又准地到达目的地。

多时间框架分析就是这个道理:

| 时间框架 | 角色 | 作用 | | --- | --- | --- | | 大周期(日线/周线) | "全国地图" | 确定大趋势方向 | | 中周期(小时线/60分钟) | "城市地图" | 确定中期趋势和关键位置 | | 小周期(5分钟/15分钟) | "街道地图" | 精确入场和出场 |

经典的多时间框架组合

不同的交易风格,适合不同的时间框架组合:

| 交易风格 | 大周期 | 中周期 | 小周期 | 持仓周期 | | --- | --- | --- | --- | --- | | 日内短线 | 日线 | 60分钟 | 5分钟 | 几分钟几小时 | | 日内波段 | 日线 | 60分钟 | 15分钟 | 几小时1天 | | 短线波段 | 周线 | 日线 | 60分钟 | 15天 | | 中线波段 | 月线 | 周线 | 日线 | 14周 | | 长线趋势 | 年线 | 月线 | 周线 | 数月~数年 |

关键原则:大周期至少是小周期的4~5倍以上。

比如:

• 5分钟 → 60分钟(12倍)✅

• 15分钟 → 日线(16倍)✅

• 60分钟 → 周线(约5倍)✅

• 5分钟 → 15分钟(3倍)❌ 差距太小,信息重叠

三重滤网法

多时间框架分析最经典的实现方式是亚历山大·埃尔德(Alexander Elder)提出的三重滤网法

核心思想:每一层时间框架像一个"滤网",只有信号连续通过三层滤网,才执行交易。

第一层滤网(大周期):判断趋势方向

• 用日线级别的趋势指标(如MACD柱状图、均线系统)判断大方向

• 如果日线趋势向上 → 只允许做多

• 如果日线趋势向下 → 只允许做空(A股则只能空仓观望)

第二层滤网(中周期):寻找回调机会

• 在大趋势方向确定后,等中周期出现逆势回调

• 日线看涨 → 等小时线出现回调(比如小时线RSI超卖或MACD死叉后金叉)

• 这个回调就是"打折入场"的机会

第三层滤网(小周期):精确入场

• 在中周期回调到位后,用小周期找入场点

• 小时线回调到位 → 等5分钟线出现顺势突破信号

• 这个信号就是精确的入场时机

举个例子:

日线趋势:上涨 ↑ → 只允许做多

小时线:回调到低位,出现企稳信号 → 准备做多

5分钟线:MACD金叉,放量突破 → 执行买入

三层滤网的关系:大周期决定方向,中周期决定时机,小周期决定入场点。

多时间框架的核心规则

规则一:大周期优先

当大周期和小周期信号冲突时,以大周期为准。

• 日线下跌 + 5分钟买入信号 → 忽略5分钟信号(或轻仓试探)

• 日线上涨 + 5分钟卖出信号 → 可能是短线回调,不一定真的要卖

规则二:共振交易

当多个时间框架同时发出同方向信号时,交易的胜率最高。

• 日线看涨 + 小时线看涨 + 5分钟看涨 → 强做多信号

• 三个周期同时看跌 → 强做空/离场信号

规则三:不做"没有大周期支持"的交易

如果大周期没有明确趋势(横盘震荡),就不做小周期信号。

因为大周期震荡时,小周期的信号胜率会大幅下降。

HOW:多时间框架分析实操(Python代码+逐行讲解)

第一步:准备多时间框架数据

首先,你需要同时拥有多个时间周期的数据。

// python
import pandas as pd
import numpy as np

# 假设你已经有了以下数据:
# 1. 日线数据(从数据源获取)
# 2. 60分钟线数据(从数据源获取或从Tick聚合)
# 3. 5分钟线数据(从数据源获取或从Tick聚合)

# 演示:从日线数据生成不同周期的数据
def generate_multi_timeframe_data(daily_df):
"""
基于日线数据,模拟生成多时间框架数据
实际使用中,你应该从数据源直接获取各周期的数据
"""
# 日线数据(假设已有)
# daily_df 包含: datetime, open, high, low, close, volume

    # 为了演示,我们从日线"放大"生成模拟的60分钟和5分钟数据
# 实际中你应该直接获取真实数据

    # 这里用日线加上随机噪音来模拟分钟数据
np.random.seed(42)

    intraday_list = []

    for _, row in daily_df.iterrows():
date = row['datetime']
daily_open = row['open']
daily_close = row['close']
daily_high = row['high']
daily_low = row['low']
daily_volume = row['volume']

        # 生成一天48根5分钟K线(简化模拟)
for i in range(48):
# 模拟价格路径
progress = i / 47  # 0到1
base_price = daily_open + (daily_close - daily_open) * progress
noise = np.random.normal(0, (daily_high - daily_low) * 0.05)
price = base_price + noise

            # 确保在日线范围内
price = max(daily_low, min(daily_high, price))

            # 模拟时间
if i < 24:
hour = 9 + (i * 5 + 30) // 60
minute = (i * 5 + 30) % 60
if minute >= 60:
hour += 1
minute -= 60
else:
j = i - 24
hour = 13 + (j * 5) // 60
minute = (j * 5) % 60

            ts = pd.Timestamp(date) + pd.Timedelta(hours=hour-9, minutes=minute)

            intraday_list.append({
'datetime': ts,
'open': price - 0.02,
'high': price + 0.05,
'low': price - 0.05,
'close': price,
'volume': daily_volume / 48,
'date': date
})

    df_5min = pd.DataFrame(intraday_list)

    # 从5分钟聚合出60分钟
df_5min['datetime'] = pd.to_datetime(df_5min['datetime'])
df_60min = df_5min.set_index('datetime').resample('60min').agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum',
'date': 'first'
}).dropna().reset_index()

    return daily_df, df_60min, df_5min

# 实际使用中,你应该分别获取三个周期的真实数据:
# daily_df = get_daily_data('000001')
# df_60min = get_60min_data('000001')
# df_5min = get_5min_data('000001')

第二步:计算各周期的技术指标

每个时间框架都需要计算自己的技术指标:

// python
def calc_indicators(df):
"""
为K线数据计算常用技术指标
"""
# 均线
df['ma5'] = df['close'].rolling(5).mean()
df['ma10'] = df['close'].rolling(10).mean()
df['ma20'] = df['close'].rolling(20).mean()
df['ma60'] = df['close'].rolling(60).mean()

    # MACD
ema12 = df['close'].ewm(span=12, adjust=False).mean()
ema26 = df['close'].ewm(span=26, adjust=False).mean()
df['macd_dif'] = ema12 - ema26
df['macd_dea'] = df['macd_dif'].ewm(span=9, adjust=False).mean()
df['macd_hist'] = 2 * (df['macd_dif'] - df['macd_dea'])

    # RSI
delta = df['close'].diff()
gain = delta.where(delta > 0, 0).rolling(14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
rs = gain / loss
df['rsi'] = 100 - (100 / (1 + rs))

    # 布林带
df['bb_mid'] = df['close'].rolling(20).mean()
bb_std = df['close'].rolling(20).std()
df['bb_upper'] = df['bb_mid'] + 2 * bb_std
df['bb_lower'] = df['bb_mid'] - 2 * bb_std

    # ATR(平均真实波幅,用于止损)
high_low = df['high'] - df['low']
high_prev_close = (df['high'] - df['close'].shift(1)).abs()
low_prev_close = (df['low'] - df['close'].shift(1)).abs()
true_range = pd.concat([high_low, high_prev_close, low_prev_close], axis=1).max(axis=1)
df['atr'] = true_range.rolling(14).mean()

    return df

# 为三个时间框架分别计算指标
# daily = calc_indicators(daily_df.copy())
# h1 = calc_indicators(df_60min.copy())
# m5 = calc_indicators(df_5min.copy())

# print("=== 日线指标 ===")
# print(daily[['datetime', 'close', 'ma5', 'ma20', 'macd_dif', 'rsi']].tail())

第三步:大周期判断趋势方向

第一层滤网——用日线判断大趋势:

// python
def judge_daily_trend(daily):
"""
用日线数据判断大趋势方向
返回:1(看涨)、-1(看跌)、0(震荡)
"""
latest = daily.iloc[-1]
prev = daily.iloc[-2] if len(daily) > 1 else latest

    signals = []

    # 信号1:均线排列
# 多头排列:ma5 > ma10 > ma20 > ma60
if latest['ma5'] > latest['ma10'] > latest['ma20']:
signals.append(1)  # 看涨
elif latest['ma5'] < latest['ma10'] < latest['ma20']:
signals.append(-1)  # 看跌
else:
signals.append(0)  # 混乱/震荡

    # 信号2:MACD方向
if latest['macd_dif'] > latest['macd_dea'] and latest['macd_hist'] > 0:
signals.append(1)
elif latest['macd_dif'] < latest['macd_dea'] and latest['macd_hist'] < 0:
signals.append(-1)
else:
signals.append(0)

    # 信号3:价格与MA20的关系
if latest['close'] > latest['ma20'] * 1.02:  # 收盘价高于20日均线2%以上
signals.append(1)
elif latest['close'] < latest['ma20'] * 0.98:  # 收盘价低于20日均线2%以上
signals.append(-1)
else:
signals.append(0)

    # 综合判断:多数投票
bullish = signals.count(1)
bearish = signals.count(-1)

    if bullish >= 2:
trend = 1
trend_text = "看涨(多头)"
elif bearish >= 2:
trend = -1
trend_text = "看跌(空头)"
else:
trend = 0
trend_text = "震荡(无方向)"

    print(f"日线趋势判断:{trend_text}")
print(f"  均线排列信号:{'看涨' if signals[0]==1 else '看跌' if signals[0]==-1 else '震荡'}")
print(f"  MACD信号:{'看涨' if signals[1]==1 else '看跌' if signals[1]==-1 else '震荡'}")
print(f"  价格vs MA20:{'看涨' if signals[2]==1 else '看跌' if signals[2]==-1 else '震荡'}")

    return trend

# daily_trend = judge_daily_trend(daily)

第四步:中周期寻找回调入场区

第二层滤网——在小时线上找回调到位的信号:

// python
def find_h1_entry_zone(h1, daily_trend):
"""
在小时线上寻找回调入场机会
daily_trend: 日线趋势方向(1=看涨,-1=看跌,0=震荡)
"""
if daily_trend == 0:
print("\n日线震荡,不建议交易,跳过小时线分析")
return None

    latest_h1 = h1.iloc[-1]

    if daily_trend == 1:
# 日线看涨 → 在小时线上找回调到位的信号
print("\n日线看涨,在小时线寻找回调买入机会...")

        signals = []

        # 信号1:RSI超卖后回升(回调到位)
if latest_h1['rsi'] < 40:
signals.append(1)
print(f"  RSI={latest_h1['rsi']:.1f},接近超卖区 ✅")
elif latest_h1['rsi'] < 50:
signals.append(0.5)
print(f"  RSI={latest_h1['rsi']:.1f},偏弱但未超卖 ⚠️")
else:
signals.append(0)
print(f"  RSI={latest_h1['rsi']:.1f},偏高(可能还没回调到位)❌")

        # 信号2:价格回调到布林带下轨或中轨附近
if latest_h1['close'] <= latest_h1['bb_lower'] * 1.01:
signals.append(1)
print(f"  价格触及布林下轨 ✅")
elif latest_h1['close'] <= latest_h1['bb_mid'] * 1.01:
signals.append(0.5)
print(f"  价格回调到布林中轨附近 ⚠️")
else:
signals.append(0)
print(f"  价格离布林下轨较远 ❌")

        # 信号3:MACD柱状图由负转正或收窄
if latest_h1['macd_hist'] > 0:
signals.append(1)
print(f"  MACD柱状图转正 ✅")
elif latest_h1['macd_hist'] > h1.iloc[-2]['macd_hist']:
signals.append(0.5)
print(f"  MACD柱状图收窄(可能在好转)⚠️")
else:
signals.append(0)
print(f"  MACD柱状图仍在扩大 ❌")

        # 综合评分
score = sum(signals) / len(signals)

        if score >= 0.6:
print(f"\n  📍 小时线回调评分:{score:.2f} → 回调到位,等待5分钟入场信号")
return 'buy'
else:
print(f"\n  ⏳ 小时线回调评分:{score:.2f} → 回调尚未到位,继续等待")
return 'wait'

    elif daily_trend == -1:
# 日线看跌 → 在小时线上找反弹到位的信号(A股则观望)
print("\n日线看跌,A股无法做空,建议空仓观望")
return None

# h1_signal = find_h1_entry_zone(h1, daily_trend)

第五步:小周期精确入场

第三层滤网——在5分钟线上找精确入场点:

// python
def find_m5_entry(m5, direction='buy'):
"""
在5分钟线上寻找精确入场点
direction: 'buy' 或 'sell'
"""
if direction is None:
return None

    latest = m5.iloc[-1]
prev = m5.iloc[-2]

    if direction == 'buy':
signals = []

        # 信号1:MACD金叉
if prev['macd_dif'] < prev['macd_dea'] and latest['macd_dif'] >= latest['macd_dea']:
signals.append('MACD金叉')

        # 信号2:放量突破(当前成交量 > 前5根平均成交量的1.5倍)
avg_vol = m5['volume'].iloc[-6:-1].mean()
if latest['volume'] > avg_vol * 1.5:
signals.append('放量')

        # 信号3:价格站上MA5
if latest['close'] > latest['ma5']:
signals.append('站上MA5')

        # 信号4:RSI从低位回升(> 30且方向向上)
if latest['rsi'] > 30 and latest['rsi'] > prev['rsi']:
signals.append('RSI回升')

        # 至少需要2个信号同时出现
if len(signals) >= 2:
print(f"\n🎯 5分钟入场信号触发!")
print(f"   信号组合:{', '.join(signals)}")
print(f"   当前价格:{latest['close']:.2f}")

            # 计算止损位(用ATR)
stop_loss = latest['close'] - 2 * latest['atr']
target_1 = latest['close'] + 2 * latest['atr']  # 1:1 风险收益比
target_2 = latest['close'] + 4 * latest['atr']  # 1:2 风险收益比

            print(f"   建议止损:{stop_loss:.2f}(2倍ATR)")
print(f"   目标1:{target_1:.2f}(1:1风险收益比)")
print(f"   目标2:{target_2:.2f}(1:2风险收益比)")

            return {
'action': 'BUY',
'price': latest['close'],
'stop_loss': stop_loss,
'target_1': target_1,
'target_2': target_2,
'signals': signals
}
else:
if signals:
print(f"\n⏳ 5分钟信号不足:仅 {', '.join(signals)}(需至少2个)")
else:
print(f"\n⏳ 5分钟暂无入场信号")
return None

# m5_signal = find_m5_entry(m5, direction='buy')

第六步:整合三重滤网系统

把三层滤网整合成一个完整的交易系统:

// python
def triple_screen_system(daily, h1, m5, symbol='000001'):
"""
三重滤网交易系统

    参数:
daily: 日线数据(含技术指标)
h1: 60分钟线数据(含技术指标)
m5: 5分钟线数据(含技术指标)
symbol: 股票代码
"""
print(f"{'='*50}")
print(f"三重滤网分析 - {symbol}")
print(f"分析时间:{m5.iloc[-1]['datetime']}")
print(f"{'='*50}")

    # 第一层滤网:日线判断大方向
print(f"\n📊 第一层滤网(日线)—— 判断大趋势")
daily_trend = judge_daily_trend(daily)

    if daily_trend == 0:
print(f"\n{'='*50}")
print(f"⚠️ 结论:日线震荡,无明确方向")
print(f"建议:暂停交易,等待趋势明确")
print(f"{'='*50}")
return None

    # 第二层滤网:小时线寻找回调机会
print(f"\n📊 第二层滤网(60分钟)—— 寻找回调入场区")
h1_signal = find_h1_entry_zone(h1, daily_trend)

    if h1_signal is None:
print(f"\n{'='*50}")
print(f"⚠️ 结论:小时线未给出入场信号")
print(f"建议:继续等待回调到位")
print(f"{'='*50}")
return None

    # 第三层滤网:5分钟线精确入场
print(f"\n📊 第三层滤网(5分钟)—— 精确入场")
entry = find_m5_entry(m5, direction=h1_signal)

    # 最终结论
print(f"\n{'='*50}")
if entry:
print(f"✅ 三重滤网全部通过!")
print(f"方向:{'做多' if daily_trend == 1 else '做空'}")
print(f"入场价:{entry['price']:.2f}")
print(f"止损价:{entry['stop_loss']:.2f}")
print(f"目标1:{entry['target_1']:.2f}")
print(f"目标2:{entry['target_2']:.2f}")
print(f"风险收益比:1:2")
risk = entry['price'] - entry['stop_loss']
reward = entry['target_2'] - entry['price']
print(f"每股风险:{risk:.2f}元 | 每股潜在收益:{reward:.2f}元")
else:
print(f"⏳ 等待5分钟入场信号...")
print(f"当前状态:日线{'看涨' if daily_trend==1 else '看跌'},小时线回调{'到位' if h1_signal=='buy' else '未到'}")
print(f"{'='*50}")

    return entry

# 完整使用示例:
# daily = calc_indicators(daily_df.copy())
# h1 = calc_indicators(df_60min.copy())
# m5 = calc_indicators(df_5min.copy())
# signal = triple_screen_system(daily, h1, m5, symbol='000001')

第七步:多时间框架数据同步

多时间框架分析有一个容易忽略的技术问题:数据对齐。

不同周期的K线,时间戳不完全对齐。比如日线的一根K线对应48根5分钟K线。

在分析时,需要确保"当前5分钟K线对应的日线和小时线数据是正确的":

// python
def align_timeframes(daily, h1, m5):
"""
对齐多时间框架数据
确保每根5分钟K线都能找到对应的日线和小时线数据
"""
# 为5分钟线的每根K线,找到对应的日线和小时线索引
m5['daily_idx'] = None
m5['h1_idx'] = None

    # 对齐日线:5分钟的日期应该和日线匹配
m5['date_only'] = m5['datetime'].dt.date
daily['date_only'] = daily['datetime'].dt.date

    for i, row in m5.iterrows():
# 找到对应的日线
daily_match = daily[daily['date_only'] == row['date_only']]
if len(daily_match) > 0:
m5.at[i, 'daily_idx'] = daily_match.index[-1]

        # 找到对应的小时线
h1_match = h1[h1['datetime'] <= row['datetime']]
if len(h1_match) > 0:
m5.at[i, 'h1_idx'] = h1_match.index[-1]

    # 清理临时列
daily.drop(columns=['date_only'], inplace=True)
m5.drop(columns=['date_only'], inplace=True)

    # 验证对齐结果
unaligned_daily = m5['daily_idx'].isna().sum()
unaligned_h1 = m5['h1_idx'].isna().sum()

    print(f"对齐检查:")
print(f"  5分钟K线总数:{len(m5)}")
print(f"  未对齐日线:{unaligned_daily} 根")
print(f"  未对齐小时线:{unaligned_h1} 根")

    if unaligned_daily == 0 and unaligned_h1 == 0:
print(f"  ✅ 全部对齐")
else:
print(f"  ⚠️ 存在未对齐数据,需要检查")

    return m5

# 对齐后,在分析时就能这样使用:
# for i, row in m5.iterrows():
#     daily_row = daily.loc[int(row['daily_idx'])]
#     h1_row = h1.loc[int(row['h1_idx'])]
#     # 现在三个时间框架的数据都是对齐的

第八步:多时间框架回测框架

最后是一个简化的多时间框架回测框架:

// python
def multi_timeframe_backtest(daily, h1, m5, initial_capital=100000):
"""
多时间框架策略回测
"""
# 对齐数据
m5_aligned = align_timeframes(daily, h1, m5)

    # 初始化
capital = initial_capital
position = 0  # 持仓数量
entry_price = 0
trades = []
equity_curve = [initial_capital]

    # 逐根5分钟K线回测
for i in range(60, len(m5_aligned)):  # 前60根用于计算指标
row = m5_aligned.iloc[i]

        # 跳过未对齐的数据
if pd.isna(row['daily_idx']) or pd.isna(row['h1_idx']):
equity_curve.append(capital + position * row['close'])
continue

        daily_row = daily.loc[int(row['daily_idx'])]
h1_row = h1.loc[int(row['h1_idx'])]

        # === 交易逻辑 ===

        # 第一层:日线趋势
daily_bullish = (
daily_row['ma5'] > daily_row['ma10'] > daily_row['ma20'] and
daily_row['macd_hist'] > 0 and
daily_row['close'] > daily_row['ma20']
)
daily_bearish = (
daily_row['ma5'] < daily_row['ma10'] < daily_row['ma20'] and
daily_row['macd_hist'] < 0 and
daily_row['close'] < daily_row['ma20']
)

        # 第二层:小时线回调
h1_pullback_buy = (
h1_row['rsi'] < 40 and
h1_row['close'] <= h1_row['bb_mid']
)

        # 第三层:5分钟入场
m5_buy_signal = (
row['macd_dif'] > row['macd_dea'] and
m5_aligned.iloc[i-1]['macd_dif'] <= m5_aligned.iloc[i-1]['macd_dea'] and
row['volume'] > m5_aligned['volume'].iloc[max(0,i-6):i].mean() * 1.3
)

        # 买入条件:日线看涨 + 小时线回调 + 5分钟金叉放量
if position == 0 and daily_bullish and h1_pullback_buy and m5_buy_signal:
position = int(capital * 0.95 / row['close'] / 100) * 100  # 95%仓位,整百股
entry_price = row['close']
capital -= position * entry_price
trades.append({
'datetime': row['datetime'],
'action': 'BUY',
'price': entry_price,
'shares': position
})

        # 卖出条件:日线看跌 或 止损 或 止盈
if position > 0:
stop_loss = entry_price * 0.97  # 3%止损
take_profit = entry_price * 1.06  # 6%止盈

            should_sell = False
sell_reason = ''

            if row['close'] <= stop_loss:
should_sell = True
sell_reason = '止损'
elif row['close'] >= take_profit:
should_sell = True
sell_reason = '止盈'
elif daily_bearish:
should_sell = True
sell_reason = '日线转空'

            if should_sell:
capital += position * row['close']
pnl = (row['close'] - entry_price) * position
trades.append({
'datetime': row['datetime'],
'action': f'SELL({sell_reason})',
'price': row['close'],
'shares': position,
'pnl': pnl
})
position = 0

        # 记录权益
equity_curve.append(capital + position * row['close'])

    # 回测统计
equity = pd.Series(equity_curve)
total_return = (equity.iloc[-1] / initial_capital - 1)

    print(f"\n=== 多时间框架回测结果 ===")
print(f"初始资金:{initial_capital:,.0f}")
print(f"最终权益:{equity.iloc[-1]:,.0f}")
print(f"总收益率:{total_return:.2%}")
print(f"交易次数:{len([t for t in trades if 'SELL' in t['action']])} 笔")

    if trades:
sell_trades = [t for t in trades if 'pnl' in t]
if sell_trades:
wins = [t for t in sell_trades if t['pnl'] > 0]
losses = [t for t in sell_trades if t['pnl'] <= 0]
print(f"胜率:{len(wins)/len(sell_trades):.1%}")
if wins:
print(f"平均盈利:{np.mean([t['pnl'] for t in wins]):,.0f}")
if losses:
print(f"平均亏损:{np.mean([t['pnl'] for t in losses]):,.0f}")

    return equity_curve, trades

总结

今天这篇文章,讲解了多时间框架分析的完整方法论和实操。

为什么重要:

• 只看一个时间周期,就像只看后视镜开车——方向感完全缺失

• 小周期信号在大趋势面前不堪一击,逆势交易是亏损主因

• 多周期共振是专业交易员的核心方法论

是什么:

• 多时间框架分析 = 同时看大、中、小三个周期的K线

• 大周期定方向(日线),中周期找时机(小时线),小周期定入场(5分钟)

• 三重滤网法:每层过滤一次,只有三层全部通过才交易

怎么做:

1. 选择合适的时间框架组合(至少4-5倍差距,如日线+60分钟+5分钟)

2. 第一层滤网:用日线均线+MACD判断大趋势方向

3. 第二层滤网:在小时线上等回调到位(RSI超卖、触及布林下轨)

4. 第三层滤网:在5分钟线上找精确入场点(MACD金叉+放量+站上MA5)

5. 确保多周期数据正确对齐

6. 大周期信号优先,冲突时以大周期为准

多时间框架组合速查表:

| 交易风格 | 大周期(方向) | 中周期(时机) | 小周期(入场) | | --- | --- | --- | --- | | 日内交易 | 日线 | 60分钟 | 5分钟 | | 短线波段 | 周线 | 日线 | 60分钟 | | 中线波段 | 月线 | 周线 | 日线 |

核心原则:

• 大周期优先,永远不要逆大趋势交易

• 多周期共振时胜率最高

• 大周期震荡时,暂停小周期交易

下一篇我们聊数据可视化——如何用图表展示你的策略回测结果。

量化笔记系列 · 第61篇

往期文章持续更新中,关注维克获取最新内容。