MQL5 多時間框架(MTF)分析完整指南:從三重濾網到實戰策略

📌 本文重點
學習如何在 MQL5 中實現多時間框架(Multi-TimeFrame, MTF)分析:正確呼叫跨週期的 iMA/iRSI/iATR、三重濾網策略實作、避免未來函數(Lookahead Bias),以及 MTF EA 的完整架構設計。

MQL5 多時間框架分析完整指南:從三重濾網到實戰策略

> 「看日線圖交易就像用望遠鏡看風景,看1分鐘圖交易就像用顯微鏡看細胞。聰明的人兩者都用。」 — 多時間框架分析的智慧

前言:為什麼專業交易者都用多時間框架?

我曾經問一個外匯基金經理:「你們的交易員最常犯的錯誤是什麼?」

他笑著說:「新手交易者就像近視的人不戴眼鏡——他們只看一個時間框架,然後奇怪為什麼總是買在高點、賣在低點。」

今天,我想分享如何「戴上眼鏡」,同時看清市場的宏觀趨勢和微觀機會。

第一部分:多時間框架的基本原理

1.1 時間框架的層級關係

在實際交易中,我通常使用三個時間框架:

//+------------------------------------------------------------------+
//| 時間框架層級定義                                                 |
//+------------------------------------------------------------------+
enum TIMEFRAME_LEVEL
{
    TF_TREND,      // 趨勢時間框架(最大)
    TF_SWING,      // 擺動時間框架(中間)
    TF_ENTRY       // 進場時間框架(最小)
};

class TimeframeHierarchy
{
private:
    ENUM_TIMEFRAMES trendTF;    // 趨勢時間框架
    ENUM_TIMEFRAMES swingTF;    // 擺動時間框架
    ENUM_TIMEFRAMES entryTF;    // 進場時間框架
    
public:
    // 根據基礎時間框架自動設定層級
    TimeframeHierarchy(ENUM_TIMEFRAMES baseTF = PERIOD_H1)
    {
        SetTimeframeHierarchy(baseTF);
    }
    
    void SetTimeframeHierarchy(ENUM_TIMEFRAMES baseTF)
    {
        // 基礎時間框架作為擺動時間框架
        swingTF = baseTF;
        
        // 自動計算趨勢和進場時間框架
        switch(baseTF)
        {
            case PERIOD_M1:
                trendTF = PERIOD_M5;
                entryTF = PERIOD_M1;
                break;
            case PERIOD_M5:
                trendTF = PERIOD_M15;
                entryTF = PERIOD_M1;
                break;
            case PERIOD_M15:
                trendTF = PERIOD_H1;
                entryTF = PERIOD_M5;
                break;
            case PERIOD_H1:
                trendTF = PERIOD_H4;
                entryTF = PERIOD_M15;
                break;
            case PERIOD_H4:
                trendTF = PERIOD_D1;
                entryTF = PERIOD_H1;
                break;
            case PERIOD_D1:
                trendTF = PERIOD_W1;
                entryTF = PERIOD_H4;
                break;
            case PERIOD_W1:
                trendTF = PERIOD_MN1;
                entryTF = PERIOD_D1;
                break;
            default:
                trendTF = PERIOD_H4;
                swingTF = PERIOD_H1;
                entryTF = PERIOD_M15;
        }
        
        Print("時間框架層級設定:");
        Print("趨勢時間框架: ", GetTimeframeName(trendTF));
        Print("擺動時間框架: ", GetTimeframeName(swingTF));
        Print("進場時間框架: ", GetTimeframeName(entryTF));
        Print("比例: 1:", GetTimeframeRatio(), "倍");
    }
    
    // 取得時間框架比例
    int GetTimeframeRatio()
    {
        int trendMinutes = PeriodSeconds(trendTF) / 60;
        int swingMinutes = PeriodSeconds(swingTF) / 60;
        
        if(swingMinutes > 0)
            return trendMinutes / swingMinutes;
        
        return 4;  // 默認4倍
    }
    
    string GetTimeframeName(ENUM_TIMEFRAMES tf)
    {
        switch(tf)
        {
            case PERIOD_M1:   return "M1";
            case PERIOD_M5:   return "M5";
            case PERIOD_M15:  return "M15";
            case PERIOD_M30:  return "M30";
            case PERIOD_H1:   return "H1";
            case PERIOD_H4:   return "H4";
            case PERIOD_D1:   return "D1";
            case PERIOD_W1:   return "W1";
            case PERIOD_MN1:  return "MN1";
            default:          return "Unknown";
        }
    }
    
    // 取得各時間框架
    ENUM_TIMEFRAMES GetTrendTF()   { return trendTF; }
    ENUM_TIMEFRAMES GetSwingTF()   { return swingTF; }
    ENUM_TIMEFRAMES GetEntryTF()   { return entryTF; }
};

// 使用範例
TimeframeHierarchy g_tfHierarchy(PERIOD_H1);

void PrintTimeframeInfo()
{
    Print("=== 多時間框架分析設定 ===");
    Print("趨勢框架: ", g_tfHierarchy.GetTimeframeName(g_tfHierarchy.GetTrendTF()));
    Print("擺動框架: ", g_tfHierarchy.GetTimeframeName(g_tfHierarchy.GetSwingTF()));
    Print("進場框架: ", g_tfHierarchy.GetTimeframeName(g_tfHierarchy.GetEntryTF()));
    Print("時間比例: 1:", g_tfHierarchy.GetTimeframeRatio());
}

1.2 黃金比例:4-6倍時間框架差距

從經驗中我發現,時間框架之間保持4-6倍的差距效果最好:

太小(如M1→M5):兩個時間框架看到的幾乎是同一件事
太大(如M5→H4):失去連貫性,難以對齊
剛好(如M15→H1→H4):能看到清晰的層級關係

// 檢查時間框架比例是否合理
bool CheckTimeframeRatio(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2)
{
    int minutes1 = PeriodSeconds(tf1) / 60;
    int minutes2 = PeriodSeconds(tf2) / 60;
    
    if(minutes1 == 0 || minutes2 == 0)
        return false;
    
    double ratio = (double)MathMax(minutes1, minutes2) / MathMin(minutes1, minutes2);
    
    Print("時間框架比例檢查:");
    Print(tf1, " (", minutes1, "分鐘) : ", tf2, " (", minutes2, "分鐘)");
    Print("比例: ", DoubleToString(ratio, 1), "倍");
    
    // 理想比例在4-6倍之間
    if(ratio >= 4.0 && ratio <= 6.0)
    {
        Print("✅ 比例合理");
        return true;
    }
    else if(ratio >= 3.0 && ratio <= 8.0)
    {
        Print("⚠️  比例尚可,但不是最優");
        return true;
    }
    else
    {
        Print("❌ 比例不合理");
        Print("建議: 調整到4-6倍之間");
        return false;
    }
}

