EA智能交易程序编程(一)

2015-09-08  素人堂

@ 测试数据次数过多,目录文件胖到走不到时,就减肥:

目录:\tester\history和tester\logs里的文件全部删除

@

如果你下载的是ex4文件,就将它拷贝到experts\indicators目录下,然后重新运行MT4,就可以在导航栏的自定义指标项目下看到新的指标名称,后面的使用和其他指标一样。

  

  如果你下载的是mq4文件,同样你也需要先拷贝的experts\indicators目录下,然后使用MetaEditor打开源文件,点击编写按钮。这时会在目录下自动生成ex4文件,同时MT4导航栏自定义指标项目下会出现新指标,直接使用即可。

  

  如果还有DLL文件,或者有.set,或者有.tpl等,

DLL为库文件,复制到experts\libraries

.set为设置文件复制到experts\presets

.tpl为模板文件,复制到templates

@

OrdersTotal()函数,可以计算当前账户中一共还没有平仓的单子和挂单的个数

@

从历史订单选出最后一单

int i =0;
while (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) )
i++;
OrderSelect(i-1,SELECT_BY_POS,MODE_HISTORY)
现在就是最后一个平仓的!


上面的使用条件是 没有使用挂单,没有取消过挂单,因为历史中包含平仓的和取消的
如果历史中有取消的挂单, 就麻烦多了,需要判断类型/时间/赢利来剔除取消的挂单,找到最后的平仓.

@

如何检测一张交易单是否已经被打止损或打止盈
答9)OrderCloseTime()这个函数返回的是订单的收盘时间。如果订单正在交易中而未平仓,此函数
返回的是0,如果平仓,此值就会变成平仓当时的服务器时间,是一个很大的正整数。


//-----------------检测是否平仓-----------------+

string IsClosed(int tik)
{
OrderSelect(tik, SELECT_BY_TICKET);
//--若为未平仓
if(OrderCloseTime()<1)
return("未平");


//--若为买单 被止盈
if(OrderType()==OP_BUY){
if(OrderClosePrice()>=OrderTakeProfit())
return("已被止盈");
}


//--若为卖单 被止盈
if(OrderType()==OP_SELL){
if(OrderClosePrice()<=OrderTakeProfit())
return("已被止盈");
}


//--其它为被止损
return("已被止损");
}

//------------------------------------------------+

有的朋友可能会质疑,打止损或打止盈的订单,其OrderComment()会包含sl或tp字样,检测这个不是
更方便吗?你要这样说我完全同意,不过上面的函数也完全可以实现功能,这个例子同时说明编程不
是死的,我们可以用不同的方式完成同一件任务。

(摘自中国自动化交易中心)

@

基准货币每一点的价值都是10美元,因为是基准货币最小的变动点就是0.0001。只要乘以合约单位可以得知,即:0.0001*100000*手数=10美元。

@
Lots = 0.1
if(AccountFreeMargin()<(1000*Lots))
{
Print("We have no money. Free Margin = ", AccountFreeMargin());
return(0);
}

这个的代码的意思是,假设我们的可用保证金小于100的话,我们就停止开仓。其目的主要是保护我们的资金,不然我们的资金无限制的开仓
朋友可以根据此逻辑判断进行触类旁通的判断

@

OrderType() 是针对OrderSelect()选中的订单有效。因此次序应在OrderSelect()之后

OrderProfit() 不是OrderTakeProfit()

@

挂单成交后,订单类型自动变成 OP_BUY和OP_SELL了

@

EA下单时有效期expiration参数,是以秒为单位的。

挂单时 用当前的时间(服务器时间或本地时间)加上你计划延隔的期限(秒)即可

示例: OrderSend(…….,TimeCurrent()+Period()*60,..);

例:下单一小时内有效

expiration= TimeCurrent()+ (Hour()+1)*60; // 当前时间加上范围秒数

ticket= OrderSend(Symbol(), OP_BUYLIMIT, lots, bid, 3, 0, bid+yl*Point, "b"+DoubleToStr(yl, 0), 81993455, expiration);

@报警开关之写法一

for (i=limit-1;i>=0;i--) {
if(......&& Time[0]>bartime &&.....){

Alert(Symbol(), " ", ......);

bartime=Time[0];

}
}

@

几个账户有关的术语的确切含义
Balance: 有仓时==净值;(开仓后则不一定)

Equity: 开仓后则包含了盈亏
Margin: 当前持有单所占用的资金

Free: 净值 - 已用

@

ordercloseby

