价格行为分析工具开发(第二十八部分):开盘区间突破工具
内容
引言
2010年5月6日,美国股市经历了臭名昭著的"闪崩",这是一次惊心动魄的暴跌。当时,E-Mini标普500期货市场一笔巨大的算法驱动卖单引发了疯狂的高频清算,导致道琼斯指数在几分钟内暴跌近1000点,随后又迅速回升。 这一戏剧性事件暴露了关键弱点:盲目响应未确认的价格突破,哪怕看似强势,然而一旦市场流动性枯竭并反弹,交易者便会深陷泥潭。
当价格果断突破清晰定义的边界(如交易时段开盘区间的高低点),即意味着供需一方压倒了另一方,形成突破。识别真正的突破至关重要,因为真正的突破往往标志着持续趋势的开始,而虚假突破如果过早行动,则会导致止损亏损。
开盘区间突破(ORB)策略通过首先捕捉该开盘区间(可配置为任意时长)的上下限来解决这个问题,并在图表上以矩形阴影标出该区间。这些边界既是视觉地标,也是精确的触发水平。策略仅当价格突破区间后,回踩边界并再次突破时才确认入场,以此过滤噪音,捕捉由真实市场力量驱动的行情。
在本文中,您将探索一个专业的ORB策略 MQL5 EA实例,其特点包括:
- 封装区间捕捉功能,用于跟踪和显示开盘高低点,而不会使您的主循环变得杂乱无章,
- 通过可重用的ATR模块实现的波动性调整止损和目标,
- 回测确认逻辑,用于区分真实突破和瞬时波动,
- 带有动态仪表板标签和图形对象的图表图形,
- 在 OnTick() 函数中实现的轻量状态机。该状态机可按步骤编排执行流程,并在会话关闭时彻底重置状态。
开盘区间
开盘区间是指交易时段最初几分钟(通常为前15或30分钟)内形成的高低价区域。这一时期反映了市场对隔夜新闻、经济数据和机构活动的即时反应,通常具有高成交量和波动性的特征。交易者将该区间的边界作为参考点;向上或向下的突破可以预示该方向的潜在动能。这些水平有助于规划具有明确入场点、止损和目标的交易,使开盘区间成为早期趋势识别和结构化日内策略的实用工具。
有效了解和交易开盘区间在日内市场具有以下优势:
| 优势 | 说明 |
|---|---|
| 早期趋势检测 | 从最初15-30分钟区间突破预示潜在动能,帮助交易者与日内走势保持一致。 |
| 明确的交易规则 | 具有精确的高低边界,您可获得客观的入场点和止损水平,减少猜测。 |
| 内置风险管理 | 止损可设置在相反边界内侧,预先定义风险/回报。 |
| 时间效率和一致性 | 交易限制在上午窗口意味着屏幕时间更少,使系统可重复。 |
| 跨市场适用性 | 适用于股票、外汇、期货和时间框架,为交易者提供更大的灵活性。 |
| 波动性优势 | 利用早盘走势中出现的流动性和点差收窄。 |
| 策略灵活性 | 在统一框架内支持突破、反转和剥头皮策略。 |
我们使用两种主要方法来计算开盘区间。
方法一:双K线区间
此方法仅依赖两根K线。首先,取前一交易时段的最后一根K线,其高低点界定昨日收盘极值。接下来,使用当前时段的开盘K线,其高低点捕捉了最初的交易爆发。开盘区间仅仅是这两根K线最高价和最低价之间的距离。这为您提供了早期动量的即时快照,并有助于确定当日潜在突破点位。