第二部分:三重濾網交易系統實作

2.1 第一重濾網:趨勢判斷(最大時間框架)

//+------------------------------------------------------------------+
//| 第一重濾網:趨勢判斷                                             |
//+------------------------------------------------------------------+
class FirstFilter_Trend
{
private:
    ENUM_TIMEFRAMES trendTF;
    int maHandle;
    int trendStrength;
    
public:
    FirstFilter_Trend(ENUM_TIMEFRAMES tf) : trendTF(tf), trendStrength(0)
    {
        // 使用200期EMA判斷長期趨勢
        maHandle = iMA(_Symbol, trendTF, 200, 0, MODE_EMA, PRICE_CLOSE);
    }
    
    // 判斷趨勢方向
    ENUM_TREND_DIRECTION GetTrendDirection()
    {
        double maCurrent[3];
        if(CopyBuffer(maHandle, 0, 0, 3, maCurrent) < 3)
            return TREND_UNKNOWN;
        
        // 簡單趨勢判斷:價格在MA之上為上升趨勢,之下為下降趨勢
        double price = iClose(_Symbol, trendTF, 0);
        
        if(price > maCurrent[0] && maCurrent[0] > maCurrent[1])
        {
            trendStrength = CalculateTrendStrength(maCurrent);
            Print("第一重濾網: 上升趨勢 (強度: ", trendStrength, "/100)");
            return TREND_UP;
        }
        else if(price < maCurrent[0] && maCurrent[0] < maCurrent[1])
        {
            trendStrength = CalculateTrendStrength(maCurrent);
            Print("第一重濾網: 下降趨勢 (強度: ", trendStrength, "/100)");
            return TREND_DOWN;
        }
        else
        {
            Print("第一重濾網: 盤整或趨勢不明確");
            return TREND_SIDEWAYS;
        }
    }
    
    // 取得趨勢強度
    int GetTrendStrength() { return trendStrength; }
    
    // 趨勢是否足夠強烈可以交易?
    bool IsTrendStrongEnough(int minStrength = 30)
    {
        return (trendStrength >= minStrength);
    }
    
private:
    int CalculateTrendStrength(double &maValues[])
    {
        // 計算趨勢強度 (0-100)
        // 基於MA的角度和價格與MA的距離
        
        if(ArraySize(maValues) < 3)
            return 0;
        
        // 1. MA角度(斜率)
        double maAngle = (maValues[0] - maValues[2]) / 2.0;
        double normalizedAngle = MathAbs(maAngle) * 10000;  // 放大以便計算
        
        // 2. 價格與MA的距離
        double price = iClose(_Symbol, trendTF, 0);
        double distance = MathAbs(price - maValues[0]) / maValues[0] * 100;
        
        // 3. 綜合計算
        int strength = (int)(normalizedAngle * 0.7 + distance * 0.3);
        
        return MathMin(strength, 100);
    }
};

// 趨勢方向枚舉
enum ENUM_TREND_DIRECTION
{
    TREND_UP,        // 上升趨勢
    TREND_DOWN,      // 下降趨勢
    TREND_SIDEWAYS,  // 盤整
    TREND_UNKNOWN    // 未知
};

2.2 第二重濾網:擺動信號(中間時間框架)

//+------------------------------------------------------------------+
//| 第二重濾網:擺動信號                                             |
//+------------------------------------------------------------------+
class SecondFilter_Swing
{
private:
    ENUM_TIMEFRAMES swingTF;
    ENUM_TREND_DIRECTION mainTrend;
    
    // 指標句柄
    int macdHandle;
    int rsiHandle;
    int stochHandle;
    
public:
    SecondFilter_Swing(ENUM_TIMEFRAMES tf) : swingTF(tf), mainTrend(TREND_UNKNOWN)
    {
        macdHandle = iMACD(_Symbol, swingTF, 12, 26, 9, PRICE_CLOSE);
        rsiHandle = iRSI(_Symbol, swingTF, 14, PRICE_CLOSE);
        stochHandle = iStochastic(_Symbol, swingTF, 5, 3, 3, MODE_SMA, STO_LOWHIGH);
    }
    
    // 設定主要趨勢方向(從第一重濾網)
    void SetMainTrend(ENUM_TREND_DIRECTION trend)
    {
        mainTrend = trend;
    }
    
    // 尋找順勢擺動信號
    ENUM_SWING_SIGNAL GetSwingSignal()
    {
        if(mainTrend == TREND_UNKNOWN || mainTrend == TREND_SIDEWAYS)
        {
            Print("第二重濾網: 主要趨勢不明確,跳過");
            return SWING_NONE;
        }
        
        // 取得指標數值
        double macdMain[2], macdSignal[2];
        double rsi[2];
        double stochMain[2], stochSignal[2];
        
        if(CopyBuffer(macdHandle, MAIN_LINE, 0, 2, macdMain) < 2 ||
           CopyBuffer(macdHandle, SIGNAL_LINE, 0, 2, macdSignal) < 2 ||
           CopyBuffer(rsiHandle, 0, 0, 2, rsi) < 2 ||
           CopyBuffer(stochHandle, MAIN_LINE, 0, 2, stochMain) < 2 ||
           CopyBuffer(stochHandle, SIGNAL_LINE, 0, 2, stochSignal) < 2)
        {
            return SWING_NONE;
        }
        
        // 根據主要趨勢尋找信號
        if(mainTrend == TREND_UP)
        {
            // 上升趨勢中尋找買入信號(回調買入)
            if(IsBuySignal(macdMain, macdSignal, rsi, stochMain, stochSignal))
            {
                Print("第二重濾網: 發現上升趨勢中的買入信號");
                return SWING_BUY;
            }
        }
        else if(mainTrend == TREND_DOWN)
        {
            // 下降趨勢中尋找賣出信號(反彈賣出)
            if(IsSellSignal(macdMain, macdSignal, rsi, stochMain, stochSignal))
            {
                Print("第二重濾網: 發現下降趨勢中的賣出信號");
                return SWING_SELL;
            }
        }
        
        return SWING_NONE;
    }
    
private:
    bool IsBuySignal(double &macdMain[], double &macdSignal[], 
                     double &rsi[], double &stochMain[], double &stochSignal[])
    {
        // 買入信號條件:
        // 1. MACD在零軸之上或剛從下方穿越
        // 2. RSI從超賣區反彈(<30回升)
        // 3. 隨機指標從超賣區金叉
        
        bool condition1 = (macdMain[0] > 0) || (macdMain[0] > macdSignal[0] && macdMain[1] <= macdSignal[1]);
        bool condition2 = (rsi[0] > 30 && rsi[0] > rsi[1] && rsi[1] < 30);
        bool condition3 = (stochMain[0] > stochSignal[0] && stochMain[1] <= stochSignal[1] && stochMain[0] < 80);
        
        int score = 0;
        if(condition1) score++;
        if(condition2) score++;
        if(condition3) score++;
        
        Print("買入信號評分: ", score, "/3");
        return (score >= 2);  // 至少滿足2個條件
    }
    
