开发EA前如何科学规划交易策略
在着手开发一个智能交易系统(EA)之前,对交易策略进行周密规划是至关重要的一步,这能让整个开发过程目标明确,有的放矢。
通常,一个完整的EA策略框架包含以下几个核心环节:
1、开仓信号:明确市场需要满足何种条件时,EA才执行开仓操作,并区分何时建立多头头寸(做多),何时建立空头头寸(做空)。
2、平仓条件:清晰界定在何种市场情况下,EA应当平掉现有持仓,锁定利润或控制风险。
3、止损与止盈设置:EA是否规划了止损和止盈位,以及如何科学设定。通常,设置止损十分必要,它能够有效防范突发性行情波动带来的潜在损失。与股票交易不同,外汇交易在下单时即可预先设定好止损与止盈价位,一旦价格触及这些水平,系统会自动执行平仓。
以做多为例:假设买入价为1.5000,止损设为1.4800,止盈设为1.5100,那么止损点差为200点,止盈点差为100点。
4、加减仓规则:策略是否包含加仓或减仓机制,以及在何种情形下触发。
接下来,我们以拉里·威廉姆斯在《短线交易秘诀》中提及的一套方法作为示例策略来演示。
if
语句:当括号内的条件评估为真时,程序将执行花括号 { } 中的代码块。
if语句:用于条件判断,若条件成立,则运行指定代码段。
==运算符:用于判断两个值是否相等。
&&运算符:表示逻辑与,需要多个条件同时为真。
Hour函数:返回当前时间的小时数(范围0~23)。
Minute函数:返回当前时间的分钟数(范围0~59)。
Open[0]代表当前K线周期的开盘价,Close[1]代表上一周期的收盘价,
Open和Close均为系统预设数组,分别存储开盘价与收盘价,索引0和1表示具体的周期序号,数组的详细概念将在后续章节展开讲解。
本EA示例运行在H1(小时图)周期,
因此Open[0]即当前一小时K线的开盘价,
而Close[1]则代表上一小时K线的收盘价;当某行(如第8行)设定的条件成立时,
Open[0]可对应为一周开始周一的开盘价,
Close[1]则相当于上周五的收盘价。
行11:执行买入下单操作。
行13:执行卖出下单操作,OrderSend函数负责发送交易指令,
其各参数含义如下:
参数1:交易品种。Symbol函数返回EA当前所依附的货币对名称。
参数2:订单类型。OP_BUY为买入单,OP_SELL为卖出单,
还有OP_BUYSTOP(买入止损单)、OP_BUYLIMIT(买入限价单)、OP_SELLSTOP(卖出止损单)、OP_SELLLIMIT(卖出限价单)等类型。
参数3:下单手数。本示例设置为0.1手。
参数4:交易价格。买入单通常以Ask(卖价)成交,卖出单以Bid(买价)成交。
参数5:允许的滑点。从发出指令到实际成交之间存在时间差,价格可能变动,因此可设定一个最大偏离值,单位为Point。
参数6:止损价位,若为0则表示不设置止损。
参数7:止盈价位,若为0则表示不设置止盈。
参数8:订单备注信息。
参数9:订单的魔术数字,用于区分不同EA(或其他程序)下的订单。
参数10:订单有效期,仅适用于挂单,当挂单被触发后自动失效,为0表示永久有效。
参数11:图表箭头颜色,下单成功后会在图表上显示一个标记,买入单通常为蓝色,卖出单为红色。
返回值:订单编号,若返回-1表示下单失败(本例未进行结果检查)。
行16:选定一笔订单。在对订单执行操作前,一般需要先通过OrderSelect函数选中目标订单。
参数2(此处指OrderSelect的第二个参数):选择标准。
SELECT_BY_POS:按订单序号选择,所有订单从0开始编号。
SELECT_BY_TICKET:按订单唯一编号选择。
这两个常量均为整数类型。
参数1:根据参数2指定的标准,提供对应的订单序号或编号。
行17:若当前时间与选定订单的下单时间间隔超过一天,则执行第18至23行的代码。
TimeCurrent函数:返回当前时间(以秒为单位,自1970年1月1日零点起)。
OrderOpenTime函数:返回所选订单的下单时间戳(秒)。
行18:若订单为买入单,则以Bid价格平仓(行19)。
行19:若订单为卖出单,则以Ask价格平仓(行22)。
OrderType函数:返回所选订单的类型。
参数1:订单编号,OrderTicket函数可获得当前选定订单的编号。
参数2:平仓手数,OrderLots函数返回当前订单的持仓手数。
参数3:平仓价格,买入单用Bid,卖出单用Ask。Ask与Bid为浮点数变量,相关概念后续详述。
参数4:允许滑点,含义与OrderSend中的一致。
本示例EA的代码量约为28行。
考虑到初学者,我们引入了尽量少的概念。
在此基础上稍作拓展,添加少量代码,即可可靠地实现完整的交易逻辑,整个代码量通常不会超过40行。
一般而言,完整实现一个交易思路所需的EA代码量并不庞大,即便是复杂的策略,
有经验的开发者往往也能将代码量控制在500行以内。如果某个交易思路需要过多的代码来表达,
通常可能源于以下两种情况。
第一种情况,逻辑结构混乱。MT平台中EA的运行方式与人工交易的步骤式思维有所不同。
人工交易往往讲究先后顺序,例如先开仓、后平仓,思维上有明确的延续性。
而EA的所有逻辑都集中在start函数内,
start函数的执行并不遵循人工的步骤顺序(其内部代码虽按顺序执行),
“每次价格变动,start函数被调用一次”是对EA逻辑的高度概括。
这种反复调用的随机性与人工交易的步骤性思维存在差异,
为了将这种随机逻辑转化为有序步骤,开发者需要在程序内部维护并检查当前交易进度状态,
以便每次start被触发时,能根据当前状态决定下一步动作:开仓还是平仓。
在ea_002中,行8、行9、行17就是对当前交易状态的判断,
特别是行17,若移除该行,可能导致在周一开盘的5分钟内,EA反复开平仓。
-------------------------------------------------------------------------------------------------------------------------
1.1. 基本语法
MT4的源代码通常由以下几部分组成,各部分之间常用换行进行分隔:
1、注释
注释是源码中的说明性文字,旨在提高代码的可读性。
编译时,注释部分会被忽略。
(1)单行注释:以 // 开头的行即为注释。
(2)多行注释:以 /* 开始,以 */ 结束,中间的部分均为注释。
2、预处理指令
以 # 开头的行,用于特殊说明,具体细节可参考“预处理指令”章节。
3、全局变量定义
可参考“变量”章节。
4、函数
除了上述部分,其余代码均由若干函数构成,函数间可相互调用。
函数由语句组成,语句以分号结尾,具体内容将在后续逐步介绍。
除非特别说明,代码是区分大小写的,例如 start 与 START 视为不同。
关于语句元素的约定如下:
2、保留字
保留字是MT语言预先占用的标识符,用户不能用于变量命名,以下为常见的保留字,后续会逐一提到:
bool, break, case, color, continue, datetime, default, double,
else, extern, false, for, if, int, return, static, string, switch, true, void, while。
其中 return 既可视为保留字,也可看作一个特殊函数。
