任何交易策略的首要核心元素,就是价格分析以及作为建仓基础的技术指标分析。我们称其为市场分析,即市场中发生的所有事情以及我们无法控制的事情。
此外,策略可能还需要另外一种类型的分析。我们称其为当前交易状况分析。它包括交易仓位状态分析、以及任何可用/缺失的挂单分析(如果用于一个策略之中)。这些分析的结果,可以帮助我们决定是否应该对仓位或订单采取某些动作,比如平仓,移动止损,下挂单或删除挂单等。换言之,这种分析会根据我们(或一个EA交易)所创建的情况以及所使用的策略规则,对我们的市场行为、动作进行研究。
从某种程度上来说,人们通常所说的“跟踪止损”,被认为是交易策略中的第二种元素类型。让我们来看看以下的分析:如果有一个持仓,其利润高于设定值,但没有设置止损,或者设置的止损远远高于当前的价格,就应该移动止损。
跟踪止损是一个非常简单的功能,而且效果很好。此外,它还是一种完全不同的交易策略因素,是一个仓位管理函数。因此,一个交易策略可以包括三种类型的要素:
以其为基础的市场分析和动作。
以其为基础的交易情况和动作分析。
仓位管理。
本文主要介绍一些主动使用挂单的策略(我们称其为订单策略)、用来描述这些策略的一种元语言、以及如何使用一种以这些描述为基础运行的多目标工具(EA 交易)。
交易通常都从建一个初始仓位开始。可以用多个方法进行:
建一个市场仓位:
在指标显示的方向中建仓。
在 EA 属性窗口中用户选择的方向中建仓。
根据上一个仓位的平仓结果而定。这种仓位并不是一个初始仓位,它可以处于一个中间操作阶段。
两个反向止损订单。当这两个订单中启动了一个,另一个就会被删除。
两个反向限价订单。当这两个订单中启动了一个,另一个就会被删除。
限价订单和止损订单都放在相同的方向。在这个例子中,需要决定订单的方向,如 1。
一旦初始仓位建立,您就可以使用不同的订单策略。
使用限价订单加仓(图 1)
您建立一个初始仓位,用增加的手数大小,在同一个方向设置了一个或多个限价订单。限价订单启动后,就设定了新的限价订单,直到仓位在获利位平仓。当仓位在获利位平仓,剩下的挂单就会被删除。
图 1. 使用限价订单加仓
止损和反转(图 2)
您建立一个初始仓位,在初始仓位的止损位,用增加的手数大小设置反向止损订单。当仓位在止损位平仓,挂单中再次在止损位设置一个新的反向止损订单,直到仓位在获利位平仓。当仓位在获利位平仓,剩下的挂单就会被删除。
图. 2. 止损和反转
金字塔(图 3)
您建立一个初始仓位,如果显示您正在获利,就增加其规模(加仓),移动止损位至盈亏平衡位。如果仓位在获利位平仓,这时候它可能已经达到一个相当大的交易量,因此获利。但是,如果在中间阶段启动止损,就没有盈利。
图 3. 金字塔
再建仓(图 4)。
建一个市场仓位:在止损位平仓,然后用增加的手数大小再次建仓,一直到仓位在获利位平仓。这个策略类似用限价订单加仓。
图. 4. 再建仓
我们也可以将上述所有策略结合起来使用。如果一个仓位显示正在盈利,就适合选择金字塔,如果正在出现亏损,就比较适合限价订单加仓。也就是说,限价订单加仓不必持续进行。比如,您可以首先加仓 3 次,然后进行几次止损和反转,再切换至限价订单加仓等等。
在实际操作中,订单策略的制定非常耗费时间,不仅因为需要很多代码,还因为需要对每一个事例中进行创意思考。让我们试着加快这种策略的编程,方法就是创建一个可以让我们实施任何一种订单策略的多目标 EA 交易。
开发订单策略的基础原则,是识别出当前的策略操作阶段,根据这个阶段采取动作。
让我们看看下面这个例子:我们需要建一个市场仓位,也就是说一个买入仓位。一旦仓位建立,就需要设置两个挂单:一个止损单在上,一个限价单在下。开始的时候市场中还没有仓位或订单,因此识别的阶段为初始操作阶段,我们在这个阶段需要建一个仓位。如果存在市场仓位,就意味着这是下一个操作阶段。因此,可以按照下面的方式识别阶段:
没有仓位或订单。需要建仓。
有一个仓位但没有设置订单,需要建立止损单。
有一个仓位和一个止损单,需要建立限价单。
按照这些规则进行的操作是比较可靠的,但还需要三个即时价格:第一个即时价格,是识别出缺少仓位和建立仓位,第二个即时价格,是识别出仓位和缺少订单,第三个即时价格,是识别出仓位和一个订单。这个策略需要同时完成这三个动作。
因此,我们应该试着同时进行所有动作:如果没有仓位或订单,我们就应该建立一个仓位。如果仓位已经成功建立,我们应该发送两个请求,一个设置止损单,一个设置限价单。如果所发送全部设置挂单请求都没有被接受(比如由于连接问题或者缺少价格信息等),但交易情况已经转换到另外一个阶段,我们可以在这个阶段中建仓。这就意味着应该涵盖所有可能的中间阶段:
没有仓位。需要建仓。如果仓位已经成功建立,应该发送止损单和限价单的请求。
有一个仓位但没有挂单,应该发送止损单和限价单的请求。
有一个仓位和一个止损单,但没有限价单。发送限价单请求。
有一个仓位和一个限价单,但没有止损单。发送止损单请求。
请注意,为了识别在指定例子中的阶段,交易情况必须完全符合所提供的识别规则。应该有某些订单组合:只有一个仓位而没有订单,或一个仓位和两个订单 - 不能有其他的方法。这个原则随之而来,就是冗长的策略操作阶段的描述,让这个过程变得非常耗时,因为需要对所有可能的选项进行描述,而事实证明这根本不可行。上述例子的操作规则,可以通过一个略有不同的方式设置:
没有仓位。需要建仓。如果仓位已经成功建立,应该发送止损单和限价单的请求。
有仓位。在这种情况下,市场中应该有两个挂单。检查一下,市场中是否有一个止损单,如果没有,对它进行设置。检查一下,市场中是否有一个限价单,如果没有,对它进行设置。
在这个例子中,我们为识别操作阶段提供了一个最小的规则系列,还对每个交易阶段应该达到的交易情况作出完整描述。
这个规则的应用,需要对仓位自身进行识别,识别出是否是初始仓位,或某个订单是否已经启动。在这些情况下,不需要试图下第二个订单,因为系统正处于一个新的操作阶段。我们还需要对订单进行识别,仓位和订单识别方面的内容将稍后讨论。我们现在先以一个更清晰明了的方式,制定描述订单策略的基本原则。
我们需要一种方法,用尽可能少的信息量描述当前的操作阶段。
每一个操作阶段都必须有一个与该阶段相对应的完整情况描述。
如果在任一指定的阶段需要市场动作(建仓、平仓、加仓、减仓等)或挂单,应该将这个阶段分成两个子阶段:进行市场行为操作之前和之后(这可以让我们能够一次进行所有的动作,重复失败的挂单操作)。
如果在任一指定的阶段需要市场动作(建仓、平仓、加仓、减仓等)或挂单,则应该在成功完成市场行为后,处理挂单。
一个阶段只能对应一个市场动作和任一数量的挂单动作。
可以用几种方式识别订单和仓位:使用订单注释、魔法数字或全球变量。首先是注释方法。使用注释过程中出现的最主要的问题,是注释的长度有限,此外,交易商可能会在注释中加入自己的内容。如果注释中没有足够空间供交易商加入自己的内容,您所写的部分注释可能会被删除。
因此,您应该尽可能用最少的空间写注释,并且想办法将其与交易商可能输入的内容分隔开。每一个订单只需要一个标识符。在实际情况中,可能是 1 或者 2 个图,或者一个字母和 1 个或 2 个图相结合。我们在标识符的末端放置一个标志,即 "="(从未发现交易商在其输入内容中使用这种标记)。因此,我们有最多 4 个字符。为了从一个注释中获得标识符,我们可以使用以下函数:
//+------------------------------------------------------------------+ //| 从aComment字符串中获取标识符的函数 | //+------------------------------------------------------------------+ string GetID(string aComment) { int p =StringFind(aComment,"=",0); // 确定分隔符的位置 string id=StringSubstr(aComment,0,p); // 获取分隔符前的子字符串 return(id); } //+------------------------------------------------------------------+
如果需要任何已知的标识符对仓位或订单进行检查,可以用以下方式进行:
//+------------------------------------------------------------------+ //| 检查已设置标识符的备注 | //+------------------------------------------------------------------+ bool FitsID(string aID,string aComment) { return(StringFind(aComment,aID+"=",0)==0); } //+------------------------------------------------------------------+
现在,让我们来定义用来描述订单策略的语言。语言应该简洁、清晰、直观,同时还要符合MQL5确保指令快速实施,无需进行不必要的计算。结果是否成功,我将把这个问题留给读者来决定。
策略的描述在一个文本文件中完成。然后在 EA 属性窗口中为这个文本命名,将其与 EA 连接。
文件的一行内容要与一个系统操作阶段相对应。这行内容分成两个域。第一个域包括阶段识别规则。第二个域包括动作列表。用竖线 "|" 将两个域分开。列出识别规则和动作列表项,用分号 ";" 将其分开。
除了指令,每一行的右侧都包括一个注释,用 "#" 与文本的其他内容分隔开,比如:
Nothing | Buy(M1,1,0,0) #If there is no position or order in the market, open a Buy position, mark it with "М1", lot 1, no Stop Loss, no Take Profit.
阶段识别
阶段识别可能需要关于当前市场仓位、挂单或上一次交易的信息。除了仓位状态,可能还需要一些仓位详情,比如价格、盈利、止损值(如果设置了相关信息)。所需要的上次交易信息可能还包括交易结果。对于挂单,可能需要指定其开盘价、止损位、获利位(最有可能需要这些信息的阶段就是执行阶段)。
可以使用交易数据访问指令获得这些信息。在这些指令中,大部分都有两个参数:仓位或订单标识符和参数标识符。如果参数标识符尚未确定,只需检查是否存在由指令和标识符确定的交易对象。
比如,Buy(M1) 指令显示出,必须有一个带有 "M1" 标识符的市场仓位。Buy() 指令自身(或不带有括号的 Buy)意味着必须有一个带标识符的买入仓位。如果您确定了参数标识符,它将显示出参数值,比如 Buy(M1,StopLossInPoints) - 为带有 "M1" 标识符的买入仓位设置的止损点数值。如果未确定标识符 - Buy(,StopLossInPoints),我们将其视为:带有标识符的买入仓位止损(如果有买入仓位)。
所获得的值可用于描述检查状况,比如 Buy(M1,StopLossInPoints)>=0 - 仓位处于平衡状态。如果没有仓位,或有一个带有不同标识符的仓位,就不会标识出按照那种标识规则方式描述的阶段,也就是说,不需要描述两种情况 - 检查仓位状态和止损值。但是在这个例子中,就需要提前检查是否存在止损 - Buy(M1,StopLossExists); Buy(M1,StopLossInPoints)>=0。
在检查这些值的时候,可以使用各种对照描述:">=", "<=", "==", "!=", ">", "<". 在对照描述右侧的值,可以表述为一个数字,或者用特殊的变量代表:Var1, Var2 ...Var20。在一个数字或一个变量的后面加上一个 "p",代表这个值还要与点值(_Point 变量)相乘。
或者,在对照表达式的右侧,可能有一个更复杂的计算式描述。可以按照以下的形式:X1*X2+X3*X4("+" 当然可以用 "-" 替代),而 X1, X2, X3 和 X4 可以是数字、变量或者数据访问指令。以下例子在理论上可以被认为是正确的(如果我们不去看其实际的值):
-BuyStop(BS1,StopLossInPoints)*-SellLimit(SL1,StopLossInPoints)+-SellStop(SS1,StopLossInPoints)*-BuyLimit(SL1,StopLossInPoints)
表 1 为所有访问指令列表。
表 1 数据访问指令
索引 | 指令 | 可能的参数 | 目标 |
---|---|---|---|
0 | Nothing | 无参数 | 市场中没有仓位或挂单 |
1 | NoPos | 无参数 | 市场中无仓位 |
2 | Pending | 对象标识符,订单参数标识符 | 已确定带对象标识符的挂单。如果未确定目标标识符,那么无论目标标识符的值如何,已确定挂单。 |
3 | Buy | 对象标识符,仓位参数标识符 | 已确定带有对象标识符的买入仓位。如果未确定对象标识符,已确定一个买入仓位 |
4 | Sell | 对象标识符,仓位参数标识符 | 已确定一个带有对象标识符的卖出仓位。如果未确定对象标识符,已确定一个卖出仓位 |
5 | BuyStop | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的买入止损单。如果对象标识符没有确定,已确定一个买入止损单 |
6 | SellStop | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的卖出止损单。如果未确定对象标识符,已确定一个卖出止损单 |
7 | BuyLimit | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的买入限价单。如果对象标识符没有确定,已确定一个买入限价单 |
8 | SelLimit | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的卖出限价单。如果对象标识符没有确定,已确定一个卖出限价单 |
9 | BuyStopLimit | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的买入止损限价单。如果对象标识符没有确定,已确定一个买入止损限价单 |
10 | SellStopLimit | 对象标识符,订单参数标识符 | 已确定一个带对象标识符的卖出止损限价单。如果对象标识符没有确定,那么就是一个卖出止损限价单 |
11 | LastDeal | 空,交易参数标识符 | 上一个交易 |
12 | LastDealBuy | 空,交易参数标识符 | 上一个交易是买入交易 |
13 | LastDealSell | 空,交易参数标识符 | 上一个交易是卖出交易 |
14 | NoLastDeal | 无参数 | 历史上没有交易数据;如果 EA 交易刚刚开始账户操作,这是必要的。 |
15 | SignalOpenBuy | 无参数 | 指标发出信号,建一个买入仓位 |
16 | SignalOpenSell | 无参数 | 指标发出信号,建一个卖出仓位 |
17 | SignalCloseBuy | 无参数 | 指标发出信号,建一个买入仓位 |
18 | SignalCloseSell | 无参数 | 指标发出信号,建一个卖出仓位 |
19 | UserBuy | 无参数 | 用户指令买入 |
20 | UserSell | 无参数 | 用户指令卖出 |
21 | Bid | 无参数 | 竞标价格 |
22 | Ask | 无参数 | 询价 |
23 | ThisOpenPrice | 无参数 | 已计算参数的订单开盘价。用于挂单的动作指令中,止损限价类型的订单除外。 |
24 | ThisOpenPrice1 | 无参数 | 已计算参数的订单开盘价-1。用于止损限价类型的挂单动作指令 |
25 | ThisOpenPrice2 | 无参数 | 已计算参数的订单开盘价-2。用于准限价类型的挂单动作指令 |
26 | LastEADeal | 对象标识符,交易参数标识符 | EA 执行的最后一个交易。在历史中搜索注释中带有 "=" 的最后一个交易,然后用对象标识符进行检查。 |
27 | LastEADealBuy | 对象标识符,交易参数标识符 | EA 执行的最后一个交易是一个买入交易。在历史中搜索注释中带有 "=" 的最后一个交易,然后用对象标识符和交易方向进行检查 |
28 | LastEADealSell | 对象标识符,交易参数标识符 | EA 执行的最后一个交易是一个卖出交易。在历史中搜索注释中带有 "=" 的最后一个交易,然后用对象标识符和交易方向进行检查 |
29 | NoTradeOnBar | 无参数 | 在最后一根柱中没有交易 |
在表 1 中所设置的指令让您可以访问以下类型的交易对象:仓位、订单、交易和即将设置的订单。不同的对象有不同的参数设置。
表 2 中列出了所有的参数标识符以及它们适用的目标类型。
表 2 数据访问标识符。
索引 | 标识符 | 目标 | 交易对象类型 |
---|---|---|---|
0 | ProfitInPoints | 获利点数 | 仓位 |
1 | ProfitInValute | 存入现金的获利 | 仓位,交易 |
2 | OpenPrice | 开盘价 | 仓位,挂单(止损限价订单除外) |
3 | LastPrice | 价格 | 交易 |
4 | OpenPrice1 | StopLimit 到 Limit 的交易价格 | StopLimit 类型挂单。当订单转成 Limit,适用于 OpenPrice 标识符 |
5 | OpenPrice2 | StopLimit 至仓位交易价格 | StopLimit 类型挂单。当订单转成 Limit,适用于 OpenPrice 标识符 |
6 | StopLossValue | 止损值 | 仓位,挂单 |
7 | TakeProfitValue | 获利值 | 仓位,挂单 |
8 | StopLossInPoints | 止损点位 | 仓位,挂单 |
9 | TakeProfitInPoints | 获利点位 | 仓位,挂单 |
10 | StopLossExists | 存在止损 | 仓位,挂单 |
11 | TakeProfitExists | 存在获利 | 仓位,挂单 |
12 | Direction | 方向 1- 买入,-1- 卖出 | 仓位,挂单,交易 |
动作描述
动作包括市场仓位的建仓和平仓、设置、修改和删除挂单、执行管理函数:跟踪止损、盈亏平衡、挂单跟踪止损(任何其他仓位管理函数)。
建仓和设置订单的动作意味着要使用所需要的参数,执行这些动作。发出指令后,会在括号内确定这些参数,通常需要调用函数。标识符是所有指令的第一个参数。在确定参数时,您可以使用数字值、变量以及现有仓位或订单的参数。您还可以使用计算式表达,比如 X1*X2+X3*X4,在阶段辨识部分中对所有动作指令的参数进行改善。
表 3 列出所有动作指令。
表 3. 动作指令
索引 | 指令 | 目标 |
---|---|---|
0 | Buy(ID,Lot,StopLoss,TakeProfit) | 建一个买入仓位 |
1 | Sell(ID,Lot,StopLoss,TakeProfit) | 建一个卖出仓位 |
2 | Close(ID) | 平一个市场仓位 |
3 | BuyStop(ID,Lot,Price,StopLoss,TakeProfit) | 设置一个买入止损订单 |
4 | SellStop(ID,Lot,Price,StopLoss,TakeProfit) | 设置一个卖出止损订单 |
5 | BuyLimit(ID,Lot,Price,StopLoss,TakeProfit) | 设置一个买入限价订单 |
6 | SellLimit(ID,Lot,Price,StopLoss,TakeProfit) | 设置一个卖出限价订单 |
7 | BuyStopLimit(ID,Lot,Price1,Price2,StopLoss,TakeProfit) | 设置一个买入止损限价订单 |
8 | SellStopLimit(ID,Lot,Price1,Price2,StopLoss,TakeProfit) | 设置一个卖出止损限价订单 |
9 | Delete(ID) | 删除一个挂单 |
10 | DeleteAll(ID,BuyStop,SellStop,BuyLimit,SellLimit,BuyStopLimit,SellStopLimit) | 删除确定类型的挂单 |
11 | Modify(ID,Price1,Price2,StopLoss,TakeProfit) | 仓位或订单修改 |
12 | TrailingStop | 跟踪止损函数操作。在 EA 属性窗口中定义函数参数 |
13 | BreakEven | 盈亏平衡函数操作。在 EA 属性窗口中定义函数参数 |
表 4 列出了动作指令参数描述。
表 4. 动作指令参数
参数 | 目标 |
---|---|
ID | 交易目标(仓位、订单)标识符 |
Lot | 单位手数大小。可以在 EA 属性窗口中找到定义单位值的手数变量。 |
StopLoss | 止损值 |
TakeProfit | 获利值 |
价格 | 挂单值(StopLimit 类型订单除外) |
Price1 | StopLimit 至 Limit 交易价格 |
Price2 | StopLimit 至仓位交易价格 |
现在,让我们在新的元语言中讨论上述订单策略。
程序列在表格中,包括所有阶段标识和动作指令,读者可以更好地理解和写注释。文件后附有所有程序的文本文件,其格式可以用于 EA 交易。
使用限价订单加仓
将根据用户在属性窗口中确定的方向,建初始仓位。加仓可以最多进行 5 次(限价订单)。市场中只能同时存在 3 个订单。
表 5. 限价订单加仓元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing 用户买入 |
Buy(1,1,0,Ask+Var1p); BuyLimit(2,2,Buy(1,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(3,4,BuyLimit(2,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(4,8,BuyLimit(3,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) |
如果市场中没有仓位或订单,在 EA 属性中设置买入方向,我们用一个初始手数建仓。如果仓位成功建立,我们将试着设置 3 个限价订单。也就是说,由于订单价格是根据之前订单的价格来计算,因此,每一个订单若想成功设置,之前必须有一个已设置的订单。 |
2 | Buy(1) | BuyLimit(2,2,Buy(1,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(3,4,BuyLimit(2,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(4,8,BuyLimit(3,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) |
如果仓位在第 1 阶段成功建立,但是没有设置所有的挂单,接下来要做的就是设置所有的挂单。 |
3 | Buy(2) | BuyLimit(3,4,Buy(2,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(4,8,BuyLimit(3,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(5,16,BuyLimit(4,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) |
如果第一个限价订单(标识符 2)出现,试着设置另外两个在之前阶段应该设置(但未能设置)的订单,设置一个新订单,确保市场中始终共有3个限价订单。 |
4 | Buy(3) | BuyLimit(4,8,Buy(3,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(5,16,BuyLimit(4,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(6,32,BuyLimit(4,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) |
另外一个限价订单已经启动,我们必须确保市场中有三个限价订单,就像之前的阶段一样。 |
5 | Buy(4) | BuyLimit(5,16,Buy(4,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p); BuyLimit(6,32,BuyLimit(5,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) |
在这个阶段,只有在总订单接近订单最大数量时,才确保有两个挂单的存在。 |
6 | Buy(5) | BuyLimit(6,32,Buy(5,OpenPrice)-Var2p,0,ThisOpenPrice+Var3p) | 这个阶段只有最后一个订单。 |
7 | Buy(6) | 修改 (6,,,Buy(6,OpenPrice)-Var4p,) | 如果最后一个订单出现,需要为其设定一个止损位。 |
8 | Nothing; UserSell |
Sell(1,1,0,Var1p); SellLimit(2,2,Sell(1,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(3,4,SellLimit(2,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(4,8,SellLimit(3,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) |
与第 1 阶段相同,但是在卖出方向。 |
9 | Sell(1) | SellLimit(2,2,Sell(1,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(3,4,SellLimit(2,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(4,8,SellLimit(3,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) |
与第 2 阶段相同,但是在卖出方向。 |
10 | Sell(2) | SellLimit(3,4,Sell(2,OpenPrice)+Var2p,0,Var3); SellLimit(4,8,SellLimit(3,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(5,16,SellLimit(4,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) |
与第 3 阶段相同,但是在卖出方向。 |
11 | Sell(3) | SellLimit(4,8,Sell(3,OpenPrice)+Var2p,0,Var3); SellLimit(5,16,SellLimit(4,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p); SellLimit(6,32,SellLimit(4,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) |
与第 4 阶段相同,但是在卖出方向。 |
12 | Sell(4) | SellLimit(5,16,Sell(4,OpenPrice)+Var2p,0,Var3); SellLimit(6,32,SellLimit(5,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) |
与第 5 阶段相同,但是在卖出方向。 |
13 | Sell(5) | SellLimit(6,32,Sell(5,OpenPrice)+Var2p,0,ThisOpenPrice-Var3p) | 与第 6 阶段相同,但是在卖出方向。 |
14 | Sell(6) | 修改(6,,,Sell(6,OpenPrice)+Var4p,) | 与第 7 阶段相同,但是在卖出方向。 |
15 | NoPos; Pending |
DeleteAll(,0,0,1,1,0,0) | 有挂单,但没有仓位。如果仓位获利已启动,就会出现这种情况。在这种情况下,应该删除订单。删除订单后,系统切换至阶段 1 或 9。如果用户在系统操作过程中停止初始方向,就不会有动作。 |
变量的使用:Var1 - 初始订单获利,Var2 - 根据之前订单的开盘价,设置限价订单,Var3 - 上一个订单的止损。
图5:列出这个元程序的性能。
图. 5. 用限价订单加仓的元程序性能
请注意:买和卖方向的规则将分别介绍。每个挂单位都根据之前订单的位置进行计算。如果某个订单设置失败,就无法设置下一个订单,因为缺少所需要的参数。根据市场仓位的价位计算是错误的方法。在这种情况下,可能会缺少某些订单。
止损和反转
这项工作开始于两个止损挂单。可以有 5 次反转。
图 6:止损和反转元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing | BuyStop(1,1,Ask+Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p); SellStop(1,1,Bid-Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) |
市场中没有仓位或订单,我们试图用标识符 1 设置两个止损单。 |
2 | NoPos; BuyStop(1) |
SellStop(1,1,Bid-Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 没有仓位,但是有一个带有标识符 1 的买入止损,也就是说,应该有一个带有标识符 1 的卖出止损。 |
3 | NoPos; SellStop(1) |
BuyStop(1,1,Ask+Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 没有仓位,但是有一个带有标识符 1 的卖出止损,也就是说,应该有一个带有标识符 1 的买入止损。 |
4 | Buy(1) | Delete(1); SellStop(2,2,Buy(1,StopLossValue),ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) |
市场中有一个带有标识符 1 的买入仓位,在这种情况下,应该没有其他带有标识符 1 的订单,但是应该有带标识符 2 的卖出止损。 |
5 | Sell(1) | Delete(1); BuyStop(2,2,Sell(1,StopLossValue),ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) |
与阶段 4 相同,但第一个卖出止损已经启动。 |
6 | Buy(2) | SellStop(3,4,Buy(2,StopLossValue),ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 第二个买入止损已经出现,因此应该设置第三个卖出止损。 |
7 | Sell(2) | BuyStop(3,4,Sell(2,StopLossValue),ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 第二个卖出止损已经出现,因此应该设置第三个买入止损。 |
8 | Buy(3) | SellStop(4,8,Buy(3,StopLossValue),ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 第三个买入止损已经出现,因此应该设置第四个卖出止损。 |
9 | Sell(3) | BuyStop(4.8,Sell(3,StopLossValue),ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 第三个卖出止损已经出现,因此应该设置第四个买入止损。 |
10 | Buy(4) | SellStop(5.16,Buy(4,StopLossValue),ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 第四个买入止损已经出现,因此应该设置第五个卖出止损。 |
11 | Sell(4) | BuyStop(5.16,Sell(4,StopLossValue),ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 第四个卖出止损已经出现,因此应该设置第五个买入止损。 |
12 | Buy(5) | SellStop(6.32,Buy(5,StopLossValue),ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 第五个买入止损已经出现,因此应该设置第六个卖出止损。 |
13 | Sell(5) | BuyStop(6.32,Sell(5,StopLossValue),ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 第五个卖出止损已经出现,因此应该设置第六个买入止损。 |
14 | NoPos; BuyStop(2) |
Delete(2) | 没有仓位,但是我们仍然有买入止损。当仓位在获利位平仓时会出现这种情况。在这种情况下,删除剩下的订单,系统切换至阶段 1。 |
15 | NoPos; SellStop(2) |
Delete(2) | 与阶段 14 相同。 |
16 | NoPos; BuyStop(3) |
Delete(3) | 与阶段 14 相同。 |
17 | NoPos; SellStop(3) |
Delete(3) | 与阶段 14 相同。 |
18 | NoPos; BuyStop(4) |
Delete(4) | 与阶段 14 相同。 |
19 | NoPos; SellStop(4) |
Delete(4) | 与阶段 14 相同。 |
20 | NoPos; BuyStop(5) |
Delete(5) | 与阶段 14 相同。 |
21 | NoPos; SellStop(5) |
Delete(5) | 与阶段 14 相同。 |
22 | NoPos; BuyStop(6) |
Delete(6) | 与阶段 14 相同。 |
23 | NoPos; SellStop(6) | |
Delete(6) | 与阶段 14 相同。 |
变量的使用:Var1-从当前市场价设置初始订单的位置,Var2-止损,Var3-获利。
图 6:这个表中显示了这个元程序的性能。
图. 6. 止损和反转元程序的性能
金字塔
根据指标信号建初始仓。可以有 5 次加仓。
表 7 金字塔元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing; SignalOpenBuy |
Buy(1,1,Ask-Var1p,Ask+Var2p*6) | 市场中没有仓位或订单;我们从指标处获得买入建仓信号,进行建仓。首先在与 Var2p*6 等距离的位置设置获利位,下一步是在 Var2p*5 设置,不断继续,确保获利与价位相同。 |
2 | Buy(1); Buy(1,ProfitInPoints)>=Var3 |
Buy(2,1,Ask-Var1p,Ask+Var2p*5) | 有一个买入仓位显示出很好的获利,于是我们加仓。 |
3 | Buy(2) | Modify(2,,,Buy(2,OpenPrice),) | 市场中的仓位有索引 2,显示这个仓位不是初始仓位,肯定已经加仓;止损应该位于盈亏平衡点。 |
4 | Buy(2); Buy(2,ProfitInPoints)>=Var3 |
Buy(3,1,Ask-Var1p,Ask+Var2p*4) | 这个仓位再一次盈利,所以我们加仓。 |
5 | Buy(3) | Modify(3,,,Buy(3,OpenPrice),) | 每次当我们加仓,都将止损移动到盈亏平衡。 |
6 | Buy(3); Buy(3,ProfitInPoints)>=Var3 |
Buy(4,1,Ask-Var1p,Ask+Var2p*3) | 与阶段 4 相同。 |
7 | Buy(4) | Modify(4,,,Buy(4,OpenPrice),) | 与阶段 5 相同。 |
8 | Buy(4); Buy(4,ProfitInPoints)>=Var3 |
Buy(5,1,Ask-Var1p,Ask+Var2p*2) | 与阶段 4 相同。 |
9 | Buy(5) | Modify(5,,,Buy(5,OpenPrice),) | 与阶段 5 相同。 |
10 | Buy(5); Buy(5,ProfitInPoints)>=Var3 |
Buy(6,1,Ask-Var1p,Ask+Var2p) | 与阶段 4 相同。 |
11 | Buy(6) | Modify(6,,,Buy(6,OpenPrice),) | 与阶段 5 相同。 |
12 | Nothing; SignalOpenSell |
Sell(1,1,Bid+Var1p,Bid-Var2p*6) | 与阶段 1 相同,但是在一个卖出仓位。 |
13 | Sell(1); Sell(1,ProfitInPoints)>=Var3 |
Sell(2,1,Bid+Var1p,Bid-Var2p*5) | 与阶段 2 相同,但是在一个卖出仓位。 |
14 | Sell(2) | Modify(2,,,Sell(2,OpenPrice),) | 与阶段 3 相同,但是在一个卖出仓位。 |
15 | Sell(2); Sell(2,ProfitInPoints)>=Var3 |
Sell(3,1,Bid+Var1p,Bid-Var2p*4) | 与阶段 4 相同,但是在一个卖出仓位。 |
16 | Sell(3) | Modify(3,,,Sell(3,OpenPrice),) | 与阶段 5 相同,但是在一个卖出仓位。 |
17 | Sell(3); Sell(3,ProfitInPoints)>=Var3 |
Sell(4,1,Bid+Var1p,Bid-Var2p*3) | 与阶段 6 相同,但是在一个卖出仓位。 |
18 | Sell(4) | Modify(4,,,Sell(4,OpenPrice),) | 与阶段 7 相同,但是在一个卖出仓位。 |
19 | Sell(4); Sell(4,ProfitInPoints)>=Var3 |
Sell(5,1,Bid+Var1p,Bid-Var2p*2) | 与阶段 8 相同,但是在一个卖出仓位。 |
20 | Sell(5) | Modify(5,,,Sell(5,OpenPrice),) | 与阶段 9 相同,但是在一个卖出仓位。 |
21 | Sell(5); Sell(5,ProfitInPoints)>=Var3 |
Sell(6,1,Bid+Var1p,Bid-Var2p) | 与阶段 10 相同,但是在一个卖出仓位。 |
22 | Sell(6) | Modify(6,,,Sell(6,OpenPrice),) | 与阶段 11 相同,但是在一个卖出仓位。 |
变量的使用:Var1-初始止损,Var2-上一个订单获利,Var3-加仓赢利位,价格止损移至盈亏平衡。
图 7:这个图中显示了这个元程序的性能。
图. 7. 金字塔元程序的性能
再建仓
首先,我们设置两个限价订单。当其中一个启动,另一个就被删除。然后,当止损点出现,就会建一个新仓位,直到它在获利点平仓,或最大数量仓位 (5) 被用尽。
表 8 再建仓元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing; NoLastDeal |
BuyLimit(1,1,Ask-Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p); SellLimit(1,1,Bid+Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) |
市场中没有仓位或订单,账户历史显示该符号没有交易。要这意味着这是系统操作的起点。设置两个限价订单作为初始动作。 |
2 | Nothing; LastDeal(,ProfitInValute)>0 |
BuyLimit(1,1,Ask-Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p); SellLimit(1,1,Bid+Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) |
市场中没有仓位或订单,但是历史显示交易已获利平仓。建议之前阶段已完成,我们需要从头开始,在阶段 1 设置两个限价订单。 |
3 | Nothing; LastEADeal(5) |
BuyLimit(1,1,Ask-Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p); SellLimit(1,1,Bid+Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) |
市场中没有仓位或订单,但是历史中包含一个带有上一个标识符的交易。在这种情况下,上一个交易所获的利润并不重要,因为那个阶段被认为已经完成。我们从头开始,在阶段 1 设置两个限价订单。 |
4 | NoPos; BuyLimit(1) |
SellLimit(1,1,Bid+Var1p,ThisOpenPrice-Var2p,ThisOpenPrice+Var3p) | 市场中没有仓位,但是我们知道有一个限价订单,这就意味着还应该有第二个。 |
5 | NoPos; SellLimit(1) |
BuyLimit(1,1,Ask-Var1p,ThisOpenPrice+Var2p,ThisOpenPrice-Var3p) | 与阶段 4 相同。 |
6 | Buy(1); SellLimit(1) |
Delete(1) | 有一个带标识符 1 的仓位。这意味着两个限价订单中,有一个已经启动,第二个订单应该删除。 |
7 | Sell(1); BuyLimit(1) |
Delete(1) | 与阶段 6 相同。 |
8 | Nothing; LastDeal(1,ProfitInValute)<=0; LastEADeal(1,Direction)==1 |
Buy(2,2,Ask-Var2p,Ask+Var3p) | 没有仓位,上一交易未获利。检查 EA 交易执行的上一个交易方向。如果是一个买入交易,您需要建的下一个仓位就是一个买入仓位。 |
9 | Nothing; LastDeal(1,ProfitInValute)<=0; LastEADeal(1,Direction)==-1 |
Sell(2,2,Bid+Var2p,Bid-Var3p) | 没有仓位,上一交易未获利。检查 EA 执行的上一个交易方向。如果是一个卖出交易,您需要建的下一个仓位就是一个卖出仓位。 |
10 | Nothing; LastDeal(2,ProfitInValute)<=0; LastEADeal(2,Direction)==1 |
Buy(3,4,Ask-Var2p,Ask+Var3p) | 与阶段 8 相同。 |
11 | Nothing; LastDeal(2,ProfitInValute)<=0; LastEADeal(2,Direction)==-1 |
Sell(3.4,Bid+Var2p,Bid-Var3p) | 与阶段 9 相同。 |
12 | Nothing; LastDeal(3,ProfitInValute)<=0; LastEADeal(3,Direction)==1 |
Buy(4,8,Ask-Var2p,Ask+Var3p) | 与阶段 8 相同。 |
13 | Nothing; LastDeal(3,ProfitInValute)<=0; LastEADeal(3,Direction)==-1 |
Sell(4.8,Bid+Var2p,Bid-Var3p) | 与阶段 9 相同。 |
14 | Nothing; LastDeal(4,ProfitInValute)<=0; LastEADeal(4,Direction)==1 |
Buy(5,16,Ask-Var2p,Ask+Var3p) | 与阶段 8 相同。 |
15 | Nothing; LastDeal(4,ProfitInValute)<=0; LastEADeal(4,Direction)==-1 |
Sell(5.16,Bid+Var2p,Bid-Var3p) | 与阶段 9 相同。 |
变量的使用:Var1-从市场价设置限价订单的位置,Var2-止损,Var3-获利。
图 8:这个表中显示了这个元程序的性能。
图. 8. 重建仓元程序的性能
下面再向您介绍几个简单的程序,了解交易信号、跟踪止损和盈亏平衡函数的操作。
交易信号
进入和退出以交易信号为基础。
表 9 交易信号元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing; SignalOpenBuy; NoTradeOnBar |
Buy(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建买入仓的信号。当前的柱没有交易,我们建一个买入仓。 |
2 | Nothing; SignalOpenSell; NoTradeOnBar |
Sell(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建卖出仓的信号。当前的柱没有交易,我们建一个卖出仓。 |
3 | SignalCloseBuy; Buy(1) |
Close(1); | 有一个买入仓和平仓信号,买入仓平仓。 |
4 | SignalCloseSell; Sell(1) |
Close(1); | 有一个卖出仓和平仓信号,卖出仓平仓。 |
图9:这个表中显示了这个元程序的性能。
图. 9. 交易信号元程序的性能
带有跟踪止损的交易信号
表 10 带有跟踪止损的交易信号元程序
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing; SignalOpenBuy; NoTradeOnBar |
Buy(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建买入仓的信号。当前的柱没有交易,我们建一个买入仓。 |
2 | Nothing; SignalOpenSell; NoTradeOnBar |
Sell(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建卖出仓的信号。当前的柱没有交易,我们建一个卖出仓。 |
3 | SignalCloseBuy; Buy(1) |
Close(1); | 有一个买入仓和平仓信号,买入仓平仓。 |
4 | SignalCloseSell; Sell(1) |
Close(1); | 有一个卖出仓和平仓信号,卖出仓平仓。 |
5 | Buy(1) | TrailingStop | 市场中有一个买入仓,应该启动跟踪止损函数。 |
6 | Sell(1) | TrailingStop | 市场中有一个卖出仓,应该启动跟踪止损函数。 |
图10:这个图中显示了这个元程序的性能。
图. 10. 带有跟踪止损的交易信号元程序性能
带有盈亏平衡函数的交易信号
图 11. 带有盈亏平衡函数的交易信号
阶段编号 | 阶段标识 | 动作 | 注释 |
---|---|---|---|
1 | Nothing; SignalOpenBuy; NoTradeOnBar |
Buy(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建买入仓的信号。由于当前柱没有交易,建买入仓。 |
2 | Nothing; SignalOpenSell; NoTradeOnBar |
Sell(1,1,0,0) | 市场中没有仓位或订单,但是我们可以看到建卖出仓的信号。由于当前柱没有交易,建卖出仓。 |
3 | SignalCloseBuy; Buy(1) |
Close(1); | 有一个买入仓和平仓信号,买入仓平仓。 |
4 | SignalCloseSell; Sell(1) |
Close(1); | 有一个卖出仓和平仓信号,卖出仓平仓。 |
5 | Buy(1) | BreakEven | 市场中有一个买入仓,应该启动盈亏平衡函数。 |
6 | Sell(1) | BreakEven | 市场中有一个卖出仓,应该启动盈亏平衡函数。 |
图11:这个图中显示了这个元程序的性能。
图. 11. 带盈亏平衡函数的交易信号元程序性能
上述构建订单策略的方法,让我们能够更好地了解这些策略,为在 EA 交易中进一步实施这些策略制定计算法,直接解释和遵循这些复杂的规则。eInterpretator Expert Advisor 就是以此为目的创建(见所附文件)。EA 交易的参数和描述见表 12。
表 12. eInterpretator Expert Advisor 参数
参数 | 目标 |
---|---|
手数 | 当手数等于 1 时的订单数量。 |
UserTradeDir | 用户确定的交易方向(当执行 UserBuy 和 UserSell 指令时,在阶段标识中进行检查)。 |
ProgramFileName | 元程序文件名(在账户中运行)。在测试或优化时,元程序应该放在 TesterMetaProgram.txt 文件中 |
DeInterpritate | 指令解释反转。在完成的时候,文件夹中将出现带有前缀 "De_" 的文件。您可以看到 EA 如何”理解“ProgramFileName 文件的元程序。 |
用户变量 | |
Var1 - Var20 | 用户变量。 |
跟踪止损 | |
TR_ON | 跟踪止损函数启动。 |
TR_Start | 跟踪止损开始工作时的仓位盈利点数。 |
TR_Level | 跟踪止损位。从现有市场价到跟踪止损之间的点数距离。 |
TR_Step | 跟踪止损修改的介入点位。 |
盈亏平衡 | |
BE_ON | 启动盈亏平衡函数。 |
BE_Start | 启动盈亏平衡的获利仓位点数。 |
BE_Level | 启动盈亏平衡时移动的止损点位。BE_Start-BE_Level 盈利点位为固定的。 |
建仓信号 | |
OS_ON | 启动建仓信号。 |
OS_Shift | 进行指标检查的柱:0 - 新,1 - 完成。 |
OS_TimeFrame | 指标时间框架。 |
OS_MA2FastPeriod | 快速 MA 周期。 |
OS_MA2FastShift | 快速 MA 位移。 |
OS_MA2FastMethod | 快速 MA 方法。 |
OS_MA2FastPrice | 快速 MA 价格。 |
OS_MA2SlowPeriod | 缓慢 MA 周期。 |
OS_MA2SlowShift | 缓慢 MA 位移。 |
OS_MA2SlowMethod | 缓慢 MA 方法。 |
OS_MA2SlowPrice | 缓慢 MA 价格。 |
平仓信号 | |
CS_ON | 启动平仓信号。 |
CS_Shift | 进行指标检查的柱:0 - 新,1 - 完成。 |
CS_TimeFrame | 指标时间框架。 |
CS_CCIPeriod | CCI 周期。 |
CS_CCIPrice | CCI 价格。 |
CS_CCILevel | CCI 上位(买入仓位平仓)。位置向下叉时,会出现买入仓位平仓信号。卖出平仓则正好与之相反。 |
EA 交易如何运行
首先,EA 会从文件中载入元程序,对其进行检查和分析。如果在元程序中有重大错误,会跳出错误警告。在分析元程序时,EA 会用与文本指令相对应的数字值,填充数据结构,确保 EA 性能的最大化。在成功分析元程序时,以下信息会在日志中出现:“解释初始化完成”。
如果 EA 交易中包括 DeInterpritate 变量,EA 就会运行一个指令的测试反转解释(通过这种方式,如果出现异常停止,就会切断它与图表和 Strategy Tester 中任何测试的联系)。在反转解释的时候,EA 交易会将结构中找到的数字值变成文本指令。尽管文件中的指令进入不同,反转解释元程序会让您更好地了解 EA 如何分析指令。
让我们来看看如何使用元程序文件中以下的字符串:
Buy(6) | Modify(6,,,ThisOpenPrice-Var4p,)
在反转解释之后,字符串如下所示:
Buy(6)==1*1+0*0; | Modify(6,,,ThisOpenPrice()*1-0.0025*1,)
如您所见,一个简单的 Buy(6) 被转变成一个对照描述,右侧包括一个计算式描述 X1*X2+X3*X4,让 1 成为计算结果。在动作域,用数字值代替了用户变量。
在分析阶段和指令执行过程中,有的人可能想要加入自己的指令,并将其他仓位管理函数纳入其中,以此对这个 EA 进行个性化。EA 的结构决定了这种个性化可以非常直接,否则,在 EA 中进行的全部工作就不可能有实际的值。
添加数据指令
在 InforCommand 数组中,可以找到一个获取数据的指令列表。指令按栏排列,每行有 5 个指令,让我们可以轻松计算他们的数量,找到需要添加的指令索引值。
在 InfoCommand 数组中添加指令后,我们在 SetValue() 函数中的切换结构中,添加一个与新指令索引相一致的新事件。为了获得这个值,我们需要首先选择可以从中获得值的对象,只有这样才能获得值。根据获得数据的对象类型,使用不同的函数选择对象。表 13 中列出了这些函数。
表 13. 选择交易对象的 EA 函数
函数 | 目标和参数 |
---|---|
Pos.Select(_Symbol) | 选择仓位。与 PositionSelect() 函数相似的标准级别方法。 |
SelectOrder(long aType,string aID,bool & aSelected) | 根据 EA 符号、类型 (aType) 和标识符值 (aID),选择一个订单的函数。如果已找到并选择了对象,aSelected 参考变量返回 true。 |
bool SelectLastDeal(int aType,bool & aSelected) | 根据 EA 符号和类型 (aType),选择上一个交易的函数。如果已找到并选择了对象,aSelected 参考变量返回 true。 |
SelectLastEADeal(int aType,string aID,bool & aSelected) | 根据 EA 信号和类型 (aType),选择 EA 执行的上一个交易的函数。如果已找到并选择了对象,aSelected 参考变量返回 true。 |
”上一个交易“和”EA 执行的上一个交易“之间的差别就是:”上一个交易“中包括止损和获利交易。在决定上一个仓位平仓结果时,可能需要”上一个交易“数据。但在判断上一个交易方向或 EA 操作阶段时,可能就需要”EA 执行的上一个交易“信息。
除了交易对象数据,还可以访问市场数据,比如价格等。重要的是,要确保数据可以获得。在选择对象操作之后,我们还要确保对象已经被选择(检查 aSelected),获得所需要的参数,将其值分配给 Val.Value 变量并返回 true。
表 14 列出了用于获得不同交易目标参数的函数。
表 14. 获得所选交易目标参数的 EA 函数
函数 | 目标和参数 |
---|---|
double SelPosParam(int aIndex) | 设置 aIndex 索引获得仓位函数。 |
double SelOrdParam(int aIndex) | 设置 aIndex 索引获得订单函数。 |
double SelDealParam(int aIndex) | 设置 aIndex 索引获得交易函数。 |
在这个函数中传递一个将要获得数据的标识符索引。索引值包括在 Val.InfoIdentifierIndex 变量中。
在添加一个新访问命令时,可能要求您还要添加将要获得的数据标识符,或只添加将要获得的数据标识符。
添加数据标识符
在 InfoIdentifier 数组中包括一个标识符列表。我们需要在数组中添加新标识符,找到它的索引,升级 SelPosParam()、SelOrdParam() 和 SelDealParam() 函数。根据新标识符是否能适用于所有交易对象,升级可能涉及的全部或部分函数。将与新标识符索引对应的新事件,添加在切换结构中,在这个过程中进行函数升级。
添加动作指令
在 ActCommand 数组中添加动作指令。在数组中的指令被安排在一个字符串中,令其更难以找到必要的索引。元素代表一个字符串,因为除了添加一个指令,我们还需要指明其参数和类型的数量。 在 ActCmndPrmCnt 数组中指明参数的数量,在 ActCmndType 数组中可以提供其类型。可能的类型包括:0 - 市场动作,1 - 挂单动作,2 - 仓位管理。
在数组中添加指令后,我们找到 DoAction() 函数,在其转换中添加新函数调用的另一个事件。新函数必须是 bool 类型,如果成功实施则返回 true,如果错误则返回 false。如果不需要检查函数性能,就像在跟踪止损函数中一样,它就会返回 true。
请记住,处理挂单的函数,比如同样设置的函数,需要对订单存在进行初步检查。
修改交易信号函数
在 EA 中获取交易信号的全部工作,都在两个函数中完成(两个平仓信号函数,两个开仓信号函数)。
从EA的 OnInit()函数中调用 CloseSignalsInit() 函数(平仓信号初始化)和 OpenSignalsInit()函数(建仓信号初始化)。这些函数负责加载指标。在每一个即时价格的 OnTick() 函数处调用主要函数 - CloseSignalsMain()(辨识平仓的交易信号)和 OpenSignalsMain()(辨识建仓的交易信号)。
在函数实施之初,应该给 GlobalCloseBuySignal、GlobalCloseSellSignal (signals for closing) 和 GlobalOpenBuySignal、GlobalOpenSellSignal (signals for opening) 分配 false,给相应的指标度数分配 true。
此外,在 EA 的 OnDeinit() 函数中,您需要执行 IndicatorRelease()。
eInterpretator.mq5 - 应该放置在终端数据目录 MQL5/Experts 中的 EA 交易。
LimitAdd.txt - 限价订单加仓元程序。
StopRev.txt - 止损和反转元程序。
Piramiding.txt - 金字塔元程序。
ReOpen.txt.txt - 重建仓元程序。
TradeSignals.txt - 交易信号元程序。
TradeSignalsTR.txt - 带有跟踪止损的交易信号元程序。
TradeSignalsBE.txt - 带有盈亏平衡函数的交易信号元程序。
limitadd.set - 限价订单加仓元程序参数文件。
stoprev.set - 止损和反转参数文件。
piramiding.set - 金字塔参数文件。
piramiding.set - 重建仓参数文件。
tradesignals.set - 交易信号参数文件。
tradesignalstr.set - 带有跟踪止损的交易信号参数文件。
tradesignalsbe.set - 带有盈亏平衡函数的交易信号参数文件。
注:在使用交易信号、跟踪止损和盈亏平衡程序时,EA 属性窗中相应的函数要始终处于启动状态。在 Strategy Tester 中测试策略时,将元文件复制到 TesterMetaProgram.txt 文件中(这样就可以使用远程测试 agents)。将文件放置在终端数据目录 MQL5/Files 中(您可以从以下终端打开:File -> Open Data Folder)。
在 Metalanguage 部分的 Examples of Order Strategies 中,可以找到显示程序性能的图表。所显示的性能根据参数文件中具体的参数而定。已经在过去的几个月中进行了测试(截止日期 2012.08.29),检测内容为 EURUSD H1 和 M1 的 OHLC 模式。.
当您开始设置订单策略的时候,第一个感觉经常是感到困惑 - 应该从何处着手?应该记住哪些规则?如何确定 EA 交易在实际环境中的稳定性?如何在实施交易策略计算式的同时,确保其运行的可靠性?
本文试图帮助那些将其策略进行初始形式化、为开发 EA 交易下订单的开发者和交易人(尽管非常片面),帮助他们理解策略开发的各个步骤,每个步骤所涉及的内容,以及应该考虑哪些方面。eInterpretator Expert Advisor 提供了无数可能性,供用户以最少的时间和经历对其订单策略进行试验。
此外,我在此难以掩饰对 MetaTrader 5 终端的喜爱之情。在 Strategy Tester 中的 eInterpretator Expert Advisor 操作速度完全超乎我的想象。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程