是用相反方向的单子来平仓 (需找到对应的单号)

@

在 МetaТrader 3客户终端中,在两笔交易中需要停留10秒钟的时间。在 MetaQuotes Software Corporation 公司创建 МТ4时,出于交易者的意愿删除了这个限定。事实上,这种情况是接收一个接一个的交易执 (对于一些仓位移动止损水平,移除挂单交易等等)。但有些交易者认为交易之间的停顿是错误的,并且进行设置智能交易可以不间断的开仓。这种结果导致账户被封,在经纪的角度这是不友好的态度。

@

#include <std.mqh>

是导入一个文件. 你可以在std.mqh文件里写好一些函数,以后写ea的时候,直接用就行了,用include包含进来 .include文件往往用于声明函数,

或者有些人也喜欢把具体实现写在H文件上 ,不同的是,MQL不用处理内存问题

@反编译出乱码的看法

[承编:] 反编译是由中间语言过度的, 这个和windows字节序有关, 就好象你删除问件恢复后,不是原来那个名字,而是一寸乱码一样, 反编译出来的东西,是他主动命名的, 变量在内存中都以堆或者栈的形式存者,反编译的时候,就按照堆栈的位置给每个变量起名,就好似你由广州去到北京,但你还是你.

[snake:] 变量名是人起的,机器不懂这些,所谓的变量名就是为了人类能看懂的,翻译成机器语言都是16进制的地址. 反编译后,需要给他们起个名字,就按照顺序编号来起了 .变量名字在编译的时候就已经被机器废弃了..其实有规律的,开头是g的是全局变量,l的是局部变量 ..

[无欢:] 在编译原理中,编译机负责把变量摆放在适合的堆栈里,所以,他的标识只能是地址号

@

订单中返回最后一笔单子的订单号
如果是历史订单,取最后一张历史单的平仓时间, 如果是还在交易中的,就取最后一口单的开仓时间

@

指出问题:
这个是调整止盈止损的 所以貌似第二个参数必须用OrderOpenPrice()
bool ModifyOrder(double PriceAverage){
for(int pos=0; pos<=OrdersTotal();pos++) {
OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
OrderModify(OrderTicket(), OrderOpenPrice(), 0, PriceAverage, 0, Blue);
}
return(0);
}


这样写不严密!
modify的时候应先检查被修改价和现在的价格是否相等
OrderModify(OrderTicket(), NormalizeDouble(OrderOpenPrice(),Digits),
NormalizeDouble(Ask+Point*TrailingStop,Digits),
NormalizeDouble(OrderTakeProfit(),Digits),0,Red);
用这个函数的时候,系统经常自动生成很多点位
另外modify的时候要检查修改价和现在的价格是否相等
NormalizeDouble(OrderStopLoss(),Digits)!=NormalizeDouble(Ask+Point*TrailingStop,Digits))
如果这两个改动之后还是有那问题,就是修改价格不合理了,比如不能太靠近现价
大部分的ea没有这些判断,平台一换了,测试结果就相去甚远

@

对于一个新帐户,OrdersHistoryTotal()应该是空值吗?
OrderSelect( OrdersHistoryTotal()-2, SELECT_BY_POS, MODE_HISTORY );
这个函数会返回什么值??

新账户时此值是0 . 则select会返回失败,也就是负值

OrdersHistoryTotal()本身是个数,同时你要清楚 第一个历史单的序号是0, 第二个是1
所以你可以理解OrdersHistoryTotal()-1是“距离现在最近的出场单的序号

@

对于一个被止赢的价位,按原来价位重新入场怎么写呢?

个数是1, 但序号是从0开始

你这个已经出场了,就算查到价格也要判断当前现价,然后决定如何处理:

如果当前价比你找到的那个价还优那你可以现价入场;如果已经偏离很远则挂单。这些由你决定

@

止盈价的获得

几句话说不清楚,大致意思是:

从最大序号开始循环select历史单
找Symble()==OrderSymble()的历史单
然后查看其OrderComment()是否=[t/p]
如果相等说明是止盈单,则取其OrderClosePrice就是止盈出场价格了

@

comment参数的特殊作用

A:这参数本意是用于记录这个订单的描述信息,程序只能在订单入场的时候设定它。同时系统会在这个订单发生止损 止赢或者拆单的时候自动修改这里的内容
既然订单发生止损 止赢或者拆单的时候自动修改这里的内容。
我可以在下单的时候给comment赋值”on”,当订单生成后我可以用OrderComment()
函数实时获取它的comment值如果不等于”on”那就说明订单已经止损或止赢了。

