
研究PrintFormat()并应用现成的示例
在日志或监视器屏幕上显示数值是一种简单而熟悉的操作,除非您需要显示比“你好,世界”更复杂的内容。但是,当您需要对不经常需要的值或属性进行格式化输出时,迟早会出现这种情况。当然,您可以查看MQL5的帮助。
但有时你想要一个现成的资料集合,用于显示MetaTrader 5终端提供的各种信息。在本文中,我们将尝试理解调用PrintFormat函数的复杂性,并编写现成的模板,您只需将其插入代码即可。
目录
- 概述
- PrintFormat(). 工作原理
- 帐户属性的格式化显示
- 显示整数帐户属性
- 显示真实帐户属性
- 账户余额
- 帐户信用
- 当前利润
- 账户净值
- 保留担保
- 可用于开仓的空闲资金
- 账户的保证金水平(%)
- 追加保证金担保水平
- 保证金停止水平
- 用于支付挂单保证金的账户预留金额
- 账户上保留以保证最低未平仓金额的最低净值
- 资产规模
- 负债金额
- 冻结的佣金
- 显示字符串帐户属性
- 客户名称
- 交易服务器名称
- 存款货币名称
- 为账户提供服务的公司名称
- 将所有帐户数据打印到日志的函数
- 从分时属性开始的时间(以毫秒为单位)
- 结论
概述
在终端中运行的任何应用程序都应该能够向用户通知其状态及其环境的状态。这些数据总是打印在程序日志中,您可以在交易终端的专家选项卡中找到。随后,在解析和分析程序日志时,重要的是所有条目都要采用易于阅读的形式,因为阅读和搜索信息的容易程度取决于此。
MQL5语言具有Print()函数,该函数将行或转换为行的数据打印到日志中。这对于短日志记录来说已经足够了。但是,如果我们向日志发送大量数据,那么最好以易于理解的形式对它们进行格式化。
当数据头(描述)及其相应的值在没有任何格式的情况下写入一行时,在短列表中读取这些数据不会造成困难。然而,如果有很多数据,并且它们都相互连接,具有不同长度的描述和含义,那么所有这些都会变成一长串信息。建议对此类数据进行格式化,并将其转换为单一的表格形式,其中所有标题都具有相同的宽度(标题列),并且与标题对应的数据将位于与标题(数据列)相同的距离处。PrintFormat()正可以这样做。它按照指定的格式将字符和数值集格式化并打印到EA日志中。
PrintFormat(). 工作原理
PrintFormat()函数输入接收一个格式字符串,该字符串描述了数据应该以何种形式显示,以及一组与格式字符串相对应的数据,这些数据将根据它们在日志中的显示方式位于结果字符串中。您可以为每个值设置自己的输出格式。简单来说,它看起来是这样的:
("%Value1要这样显示%Value2要这样显示%Value3要这样显示 ... ... %ValueN要这样显示 一些文本", Value1, Value2, Value3, ... ..., ValueN)
正如您所看到的,在需要在文本中显示某些数据的地方,应该有描述显示输出数据值的方法的格式行。每个格式字符串的前面都有%,这表明下面是输出格式的描述。您可以在格式描述之间编写任何文本(在上面的示例中,“一些文本”位于末尾)。在完成具有格式字符和文本的行的输入后,数据以逗号分隔,其顺序是在格式行中为它们描述输出格式。在上面的例子中,每个格式描述及其相应的值都用相同的颜色标记。
首先,我们写出应该显示在日志中的文本。接下来,在文本中,如果数据应该位于此位置,就输入数据输出格式的符号。
例如: ("%这些文本将位于50个字符宽度的列中%这些double 数据应该在下一列并且向左对齐", string_variable_with_text_of_the_first_column, double data_of_the_second_column);
当然,您不需要文本来描述这一切,因为有特殊格式的字符。它们应该按照严格指定的顺序进行,但不是所有的都应该出现在格式行中。
格式字符串是从左到右读取的。当遇到第一个格式规范(如果有)时,根据给定规范转换和显示格式字符串后的第一个参数的值。第二个格式规范引出第二个参数被转换和显示,依此类推,直到格式字符串结束。
格式规范具有以下形式:
%[flags][width][.precision][{h | l | ll | I32 | I64}]type
让我们看看格式字符串中每个项目的帮助中写了什么,并对其进行更详细的描述。
百分比符号(%)--开始一个新的格式字符串。在此符号之后,必须至少指定一个说明符,并且必须了解类型说明符(<b1>类型</b1>)是格式化输出所需的唯一字段。也就是说,如果在一行中输入了“%”符号,则必须在其后面指示在此位置显示的数据类型,或者是另一个百分号,以便在文本中写入“%”号,要表明这不是新格式行的开始,而只是文本中的一个百分比符号,您需要编写组合:“%%”。
标志(flags):
- -(减号),行文本将在指定的宽度内左对齐。宽度由标志后面的宽度说明符指定。“%-10”表示文本将与字段的左边缘对齐,该字段宽10个字符。这一行中的下一个文本将从10个字符的同一字段的右边缘开始定位。如果此10个字符字段中显示的文本大于10个字符,则以下文本将位于文本的末尾,而不是字段。换句话说,字段的宽度将扩展到其中放置的文本的大小。文本不会沿着字段的宽度进行修剪,相反,字段会沿着文本的长度展开。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- First line with a header of less than 10 characters and data in 20-character fields //--- The header and data are pressed to the left edge of their field header="10characters"; value1=10000000; value2=20000000; PrintFormat("%-10s%-20ld%-20lld",header,(int)value1,(long)value2); //--- Second line with a header of more than 10 characters and data in 20-character fields //--- The header and data are pressed to the left edge of their field header="Over10characters"; value1=10000000; value2=20000000; PrintFormat("%-10s%-20ld%-20lld",header,(int)value1,(long)value2); /* Sample output: 10characters10000000 20000000 Over10characters10000000 20000000 */ }
- +(加号),对于带符号的类型,根据输出数据的值,始终显示+或-符号。例如:+222或-12.35。如果格式化文本的两行是连续的,而在同一数据列的顶行中,输出数据的值是正的,在底行中是负的,那么在视觉上,这些值将相对彼此移动一个字符(通过“-”号)。下面我们将探讨一个消除这种视觉不便的标志。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%-+20ld%-20lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%-+20ld%-20lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 20000000 Header2 +10000000 -20000000 */ }
- 0 (零),在指定的字段宽度内,零被添加到输出值之前。如果标志0是用整数格式(i,u,x,x,o,d)指定的,并且设置了精度规范(例如%04.d),则0将被忽略。换句话说,对于给定精度格式(至少输出这么多字符)的整数类型,这种格式(格式0)的前导零没有优先级,因为它们填充了整个字段,这与精度格式相矛盾。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs //--- The data values of the third field are pressed to the right edge with leading zeros added. header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%-+20ld%020lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs //--- The data values of the third field are pressed to the right edge with leading zeros added. header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%-+20ld%020lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 00000000000020000000 Header2 +10000000 -0000000000020000000 */ }
- (空格),如果输出值为带符号且为正,则输出值前面会有一个空格。具有此标志的字段的每个正数据值向右移动一个字符。这允许我们在同一列中不同行中存在正值和负值的情况下直观地对齐值,放置空格而不是负数数据的“-”字符。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the third field are pressed to the right edge //--- For the second and third fields from the left, a space is added for positive values. header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%- 20ld% 20lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the third field are pressed to the right edge //--- For the second and third fields from the left, a space is added for positive values. header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%- 20ld% 20lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 20000000 Header2 10000000 -20000000 */ }
- # 井号.
1. 当与o、x或x格式一起使用时,则在输出值之前分别添加0、0x或0x
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- First line with a header and data in 16-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed in decimal format //--- Data values of the third field are displayed in octal format with 0 added before the value header="Header1"; value1=10000; value2=10000; PrintFormat("%-16s(DEC) %-16ld(OCT) %-#16lo",header,(uint)value1,(uint)value2); //--- Second line with header and data in 16-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed in hexadecimal format with 0x added before the value //--- Data values of the third field are displayed in hexadecimal format with 0X added before the value header="Header2"; value1=10000; value2=10000; PrintFormat("%-16s(hex) %-#16lx(HEX) %-#16lX",header,(uint)value1,(uint)value2); /* Sample output: Header1 (DEC) 10000 (OCT) 023420 Header2 (hex) 0x2710 (HEX) 0X2710 */ }
2. 当与e、e、a或a格式一起使用时,该值总是以小数点输出。void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'e' format //--- Data values of the third field are displayed together with the 'E' format header="Header1"; value1=255; value2=1024; PrintFormat("%-16s(e) %-22e(E) %-#22E",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format //--- Data values of the third field are displayed together with the 'A' format header="Header2"; value1=255; value2=1024; PrintFormat("%-16s(a) %-#22a(A) %-#22A",header,(double)value1,(double)value2); /* Sample output: Header1 (e) 2.550000e+02 (E) 1.024000E+03 Header2 (a) 0x1.fe00000000000p+7 (A) 0X1.0000000000000P+10 */ }
3. 当与g或g格式一起使用时,该标志确定输出值中是否存在小数点,并防止截断前导零。g格式选择最紧凑类型的显示f或e,并以所选格式显示条目。G格式与G格式相同,但可在f和E格式之间进行选择。void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with default precision //--- Data values of the third field are displayed together with the 'g' format header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-16s(f) %-22f(g) %-#22g",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 5-character precision //--- Data values of the third field are displayed together with the 'G' format header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-16s(f) %-#22.5f(G) %-#22G",header,(double)value1,(double)value2); /* Sample output: Header1 (f) 0.000010 (g) 1.79769e+308 Header2 (f) 0.00001 (G) 1.79769E+308 */ }
当与格式c、d、i、u和s一起使用时,将忽略#标志。
宽度说明符(width)。要打印的格式化值的最小字符数。我们已经与上面的标志一起讨论了宽度说明符的工作,有一个有趣的细微差别:如果指定星号(*号)作为宽度值,则列表中指定的值和数据应替换星号:
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a *-character field (16) and data in *-character fields (22) //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with default precision //--- Data values of the third field are displayed together with the 'g' format header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-*s(f) %-*f(g) %-#*g",16,header,22,(double)value1,22,(double)value2); //--- The second line with a header in a *-character field (16) and data in *-character fields (22) //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 5-character precision //--- Data values of the third field are displayed together with the 'G' format header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-*s(f) %-#*.5f(G) %-#*G",16,header,22,(double)value1,22,(double)value2); /* Sample output: Header1 (f) 0.000010 (g) 1.79769e+308 Header2 (f) 0.00001 (G) 1.79769E+308 */ }
在这个例子中,输出与上一个没有什么不同,但这里我们将每个字段的宽度指定为值列表中的数字参数。如果表格显示在一个函数内,我们可以将表格每列的宽度值传递到该函数中,这将非常方便。它们将被替换为格式字符串中的星号。
精度说明符(.precision)。小数点后的位数。精度规格可以修剪部分分数值(带或不带舍入)。
对于不同格式的类型(type),精度规范以不同方式应用:
- a,A。指定小数点后的位数。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format with default precision //--- Data values of the third field are displayed together with the 'A' format with default precision header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-16s(a) %-22a(A) %-#22A",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format with 5-character precision //--- Data values of the third field are displayed together with the 'A' format with 7-character precision header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-16s(a) %-#22.5a(A) %-#22.7A",header,(double)value1,(double)value2); /* Sample output: Header1 (a) 0x1.4f8b588e368f1p-17 (A ) 0X1.FFFFFFFFFFFFFP+1023 Header2 (a) 0x1.4f8b6p-17 (A) 0X2.0000000P+1023 */ }
- d, i, u, o, x, X. 指定显示的最小位数。如果相应参数中的位数小于指定的精度,则输出值在左侧补零。如果输出位数大于指定的精度,则不会截断显示的值。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'd' format with 4-character precision //--- Data values of the third field are displayed together with the 'i' format with 11-character precision header="Header1"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(d) %-22.4d(i) %-#22.11i",header,(int)value1,(int)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'u' format with 4-character precision //--- Data values of the third field are displayed together with the 'o' format with 11-character precision header="Header2"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(u) %-#22.4u(o) %-#22.11o",header,(double)value1,(double)value2); //--- The third line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'x' format with 4-character precision //--- Data values of the third field are displayed together with the 'X' format with 11-character precision header="Header3"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(x) %-#22.4x(X) %-#22.11X",header,(double)value1,(double)value2); /* Sample output: Header1 (d) 2147483647 (i) 02147483647 Header2 (u) 4290772992 (o) 037760000000 Header3 (x) 0xffc00000 (X) 0X000FFC00000 */ }
- e, E, f. 指定小数点后显示的位数。最后一位显示的数字为四舍五入。
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'e' format with 4-character precision //--- Data values of the third field are displayed together with the 'E' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=DBL_MAX; PrintFormat("%-16s(e) %-22.4e(E) %-#22.11E",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 4-character precision //--- Data values of the third field are displayed together with the 'f' format with 11-character precision header="Header2"; value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK); value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(f) %-#22.4f(f) %-#22.11f",header,(double)value1,(double)value2); /* Sample output: Header1 (e) 1.7977e+308 (E) 1.79769313486E+308 Header2 (f) 1.2729 (f) 1.27286000000 */ }
- g, G. 指定最大有效位数
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 'G' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-22.4g(G) %-#22.11G",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 'G' format with 11-character precision header="Header2"; value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK); value2=DBL_MAX; PrintFormat("%-16s(g) %-#22.4g(G) %-#22.11G",header,(double)value1,(double)value2); /* Sample output: Header1 (g) 1.798e+308 (G) 1.2731600000 Header2 (g) 1.273 (G) 1.7976931349E+308 */ }
请记住最大有效位数并不意味着小数位数。这里会考虑数字的所有数位。如果指定的位数深度是4位,在digits()值为5的情况下,我们将看不到价格值小数点后的四位数字。在这个例子中,我们只看到<s1>小数点后三位<s1>(<s2>1。<s2><s3>273)<s3>,因为这里的数字的第四位是<s4>小数点前的数字。 - s. 显示的行字符数。如果行长度超过精度值,则在输出过程中截断该行。
void OnStart() { //--- //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 's' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-22.4g(s) %-#22.11s",header,(double)value1,(string)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 5-character precision //--- Data values of the third field are displayed together with the 's' format with 4-character precision header="Header2"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-#22.5g(s) %-#22.4s",header,(double)value1,(string)value2); /* Sample output: Header1 (g) 1.798e+308 (s) 1.2872 Header2 (g) 1.7977e+308 (s) 1.28 */ }
数据大小说明符(h|l|ll|I32|I64)。指定作为参数传递的整数数据的大小。我们可以通过传递一个整数作为参数来指定此数据的大小(int、uint、short、ushort、long、ulong)。以下是大小说明符和数据类型之间的兼容性表:
数据大小 | 大小说明符 | 类型说明符 |
---|---|---|
short | h | d, i, o, x, X |
ushort | h | u, o, x, X |
int | l (小写 L), I32 | d, i, o, x, X |
uint | l (小写 L), I32 | u, o, x, X |
long | ll (两个小写 Ls), I64 | d, i, o, x, X |
ulong | I64 | u, o, x, X |
数据类型说明符(type) 。格式化输出所需的唯一字段。
符号 | 类型 | 格式 |
---|---|---|
c | int | 短整型符号(Unicode) |
C | int | 字符型符号 |
d | int | 有符号十进制整数 |
i | int | 有符号十进制整数 |
o | int | 无符号八进制整数 |
u | int | 无符号十进制整数 |
x | int | 使用“abcdef”的无符号十六进制整数 |
X | int | 使用“ABCDEFEF”的无符号十六进制整数 |
e | double | [–]d.dddd e[sign]ddd格式的实数,其中d是一个十进制数字,dddd是一个或多个十进制数字。ddd是定义指数大小的三位数,而“sign”是加号或减号 |
E | double | 与e格式相同,只是指数符号大写(E而不是e) |
f | double | 一个[–]dddd.dddd格式的实数,其中dddd是一个或多个十进制数字。小数点前显示的位数取决于数字的值。小数点后的位数取决于所需的精度。 |
g | double | f或e格式的实值输出,具体取决于哪种输出更紧凑。 |
G | double | f或E格式的实值输出,具体取决于哪种输出更紧凑。 |
a | double | 一个[−]0xh.hhhh p±dd格式的实数,其中h.hhhhh是使用“abcdef”的十六进制数字的尾数,dd是一个或多个指数数字。小数位数由精度规格决定 |
A | double | 一个[−]0xh.hhhh P±dd格式的实数,其中h.hhhhh是使用“ABCDEF”的十六进制数字的尾数,dd是一个或多个指数数字。小数位数由精度规格决定 |
s | 字符串 | 行输出 |
数据类型允许我们指定要在终端日志中接收条目的形式。例如,当使用“c”或“C”类型时,输出为一个字符。参数传递的值指定该字符的Unicode或ANSI表代码,而与其他类型说明符一起使用相同的值将以所选格式显示参数值本身,但不显示字符:
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header char value1=0; // First value char value2=0; // Second value //--- The first line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'c' format //--- Data values of the third field are displayed together with the 'C' format header="Header1"; value1=65; value2=66; PrintFormat("%-16s(c) %-10c(C) %-10C",header,(char)value1,(char)value2); //--- The second line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'c' format //--- Data values of the third field are displayed together with the 'C' format header="Header2"; value1=67; value2=68; PrintFormat("%-16s(c) %-10c(C) %-10C",header,(char)value1,(char)value2); //--- The third line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'd' format //--- Data values of the third field are displayed together with the 'i' format header="Header3"; value1=65; value2=66; PrintFormat("%-16s(d) %-10d(i) %-10i",header,(int)value1,(int)value2); /* Sample output: Header1 (c) A (C) B Header2 (c) C (C) D Header3 (d) 65 (i) 66 */ }
我们简要介绍了日志中显示的文本的所有格式说明符,让我们使用显示交易账户属性的特定示例来看看这是什么样子的。
帐户属性的格式化显示
我们可以分别使用AccountInfoInteger()、AccountInfoDouble()和AccountInfoString()函数来获得整数、实数和字符串属性。
并非总是需要显示所有特性的完整列表,因此,对于每个属性,我们将制作一个函数,在日志中打印该属性的描述。之后,就可以从现成的函数中组装任何函数,将所需的属性(全部或选定的属性)发送到日志。
我们将向函数传递两个参数——标题字段的宽度和标题字段从左边缘开始的缩进。让我们按以下顺序开始:整数、实数和最后的字符串属性。
用于打印整数帐户属性的函数。
账号:
//+------------------------------------------------------------------+ //| Print a description of the account number into the journal | //+------------------------------------------------------------------+ void AccountLoginPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Login:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LOGIN)); /* Sample output: Login: 68008618 */ }
在格式字符串中,首先用星号指示从左边缘开始的行缩进的大小。在行参数中,传递缩进字段的大小(代替星号)和字符串值-一个空字符串(代替s字符)。
“%*s”格式根据字符串参数中也传递的缩进值,用空格补充参数中传递的空字符串。因此,可以方便地从所需大小的行中的空格字符中生成任何空字段。然后,在格式行中,我们还用星号指示标题字段的大小,在其位置传递w变量的值,并在header变量中传递标题行。最后一个参数是AccountInfoInteger()中的帐户索引值,作为一行。
交易账户类型:
//+------------------------------------------------------------------+ //| Print a trading account type into the journal | //+------------------------------------------------------------------+ void AccountTradeModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the trading account type ENUM_ACCOUNT_TRADE_MODE trade_mode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE); //--- "Cut out" the name of the trading account type from the line obtained from enum string mode=StringSubstr(EnumToString(trade_mode),19); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Trade mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: Trade mode: Demo */ }
杠杆大小:
//+------------------------------------------------------------------+ //| Print a description of the provided leverage size in the journal | //+------------------------------------------------------------------+ void AccountLeveragePrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Leverage:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s1:%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LEVERAGE)); /* Sample output: Leverage: 1:100 */ }
最大订单数:
//+------------------------------------------------------------------+ //| Print a description of the maximum allowed | //| number of active pending orders | //+------------------------------------------------------------------+ void AccountLimitOrdersPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Limit orders:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS)); /* Sample output: Limit orders: 200 */ }
最小担保模式:
//+------------------------------------------------------------------+ //| Print a description of the mode for setting a minimal | //| accepted level of collateral in the journal | //+------------------------------------------------------------------+ void AccountMarginSOModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the mode for setting the minimum available collateral ENUM_ACCOUNT_STOPOUT_MODE so_mode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); //--- "Cut out" the mode name from the line obtained from enum string mode=StringSubstr(EnumToString(so_mode),21); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="StopOut mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: StopOut mode: Percent */ }
允许账户交易:
//+------------------------------------------------------------------+ //| Print a description | //| of allowing trading for the current account in the journal | //+------------------------------------------------------------------+ void AccountTradeAllowedPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Trade allowed:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) ? "Yes" : "No")); /* Sample output: Trade allowed: Yes */ }
EA的交易权限:
//+------------------------------------------------------------------+ //| Print a description | //| allowing trading for an EA | //+------------------------------------------------------------------+ void AccountTradeExpertPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Trade expert:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT) ? "Yes" : "No")); /* Sample output: Trade expert: Yes */ }
保证金计算模式:
//+------------------------------------------------------------------+ //| Print a description of the margin calculation mode in the journal| //+------------------------------------------------------------------+ void AccountMarginModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the margin calculation mode ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); //--- "Cut out" the mode name from the line obtained from enum string mode=StringSubstr(EnumToString(margin_mode),20); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(mode,"_"," "); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: Margin mode: Retail hedging */ }
帐户货币的小数位数:
//+------------------------------------------------------------------+ //| Print a description of the number of | //| decimal places for an account currency | //+------------------------------------------------------------------+ void AccountCurrencyDigitsPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Currency digits:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS)); /* Sample output: Currency digits: 2 */ }
FIFO规则关闭仓位的标志:
//+------------------------------------------------------------------+ //| Print a description of the flag indicating | //| that positions can only be closed using the FIFO rule | //+------------------------------------------------------------------+ void AccountFIFOClosePrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="FIFO close:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_FIFO_CLOSE) ? "Yes" : "No")); /* Sample output: FIFO close: No */ }
允许交易品种的反向仓位:
//+------------------------------------------------------------------+ //| Print a description of the flag indicating | //| opposite positions are allowed on a single symbol | //+------------------------------------------------------------------+ void AccountHedgeAllowedPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Hedge allowed:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_HEDGE_ALLOWED) ? "Yes" : "No")); /* Sample output: Hedge allowed: Yes */ }
用于打印真实帐户属性的函数。
帐户余额:
//+------------------------------------------------------------------------------------+ //| Print a description of the account balance in the deposit currency in the journal | //+------------------------------------------------------------------------------------+ void AccountBalancePrint(const uint header_width=0,const uint indent=0) { //--- Get the balance, the number of decimal places for the symbol and its name double ballance=AccountInfoDouble(ACCOUNT_BALANCE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Balance:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,ballance,currency); /* Sample output: Balance: 10015.00 USD */ }
帐户信用:
//+------------------------------------------------------------------+ //| Print a description of account credit size | //| in a deposit currency | //+------------------------------------------------------------------+ void AccountCreditPrint(const uint header_width=0,const uint indent=0) { //--- Get the credit, the number of decimal places for the symbol and its name double credit=AccountInfoDouble(ACCOUNT_CREDIT); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Credit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,credit,currency); /* Sample output: Credit: 0.00 USD */ }
账户的当前利润:
//+------------------------------------------------------------------+ //| Print a description | //| of the current profit in the deposit currency | //+------------------------------------------------------------------+ void AccountProfitPrint(const uint header_width=0,const uint indent=0) { //--- Get the current profit, the number of decimal places for the symbol and its name double profit=AccountInfoDouble(ACCOUNT_PROFIT); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Profit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,profit,currency); /* Sample output: Profit: 0.00 USD */ }
账户净值:
//+------------------------------------------------------------------+ //| Print a description of the value of | //| equity on an account in a deposit currency | //+------------------------------------------------------------------+ void AccountEquityPrint(const uint header_width=0,const uint indent=0) { //--- Get the equity, the number of decimal places for the symbol and its name double equity=AccountInfoDouble(ACCOUNT_EQUITY); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Equity:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,equity,currency); /* Sample output: Equity: 10015.00 USD */ }
保留担保:
//+------------------------------------------------------------------+ //| Print a description of | //| reserved collateral funds on the account in a deposit currency | //+------------------------------------------------------------------+ void AccountMarginPrint(const uint header_width=0,const uint indent=0) { //--- Get the reserved collateral, the number of decimal places for the symbol and its name double margin=AccountInfoDouble(ACCOUNT_MARGIN); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin,currency); /* Sample output: Margin: 0.00 USD */ }
可用于开仓的可用自由资金:
//+--------------------------------------------------------------------------------------+ //| Print a description of the free funds, | //| available for opening a position on an account in a deposit currency, in the journal | //+--------------------------------------------------------------------------------------+ void AccountMarginFreePrint(const uint header_width=0,const uint indent=0) { //--- Get the reserved collateral, the number of decimal places for the symbol and its name double margin_free=AccountInfoDouble(ACCOUNT_MARGIN_FREE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin free:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_free,currency); /* Sample output: Margin free: 10015.00 USD */ }
账户的担保金水平百分比:
//+------------------------------------------------------------------+ //| Print a description | //| of the collateral level on an account in % | //+------------------------------------------------------------------+ void AccountMarginLevelPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin level:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- The value is set with 'digits' equal to 2 and the fact that the property is displayed in % is specified PrintFormat("%*s%-*s%-.2f %%",indent,"",w,header,AccountInfoDouble(ACCOUNT_MARGIN_LEVEL)); /* Sample output: Margin level: 0.00 % */ }
追加保证金通知担保水平:
//+----------------------------------------------------------------------------+ //| Print a description of the collateral level, | //| at which a deposit to an account is required (Margin Call), in the journal | //+----------------------------------------------------------------------------+ void AccountMarginSOCallPrint(const uint header_width=0,const uint indent=0) { //--- Get the MarginCall level values, the number of decimal places for the symbol and its name double margin_so_call=AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- If the level of collateral for MarginCall is calculated as %, //--- specify 'currency' in % rather than in account currency, while 'digits' will be equal to 2 if(AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE)==ACCOUNT_STOPOUT_MODE_PERCENT) { currency="%"; digits=2; } //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin Call:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value obtained above PrintFormat("%*s%-*s%-.*f %s",indent,"",w,header,digits,margin_so_call,currency); /* Sample output: Margin Call: 50.00 % */ }
保证金停损水平:
//+------------------------------------------------------------------+ //| Print a description of the collateral level, | //| upon reaching which | //| the most loss-making position is forcefully closed (Stop Out) | //+------------------------------------------------------------------+ void AccountMarginStopOutPrint(const uint header_width=0,const uint indent=0) { //--- Get the StopOut level values, the number of decimal places for the symbol and its name double margin_so_so=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- If the level of collateral for StopOut is calculated as %, //--- specify 'currency' in % rather than in account currency, while 'digits' will be equal to 2 if(AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE)==ACCOUNT_STOPOUT_MODE_PERCENT) { currency="%"; digits=2; } //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin Stop Out:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value obtained above PrintFormat("%*s%-*s%-.*f %s",indent,"",w,header,digits,margin_so_so,currency); /* Sample output: Margin Stop Out: 30.00 % */ }
账户预留金额,用于支付所有挂单的保证金:
//+------------------------------------------------------------------+ //| Print a description of the funds | //| reserved on the account for security | //| of a guarantee amount for all pending orders | //+------------------------------------------------------------------+ void AccountMarginInitialPrint(const uint header_width=0,const uint indent=0) { //--- Get the amount of the reserved funds, the number of decimal places for the symbol and its name double margin_initial=AccountInfoDouble(ACCOUNT_MARGIN_INITIAL); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin initial:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_initial,currency); /* Sample output: Margin initial: 0.00 USD */ }
为弥补未平仓头寸的最小金额而保留的最低净值:
//+------------------------------------------------------------------+ //| Print a description of the funds | //| reserved on the account for security | //| of the min amount of all open positions | //+------------------------------------------------------------------+ void AccountMarginMaintenancePrint(const uint header_width=0,const uint indent=0) { //--- Get the amount of the reserved funds, the number of decimal places for the symbol and its name double margin_maintenance=AccountInfoDouble(ACCOUNT_MARGIN_MAINTENANCE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Margin maintenance:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_maintenance,currency); /* Sample output: Margin maintenance: 0.00 USD */ }
资产规模:
//+----------------------------------------------------------------------------+ //| Print a description of the current asset size on the account in the journal| //+----------------------------------------------------------------------------+ void AccountAssetsPrint(const uint header_width=0,const uint indent=0) { //--- Get the current asset size on the account, the number of decimal places for the symbol and its name double assets=AccountInfoDouble(ACCOUNT_ASSETS); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Assets:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,assets,currency); /* Sample output: Assets: 0.00 USD */ }
负债金额:
//+------------------------------------------------------------------+ //| Print a description | //| of the current liabilities on the account | //+------------------------------------------------------------------+ void AccountLiabilitiesPrint(const uint header_width=0,const uint indent=0) { //--- Get the current liabilities on the account, the number of decimal places for the symbol and its name double liabilities=AccountInfoDouble(ACCOUNT_LIABILITIES); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Liabilities:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,liabilities,currency); /* Sample output: Liabilities: 0.00 USD */ }
冻结的佣金:
//+------------------------------------------------------------------+ //| Print a description | //| of the current sum of blocked commissions on an account | //+------------------------------------------------------------------+ void AccountComissionBlockedPrint(const uint header_width=0,const uint indent=0) { //--- Get the current blocked commissions on the account, the number of decimal places for the symbol and its name double commission_blocked=AccountInfoDouble(ACCOUNT_COMMISSION_BLOCKED); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Comission blocked:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,commission_blocked,currency); /* Sample output: Comission blocked: 0.00 USD */ }
用于打印字符串型帐户属性的函数。
客户名称:
//+------------------------------------------------------------------+ //| Print a description of the client name into the journal | //+------------------------------------------------------------------+ void AccountNamePrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Name:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_NAME)); /* Sample output: Name: Artem */ }
交易服务器名称:
//+------------------------------------------------------------------+ //| Print a description of the trade server name into the journal | //+------------------------------------------------------------------+ void AccountServerPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Server:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_SERVER)); /* Sample output: Server: MetaQuotes-Demo */ } //+------------------------------------------------------------------+
存款货币名称:
//+------------------------------------------------------------------+ //| Print a description of a deposit currency name | //+------------------------------------------------------------------+ void AccountCurrencyPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Currency:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_CURRENCY)); /* Sample output: Currency: USD */ }
为帐户提供服务的公司的名称:
//+------------------------------------------------------------------+ //| Print a description of the company name, | //| serving an account, into the journal | //+------------------------------------------------------------------+ void AccountCompanyPrint(const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Company:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_COMPANY)); /* Sample output: Company: MetaQuotes Software Corp. */ }
上面介绍的所有函数几乎彼此相同。每个都可以设置从左边缘开始的行缩进和标题字段的宽度。传递给函数的默认值为零意味着没有缩进,页边宽度等于标题行的大小+1个字符。因此,可以按原样使用这些函数来显示所需的帐户属性。但是,当您需要创建一个函数来显示一组属性时,您将需要标题字段的缩进和宽度,以便在日志中整洁易读地输出值。
让我们创建一个这样的函数示例,该函数显示日记账中的所有帐户属性。
将所有帐户数据打印到日记账的函数:
//+------------------------------------------------------------------+ //| Print account data into the journal | //+------------------------------------------------------------------+ void AccountInfoPrint(const uint header_width=0,const uint indent=0) { //--- Display descriptions of integer properties according to their location in ENUM_ACCOUNT_INFO_INTEGER Print("AccountInfoInteger properties:"); AccountLoginPrint(header_width,indent); AccountTradeModePrint(header_width,indent); AccountLeveragePrint(header_width,indent); AccountLimitOrdersPrint(header_width,indent); AccountMarginSOModePrint(header_width,indent); AccountTradeAllowedPrint(header_width,indent); AccountTradeExpertPrint(header_width,indent); AccountMarginModePrint(header_width,indent); AccountCurrencyDigitsPrint(header_width,indent); AccountFIFOClosePrint(header_width,indent); AccountHedgeAllowedPrint(header_width,indent); //--- Display descriptions of real properties according to their location in ENUM_ACCOUNT_INFO_DOUBLE Print("AccountInfoDouble properties:"); AccountBalancePrint(header_width,indent); AccountCreditPrint(header_width,indent); AccountProfitPrint(header_width,indent); AccountEquityPrint(header_width,indent); AccountMarginPrint(header_width,indent); AccountMarginFreePrint(header_width,indent); AccountMarginLevelPrint(header_width,indent); AccountMarginSOCallPrint(header_width,indent); AccountMarginStopOutPrint(header_width,indent); AccountMarginInitialPrint(header_width,indent); AccountMarginMaintenancePrint(header_width,indent); AccountAssetsPrint(header_width,indent); AccountLiabilitiesPrint(header_width,indent); AccountComissionBlockedPrint(header_width,indent); //--- Display descriptions of string properties according to their location in ENUM_ACCOUNT_INFO_STRING Print("AccountInfoString properties:"); AccountNamePrint(header_width,indent); AccountServerPrint(header_width,indent); AccountCurrencyPrint(header_width,indent); AccountCompanyPrint(header_width,indent); }
该函数依次调用所有打印帐户属性数据的函数,按这些属性在枚举中出现的顺序排列:ENUM_ACCOUNT_INFO_INTEGER、ENUM_ACCOUNT_INFO_DOUBLE和ENUM_ACCOUNT_INFO_STRING。
从标题字段宽度为20个字符、缩进为2个字符的脚本调用函数的结果:
void OnStart() { //--- Print trading account properties in the journal AccountInfoPrint(20,2); /* Sample output: AccountInfoInteger properties: Login: 68008618 Trade mode: Demo Leverage: 1:100 Limit orders: 200 StopOut mode: Percent Trade allowed: Yes Trade expert: Yes Margin mode: Retail hedging Currency digits: 2 FIFO close: No Hedge allowed: Yes AccountInfoDouble properties: Balance: 10015.00 USD Credit: 0.00 USD Profit: 2.11 USD Equity: 10017.11 USD Margin: 25.61 USD Margin free: 9991.50 USD Margin level: 39114.06 % Margin Call: 50.00 % Margin Stop Out: 30.00 % Margin initial: 0.00 USD Margin maintenance: 0.00 USD Assets: 0.00 USD Liabilities: 0.00 USD Comission blocked: 0.00 USD AccountInfoString properties: Name: Artem Server: MetaQuotes-Demo Currency: USD Company: MetaQuotes Software Corp. */ }
从分时属性开始的时间(以毫秒为单位)
MqlTick结构旨在及时获得当前价格的最需要数据。
MqlTick类型的变量允许在SymbolInfoTick()函数的一次调用中获得Ask、Bid、Last和Volume值。此外,该结构还包含以毫秒为单位的分时时间。时间值在<s1>long</s1>类型的变量中给定。换句话说,当在日志中打印这些数据时,我们只会得到一个特定的数字——自1970年1月1日以来经过的毫秒数。要以人类可读的时间格式显示这些数据,您需要将此数字转换为日期,并在生成的日期上添加毫秒。
要获得带秒的日期,需要将毫秒数除以1000,要获得毫秒的时间,需要将日期的毫秒数的余数除以1000。
一般来说,它看起来是这样的:
void OnStart() { //--- MqlTick tick; if(SymbolInfoTick(Symbol(),tick)) { string time_str=string((datetime)tick.time_msc / 1000)+"."+string(tick.time_msc % 1000); Print("time_str=",time_str); } /* Sample output: time_str=2023.07.10 18:49:36.463 */ }
让我们编写一个函数,它以毫秒为单位接收时间,并以“日期 时间.毫秒”格式显示:
//+------------------------------------------------------------------+ //| Print the time in the Date Time.Msc format in the journal | //+------------------------------------------------------------------+ void TimeMSCPrint(const long time_msc,const uint header_width=0,const uint indent=0) { //--- Define the header text and the width of the header field //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 string header="Time msc:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the date and time in the journal with a header with the required width and indentation, milliseconds with 3 digit precision PrintFormat("%*s%-*s%-s.%.3lu",indent,"",w,header,string((datetime)time_msc / 1000),time_msc % 1000); /* Sample output: Time msc: 2023.07.10 19:49:05.233 */ }
要直接获取以毫秒为单位的日期和时间并将其显示在日记账中,可以使用以下函数:
//+------------------------------------------------------------------+ //| Print the time in the Date Time.Msc format for a symbol | //+------------------------------------------------------------------+ void TimeMSCPrint(const string symbol,const uint header_width=0,const uint indent=0) { //--- Get time from the tick MqlTick tick; if(!SymbolInfoTick(symbol,tick)) { Print(__FUNCTION__,": SymbolInfoTick error: ",(string)GetLastError()); return; } //--- Print the time in milliseconds using the first version of the function TimeMSCPrint(tick.time_msc,header_width,indent); /* Sample output: Time msc: 2023.07.10 20:07:08.202 */ }
结论
在本文中,我们研究了PrintFormat()打印格式化行的能力,并创建了用于打印帐户属性的示例函数,您可以在程序中“按原样”使用这些属性。但是还有另一种创建格式化输出的方法-StringFormat()函数。与PrintFormat()不同,它以所需的格式将一行打印到日志中,它以指定的格式返回一行格式化的文本。我认为显示格式化文本更方便,因为它可以从格式化行中创建所需的行。这一行可以在程序的不同位置使用,而不仅仅是输出到日志中。在下一篇文章中,我将考虑StringFormat()并了解它的特性。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/12905
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.



谢谢
文本输出的信息量非常大、
请准备好应对大量的使用问题。
我还是不明白打印格式是如何工作的。
文本输出的信息量巨大、
在使用中要准备好应对大量问题
无论我怎么努力,都不明白 printformat 是如何工作的。
不会有你想象的那么多。有很多人像费多谢耶夫一样
交易、自动交易系统和交易策略测试论坛。
讨论文章 "学习PrintFormat()并使用现成的例子"。
Dmitry Fedoseev, 2023.07.25 11:52 AM
如果没有 PrintFormat,我是怎么活了这么多年的......我可能会继续活下去...
不会有你想象的那么多。外面有很多费多谢耶夫
这正是我在这里所说的,你必须是个大傻瓜,才能仅凭个人信息就覆盖那么大的数量。
我再一次责怪 MQ 只会用它而无济于事。
--
我知道它来自 C++。
这跟商业有什么关系?
这正是我想说的,你必须是个大傻瓜,才会为个人信息付出那么多。
我再次责怪 MQ 使用不当。
--
我知道它来自 C++。
这 和商业有什么 关系?
对于方便的结构化信息输出来说,这很重要。
如果不需要,就把信息堆成一大堆,然后花几个小时整理出来。
而且,有人看到所有东西都整整齐齐地 "摆在架子上",会觉得很舒服。
还有人需要 "橡皮 "图表。这和交易有什么关系?
一般来说,这是尖头人和钝头人之间的争执。
这与方便的结构化信息输出有关。
如果不需要,就把信息堆成一大堆,然后花几个小时进行整理。
而且,别人看到所有东西都整齐地 "摆放在架子上 "也很方便。
有人需要 "橡皮 "图表。这和交易有什么关系?
一般来说,这是尖头人和钝头人之间的争执。
Artem,你能做的都是好事。
当你进入 "帮助 "页面,看到的不是20页有用的信息,而是50页