账户操作的限制和权限
在账户的特性中,有一些是对交易操作的限制,包括完全禁用交易。所有这些特性都属于 ENUM_ACCOUNT_INFO_INTEGER 枚举,并且为布尔标志,ACCOUNT_LIMIT_ORDERS 除外。
标识符
|
说明
|
ACCOUNT_TRADE_ALLOWED
|
允许在当前账户上进行交易
|
ACCOUNT_TRADE_EXPERT
|
允许使用 EA 交易和脚本进行算法交易
|
ACCOUNT_LIMIT_ORDERS
|
有效挂单的最大允许数量
|
ACCOUNT_FIFO_CLOSE
|
仅根据 FIFO 规则进行平仓的要求
|
由于本书为关于 MQL5 编程的指南,其中包括算法交易,所以需要注意的是,当 ACCOUNT_TRADE_ALLOWED 等于 false 时,将全面禁止交易,而禁用 ACCOUNT_TRADE_EXPERT 权限的重要性与之相当。经纪商可禁止使用 EA 交易和脚本进行交易,但允许手动交易。
如果使用投资密码连接到账户,ACCOUNT_TRADE_ALLOWED 特性通常等于 false。
如果 ACCOUNT_FIFO_CLOSE 特性值为 true,则每个交易品种的头寸只能按其开仓时的相同顺序平仓,即首先平仓最旧的订单,然后平仓较新的订单,依此类推,直到最后一个订单。如果试图以不同顺序平仓,则会收到错误。对于没有头寸对冲的账户,即,如果 ACCOUNT_MARGIN_MODE 特性不等于 ACCOUNT_MARGIN_MODE_RETAIL_HEDGING,则 ACCOUNT_FIFO_CLOSE 特性始终为 false。
在 权限 和 交易和报价时段时间表 章节中,我们已经开始开发一个类来检测 MQL 程序可用的交易操作。现在我们可以用账户权限检查作为其补充,并将其完善为最终版本 (Permissions.mqh) 中。
TRADE_RESTRICTIONS 枚举中提供了限制级别,在添加了两个与账户特性相关的新元素后,该枚举采用以下形式。
class Permissions
{
enum TRADE_RESTRICTIONS
{
NO_RESTRICTIONS = 0,
TERMINAL_RESTRICTION = 1, // user's restriction for all programs
PROGRAM_RESTRICTION = 2, // user's restriction for a specific program
SYMBOL_RESTRICTION = 4, // the symbol is not traded according to the specification
SESSION_RESTRICTION = 8, // the market is closed according to the session schedule
ACCOUNT_RESTRICTION = 16, // investor password or broker restriction
EXPERTS_RESTRICTION = 32, // broker restricted algorithmic trading
};
...
|
在检查过程中,由于各种原因,MQL 程序可能会检测到若干限制,因此这些元素由单独的位进行编码。最终结果可以代表它们的叠加状态。
最后两个限制刚好与新特性相对应,并在 getTradeRestrictionsOnAccount 方法中设置。检测到的限制的通用位掩码(如果有的话)在 lastRestrictionBitMask 变量中形成。
private:
static uint lastRestrictionBitMask;
static bool pass(const uint bitflag)
{
lastRestrictionBitMask |= bitflag;
return lastRestrictionBitMask == 0;
}
public:
static uint getTradeRestrictionsOnAccount()
{
return (AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) ? 0 : ACCOUNT_RESTRICTION)
| (AccountInfoInteger(ACCOUNT_TRADE_EXPERT) ? 0 : EXPERTS_RESTRICTION);
}
static bool isTradeOnAccountEnabled()
{
lastRestrictionBitMask = 0;
return pass(getTradeRestrictionsOnAccount());
}
...
|
如果调用代码与限制的原因无关,而只需要确定执行交易操作的可能性,那么使用 isTradeOnAccountEnabled 方法会更方便,该方法可返回一个布尔符号 (true/false)。
交易品种和终端特性的检查已根据类似的原则进行了重新组织。例如,getTradeRestrictionsOnSymbol 方法包含以前版本的类中已经熟悉的源代码(检查交易品种的交易会话和交易模式),但返回一个标志掩码。如果至少有一位被设置,则该方法描述限制的来源。
static uint getTradeRestrictionsOnSymbol(const string symbol, datetime now = 0,
const ENUM_SYMBOL_TRADE_MODE mode = SYMBOL_TRADE_MODE_FULL)
{
if(now == 0) now = TimeTradeServer();
bool found = false;
// checking the symbol trading sessions and setting 'found' to 'true',
// if the 'now' time is inside one of the sessions
...
// in addition to sessions, check the trading mode
const ENUM_SYMBOL_TRADE_MODE m = (ENUM_SYMBOL_TRADE_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE);
return (found ? 0 : SESSION_RESTRICTION)
| (((m & mode) != 0) || (m == SYMBOL_TRADE_MODE_FULL) ? 0 : SYMBOL_RESTRICTION);
}
static bool isTradeOnSymbolEnabled(const string symbol, const datetime now = 0,
const ENUM_SYMBOL_TRADE_MODE mode = SYMBOL_TRADE_MODE_FULL)
{
lastRestrictionBitMask = 0;
return pass(getTradeRestrictionsOnSymbol(symbol, now, mode));
}
...
|
最后,在 getTradeRestrictions 和 isTradeEnabled 方法中执行对所有潜在“实例”的一般检查,包括(除了前面的水平之外)终端和程序的设置。
static uint getTradeRestrictions(const string symbol = NULL, const datetime now = 0,
const ENUM_SYMBOL_TRADE_MODE mode = SYMBOL_TRADE_MODE_FULL)
{
return (TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) ? 0 : TERMINAL_RESTRICTION)
| (MQLInfoInteger(MQL_TRADE_ALLOWED) ? 0 : PROGRAM_RESTRICTION)
| getTradeRestrictionsOnSymbol(symbol == NULL ? _Symbol : symbol, now, mode)
| getTradeRestrictionsOnAccount();
}
static bool isTradeEnabled(const string symbol = NULL, const datetime now = 0,
const ENUM_SYMBOL_TRADE_MODE mode = SYMBOL_TRADE_MODE_FULL)
{
lastRestrictionBitMask = 0;
return pass(getTradeRestrictions(symbol, now, mode));
}
|
脚本 AccountPermissions.mq5 演示了使用新类对交易权限全面检查。
#include <MQL5Book/Permissions.mqh>
void OnStart()
{
PrintFormat("Run on %s", _Symbol);
if(!Permissions::isTradeEnabled()) // checking for current character, default
{
Print("Trade is disabled for the following reasons:");
Print(Permissions::explainLastRestrictionBitMask());
}
else
{
Print("Trade is enabled");
}
}
|
如果发现了限制,可以使用 explainLastRestrictionBitMask 方法以清晰的字符串表示形式显示其位掩码。
以下是一些脚本的结果。在前两种情况下,交易在终端的全局设置中被禁用(特性 TERMINAL_TRADE_ALLOWED 和 MQL_TRADE_ALLOWED 等于 false,对应于 TERMINAL_RESTRICTION 和 PROGRAM_RESTRICTION 位)。
当在市场关闭期间在 USDRUB 上运行时,我们还会收到 SESSION_RESTRICTION:
Trade is disabled for USDRUB following reasons:
TERMINAL_RESTRICTION PROGRAM_RESTRICTION SESSION_RESTRICTION
|
对于完全禁止交易的交易品种 SP500m,会出现 SYMBOL_RESTRICTION 标志。
Trade is disabled for SP500m following reasons:
TERMINAL_RESTRICTION PROGRAM_RESTRICTION SYMBOL_RESTRICTION SESSION_RESTRICTION
|
最后一点,如果已经允许在终端中交易,但已经使用投资者的密码登录账户,我们将在任何交易品种上看到 ACCOUNT_RESTRICTION。
Run on XAUUSD
Trade is disabled for following reasons:
ACCOUNT_RESTRICTION
|
MQL 程序中的早期权限检查有助于避免连续发送交易指令失败的情况。