@string OrderComment() 返回定单的注释。

int ticket=12345678;

if ( OrderSelect( ticket, SELECT_BY_TICKET ) == true )
{
if( OrderCloseTime() != 0 && OrderProfit() < 0 )
{
Print(StringConcatenate("Order #", ticket, " closed by stoploss!");
}
}
这种方法就是判断订单的盈利是小于0来判断的,但是有个问题,就是如果是移动止损,虽然止损了但是有可能是盈利的,这样的就没法判断出来

用OrderComment 函数,每次止损或者止盈后,系统自动给订单加入一个注释,如果是止损就是s/l,判断字符串里包含这个字符串就行了。同理,只赢的就是t/p。

@

有函数能实时地获取订单被止损止赢的信息吗?

比如,对于主动平仓,我可以:

int cc2 =OrderClose(...);

if (cc2>0)...... 知道已平了仓,但对于止损止赢的被动平仓呢?

被平仓的订单 其Comment的属性会被系统自动更改为[ST] 止赢是[TP] 用这个去过滤就知道了!

@

RefreshRates(); 刷新预定义变量和系列数组的数据
是开平仓失败时重新要价的
重新要价是按原来的价格吗?

没准
你手动下单的时候,有时候行情速度太快,会提示你价格已经变动了,是否按照最新价格下单
ea下单也有这个问题,一般都是判断下单失败后,调用一下这函数,刷新一下价格。
挂单一般没这问题

@

取消了指标后,在窗口还留着这些东东的解决办法:

Ctrl+B 用对象列表删除;

点市场报价,拖动一个其它货币对再试试;

@

MODE_STOPLEVEL 停止水平点

它的意思是指是止损位置与入场价格之间的最小点数差距

@

EA下单时有效期expiration参数应怎么写?

此参数是以秒为单位。 下单时用当前的时间(服务器时间或本地时间)加上你计划的期限(以秒计算)即可,例如:

OrderSend (……., TimeCurrent()+Period()*60, ..);

@图形操作用到的函数

创建一个图形,用ObjectCreate,

修改一个图形,用ObjectSet。

@一个返回订单数的子函数

#define MAGICMA 20050610
int CalculateCurrentOrders(string symbol)
{
int buys=0;
int sells=0;

for (int i=0; i<OrdersTotal(); i++)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) ==false)
break;
if ( OrderSymbol() ==Symbol() && OrderMagicNumber() ==MAGICMA)
{
if ( OrderType()==OP_BUY)
buys++;
if ( OrderType()==OP_SELL)
sells++;
}
}
//---- 返回单子数量
if(buys>0)
return(buys);
else
return(-sells);
}

@

怎样将时间相加减,及时间转换的函数
int start()
{

datetime iCurrTime = TimeCurrent();
Print (iCurrTime);
iCurrTime =iCurrTime +6;
Print (iCurrTime);
Print( TimeToStr(TimeCurrent()) );
}

@

SetIndexStyle( index, type, style(可以为空,默认为0), width(可以为空,默认为1), clr=CLR_NONE)

SetIndexBuffer(0,Buffer1); // 为定义的指标变量数组标记索引号。使它们一一对应。

ndicatorShortName("xxxx "); // 当鼠标放在指标上所看到的指标名称。与文件名不相关

if(counted_bars>0) counted_bars--; // 从已经计算的指标中去除最后一条。

@

Low [ ] 是一个数组,里面储存了当前周期图表上每根K线的 L ;

Low[0]是表示当前K线的L 。注意了:它仅储存了当前周期的!

iLow() 用这个函数则可获取其它周期的图表上的某根K线的最低价

@
OP_BUY 是指 买的位置

@

如何在n根柱后关闭订单

if (TimeCurrent() - OrderOpenTime()>600)
{
OrderDelete(order_ticket);
return(0);
}
复制代码不知对不对?

1、获得持仓单的入场时间
2、用iBarShift函数算出入场时对应的K线序号
3、比较这个序号是否大于你说的K线个数

@

调出平行线

先画一条趋势线
然后 双击然后按住ctrl 用左键拖那根线

@报警功能使用方法

如果要休息一会或有事要处理,而这时持有单子,但又无法实时看盘,怎么监测汇价呢?

MT4有一个汇价报警功能,启动MT4,crtl+t,警报。然后在空白处右键鼠标,会出现一个对话框,选择创建,如下图。报警方式选择sound,商品选择你要的货币,条件可以选择买卖价大于小于某个价位,最后选则具体报警价位,执行选项就是各种报警的声音