    bool IsSellSignal(double &macdMain[], double &macdSignal[], 
                      double &rsi[], double &stochMain[], double &stochSignal[])
    {
        // 賣出信號條件:
        // 1. MACD在零軸之下或剛從上方穿越
        // 2. RSI從超買區回落(>70下降)
        // 3. 隨機指標從超買區死叉
        
        bool condition1 = (macdMain[0] < 0) || (macdMain[0] < macdSignal[0] && macdMain[1] >= macdSignal[1]);
        bool condition2 = (rsi[0] < 70 && rsi[0] < rsi[1] && rsi[1] > 70);
        bool condition3 = (stochMain[0] < stochSignal[0] && stochMain[1] >= stochSignal[1] && stochMain[0] > 20);
        
        int score = 0;
        if(condition1) score++;
        if(condition2) score++;
        if(condition3) score++;
        
        Print("賣出信號評分: ", score, "/3");
        return (score >= 2);  // 至少滿足2個條件
    }
};

// 擺動信號枚舉
enum ENUM_SWING_SIGNAL
{
    SWING_NONE,  // 無信號
    SWING_BUY,   // 買入信號
    SWING_SELL   // 賣出信號
};

2.3 第三重濾網:精確進場(最小時間框架)

//+------------------------------------------------------------------+
//| 第三重濾網:精確進場                                             |
//+------------------------------------------------------------------+
class ThirdFilter_Entry
{
private:
    ENUM_TIMEFRAMES entryTF;
    ENUM_TREND_DIRECTION mainTrend;
    ENUM_SWING_SIGNAL swingSignal;
    
    // 價格行為工具
    struct PriceAction
    {
        bool isPinBar;          // 是否為針形線
        bool isEngulfing;       // 是否為吞噬線
        bool isInsideBar;       // 是否為內包線
        bool supportResistance; // 是否在支撐阻力位
        double strength;        // 信號強度 (0-100)
    };
    
public:
    ThirdFilter_Entry(ENUM_TIMEFRAMES tf) : entryTF(tf), 
        mainTrend(TREND_UNKNOWN), swingSignal(SWING_NONE) {}
    
    // 設定前兩重濾網的結果
    void SetFilters(ENUM_TREND_DIRECTION trend, ENUM_SWING_SIGNAL swing)
    {
        mainTrend = trend;
        swingSignal = swing;
    }
    
    // 尋找精確進場點
    ENUM_ENTRY_SIGNAL GetEntrySignal()
    {
        if(mainTrend == TREND_UNKNOWN || swingSignal == SWING_NONE)
        {
            Print("第三重濾網: 前兩重濾網無信號,跳過");
            return ENTRY_NONE;
        }
        
        // 檢查價格行為
        PriceAction pa = AnalyzePriceAction();
        
        // 檢查支撐阻力
        bool nearKeyLevel = CheckSupportResistance();
        
        // 檢查動量
        bool momentumConfirm = CheckMomentum();
        
        // 綜合判斷
        if(ShouldEnter(pa, nearKeyLevel, momentumConfirm))
        {
            if(swingSignal == SWING_BUY)
            {
                Print("第三重濾網: 發現精確買入點");
                Print("價格行為強度: ", DoubleToString(pa.strength, 1), "/100");
                return ENTRY_BUY;
            }
            else if(swingSignal == SWING_SELL)
            {
                Print("第三重濾網: 發現精確賣出點");
                Print("價格行為強度: ", DoubleToString(pa.strength, 1), "/100");
                return ENTRY_SELL;
            }
        }
        
        return ENTRY_NONE;
    }
    
    // 取得建議的進場價格和止損
    bool GetEntryDetails(ENUM_ENTRY_SIGNAL signal, double &entryPrice, double &stopLoss, double &takeProfit)
    {
        if(signal == ENTRY_NONE)
            return false;
        
        // 根據信號類型設定
        if(signal == ENTRY_BUY)
        {
            entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            
            // 止損設在最近支撐下方
            stopLoss = FindNearestSupport();
            
            // 止盈基於風險回報比
            double risk = entryPrice - stopLoss;
            takeProfit = entryPrice + risk * 2;  // 1:2風險回報比
            
            Print("買入進場細節:");
            Print("進場價: ", DoubleToString(entryPrice, 5));
            Print("止損價: ", DoubleToString(stopLoss, 5));
            Print("止盈價: ", DoubleToString(takeProfit, 5));
            Print("風險點數: ", DoubleToString((entryPrice - stopLoss) / SymbolInfoDouble(_Symbol, SYMBOL_POINT), 0));
        }
        else if(signal == ENTRY_SELL)
        {
            entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            
            // 止損設在最近阻力上方
            stopLoss = FindNearestResistance();
            
            // 止盈基於風險回報比
            double risk = stopLoss - entryPrice;
            takeProfit = entryPrice - risk * 2;  // 1:2風險回報比
            
            Print("賣出進場細節:");
            Print("進場價: ", DoubleToString(entryPrice, 5));
            Print("止損價: ", DoubleToString(stopLoss, 5));
            Print("止盈價: ", DoubleToString(takeProfit, 5));
            Print("風險點數: ", DoubleToString((stopLoss - entryPrice) / SymbolInfoDouble(_Symbol, SYMBOL_POINT), 0));
        }
        
        return true;
    }
    
private:
    PriceAction AnalyzePriceAction()
    {
        PriceAction pa = {false, false, false, false, 0.0};
        
        // 取得最近幾根K線
        MqlRates rates[5];
        if(CopyRates(_Symbol, entryTF, 0, 5, rates) < 5)
            return pa;
        
        // 檢查針形線 (Pin Bar)
        pa.isPinBar = IsPinBar(rates[0]);
        
        // 檢查吞噬線 (Engulfing)
        pa.isEngulfing = IsEngulfing(rates[0], rates[1]);
        
        // 檢查內包線 (Inside Bar)
        pa.isInsideBar = IsInsideBar(rates[0], rates[1]);
        
        // 計算信號強度
        pa.strength = CalculateSignalStrength(pa);
        
        return pa;
    }
    
    bool IsPinBar(MqlRates &current)
    {
        // 針形線條件:長影線,短實體
        double bodySize = MathAbs(current.close - current.open);
        double totalRange = current.high - current.low;
        
        if(totalRange == 0)
            return false;
        
        double shadowRatio = (totalRange - bodySize) / totalRange;
        
        // 影線佔比超過60%,實體佔比小於40%
        return (shadowRatio > 0.6 && bodySize / totalRange < 0.4);
    }
    
