研究PrintFormat()并应用现成的示例·进阶篇
📘

研究PrintFormat()并应用现成的示例·进阶篇

第 2/3 篇

「用 PrintFormat 把浮点打印成不同进制与精度」

在 MT5 脚本调试里,PrintFormat 比 Print 更可控,能用类 C 的格式化串把同一笔数据按多种表示法输出,方便比对点位精度或极值溢出。下面这段演示了 e/E 科学计数与 a/A 十六进制浮点的差异:value1=255 在 e 格式下是 2.550000e+02,而 a 格式直接给出 0x1.fe00000000000p+7 的底层位模式。 另一组调用把 Point()(默认品种下常见为 0.00001)和 DBL_MAX 打出来:%-22f 给到 0.000010,%-#22g 则是 1.79769e+308,能直观看到双精度上限量级。把 EMPTY_VALUE 套上 %-#22.5f 与 %-#22G,输出 0.00001 与 1.79769E+308,说明空值在 double 层本质仍是 DBL_MAX。 开 MT5 新建脚本粘入下方代码,跑完看日志:若你经纪商黄金点差是 0.01,Point() 会变成 0.01,浮点尾数位宽不变但小数位缩短,这类细节只有实盘品种能暴露。外汇与贵金属波动剧烈,点值精度误差可能在剥头皮策略里放大风险,建议先回测再上实盘。