@

指标文件呈灰色显示的 说明你添加的是EX4文件,没有原码不能修改代码,但不影响使用

@

三种复盘方式的差别


第一个 是你平台上下载到的最精确的价格来模拟,比如有1分钟的,就按1分钟的测试

第二个 是你测试1小时图的话,就按半小时图k线选12个点来测试

第三个 只是开盘价

@

如果在一个价位开了多口买单,而且在另一个价位也开了多口买单,如果遇到开空单条件时,我想平掉第一个价位的一半买单,怎么写呢

两个多单用不同的magic或comment

@

让mt4主图指标在副图显示 [转]

例如:Heiken Ashi是个主图指标,不能直接加到副图,要加到副图需要骗一下MT4,

进入MT4的指标目录MetaTrader\experts\indicators 找到Heiken Ashi.mq4文件,移动到别的文件夹,再找一个副图指标(比如MACD.mq4)改名为Heiken Ashi.mq4 打开MT4,加入Heiken Ashi指标,这时在副图显示的是MACD指标,把这个画面保存模板,关闭MT4,把Heiken Ashi.mq4改回MACD原指标,然后把原来的Heiken Ashi.mq4拷回来,打开MT4,调入你刚才保存的模板,Heiken Ashi就在副图显示了。

@

脚本的写法和EA基本一样,唯一的不同是脚本只运行一次

@

善于使用print作为排错方法,输出关键位置的数值,来帮助自己判断程序是否正确

@

for (int i=Bars; i>=0; i--)

是重新从头到尾(图表最左至右)来循环计算。
这是最不科学的方法!

@

如果EA里没有特别指定使用哪个周期的话,
已打开EA交易时,改变图表,会不会影响EA的使用周期

会,一般指标函数第二个参数是指定时间框,如果它是0,代表用当前的时间周期.如果你改变图表的周期,他就跟着变了

@

开多仓的条件和平空仓的条件一样,那么怎样实现开多仓的同时平空仓呢?
我用了开仓和平仓指令,结果开了的仓,马上又被平了,我该怎么控制平仓时候是平多仓,还是平空仓呢?

注意程序逻辑结构的设计,按以下逻辑设计即可实现先平仓,后反向开仓的目的:

Start开始后,先判断持仓情况
如果空仓状态: 则判断多空单的条件是否满足,如果满足则入场。
如果持仓状态: 则判断出场条件是否满足如果满足则出场。
记住:上述操作后都使用return返回,则下次价格到来的时候就会立刻执行下一步的出场动作。

@

return 意思是结束当前函数的执行。
return(0) 则表示不仅结束当前函数,同时返回数值0给调用当前函数的上一级过程中的指定变量

@

为了尽最大程度消化滑点因素,怎样严格定义订单发送价格? 比如以本周期收盘价格加上[多头]或减去[空头]几个点,在下个周期开始后发送

可以,你要先判断当前价格与你的预想价格的位置关系,然后使用 上挂单 或者下挂单 的方式发送订单指令就行了

@

其实可以在当前图形调用任何时间段的技术指标,方法就是你使用的函数里都有一个TimeFrame参数,这个参数设成你想要的时间段就行了。这样更简单些

@

如果是用数组方式画的箭头,是无法改变大小的。
而用Object方式画箭头只适合与运行开始后的动态画出新箭头,不能追溯历史。(Object中有些比较大的箭头)

@

不知是否一分钟数据太多,我的mt4不能进行backward test了,没有反应,想进1分钟图就死掉, 怎么办好?

有两种可能:
1、历史数据太多。方法: 到History目录里,进入你当前账号所在目录,删掉历史文件
2、图表加载的指标编的的不好,计算量过大。方法:找一下图表上是哪个指标,到indicator目录下将这个指标的ex4删除,然后重新进入MT4看看

@

int counted_bars =IndicatorCounted();
if(counted_bars <0) return(-1);
if(counted_bars >0) counted_bars--;
int limit =Bars -IndicatorCounted();

上面一整段就是为了计算出limit的数值(当前需要计算的K线个数)

为什么要列举一个 if(counted_bars<0) ,难道counted_bars有可能小于0吗?return是返回一个东西给调用当前函数的变量,这里的return(-1)是否理解为返回-1这个值给counted_bars呢?