首先,计算您交易时段开始的确切日期时间(例如,本地服务器时间09:30)。您可以通过编写代码获取,或通过SymbolInfoSessionTrade进行计算。
// Example: use SymbolInfoSessionTrade to get today's session start MqlDateTime nowStruct; TimeToStruct(TimeCurrent(), nowStruct); datetime from, to; SymbolInfoSessionTrade(_Symbol, (ENUM_DAY_OF_WEEK)nowStruct.day_of_week, SessionIndex, from, to); // 'from' now holds seconds since midnight; convert to full datetime: datetime todayStart = (TimeCurrent() - TimeCurrent()%86400) + from;
找到todayStart当天或之后第一根M1柱的索引,然后将下一根柱(索引+1)作为昨日的最后一根柱。
// Find bar numbers int firstBarToday = iBarShift(_Symbol, PERIOD_M1, todayStart, false); int lastBarYesterday = firstBarToday + 1;使用内置时间序列函数获取每根K线索引对应的最高最低价格。
double highYesterday = iHigh(_Symbol, PERIOD_M1, lastBarYesterday); double lowYesterday = iLow (_Symbol, PERIOD_M1, lastBarYesterday); double highToday = iHigh(_Symbol, PERIOD_M1, firstBarToday); double lowToday = iLow (_Symbol, PERIOD_M1, firstBarToday);取两个高点的最大值和两个低点的最小值来形成开盘区间,然后计算其大小。
double openingHigh = MathMax(highYesterday, highToday); double openingLow = MathMin (lowYesterday, lowToday); double openingSize = openingHigh - openingLow; PrintFormat("Opening Range → High: %.5f Low: %.5f Size: %.5f", openingHigh, openingLow, openingSize);
方法 2
此方法不使用特定K线,而是通过市场开盘后最初几分钟内的最高价和最低价来定义开盘区间。通过跟踪这些早期极端值,您可以实时捕捉当日的初步情绪和动能。这些开盘高低点水平随后作为您的突破阈值,一旦价格越过它们,就预示着该交易时段剩余时间的潜在趋势。