    bool IsEngulfing(MqlRates &current, MqlRates &previous)
    {
        // 吞噬線條件:當前K線完全吞噬前一根K線
        bool bullishEngulfing = (current.close > current.open &&  // 陽線
                                previous.close < previous.open && // 前一根陰線
                                current.open < previous.close &&  // 開盤低於前收盤
                                current.close > previous.open);   // 收盤高於前開盤
        
        bool bearishEngulfing = (current.close < current.open &&  // 陰線
                                previous.close > previous.open && // 前一根陽線
                                current.open > previous.close &&  // 開盤高於前收盤
                                current.close < previous.open);   // 收盤低於前開盤
        
        return (bullishEngulfing || bearishEngulfing);
    }
    
    bool IsInsideBar(MqlRates &current, MqlRates &previous)
    {
        // 內包線條件:當前K線範圍完全在前一根K線範圍內
        return (current.high <= previous.high && 
                current.low >= previous.low);
    }
    
    double CalculateSignalStrength(PriceAction &pa)
    {
        double strength = 0;
        
        if(pa.isPinBar) strength += 40;
        if(pa.isEngulfing) strength += 35;
        if(pa.isInsideBar) strength += 25;
        
        // 根據位置調整強度
        if(pa.supportResistance) strength *= 1.2;
        
        return MathMin(strength, 100);
    }
    
    bool CheckSupportResistance()
    {
        // 檢查是否在關鍵支撐阻力位附近
        double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        
        // 這裡應該實作具體的支撐阻力檢測邏輯
        // 例如:檢查前高前低、移動平均線、斐波那契水平等
        
        return false;  // 簡化實現
    }
    
    bool CheckMomentum()
    {
        // 檢查動量是否確認信號
        // 使用RSI、MACD等指標確認
        
        return true;  // 簡化實現
    }
    
    bool ShouldEnter(PriceAction &pa, bool nearKeyLevel, bool momentumConfirm)
    {
        // 綜合判斷是否應該進場
        
        int score = 0;
        int maxScore = 0;
        
        // 價格行為分數
        if(pa.strength >= 60) score += 2;
        else if(pa.strength >= 30) score += 1;
        maxScore += 2;
        
        // 關鍵位置分數
        if(nearKeyLevel) score += 2;
        maxScore += 2;
        
        // 動量確認分數
        if(momentumConfirm) score += 2;
        maxScore += 2;
        
        // 趨勢一致性分數(已在前面檢查)
        score += 2;
        maxScore += 2;
        
        double passRate = (double)score / maxScore;
        
        Print("進場決策評分: ", score, "/", maxScore, " (", DoubleToString(passRate * 100, 0), "%)");
        
        return (passRate >= 0.75);  // 需要75%以上的分數
    }
    
    double FindNearestSupport()
    {
        // 尋找最近的支撐位
        // 這裡應該實作具體的支撐位檢測邏輯
        
        double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        return currentPrice * 0.99;  // 簡化實現:設在當前價格下方1%
    }
    
    double FindNearestResistance()
    {
        // 尋找最近的阻力位
        // 這裡應該實作具體的阻力位檢測邏輯
        
        double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        return currentPrice * 1.01;  // 簡化實現:設在當前價格上方1%
    }
};

// 進場信號枚舉
enum ENUM_ENTRY_SIGNAL
{
    ENTRY_NONE,  // 無信號
    ENTRY_BUY,   // 買入
    ENTRY_SELL   // 賣出
};

2.4 完整的三重濾網系統

//+------------------------------------------------------------------+
//| 完整的三重濾網交易系統                                           |
//+------------------------------------------------------------------+
class TripleScreenTradingSystem
{
private:
    TimeframeHierarchy* tfHierarchy;
    FirstFilter_Trend* firstFilter;
    SecondFilter_Swing* secondFilter;
    ThirdFilter_Entry* thirdFilter;
    
    // 交易狀態
    bool isInitialized;
    ENUM_TREND_DIRECTION currentTrend;
    ENUM_SWING_SIGNAL currentSwing;
    ENUM_ENTRY_SIGNAL currentEntry;
    
public:
    TripleScreenTradingSystem(ENUM_TIMEFRAMES baseTF = PERIOD_H1)
    {
        Print("=== 三重濾網交易系統初始化 ===");
        
        // 建立時間框架層級
        tfHierarchy = new TimeframeHierarchy(baseTF);
        
        // 建立三重濾網
        firstFilter = new FirstFilter_Trend(tfHierarchy->GetTrendTF());
        secondFilter = new SecondFilter_Swing(tfHierarchy->GetSwingTF());
        thirdFilter = new ThirdFilter_Entry(tfHierarchy->GetEntryTF());
        
        isInitialized = true;
        currentTrend = TREND_UNKNOWN;
        currentSwing = SWING_NONE;
        currentEntry = ENTRY_NONE;
        
        Print("系統初始化完成");
    }
    
    ~TripleScreenTradingSystem()
    {
        delete tfHierarchy;
        delete firstFilter;
        delete secondFilter;
        delete thirdFilter;
    }
    
    // 執行三重濾網分析
    ENUM_ENTRY_SIGNAL Analyze()
    {
        if(!isInitialized)
        {
            Print("錯誤: 系統未初始化");
            return ENTRY_NONE;
        }
        
        Print("\n=== 開始三重濾網分析 ===");
        
        // 第一重濾網:趨勢判斷
        Print("\n[第一重濾網] 趨勢分析...");
        currentTrend = firstFilter->GetTrendDirection();
        
        if(!firstFilter->IsTrendStrongEnough(30))
        {
            Print("趨勢強度不足,跳過後續分析");
            return ENTRY_NONE;
        }
        
        // 第二重濾網:擺動信號
        Print("\n[第二重濾網] 擺動信號分析...");
        secondFilter->SetMainTrend(currentTrend);
        currentSwing = secondFilter->GetSwingSignal();
        
        if(currentSwing == SWING_NONE)
        {
            Print("無擺動信號,跳過進場分析");
            return ENTRY_NONE;
        }
        
        // 第三重濾網:精確進場
        Print("\n[第三重濾網] 進場點分析...");
        thirdFilter->SetFilters(currentTrend, currentSwing);
        currentEntry = thirdFilter->GetEntrySignal();
        
        if(currentEntry != ENTRY_NONE)
        {
            Print("\n🎉 三重濾網分析完成:發現交易機會!");
            Print("趨勢: ", GetTrendName(currentTrend));
            Print("擺動信號: ", GetSwingName(currentSwing));
            Print("進場信號: ", GetEntryName(currentEntry));
        }
        else
        {
            Print("\n三重濾網分析完成:無合適進場點");
        }
        
        return currentEntry;
    }
    