if(counted_bars<0)这种用法是很严谨的指标编写方法。小于零的情况会有,比如当你打开着一个商品的K线图,然后你换了一个服务器,而这个服务器上并没有这个商品。这时候就是小于零的情况。
关于return 它是返回数值给 调用return所在函数 的变量。 这里的return是在系统函数start里面,所以这里的返回-1不会有任何实际变化, 主要实现的是退出start()的当前这次运算过程。

@

内存占用很大?

首先占用CPU大一定是循环的部分过多, 有可能的原因是你的循环是每次都是“从头到尾”的方式还有就是死循环 或者叫连续出现仓位操作错误

@

解读:

int counted_bars =IndicatorCounted(); // IndicatorCounted()表示当前价格到来后没有发生变化的K线个数

if (counted_bars>0) counted_bars--; // 计算出当前价格到来后需要重新计算的K线个数(从右往左数), 而没有条件限制, 就是计算当前应该进行循环重新计算的K线的个数

@

想返回某个条件的那天(非固定周期),取那天的指标数值如何做到?

关于取特定时间的特定指标的数值。大致思路如下:

1、首先循环计算特定指标的所有历史数据

2、使用iBarShift函数根据指定时间或者那个时间段对应这个时间的K线序列号。

3、根据1已经计算出来的指标数组和2计算得到的序列号,或者指定的指标的数值

@

怎么看未来函数的代码

要看具体程序,例如:如果在循环赋值当前指标数值X的时候,(i是当前K线序列标记)使用了i+1 以后的数据则被视为“未来函数”

@

只想让EA只按照15分钟时间段操作
要放在init中,最好赋值一个全局变量让start函数一开始也做相同的判断
同时最好控制一下Alert一次就行了,要不就光弹窗口了,很烦人的

int 报警次数=0;

//--------------------------------------
int init()
{
if (Period() !=15)
{
Alert("这不是15分钟图表!");
报警次数= 1;
}
return(0);
}

//----------------------------------------
int start()
{
if (报警次数 ==1) return(0);
.........
return(0);
}

@

50分钟内的最高价所对应的那条K线,求这条K线所对应的26均线的值该怎么写?

也就是说找出 iHighest(NULL,0,MODE_HIGH,50,i) 这条K线对应的MA26的值。

iMa( NULL, 0, 26, 0, MODE_SMA, PRICE_CLOSE, iHighest(NULL,0,MODE_HIGH,50,0) )
应用在1分钟图上,或者 指标上的时间段指定为PERIOD_M1
(看到这句,终于明白 better 为什么要用1分钟图输入数据了。)

@

当我用老方法直接合并多空后,相互影响就出现了好几次,导致接下来的开仓位置不合里,从而多出几次止损交易:

进入start函数后首先要进行仓位个数的判断,你所做的分辨不同类型持仓也是在这里进行,然后根据持仓情况分成多种状态进行处理。这样才可以防止重复入场

@

我重新下载了一个MT4,不知为什么自定义指标都不能使用了?

加载不上的原因一般都是程序没通过编译,要编译一下看看什么错误信息

@

TB你还是放弃吧,我们比你更了解他的细节,根本没法和MT4相比,稍微复杂一点的想法都无法实现,而且设计原理上有重大缺陷。

@

@

返回第X根K线上的 YY.MM.DD HH:MM 这段代码该怎么写

例如 变量A= 第5根K线上的日期时间;

Datetime A=Time[X]

如果要找这个K线 用函数 iBarShift

@

如何用帐户函数进行读取仓位入场价

例子:

double GetFirstOrderOpenPrice() //定义子函数
{
int i,j;
for (i=OrdersTotal()-1; i>=0; i--)
{
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if (OrderSymbol() ==Symbol())
{
return(OrderOpenPrice());
}
}
}

@

做EA

1、第一步就是:提取持仓信息并进行判断,以决定当前的状态,然后通过条件语句分配到针对不同状态的具体程序段中。
2、持仓单的区分可以通过 持仓单中的 货币名称 单子类型 甚至Magic 和 Commssion来进行更进一步的细分,从而实现例如:查看当前多少个多单,多少个空单,多少个挂单,总持仓量是多少,最后一个入场单的时间,.....花样出来。
这些技巧就要靠不断的练习来实现。

@通过全局变量可以让某个值在各个函数中传递,各个函数也都可以修改这个变量的值,起到一种互通有无的作用

@