MQL5 / C++
class="type">class="kw">string header=""; class=class="str">"cmt">// Data header
class="type">class="kw">double value1=class="num">0; class=class="str">"cmt">// First value
class="type">class="kw">double value2=class="num">0; class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;e&class="macro">#x27; format
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;E&class="macro">#x27; format
header="Header1";
value1=class="num">255;
value2=class="num">1024;
PrintFormat("%-16s(e) %-22e(E) %-class="macro">#22E",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;a&class="macro">#x27; format
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;A&class="macro">#x27; format
header="Header2";
value1=class="num">255;
value2=class="num">1024;
PrintFormat("%-16s(a) %-class="macro">#22a(A) %-class="macro">#22A",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">/* Sample output:
    Header1(e) class="num">2.550000e+02          (E) class="num">1.024000E+03          
    Header2(a) 0x1.fe00000000000p+class="num">7 (A) 0X1.0000000000000P+class="num">10
 */
}
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
  class="type">class="kw">string  header=""; class=class="str">"cmt">// Data header
  class="type">class="kw">double  value1=class="num">0;  class=class="str">"cmt">// First value
  class="type">class="kw">double  value2=class="num">0;  class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="kw">default precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;g&class="macro">#x27; format
  header="Header1";
  value1=Point();
  value2=DBL_MAX;
  PrintFormat("%-16s(f) %-22f(g) %-class="macro">#22g",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="num">5-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;G&class="macro">#x27; format
  header="Header2";
  value1=Point();
  value2=EMPTY_VALUE;
  PrintFormat("%-16s(f) %-#class="num">22.5f(G) %-class="macro">#22G",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

  class=class="str">"cmt">/* Sample output:
    Header1(f) class="num">0.000010             (g) class="num">1.79769e+308         
    Header2(f) class="num">0.00001              (G) class="num">1.79769E+308         
  */
  }
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
  class="type">class="kw">string  header=""; class=class="str">"cmt">// Data header
  class="type">class="kw">double  value1=class="num">0;  class=class="str">"cmt">// First value

◍ PrintFormat 的星号字段与浮点格式实战

在 MT5 的 PrintFormat 里,用 *- 这类星号宽度占位符可以把字段宽度推迟到参数里传,而不是写死在格式串中。上面第一段代码把表头塞进 16 字符左对齐域,两个数据各占 22 字符左对齐域,第二域用 %f 默认精度、第三域用 %g 科学计数。 跑出来的样例里,Point() 在多数外汇品种下输出 0.00001,DBL_MAX 走 %g 显示成 1.79769e+308;把格式换成 %G 后同一数变成 1.79769E+308,仅大小写与指数标记差异。 第二段改用十六进制浮点:%a 把 Point() 打成 0x1.4f8b588e368f1p-17,%A 把 DBL_MAX 打成 0X1.FFFFFFFFFFFFFP+1023。限定 .5a 后尾数截断到 5 位十六进制即 0x1.4f8b6p-17,EMPTY_VALUE 在 %A 下显示为 0X2.0000000P+1023。 别把正态当圣经:这些输出依赖当前品种 Point 精度与双精度极值,换贵金属点位或 ECn 账户可能末位不同,开 MT5 切品种复跑即可验证。

MQL5 / C++
class="type">class="kw">double value2=class="num">0; class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a *-character field(class="num">16) and data in *-character fields(class="num">22)
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="kw">default precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;g&class="macro">#x27; format
  header="Header1";
  value1=Point();
  value2=DBL_MAX;
  PrintFormat("%-*s(f) %-*f(g) %-#*g",class="num">16,header,class="num">22,(class="type">class="kw">double)value1,class="num">22,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a *-character field(class="num">16) and data in *-character fields(class="num">22)
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="num">5-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;G&class="macro">#x27; format
  header="Header2";
  value1=Point();
  value2=EMPTY_VALUE;
  PrintFormat("%-*s(f) %-#*.5f(G) %-#*G",class="num">16,header,class="num">22,(class="type">class="kw">double)value1,class="num">22,(class="type">class="kw">double)value2);

  class=class="str">"cmt">/* Sample output:
      Header1(f) class="num">0.000010                   (g) class="num">1.79769e+308                
      Header2(f) class="num">0.00001                     (G) class="num">1.79769E+308                
   */
}
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
  class="type">class="kw">string  header=""; class=class="str">"cmt">// Data header
  class="type">class="kw">double  value1=class="num">0;  class=class="str">"cmt">// First value
  class="type">class="kw">double  value2=class="num">0;  class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;a&class="macro">#x27; format with class="kw">default precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;A&class="macro">#x27; format with class="kw">default precision
  header="Header1";
  value1=Point();
  value2=DBL_MAX;
  PrintFormat("%-16s(a) %-22a(A) %-class="macro">#22A",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;a&class="macro">#x27; format with class="num">5-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;A&class="macro">#x27; format with class="num">7-character precision
  header="Header2";
  value1=Point();
  value2=EMPTY_VALUE;
  PrintFormat("%-16s(a) %-#class="num">22.5a(A) %-#class="num">22.7A",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

  class=class="str">"cmt">/* Sample output:
      Header1(a) 0x1.4f8b588e368f1p-class="num">17 (A ) 0X1.FFFFFFFFFFFFFP+class="num">1023
      Header2(a) 0x1.4f8b6p-class="num">17          (A) 0X2.0000000P+class="num">1023      
   */
}
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
  class="type">class="kw">string  header=""; class=class="str">"cmt">// Data header
  class="type">class="kw">double  value1=class="num">0;  class=class="str">"cmt">// First value
  class="type">class="kw">double  value2=class="num">0;  class=class="str">"cmt">// Second value

PrintFormat 多进制与浮点格式混排实测

在 MT5 的 EA 或脚本里,PrintFormat 能像 C 语言 printf 那样用格式符把同一条日志压成对齐的表格。上面这段把 INT_MAX(2147483647)分别用十进制、八进制、十六进制小写和大写打印,终端里会看到 Header1 行第三列输出 02147483647,Header3 行第二列输出 0xffc00000,字段宽度锁死在 16 和 22 字符,左对齐靠 %- 控制。 浮点侧换 DBL_MAX 进场,%e 与 %E 决定科学计数法的大小写,%f 则走定点小数。把 value1、value2 改成 SymbolInfoDouble(Symbol(), SYMBOL_ASK) 就能直接把当前品种卖价按 4 位和 11 位精度打出来,EURUSD 这类小数位多的报价差异一眼可辨。 外汇与贵金属报价跳动快、点差随机,用这种格式做本地日志比对时,记得多跑几根 Bar 看精度截断是否影响你的判断。开 MT5 新建脚本粘入下方代码,改 Symbol 就能验证你经纪商的实际输出。

MQL5 / C++
class="type">class="kw">double value2=class="num">0; class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;d&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;i&class="macro">#x27; format with class="num">11-character precision
  header="Header1";
  value1=INT_MAX;
  value2=INT_MAX;
  PrintFormat("%-16s(d) %-class="num">22.4d(i) %-#class="num">22.11i",header,(class="type">int)value1,(class="type">int)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;u&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;o&class="macro">#x27; format with class="num">11-character precision
  header="Header2";
  value1=INT_MAX;
  value2=INT_MAX;
  PrintFormat("%-16s(u) %-#class="num">22.4u(o) %-#class="num">22.11o",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The third line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;x&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;X&class="macro">#x27; format with class="num">11-character precision
  header="Header3";
  value1=INT_MAX;
  value2=INT_MAX;
  PrintFormat("%-16s(x) %-#class="num">22.4x(X) %-#class="num">22.11X",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

  class=class="str">"cmt">/* Sample output:
      Header1(d) class="num">2147483647          (i) class="num">02147483647
      Header2(u) class="num">4290772992          (o) class="num">037760000000
      Header3(x) 0xffc00000          (X) 0X000FFC00000
   */
}
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
  class="type">class="kw">string  header=""; class=class="str">"cmt">// Data header
  class="type">class="kw">double  value1=class="num">0;  class=class="str">"cmt">// First value
  class="type">class="kw">double  value2=class="num">0;  class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;e&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;E&class="macro">#x27; format with class="num">11-character precision
  header="Header1";
  value1=DBL_MAX;
  value2=DBL_MAX;
  PrintFormat("%-16s(e) %-class="num">22.4e(E) %-#class="num">22.11E",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;f&class="macro">#x27; format with class="num">11-character precision
  header="Header2";
  value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

「用 PrintFormat 对齐报价与极值输出」

在 MT5 脚本里做价格行为日志时,PrintFormat 的格式化串比手动拼字符串更省事。下面这段把表头固定占 16 字符、数据域占 22 字符且全部左对齐,第二列用 (g) 格式保留 4 位有效数,第三列用 (G) 格式保留 11 位有效数。 实际跑出来,Header1 行第二列会打出 1.798e+308(即 DBL_MAX),第三列是当时 SYMBOL_ASK 的 1.2731600000;Header2 行反过来,第二列只显示 1.273(精度截断到 4 位),第三列是 1.7976931349E+308。外汇与贵金属报价跳动快,这种对齐方式便于你肉眼比对跨品种点差。 若把第三列格式换成 (s) 并强转 string,就能直接把 SymbolInfoDouble 取到的 ask 当文本落盘,避免浮点格式在日志里被四舍五入。开 MT5 新建脚本粘入下方代码,改 Symbol() 为具体品种如 XAUUSD,即可验证不同格式串的差异。

MQL5 / C++
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
   class="type">class="kw">string  header="";   class=class="str">"cmt">// Data header
   class="type">class="kw">double  value1=class="num">0;    class=class="str">"cmt">// First value
   class="type">class="kw">double  value2=class="num">0;    class=class="str">"cmt">// Second value

class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;g&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;G&class="macro">#x27; format with class="num">11-character precision
   header="Header1";
   value1=DBL_MAX;
   value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
   PrintFormat("%-16s(g) %-class="num">22.4g(G) %-#class="num">22.11G",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);

class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">22-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;g&class="macro">#x27; format with class="num">4-character precision
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;G&class="macro">#x27; format with class="num">11-character precision
   header="Header2";
   value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
   value2=DBL_MAX;
   PrintFormat("%-16s(g) %-#class="num">22.4g(G) %-#class="num">22.11G",header,(class="type">class="kw">double)value1,(class="type">class="kw">double)value2);
  }

◍ PrintFormat 里 c/C 与 d/i 的格式差异

在 MT5 脚本排错时,PrintFormat 的格式符直接决定终端里你能看到什么。用 %c 打印 char 类型 65 得到字母 A,用 %C 打印 66 得到 B;换成 %d 或 %i 打印同样数值,终端只显示整数 65、66。 left-align 的 %-10c 和 %-10C 都占 10 字符宽,但大小写格式符对 char 的解释输出一致,仅语义上区分单字节与宽字符。 下面这段可直接贴进 EA 的 OnStart 验证:声明 header 为空串、value1/value2 为 char 初值 0,随后分三行打印。第一行 Header1 配 (c) A (C) B,第二行 Header2 配 (c) C (C) D,第三行 Header3 用 (d) 65 (i) 66。跑完在专家日志里对照样例输出,能确认格式串没写错。 外汇与贵金属行情里 SymbolInfoDouble(Symbol(),SYMBOL_ASK) 取到的卖价,若用 %-#22.4s 截断成 4 字符精度,1.2872 会显示成 1.28。这种截断在快速扫日志时有用,但高频策略里可能漏看小数点后细微跳动,属高风险品种下的信息损失,建议只在人工巡检时用。

MQL5 / C++
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;s&class="macro">#x27; format with class="num">4-character precision
  header="Header2";
  value1=DBL_MAX;
  value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
  PrintFormat("%-16s(g) %-#class="num">22.5g(s) %-#class="num">22.4s",header,(class="type">class="kw">double)value1,(class="type">class="kw">string)value2);
  
  class=class="str">"cmt">/* Sample output:
      Header1(g) class="num">1.798e+308            (s) class="num">1.2872                 
      Header2(g) class="num">1.7977e+308           (s) class="num">1.28                   
  */
  }
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Declare the variables to be printed
   class="type">class="kw">string  header="";  class=class="str">"cmt">// Data header
   class="type">char    value1=class="num">0;   class=class="str">"cmt">// First value
   class="type">char    value2=class="num">0;   class=class="str">"cmt">// Second value
  
class=class="str">"cmt">//--- The first line with a header in a class="num">16-character field and data in class="num">10-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;c&class="macro">#x27; format
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;C&class="macro">#x27; format
   header="Header1";
   value1=class="num">65;
   value2=class="num">66;
   PrintFormat("%-16s(c) %-10c(C) %-10C",header,(class="type">char)value1,(class="type">char)value2);
  
class=class="str">"cmt">//--- The second line with a header in a class="num">16-character field and data in class="num">10-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;c&class="macro">#x27; format
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;C&class="macro">#x27; format
   header="Header2";
   value1=class="num">67;
   value2=class="num">68;
   PrintFormat("%-16s(c) %-10c(C) %-10C",header,(class="type">char)value1,(class="type">char)value2);
  
class=class="str">"cmt">//--- The third line with a header in a class="num">16-character field and data in class="num">10-character fields
class=class="str">"cmt">//--- The header and data of all fields are pressed to the left edge.
class=class="str">"cmt">//--- Data values of the second field are displayed together with the &class="macro">#x27;d&class="macro">#x27; format
class=class="str">"cmt">//--- Data values of the third field are displayed together with the &class="macro">#x27;i&class="macro">#x27; format
   header="Header3";
   value1=class="num">65;
   value2=class="num">66;
   PrintFormat("%-16s(d) %-10d(i) %-10i",header,(class="type">int)value1,(class="type">int)value2);
  
   class=class="str">"cmt">/* Sample output:
      Header1(c) A(C) B         
      Header2(c) C(C) D         
      Header3(d) class="num">65         (i) class="num">66        
   */
  }

把账户属性整齐打进日志的写法

MT5 里读账户信息分三族函数:AccountInfoInteger 取整数、AccountInfoDouble 取实数、AccountInfoString 取字符串。与其每次把全部属性罗列出来,不如给每类属性单独封一个打印函数,用的时候按需要拼装,日志可读性高得多。 封装时建议传两个参数:标题字段宽度 header_width 和从左边缘的缩进 indent。若 header_width 传 0,函数内部自动取标题文本长度 +1,等于不做对齐强制;indent 传 0 则无缩进。这样单属性调试能直接调,批量输出时再统一给宽度和缩进。 格式串里 %*s 是关键:星号位置由参数填缩进值,对应传一个空字符串,就能用空格垫出任意空字段;标题宽度也用 %-*s 接 w 变量控制。下面这段摘了登录号和账户类型的打印函数,能看到整数直接转型输出,枚举型先 EnumToString 再截掉前缀、首字母大写。 [CODE] //+------------------------------------------------------------------+

//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 */ } //+------------------------------------------------------------------+

//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

//+------------------------------------------------------------------+ 逐行拆解:AccountLoginPrint 中 header 写死 "Login:",w 在零宽时取字符串长+1;PrintFormat 的 "%*s%-*s%-s" 依次吃 indent、空串、w、header、登录号转字符串,样例输出 Login: 68008618。AccountTradeModePrint 先读 ACCOUNT_TRADE_MODE 整数转枚举,EnumToString 后从索引 19 截掉 "ACCOUNT_TRADE_MODE_" 前缀,Lower 再手动把首字母加 0x20 变大写,最后同样用 PrintFormat 输出,样例得 Trade mode: Demo。 真要一次看全貌,写个总函数按 ENUM_ACCOUNT_INFO_INTEGER、ENUM_ACCOUNT_INFO_DOUBLE、ENUM_ACCOUNT_INFO_STRING 顺序调一遍子函数即可。脚本里用标题宽 20、缩进 2 调用,日志里每行前面空两格、标题占 20 宽,扫一眼就能核对杠杆、净值、信用等字段。外汇和贵金属账户这类属性随券商策略变动,高杠杆意味着回撤可能被放大,核对完记得结合风控参数看。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Print a description of the account number into the journal       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void AccountLoginPrint(const class="type">uint header_width=class="num">0,const class="type">uint indent=class="num">0)
  {
class=class="str">"cmt">//--- Define the header text and the width of the header field
class=class="str">"cmt">//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + class="num">1
   class="type">class="kw">string header="Login:";
   class="type">uint w=(header_width==class="num">0 ? header.Length()+class="num">1 : header_width);
class=class="str">"cmt">//--- Print the class="kw">property value in the log with a header with the required width and indentation
   PrintFormat("%*s%-*s%-s",indent,"",w,header,(class="type">class="kw">string)AccountInfoInteger(ACCOUNT_LOGIN));
   class=class="str">"cmt">/* Sample output:
       Login: class="num">68008618
   */
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Print a trading account type into the journal                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void AccountTradeModePrint(const class="type">uint header_width=class="num">0,const class="type">uint indent=class="num">0)
  {
class=class="str">"cmt">//--- Get the value of the trading account type
   ENUM_ACCOUNT_TRADE_MODE trade_mode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
class=class="str">"cmt">//--- "Cut out" the name of the trading account type from the line obtained from enum
   class="type">class="kw">string mode=StringSubstr(EnumToString(trade_mode),class="num">19);
class=class="str">"cmt">//--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital
   if(mode.Lower())
      mode.SetChar(class="num">0,class="type">class="kw">ushort(mode.GetChar(class="num">0)-0x20));
class=class="str">"cmt">//--- Define the header text and the width of the header field
class=class="str">"cmt">//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + class="num">1
   class="type">class="kw">string header="Trade mode:";
   class="type">uint w=(header_width==class="num">0 ? header.Length()+class="num">1 : header_width);
class=class="str">"cmt">//--- Print the class="kw">property value in the log with a header with the required width and indentation
   PrintFormat("%*s%-*s%-s",indent,"",w,header,mode);
   class=class="str">"cmt">/* Sample output:
       Trade mode: Demo
   */
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Print a description of the provided leverage size in the journal |
class=class="str">"cmt">//+------------------------------------------------------------------+

常见问题

用 PrintFormat("%b", price) 可直接输出二进制;若要限定小数位,配合精度符如 "%.4f" 控制显示位数,先在脚本里跑一遍看日志。
写成 PrintFormat("%-*.*f", width, prec, value),width 和 prec 用变量传,就能随账户小数位自适应对齐,避免数字乱跳。
可以,小布能根据你说出的字段名和进制要求,直接生成对应的格式化打印代码并标好参数含义,你复制到脚本即可跑。
c 按单字符输出,d/i 按十进制整数;用 d 打字符会把 ASCII 码当数字显示,必须改用 %c 才能看到原字符。
用 PrintFormat("杠杆=%d 结余=%.2f", leverage, balance) 混排,左侧整数右侧两位小数,日志一眼能扫完。