    // 取得進場細節
    bool GetTradeDetails(double &entryPrice, double &stopLoss, double &takeProfit)
    {
        if(currentEntry == ENTRY_NONE)
            return false;
        
        return thirdFilter->GetEntryDetails(currentEntry, entryPrice, stopLoss, takeProfit);
    }
    
    // 取得分析結果
    ENUM_TREND_DIRECTION GetTrend() { return currentTrend; }
    ENUM_SWING_SIGNAL GetSwing() { return currentSwing; }
    ENUM_ENTRY_SIGNAL GetEntry() { return currentEntry; }
    
private:
    string GetTrendName(ENUM_TREND_DIRECTION trend)
    {
        switch(trend)
        {
            case TREND_UP: return "上升";
            case TREND_DOWN: return "下降";
            case TREND_SIDEWAYS: return "盤整";
            default: return "未知";
        }
    }
    
    string GetSwingName(ENUM_SWING_SIGNAL swing)
    {
        switch(swing)
        {
            case SWING_BUY: return "買入";
            case SWING_SELL: return "賣出";
            default: return "無";
        }
    }
    
    string GetEntryName(ENUM_ENTRY_SIGNAL entry)
    {
        switch(entry)
        {
            case ENTRY_BUY: return "買入";
            case ENTRY_SELL: return "賣出";
            default: return "無";
        }
    }
};

// 全域三重濾網系統實例
TripleScreenTradingSystem* g_tripleScreen = NULL;

// 初始化函數
bool InitializeTripleScreen(ENUM_TIMEFRAMES baseTF = PERIOD_H1)
{
    if(g_tripleScreen != NULL)
        delete g_tripleScreen;
    
    g_tripleScreen = new TripleScreenTradingSystem(baseTF);
    return (g_tripleScreen != NULL);
}

// 分析函數
ENUM_ENTRY_SIGNAL RunTripleScreenAnalysis()
{
    if(g_tripleScreen == NULL)
    {
        Print("錯誤: 三重濾網系統未初始化");
        return ENTRY_NONE;
    }
    
    return g_tripleScreen->Analyze();
}

第三部分:進階多時間框架技巧

3.1 時間框架對齊技巧

//+------------------------------------------------------------------+
//| 時間框架對齊檢測                                                 |
//+------------------------------------------------------------------+
class TimeframeAlignment
{
public:
    // 檢查多時間框架是否對齊
    static bool CheckAlignment(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3)
    {
        Print("=== 時間框架對齊檢查 ===");
        
        bool aligned = true;
        
        // 檢查K線時間對齊
        if(!CheckCandleAlignment(tf1, tf2))
        {
            Print("❌ ", tf1, " 和 ", tf2, " K線時間未對齊");
            aligned = false;
        }
        
        if(!CheckCandleAlignment(tf2, tf3))
        {
            Print("❌ ", tf2, " 和 ", tf3, " K線時間未對齊");
            aligned = false;
        }
        
        // 檢查趨勢方向一致性
        if(!CheckTrendConsistency(tf1, tf2, tf3))
        {
            Print("❌ 趨勢方向不一致");
            aligned = false;
        }
        
        if(aligned)
        {
            Print("✅ 所有時間框架對齊良好");
        }
        else
        {
            Print("⚠️  時間框架未完全對齊,可能影響信號質量");
        }
        
        return aligned;
    }
    
    // 取得最佳對齊的時間框架組合
    static void FindBestAlignment(ENUM_TIMEFRAMES baseTF, 
                                  ENUM_TIMEFRAMES &bestTrendTF, 
                                  ENUM_TIMEFRAMES &bestSwingTF, 
                                  ENUM_TIMEFRAMES &bestEntryTF)
    {
        Print("尋找最佳時間框架組合...");
        
        // 候選時間框架
        ENUM_TIMEFRAMES candidateTFs[] = {
            PERIOD_M5, PERIOD_M15, PERIOD_M30,
            PERIOD_H1, PERIOD_H4, PERIOD_D1
        };
        
        double bestScore = -1;
        
        // 測試所有可能的組合
        for(int i = 0; i < ArraySize(candidateTFs); i++)
        {
            for(int j = 0; j < ArraySize(candidateTFs); j++)
            {
                for(int k = 0; k < ArraySize(candidateTFs); k++)
                {
                    if(i == j || i == k || j == k)
                        continue;
                    
                    ENUM_TIMEFRAMES tf1 = candidateTFs[i];
                    ENUM_TIMEFRAMES tf2 = candidateTFs[j];
                    ENUM_TIMEFRAMES tf3 = candidateTFs[k];
                    
                    // 確保時間框架大小順序正確
                    if(PeriodSeconds(tf1) <= PeriodSeconds(tf2) || 
                       PeriodSeconds(tf2) <= PeriodSeconds(tf3))
                        continue;
                    
                    // 計算對齊分數
                    double score = CalculateAlignmentScore(tf1, tf2, tf3);
                    
                    if(score > bestScore)
                    {
                        bestScore = score;
                        bestTrendTF = tf1;
                        bestSwingTF = tf2;
                        bestEntryTF = tf3;
                    }
                }
            }
        }
        
        Print("最佳組合: ", bestTrendTF, " → ", bestSwingTF, " → ", bestEntryTF);
        Print("對齊分數: ", DoubleToString(bestScore, 2), "/100");
    }
    
private:
    static bool CheckCandleAlignment(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2)
    {
        // 檢查兩個時間框架的K線時間是否對齊
        // 例如:H1的K線應該對齊H4的K線開始時間
        
        datetime time1 = iTime(_Symbol, tf1, 0);
        datetime time2 = iTime(_Symbol, tf2, 0);
        
        // 較大時間框架的K線開始時間應該是較小時間框架K線開始時間的倍數
        int seconds1 = PeriodSeconds(tf1);
        int seconds2 = PeriodSeconds(tf2);
        
        if(seconds2 > seconds1)
        {
            // tf2是較大的時間框架
            return (time1 % seconds2 == 0);
        }
        else
        {
            // tf1是較大的時間框架
            return (time2 % seconds1 == 0);
        }
    }
    
