本章解决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
bool RefreshRates();
返回值 数据得到更新返回True,否则,返回false。
说明 在“操盘手”或脚本中,刷新预定义变量和时序数组。
函数GetLastError
int 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 --