我的第一个 "圣杯"
"... 艺术永远不能进行编程,
两首特殊情感的诗永远不能孕育下一代。
人才不能通过种植获得。
他们是民族的财富-像是镭的储备,
像是九月的斯伽尔达和贝塞斯达 ..."(Andrey Voznesenskiy)
圣杯通常理解为耶稣在最后一次用餐时所用的杯子或盘子,后来阿里马西用此盛装耶稣从十字架上留下的血。更多详细信息请点击查看 。
现在"圣杯"一词经常性地以讽刺意味使用于现代程序。其意告诉我们不能够创建一个“通用”的程序以应万变。在MQL4程序语言中 ,这个词告知我们在真正的交易中不可能创建出具有傲人结果的智能交易。
事实上,外汇是一个经济和工业关系、人类属性,政治事件的混合体反射。更重要的是外汇不能够简简单单地形式化。只有在三到五个甚至更多的趋势信号指示时,老练的交易者才会见以进入市场。
然而,到目前为止不存在任何规律可以完全确定市场趋势和成功概率的预测。很多知名银行和金融机构的首席分析师对这个观点普遍认同。所有的分析师无一例外地给出了解释。其中的少数人也表示对预测报有信心。
我们对这些人投向了关注目光:他们中间的大多数人是使我们羡慕的,具有长期丰富的交易经验和学识。但事实上错误往往在他们身上出现。他们的东西看起来规模大并受到一致好评,有时还会带来财富 (在Alexander Elder的书中 Trading for a Living: Psychology, Trading Tactics, Money Management对不同类型的“大师”进行了完整的描述。)。事实表明这些有经验的分析师经常性地出现错误。
那么,针对现有的情况,对于一个新手如何能够抓住机会并在外汇市场成功迈出第一步呢?我们回到文章的主题,探索"Grail"。
1. "圣杯" 的组成部分
在形式逻辑中,权威的见解并不能作为依据。"圣杯"初学者曾经有这样的谈话: "你能够证明 "圣杯"的创建是不可能的吗?如果不能证明,它就是可能!"。初学者并不能考虑到账户是否能够创建,而且不会加以证明。“挖金者”往往是没有任何考虑因素并请没有任何研究经验,但自认为能够做到。这样的盲目自信完全是因为激情和缺乏经验所致。
1.1.形式策略
大多数情况下,新手大多不会为自己设定创建一个有效盈利交易策略的时间和任务。怀揣着在外汇市场快速盈利的梦想,认为实现盈利至少需要一个赢利的智能交易。
为了找到一个好标准,我们的主人公打开MetaTrader 4客户端并观看货币对 EURUSD 在 M1图表上的情况。我们明显地注意到货币对在波动:上下,上下。主人公决定在这种波动中获取赢利。但是想要抓住这个波动,真是难上加难。例如,上升并开始呈下降趋势。
- 如果汇率向上移动几个点数,需要开Sell仓, 例如, 10 到 15 (图.1中 А-В的波动) ,随后上升停止并开始下降(图.1中 В-C的波动), 可以说是3个点数。 此外,市场下降是被预测到的 (图.1中C-D )。同样的标准使用平 Buy仓。
如果汇率向下移动几个点数,需要开Buy仓, 例如, 10 到 15 (图.1中 C-D的波动 ) ,随后下降停止并开始上升(图.1中 D-E 的波动) 可以说是3个点数。 此外, 市场上升是被预测到的 (图.1中E-F )。同样的标准使用平 Sell仓。
.1. 智能交易 Graal_1 的交易标准(Grail 1).
现在生活的时代令我们惊讶:一个刚刚成熟的程序员只用了3天的时间就创建了第一个 "圣杯"(grail)。
extern int TP=100; extern int SL=100; extern int lim=1; extern int prodvig=3; extern double Prots= 10; int total, bb=0,ss=0; double max,min,lmax,lmin,Lot; int start(){ total=OrdersTotal(); if (total==0){bb=0;ss=0;} if (max<Bid) max=Bid;if (min>Ask) min=Ask; if (((max-Bid)>=lim*Point)&&(Bid>lmax )) { for (int i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE); bb=0;}} Strateg(1); } if (((Ask-min)>=lim*Point)&&(lmin>Ask )) { for (i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) {OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);ss=0;}} Strateg(2);}return;} void Strateg (int vv) {if (vv==1 && ss==0) {OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red); ss=1;} if (vv==2 && bb==0) {OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);bb=1;} lmax=Ask+prodvig*Point; lmin=Bid-prodvig*Point; return; } double Lots(){ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1); double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); if (Lot==0 ) Lot=Min_Lot; return(Lot); }
我们想要的,已经得到。我们并不需要探讨它的严谨性- 这只是一个新手第一次创建智能交易的宝贵经验,还没有形成自己的风格。我们需要尊敬这个智能交易,因为它的正确运行并且显示了意想不到的结果。
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_1.mq4 (Grail 1). // 文章我的第一个"圣杯"中使用的范例。 // Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/ //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int TP = 100; // 赢利定单 extern int SL = 100; // 止损定单 extern int lim= 1; // 比率返回距离 extern int prodvig=3; // 比率前进距离 extern double Prots= 10; //流动资金百分比 //-------------------------------------------------------------------------------------------- int total, // 标准手数计算 bb=0, // 1 = 可用Buy 定单 ss=0; // 1 = 可用Sell定单 //-------------------------------------------------------------------------------------------- double max, // 波动顶风的最高价格 min, // 波动谷底的最该价格 lmax, // 限定价格 // 超出我们考虑卖出价 lmin, // 购买 Lot; // 标准手数计算 //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // 标准手数计算 if (total==0) // 如果没有定单, .. { bb=0; // .. 不Buys ss=0; // .. 不Sells } if (max<Bid) max=Bid; // 计算波动顶风的最高价格 if (min>Ask) min=Ask; // 计算波动谷底的最高价格 //------------------------------------------------------------- 价格下降 ---- if (((max-Bid)>=lim*Point)&&(Bid>lmax )) // 转向高水平 { for (int i=total;i>=0;i--) // 全部定单 { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) { OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);// 关闭Buy bb=0; // 没有任何Buys } } Strateg(1); // 打开函数 } //------------------------------------------------------------ 价格上升 ---- if (((Ask-min)>=lim*Point)&&(lmin>Ask )) // 转向底端 { for (i=total;i>=0;i--) // 所有订单 { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) { OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);// 关闭Sell ss=0; // 没有任何Sells } } Strateg(2); // 打开函数 } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Strateg (int vv) // 打开函数 { //============================================================================================ if (vv==1 && ss==0) // Sell 情况和没有Sells { OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red);// Откр ss=1; // 现在是Sell } //-------------------------------------------------------------------------------------------- if (vv==2 && bb==0) // Buy 情况和没有 Buys { OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);// Откр bb=1; // 现在为 Buy } //-------------------------------------------------------------------------------------------- lmax=Ask+prodvig*Point; // 重现设置限定 .. lmin=Bid-prodvig*Point; // .. 开仓和平仓水平 //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // 标准手数的计算 { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// 计算总的标准手数 double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // 允许最少的标准手数 if (Lot == 0 ) Lot = Min_Lot; // 测试允许最少的标准手数 //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /*
通常来讲,智能交易的内容是很容易理解的。
以上的部分中在 start()函数之前收集了变量。在start() 函数中, 首先需要计算当前仓位谷底倾斜的比率,然后根据情况分析交易标准。 如果该标准开启,已经执行的定单将关闭。在这个智能交易中会使用两个函数 - Strateg() 打开新定单和 Lots()确定总的标准手数。变量 ss 和 bb 被使用到开单的注册中。
在MetaTrader 4 客户端中策略测试是非常重要的工具。我们的主人公小心地测试了智能交易并优化了输入数据,下图为其中的一个最佳结果:我们可以很容易想象主人公的喜悦:这个创建出自他的手!在探索和求知之间创建了他的第一个“圣杯”。得到的结论: "我独立创建了“圣杯”!"
1.2.超前投资
图. 3. 侵略性投资可能导致意想不到的损失
我们的主人公对于这样的结果表示惊讶。他表示:“这个赢利智能交易,投资越多,回报越多!”但是显示的测试结果往往不是如此。
1.2.1. 几何级数
Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// 计算总的标准手数 double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // 最小允许标准手成交量 if (Lot == 0 ) Lot = Min_Lot; // 测试允许的最小标准手数
这种运算方法为几何级数。 百分比变量可以依赖当前流动资金的总数限制定单的成交量。通过这种方法计算定单的成交量并不正确,因为没有考虑到经纪人调用保证金的需求。 然而,我们在上段中要解决的主要问题是投资比例的问题。因此,每个定单的成交量将取决于获得结果的比率:在每笔赢利交易过后成交量会增长,在每笔亏损交易过后成交量会减少。在上面Graal_1.mq4 (Grail 1)中定单成交量的代码为流动资金的10%。
设定 Prots变量成交量等于 0 ,代码如下:
if (Lot == 0 ) Lot = Min_Lot; // 测试允许的最小标准手数
在常数定单成交量中测试智能交易。
图.4. 智能交易 Graal_1.mq4 (Grail 1) 在常数标准手成交量中的测试结果
级数排除后在图表中定单成交量的曲线变化更加直观化,更加自然- 涌动、深陷、下降等等
1.2.2. 再次侵略性投资
任何智能交易都将在赢利和亏损之间找寻它的优势。目前,没有任何的技术可以执行仅一次的赢利交易。亏损交易是每个常规交易策略真实存在的。问题是赢利仓位和亏损仓位之间的比率是多少。
В. 下面是一组在真实交易中赢利交易和亏损交易不均匀分布的范例:
上面的范例中显示一连串5各连续亏损交易,可以更长的亏损交易也会发生。在这种情况下,你需要注意的是赢利交易和亏损交易之间的比率被保持在 3 : 1。
那么,如何能够控制这种随机的结果呢?问题的答案取决于交易者所选择交易策略的质量。 首先,如果交易者是故意的,要遵循相应的防范措施-他的定单总数值不能超过存款额的10% 到 15% ; 第二,如果交易允许再次侵略性投资: 决定投资他的大部分存款额仅限一次,并且是在他获得盈利之后。
- 选项 1. 一个定单值是流动资金的 10% (Prots=10;)。在这种情况下,测试可以使智能交易在一个很好的工作状态下运行,提高差额。你可以在图.2 中查看运行结果。你同样可以注意到在图.2中智能交易运行作业的时间非常长(接近 10 000定单)
- 选项 2. 一个定单值是流动资金的 70% (Prots=70;)。 在图3中显示测试的结果。 在智能交易完成400笔交易之前,两到三个连续亏损定单导致存款额为空。
我们现在来看看测试结果报告:智能交易Graal_1.mq4 (Grail 1)的连续亏损最大总数只有 10笔交易。在测试期间,其他的每组连续亏损总数不超过10。在选项1 中的连续亏损总数不会影响交易的总结果,但是选项2 中的结果却是灾难性的。
因此, 我们可以说错误的投资带来的连续亏损导致的是全面性的灾难。为此,我们可以创建有效的管理系统 - 金钱管理 。根据这个系统限定,一个定单的值不能超出总体差额的15%,并且投资的总数额不能超过它的50%。该系统为交易做出了有益的限定规则。
"圣杯"可以确信一切运行正常,我们的主人公开设真实账户并开始"赚钱"。在一定数量的成功开仓和平仓之后,差额不会增长并平稳下降。此外,在程序员智能交易的交易日结束时,中心交易经纪员会终止交易。
我们的主人公感到困扰。困惑什么是 "技术限定"?什么致使 "延误"?! 在真实交易中的第一个交易结果,我们的主人公得出的结论是这是一个"不好的交易中心",他产生了一种被骗得感觉。这样他终止了与该交易中心的合作。
不过,我们的主人公并没有放弃,决定进一步了解中心过程。他在MQL4 论坛上与有经验的交易者进行交流并且展示出代码。 通过大家的讨论,最终的结果是在任何情况下他智能交易中的代码都是无利可图。在论坛上交流使主人公明白失利的原因。
1.3. 错误
Meta Editor 不断证实没有错误生成
但是错误却存在。
1.3.1. 偏离形式策略
虽然智能交易的创建是在一个简单易懂的策略下,本质上是变量代码和优化期间的改变。 这样,在真实“圣杯”中最初的想法是呈现出来的是下跌。实际上,最初构想能够赚取的波动长度为15到 20点,但是在现存的“圣杯”版本中这个参量 的值为3 。在这里谁还会谈及顶峰和低谷...
需要注意的是变量ss和bb。这样考虑定单是错误的。在定单命令形成阶段,定单已经可以处于打开状态。但不能够确定定单是否被打开。 为了明确定单是否开仓,可以等待服务器的回复并开始分析在终端内可用的定单。在真实的交易中部分代码需要重新编写,大多数情况下修改版本可以运行,其中包括策略测试 (查看文章 巨大程序中的定单考虑)。
1.4. 硬件限制
智能交易的测试时间限定为М1。值得注意的是当智能交易在时间期限上M1交易时,对于智能交易的价格变动非常敏感。
测试模式和真实交易之间的主要区别在于测试模式中不提供价格下降和重新报价 。
不同的经纪中心存在不同的报价(考虑到延迟)。 汇率越是频繁地更新, 经纪人建议交易者以其他价格执行的可能性越高。 另一方面,图表中越多 "平滑部分" 重重新报价的可能性越低,但智能交易的交易频率空间越小。
我们的主人公在其他经纪中心(差价相同)1分钟历史上测试了Graal_1 (Grail 1)。事实证明结果取决于图表类型。
较大的借款,不稳定盈利创建显示在亏损边缘智能交易的差额。.
通常来讲,重新报价的价格会存在1或2点的差异(不过在市场中可能更多)。 如果点差差距较小不会影响智能交易的成功盈利运行,例如 10 - 15。但是 ,智能交易存在最小的期待盈利。如果小于2,一般情况下不能成功完成。因为它取决于自然报价和重新报价。
经纪人是否可以对当前替克重新开价--这是一各单独的问题有经纪人解决。但是,在真实市场上开始运行时,在真实账户上需要考虑假设重新报价正常,自然状况和交易技术。
1.5.经济方面
- 小额价格定单
常见状况交易者注意力都集中在自己的交易账户上和相关的事件,这里包括交易策略,智能交易等等。 不过交易者的忧虑也正是经纪人的经济忧虑。
在“正常”的交易中,可以达到双方赢利:交易者使用一个稳妥的交易策略,经纪人则从交易者的交易业务中获取利益。这样,双方在相互支持支撑下获取赢利。
不过,有时双方也会发生冲突。例如,如果经纪人增加价差并开启自动交易,或者是在当前价位没有及时开仓(平仓),这时交易者不会盈利。
同样地,交易者的一些交易业务也会影响到经纪人的利益。一些交易者频繁使用小数额金钱进行交易业务。
经纪人的工作技术是整体层面的,并且非常简单。他收集交易者定单的买卖并协调到相关银行或其他金融机构。我门来看一个简单的例子。假设经纪人服务的总数为100单交易,货币对为EURUSD1 标准手。其中的60单为买入,40单卖出。这种情况下,经纪人必须从银行购买20单(60和40单之间的差额)。另外,汇率的变动不会对经纪人产生影响。这样经纪人将得到的价差为80单(40+40)和 20单的部分价差 (包括付给银行的部分)。
这种情况下,40单交易的赢利/亏损的源代码为其他40单交易的亏损/赢利。剩下20单交易赢利/亏损的源代码为银行(精确地讲是法人服务的银行和当前货币对买卖进出口业务)。这是基本的金钱市场参与者之间的相互关系。
对于经纪人和银行或金融机构之间的关系。如果交易者买卖的金钱数量少得可怜 ,在这些买卖业务中经纪人与银行没有任何关联。在МТ4 终端内经纪人和银行之间执行交易业务要少于交易者的点击次数。真常情况下,经纪人和银行之间的最小交易量不能超过50 000美元, 转入的定单价格0.5标准手1:100杠杆。这就是交易者经常使用小金钱总数不能盈利的原因。
经纪人与其他交易者一样属于金钱市场的参与者。他必须注视并分析所有交易者的运行。 当然,如果交易者证实亏损或在一定周期内(例如,一天之内的结果)的总结果为零,经纪人可以盲目地进行重复性投资。但是如果这些相互关联的结果在经纪人的亏损中,任何一个经纪人都将终止这种关系。这时,经纪人会做出相应的反应,否则在经纪人的金钱市场领域将是风平浪静。
请注意在外汇市场现代程序不是经纪人可以恶意操作的。经纪人和银行之间存在协议。 经纪人通过价差赚取盈利属公平手段(本文不与讨论滥用职权的经纪人)。也许经纪人喜欢每时每刻与银行交易,但此时则没有可能性。
在交易者频繁执行小数额的交易业务情况下,经纪人会采取一定措施。可以发送传达信息给交易者。经纪人同样可以对该交易者开启自动交易或发送增加请求业务的总数。
- 大额价格定单
在区分真实账户或模拟账户上的交易和测试中存在限定。它是标准手价格的最大值。不存在经纪中心,银行和金融机构可以执行大额度的金钱交易。
如果定单花费约10 000到20 000美元 (请注意杠杆,通常为 100),经纪中心将卖出/买入约1 000 000美元。这个数额是非常大的,经纪人学会了如何处理这样大量的金钱总数并时它们成功运行。
如果定单价格达到$50 000美元甚至是$100 000美元,在一些中型金融机构可能会出现问题。 这种情况下,在内部银行市场美元的总数在 5百万-1千万。在一定时间内这样大量的数额很难卖出/买入。
如果定单的价格超过300 000 到500 000美元就会出现窘境。经纪中心将与交易者独立交易。我们可以说,5千万美元对于任何机构都是一个非常大的数额定单。
在大额价格定单的情况下,经纪中心本身不会做出任何保证。这种情况要依赖交易者的理解和受理。
基于这个原因,数以百万交易的智能交易成为交易者极大错误的证据 和真实生活没有任何的共同之处。
根据这种因素建议我们的主人公先赚取l 100 "kilobucks" ,然后找一个 "很破的办公室"。主人公开始安静地思考 "全部限制"。
我们不要忘记经纪人和我们一样有着相似的教育和文化水平,他们只是以不同的方式在执行交易。相同的技术对于经纪人非赢利,他可以立即进行探测分析运行的成效。而对于非赢利做出缓慢反应的经纪人,可以说他是没有足够经验的。在大多数情况下,经纪人在交易中是有经验的并且清楚外汇交易市场的所有细节。所以他们知道什么是几何级数、经济忧虑、再次侵略性投资、小额和大额价格定单。一般来讲,每个交易者都可以说经纪人的资格要高于交易者,他可以对出现的问题作出解答。
试着质问自己:什么样的智能交易 (在经济和技术状况下)可以在一年内开单超过20 000?
我们的主人公为这些替克、柱、点数、价差、经纪人和银行费神。他决定不去触碰细节和“单一问题”。他能够明白 "测试的结果不会与真实交易吻合"的道理。他决定在挂单基础上创建一个适合的技术。
2. 第二个 "圣杯"
2.1 策略
在挂单上创建的构想是我们的主人公在研究货币对 EURGBP和EURCHF在1-分钟图表上交叉之后提出的想法。
图 8. 在价格上交叉率有重大偏差
可以清晰地注意到:晚间当欧洲部分已经结束,而亚洲部分还没有开始。图表中的一些货币对显示出柱的价格显然与“正常”价格的完全不同。从形态学逻辑出发,略高于或 略低于主流趋势放置限定类型的挂单拥有很高的成功概率。想要挂单适应主流趋势的变化,必须 沿着中间线"拖拉"并且支持移动平均线之间的距离。
我们的主人公实现了这个构想,并编写智能交易如下:
// Graal_2.mq4 (Grail 2).
// 我的第一个“圣杯”文章中使用的范例
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int TakeProfit=5; // 赢利定单
extern int StopLoss= 29; // 止损定单
extern int Distan = 2; // 距МА线的距离
extern int Cls = 2; // 平仓 ** 赢利点数
extern int period_MA=16; // MA 时间周期
//extern int Time_1 = 0; // 起始时间
//extern int Time_2 = 0; // 终止时间
extern int Prots = 0; // 流动资金百分比
//--------------------------------------------------------------------------------------------
int
Nom_bl, // BuyLimit 定单数
Nom_sl, // SellLimit
total, // 计算标准手术
bl = 0, // 1 = BuyLimit 可用定单
sl = 0, // 1 = SellLimit 可用定单
b = 0, // 1 = Buy 可用定单
s = 0; // 1 = Sell 可用定单
//--------------------------------------------------------------------------------------------
double
OP, // 开盘价 (绝对点数)
SL, // 止损定单 (相对点数)
TP, // 赢利定单 (相对点数)
dist, // 距МА线的距离 (相对点数)
Level, // 允许挂单交易的最短距离
OP_bl, // OpenPrice BuyLimit (绝对点数)
OP_sl, // OpenPrice SellLimit(绝对点数)
cls, // 平仓 ** 赢利 (绝对点数)
MA, // MA 值 (比率)
spred, // 价差 (绝对点数)
Lot; // 计算标准手数
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()
{
Level=MarketInfo(Symbol(),MODE_STOPLEVEL); // 检查服务器显示的内容
Level=(Level+1)*Point; // ?:)
SL=StopLoss*Point; // 止损定单(相对点数)
TP=TakeProfit*Point; // 赢利定单(相对点数)
dist=Distan*Point; // 距MA线的距离(相对点数)
cls=Cls*Point; // 平仓 ** 赢利 (绝对点数)
spred=Ask-Bid; // 价差 (绝对点数)
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
{
//============================================================================================
total=OrdersTotal(); // 标准手数计算
bl=0; // 通过开始处归零
sl=0; // 通过开始处归零
b=0; // 通过开始处归零
s=0; // 通过开始处归零
//--------------------------------------------------------------------------------------------
for (int i=total; i>=0; i--) // 全部定单
{
if (OrderSelect(i,SELECT_BY_POS)==true && // 所选定单
OrderSymbol()==Symbol())
{
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_BUY) // 买入定单
{
b =1; // 发现定单
Close_B(OrderTicket(),OrderLots()); // 平单 (由函数决定)
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_SELL) // 卖出定单
{
s =1; // 发现定单
Close_S(OrderTicket(),OrderLots()); // 平单 (如果需要)
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_BUYLIMIT) // BuyLimit 定单
{
OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(绝对点数)
Nom_bl=OrderTicket();
bl=1; // 发现定单
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_SELLLIMIT) // SellLimit 定单
{
OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(绝对点数)
Nom_sl=OrderTicket();
sl=1; // 发现定单
}
//--------------------------------------------------------------------------------------------
}
}
//--------------------------------------------------------------------------------------------
MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// MA当前值
Modify_order(); // 激活修改
Open_order() ; // 激活打开
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_B(int Nomber, double lots) // 关闭 Buy 定单
{
//============================================================================================
if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// 如果达到预设定赢利
{
OrderClose( Nomber, lots, Bid, 1, Yellow); // 平仓
b = 0; // 没有任何Buy定单
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_S(int Nomber, double lots) // 关闭Sell定单
{
//============================================================================================
if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// 如果达到预设定赢利
{
OrderClose( Nomber, lots, Ask, 1, Yellow); // 平仓
s = 0; // 没有任何 Sell定单
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Modify_order() // 定单修改版本
{
//============================================================================================
if (bl==1) // 如果是 BuyLimit
{
OP=MA-dist; // 必须在这里找到
if (MathAbs(OP_bl-OP)>0.5*Point) // 如果这里没有找到
{
OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// 定单修改
}
}
//--------------------------------------------------------------------------------------------
if (sl==1) // 如果是SeelLimit
{
OP=MA+spred+dist; // 必须在这里找到
if (MathAbs(OP_sl-OP)>0.5*Point) //如果这里没有找到
{
OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// 定单修改
}
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Open_order() // 打开函数
{
// int Tek_Time=TimeHour(CurTime()); // 时间测试
// if (Tek_Time>Time_2 && Tek_Time>
//============================================================================================
if (b==0 && bl==0) // 没有Buy定单,打开 bl
{
OP=MA-dist; // bl 开单汇率
if(OP>Ask-Level) OP=Ask-Level; // 在相关的变量中精确OP
OP=NormalizeDouble(OP,Digits); // 正常化 (MA给出的第五个小数点 )
OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Open
bl=1; // 现在有 Buy 定单b1
}
//--------------------------------------------------------------------------------------------
if (s==0 && sl==0) // 没有Sell定单, 打开 sl
{
OP=MA+spred+dist; // sl 开单汇率
if(OP<Bid+Level) OP=Bid+Level; // 在相关的变量中精确OP
OP=NormalizeDouble(OP,Digits); // 正常化(MA 给出的第五个小数点)
OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// 打开
sl=1; // 现有Sell定单 sl
}
///============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots() // 标准手数计算
{
//============================================================================================
Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// 计算标准手总数
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // 最小标准手成交量
if (Lot == 0 ) Lot = Min_Lot; // 剩余最小标准手数
//============================================================================================
return(Lot);
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*
可以选择止损、赢利、距离(定单保持主流趋势),Cls (定单上获取的最小点总数,当达到该值时必须平单), period_MA (移动平均线时间周期;MA是最近历史汇率的中间线)和 Prots (流动资金百分比, 定单价格)作为协调变量。这些条件足以实现主人公的构想。
- 在特殊函数start() 中,分析定单 (查看考虑定单的方法)并决定作出相应的动作。如果在终端内开单,相关的函数 Close_*()将会在需要分析关闭和平单中立即被调用。
- 在start()函数末尾,打开Modify_order() 和Open_order() 函数可以修改并打开限定类型的挂单。不会打开其他类型定单。
- 在 Modify_order() 函数中,计算定单的位置 (与中间线的距离相同)。如果没有找到放置位置,将被移动。
- 在Open_order()函数中,确定放置挂单的理想位置。另外还有考虑服务器的限定。如果没有定单,放置定单。
2.2. 几何级数
图. 10. 在 MIG Investments公司的交易状况下智能交易 Graal_2.mq4 (Grail 2) 使用EURUSD 货币对在М1图表从2005年3月到2006年6月常数价格定单测试结果
起初我们的交易员向要在晚间赚取赢利。但惊奇地发现在白天智能交易成功地运行。在看到如此漂亮的结果后,我们的交易员再次决定: "只有我!" 并且开始在此“赚钱”?但是并非想像发生的... 此时,我们的主人公并没有真正认识"尖峰"。
2.3. 错误
在上面的智能交易范例中,存在大量的缺陷和不正确解决方案。 在 Modify_order()中,挂单没有考虑允许的最小距离,组织考虑开单不正确, 没有单独修改倾向于Cls赢利,智能交易的分析部分被整体代码“抹黑 ”等等。
智能交易编成过程中不正确和疏忽大意形成的错误会潜移默化地融入其他智能交易。
2.4. 技术限定 (Spikes-尖峰)
无论是技术限定还是组织限定,这些所有的限定最终将导致经济上的亏损。最主要的问题是这些损失在交易账户之内。
通常交易者在屏幕图表中注视的蜡烛柱表示在特定区域一个市场发展的平均结果 (例如,其中包括欧洲银行)。不同的经纪人可以分析历史短期的汇率变动。另外,我们注意到这些图表相互之间都存在不同之处。.一些经纪人的图表包含长期不同方向的蜡烛柱标准手数,同时其他经纪人的图表将“和平并且安静”地显示。
替克图表同样是买卖的对象。这是一些非自然价格替克和多余过滤程序的运行结果,并且会显现"非自然"替克。这种情况通常发生在个人,以个人原因在银行买卖的价格远远不同于市场价格。有时程序能够接受该信息并且能够一次性地传输,不考虑形成最终图表。在部分情况下,程序很难理解什么是“正常”价格,什么不是。 由于上述原因,图表中会出现不同宽度(取决于程序计算)的单独蜡烛柱。这些便属于 尖锋 它们会以不同形式显现,但是在外汇市场不显示 真实状况。
使智能交易赶上这些"尖"、 "脊"、"尖峰"很容易。当价格为最大赢利时开单。但是要清楚一点:由于经纪人和银行之间的关系,通常在这种传输中银行不会支付此类交易。这就意味着交易者的赢利来自于经纪人的口袋!当然,经纪人不希望发生此类状况,经纪方会使交易者回归“正常”的市场价格。
作为保护经纪人利益的措施,经纪人和交易者之间的合同通常包含这样的条款-经纪方有权利重新报价,在市场价格强烈变动中不保证开单, 第二次接触挂单打开和其他一些措施。一些情况下,经纪人可以取消已经打开的定单。经纪人认为定单已经到达尖峰。
我们的主人公再次遇到这样的问题。在模拟账户运行很好的智能交易由需要重新修改。这次当定单被强行关闭时,我们的主人公并没有认真听经纪人解释。但是,当经纪人终止智能交易时,主人公不能够再理解。最终双方解除了合同。
我们的主人公觉得这些失败是由于一分钟时间期限。他通过论坛与其他的交易者进行了交流,决定使用同样的货币对匹配较大的时间期限进行交易。他认为是直觉的引领。主人公逐渐地得出结论 "Mozart和我 me" 并且开始他的第三次创建 - 不再使用 M1图表("永远不再使用!")
3. 第三个 "圣杯"
3.1 形式策略
仔细研究货币对EURUSD Н1图表并使用不同指标进行分析,我们的主人公发现一个非常有吸引力的规律:如果较小时间周期的移动平均线 (Moving Average)遇到较大时间周期的移动平均线,市场通常按照较小移动平均线的方向移动。
图. 11. 策略的图表体现是以不同时间周期的 MA交叉为基础的
他同样注意到所有的时间期限都会显现类似的相互关联, 但是只有设定和较大的公司运行工作。他通过MQL4语言的知识告知定单的方向和开仓的时间状况。智能交易准备就绪后,需要对其参量进行优化 - 把最有成效的MA长度整理分类并妥善放置 StopLoss和TakeProfit。
这时下面的智能交易代码产生了:// Graal_3.mq4 (Grail 3).
// 我的第一个"圣杯"中使用的范例。
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int MA1 = 11; // 第一个MA的时间周期
extern int MA2 = 23; // 第二个MA的时间周期
extern double TP = 50; // 赢利定单
extern double SL = 15; // 止损定单
extern double Prots= 0; // 流动资金百分比
//--------------------------------------------------------------------------------------------
int
ret, // 交汇点
total; // 开单计算
//--------------------------------------------------------------------------------------------
double
Lot, // 标准手数计算
Pred, // 第一个MA的先前值(红色)
Tek, // 第一个MA的当前值 (红色)
Golub; // 第二个MA的当前值 (蓝色)
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()
{
//============================================================================================
SL = SL*Point; // 止损点数
TP = TP*Point; // 赢利点数
return;
//============================================================================================
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
{
//============================================================================================
total=OrdersTotal(); // 定单总数
if (total==2)return; // 已经打开定单
//--------------------------------------------------------------------------------------------
Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// 第一个MA的当前值
Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// 第二个MA的先前值
Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// 第二个MA的当前值
//--------------------------------------------------------------------------------------------
if (Peresechenie()==1) Open_Buy(); // 由下向上移动 = 打开 Buy
if (Peresechenie()==2) Open_Sell(); // 由上向下一栋 = 打开 Sell
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie() // 函数决定交汇点
{
//============================================================================================
if ((Pred<=Golub && Tek> Golub) ||
(Pred< Golub && Tek>=Golub) ) ret=1; // 交点由下向上
//--------------------------------------------------------------------------------------------
if ((Pred>=Golub && Tek< Golub) ||
(Pred> Golub && Tek<=Golub) ) ret=2; // 交点由上向下
//============================================================================================
return(ret); // 返回交汇点
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Buy() // 函数打开 Buy
{
//============================================================================================
if (total==1) // 如果只有一个定单...
{ // ... 说明会打开其他定单
OrderSelect(0, SELECT_BY_POS); // 选择定单
if (OrderType()==0)return; // 如果是Buy定单, 不打开
}
OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// 打开
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Sell() // 函数打开Sell定单
{
//============================================================================================
if (total==1) // 如果只有一个定单...
{ // ... 说明会打开其他定单
OrderSelect(0, SELECT_BY_POS); // 选择定单
if (OrderType()==1)return; // 如果是 Sell定单, 不打开
}
OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// 打开
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots() // 标准手数计算
{
//============================================================================================
Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// 计算标准手总数
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // 最小标准手值
if (Lot == 0 ) Lot = Min_Lot; // 剩余最小标准手数
//============================================================================================
return(Lot);
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*
这个智能交易与先前的类似,可以说是相当地简单。
智能交易开始结合了变量的描述。在 start() 函数中,指定较大或较小时间周期定单总数就是 MA值。 如果移动平均线相遇,相应的函数将会打开定单: Open_*()。 确定移动平均线相遇的状态使用Peresechenie()函数。使用Lots()函数找出标准手的成交量。
在五个月内得到了300 000! 非常精彩!在这个图表上我们的主人公似乎看到了以前一切试探的辛酸。他决定放慢脚步,不急于求成。
3.2. 进展
在常数价格定单测试了该智能交易后,显示了可以接受的图表差价:
五个月内6000点。每个月接近1000点!但是我们的主人公对智能交易在真实交易中的状态表示怀疑。毕竟已经有了前两次的错误...
3.3. 错误
首先想到的是"太奇怪了!一定是 MetaEditor出现了问题!" 随后,主人公在查看代码中发现的问题。我们也来学习一下。
我们开看看下面的函数:
int Peresechenie() // 函数探测交点
{
//=================================================================================================
if ((Pred<=Golub && Tek> Golub) ||
(Pred< Golub && Tek>=Golub) ) ret=1; // 由下向上相交
//-------------------------------------------------------------------------------------------------
if ((Pred>=Golub && Tek< Golub) ||
(Pred> Golub && Tek<=Golub) ) ret=2; // 由上向下相交
//=================================================================================================
return(ret); // 返回交点方向
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
很明显,这里存在错误。当使用整体变量 ret 时,它的保存值等于最后计算值,即 1 或 2。因为这个原因 Peresechenie()函数不会顾虑当前的状况而返回到最后计算值。这就是在函数 start() 中打开常数定单的原因:
更正这个错误,在Peresechenie()函数开始之前使ret变量值归零。我们的主人公更正了这个错误并只允许在一个柱上开单。现在我们来看下面这个智能交易的代码:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_31.mq4 (Grail 31) // Used as an example in the article My First "Grail" // Sergey Kovalyov, Dnepropetrovsk, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int MA1 = 11; // 第一个MA时间周期 extern int MA2 = 23; // 第二个MA时间周期 extern double TP = 50; // 赢利定单 extern double SL = 15; // 止损定单 extern double Prots= 0; // 流动资金百分比 //-------------------------------------------------------------------------------------------- int New_Bar, // 0/1新柱形成的事实 Time_0, // 新柱形成的时间 ret, // 交点方向 total; // 开单数 //-------------------------------------------------------------------------------------------- double Lot, // 标准手数 Pred, // 第一个MA的先前值 (红色) Tek, // 第一个MA的当前值 (红色) Golub; // 第二个MA的当前值 (蓝色) //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { //============================================================================================ SL = SL*Point; // SL点数 TP = TP*Point; // ТР点数 return; //============================================================================================ } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // 定单总数 if (total==2)return; // 已经开单 //----------------------------------------------------------------------------- New bar ------ New_Bar=0; // 首先归零 if (Time_0 != Time[0]) // 如果柱开始时间改变 { New_Bar= 1; // 新柱 Time_0 = Time[0]; // 记住新柱开始的时间 } //-------------------------------------------------------------------------------------------- Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// 第一个MA当前值 Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// 第二个MA先前值 Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// 第二个MA当前值 //-------------------------------------------------------------------------------------------- if (Peresechenie()==1 && New_Bar==1) Open_Buy(); // 由下向上移动 = 打开 Buy if (Peresechenie()==2 && New_Bar==1) Open_Sell(); // 由上向下移动 = 打开 Sell //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() { ret=0; // That's the heart of the matter!:) //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // 由下向上相交 //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // 由上向下相交 //============================================================================================ return(ret); // 返回交汇方向 } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Buy() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // 选择定单 if (OrderType()==0)return; // 如果是买入,不打开 } OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// 打开 return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Sell() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // 选择定单 if (OrderType()==1)return; // 如果是卖出,不打开 } OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// 打开 return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() { Lot = NormalizeDouble( AccountEquity()*Prots/100/1000, 1);// 计算标准手总数 if (Lot<0.1)Lot = 0.1; // 剩余最小标准手 return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /*
这个智能交易在常数标准手价格中测试取得了有限成果:
我们的主人公显然有些气馁!这么久的努力似乎是徒劳。 主人公继续找寻着自己的“圣杯”。数月后,他决定重新捡起名称为Graal_3.mq4 (Grail 3)的智能交易。"虽然存在错误,但是也显示了不错的结果。这可能是必然!如果智能交易能够保持好的结果,就让它随意开仓吧!"。开始了又一次的测试。
3.4. 适应结果
我们的主人公发现自己是一个不敢面对现实的人。 在历史部分轻松地可以证明所有的优化参量全部适合。在不同的历史周期,同样的智能交易总会给出不同的结果。
问题在于怎样能够找到最有利的输入数据,尽可能地降低小波动对于智能交易的功效和效率的影响。通常我们会聚焦到策略上,可以根据市场帮助应变。其实它指能够起到帮助作用,不要期待通过策略获得最佳结果!
以Graal_3.mq4 (Grail 3)命名的智能交易最有利的设定搜索没有任何结果。智能交易测试在不同的外部变量值中显示了亏损,在不同历史周期的测试显示了差异性的结果。由于以上这些原因,我们的主人公没有成功地找到最佳设置。他得出了这样的结论:不存在通用的交易策略。
我们的主人公再次回到以 Graal_31.mq4 (Grail 31)命名的智能交易并得到了预期的结果。下面是最佳的结果:
主人公回顾上面的这些智能交易,似乎没有一个像是“圣杯”。因为在真实的账户中智能交易不能够理想化地运行。但是,它是真正的智能交易并且显示了赢利结果。
4. 结论
生命中事物总是很难让自己摆布,特别是美好的事物。但是这些美好的事物或早或晚都会一一到来。 我们的主人公太过急于求成:他损毁了与两个经纪人之间的合作关系,失去了辛苦赚取的金钱... 但是获取了在外汇市场不可估量的宝贵经验。主人公得到的结论是 "只有Mozart ...",及时停止并决定不再草率地下结论!
从以上的反复失败的教训中,我们的主人公总结出了一下结论:
- 渐进式投资- 在真实的交易中进行正常的渐进式投资。不应该使定单的价格过分提高。
- 不偏离初始策略
如果在智能交易运行过程中,制定参数发生转变导致结果大幅度更改,说明初始策略水平不均匀。很有可能发现一种新的交易策略引导智能交易得到较好的结果。这种情况下,应该仔细查看该策略并且考虑突然成功的原因。 首先需要回到自己最初的想法和理念,在一定限度内充分地研究其参数的适用性。 - 密切注视运算错误
运算错误的产生是非常自然的现象。发现错误的存在需要有丰富的经验。另外,其中的一些错误之能够在智能交易的最终结果中被发现。往往是开单或 "不适当"的开单 成为计算错误的明显标志。 - 正确对待策略测试中智能交易的测试结果
智能交易在真实账户中得运行和测试策略中的模式完全不同。两者的区别在于在真实账户中不考虑执行定单和重新报价的生成。 对于预期回报高的智能交易不会有影响,但是对于预期回报较低的智能交易其结果则完全不同于测试期间得到的结果。在一些范例中,我们看到预期回报较低的智能交易在测试期间显示了不可思议的结果,但却在真实交易中遭遇亏损。 - 不存在侵略性投资
任何的交易策略必须考虑到亏损交易。如果定单价格没有较高的限定,一个短期交易亏损肯能会导致整体差额的下降,甚至是整体存款额的下降。 自欺欺人的进行侵略性的强行投资导致的结果无疑是破产。 - 不尝试在随机中赚取赢利
尖峰并不是自然反应,自然的市场汇率。如果交易者在随机尖峰中赚取赢利,其赢利来自经纪人的资金。经纪人或早或晚都会发现,并且停止与该交易者的合作、终止智能交易、封闭账户。 - 在不同的历史时间周期上交叉检测测试结果
在不同的时间期限上每个智能交易将显示不同的结果。每个历史期间都可以发现它的最佳优化设定。在测试中需要非常细心,不要自我欺骗(符合智能交易参数),尽可能地在很多历史期间交叉检测获取的测试结果。
SK. Dnepropetrovsk. 2006.
原文: http://articles.mql4.com/ru/articles/1413
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1413
看了例子1的代码,有些不明白的地方,请高人指点。
if (max<Bid) max=Bid;
if (min>Ask) min=Ask;
min这个变量,初始值为0,然后应该始终不可能>Ask(没有别的赋值的地方),始终为0,根本没法赋值为Ask,那么这个变量还有什么意义?
那么后面这一句: if (((Ask-min)>=lim*Point) && (lmin>Ask )) 中,(Ask-min)>=lim*Point始终为True,就失去了计算的意义。所以不知道是不是代码有误,因水平低,没法判断,请高人指点?