    static bool CheckTrendConsistency(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3)
    {
        // 檢查三個時間框架的趨勢方向是否一致
        
        // 簡化實現:使用移動平均線判斷趨勢
        int maHandle1 = iMA(_Symbol, tf1, 50, 0, MODE_SMA, PRICE_CLOSE);
        int maHandle2 = iMA(_Symbol, tf2, 50, 0, MODE_SMA, PRICE_CLOSE);
        int maHandle3 = iMA(_Symbol, tf3, 50, 0, MODE_SMA, PRICE_CLOSE);
        
        double ma1[1], ma2[1], ma3[1];
        double price1 = iClose(_Symbol, tf1, 0);
        double price2 = iClose(_Symbol, tf2, 0);
        double price3 = iClose(_Symbol, tf3, 0);
        
        if(CopyBuffer(maHandle1, 0, 0, 1, ma1) > 0 &&
           CopyBuffer(maHandle2, 0, 0, 1, ma2) > 0 &&
           CopyBuffer(maHandle3, 0, 0, 1, ma3) > 0)
        {
            bool trend1 = (price1 > ma1[0]);  // true = 上升
            bool trend2 = (price2 > ma2[0]);
            bool trend3 = (price3 > ma3[0]);
            
            // 檢查一致性:至少兩個時間框架趨勢相同
            int upCount = 0;
            if(trend1) upCount++;
            if(trend2) upCount++;
            if(trend3) upCount++;
            
            return (upCount >= 2 || upCount <= 1);  // 大多數一致
        }
        
        return false;
    }
    
    static double CalculateAlignmentScore(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3)
    {
        double score = 0;
        
        // 1. 時間比例分數 (40%)
        double ratio12 = (double)PeriodSeconds(tf1) / PeriodSeconds(tf2);
        double ratio23 = (double)PeriodSeconds(tf2) / PeriodSeconds(tf3);
        
        double ratioScore = 0;
        if(ratio12 >= 4 && ratio12 <= 6) ratioScore += 20;
        if(ratio23 >= 4 && ratio23 <= 6) ratioScore += 20;
        
        score += ratioScore;
        
        // 2. K線對齊分數 (30%)
        double alignmentScore = 0;
        if(CheckCandleAlignment(tf1, tf2)) alignmentScore += 15;
        if(CheckCandleAlignment(tf2, tf3)) alignmentScore += 15;
        
        score += alignmentScore;
        
        // 3. 趨勢一致性分數 (30%)
        if(CheckTrendConsistency(tf1, tf2, tf3))
            score += 30;
        
        return score;
    }
};

3.2 動態時間框架調整

//+------------------------------------------------------------------+
//| 動態時間框架調整系統                                             |
//+------------------------------------------------------------------+
class DynamicTimeframeAdjustment
{
private:
    ENUM_TIMEFRAMES currentTrendTF;
    ENUM_TIMEFRAMES currentSwingTF;
    ENUM_TIMEFRAMES currentEntryTF;
    
    // 市場狀態
    enum MARKET_CONDITION
    {
        MARKET_TRENDING,      // 趨勢市場
        MARKET_RANGING,       // 區間市場
        MARKET_VOLATILE,      // 高波動市場
        MARKET_CALM           // 低波動市場
    };
    
    MARKET_CONDITION currentCondition;
    
public:
    DynamicTimeframeAdjustment()
    {
        // 初始設定
        currentTrendTF = PERIOD_H4;
        currentSwingTF = PERIOD_H1;
        currentEntryTF = PERIOD_M15;
        currentCondition = MARKET_TRENDING;
    }
    
    // 根據市場狀況調整時間框架
    void AdjustTimeframes()
    {
        MARKET_CONDITION newCondition = AnalyzeMarketCondition();
        
        if(newCondition != currentCondition)
        {
            Print("市場狀況改變: ", GetConditionName(currentCondition), 
                  " → ", GetConditionName(newCondition));
            
            AdjustForCondition(newCondition);
            currentCondition = newCondition;
        }
    }
    
    // 取得當前時間框架
    ENUM_TIMEFRAMES GetTrendTF() { return currentTrendTF; }
    ENUM_TIMEFRAMES GetSwingTF() { return currentSwingTF; }
    ENUM_TIMEFRAMES GetEntryTF() { return currentEntryTF; }
    
private:
    MARKET_CONDITION AnalyzeMarketCondition()
    {
        // 分析當前市場狀況
        
        // 1. 檢查波動性
        double atrValue = GetATRValue(PERIOD_H1, 14);
        double avgATR = GetAverageATR(PERIOD_H1, 14, 100);
        
        // 2. 檢查趨勢強度
        double trendStrength = CalculateTrendStrength(PERIOD_H4);
        
        // 3. 判斷市場狀況
        if(trendStrength > 60)
        {
            return MARKET_TRENDING;
        }
        else if(atrValue > avgATR * 1.5)
        {
            return MARKET_VOLATILE;
        }
        else if(atrValue < avgATR * 0.5)
        {
            return MARKET_CALM;
        }
        else
        {
            return MARKET_RANGING;
        }
    }
    
    void AdjustForCondition(MARKET_CONDITION condition)
    {
        switch(condition)
        {
            case MARKET_TRENDING:
                // 趨勢市場:使用較大時間框架,跟隨趨勢
                currentTrendTF = PERIOD_H4;
                currentSwingTF = PERIOD_H1;
                currentEntryTF = PERIOD_M15;
                Print("調整為趨勢市場設定");
                break;
                
            case MARKET_RANGING:
                // 區間市場:使用較小時間框架,捕捉區間波動
                currentTrendTF = PERIOD_H1;
                currentSwingTF = PERIOD_M15;
                currentEntryTF = PERIOD_M5;
                Print("調整為區間市場設定");
                break;
                
            case MARKET_VOLATILE:
                // 高波動市場:放大時間框架,避免噪音
                currentTrendTF = PERIOD_D1;
                currentSwingTF = PERIOD_H4;
                currentEntryTF = PERIOD_H1;
                Print("調整為高波動市場設定");
                break;
                
            case MARKET_CALM:
                // 低波動市場:縮小時間框架,尋找機會
                currentTrendTF = PERIOD_H1;
                currentSwingTF = PERIOD_M15;
                currentEntryTF = PERIOD_M5;
                Print("調整為低波動市場設定");
                break;
        }
        
        Print("新時間框架設定:");
        Print("趨勢: ", currentTrendTF);
        Print("擺動: ", currentSwingTF);
        Print("進場: ", currentEntryTF);
    }
    
    string GetConditionName(MARKET_CONDITION condition)
    {
        switch(condition)
        {
            case MARKET_TRENDING: return "趨勢市場";
            case MARKET_RANGING:  return "區間市場";
            case MARKET_VOLATILE: return "高波動市場";
            case MARKET_CALM:     return "低波動市場";
            default:              return "未知";
        }
    }
    
    double GetATRValue(ENUM_TIMEFRAMES tf, int period)
    {
        int atrHandle = iATR(_Symbol, tf, period);
        double values[1];
        
        if(CopyBuffer(atrHandle, 0, 0, 1, values) > 0)
            return values[0];
        
        return 0;
    }
    
