本章解决2个编程问题:现价交易和挂单交易。
原文讲得很详细,但我只译出两个例程。我觉得,这是高效率学习编程的最好办法。
先看几个相关函数:
函数OrderSend
- int OrderSend (string symbol, int cmd, double volume, double price,
- int slippage, double stoploss,double takeprofit,
- string comment=NULL, int magic=0, datetime expiration=0,
- color arrow_color=CLR_NONE)
OrderSend 返回定单的编号。编号由交易服务器给出,独一无二。若编号为-1,则定单被服务器或客户端拒绝。可通过函数GetLastError()查看拒绝的原因。
symbol 交易对象的名称,用字符串,如"EURUSD",表示“欧元/美元”货币对。在“操盘手”中,可用函数 Symbol()得到交易对象的名称。
cmd 交易操作的类型,分别以内建常量表示。
volume 交易手数。现价交易,必须检查帐户资金是否充足;挂单交易,手数不受限制。
price 建仓(开单)价格。它由定单特点和交易规则确定。
slippage 滑点。能够接受的建仓报价与成交价之间的最大点差。挂单不处理这一参数。
stoploss 止损价(点位)。
takeprofit 止盈价(点位)。
comment 对定单的文字说明。
magic 汇客自定义的定单标识。
expiration 定单期限。
arrow_color 在主图中,标示建仓位置的箭头颜色。若无此参数或其值为 CLR_NONE,则不显示该箭头。
函数MarketInfo
- double MarketInfo(string symbol, int type)
它返回的信息,是MT4终端窗口"Market Watch"中的数据。而当前交易对象的另外一些信息,则保存在预定义变量中。
参数:
symbol - 交易对象的名称;
type - 所要返回的信息类别代号。(参见Function MarketInfo Identifier)。
为了程序运行稳定,最大限度减少交易请求被拒绝,在执行函数OrderSend()之前,应当先用函数MarketInfo()和RefreshRates(),更新相关交易数据。
函数AccountFreeMargin
- double AccountFreeMargin();
返回当前帐户可用的保证金数额。
函数MathFloor
- double MathFloor(
- double val // 数字
- );
参数
val 数值
返回值 小于或等于val的最大整数
注意 可用函数floor()代替MathFloor()
函数RefreshRates
返回值 数据得到更新返回True,否则,返回false。
说明 在“操盘手”或脚本中,刷新预定义变量和时序数组。
函数GetLastError
返回值 返回MQL4程序运行时,最新发生的错误。
说明 本函数被调用后,内建变量 _LastError 没有重设。若需重设,调用函数ResetLastError()。
函数WindowPriceOnDropped
- double WindowPriceOnDropped();
返回值 “操盘手”或脚本运行的主图窗口价格点位。只有用鼠标将它俩拖拉到主图中,数值才为有效。
说明 外建指标没有此值。
一、现价交易
- //-------------------------------------------------------------------------------
- // openbuy.mq4
- // 代码仅用于教学
- //-------------------------------------------------------------------------- 1 --
- int start() // 特别函数 start
- {
- int Dist_SL =10; // 设定止损价位 10 点
- int Dist_TP =3; // 设定止盈价位 3 点
- double Prots=0.35; // 使用 35% 的保证金
- string Symb=Symbol(); // 交易对象名称
- //-------------------------------------------------------------------------- 2 --
- while(true) // 建仓过程的循环
- {
- int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);// 交易允许的止损/止盈最小点位
- double Min_Lot=MarketInfo(Symb,MODE_MINLOT);// 交易允许的最小手数
- double Step =MarketInfo(Symb,MODE_LOTSTEP);//交易允许的手数变化幅度
- double Free =AccountFreeMargin(); // 保证金
- double One_Lot=MarketInfo(Symb,MODE_MARGINREQUIRED);//每买进一手所需保证金
- //-------------------------------------------------------------------- 3 --
- double Lot=MathFloor(Free*ProtsOne_LotStep)*Step;// 总手数
- if (Lot < Min_Lot) // 若总手数小于允许的下限
- {
- Alert(" Not enough money for ", Min_Lot," lots");
- break; // 退出循环
- }
- //-------------------------------------------------------------------- 4 --
- if (Dist_SL < Min_Dist) // 止损点位小于允许的最小值
- {
- Dist_SL=Min_Dist; // 设定最小止损位
- Alert(" Increased the distance of SL = ",Dist_SL," pt");
- }
- double SL=Bid - Dist_SL*Point; // 确定交易的止损价位
- // Bid 系统内建变量:当前交易品种的最新买价
- // Point 系统内建变量:报价小数部分的值
-
- //-------------------------------------------------------------------- 5 --
- if (Dist_TP < Min_Dist) // 止盈点位小于允许的最小值
- {
- Dist_TP=Min_Dist; // 设定最小止盈位
- Alert(" Increased the distance of TP = ",Dist_TP," pt");
- }
- double TP=Bid + Dist_TP*Point; // 确定交易的止盈价位
-
- // Bid 系统内建变量:当前交易品种的最新买价
-
- // Point 系统内建变量:报价小数部分的值
-
- //-------------------------------------------------------------------- 6 --
- Alert("The request was sent to the server. Waiting for reply..");
- int ticket=OrderSend(Symb, OP_BUY, Lot, Ask, 2, SL, TP);
-
- //-------------------------------------------------------------------- 7 --
- if (ticket>0) // 交易成功! :)
- {
- Alert ("Opened order Buy ",ticket);
- break; // 退出循环
- }
- //-------------------------------------------------------------------- 8 --
- int Error=GetLastError(); // 交易失败 :(
- switch(Error) // 可以克服的错误
- {
- case 135:Alert("The price has changed. Retrying..");
- RefreshRates(); // 更新数据
- continue; // 继续循环
- case 136:
- Alert("No prices. Waiting for a new tick..");
- while(RefreshRates()==false) // 获得新报价
- Sleep(1); // 延迟循环
- continue; // 继续循环
- case 146:Alert("Trading subsystem is busy. Retrying..");
- Sleep(500); // 简单处理方案
- RefreshRates(); // 更新数据
- continue; // 继续循环
- }
- switch(Error) // 致命错误
- {
- case 2 :
- Alert("Common error.");
- break; // 退出本 'switch'
- case 5 :
- Alert("Outdated version of the client terminal.");
- break; // 退出本 'switch'
- case 64:
- Alert("The account is blocked.");
- break; // 退出本 'switch'
- case 133:
- Alert("Trading forbidden");
- break; // 退出本 'switch'
- default:
- Alert("Occurred error ",Error);// 其他错误
- }
- break; // 退出循环
- }
- //-------------------------------------------------------------------------- 9 --
- Alert ("The script has completed its operations ---------------------------");
- return; // 退出 start()
- }
- //-------------------------------------------------------------------------- 10 --
二、挂单交易
- //------------------------------------------------------------------------------------
- // openbuystop.mq4
- // 代码仅用于教学
- //------------------------------------------------------------------------------- 1 --
- int start() // 特别函数 start
- {
- int Dist_SL =10; // 设定止损位 10 个点
- int Dist_TP =3; // 设定止盈位 3 个点
- double Prots=0.35; // 交易使用35%的保证金
- string Symb=Symbol(); // 交易对象名称
- double Win_Price=WindowPriceOnDropped(); // 脚本被拖拉进的窗口,价格点位
- Alert("The price is set by the mouse as Price = ",Win_Price);// 点击鼠标设定的价格
- //------------------------------------------------------------------------------- 2 --
- while(true) // 建仓过程循环
- {
- int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);// 最小止损/止盈点位
- double Min_Lot=MarketInfo(Symb,MODE_MINLOT);// 最小交易手数
- double Free =AccountFreeMargin(); // 保证金
- double One_Lot=MarketInfo(Symb,MODE_MARGINREQUIRED);//每手所需保证金
- double Lot=MathFloor(Free*ProtsOne_LotMin_Lot)*Min_Lot;// 总手数
- //------------------------------------------------------------------------- 3 --
- double Price=Win_Price; // 点击鼠标设定的价格
- if (NormalizeDouble(Price,Digits)< // 若小于下限
- NormalizeDouble(Ask+Min_Dist*Point,Digits))
- { // 仅可 BuyStop 挂单!
- Price=Ask+Min_Dist*Point; // 没有平仓
- Alert("Changed the requested price: Price = ",Price);
- }
- //------------------------------------------------------------------------- 4 --
- double SL=Price - Dist_SL*Point; // 止损报价
- if (Dist_SL < Min_Dist) // 若低于下限
- {
- SL=Price - Min_Dist*Point; // 以下限为止损点位
- Alert(" Increased the distance of SL = ",Min_Dist," pt");
- }
- //------------------------------------------------------------------------- 5 --
- double TP=Price + Dist_TP*Point; // 止盈报价
- if (Dist_TP < Min_Dist) // 若低于下限
- {
- TP=Price + Min_Dist*Point; // 以下限为止盈点位
- Alert(" Increased the distance of TP = ",Min_Dist," pt");
- }
- //------------------------------------------------------------------------- 6 --
- Alert("The request was sent to the server. Waiting for reply..");
- int ticket=OrderSend(Symb, OP_BUYSTOP, Lot, Price, 0, SL, TP);
- //------------------------------------------------------------------------- 7 --
- if (ticket>0) // 服务器接受挂单!:)
- {
- Alert ("Placed order BuyStop ",ticket);
- break; // 退出挂单
- }
- //------------------------------------------------------------------------- 8 --
- int Error=GetLastError(); // 挂单被拒绝 :(
- switch(Error) // 可克服的错误
- {
- case 129:Alert("Invalid price. Retrying..");
- RefreshRates(); // 更新数据
- continue; // 继续
- case 135:Alert("The price has changed. Retrying..");
- RefreshRates(); // 更新数据
- continue; // 继续
- case 146:Alert("Trading subsystem is busy. Retrying..");
- Sleep(500); // 简单处理方案
- RefreshRates(); // 更新数据
- continue; // 继续
- }
- switch(Error) // 致命错误
- {
- case 2 : Alert("Common error.");
- break; // 退出本 'switch'
- case 5 : Alert("Outdated version of the client terminal.");
- break; // 退出本 'switch'
- case 64: Alert("The account is blocked.");
- break; // 退出本 'switch'
- case 133:Alert("Trading fobidden");
- break; // 退出本 'switch'
- default: Alert("Occurred error ",Error);// 其他错误
- }
- break; // 退出挂单
- }
- //------------------------------------------------------------------------------- 9 --
- Alert ("The script has completed its operations -----------------------------");
- return; // 退出 start()
- }
- //------------------------------------------------------------------------------- 10 --
|