如果一个交易策略打算运行一定数量的定单 (例如,一个买入定单和一个卖出定单),这样智能交易在实行这些策略时可能不会考虑这些定单的差别。智能交易只是在自己构想的基础上决定交易,即,在终端内不能存在不同方向的定单。
这种方法基本上被接受,但是它仅适用于一小部分程序并不能做到普及。如果相同货币对存在两个或多个不同形式的定单,那么,智能交易应该怎样做呢? 可以说是违背,交易策略没有预见过这种情况并且不会发生。我们需要解决这个缺陷并且限定这个构想。
作为拥有丰富经验的交易者使用几个定单交易 (包括挂单交易),交易者将需要考虑所有定单的可用性。因为挂单交易可以转至开仓。此外,众所周知,交易者可以忘记在终端内正在运行的智能交易,随时可以手动开仓。几个交易者在一个账户上执行交易同样存在。这种情况下,交易策略本身会运行较大数量的定单。
我们尝试考虑在巨大程序中很好地考虑定单。
我们来简短描述一下程序运行的环境特点。
1.首先,我们确定要知道程序中定单的数量和类型(考虑数据会由程序收集)。 不能简简单单地说,我们的程序中有3个卖单和4个买单。任何智慧的交易系统都包含一个检测定单的计算 -止损水平和赢利水平,挂单交易开盘价。另外 我们需要知道每个定单的价值,它的期限,什么样的程序可以放置。
2.替克数。如果及时查看任何信息,都会带来一定意义。任何智能交易都会终端内处理开价。很明显,定单的状态会因为价格的改变而改变。这就意味着每个替克必须"重新考虑"。
3. 智能交易在窗口中获取的货币对可以把它列为 "一般特性".
在这些简单的数据基础上,我们能够测定出创建考虑定单智能交易的基本原理。
首先, 考虑定单的智能交易,其交易系统必须能够解决相应的问题。例如,分析可用性、定单的质量、关注这些数据、 决定交易。 如果状况是已知的情况,那么当前状况的任何分析都可能出现。这就说明程序代码已经开始考虑定单,并且在其他代码之前执行定单的代码。我们最好把形成考虑代码作为一个单独的函数。我们把它称作 Terminal(),因为它的主要任务是在终端内关注定单。
第二,由Terminal()函数所累积的数据必须使用于其他函数。这就是为什么显示有用信息变量的定单必须被纳入到整体水平 (不与GlobalVariables混淆)的原因。
第三,既然我们处理信息设定,必须在定单数组的基础上合乎逻辑地组织考虑。
根据上述的讲解,我们创建一个常规可以考虑定单的程序结构:
// My_expert.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж #include ... #include <Peremen.mq4> // Description of the expert's variables. #include <Terminal.mq4> // Attach the Terminal function. #include <Sobytiya.mq4> // Attach the Sobytiya function. #include ... //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { ... // 函数代码init() return; } //================================================================= int start() { Terminal(); // 该函数在函数的顺序上 // 要排在第一位 ... // 其次是start()函数代码 Sobytiya(); // 事件处理函数 ... // 其次start()函数代码 return; } //================================================================= int deinit() { ... // deinit()函数代码 return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
Peremen.mq4 文件描述变量必须包含数组的描述给出定单的数据。
// Peremen.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж //================================================================== int ... //================================================================== double ... Mas_Ord_Tek[31][8], Mas_Ord_Old[31][8], // 定单的当前数组和旧数组 // 第一个指数 = 在该数组中的定单数字 // [][0] 未指定 // [][1] 开单汇率 (汇率的绝对值) // [][2] 止损定单 (汇率的绝对值) // [][3] 赢利定单(汇率的绝对值) // [][4] 定单数字 // [][5] 定单中的标准手数(汇率的绝对值) // [][6] 定单类型1=B,2=S,3=BL,4=SL,5=BS,6=SS // [][7] 定单的Magic Number ... //================================================================= string ... //================================================================= //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
当在较小程序中指定整体变量时,通常在第一个函数进入之前编写。在中等和较大的程序中,会在一个文件内收集全部整体变量并且把这个文件附加到智能交易使用的#include上。
在代码的效率上,在方法和不重要之间出现不同。但是在可用性上,附加的文件上时可取的。这也是一种附加
Peremen.mq4
文件到以上智能交易示例的一种方法。
在 Peremen.mq4文件中,两个数组被指定作为整体变量:
Mas_Ord_Tek[31][8] - 定单当前数组。
Mas_Ord_Old[31][8] -定单的旧数组。
为什么我们需要使用不是一个数组,而两个呢? 为的是能够检测事件。至于是什么事件,我们将会晚些讨论。现在,让我们来谈谈以比较初始状态和当前状态比较为基础的指定事件本身。如果不存在任何状态数据,就不可能指定事件。这种情况下,定单的数组被用作通知交易空间状态前后的替克。
为什么使用2D 数组? 因为我们考虑到几个定单同时运行并且保持其中每个定单的几个特性。在数组中第一个指数为定单数字,第二个指数为定单标准特性。在上面的示例中,在终端内第一个指数不允许超过30个定单变量。您可以根据自己的需要改变这个总数。例如,在终端内同时运行 50或100定单。当然,如果你的智能交易系统允许运行这些定单的总数,可以执行改变。在标准状况下,使用 1到 2个定单,较大的范围,我认为4. 30已经很多了。
为什么在括号中给出的数组是 31 和 8,而不是 30 和 7呢?这是因为在 MQL4中数组计数是从零开始 。使用零开始计数在整体元素中有它的道理。我认为,使用定单数字(号码)作为相应的数组元素号码是符合逻辑的。例如,第三个定单必须在指数3的线内。事实上,这个线将是第四个,但是它的指数为3 。因为第一个线指数为0 。
现在我们来看看以下表格中插入的数组。建议仅存3个定单: Buy, Sell和不同质量的 BuyStop:
定单的信息被放置在数组中的号码是从[1][1]到 to [7][30]。另外,我们将在数组定单总数量中放置的元素指数为[0][0]。这种情况下为 3。在以后的计算中,这个号码将被使用于当前分析状态的循环组织 。
因此, 我们能够存储接近30个定单的信息,每个定单的特性为 7个。
如果你的交易策略建议同时交易几种货币对,你可以开设一个数组号码并且按照当前货币对放置定单。这种方法能够达到目的,但是并不方便。如果用这种方法考虑定单的组织,你需要开设其他数组用来存储包含定单信息的数组名称。
一个较为方便的解决方法可以使用较大的数组考虑全部定单。这种选择更好些,在将来代码的处理中,将不再需要搜索货币对定单数组的名称。在一个接一个的模式数字循环中将正好被使用。
包含全部被组织定单的数组如下:
每种货币对的定单信息存储在相同的指数水平内,如上示例。不同组成的在于,在这种情况下,一些水平的号码(在途中,其中的3个:黄色,粉色和绿色)。他们的总数等于我们当前运行的总数(加上一个)。在这个水平中 (灰色),只有一个值,定单的总数被存储在指数做为 [0][0][0]中。
数组范围, 25第一个指数货币对将为26。这种情况下,
Peremen.mq4
文件描述数组将如下:
// Peremen.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж //=========================================================================== int ... //=========================================================================== double ... Mas_Ord_Tek[26][31][8], Mas_Ord_Old[26][31][8], //定单的当前数组和新数组 // 第一个指数 = 货币对号码 // 第二个指数= 定单号码 ... // ... 货币对水平 // [][][0] 未指定 // [][][1] 开单汇率 (汇率的绝对值) // [][][2] 止损定单 (汇率的绝对值) // [][][3] 赢利定单 (汇率的绝对值) // [][][4] 定单号码 // [][][5] 定单的标准手数 (汇率的绝对值) // [][][6] 定单类型 1=B,2=S,3=BL,4=SL,5=BS,6=SS // [][][7] 定单的MagicNumber //================================================================= string Instrument[26]; // 货币对名称数组 ... //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Predopred() { //================================================= 预定义 = Instrument[1] = "EURUSD"; Instrument[2] = "GBPUSD"; ... Instrument[25]= "AUDCAD"; //================================================================== return(); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
在这个文件底部中打开变量,数组instrument[26]被打开。
一个较大的程序通常存在许多变量,在程序执行期间这些值不能改变。在我们的情况中,Instrument[] 数组为这些元素。对于程序更加方便,能够在一个很函数中更好地收集一些变量。这个变量同样可以是作为单独文件模式被附加到程序使用的 #include。
在下面的示例中,我们在包含相同 Peremen.mq4 文件Predopred() 函数中看看Instrument[]数组元素的预定义。 这个函数只够开启一次,所以在程序中包含特殊函数名称为 init():
int init() { Predopred(); // 一些变量的预定义 return; }
在我们的情况中包含一些整数,因此,Instrument[]数组指数的值作为相应货币对的号码。.
现在让我们来看看对于一种货币对考虑定单的函数 Terminal() 。这个函数同样是一个单独文件被命名为 Terminal.mq4,并且附加到智能交易上使用 #include 。
// Terminal.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Terminal() { //================================================ 预定义 == ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);// 保存先前历史 int Kol=0; // 定单计数归零 //=============================================== 定单分析 == for (int i=0; i<OrdersTotal(); i++) // 终端内的全部定单 { if((OrderSelect(i, SELECT_BY_POS)==true) && (OrderSymbol()==Symbol())) //如果存在下一个和我们的货币对 { Kol++; // 计算定单的总数 //--------------------------- 模式化定单的新数组 -- Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(), Digits); // 开单汇率 Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(), Digits); // 止损汇率 Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(), Digits); //赢利汇率 Mas_Ord_Tek[Kol][4] = OrderTicket(); // 定单号码 Mas_Ord_Tek[Kol][5] = OrderLots(); // 标准手数计算 Mas_Ord_Tek[Kol][6] = OrderType(); // 定单类型 Mas_Ord_Tek[Kol][7] = OrderMagicNumber(); // Magic number //----------------------------------------------------------------- } } Mas_Ord_Tek[0][0] = Kol; // 保存零 //================================================================= return(); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
首先要做的是在系统通过Terminal()函数的检测后被保存到定单的先前状态。在 Mas_Ord_Tek[][] 数组中,但是在当前时刻不是真实的,因为反映的是在先前替克上模式化定单的状态。在初始时刻当前状态未知。
在字行中
ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek); // 保存先前历史
定单的最近已知状态被 Mas_Ord_Old[][]数组通过。
使用到地方变量的函数命名为 Kol 并且反映当前定单的总数。 必须要使用这个变量 生成,因为 MQL4 不允许使用指定指数。在代码中可以看出,它作为指数值使用。 我们归零这个变量,以及作为整个当前变量的数组并且注意实际状况。
这样做,我们组织一个终端的循环,即连续调用全部可用定单并且找出它们的特性。
for (int i=0; i<OrdersTotal(); i++) // 终端中的全部定单
请注意:
OrdersTotal()
确定定单总数,并且在终端内开始为0时数定单的号码。这就是为什么 "
<" 被使用到循环线并且以零循环开始的整体变量改变的原因:
i
=
0
.
在以下的代码中,附加到智能交易上的货币对定单被着重强调。使用函数确定不同定单的特性,获取的信息放置到相应的 the Mas_Ord_Tek[][] 数组中。
//---------------------------模式化定单的新数组 -- Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(), Digits); // 开单汇率 Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss() , Digits); // SL 汇率 Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(), Digits); // ТР 汇率 Mas_Ord_Tek[Kol][4] = OrderTicket(); // 定单号码 Mas_Ord_Tek[Kol][5] = OrderLots(); // 标准手数 // 计算 Mas_Ord_Tek[Kol][6] = OrderType(); // 定单类型 Mas_Ord_Tek[Kol][7] = OrderMagicNumber(); // Magic number //------------------------------------------------------------------
在通过中计数被提填充 ,将通过它的值数组零元素循环到底部归零。
Mas_Ord_Tek[0][0] = Kol; // 保存零
对于同时运行的几种货币对,Tеrminal() 函数的构造如下:
// Terminal.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Terminal() { //================================================== 预定义 = ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek); // 保存先前历史 ArrayInitialize(Mas_Ord_Tek,0); // 当前定单数组归零 //==================================================定单分析= for (int i=0; i<OrdersTotal(); i++) //终端的全部定单 { if(OrderSelect(i, SELECT_BY_POS)==true) // 如果存在“即时”交易 { //--------------------------------------- 指定货币对指数- string Symb=OrderSymbol(); // 查明当前定单货币对 for (int ind=1; ind<=25; ind++) // 在货币对数组中搜索 { if (Symb==Instrument[ind]) // 找到指数,搜索完成 break; // 退出循环 } //------------------------模式化定单的新数组 ---- Mas_Ord_Tek[0][0][0]++; // 计算定单总数 Mas_Ord_Tek[ind][0][0]++; // 计算一种货币对的定单总数 int k=Mas_Ord_Tek[ind][0][0]; // 模式化变量 Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(), Digits); // 开单汇率 Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(), Digits); // SL 汇率 Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(), Digits); // ТР 汇率 Mas_Ord_Tek[ind][k][4] = OrderTicket(); // 定单号码 Mas_Ord_Tek[ind][k][5] = OrderLots(); // 标准手数计算 Mas_Ord_Tek[ind][k][6] = OrderType(); //定单类型 Mas_Ord_Tek[ind][k][7] = OrderMagicNumber(); // Magic // number //----------------------------------------------------------------- } } //================================================================= return(); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
对于多种货币对的考虑定单计算不同于一种货币对,它通过一个很小的区域查明货币对的指数。
//----------------------------------- 指定货币对指数---- string Symb=OrderSymbol(); // 查明当前定单的货币对 for (int ind=1; ind<=25; ind++) //在货币对数组中搜索 { if (Symb==Instrument[ind]) // 指数找到,完成搜索 break; // 退出循环 }
在Terminal()函数的连续线中,
找到货币对指数值
ind查明数组的水平指数,其包含数据定单相关货币对的定单。
在上面Terminal()函数的真实示例中,一些变量的计算使用了正常化:
Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(), Digits); // 开单汇率 Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(), Digits); // SL 汇率 Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(), Digits); // ТР 汇率
使用这些计算查明是为了将来在交易业务中使用正常化变量值。另外,有效数字的总数需要在预定义变量数字基础上查明。
一个交易系统可以考虑其他特性和定单的特性。但是在上面的示例中所给出的只是在较大程序中考虑定单的基本原理。例如,在这里我们不讨论平单和删除定单,也不考虑一些其他定单的特性。例如,挂单交易的时间期限。如果您需要处理以上特性,您可以轻松地确认数组在定单的附加数据中存储。比如,您可以增加最近指数元素总数,将其储存为挂单交易的时间期限值。
在这里由Tеrminal()函数引发了一个新的替克 。检测被交易业务通过,在函数 Terminal()之后立即被地方化。 不能提前预测特殊函数start()在那个部分或其他事件的处理自定义函数必须被放置 - 它取决于交易系统的想法。在一些简单的情况中,一些事件可以立刻解决。
在给出如何处理事件的范例之前,我想要提醒交易者在有些特殊的情况下这种解决方法并不能处理事件。
第一,一些证券交易人 (银行,例如,他们的特殊账户)。他们的账户在一天结束后会关闭所有定单,第二天早晨会开单。银行会根据汇率点数区分当前定单。 这些点数的掉期汇进入到定单经济中。掉期本身会作为零显示在终端内。这种情况下,类似银行的证券交易人不能遵循这个规则。对于我们而言,在这种情况下重要的是新开单并获取定单号码,其定单与先前的完全不同。
第二,平单分为两个单独的完成。第一步,完全关闭定单。第二步,打开价格略低的新定单并使用新单号码。另外, 最初定单号码被写入到新定单的注解中。
第三,当使用其他定单平单时,如果两个定单的价格不同,会出现 类似的错误。这种情况下,定单会重复部分平单。
一个较弱的特殊识别符开单时进行服务。但是这个标准不能考虑稳定性和普遍性。因为在理论上有可能几个定单同时打开 (同一秒钟)。例如,如果价格迅速地变化,不同货币对的两个挂单交易会同时打开。
让我们从包含Sobytiya.mq4文件的
Sobytiya()
函数中学习真实范例。我们将观看一个简单的事件 - 一个定单的删除或关闭。 We have already
我们知道定单号码有时会不合适,所以我们来分析
MagicNumber。
.
// Sobytiya.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Sobytiya() { //==================================== 搜索亏损定单 ==== for (int oo=1;oo<=Mas_Ord_Old[0][0];oo++) // 从旧数组中拿走定单号码 { int Sovpadenie=0; // 使符合状态归零 for (int i=1;i<=Mas_Ord_Tek[0][0];i++) // 在当前的数组中尝试找出这个定单 { if (Mas_Ord_Tek[i][7]==Mas_Ord_Old[oo][7]) // 如果定单MagicNumber 适合, 记住 // 退出循环模式 { Sovpadenie=1; break; } } if (Sovpadenie==1) continue; // 去下一个旧数组 Alert("平单 ",Mas_Ord_Old[oo][4]); // 在屏幕上显示信息文本 PlaySound( "Close_order.wav" ); // 音乐 } //================================================================= return(); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
正如你所看到的,如果你能够准确地描述注视的事件,你可以轻松地处理它。 可以充分地连续比较定单之前和之后的替克 - 明显看到他们之间存在差别。这样我们可以确定事件发生了。
在下一个示例中,我们考虑了其他事件的搜索 - 定单类型修改。这里我们使用的是相同原理,但是需要提供其他的标准。使用的定单号码和类型分析。
// Sobytiya_2.mq4 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Sobytiya_2() { //============ 搜索定单改变其类型 ==== for(int oo=1;oo<=Mas_Ord_Old[0][0]; oo++) // 穿过旧数组 { for (int i=1;i<=Mas_Ord_Tek[0][0];i++) // 在当前的数组中搜索定单 { if (Mas_Ord_Tek[i][4] == Mas_Ord_Old[oo][4] && // 如果旧数组中包含相同定单,但是不同类型, // 那么: 实行挂单交易 Mas_Ord_Tek[i][6] != Mas_Ord_Old[oo][6]) { Alert("定单转换",Mas_Ord_Tek[i][4]); // 在屏幕上显示信息文本 PlaySound("Transform.wav" ); // 音乐 } } } //================================================================= return(); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
在智能交易中程序的创建是依赖创建者的构想完成的,所以事件可能在程序的不同位置。如果需要,可以将模式化的所有事件放置在一个文件中。另外,在定单中的这些代码需要修改几次,为得是在数组搜索的运行中无须根据每个标准经常停顿。 对于将来的分析同样很容易的出现一种计算方法,从关闭定单的部分注解中提取初步号码进行计算。做到这些需要使用OrderComment() 函数。
除了上述的一些特性外,智能交易定单的考虑还存在一些其他方法。让我们仔细地看看,使其帮助我们拓宽真实智能交易的认知并且避免一些不必要的错误出现。那么我们回到交易者交易日结束的平单。
Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(), Digits+1); // 开单汇率
另外,在这种状况下需要注意开单的汇率可能会改变定单的状态。如果交易者使用一个交易系统决定关注开单汇率,那么这个交易系统只能坚持一天之久。纵观整个交易,我们可以得出结论开单的汇率根本没有连续性!一个重要的因素是状态的发展趋势。如果与我们的状态相反,选择平仓。
在这篇文章里我们谈及到了影响交易决定的标准。但是对于任何交易策略,在程序中我们仍然有必要选择使用标准 。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程