想根据不同的条件开3个仓,还有每个平仓条件也不一样,
现在的问题是,每一段之间是怎么隔开的,平仓是又怎么区别出哪个单子呢?
如ticket= OrderSendExtended(Symbol(), OP_BUYSTOP, Lots, Price, Slippage, sl, tp, setup,(MagicNumber+1),Validity,Green)中,setup 是订单的注释.(MagicNumber+1)是选定的订单的指定编号.接下来呢?


不同条件产生的订单用不同的订单注释标记或者用不同的Magic号码也行。
找出的过程:
循环所有持仓单,找出商品名和当前K线图商品一样并且订单注释等于特定注释的订单Ticket,然后
OrderSelect选择,进行操作就行。

想根据不同的条件开3个仓,还有每个平仓条件也不一样,
现在的问题是,每一段之间是怎么隔开的,平仓是又怎么区别出哪个单子呢?


入场的时候不同条件入场的单子,其Magic设成不同的
这样在需要找哪个入场单的时候,就用同样的循环查找,只不过过滤条件使用的Magic自己选择,就可以找到了。给你一段实例程序,自己理解吧:
for(int i=0; i<OrdersTotal(); i++)
{
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic && OrderType()==OP_SELL)
{
//这里为找到单子后的处理部分
}
}

@

OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)

OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)

有什么区别?

一个根据单号, SELECT_BY_TICKET 表示采用单号操作 ticket就是单号
一个根据单子的位置来操作(时间最前面的编号为1,后面的以此类推2,3,4,5) , SELECT_BY_POS  表示采用序号操作 cnt就是序号

@

MT图表显示的价格线默认为买进价格线,您若想看到卖出价格线可这样进行:

打开MT4,点击F8健,在出现的对话窗口点击常用,把显出卖出价格图前面的勾勾选上。

确认后,点击MT4上面的工具、选项、图表,把显出卖出价格图前面的勾勾选上

@

double Buy1_1 = iMA(NULL, PERIOD_H1, 5, 0, MODE_SMA, PRICE_CLOSE, Current + 0);
double Buy1_2 = iMA(NULL, PERIOD_H1, 13, 0, MODE_SMA, PRICE_CLOSE, Current + 0);

。。。。。。

if (Buy1_1 > Buy1_2 ) Order = SIGNAL_BUY;

之所以有“假叉”和“粘合”,原因不在于程序,而在于我们的肉眼。程序判断交叉哪怕是0.0001的超越都认为发生了交叉。所以在此基础上,我们可以在程序中增加一个判断就是交叉后并距离交叉位置有一定宽度后再视为“有效”。

改后一句:

if ((Buy1_1 - Buy1_2)>=5*Point ) Order = SIGNAL_BUY;

也可:判断条件的时候使用上一根K线的收盘价做计算,而不要用当前未完成的K线收盘价做计算就可以了。

@

for语句:for语句是循环控制结构中使用最广泛的一种循环控制语句。其功能是将某段程序代码反复执行若干次,特别适合已知循环次数的情况。

语句格式:

for (表达式1;表达式2;表达式3)

循环体 {语句序列;}

其中:

表达式1:通常为赋值表达式,用来确定循环结构中的控制循环次数的变量的初始值,实现循环控制变量的初始化。

表达式2:通常为关系表达式或逻辑表达式,用来判断循环是否继续进行的条件,将循环控制变量与某一值进行比较,以决定是否退出循环。

表达式3:通常为表达式语句,用来描述循环控制变量的变化,多数情况下为自增/自减表达式(复合加/减语句),实现对循环控制变量的修改。

循环体(语句序列):当循环条件满足时应该执行的语句序列。可以是简单语句、复合语句。若只有一条语句,则可以省略{}。

执行过程:

1)计算表达式1的值,为循环控制变量赋初值。

2)计算表达式2的值,如果其值为‘真’则执行循环体语句,否则退出循环。执行for循环后的语句。

3)如果执行了循环体语句,则在每一次执行循环体结束时,都要计算一次表达式3的值,调整循环控制变量。之后返回2)步重新计算表达式2的值,依此重复过程,直到表达式2的值为‘假’时,退出循环。

for语句很好的体现了正确表达循环结构应注意的三个问题:循环控制变量的初始化、循环控制的条件以及循环控制变量的更新。

@

报警方式可采用Alert(),也可以采用MessageBox(), 比如if(ihight(,,i)>ihight(,,i-1))MessageBox()

@

如果要统一图形上显示不同时间段的指标,只能换其他方法,具体方法,你可以参考网上_MTF开头的源码指标。这类指标是显示跨时间段的方法

    猜你喜欢
    发表评论评论公约
    喜欢该文的人也喜欢 更多