首先,计算当前交易时段开始的确切时间戳(例如,09:30)。我们使用SymbolInfoSessionTrade获取“开始时点”的秒数,并将其转换为完整的日期时间。
// Calculate the session’s opening datetime MqlDateTime nowStruct; TimeToStruct(TimeCurrent(), nowStruct); datetime fromSec, toSec; SymbolInfoSessionTrade(_Symbol, (ENUM_DAY_OF_WEEK)nowStruct.day_of_week, SessionIndex, fromSec, toSec); // Build a full datetime from today’s midnight plus the session offset datetime sessionStart = (TimeCurrent() - TimeCurrent() % 86400) + fromSec;
接下来,循环遍历sessionStart之后前RangeMinutes内的每根分钟K线,跟踪此区间范围内的最高价和最低价。
double orHigh = -DBL_MAX; double orLow = DBL_MAX; // Find the bar index at or just after sessionStart int startIdx = iBarShift(_Symbol, TF, sessionStart, false); // Loop through the first RangeMinutes bars (M1 timeframe) for(int i = startIdx; i >= startIdx - (RangeMinutes - 1); i--) { if(i < 0) break; // safety check double h = iHigh(_Symbol, TF, i); double l = iLow (_Symbol, TF, i); orHigh = MathMax(orHigh, h); orLow = MathMin(orLow, l); }
最后,您得到了orHigh和orLow。您可以计算区间大小,并将当前价格与这些水平进行比较以生成信号。
double openingSize = orHigh - orLow; PrintFormat("Opening Range (Method 2): High=%.5f Low=%.5f Size=%.5f", orHigh, orLow, openingSize); // Breakout detection double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(bid > orHigh) Alert("Breakout Long at price " + DoubleToString(bid, _Digits)); else if(bid < orLow) Alert("Breakout Short at price " + DoubleToString(bid, _Digits));
策略概述
该EA首先识别市场开盘时段的高低边界,从而实现开盘区间突破策略的自动化。在每个时段开始时,它记录时段开盘价,然后在接下来的RangeMinutes(例如,15分钟)内持续更新最高价和最低价。一旦该窗口关闭,它就在图表上绘制水平线和一个矩形,以直观地标出早期波动所在的"区间"区域。一个ATR过滤器(使用可配置的ATR周期和乘数)确保交易信号仅在波动率达到有意义水平时触发。
在定义区间后,EA会监控两步突破:首先,价格必须收于区间之外;其次,它必须回撤至边界,然后再次收于其外(“回测”)。当回测确认发生时,EA会在入场K线上绘制向上或向下的箭头,根据ATR计算止损和目标水平,并触发警报(屏幕、电子邮件和/或推送通知)宣布信号。仪表盘实时更新EA状态、ATR值及区间宽度,并于下一时段或午夜自动重置。
该EA首先识别市场开盘时段的高低边界,从而实现开盘区间突破策略的自动化。在每个时段开始时,它记录时段开盘价,然后在接下来的RangeMinutes(例如,15分钟)内持续更新最高价和最低价。一旦该窗口关闭,它就在图表上绘制水平线和一个矩形,以直观地标出早期波动所在的"区间"区域。一个ATR过滤器(使用可配置的ATR周期和乘数)确保交易信号仅在波动率达到有意义水平时触发。
在定义区间后,EA会监控两步突破:首先,价格必须收于区间之外;其次,它必须回撤至边界,然后再次收于其外(“回测”)。当回测确认发生时,EA会在入场K线上绘制向上或向下的箭头,根据ATR计算止损和目标水平,并触发警报(屏幕、电子邮件和/或推送通知)宣布信号。仪表盘实时更新EA状态、ATR值及区间宽度,并于下一时段或午夜自动重置。
EA组成分解详述
1. 文件头和属性
文件头部使用 #property 声明版权、链接及版本。这不仅仅是样板代码;#property strict指令告诉编译器强制执行现代MQL5规则(无隐式转换、强制函数原型等),这有助于在编译时捕获细微的错误。通过设置#property link,任何在MetaEditor中检查该EA的人都可以点击链接访问我们的MQL5社区主页,这加强了版本控制和作者身份。您还可以使用#property description嵌入您自己的注释,这些注释会显示在EA的属性对话框中,使读者更容易记录他们的设置,而无需额外的UI代码。
//+------------------------------------------------------------------+ //| ORB Breakout EA| //| Copyright 2025, MetaQuotes Ltd.| //| https://www.mql5.com/en/users/lynnchris| //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property description "Opening‑Range Breakout with ATR confirmation" #property strict
2. 输入参数
我们将用户可自定义的设置项分门别类,通过清晰的注释进行说明,涵盖会话索引、范围长度、ATR过滤设置、箭头编码/颜色以及警报开关。在MQL5中,输入变量会自动出现在EA的属性对话框中,具有正确的类型,并且枚举(如用于时间框架的ENUM_TIMEFRAMES)会渲染为下拉菜单——无需手动构建自己的GUI。请注意,通过选择input int ArrowUpCode,我们允许用户选择任意的Wingdings字符代码,但如果我们强制指定特定的列表,我们可以在编译时定义我们自己的枚举ArrowSymbol { UP=233, DOWN=234 }来限制选择。如果希望锁定输入使其在运行时无法编辑,输入变量也支持只读属性。
//--- session & range input int SessionIndex = 0; // 0 = first session input int RangeMinutes = 15; // minutes to capture range //--- ATR filter input ENUM_TIMEFRAMES TF = PERIOD_M1; // ATR timeframe input int ATRPeriod = 14; // ATR look‑back input double ATRMultiplier = 1.5; // ATR * multiplier //--- arrows & alerts input int ArrowUpCode = 233; // wingdings ↑ input int ArrowDnCode = 234; // wingdings ↓ input color ArrowUpColor = clrLime; // long arrow input color ArrowDnColor = clrRed; // short arrow input bool SendEmailAlert = false; // email on signal input bool PushNotify = false; // push on signal input string EmailSubject = "ORB Signal"; // mail subject
3. CRangeCapture类
将开盘区间逻辑封装进独立的 CRangeCapture 类,不仅简化了 OnTick() 主函数,也体现了MQL5面向对象编程的核心优势。我们将开盘时间与实时变动的高低价封装到类中,提供了 Init()、Update() 和 IsDefined() 三个核心方法。由于 MQL5 类不会自动执行构造函数,必须显式调用 Init() 完成初始化。此外,将高低价hi 和 lo 声明为 double 类型,可以充分利用 MQL5 的64位浮点运算精度,这对精确处理外汇报价至关重要。如果您以后想将每个tick的高低点记录到内部缓冲区中,可以扩展此类,这说明了类如何在保持原始接口的同时进行演进。
class CRangeCapture { private: datetime startTime; double hi, lo; public: void Init(datetime t, double price) { startTime = t; hi = lo = price; } void Update(double price, datetime now) { if(now < startTime + RangeMinutes*60) { hi = MathMax(hi, price); lo = MathMin(lo, price); } } bool IsDefined(datetime now) const { return(now >= startTime + RangeMinutes*60); } double High() const { return hi; } double Low() const { return lo; } }; static CRangeCapture g_range;
4. CATRModule类
此处我们将内置ATR指标句柄封装于 CATRModule 类中。Init() 创建句柄并检查 INVALID_HANDLE,以防品种或周期设置错误。Value()方法每个tick仅调用一次CopyBuffer,这比在OnTick()中反复调用iATR效率要高得多。通过缓存句柄,我们避免了内存泄漏并减少了开销。在 Release() 函数中调用 IndicatorRelease() 释放指标句柄是必不可少的操作。如果省略这一步,终端的“指标”标签页会不断积累大量无效指标。采用模块化设计,将EMA、布林带等指标独立封装,能让形态识别逻辑清晰易读,可灵活扩展而不破坏原有代码结构。
class CATRModule { private: int handle; public: bool Init() { handle = iATR(_Symbol, TF, ATRPeriod); return(handle != INVALID_HANDLE); } double Value() const { double buf[]; if(handle != INVALID_HANDLE && CopyBuffer(handle, 0, 0, 1, buf) == 1) return buf[0] * ATRMultiplier; return 0.0; } void Release() { if(handle != INVALID_HANDLE) IndicatorRelease(handle); } }; static CATRModule g_atr;
5. CRetestSignal类
CRetestSignal类使用三个简单的布尔值实现我们的"突破、回测、再突破"模式。我们将breakLong、breakShort 和 retested 设为私有变量,Reset()、OnBreak() 和 CheckRetest() 则为公共方法这对OnTick()隐藏了实现细节,因此读者关注"是什么"而不是"如何做"。请注意,我们通过引用传递最新的MqlRates K线,这节省了用于拷贝复制的内存开销。如果您需要支持多个时间框架,可以扩展CheckRetest()以接受MqlRates数组或时间框架参数,这展示了MQL5中方法重载的灵活性。
class CRetestSignal { private: bool breakLong, breakShort, retested; public: void Reset() { breakLong = breakShort = retested = false; } void OnBreak(double close, double h, double l) { breakLong = (close > h); breakShort = (close < l); retested = false; } bool CheckRetest(const MqlRates &r, bool &isLong) { if(breakLong) { if(!retested && r.low <= g_range.High()) { retested = true; isLong = true; return false; } if(retested && r.close > g_range.High()) { isLong = true; return true; } } else if(breakShort) { if(!retested && r.high >= g_range.Low()) { retested = true; isLong = false; return false; } if(retested && r.close < g_range.Low()) { isLong = false; return true; } } return false; } }; static CRetestSignal g_retest;
6. 图表仪表板
CDashboard 类在左上角创建简单的 OBJ_LABEL 标签,提供实时反馈。您可以看到Init()、Update()和Delete()如何管理此标签的生命周期,此模式同样适用于OBJ_TEXT、OBJ_RECTANGLE或任何其他对象类型。标签内容随每个tick更新,但由于重复设置相同文本的性能开销极低,整体运行效率仍能保持高水平。若想进一步优化性能,可以缓存上一次的显示字符串,仅在文本内容实际变化时才调用 ObjectSetString() 函数。这一优化充分说明,在对象管理上的细微调整,就能在高频tick触发的EA中带来可观的性能提升。
class CDashboard { private: string name; public: void Init() { name = "ORB_Info"; if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30); } } void Update(const string &txt) { ObjectSetString(0, name, OBJPROP_TEXT, txt); } void Delete() { if(ObjectFind(0, name) >= 0) ObjectDelete(0, name); } }; static CDashboard g_dash;
7. 交易界面与通知
尽管本示例暂不实际下单,但我们仍定义了静态对象CTrade trade;,用于展示后续接入真实交易逻辑的实现思路。更关键的是,当交易信号确认后,程序会调用用户指定的Wingdings字符代码与配色绘制箭头指标(OBJ_ARROW),并同时触发Alert()弹窗提示、SendNotification()终端推送和SendMail()邮件通知。这套组合完整展示了MQL5内置的事件与消息机制,无需依赖任何外部类库。你还可以进一步集成PlaySound()音效播放或EventChartCustom()网络回调函数,向读者直观呈现MT5原生通信通道的丰富扩展性。
static CTrade trade; // ... inside your retest-confirmation block: string msg = StringFormat("%s Signal @%.5f SL=%.5f TP=%.5f", isLong ? "LONG" : "SHORT", r[0].close, sl, tp); Alert(msg); if(PushNotify) SendNotification(msg); if(SendEmailAlert) SendMail(EmailSubject, msg); // draw arrow on chart: string arrowName = "ORB_Arrow_" + IntegerToString((int)r[0].time); ObjectCreate(0, arrowName, OBJ_ARROW, 0, r[0].time, isLong ? r[0].low - 5 * _Point : r[0].high + 5 * _Point); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, isLong ? ArrowUpCode : ArrowDnCode); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, isLong ? ArrowUpColor : ArrowDnColor);
8. OnInit()与OnDeinit()
OnInit() 函数:我们在此初始化ATR模块与数据面板。若初始化出现任何异常,则返回INIT_FAILED状态码。这种设计能确保EA(智能交易系统)绝不会以残缺状态启动运行。OnDeinit() 函数:我们会在此规范释放ATR句柄并删除所有图表对象,避免在重载或移除EA时,残留孤立的指标或无效对象。在实际部署代码时,必须严格遵循以下配对原则:每通过iXXX函数创建的句柄,都必须搭配IndicatorRelease()释放;每通过ObjectCreate()创建的对象,要么在OnDeinit()中调用ObjectDelete()主动销毁,要么在重置流程中通过条件逻辑进行清理。
int OnInit() { if(!g_atr.Init()) return INIT_FAILED; g_dash.Init(); return INIT_SUCCEEDED; } void OnDeinit(const int reason) { g_atr.Release(); ObjectDelete(0, "ORB_High"); ObjectDelete(0, "ORB_Low"); ObjectDelete(0, "ORB_Range"); g_dash.Delete(); }
9. OnTick() 状态机
OnTick()是EA的核心运行单元。代码使用static bool inited和static int state两个静态变量,让它们的取值在多次OnTick()调用之间保持不变。这是MQL5规避全局变量和外部存储,实现单EA独立内存管理的经典方法。我们首先计算当日交易时段的起始时间,并实现每日一次的状态重置逻辑,是日内交易策略中最常见的时间维度控制范式。然后通过switch(state)语句将交易策略拆解为四个清晰阶段——(行情)捕捉、(突破)确认、(支撑阻力)回踩、(周期)结束。由于MQL5不支持协程式的代码暂停与恢复,采用状态机将多步骤策略拆解为单tick独立执行,是编写复杂EA的标准范式。这种设计让每一分支逻辑都足够轻量化,便于独立测试。
void OnTick() { static bool inited = false; static int state = 0; static datetime sessionStart; if(!inited) { // compute sessionStart, init g_range & g_retest, Alert inited = true; state = 0; } // fetch latest MqlRates r[0] and bid/ask switch(state) { case 0: // Capture g_range.Update(bid, TimeCurrent()); if(g_range.IsDefined(TimeCurrent())) state = 1; break; case 1: // Break if(r[0].close > g_range.High() || r[0].close < g_range.Low()) { g_retest.OnBreak(r[0].close, g_range.High(), g_range.Low()); state = 2; } break; case 2: // Retest { bool isLong; if(g_retest.CheckRetest(r[0], isLong)) state = 3; } break; case 3: // Done break; } }
10. 午夜重置
最后,通过对比 today = now - now%86400 与静态变量 lastDay,实现日期变更检测。一旦日期更替,即删除旧有图表对象并重置状态标志,彻底摒弃“if hour==0”这类粗糙写法。该方案适用于所有基于自然日的EA场景,如零延迟开盘、每日Pivot计算、收盘统计等。采用此标准范式,可有效规避跨零点时因时区或夏令时切换引发的“差一天”等细微逻辑Bug。
// at the end of OnTick(): static datetime lastDay = 0; datetime today = TimeCurrent() - TimeCurrent() % 86400; if(today != lastDay) { lastDay = today; inited = false; state = 0; ObjectDelete(0, "ORB_High"); ObjectDelete(0, "ORB_Low"); ObjectDelete(0, "ORB_Range"); }
回测与结果
回测就是将EA中写好的交易策略,完全按原样在历史市场数据中运行,观察该策略在过去会有怎样的表现。这一过程让你可以:
- 验证交易规则是否能得到合理的结果;
- 测算胜率、最大回撤、盈利因子等关键指标;
- 优化输入参数(如区间长度、ATR倍数),寻找在历史上表现最好的参数组合。
在 MetaTrader 5 中,策略测试器会将每一个历史 tick 传入 OnTick() 函数,因此:
- OnInit() 负责初始化一切:ATR 句柄、图表对象、初始状态;
- OnTick() 驱动区间识别、突破/回测逻辑、绘制箭头、触发警报,并在每个模拟 tick 上更新仪表盘;
- OnDeinit() 在测试结束后完成清理工作。
换句话说,你在实盘图表上运行的代码路径,与测试器用来“回测”的路径完全一致。

上面的动图展示了开盘区间突破 EA 在 EURUSD M15 周期上进行回测的过程。主图中可以看到一个阴影矩形标出开盘区间,上下由两条水平线界定,对应初始时段的高点和低点。这直观展示了 EA 认为可能出现显著价格波动的区域。
图表上每个绿色箭头都代表一个已确认的多头入场信号。EA 的“突破 → 回测 → 二次突破”逻辑确保:价格必须先突破上边界,随后回踩该边界,并且收盘价再次站上边界后,箭头才会出现。这种两步确认机制可以有效过滤假突破,仅在真实动能存在时才发出信号。
图表下方的日志面板记录了所有关键事件:交易时段启动、区间界定、突破识别,以及最终信号的入场价、止损价和止盈价。这些日志完整再现了 EA 内部状态切换过程,让交易决策的形成逻辑与时间节点一目了然。
本案例展示了 ORB 策略如何捕捉开盘时段波动、确认真突破,并在 EURUSD M15 周期上生成可复现、质量较高的交易信号。

我也在 AUD/USD 的 M5 周期上测试了这款 EA,以便更清晰地观察日内价格走势,详见上图。
结论
我们用 MQL5 开发的这款开盘区间突破 EA,将“早盘价格走廊”这一简单概念,转化为一套纪律严明、可自动运行的策略。通过将区间识别、波动止损、回测验证、图表反馈等模块化,我们构建了易于维护、同时满足实盘运行速度要求的代码库。
这一方案解决了日内交易的两大核心难题:一是区分真趋势与短暂脉冲;二是根据实时市场状况动态调整风险敞口。“突破 → 回测 → 二次突破”的确认流程过滤掉了虚假波动,而基于 ATR 的止损止盈水平则随波动率动态调整。由此,EA 能够输出稳定、高信心的信号,正是那种在动荡市场中依然可靠、并利用真实价格行为获利的入场点。
现在,请把这套策略改造成你自己的版本。在 MetaEditor 中编译 EA,在不同品种和时段中回测,尝试调整区间时长、ATR 倍数等参数。看着矩形、水平线和箭头在图表上逐步“活起来”,并通过日志跟踪每一个决策的执行过程。掌握这套 ORB 框架后,你将能够把每日的开盘波动转化为可重复、令你更有信心的交易机会。祝你入场更精准,风控更从容。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/18486
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
从新手到专家:使用 MQL5 制作动画新闻标题(五)—— 事件提醒系统
新手在交易中的10个基本错误
重构经典策略(第十三部分):让我们的交叉策略迈向新维度(2)