    double GetAverageATR(ENUM_TIMEFRAMES tf, int period, int bars)
    {
        int atrHandle = iATR(_Symbol, tf, period);
        double values[];
        
        if(CopyBuffer(atrHandle, 0, 0, bars, values) >= bars)
        {
            double sum = 0;
            for(int i = 0; i < bars; i++)
                sum += values[i];
            
            return sum / bars;
        }
        
        return 0;
    }
    
    double CalculateTrendStrength(ENUM_TIMEFRAMES tf)
    {
        // 計算趨勢強度 (0-100)
        int maHandle = iMA(_Symbol, tf, 50, 0, MODE_SMA, PRICE_CLOSE);
        double maValues[3];
        
        if(CopyBuffer(maHandle, 0, 0, 3, maValues) >= 3)
        {
            // 基於MA的角度計算趨勢強度
            double angle = (maValues[0] - maValues[2]) / 2.0;
            double strength = MathAbs(angle) * 10000;
            
            return MathMin(strength, 100);
        }
        
        return 0;
    }
};

第四部分:實戰案例與常見錯誤

4.1 實戰案例:EURUSD 多時間框架交易

// EURUSD 多時間框架交易案例
class EURUSDMultiTimeframeExample
{
public:
    void RunExample()
    {
        Print("=== EURUSD 多時間框架交易案例 ===");
        
        // 步驟1:設定時間框架
        TimeframeHierarchy tf(PERIOD_H1);
        
        // 步驟2:分析各時間框架
        AnalyzeTimeframes(tf.GetTrendTF(), tf.GetSwingTF(), tf.GetEntryTF());
        
        // 步驟3:檢查對齊
        bool aligned = TimeframeAlignment::CheckAlignment(
            tf.GetTrendTF(), tf.GetSwingTF(), tf.GetEntryTF());
        
        // 步驟4:執行三重濾網分析
        if(aligned)
        {
            TripleScreenTradingSystem tripleScreen(PERIOD_H1);
            ENUM_ENTRY_SIGNAL signal = tripleScreen.Analyze();
            
            if(signal != ENTRY_NONE)
            {
                double entry, sl, tp;
                if(tripleScreen.GetTradeDetails(entry, sl, tp))
                {
                    ExecuteTrade(signal, entry, sl, tp);
                }
            }
        }
    }
    
private:
    void AnalyzeTimeframes(ENUM_TIMEFRAMES trendTF, ENUM_TIMEFRAMES swingTF, ENUM_TIMEFRAMES entryTF)
    {
        Print("\n各時間框架分析:");
        
        // 趨勢時間框架分析
        Print("1. 趨勢框架 (", trendTF, "):");
        AnalyzeTrend(trendTF);
        
        // 擺動時間框架分析
        Print("\n2. 擺動框架 (", swingTF, "):");
        AnalyzeSwing(swingTF);
        
        // 進場時間框架分析
        Print("\n3. 進場框架 (", entryTF, "):");
        AnalyzeEntry(entryTF);
    }
    
    void AnalyzeTrend(ENUM_TIMEFRAMES tf)
    {
        // 使用200EMA判斷長期趨勢
        int maHandle = iMA(_Symbol, tf, 200, 0, MODE_EMA, PRICE_CLOSE);
        double maValue[1];
        double price = iClose(_Symbol, tf, 0);
        
        if(CopyBuffer(maHandle, 0, 0, 1, maValue) > 0)
        {
            if(price > maValue[0])
                Print("  價格在200EMA之上,長期趨勢向上");
            else
                Print("  價格在200EMA之下,長期趨勢向下");
            
            Print("  價格: ", DoubleToString(price, 5));
            Print("  200EMA: ", DoubleToString(maValue[0], 5));
        }
    }
    
    void AnalyzeSwing(ENUM_TIMEFRAMES tf)
    {
        // 使用MACD和RSI分析擺動信號
        int macdHandle = iMACD(_Symbol, tf, 12, 26, 9, PRICE_CLOSE);
        int rsiHandle = iRSI(_Symbol, tf, 14, PRICE_CLOSE);
        
        double macdMain[2], macdSignal[2];
        double rsi[2];
        
        if(CopyBuffer(macdHandle, MAIN_LINE, 0, 2, macdMain) >= 2 &&
           CopyBuffer(macdHandle, SIGNAL_LINE, 0, 2, macdSignal) >= 2 &&
           CopyBuffer(rsiHandle, 0, 0, 2, rsi) >= 2)
        {
            // MACD分析
            if(macdMain[0] > macdSignal[0] && macdMain[1] <= macdSignal[1])
                Print("  MACD金叉,買入信號");
            else if(macdMain[0] < macdSignal[0] && macdMain[1] >= macdSignal[1])
                Print("  MACD死叉,賣出信號");
            else
                Print("  MACD無明確信號");
            
            // RSI分析
            if(rsi[0] > 70)
                Print("  RSI超買 (>70)");
            else if(rsi[0] < 30)
                Print("  RSI超賣 (<30)");
            else
                Print("  RSI中性 (", DoubleToString(rsi[0], 1), ")");
        }
    }
    
    void AnalyzeEntry(ENUM_TIMEFRAMES tf)
    {
        // 分析價格行為
        MqlRates rates[3];
        if(CopyRates(_Symbol, tf, 0, 3, rates) >= 3)
        {
            Print("  最新K線:");
            Print("  開盤: ", DoubleToString(rates[0].open, 5));
            Print("  最高: ", DoubleToString(rates[0].high, 5));
            Print("  最低: ", DoubleToString(rates[0].low, 5));
            Print("  收盤: ", DoubleToString(rates[0].close, 5));
            
            // 檢查K線形態
            if(rates[0].close > rates[0].open)
                Print("  陽線");
            else
                Print("  陰線");
        }
    }
    
    void ExecuteTrade(ENUM_ENTRY_SIGNAL signal, double entry, double sl, double tp)
    {
        Print("\n🎯 執行交易:");
        Print("信號: ", (signal == ENTRY_BUY ? "買入" : "賣出"));
        Print("進場: ", DoubleToString(entry, 5));
        Print("止損: ", DoubleToString(sl, 5));
        Print("止盈: ", DoubleToString(tp, 5));
        
        // 這裡應該實作實際的交易執行邏輯
        // 注意:這只是範例,實際交易需要完整的錯誤處理和風險管理
    }
};

4.2 常見多時間框架錯誤

// 常見錯誤與解決方案
void CommonMultiTimeframeMistakes()
{
    Print("=== 常見多時間框架錯誤 ===");
    
    Print("\n❌ 錯誤1: 時間框架比例不當");
    Print("   表現: 使用M1和M5(比例太小)或M5和H4(比例太大)");
    Print("   結果: 信號混亂,難以對齊");
    Print("   解決: 使用4-6倍比例的時間框架組合");
    
    Print("\n❌ 錯誤2: 忽略時間框架對齊");
    Print("   表現: 在不同時間框架的K線中間進行分析");
    Print("   結果: 信號時機不準確");
    Print("   解決: 確保分析時所有時間框架的K線時間對齊");
    
    Print("\n❌ 錯誤3: 過度分析");
    Print("   表現: 同時看太多時間框架(如M1、M5、M15、H1、H4、D1)");
    Print("   結果: 分析癱瘓,無法做出決策");
    Print("   解決: 專注於3個關鍵時間框架(趨勢、擺動、進場)");
    
    Print("\n❌ 錯誤4: 忽略市場狀況");
    Print("   表現: 在高波動市場使用小時間框架,或在低波動市場使用大時間框架");
    Print("   結果: 頻繁止損或錯失機會");
    Print("   解決: 根據市場波動性動態調整時間框架");
    
    Print("\n❌ 錯誤5: 違反時間框架層級");
    Print("   表現: 在小時間框架逆勢交易,或在大時間框架追逐小波動");
    Print("   結果: 風險回報比不佳");
    Print("   解決: 遵守『大框架定方向,小框架找進場』原則");
}

第五部分:實戰檢查清單與最佳實踐

5.1 多時間框架交易檢查清單

bool RunMultiTimeframeChecklist()
{
    Print("=== 多時間框架交易檢查清單 ===");
    
    bool checklist[10] = {false};
    int passed = 0;
    
    // 1. 是否使用至少3個時間框架?
    checklist[0] = (GetUsedTimeframeCount() >= 3);
    Print(checklist[0] ? "✅ 1. 使用≥3個時間框架" : "❌ 1. 使用<3個時間框架");
    
    // 2. 時間框架比例是否合理(4-6倍)?
    checklist[1] = CheckTimeframeRatios();
    Print(checklist[1] ? "✅ 2. 時間框架比例合理" : "❌ 2. 時間框架比例不合理");
    
    // 3. 時間框架是否對齊?
    checklist[2] = CheckTimeframeAlignment();
    Print(checklist[2] ? "✅ 3. 時間框架對齊" : "❌ 3. 時間框架未對齊");
    
    // 4. 趨勢方向是否一致?
    checklist[3] = CheckTrendConsistency();
    Print(checklist[3] ? "✅ 4. 趨勢方向一致" : "❌ 4. 趨勢方向不一致");
    
    // 5. 是否遵守時間框架層級?
    checklist[4] = CheckTimeframeHierarchy();
    Print(checklist[4] ? "✅ 5. 遵守時間框架層級" : "❌ 5. 違反時間框架層級");
    
    // 6. 是否有明確的進出場規則?
    checklist[5] = HasClearRules();
    Print(checklist[5] ? "✅ 6. 有明確進出場規則" : "❌ 6. 無明確進出場規則");
    
    // 7. 是否考慮市場狀況?
    checklist[6] = ConsiderMarketCondition();
    Print(checklist[6] ? "✅ 7. 考慮市場狀況" : "❌ 7. 忽略市場狀況");
    
    // 8. 是否有風險管理?
    checklist[7] = HasRiskManagement();
    Print(checklist[7] ? "✅ 8. 有風險管理" : "❌ 8. 無風險管理");
    
    // 9. 是否有交易計劃?
    checklist[8] = HasTradingPlan();
    Print(checklist[8] ? "✅ 9. 有交易計劃" : "❌ 9. 無交易計劃");
    
    // 10. 是否有交易日誌?
    checklist[9] = HasTradeJournal();
    Print(checklist[9] ? "✅ 10. 有交易日誌" : "❌ 10. 無交易日誌");
    
    // 計算通過率
    for(int i = 0; i < 10; i++)
    {
        if(checklist[i]) passed++;
    }
    
    double passRate = (double)passed / 10 * 100;
    Print("\n檢查結果: ", passed, "/10 通過 (", DoubleToString(passRate, 1), "%)");
    
    if(passRate >= 80.0)
    {
        Print("🎉 多時間框架交易準備良好!");
        return true;
    }
    else if(passRate >= 60.0)
    {
        Print("⚠️  多時間框架交易需要改進");
        return false;
    }
    else
    {
        Print("❌ 多時間框架交易存在嚴重問題");
        return false;
    }
}

// 檢查函數的簡化實現
int GetUsedTimeframeCount() { return 3; }
bool CheckTimeframeRatios() { return true; }
bool CheckTimeframeAlignment() { return true; }
bool CheckTrendConsistency() { return true; }
bool CheckTimeframeHierarchy() { return true; }
bool HasClearRules() { return true; }
bool ConsiderMarketCondition() { return true; }
bool HasRiskManagement() { return true; }
bool HasTradingPlan() { return true; }
bool HasTradeJournal() { return true; }

5.2 最佳實踐總結

1. 保持簡單:專注於3個關鍵時間框架
2. 遵守比例:使用4-6倍的時間框架差距
3. 確保對齊:只在對齊的K線時間進行分析
4. 尊重層級:大框架定方向,小框架找進場
5. 動態調整:根據市場狀況調整時間框架
6. 保持耐心:等待所有時間框架信號一致
7. 嚴格執行:遵守你的交易規則
8. 持續學習:從每筆交易中學習和改進

結語:多時間框架的藝術

多時間框架分析就像是用不同倍率的鏡頭看世界:
- 望遠鏡(大時間框架):看清整體趨勢和方向
- 標準鏡(中時間框架):找到交易機會和擺動點
- 顯微鏡(小時間框架):精確定位進場點

我學到的最重要一課是:市場就像洋蔥,需要一層一層剝開來看。只看一層,你會錯過很多;看太多層,你會流淚。

三個關鍵收穫:

1. 一致性最重要:當所有時間框架都指向同一方向時,成功的機率最高
2. 耐心是美德:等待所有條件對齊,比頻繁交易更重要
3. 簡單最有效:複雜的系統不一定比簡單的系統更好

記住,多時間框架分析不是為了讓你找到更多交易機會,而是為了讓你找到更好的交易機會。

---

系列文章進度:
1. ✅ 從零開始建立你的第一個 MQL5 專家顧問
2. ✅ MQL5 程式設計常見錯誤與最佳實踐
3. ✅ 回測與實盤測試完全指南
4. ✅ MQL5 資金管理演算法完整指南
5. ✅ MQL5 多時間框架分析完整指南(本篇)
6. 🔜 MQL5 技術指標深度解析與實戰應用

---

*多時間框架分析需要時間和練習才能掌握。一開始可能會覺得複雜,但隨著經驗積累,它會成為你交易工具箱中最強大的工具之一。如果你在實作過程中遇到問題,歡迎在下方留言討論!*

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *