MT5 金麒麟 加强版 源码发放

| 发表于 5 天前 | 显示全部楼层 |复制链接
下面是金麒麟MT5修正版的源码,我在另外的地方发布了,可一直没能通过审核。
我不知道为什么。所以在这里重新发布一次。

各位老板,你们这下不给我点赞收藏加关注是有点儿过份了!!!

优化升级内容,详看这篇帖子:https://www.eahub.cn/thread-182156-1-1.html

  1. #property strict
  2. #property version   "2.11"
  3. #property description "GoldKylin MT5 CTrade edition"
  4. #include <Trade/Trade.mqh>
  5. // --- Embedded USD high-impact backtest news start ---
  6. // Auto-generated by generate_backtest_news_include.py
  7. // Source: https://www.mql5.com/en/economic-calendar/content
  8. // Filters: USD + high importance + exact datetime
  9. // Range: 2025-01-01 .. 2026-04-03
  10. // Generated: 2026-04-03 03:28:49 UTC
  11. #define GOLDKING_BACKTEST_USD_HIGH_NEWS_COUNT 615
  12. #define GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_LABEL "2025-01-01~2026-04-03"
  13. #define GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_START D'2025.01.01 00:00:00'
  14. #define GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_END D'2026.04.03 23:59:59'
  15. datetime GOLDKING_BACKTEST_USD_HIGH_NEWS_TIMES[GOLDKING_BACKTEST_USD_HIGH_NEWS_COUNT]=
  16.   {
  17.    D'2025.01.02 13:30:00',
  18.    D'2025.01.02 14:45:00',
  19.    D'2025.01.02 16:00:00',
  20.    D'2025.01.03 15:00:00',
  21.    D'2025.01.03 15:00:00',
  22.    D'2025.01.06 14:45:00',
  23.    D'2025.01.07 15:00:00',
  24.    D'2025.01.07 15:00:00',
  25.    D'2025.01.07 15:00:00',
  26.    D'2025.01.07 18:00:00',
  27.    D'2025.01.08 13:15:00',
  28.    D'2025.01.08 13:30:00',
  29.    D'2025.01.08 15:30:00',
  30.    D'2025.01.08 18:00:00',
  31.    D'2025.01.10 13:30:00',
  32.    D'2025.01.10 13:30:00',
  33.    D'2025.01.10 13:30:00',
  34.    D'2025.01.14 13:30:00',
  35.    D'2025.01.15 13:30:00',
  36.    D'2025.01.15 13:30:00',
  37.    D'2025.01.15 13:30:00',
  38.    D'2025.01.15 13:30:00',
  39.    D'2025.01.15 13:30:00',
  40.    D'2025.01.15 15:30:00',
  41.    D'2025.01.16 13:30:00',
  42.    D'2025.01.16 13:30:00',
  43.    D'2025.01.16 13:30:00',
  44.    D'2025.01.16 13:30:00',
  45.    D'2025.01.23 13:30:00',
  46.    D'2025.01.23 17:00:00',
  47.    D'2025.01.24 15:00:00',
  48.    D'2025.01.27 15:00:00',
  49.    D'2025.01.28 13:30:00',
  50.    D'2025.01.28 15:00:00',
  51.    D'2025.01.29 15:30:00',
  52.    D'2025.01.29 19:00:00',
  53.    D'2025.01.29 19:30:00',
  54.    D'2025.01.30 13:30:00',
  55.    D'2025.01.30 13:30:00',
  56.    D'2025.01.30 13:30:00',
  57.    D'2025.01.31 13:30:00',
  58.    D'2025.01.31 13:30:00',
  59.    D'2025.01.31 14:45:00',
  60.    D'2025.02.03 14:45:00',
  61.    D'2025.02.03 15:00:00',
  62.    D'2025.02.03 15:00:00',
  63.    D'2025.02.04 15:00:00',
  64.    D'2025.02.05 13:15:00',
  65.    D'2025.02.05 14:45:00',
  66.    D'2025.02.05 15:00:00',
  67.    D'2025.02.05 15:00:00',
  68.    D'2025.02.05 15:30:00',
  69.    D'2025.02.06 13:30:00',
  70.    D'2025.02.07 13:30:00',
  71.    D'2025.02.07 13:30:00',
  72.    D'2025.02.07 13:30:00',
  73.    D'2025.02.11 15:00:00',
  74.    D'2025.02.12 13:30:00',
  75.    D'2025.02.12 13:30:00',
  76.    D'2025.02.12 13:30:00',
  77.    D'2025.02.12 13:30:00',
  78.    D'2025.02.12 13:30:00',
  79.    D'2025.02.12 15:00:00',
  80.    D'2025.02.12 15:30:00',
  81.    D'2025.02.12 18:00:00',
  82.    D'2025.02.13 13:30:00',
  83.    D'2025.02.13 13:30:00',
  84.    D'2025.02.13 18:00:00',
  85.    D'2025.02.14 13:30:00',
  86.    D'2025.02.14 13:30:00',
  87.    D'2025.02.20 13:30:00',
  88.    D'2025.02.20 13:30:00',
  89.    D'2025.02.20 17:00:00',
  90.    D'2025.02.21 15:00:00',
  91.    D'2025.02.25 15:00:00',
  92.    D'2025.02.26 15:00:00',
  93.    D'2025.02.26 15:30:00',
  94.    D'2025.02.27 13:30:00',
  95.    D'2025.02.27 13:30:00',
  96.    D'2025.02.27 13:30:00',
  97.    D'2025.02.27 13:30:00',
  98.    D'2025.02.28 13:30:00',
  99.    D'2025.02.28 13:30:00',
  100.    D'2025.02.28 14:45:00',
  101.    D'2025.03.03 14:45:00',
  102.    D'2025.03.03 15:00:00',
  103.    D'2025.03.03 15:00:00',
  104.    D'2025.03.05 13:15:00',
  105.    D'2025.03.05 14:45:00',
  106.    D'2025.03.05 15:00:00',
  107.    D'2025.03.05 15:00:00',
  108.    D'2025.03.05 15:30:00',
  109.    D'2025.03.06 13:30:00',
  110.    D'2025.03.07 13:30:00',
  111.    D'2025.03.07 13:30:00',
  112.    D'2025.03.07 13:30:00',
  113.    D'2025.03.07 17:30:00',
  114.    D'2025.03.11 14:00:00',
  115.    D'2025.03.12 12:30:00',
  116.    D'2025.03.12 12:30:00',
  117.    D'2025.03.12 12:30:00',
  118.    D'2025.03.12 12:30:00',
  119.    D'2025.03.12 12:30:00',
  120.    D'2025.03.12 14:30:00',
  121.    D'2025.03.12 17:00:00',
  122.    D'2025.03.13 12:30:00',
  123.    D'2025.03.13 12:30:00',
  124.    D'2025.03.13 17:00:00',
  125.    D'2025.03.17 12:30:00',
  126.    D'2025.03.17 12:30:00',
  127.    D'2025.03.19 14:30:00',
  128.    D'2025.03.19 18:00:00',
  129.    D'2025.03.19 18:30:00',
  130.    D'2025.03.20 12:30:00',
  131.    D'2025.03.20 12:30:00',
  132.    D'2025.03.20 14:00:00',
  133.    D'2025.03.25 14:00:00',
  134.    D'2025.03.25 14:00:00',
  135.    D'2025.03.26 12:30:00',
  136.    D'2025.03.26 14:30:00',
  137.    D'2025.03.27 12:30:00',
  138.    D'2025.03.27 12:30:00',
  139.    D'2025.03.27 12:30:00',
  140.    D'2025.03.28 12:30:00',
  141.    D'2025.03.28 12:30:00',
  142.    D'2025.03.31 13:45:00',
  143.    D'2025.04.01 13:45:00',
  144.    D'2025.04.01 14:00:00',
  145.    D'2025.04.01 14:00:00',
  146.    D'2025.04.01 14:00:00',
  147.    D'2025.04.02 12:15:00',
  148.    D'2025.04.02 14:30:00',
  149.    D'2025.04.03 12:30:00',
  150.    D'2025.04.03 13:45:00',
  151.    D'2025.04.03 14:00:00',
  152.    D'2025.04.03 14:00:00',
  153.    D'2025.04.04 12:30:00',
  154.    D'2025.04.04 12:30:00',
  155.    D'2025.04.04 12:30:00',
  156.    D'2025.04.04 15:25:00',
  157.    D'2025.04.09 14:30:00',
  158.    D'2025.04.09 17:00:00',
  159.    D'2025.04.10 12:30:00',
  160.    D'2025.04.10 12:30:00',
  161.    D'2025.04.10 12:30:00',
  162.    D'2025.04.10 12:30:00',
  163.    D'2025.04.10 12:30:00',
  164.    D'2025.04.10 12:30:00',
  165.    D'2025.04.10 17:00:00',
  166.    D'2025.04.11 12:30:00',
  167.    D'2025.04.16 12:30:00',
  168.    D'2025.04.16 12:30:00',
  169.    D'2025.04.16 14:30:00',
  170.    D'2025.04.16 17:30:00',
  171.    D'2025.04.17 12:30:00',
  172.    D'2025.04.17 12:30:00',
  173.    D'2025.04.23 14:00:00',
  174.    D'2025.04.23 14:30:00',
  175.    D'2025.04.24 12:30:00',
  176.    D'2025.04.24 12:30:00',
  177.    D'2025.04.24 14:00:00',
  178.    D'2025.04.29 14:00:00',
  179.    D'2025.04.29 14:00:00',
  180.    D'2025.04.30 12:15:00',
  181.    D'2025.04.30 12:30:00',
  182.    D'2025.04.30 12:30:00',
  183.    D'2025.04.30 13:45:00',
  184.    D'2025.04.30 14:00:00',
  185.    D'2025.04.30 14:00:00',
  186.    D'2025.04.30 14:30:00',
  187.    D'2025.05.01 12:30:00',
  188.    D'2025.05.01 13:45:00',
  189.    D'2025.05.01 14:00:00',
  190.    D'2025.05.01 14:00:00',
  191.    D'2025.05.02 12:30:00',
  192.    D'2025.05.02 12:30:00',
  193.    D'2025.05.02 12:30:00',
  194.    D'2025.05.05 13:45:00',
  195.    D'2025.05.05 14:00:00',
  196.    D'2025.05.05 14:00:00',
  197.    D'2025.05.06 17:00:00',
  198.    D'2025.05.07 14:30:00',
  199.    D'2025.05.07 18:00:00',
  200.    D'2025.05.07 18:30:00',
  201.    D'2025.05.08 12:30:00',
  202.    D'2025.05.08 17:00:00',
  203.    D'2025.05.13 12:30:00',
  204.    D'2025.05.13 12:30:00',
  205.    D'2025.05.13 12:30:00',
  206.    D'2025.05.13 12:30:00',
  207.    D'2025.05.13 12:30:00',
  208.    D'2025.05.14 14:30:00',
  209.    D'2025.05.15 12:30:00',
  210.    D'2025.05.15 12:30:00',
  211.    D'2025.05.15 12:30:00',
  212.    D'2025.05.15 12:30:00',
  213.    D'2025.05.15 12:30:00',
  214.    D'2025.05.15 12:40:00',
  215.    D'2025.05.21 14:30:00',
  216.    D'2025.05.22 12:30:00',
  217.    D'2025.05.22 14:00:00',
  218.    D'2025.05.23 14:00:00',
  219.    D'2025.05.25 18:40:00',
  220.    D'2025.05.27 12:30:00',
  221.    D'2025.05.27 14:00:00',
  222.    D'2025.05.29 12:30:00',
  223.    D'2025.05.29 12:30:00',
  224.    D'2025.05.29 12:30:00',
  225.    D'2025.05.29 16:00:00',
  226.    D'2025.05.30 12:30:00',
  227.    D'2025.05.30 12:30:00',
  228.    D'2025.05.30 13:45:00',
  229.    D'2025.06.02 13:45:00',
  230.    D'2025.06.02 14:00:00',
  231.    D'2025.06.02 14:00:00',
  232.    D'2025.06.02 17:00:00',
  233.    D'2025.06.03 14:00:00',
  234.    D'2025.06.04 12:15:00',
  235.    D'2025.06.04 13:45:00',
  236.    D'2025.06.04 14:00:00',
  237.    D'2025.06.04 14:00:00',
  238.    D'2025.06.04 14:30:00',
  239.    D'2025.06.05 12:30:00',
  240.    D'2025.06.06 12:30:00',
  241.    D'2025.06.06 12:30:00',
  242.    D'2025.06.06 12:30:00',
  243.    D'2025.06.11 12:30:00',
  244.    D'2025.06.11 12:30:00',
  245.    D'2025.06.11 12:30:00',
  246.    D'2025.06.11 12:30:00',
  247.    D'2025.06.11 12:30:00',
  248.    D'2025.06.11 14:30:00',
  249.    D'2025.06.11 17:00:00',
  250.    D'2025.06.12 12:30:00',
  251.    D'2025.06.12 12:30:00',
  252.    D'2025.06.12 17:00:00',
  253.    D'2025.06.17 12:30:00',
  254.    D'2025.06.17 12:30:00',
  255.    D'2025.06.18 12:30:00',
  256.    D'2025.06.18 14:30:00',
  257.    D'2025.06.18 18:00:00',
  258.    D'2025.06.18 18:30:00',
  259.    D'2025.06.20 12:30:00',
  260.    D'2025.06.23 14:00:00',
  261.    D'2025.06.24 14:00:00',
  262.    D'2025.06.24 14:00:00',
  263.    D'2025.06.25 14:00:00',
  264.    D'2025.06.25 14:00:00',
  265.    D'2025.06.25 14:30:00',
  266.    D'2025.06.26 12:30:00',
  267.    D'2025.06.26 12:30:00',
  268.    D'2025.06.26 12:30:00',
  269.    D'2025.06.26 12:30:00',
  270.    D'2025.06.27 12:30:00',
  271.    D'2025.06.27 12:30:00',
  272.    D'2025.06.30 13:45:00',
  273.    D'2025.07.01 13:30:00',
  274.    D'2025.07.01 13:45:00',
  275.    D'2025.07.01 14:00:00',
  276.    D'2025.07.01 14:00:00',
  277.    D'2025.07.01 14:00:00',
  278.    D'2025.07.02 12:15:00',
  279.    D'2025.07.02 14:30:00',
  280.    D'2025.07.03 12:30:00',
  281.    D'2025.07.03 12:30:00',
  282.    D'2025.07.03 12:30:00',
  283.    D'2025.07.03 12:30:00',
  284.    D'2025.07.03 13:45:00',
  285.    D'2025.07.03 14:00:00',
  286.    D'2025.07.03 14:00:00',
  287.    D'2025.07.09 14:30:00',
  288.    D'2025.07.09 17:00:00',
  289.    D'2025.07.10 12:30:00',
  290.    D'2025.07.10 17:00:00',
  291.    D'2025.07.15 12:30:00',
  292.    D'2025.07.15 12:30:00',
  293.    D'2025.07.15 12:30:00',
  294.    D'2025.07.15 12:30:00',
  295.    D'2025.07.15 12:30:00',
  296.    D'2025.07.16 12:30:00',
  297.    D'2025.07.16 14:30:00',
  298.    D'2025.07.17 12:30:00',
  299.    D'2025.07.17 12:30:00',
  300.    D'2025.07.17 12:30:00',
  301.    D'2025.07.17 12:30:00',
  302.    D'2025.07.22 12:30:00',
  303.    D'2025.07.23 14:00:00',
  304.    D'2025.07.23 14:30:00',
  305.    D'2025.07.24 12:30:00',
  306.    D'2025.07.24 14:00:00',
  307.    D'2025.07.25 12:30:00',
  308.    D'2025.07.29 14:00:00',
  309.    D'2025.07.29 14:00:00',
  310.    D'2025.07.30 12:15:00',
  311.    D'2025.07.30 12:30:00',
  312.    D'2025.07.30 12:30:00',
  313.    D'2025.07.30 14:30:00',
  314.    D'2025.07.30 18:00:00',
  315.    D'2025.07.30 18:30:00',
  316.    D'2025.07.31 12:30:00',
  317.    D'2025.07.31 12:30:00',
  318.    D'2025.07.31 12:30:00',
  319.    D'2025.07.31 13:45:00',
  320.    D'2025.08.01 12:30:00',
  321.    D'2025.08.01 12:30:00',
  322.    D'2025.08.01 12:30:00',
  323.    D'2025.08.01 13:45:00',
  324.    D'2025.08.01 14:00:00',
  325.    D'2025.08.01 14:00:00',
  326.    D'2025.08.05 13:45:00',
  327.    D'2025.08.05 14:00:00',
  328.    D'2025.08.05 14:00:00',
  329.    D'2025.08.06 14:30:00',
  330.    D'2025.08.06 17:00:00',
  331.    D'2025.08.07 12:30:00',
  332.    D'2025.08.07 17:00:00',
  333.    D'2025.08.12 12:30:00',
  334.    D'2025.08.12 12:30:00',
  335.    D'2025.08.12 12:30:00',
  336.    D'2025.08.12 12:30:00',
  337.    D'2025.08.12 12:30:00',
  338.    D'2025.08.13 14:30:00',
  339.    D'2025.08.14 12:30:00',
  340.    D'2025.08.14 12:30:00',
  341.    D'2025.08.15 12:30:00',
  342.    D'2025.08.15 12:30:00',
  343.    D'2025.08.20 14:30:00',
  344.    D'2025.08.21 12:30:00',
  345.    D'2025.08.21 12:30:00',
  346.    D'2025.08.21 14:00:00',
  347.    D'2025.08.22 14:00:00',
  348.    D'2025.08.25 14:00:00',
  349.    D'2025.08.26 12:30:00',
  350.    D'2025.08.26 14:00:00',
  351.    D'2025.08.27 14:30:00',
  352.    D'2025.08.28 12:30:00',
  353.    D'2025.08.28 12:30:00',
  354.    D'2025.08.28 12:30:00',
  355.    D'2025.08.29 12:30:00',
  356.    D'2025.08.29 12:30:00',
  357.    D'2025.08.29 13:45:00',
  358.    D'2025.09.02 13:45:00',
  359.    D'2025.09.02 14:00:00',
  360.    D'2025.09.02 14:00:00',
  361.    D'2025.09.03 14:00:00',
  362.    D'2025.09.04 12:15:00',
  363.    D'2025.09.04 12:30:00',
  364.    D'2025.09.04 13:45:00',
  365.    D'2025.09.04 14:00:00',
  366.    D'2025.09.04 14:00:00',
  367.    D'2025.09.04 16:00:00',
  368.    D'2025.09.05 12:30:00',
  369.    D'2025.09.05 12:30:00',
  370.    D'2025.09.05 12:30:00',
  371.    D'2025.09.10 12:30:00',
  372.    D'2025.09.10 14:30:00',
  373.    D'2025.09.10 17:00:00',
  374.    D'2025.09.11 12:30:00',
  375.    D'2025.09.11 12:30:00',
  376.    D'2025.09.11 12:30:00',
  377.    D'2025.09.11 12:30:00',
  378.    D'2025.09.11 12:30:00',
  379.    D'2025.09.11 12:30:00',
  380.    D'2025.09.11 17:00:00',
  381.    D'2025.09.16 12:30:00',
  382.    D'2025.09.16 12:30:00',
  383.    D'2025.09.17 14:30:00',
  384.    D'2025.09.17 18:00:00',
  385.    D'2025.09.17 18:30:00',
  386.    D'2025.09.18 12:30:00',
  387.    D'2025.09.18 12:30:00',
  388.    D'2025.09.23 14:00:00',
  389.    D'2025.09.23 16:35:00',
  390.    D'2025.09.24 14:00:00',
  391.    D'2025.09.24 14:30:00',
  392.    D'2025.09.25 12:30:00',
  393.    D'2025.09.25 12:30:00',
  394.    D'2025.09.25 12:30:00',
  395.    D'2025.09.25 12:30:00',
  396.    D'2025.09.26 12:30:00',
  397.    D'2025.09.26 12:30:00',
  398.    D'2025.09.30 13:45:00',
  399.    D'2025.09.30 14:00:00',
  400.    D'2025.09.30 14:00:00',
  401.    D'2025.10.01 12:15:00',
  402.    D'2025.10.01 13:45:00',
  403.    D'2025.10.01 14:00:00',
  404.    D'2025.10.01 14:00:00',
  405.    D'2025.10.01 14:30:00',
  406.    D'2025.10.03 13:45:00',
  407.    D'2025.10.05 14:00:00',
  408.    D'2025.10.05 14:00:00',
  409.    D'2025.10.08 14:30:00',
  410.    D'2025.10.08 17:00:00',
  411.    D'2025.10.09 12:30:00',
  412.    D'2025.10.09 17:00:00',
  413.    D'2025.10.14 16:20:00',
  414.    D'2025.10.16 12:30:00',
  415.    D'2025.10.16 16:00:00',
  416.    D'2025.10.22 14:30:00',
  417.    D'2025.10.23 14:00:00',
  418.    D'2025.10.24 12:30:00',
  419.    D'2025.10.24 12:30:00',
  420.    D'2025.10.24 12:30:00',
  421.    D'2025.10.24 12:30:00',
  422.    D'2025.10.24 12:30:00',
  423.    D'2025.10.28 14:00:00',
  424.    D'2025.10.29 14:30:00',
  425.    D'2025.10.29 18:00:00',
  426.    D'2025.10.29 18:30:00',
  427.    D'2025.10.31 13:45:00',
  428.    D'2025.11.03 14:45:00',
  429.    D'2025.11.03 15:00:00',
  430.    D'2025.11.03 15:00:00',
  431.    D'2025.11.05 13:15:00',
  432.    D'2025.11.05 14:45:00',
  433.    D'2025.11.05 15:00:00',
  434.    D'2025.11.05 15:00:00',
  435.    D'2025.11.05 15:30:00',
  436.    D'2025.11.12 18:00:00',
  437.    D'2025.11.13 17:00:00',
  438.    D'2025.11.13 18:00:00',
  439.    D'2025.11.19 15:30:00',
  440.    D'2025.11.20 12:30:00',
  441.    D'2025.11.20 12:30:00',
  442.    D'2025.11.20 12:30:00',
  443.    D'2025.11.20 13:30:00',
  444.    D'2025.11.20 13:30:00',
  445.    D'2025.11.20 15:00:00',
  446.    D'2025.11.25 12:30:00',
  447.    D'2025.11.25 12:30:00',
  448.    D'2025.11.25 12:30:00',
  449.    D'2025.11.25 15:00:00',
  450.    D'2025.11.26 12:30:00',
  451.    D'2025.11.26 13:30:00',
  452.    D'2025.11.26 14:45:00',
  453.    D'2025.11.26 15:30:00',
  454.    D'2025.12.01 14:45:00',
  455.    D'2025.12.01 15:00:00',
  456.    D'2025.12.01 15:00:00',
  457.    D'2025.12.02 01:00:00',
  458.    D'2025.12.03 13:15:00',
  459.    D'2025.12.03 14:45:00',
  460.    D'2025.12.03 15:00:00',
  461.    D'2025.12.03 15:00:00',
  462.    D'2025.12.03 15:30:00',
  463.    D'2025.12.04 13:30:00',
  464.    D'2025.12.05 15:00:00',
  465.    D'2025.12.05 15:00:00',
  466.    D'2025.12.09 15:00:00',
  467.    D'2025.12.09 18:00:00',
  468.    D'2025.12.10 15:30:00',
  469.    D'2025.12.10 19:00:00',
  470.    D'2025.12.10 19:30:00',
  471.    D'2025.12.11 13:30:00',
  472.    D'2025.12.11 18:00:00',
  473.    D'2025.12.16 13:30:00',
  474.    D'2025.12.16 13:30:00',
  475.    D'2025.12.16 13:30:00',
  476.    D'2025.12.16 13:30:00',
  477.    D'2025.12.16 13:30:00',
  478.    D'2025.12.17 15:30:00',
  479.    D'2025.12.18 13:30:00',
  480.    D'2025.12.18 13:30:00',
  481.    D'2025.12.18 13:30:00',
  482.    D'2025.12.18 13:30:00',
  483.    D'2025.12.18 13:30:00',
  484.    D'2025.12.18 13:30:00',
  485.    D'2025.12.18 13:30:00',
  486.    D'2025.12.19 15:00:00',
  487.    D'2025.12.23 13:30:00',
  488.    D'2025.12.23 13:30:00',
  489.    D'2025.12.23 13:30:00',
  490.    D'2025.12.23 15:00:00',
  491.    D'2025.12.24 13:30:00',
  492.    D'2025.12.24 15:30:00',
  493.    D'2025.12.29 22:00:00',
  494.    D'2025.12.30 14:45:00',
  495.    D'2025.12.31 13:30:00',
  496.    D'2026.01.02 14:45:00',
  497.    D'2026.01.05 15:00:00',
  498.    D'2026.01.05 15:00:00',
  499.    D'2026.01.06 14:45:00',
  500.    D'2026.01.07 13:15:00',
  501.    D'2026.01.07 15:00:00',
  502.    D'2026.01.07 15:00:00',
  503.    D'2026.01.07 15:00:00',
  504.    D'2026.01.07 15:30:00',
  505.    D'2026.01.08 13:30:00',
  506.    D'2026.01.09 13:30:00',
  507.    D'2026.01.09 13:30:00',
  508.    D'2026.01.09 13:30:00',
  509.    D'2026.01.12 18:00:00',
  510.    D'2026.01.13 13:30:00',
  511.    D'2026.01.13 13:30:00',
  512.    D'2026.01.13 13:30:00',
  513.    D'2026.01.13 13:30:00',
  514.    D'2026.01.13 13:30:00',
  515.    D'2026.01.13 15:00:00',
  516.    D'2026.01.13 18:00:00',
  517.    D'2026.01.14 13:30:00',
  518.    D'2026.01.14 13:30:00',
  519.    D'2026.01.14 13:30:00',
  520.    D'2026.01.14 15:30:00',
  521.    D'2026.01.15 13:30:00',
  522.    D'2026.01.15 13:30:00',
  523.    D'2026.01.22 13:30:00',
  524.    D'2026.01.22 13:30:00',
  525.    D'2026.01.22 13:30:00',
  526.    D'2026.01.22 15:00:00',
  527.    D'2026.01.22 15:00:00',
  528.    D'2026.01.22 17:00:00',
  529.    D'2026.01.26 13:30:00',
  530.    D'2026.01.27 15:00:00',
  531.    D'2026.01.28 15:30:00',
  532.    D'2026.01.28 19:00:00',
  533.    D'2026.01.28 19:30:00',
  534.    D'2026.01.29 13:30:00',
  535.    D'2026.01.30 13:30:00',
  536.    D'2026.01.30 14:45:00',
  537.    D'2026.02.02 15:00:00',
  538.    D'2026.02.02 15:00:00',
  539.    D'2026.02.04 13:15:00',
  540.    D'2026.02.04 15:00:00',
  541.    D'2026.02.04 15:00:00',
  542.    D'2026.02.04 15:30:00',
  543.    D'2026.02.05 13:30:00',
  544.    D'2026.02.05 15:00:00',
  545.    D'2026.02.10 13:30:00',
  546.    D'2026.02.10 13:30:00',
  547.    D'2026.02.11 13:30:00',
  548.    D'2026.02.11 13:30:00',
  549.    D'2026.02.11 13:30:00',
  550.    D'2026.02.11 15:30:00',
  551.    D'2026.02.11 18:00:00',
  552.    D'2026.02.12 13:30:00',
  553.    D'2026.02.12 15:00:00',
  554.    D'2026.02.12 18:00:00',
  555.    D'2026.02.13 13:30:00',
  556.    D'2026.02.13 13:30:00',
  557.    D'2026.02.13 13:30:00',
  558.    D'2026.02.13 13:30:00',
  559.    D'2026.02.13 13:30:00',
  560.    D'2026.02.18 13:30:00',
  561.    D'2026.02.19 13:30:00',
  562.    D'2026.02.19 13:30:00',
  563.    D'2026.02.19 17:00:00',
  564.    D'2026.02.20 13:30:00',
  565.    D'2026.02.20 13:30:00',
  566.    D'2026.02.20 13:30:00',
  567.    D'2026.02.20 13:30:00',
  568.    D'2026.02.20 15:00:00',
  569.    D'2026.02.24 15:00:00',
  570.    D'2026.02.25 15:30:00',
  571.    D'2026.02.26 13:30:00',
  572.    D'2026.02.27 13:30:00',
  573.    D'2026.02.27 14:45:00',
  574.    D'2026.03.02 14:45:00',
  575.    D'2026.03.02 15:00:00',
  576.    D'2026.03.02 15:00:00',
  577.    D'2026.03.04 13:15:00',
  578.    D'2026.03.04 14:45:00',
  579.    D'2026.03.04 15:00:00',
  580.    D'2026.03.04 15:00:00',
  581.    D'2026.03.04 15:30:00',
  582.    D'2026.03.05 13:30:00',
  583.    D'2026.03.06 13:30:00',
  584.    D'2026.03.06 13:30:00',
  585.    D'2026.03.06 13:30:00',
  586.    D'2026.03.06 13:30:00',
  587.    D'2026.03.06 13:30:00',
  588.    D'2026.03.10 14:00:00',
  589.    D'2026.03.11 12:30:00',
  590.    D'2026.03.11 12:30:00',
  591.    D'2026.03.11 12:30:00',
  592.    D'2026.03.11 12:30:00',
  593.    D'2026.03.11 12:30:00',
  594.    D'2026.03.11 14:30:00',
  595.    D'2026.03.11 17:00:00',
  596.    D'2026.03.12 12:30:00',
  597.    D'2026.03.12 17:00:00',
  598.    D'2026.03.13 12:30:00',
  599.    D'2026.03.13 12:30:00',
  600.    D'2026.03.13 12:30:00',
  601.    D'2026.03.13 12:30:00',
  602.    D'2026.03.13 12:30:00',
  603.    D'2026.03.13 14:00:00',
  604.    D'2026.03.18 12:30:00',
  605.    D'2026.03.18 14:30:00',
  606.    D'2026.03.18 18:00:00',
  607.    D'2026.03.18 18:30:00',
  608.    D'2026.03.19 12:30:00',
  609.    D'2026.03.19 12:30:00',
  610.    D'2026.03.19 14:00:00',
  611.    D'2026.03.21 17:30:00',
  612.    D'2026.03.25 14:30:00',
  613.    D'2026.03.26 12:30:00',
  614.    D'2026.03.30 14:30:00',
  615.    D'2026.03.31 13:45:00',
  616.    D'2026.03.31 14:00:00',
  617.    D'2026.03.31 14:00:00',
  618.    D'2026.04.01 12:15:00',
  619.    D'2026.04.01 12:30:00',
  620.    D'2026.04.01 12:30:00',
  621.    D'2026.04.01 13:45:00',
  622.    D'2026.04.01 14:00:00',
  623.    D'2026.04.01 14:00:00',
  624.    D'2026.04.01 14:30:00',
  625.    D'2026.04.02 12:30:00',
  626.    D'2026.04.03 12:30:00',
  627.    D'2026.04.03 12:30:00',
  628.    D'2026.04.03 12:30:00',
  629.    D'2026.04.03 13:45:00',
  630.    D'2026.04.03 14:00:00',
  631.    D'2026.04.03 14:00:00'
  632.   };
  633. string GOLDKING_BACKTEST_USD_HIGH_NEWS_NAMES[GOLDKING_BACKTEST_USD_HIGH_NEWS_COUNT]=
  634.   {
  635.    "Initial Jobless Claims",
  636.    "S&P Global Manufacturing PMI",
  637.    "EIA Crude Oil Stocks Change",
  638.    "ISM Manufacturing PMI",
  639.    "ISM Manufacturing Prices Paid",
  640.    "S&P Global Services PMI",
  641.    "ISM Non-Manufacturing PMI",
  642.    "ISM Non-Manufacturing Prices Paid",
  643.    "JOLTS Job Openings",
  644.    "10-Year Note Auction",
  645.    "ADP Nonfarm Employment Change",
  646.    "Initial Jobless Claims",
  647.    "EIA Crude Oil Stocks Change",
  648.    "30-Year Bond Auction",
  649.    "Average Hourly Earnings m/m",
  650.    "Nonfarm Payrolls",
  651.    "Unemployment Rate",
  652.    "PPI m/m",
  653.    "CPI",
  654.    "CPI m/m",
  655.    "CPI y/y",
  656.    "Core CPI m/m",
  657.    "Core CPI n.s.a. m/m",
  658.    "EIA Crude Oil Stocks Change",
  659.    "Core Retail Sales m/m",
  660.    "Initial Jobless Claims",
  661.    "Philadelphia Fed Manufacturing Index",
  662.    "Retail Sales m/m",
  663.    "Initial Jobless Claims",
  664.    "EIA Crude Oil Stocks Change",
  665.    "Existing Home Sales",
  666.    "New Home Sales",
  667.    "Durable Goods Orders m/m",
  668.    "CB Consumer Confidence Index",
  669.    "EIA Crude Oil Stocks Change",
  670.    "Fed Interest Rate Decision",
  671.    "FOMC Press Conference",
  672.    "GDP Sales q/q",
  673.    "GDP q/q",
  674.    "Initial Jobless Claims",
  675.    "Core PCE Price Index m/m",
  676.    "Core PCE Price Index y/y",
  677.    "MNI Chicago Business Barometer",
  678.    "S&P Global Manufacturing PMI",
  679.    "ISM Manufacturing PMI",
  680.    "ISM Manufacturing Prices Paid",
  681.    "JOLTS Job Openings",
  682.    "ADP Nonfarm Employment Change",
  683.    "S&P Global Services PMI",
  684.    "ISM Non-Manufacturing PMI",
  685.    "ISM Non-Manufacturing Prices Paid",
  686.    "EIA Crude Oil Stocks Change",
  687.    "Initial Jobless Claims",
  688.    "Average Hourly Earnings m/m",
  689.    "Nonfarm Payrolls",
  690.    "Unemployment Rate",
  691.    "Fed Chair Powell Testimony",
  692.    "CPI",
  693.    "CPI m/m",
  694.    "CPI y/y",
  695.    "Core CPI m/m",
  696.    "Core CPI n.s.a. m/m",
  697.    "Fed Chair Powell Testimony",
  698.    "EIA Crude Oil Stocks Change",
  699.    "10-Year Note Auction",
  700.    "Initial Jobless Claims",
  701.    "PPI m/m",
  702.    "30-Year Bond Auction",
  703.    "Core Retail Sales m/m",
  704.    "Retail Sales m/m",
  705.    "Initial Jobless Claims",
  706.    "Philadelphia Fed Manufacturing Index",
  707.    "EIA Crude Oil Stocks Change",
  708.    "Existing Home Sales",
  709.    "CB Consumer Confidence Index",
  710.    "New Home Sales",
  711.    "EIA Crude Oil Stocks Change",
  712.    "Durable Goods Orders m/m",
  713.    "GDP Sales q/q",
  714.    "GDP q/q",
  715.    "Initial Jobless Claims",
  716.    "Core PCE Price Index m/m",
  717.    "Core PCE Price Index y/y",
  718.    "MNI Chicago Business Barometer",
  719.    "S&P Global Manufacturing PMI",
  720.    "ISM Manufacturing PMI",
  721.    "ISM Manufacturing Prices Paid",
  722.    "ADP Nonfarm Employment Change",
  723.    "S&P Global Services PMI",
  724.    "ISM Non-Manufacturing PMI",
  725.    "ISM Non-Manufacturing Prices Paid",
  726.    "EIA Crude Oil Stocks Change",
  727.    "Initial Jobless Claims",
  728.    "Average Hourly Earnings m/m",
  729.    "Nonfarm Payrolls",
  730.    "Unemployment Rate",
  731.    "Fed Chair Powell Speech",
  732.    "JOLTS Job Openings",
  733.    "CPI",
  734.    "CPI m/m",
  735.    "CPI y/y",
  736.    "Core CPI m/m",
  737.    "Core CPI n.s.a. m/m",
  738.    "EIA Crude Oil Stocks Change",
  739.    "10-Year Note Auction",
  740.    "Initial Jobless Claims",
  741.    "PPI m/m",
  742.    "30-Year Bond Auction",
  743.    "Core Retail Sales m/m",
  744.    "Retail Sales m/m",
  745.    "EIA Crude Oil Stocks Change",
  746.    "Fed Interest Rate Decision",
  747.    "FOMC Press Conference",
  748.    "Initial Jobless Claims",
  749.    "Philadelphia Fed Manufacturing Index",
  750.    "Existing Home Sales",
  751.    "CB Consumer Confidence Index",
  752.    "New Home Sales",
  753.    "Durable Goods Orders m/m",
  754.    "EIA Crude Oil Stocks Change",
  755.    "GDP Sales q/q",
  756.    "GDP q/q",
  757.    "Initial Jobless Claims",
  758.    "Core PCE Price Index m/m",
  759.    "Core PCE Price Index y/y",
  760.    "MNI Chicago Business Barometer",
  761.    "S&P Global Manufacturing PMI",
  762.    "ISM Manufacturing PMI",
  763.    "ISM Manufacturing Prices Paid",
  764.    "JOLTS Job Openings",
  765.    "ADP Nonfarm Employment Change",
  766.    "EIA Crude Oil Stocks Change",
  767.    "Initial Jobless Claims",
  768.    "S&P Global Services PMI",
  769.    "ISM Non-Manufacturing PMI",
  770.    "ISM Non-Manufacturing Prices Paid",
  771.    "Average Hourly Earnings m/m",
  772.    "Nonfarm Payrolls",
  773.    "Unemployment Rate",
  774.    "Fed Chair Powell Speech",
  775.    "EIA Crude Oil Stocks Change",
  776.    "10-Year Note Auction",
  777.    "CPI",
  778.    "CPI m/m",
  779.    "CPI y/y",
  780.    "Core CPI m/m",
  781.    "Core CPI n.s.a. m/m",
  782.    "Initial Jobless Claims",
  783.    "30-Year Bond Auction",
  784.    "PPI m/m",
  785.    "Core Retail Sales m/m",
  786.    "Retail Sales m/m",
  787.    "EIA Crude Oil Stocks Change",
  788.    "Fed Chair Powell Speech",
  789.    "Initial Jobless Claims",
  790.    "Philadelphia Fed Manufacturing Index",
  791.    "New Home Sales",
  792.    "EIA Crude Oil Stocks Change",
  793.    "Durable Goods Orders m/m",
  794.    "Initial Jobless Claims",
  795.    "Existing Home Sales",
  796.    "CB Consumer Confidence Index",
  797.    "JOLTS Job Openings",
  798.    "ADP Nonfarm Employment Change",
  799.    "GDP Sales q/q",
  800.    "GDP q/q",
  801.    "MNI Chicago Business Barometer",
  802.    "Core PCE Price Index m/m",
  803.    "Core PCE Price Index y/y",
  804.    "EIA Crude Oil Stocks Change",
  805.    "Initial Jobless Claims",
  806.    "S&P Global Manufacturing PMI",
  807.    "ISM Manufacturing PMI",
  808.    "ISM Manufacturing Prices Paid",
  809.    "Average Hourly Earnings m/m",
  810.    "Nonfarm Payrolls",
  811.    "Unemployment Rate",
  812.    "S&P Global Services PMI",
  813.    "ISM Non-Manufacturing PMI",
  814.    "ISM Non-Manufacturing Prices Paid",
  815.    "10-Year Note Auction",
  816.    "EIA Crude Oil Stocks Change",
  817.    "Fed Interest Rate Decision",
  818.    "FOMC Press Conference",
  819.    "Initial Jobless Claims",
  820.    "30-Year Bond Auction",
  821.    "CPI",
  822.    "CPI m/m",
  823.    "CPI y/y",
  824.    "Core CPI m/m",
  825.    "Core CPI n.s.a. m/m",
  826.    "EIA Crude Oil Stocks Change",
  827.    "Core Retail Sales m/m",
  828.    "Initial Jobless Claims",
  829.    "PPI m/m",
  830.    "Philadelphia Fed Manufacturing Index",
  831.    "Retail Sales m/m",
  832.    "Fed Chair Powell Speech",
  833.    "EIA Crude Oil Stocks Change",
  834.    "Initial Jobless Claims",
  835.    "Existing Home Sales",
  836.    "New Home Sales",
  837.    "Fed Chair Powell Speech",
  838.    "Durable Goods Orders m/m",
  839.    "CB Consumer Confidence Index",
  840.    "GDP Sales q/q",
  841.    "GDP q/q",
  842.    "Initial Jobless Claims",
  843.    "EIA Crude Oil Stocks Change",
  844.    "Core PCE Price Index m/m",
  845.    "Core PCE Price Index y/y",
  846.    "MNI Chicago Business Barometer",
  847.    "S&P Global Manufacturing PMI",
  848.    "ISM Manufacturing PMI",
  849.    "ISM Manufacturing Prices Paid",
  850.    "Fed Chair Powell Speech",
  851.    "JOLTS Job Openings",
  852.    "ADP Nonfarm Employment Change",
  853.    "S&P Global Services PMI",
  854.    "ISM Non-Manufacturing PMI",
  855.    "ISM Non-Manufacturing Prices Paid",
  856.    "EIA Crude Oil Stocks Change",
  857.    "Initial Jobless Claims",
  858.    "Average Hourly Earnings m/m",
  859.    "Nonfarm Payrolls",
  860.    "Unemployment Rate",
  861.    "CPI",
  862.    "CPI m/m",
  863.    "CPI y/y",
  864.    "Core CPI m/m",
  865.    "Core CPI n.s.a. m/m",
  866.    "EIA Crude Oil Stocks Change",
  867.    "10-Year Note Auction",
  868.    "Initial Jobless Claims",
  869.    "PPI m/m",
  870.    "30-Year Bond Auction",
  871.    "Core Retail Sales m/m",
  872.    "Retail Sales m/m",
  873.    "Initial Jobless Claims",
  874.    "EIA Crude Oil Stocks Change",
  875.    "Fed Interest Rate Decision",
  876.    "FOMC Press Conference",
  877.    "Philadelphia Fed Manufacturing Index",
  878.    "Existing Home Sales",
  879.    "CB Consumer Confidence Index",
  880.    "Fed Chair Powell Testimony",
  881.    "Fed Chair Powell Testimony",
  882.    "New Home Sales",
  883.    "EIA Crude Oil Stocks Change",
  884.    "Durable Goods Orders m/m",
  885.    "GDP Sales q/q",
  886.    "GDP q/q",
  887.    "Initial Jobless Claims",
  888.    "Core PCE Price Index m/m",
  889.    "Core PCE Price Index y/y",
  890.    "MNI Chicago Business Barometer",
  891.    "Fed Chair Powell Speech",
  892.    "S&P Global Manufacturing PMI",
  893.    "ISM Manufacturing PMI",
  894.    "ISM Manufacturing Prices Paid",
  895.    "JOLTS Job Openings",
  896.    "ADP Nonfarm Employment Change",
  897.    "EIA Crude Oil Stocks Change",
  898.    "Average Hourly Earnings m/m",
  899.    "Initial Jobless Claims",
  900.    "Nonfarm Payrolls",
  901.    "Unemployment Rate",
  902.    "S&P Global Services PMI",
  903.    "ISM Non-Manufacturing PMI",
  904.    "ISM Non-Manufacturing Prices Paid",
  905.    "EIA Crude Oil Stocks Change",
  906.    "10-Year Note Auction",
  907.    "Initial Jobless Claims",
  908.    "30-Year Bond Auction",
  909.    "CPI",
  910.    "CPI m/m",
  911.    "CPI y/y",
  912.    "Core CPI m/m",
  913.    "Core CPI n.s.a. m/m",
  914.    "PPI m/m",
  915.    "EIA Crude Oil Stocks Change",
  916.    "Core Retail Sales m/m",
  917.    "Initial Jobless Claims",
  918.    "Philadelphia Fed Manufacturing Index",
  919.    "Retail Sales m/m",
  920.    "Fed Chair Powell Speech",
  921.    "Existing Home Sales",
  922.    "EIA Crude Oil Stocks Change",
  923.    "Initial Jobless Claims",
  924.    "New Home Sales",
  925.    "Durable Goods Orders m/m",
  926.    "CB Consumer Confidence Index",
  927.    "JOLTS Job Openings",
  928.    "ADP Nonfarm Employment Change",
  929.    "GDP Sales q/q",
  930.    "GDP q/q",
  931.    "EIA Crude Oil Stocks Change",
  932.    "Fed Interest Rate Decision",
  933.    "FOMC Press Conference",
  934.    "Core PCE Price Index m/m",
  935.    "Core PCE Price Index y/y",
  936.    "Initial Jobless Claims",
  937.    "MNI Chicago Business Barometer",
  938.    "Average Hourly Earnings m/m",
  939.    "Nonfarm Payrolls",
  940.    "Unemployment Rate",
  941.    "S&P Global Manufacturing PMI",
  942.    "ISM Manufacturing PMI",
  943.    "ISM Manufacturing Prices Paid",
  944.    "S&P Global Services PMI",
  945.    "ISM Non-Manufacturing PMI",
  946.    "ISM Non-Manufacturing Prices Paid",
  947.    "EIA Crude Oil Stocks Change",
  948.    "10-Year Note Auction",
  949.    "Initial Jobless Claims",
  950.    "30-Year Bond Auction",
  951.    "CPI",
  952.    "CPI m/m",
  953.    "CPI y/y",
  954.    "Core CPI m/m",
  955.    "Core CPI n.s.a. m/m",
  956.    "EIA Crude Oil Stocks Change",
  957.    "Initial Jobless Claims",
  958.    "PPI m/m",
  959.    "Core Retail Sales m/m",
  960.    "Retail Sales m/m",
  961.    "EIA Crude Oil Stocks Change",
  962.    "Initial Jobless Claims",
  963.    "Philadelphia Fed Manufacturing Index",
  964.    "Existing Home Sales",
  965.    "Fed Chair Powell Speech",
  966.    "New Home Sales",
  967.    "Durable Goods Orders m/m",
  968.    "CB Consumer Confidence Index",
  969.    "EIA Crude Oil Stocks Change",
  970.    "GDP Sales q/q",
  971.    "GDP q/q",
  972.    "Initial Jobless Claims",
  973.    "Core PCE Price Index m/m",
  974.    "Core PCE Price Index y/y",
  975.    "MNI Chicago Business Barometer",
  976.    "S&P Global Manufacturing PMI",
  977.    "ISM Manufacturing PMI",
  978.    "ISM Manufacturing Prices Paid",
  979.    "JOLTS Job Openings",
  980.    "ADP Nonfarm Employment Change",
  981.    "Initial Jobless Claims",
  982.    "S&P Global Services PMI",
  983.    "ISM Non-Manufacturing PMI",
  984.    "ISM Non-Manufacturing Prices Paid",
  985.    "EIA Crude Oil Stocks Change",
  986.    "Average Hourly Earnings m/m",
  987.    "Nonfarm Payrolls",
  988.    "Unemployment Rate",
  989.    "PPI m/m",
  990.    "EIA Crude Oil Stocks Change",
  991.    "10-Year Note Auction",
  992.    "CPI",
  993.    "CPI m/m",
  994.    "CPI y/y",
  995.    "Core CPI m/m",
  996.    "Core CPI n.s.a. m/m",
  997.    "Initial Jobless Claims",
  998.    "30-Year Bond Auction",
  999.    "Core Retail Sales m/m",
  1000.    "Retail Sales m/m",
  1001.    "EIA Crude Oil Stocks Change",
  1002.    "Fed Interest Rate Decision",
  1003.    "FOMC Press Conference",
  1004.    "Initial Jobless Claims",
  1005.    "Philadelphia Fed Manufacturing Index",
  1006.    "Existing Home Sales",
  1007.    "Fed Chair Powell Speech",
  1008.    "New Home Sales",
  1009.    "EIA Crude Oil Stocks Change",
  1010.    "Durable Goods Orders m/m",
  1011.    "GDP Sales q/q",
  1012.    "GDP q/q",
  1013.    "Initial Jobless Claims",
  1014.    "Core PCE Price Index m/m",
  1015.    "Core PCE Price Index y/y",
  1016.    "MNI Chicago Business Barometer",
  1017.    "CB Consumer Confidence Index",
  1018.    "JOLTS Job Openings",
  1019.    "ADP Nonfarm Employment Change",
  1020.    "S&P Global Manufacturing PMI",
  1021.    "ISM Manufacturing PMI",
  1022.    "ISM Manufacturing Prices Paid",
  1023.    "EIA Crude Oil Stocks Change",
  1024.    "S&P Global Services PMI",
  1025.    "ISM Non-Manufacturing PMI",
  1026.    "ISM Non-Manufacturing Prices Paid",
  1027.    "EIA Crude Oil Stocks Change",
  1028.    "10-Year Note Auction",
  1029.    "Fed Chair Powell Speech",
  1030.    "30-Year Bond Auction",
  1031.    "Fed Chair Powell Speech",
  1032.    "Philadelphia Fed Manufacturing Index",
  1033.    "EIA Crude Oil Stocks Change",
  1034.    "EIA Crude Oil Stocks Change",
  1035.    "Existing Home Sales",
  1036.    "CPI",
  1037.    "CPI m/m",
  1038.    "CPI y/y",
  1039.    "Core CPI m/m",
  1040.    "Core CPI n.s.a. m/m",
  1041.    "CB Consumer Confidence Index",
  1042.    "EIA Crude Oil Stocks Change",
  1043.    "Fed Interest Rate Decision",
  1044.    "FOMC Press Conference",
  1045.    "MNI Chicago Business Barometer",
  1046.    "S&P Global Manufacturing PMI",
  1047.    "ISM Manufacturing PMI",
  1048.    "ISM Manufacturing Prices Paid",
  1049.    "ADP Nonfarm Employment Change",
  1050.    "S&P Global Services PMI",
  1051.    "ISM Non-Manufacturing PMI",
  1052.    "ISM Non-Manufacturing Prices Paid",
  1053.    "EIA Crude Oil Stocks Change",
  1054.    "10-Year Note Auction",
  1055.    "EIA Crude Oil Stocks Change",
  1056.    "30-Year Bond Auction",
  1057.    "EIA Crude Oil Stocks Change",
  1058.    "Average Hourly Earnings m/m",
  1059.    "Nonfarm Payrolls",
  1060.    "Unemployment Rate",
  1061.    "Initial Jobless Claims",
  1062.    "Philadelphia Fed Manufacturing Index",
  1063.    "Existing Home Sales",
  1064.    "Core Retail Sales m/m",
  1065.    "PPI m/m",
  1066.    "Retail Sales m/m",
  1067.    "CB Consumer Confidence Index",
  1068.    "Durable Goods Orders m/m",
  1069.    "Initial Jobless Claims",
  1070.    "MNI Chicago Business Barometer",
  1071.    "EIA Crude Oil Stocks Change",
  1072.    "S&P Global Manufacturing PMI",
  1073.    "ISM Manufacturing PMI",
  1074.    "ISM Manufacturing Prices Paid",
  1075.    "Fed Chair Powell Speech",
  1076.    "ADP Nonfarm Employment Change",
  1077.    "S&P Global Services PMI",
  1078.    "ISM Non-Manufacturing PMI",
  1079.    "ISM Non-Manufacturing Prices Paid",
  1080.    "EIA Crude Oil Stocks Change",
  1081.    "Initial Jobless Claims",
  1082.    "Core PCE Price Index m/m",
  1083.    "Core PCE Price Index y/y",
  1084.    "JOLTS Job Openings",
  1085.    "10-Year Note Auction",
  1086.    "EIA Crude Oil Stocks Change",
  1087.    "Fed Interest Rate Decision",
  1088.    "FOMC Press Conference",
  1089.    "Initial Jobless Claims",
  1090.    "30-Year Bond Auction",
  1091.    "Average Hourly Earnings m/m",
  1092.    "Core Retail Sales m/m",
  1093.    "Nonfarm Payrolls",
  1094.    "Retail Sales m/m",
  1095.    "Unemployment Rate",
  1096.    "EIA Crude Oil Stocks Change",
  1097.    "CPI",
  1098.    "CPI m/m",
  1099.    "CPI y/y",
  1100.    "Core CPI m/m",
  1101.    "Core CPI n.s.a. m/m",
  1102.    "Initial Jobless Claims",
  1103.    "Philadelphia Fed Manufacturing Index",
  1104.    "Existing Home Sales",
  1105.    "Durable Goods Orders m/m",
  1106.    "GDP Sales q/q",
  1107.    "GDP q/q",
  1108.    "CB Consumer Confidence Index",
  1109.    "Initial Jobless Claims",
  1110.    "EIA Crude Oil Stocks Change",
  1111.    "EIA Crude Oil Stocks Change",
  1112.    "MNI Chicago Business Barometer",
  1113.    "Initial Jobless Claims",
  1114.    "S&P Global Manufacturing PMI",
  1115.    "ISM Manufacturing PMI",
  1116.    "ISM Manufacturing Prices Paid",
  1117.    "S&P Global Services PMI",
  1118.    "ADP Nonfarm Employment Change",
  1119.    "ISM Non-Manufacturing PMI",
  1120.    "ISM Non-Manufacturing Prices Paid",
  1121.    "JOLTS Job Openings",
  1122.    "EIA Crude Oil Stocks Change",
  1123.    "Initial Jobless Claims",
  1124.    "Average Hourly Earnings m/m",
  1125.    "Nonfarm Payrolls",
  1126.    "Unemployment Rate",
  1127.    "10-Year Note Auction",
  1128.    "CPI",
  1129.    "CPI m/m",
  1130.    "CPI y/y",
  1131.    "Core CPI m/m",
  1132.    "Core CPI n.s.a. m/m",
  1133.    "New Home Sales",
  1134.    "30-Year Bond Auction",
  1135.    "Core Retail Sales m/m",
  1136.    "PPI m/m",
  1137.    "Retail Sales m/m",
  1138.    "EIA Crude Oil Stocks Change",
  1139.    "Initial Jobless Claims",
  1140.    "Philadelphia Fed Manufacturing Index",
  1141.    "GDP Sales q/q",
  1142.    "GDP q/q",
  1143.    "Initial Jobless Claims",
  1144.    "Core PCE Price Index m/m",
  1145.    "Core PCE Price Index y/y",
  1146.    "EIA Crude Oil Stocks Change",
  1147.    "Durable Goods Orders m/m",
  1148.    "CB Consumer Confidence Index",
  1149.    "EIA Crude Oil Stocks Change",
  1150.    "Fed Interest Rate Decision",
  1151.    "FOMC Press Conference",
  1152.    "Initial Jobless Claims",
  1153.    "PPI m/m",
  1154.    "MNI Chicago Business Barometer",
  1155.    "ISM Manufacturing PMI",
  1156.    "ISM Manufacturing Prices Paid",
  1157.    "ADP Nonfarm Employment Change",
  1158.    "ISM Non-Manufacturing PMI",
  1159.    "ISM Non-Manufacturing Prices Paid",
  1160.    "EIA Crude Oil Stocks Change",
  1161.    "Initial Jobless Claims",
  1162.    "JOLTS Job Openings",
  1163.    "Core Retail Sales m/m",
  1164.    "Retail Sales m/m",
  1165.    "Average Hourly Earnings m/m",
  1166.    "Nonfarm Payrolls",
  1167.    "Unemployment Rate",
  1168.    "EIA Crude Oil Stocks Change",
  1169.    "10-Year Note Auction",
  1170.    "Initial Jobless Claims",
  1171.    "Existing Home Sales",
  1172.    "30-Year Bond Auction",
  1173.    "CPI",
  1174.    "CPI m/m",
  1175.    "CPI y/y",
  1176.    "Core CPI m/m",
  1177.    "Core CPI n.s.a. m/m",
  1178.    "Durable Goods Orders m/m",
  1179.    "Initial Jobless Claims",
  1180.    "Philadelphia Fed Manufacturing Index",
  1181.    "EIA Crude Oil Stocks Change",
  1182.    "Core PCE Price Index m/m",
  1183.    "Core PCE Price Index y/y",
  1184.    "GDP Sales q/q",
  1185.    "GDP q/q",
  1186.    "New Home Sales",
  1187.    "CB Consumer Confidence Index",
  1188.    "EIA Crude Oil Stocks Change",
  1189.    "Initial Jobless Claims",
  1190.    "PPI m/m",
  1191.    "MNI Chicago Business Barometer",
  1192.    "S&P Global Manufacturing PMI",
  1193.    "ISM Manufacturing PMI",
  1194.    "ISM Manufacturing Prices Paid",
  1195.    "ADP Nonfarm Employment Change",
  1196.    "S&P Global Services PMI",
  1197.    "ISM Non-Manufacturing PMI",
  1198.    "ISM Non-Manufacturing Prices Paid",
  1199.    "EIA Crude Oil Stocks Change",
  1200.    "Initial Jobless Claims",
  1201.    "Average Hourly Earnings m/m",
  1202.    "Core Retail Sales m/m",
  1203.    "Nonfarm Payrolls",
  1204.    "Retail Sales m/m",
  1205.    "Unemployment Rate",
  1206.    "Existing Home Sales",
  1207.    "CPI",
  1208.    "CPI m/m",
  1209.    "CPI y/y",
  1210.    "Core CPI m/m",
  1211.    "Core CPI n.s.a. m/m",
  1212.    "EIA Crude Oil Stocks Change",
  1213.    "10-Year Note Auction",
  1214.    "Initial Jobless Claims",
  1215.    "30-Year Bond Auction",
  1216.    "Core PCE Price Index m/m",
  1217.    "Core PCE Price Index y/y",
  1218.    "Durable Goods Orders m/m",
  1219.    "GDP Sales q/q",
  1220.    "GDP q/q",
  1221.    "JOLTS Job Openings",
  1222.    "PPI m/m",
  1223.    "EIA Crude Oil Stocks Change",
  1224.    "Fed Interest Rate Decision",
  1225.    "FOMC Press Conference",
  1226.    "Initial Jobless Claims",
  1227.    "Philadelphia Fed Manufacturing Index",
  1228.    "New Home Sales",
  1229.    "Fed Chair Powell Speech",
  1230.    "EIA Crude Oil Stocks Change",
  1231.    "Initial Jobless Claims",
  1232.    "Fed Chair Powell Speech",
  1233.    "MNI Chicago Business Barometer",
  1234.    "CB Consumer Confidence Index",
  1235.    "JOLTS Job Openings",
  1236.    "ADP Nonfarm Employment Change",
  1237.    "Core Retail Sales m/m",
  1238.    "Retail Sales m/m",
  1239.    "S&P Global Manufacturing PMI",
  1240.    "ISM Manufacturing PMI",
  1241.    "ISM Manufacturing Prices Paid",
  1242.    "EIA Crude Oil Stocks Change",
  1243.    "Initial Jobless Claims",
  1244.    "Average Hourly Earnings m/m",
  1245.    "Nonfarm Payrolls",
  1246.    "Unemployment Rate",
  1247.    "S&P Global Services PMI",
  1248.    "ISM Non-Manufacturing PMI",
  1249.    "ISM Non-Manufacturing Prices Paid"
  1250.   };
  1251. // --- Embedded USD high-impact backtest news end ---
  1252. enum OpenModeEnum
  1253.   {
  1254.    OpenMode_Bar      = 1,
  1255.    OpenMode_Interval = 2,
  1256.    OpenMode_NoDelay  = 3
  1257.   };
  1258. input group "Grid"
  1259. input double         On_top_of_this_price_not_Buy_order      = 0.0;     // B以上不开(补)
  1260. input double         On_under_of_this_price_not_Sell_order   = 0.0;     // S以下不开(补)
  1261. input string         Limit_StartTime                         = "00:00"; // 限价开始时间
  1262. input string         Limit_StopTime                          = "24:00"; // 限价结束时间
  1263. input bool           CloseBuySell                            = true;    // 逆势保护开关
  1264. input bool           HomeopathyCloseAll                      = true;    // 顺势保护开关
  1265. input bool           Homeopathy                              = false;   // 完全对锁时挂上顺势开关
  1266. input bool           Over                                    = false;   // 平仓后停止交易
  1267. input int            NextTime                                = 0;       // 整体平仓后多少秒后新局
  1268. input double         Money                                   = 0.0;     // 浮亏多少启用第二参数
  1269. input int            FirstStep                               = 30;      // 首单距离
  1270. input int            MinDistance                             = 60;      // 最小距离
  1271. input int            TwoMinDistance                          = 60;      // 第二最小距离
  1272. input int            StepTrallOrders                         = 5;       // 挂单追踪点数
  1273. input int            Step                                    = 100;     // 补单间距
  1274. input int            TwoStep                                 = 100;     // 第二补单间距
  1275. input OpenModeEnum   OpenMode                                = OpenMode_NoDelay;
  1276. input ENUM_TIMEFRAMES TimeZone                               = PERIOD_M1; // 开单时区
  1277. input int            sleep                                   = 30;      // 开单时间间距(秒)
  1278. input double         MaxLoss                                 = 100000.0;// 单边浮亏超过多少不继续加仓
  1279. input double         MaxLossCloseAll                         = 50.0;    // 单边平仓限制
  1280. input group "Risk"
  1281. input double         lot                                     = 0.01;    // 起始手数
  1282. input double         Maxlot                                  = 10.0;    // 最大开单手数
  1283. input double         PlusLot                                 = 0.0;     // 累加手数
  1284. input double         K_Lot                                   = 1.3;     // 倍率
  1285. input int            DigitsLot                               = 2;       // 下单量小数位
  1286. input double         CloseAll                                = 0.5;     // 整体平仓金额
  1287. input bool           Profit                                  = true;    // 单边平仓金额累加开关
  1288. input double         StopProfit                              = 2.0;     // 单边平仓金额
  1289. input double         StopLoss                                = 0.0;     // 止损金额
  1290. input long           Magic                                   = 958999848;
  1291. input int            Totals                                  = 50;      // 最大单量
  1292. input int            MaxSpread                               = 60;      // 点差限制(点)
  1293. input int            Leverage                                = 100;     // 平台杠杆限制
  1294. input group "Session"
  1295. input bool           EnableTradingSessionWindow             = true;    // 启用工作时间段控制
  1296. input string         EA_StartTime                            = "00:00"; // EA开始时间
  1297. input string         EA_StopTime                             = "24:00"; // EA结束时间
  1298. input bool           EnableDailyWrapUpPhase                 = true;    // 启用日内收尾阶段
  1299. input string         DailyWrapUpStartTime                   = "20:00"; // 收尾开始(盘面/服务器时间)
  1300. input string         DailyWrapUpStopTime                    = "24:00"; // 收尾结束(盘面/服务器时间)
  1301. input bool           EnableDailyProfitTarget                = true;    // 启用每日盈利目标
  1302. input double         DailyProfitTarget                       = 50.0;    // 每日盈利目标,达到后封盘
  1303. input bool           EnableHighImpactNewsPause              = true;    // 启用高影响新闻暂停
  1304. input int            NewsLeadMinutes                        = 180;     // 新闻前等待平仓分钟
  1305. input int            NewsCooldownMinutes                    = 180;     // 新闻后暂停分钟
  1306. input group "Visual"
  1307. input color          clr1                                    = MediumSeaGreen; // 多单均价线
  1308. input color          clr2                                    = Crimson;        // 空单均价线
  1309. struct EAStats
  1310.   {
  1311.    int               buy_positions;
  1312.    int               sell_positions;
  1313.    int               buy_pending;
  1314.    int               sell_pending;
  1315.    double            buy_lots;
  1316.    double            sell_lots;
  1317.    double            buy_profit;
  1318.    double            sell_profit;
  1319.    double            total_profit;
  1320.    double            buy_weighted_sum;
  1321.    double            sell_weighted_sum;
  1322.    double            buy_avg_price;
  1323.    double            sell_avg_price;
  1324.    double            buy_highest_any;
  1325.    double            buy_lowest_position;
  1326.    double            sell_highest_position;
  1327.    double            sell_lowest_any;
  1328.    double            buy_pending_price;
  1329.    double            sell_pending_price;
  1330.    ulong             buy_pending_ticket;
  1331.    ulong             sell_pending_ticket;
  1332.    datetime          last_buy_open_time;
  1333.    datetime          last_sell_open_time;
  1334.   };
  1335. struct PanelMetrics
  1336.   {
  1337.    int               margin_x;
  1338.    int               margin_y;
  1339.    int               width;
  1340.    int               pad;
  1341.    int               section_gap;
  1342.    int               header_h;
  1343.    int               row_h;
  1344.    int               gap;
  1345.    int               button_h;
  1346.    int               inner_w;
  1347.    int               half_w;
  1348.    int               card_status_h;
  1349.    int               card_metrics_h;
  1350.    int               card_actions_h;
  1351.    int               button_font;
  1352.    int               font_sm;
  1353.    int               font_xs;
  1354.    int               font_md;
  1355.    int               font_lg;
  1356.    int               panel_h;
  1357.    int               toggle_w;
  1358.   };
  1359. struct NewsWindowState
  1360.   {
  1361.    bool              enabled;
  1362.    bool              calendar_available;
  1363.    bool              using_embedded_history;
  1364.    bool              has_active_window;
  1365.    bool              in_pre_window;
  1366.    bool              in_post_window;
  1367.    bool              has_upcoming_event;
  1368.    bool              block_entries;
  1369.    datetime          server_now;
  1370.    datetime          event_time;
  1371.    datetime          window_start;
  1372.    datetime          resume_time;
  1373.    string            currency;
  1374.    string            event_name;
  1375.   string            error_text;
  1376.   };
  1377. struct NewsEvalAccumulator
  1378.   {
  1379.    bool              any_success;
  1380.    string            first_error;
  1381.    datetime          active_block_start;
  1382.    datetime          active_block_end;
  1383.    datetime          active_future_time;
  1384.    string            active_future_currency;
  1385.    string            active_future_name;
  1386.    datetime          active_past_time;
  1387.    string            active_past_currency;
  1388.    string            active_past_name;
  1389.    datetime          next_upcoming_time;
  1390.    string            next_upcoming_currency;
  1391.    string            next_upcoming_name;
  1392.   };
  1393. CTrade               g_trade;
  1394. bool                 g_allow_buy              = true;
  1395. bool                 g_allow_sell             = true;
  1396. bool                 g_panel_open             = true;
  1397. datetime             g_pause_until            = 0;
  1398. datetime             g_last_open_bar_time     = 0;
  1399. datetime             g_last_panel_refresh     = 0;
  1400. double               g_max_loss_limit         = 0.0;
  1401. double               g_max_loss_close_all     = 0.0;
  1402. double               g_stop_loss_limit        = 0.0;
  1403. double               g_second_loss_threshold  = 0.0;
  1404. double               g_deposit_base           = 100.0;
  1405. double               g_buy_protection_peak    = 0.0;
  1406. double               g_sell_protection_peak   = 0.0;
  1407. string               g_today_key              = "";
  1408. bool                 g_daily_target_locked    = false;
  1409. double               g_daily_target_hit_value = 0.0;
  1410. NewsWindowState      g_news_state;
  1411. datetime             g_news_cache_minute      = 0;
  1412. string               g_panel_prefix           = "GoldKylinMT5.";
  1413. #define GOLDKING_ORDER_COMMENT_PRIMARY   "FXKiller_GoldKing"
  1414. #define GOLDKING_ORDER_COMMENT_SECONDARY "FXKiller_GoldKing_SS"
  1415. bool       IsTestingMode();
  1416. datetime   ReferenceNow();
  1417. datetime   ReferenceNewsNow();
  1418. string     CleanTimeString(const string value);
  1419. datetime   TodayAt(const string time_text,const datetime now_value);
  1420. bool       IsInWindow(const string start_text,const string stop_text,const datetime now_value);
  1421. bool       IsAfterSessionStop(const datetime now_value);
  1422. bool       IsTradingSessionOpen(const datetime now_value);
  1423. bool       IsTradingSessionAfterStop(const datetime now_value);
  1424. bool       IsDailyWrapUpWindow(const datetime now_value);
  1425. void       ResetNewsState(NewsWindowState &state);
  1426. void       ResetNewsEvalAccumulator(NewsEvalAccumulator &eval);
  1427. void       AppendUniqueText(string &items[],const string value);
  1428. void       BuildNewsCurrencies(string &currencies[]);
  1429. string     CalendarErrorText(const int error_code);
  1430. void       ConsiderNewsEvent(const datetime now_server,const datetime event_time,const string currency,const string event_name,const int lead_seconds,const int cooldown_seconds,NewsEvalAccumulator &eval);
  1431. void       ApplyNewsAccumulator(const NewsEvalAccumulator &eval);
  1432. void       RefreshEmbeddedBacktestNewsState(const datetime now_server);
  1433. void       RefreshNewsState(const bool force);
  1434. double     PipDivisor();
  1435. double     CurrentSpreadPoints();
  1436. int        VolumeDigits(const double step);
  1437. double     NormalizeVolumeToSymbol(double volume);
  1438. double     NormalizePriceToSymbol(double price);
  1439. int        BrokerMinDistancePoints();
  1440. bool       IsHedgingAccount();
  1441. void       ResetStats(EAStats &stats);
  1442. void       CollectStats(EAStats &stats);
  1443. double     CalculateDepositBase();
  1444. double     CalculateClosedProfit(const datetime from_time,const datetime to_time,const long magic_filter,const bool current_symbol_only);
  1445. string     TradingDayKey(const datetime now_value);
  1446. double     TodayClosedProfit(const datetime now_value);
  1447. double     TodayProgressProfit(const datetime now_value,const EAStats &stats);
  1448. bool       HasOpenPositions(const EAStats &stats);
  1449. bool       HasActiveExposure(const EAStats &stats);
  1450. void       RefreshDailyLocks(const datetime now_value,const EAStats &stats);
  1451. double     AccountProfitForPanel();
  1452. int        CountPositionsWithComment(const string comment_text,const ENUM_POSITION_TYPE type);
  1453. double     SumExtremePositionProfits(const ENUM_POSITION_TYPE type,const bool positive,const int count);
  1454. ulong      FindExtremePositionTicket(const ENUM_POSITION_TYPE type,const bool positive);
  1455. double     FindExtremePositionLot(const ENUM_POSITION_TYPE type,const bool positive);
  1456. void       CloseExtremePositions(const ENUM_POSITION_TYPE type,int count,const bool positive);
  1457. ulong      FindNewestPositionTicket(const ENUM_POSITION_TYPE type,const bool current_symbol_only,const long magic_filter);
  1458. bool       CloseByPair(const ulong position_ticket,const ulong opposite_ticket);
  1459. void       CloseOppositePairs();
  1460. bool       TradeRetcodeOk(const uint retcode);
  1461. bool       CheckTradeResult(const bool request_ok,const string action);
  1462. bool       CheckOrderSendResult(const bool request_ok,const MqlTradeResult &result,const string action);
  1463. bool       ClosePositionTicket(const ulong ticket);
  1464. bool       DeletePendingOrder(const ulong ticket);
  1465. void       DeleteEaPendingOrders();
  1466. bool       ModifyPendingPrice(const ulong ticket,const double new_price);
  1467. void       CloseEaOrders(const int direction,const bool use_pairs,const bool arm_cooldown);
  1468. void       ClosePositionsByProfitState(const bool close_profit);
  1469. void       CloseCurrentSymbolPositions();
  1470. void       CloseAllAccountPositions();
  1471. bool       IsTradingEnvironmentOk(const EAStats &stats,string &reason);
  1472. void       UpdateLimitLines();
  1473. void       UpdateAverageLines(const EAStats &stats);
  1474. bool       ShouldUsePrimaryParameters(const EAStats &stats);
  1475. bool       AllowBuyOrderByPriceLimit(const EAStats &stats,const double target_price,const bool limit_window_active);
  1476. bool       AllowSellOrderByPriceLimit(const EAStats &stats,const double target_price,const bool limit_window_active);
  1477. bool       CanOpenThisCycle(const bool is_buy,const EAStats &stats);
  1478. bool       TryProtectiveCloseBySide(const EAStats &stats);
  1479. bool       ApplyCloseBuySellProtection(const EAStats &stats);
  1480. bool       TryAutoCloseLogic(const EAStats &stats);
  1481. void       TryPlacePendingOrders(const EAStats &stats,const bool allow_buy,const bool allow_sell);
  1482. void       TryTrailPendingOrders(const EAStats &stats,const bool allow_buy,const bool allow_sell);
  1483. void       ExecuteStrategy();
  1484. double     UiScale();
  1485. double     UiFontScale();
  1486. int        ScalePx(const int value);
  1487. int        ScaleFont(const int value);
  1488. void       BuildPanelMetrics(PanelMetrics &m);
  1489. void       EnsureRectangle(const string name,const int x,const int y,const int w,const int h,const color bg,const color border,const int corner);
  1490. void       EnsureLabel(const string name,const string text,const int x,const int y,const int font_size,const color clr,const int corner,const string font="Microsoft YaHei");
  1491. void       EnsureButton(const string name,const string text,const int x,const int y,const int w,const int h,const color bg,const color fg,const int corner);
  1492. string     BoolText(const bool enabled,const string on_text,const string off_text);
  1493. string     FormatSignedMoney(const double value);
  1494. string     FormatPercent(const double value);
  1495. string     FormatPanelMoment(const datetime when,const datetime now_value);
  1496. string     NewsPauseReason(const EAStats &stats);
  1497. string     WrapUpPauseReason(const EAStats &stats);
  1498. string     SessionStateText(const datetime now_value,const EAStats &stats);
  1499. string     WrapUpStateText(const EAStats &stats);
  1500. string     GoalStateText(const double target_progress_display);
  1501. string     NewsStateText(const EAStats &stats);
  1502. string     EntryStateText(const string stop_reason);
  1503. string     CloseReasonText();
  1504. string     ClipText(const string text,const int max_chars);
  1505. string     TimeframeLabel(const ENUM_TIMEFRAMES timeframe);
  1506. void       DrawPanel(const EAStats &stats);
  1507. void       RefreshPanel(const bool force);
  1508. void       DeleteObjectsByPrefix(const string prefix);
  1509. int OnInit()
  1510.   {
  1511.    g_trade.SetExpertMagicNumber(Magic);
  1512.    g_trade.SetTypeFillingBySymbol(_Symbol);
  1513.    g_trade.SetDeviationInPoints((_Digits == 3 || _Digits == 5) ? 30 : 3);
  1514.    g_allow_buy             = true;
  1515.    g_allow_sell            = true;
  1516.    g_panel_open            = true;
  1517.    g_pause_until           = 0;
  1518.    g_last_open_bar_time    = 0;
  1519.    g_last_panel_refresh    = 0;
  1520.    g_buy_protection_peak   = 0.0;
  1521.    g_sell_protection_peak  = 0.0;
  1522.    g_max_loss_limit        = -MathAbs(MaxLoss);
  1523.    g_max_loss_close_all    = -MathAbs(MaxLossCloseAll);
  1524.    g_stop_loss_limit       = -MathAbs(StopLoss);
  1525.    g_second_loss_threshold = -MathAbs(Money);
  1526.    g_deposit_base          = CalculateDepositBase();
  1527.    ResetNewsState(g_news_state);
  1528.    g_news_cache_minute     = 0;
  1529.    DeleteObjectsByPrefix(g_panel_prefix);
  1530.    RefreshNewsState(true);
  1531.    EventSetTimer(1);
  1532.    RefreshPanel(true);
  1533.    return(INIT_SUCCEEDED);
  1534.   }
  1535. void OnDeinit(const int reason)
  1536.   {
  1537.    EventKillTimer();
  1538.    DeleteObjectsByPrefix(g_panel_prefix);
  1539.   }
  1540. void OnTick()
  1541.   {
  1542.    ExecuteStrategy();
  1543.   }
  1544. void OnTimer()
  1545.   {
  1546.    RefreshPanel(false);
  1547.   }
  1548. void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  1549.   {
  1550.    if(id != CHARTEVENT_OBJECT_CLICK)
  1551.       return;
  1552.    const string key=sparam;
  1553.    if(key == g_panel_prefix + "toggle_panel")
  1554.      {
  1555.       g_panel_open = !g_panel_open;
  1556.       RefreshPanel(true);
  1557.       return;
  1558.      }
  1559.    if(key == g_panel_prefix + "stop_all")
  1560.      {
  1561.       const bool currently_on=(g_allow_buy || g_allow_sell);
  1562.       g_allow_buy = !currently_on;
  1563.       g_allow_sell = !currently_on;
  1564.       RefreshPanel(true);
  1565.       return;
  1566.      }
  1567.    if(key == g_panel_prefix + "stop_buy")
  1568.      {
  1569.       g_allow_buy = !g_allow_buy;
  1570.       RefreshPanel(true);
  1571.       return;
  1572.      }
  1573.    if(key == g_panel_prefix + "stop_sell")
  1574.      {
  1575.       g_allow_sell = !g_allow_sell;
  1576.       RefreshPanel(true);
  1577.       return;
  1578.      }
  1579.    if(key == g_panel_prefix + "close_profit")
  1580.      {
  1581.       ClosePositionsByProfitState(true);
  1582.       RefreshPanel(true);
  1583.       return;
  1584.      }
  1585.    if(key == g_panel_prefix + "close_loss")
  1586.      {
  1587.       ClosePositionsByProfitState(false);
  1588.       RefreshPanel(true);
  1589.       return;
  1590.      }
  1591.    if(key == g_panel_prefix + "close_buy")
  1592.      {
  1593.       CloseEaOrders(1,false,false);
  1594.       RefreshPanel(true);
  1595.       return;
  1596.      }
  1597.    if(key == g_panel_prefix + "close_sell")
  1598.      {
  1599.       CloseEaOrders(-1,false,false);
  1600.       RefreshPanel(true);
  1601.       return;
  1602.      }
  1603.    if(key == g_panel_prefix + "close_symbol")
  1604.      {
  1605.       CloseCurrentSymbolPositions();
  1606.       RefreshPanel(true);
  1607.       return;
  1608.      }
  1609.    if(key == g_panel_prefix + "close_ea")
  1610.      {
  1611.       CloseEaOrders(0,false,false);
  1612.       RefreshPanel(true);
  1613.       return;
  1614.      }
  1615.    if(key == g_panel_prefix + "close_account")
  1616.      {
  1617.       CloseAllAccountPositions();
  1618.       RefreshPanel(true);
  1619.      }
  1620.   }
  1621. bool IsTestingMode()
  1622.   {
  1623.    return((bool)MQLInfoInteger(MQL_TESTER));
  1624.   }
  1625. datetime ReferenceNow()
  1626.   {
  1627.    return(IsTestingMode() ? TimeCurrent() : TimeLocal());
  1628.   }
  1629. datetime ReferenceNewsNow()
  1630.   {
  1631.    if(IsTestingMode())
  1632.       return(TimeCurrent());
  1633.    datetime server_time=TimeTradeServer();
  1634.    if(server_time > 0)
  1635.       return(server_time);
  1636.    server_time=TimeCurrent();
  1637.    if(server_time > 0)
  1638.       return(server_time);
  1639.    return(TimeLocal());
  1640.   }
  1641. string CleanTimeString(const string value)
  1642.   {
  1643.    string result=value;
  1644.    StringReplace(result," ","");
  1645.    StringTrimLeft(result);
  1646.    StringTrimRight(result);
  1647.    if(result == "24:00")
  1648.       result="23:59:59";
  1649.    return(result);
  1650.   }
  1651. datetime TodayAt(const string time_text,const datetime now_value)
  1652.   {
  1653.    string t=CleanTimeString(time_text);
  1654.    if(StringLen(t) == 5)
  1655.       t+=":00";
  1656.    return(StringToTime(TimeToString(now_value,TIME_DATE) + " " + t));
  1657.   }
  1658. bool IsInWindow(const string start_text,const string stop_text,const datetime now_value)
  1659.   {
  1660.    const datetime start_time=TodayAt(start_text,now_value);
  1661.    const datetime stop_time=TodayAt(stop_text,now_value);
  1662.    if(start_time <= stop_time)
  1663.       return(now_value >= start_time && now_value <= stop_time);
  1664.    return(now_value >= start_time || now_value <= stop_time);
  1665.   }
  1666. bool IsAfterSessionStop(const datetime now_value)
  1667.   {
  1668.    if(IsInWindow(EA_StartTime,EA_StopTime,now_value))
  1669.       return(false);
  1670.    const datetime start_time=TodayAt(EA_StartTime,now_value);
  1671.    const datetime stop_time=TodayAt(EA_StopTime,now_value);
  1672.    if(start_time <= stop_time)
  1673.       return(now_value > stop_time);
  1674.    return(now_value > stop_time && now_value < start_time);
  1675.   }
  1676. bool IsTradingSessionOpen(const datetime now_value)
  1677.   {
  1678.    if(!EnableTradingSessionWindow)
  1679.       return(true);
  1680.    return(IsInWindow(EA_StartTime,EA_StopTime,now_value));
  1681.   }
  1682. bool IsTradingSessionAfterStop(const datetime now_value)
  1683.   {
  1684.    if(!EnableTradingSessionWindow)
  1685.       return(false);
  1686.    return(IsAfterSessionStop(now_value));
  1687.   }
  1688. bool IsDailyWrapUpWindow(const datetime now_value)
  1689.   {
  1690.    if(!EnableDailyWrapUpPhase)
  1691.       return(false);
  1692.    return(IsInWindow(DailyWrapUpStartTime,DailyWrapUpStopTime,now_value));
  1693.   }
  1694. void ResetNewsState(NewsWindowState &state)
  1695.   {
  1696.    state.enabled=false;
  1697.    state.calendar_available=false;
  1698.    state.using_embedded_history=false;
  1699.    state.has_active_window=false;
  1700.    state.in_pre_window=false;
  1701.    state.in_post_window=false;
  1702.    state.has_upcoming_event=false;
  1703.    state.block_entries=false;
  1704.    state.server_now=0;
  1705.    state.event_time=0;
  1706.    state.window_start=0;
  1707.    state.resume_time=0;
  1708.    state.currency="";
  1709.    state.event_name="";
  1710.    state.error_text="";
  1711.   }
  1712. void ResetNewsEvalAccumulator(NewsEvalAccumulator &eval)
  1713.   {
  1714.    eval.any_success=false;
  1715.    eval.first_error="";
  1716.    eval.active_block_start=0;
  1717.    eval.active_block_end=0;
  1718.    eval.active_future_time=0;
  1719.    eval.active_future_currency="";
  1720.    eval.active_future_name="";
  1721.    eval.active_past_time=0;
  1722.    eval.active_past_currency="";
  1723.    eval.active_past_name="";
  1724.    eval.next_upcoming_time=0;
  1725.    eval.next_upcoming_currency="";
  1726.    eval.next_upcoming_name="";
  1727.   }
  1728. void AppendUniqueText(string &items[],const string value)
  1729.   {
  1730.    string item=value;
  1731.    StringTrimLeft(item);
  1732.    StringTrimRight(item);
  1733.    if(item == "")
  1734.       return;
  1735.    for(int i=0; i<ArraySize(items); ++i)
  1736.      {
  1737.       if(items[i] == item)
  1738.          return;
  1739.      }
  1740.    const int size=ArraySize(items);
  1741.    ArrayResize(items,size + 1);
  1742.    items[size]=item;
  1743.   }
  1744. void BuildNewsCurrencies(string &currencies[])
  1745.   {
  1746.    ArrayResize(currencies,0);
  1747.    AppendUniqueText(currencies,SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT));
  1748.    AppendUniqueText(currencies,SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE));
  1749.    AppendUniqueText(currencies,SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN));
  1750.   }
  1751. string CalendarErrorText(const int error_code)
  1752.   {
  1753.    switch(error_code)
  1754.      {
  1755.       case 0:
  1756.          return("");
  1757.       case 5400:
  1758.          return("经济日历返回过多数据");
  1759.       case 5401:
  1760.          return("经济日历请求超时");
  1761.       case 5402:
  1762.          return("经济日历无可用数据");
  1763.      default:
  1764.          return("经济日历错误 " + IntegerToString(error_code));
  1765.      }
  1766.   }
  1767. void ConsiderNewsEvent(const datetime now_server,const datetime event_time,const string currency,const string event_name,const int lead_seconds,const int cooldown_seconds,NewsEvalAccumulator &eval)
  1768.   {
  1769.    if(event_time <= 0)
  1770.       return;
  1771.    const datetime window_start=event_time - lead_seconds;
  1772.    const datetime window_end=event_time + cooldown_seconds;
  1773.    if(now_server >= window_start && now_server < window_end)
  1774.      {
  1775.       if(eval.active_block_start == 0 || window_start < eval.active_block_start)
  1776.          eval.active_block_start=window_start;
  1777.       if(window_end > eval.active_block_end)
  1778.          eval.active_block_end=window_end;
  1779.       if(event_time >= now_server)
  1780.         {
  1781.          if(eval.active_future_time == 0 || event_time < eval.active_future_time)
  1782.            {
  1783.             eval.active_future_time=event_time;
  1784.             eval.active_future_currency=currency;
  1785.             eval.active_future_name=event_name;
  1786.            }
  1787.         }
  1788.       else
  1789.         {
  1790.          if(eval.active_past_time == 0 || event_time > eval.active_past_time)
  1791.            {
  1792.             eval.active_past_time=event_time;
  1793.             eval.active_past_currency=currency;
  1794.             eval.active_past_name=event_name;
  1795.            }
  1796.         }
  1797.       return;
  1798.      }
  1799.    if(event_time > now_server && (eval.next_upcoming_time == 0 || event_time < eval.next_upcoming_time))
  1800.      {
  1801.       eval.next_upcoming_time=event_time;
  1802.       eval.next_upcoming_currency=currency;
  1803.       eval.next_upcoming_name=event_name;
  1804.      }
  1805.   }
  1806. void ApplyNewsAccumulator(const NewsEvalAccumulator &eval)
  1807.   {
  1808.    g_news_state.calendar_available=eval.any_success;
  1809.    if(!eval.any_success)
  1810.      {
  1811.       g_news_state.error_text=(eval.first_error != "" ? eval.first_error : "经济日历不可用,已忽略");
  1812.       return;
  1813.      }
  1814.    if(eval.active_block_start != 0)
  1815.      {
  1816.       g_news_state.has_active_window=true;
  1817.       g_news_state.block_entries=true;
  1818.       g_news_state.window_start=eval.active_block_start;
  1819.       g_news_state.resume_time=eval.active_block_end;
  1820.       g_news_state.in_pre_window=(eval.active_future_time != 0);
  1821.       g_news_state.in_post_window=(eval.active_past_time != 0) || !g_news_state.in_pre_window;
  1822.       if(g_news_state.in_pre_window)
  1823.         {
  1824.          g_news_state.event_time=eval.active_future_time;
  1825.          g_news_state.currency=eval.active_future_currency;
  1826.          g_news_state.event_name=eval.active_future_name;
  1827.         }
  1828.       else
  1829.         {
  1830.          g_news_state.event_time=eval.active_past_time;
  1831.          g_news_state.currency=eval.active_past_currency;
  1832.          g_news_state.event_name=eval.active_past_name;
  1833.         }
  1834.       return;
  1835.      }
  1836.    if(eval.next_upcoming_time != 0)
  1837.      {
  1838.       g_news_state.has_upcoming_event=true;
  1839.       g_news_state.event_time=eval.next_upcoming_time;
  1840.       g_news_state.currency=eval.next_upcoming_currency;
  1841.       g_news_state.event_name=eval.next_upcoming_name;
  1842.      }
  1843.   }
  1844. void RefreshEmbeddedBacktestNewsState(const datetime now_server)
  1845.   {
  1846.    g_news_state.using_embedded_history=true;
  1847.    NewsEvalAccumulator eval;
  1848.    ResetNewsEvalAccumulator(eval);
  1849.    eval.any_success=(GOLDKING_BACKTEST_USD_HIGH_NEWS_COUNT > 0);
  1850.    if(!eval.any_success)
  1851.      {
  1852.       eval.first_error="回测内置新闻为空";
  1853.       ApplyNewsAccumulator(eval);
  1854.       return;
  1855.      }
  1856.    const int lead_seconds=MathMax(0,NewsLeadMinutes) * 60;
  1857.    const int cooldown_seconds=MathMax(0,NewsCooldownMinutes) * 60;
  1858.    for(int i=0; i<GOLDKING_BACKTEST_USD_HIGH_NEWS_COUNT; ++i)
  1859.       ConsiderNewsEvent(now_server,GOLDKING_BACKTEST_USD_HIGH_NEWS_TIMES[i],"USD",GOLDKING_BACKTEST_USD_HIGH_NEWS_NAMES[i],lead_seconds,cooldown_seconds,eval);
  1860.    ApplyNewsAccumulator(eval);
  1861.   }
  1862. void RefreshNewsState(const bool force)
  1863.   {
  1864.    const datetime now_server=ReferenceNewsNow();
  1865.    const datetime minute_key=now_server - now_server % 60;
  1866.    if(!force && g_news_cache_minute == minute_key && g_news_state.server_now != 0)
  1867.      {
  1868.       g_news_state.server_now=now_server;
  1869.       return;
  1870.      }
  1871.    g_news_cache_minute=minute_key;
  1872.    ResetNewsState(g_news_state);
  1873.    g_news_state.enabled=EnableHighImpactNewsPause;
  1874.    g_news_state.server_now=now_server;
  1875.    if(!EnableHighImpactNewsPause)
  1876.       return;
  1877.    if(IsTestingMode())
  1878.      {
  1879.       RefreshEmbeddedBacktestNewsState(now_server);
  1880.       return;
  1881.      }
  1882.    string currencies[];
  1883.    BuildNewsCurrencies(currencies);
  1884.    if(ArraySize(currencies) == 0)
  1885.      {
  1886.       g_news_state.error_text="新闻过滤无可用货币";
  1887.       return;
  1888.      }
  1889.    const int lead_seconds=MathMax(0,NewsLeadMinutes) * 60;
  1890.    const int cooldown_seconds=MathMax(0,NewsCooldownMinutes) * 60;
  1891.    const datetime query_from=now_server - cooldown_seconds;
  1892.    const datetime query_to=now_server + 86400;
  1893.    NewsEvalAccumulator eval;
  1894.    ResetNewsEvalAccumulator(eval);
  1895.    for(int c=0; c<ArraySize(currencies); ++c)
  1896.      {
  1897.       MqlCalendarValue values[];
  1898.       ResetLastError();
  1899.       const int count=CalendarValueHistory(values,query_from,query_to,NULL,currencies[c]);
  1900.       const int error_code=GetLastError();
  1901.       if(count < 0)
  1902.         {
  1903.          if(eval.first_error == "" && error_code != 0)
  1904.             eval.first_error=CalendarErrorText(error_code);
  1905.          continue;
  1906.         }
  1907.       eval.any_success=true;
  1908.       for(int i=0; i<count; ++i)
  1909.         {
  1910.          if(values[i].event_id == 0 || values[i].time <= 0)
  1911.             continue;
  1912.          MqlCalendarEvent event={};
  1913.          if(!CalendarEventById(values[i].event_id,event))
  1914.             continue;
  1915.          if(event.importance != CALENDAR_IMPORTANCE_HIGH)
  1916.             continue;
  1917.          if(event.time_mode != CALENDAR_TIMEMODE_DATETIME)
  1918.             continue;
  1919.          ConsiderNewsEvent(now_server,values[i].time,currencies[c],event.name,lead_seconds,cooldown_seconds,eval);
  1920.         }
  1921.      }
  1922.    ApplyNewsAccumulator(eval);
  1923.   }
  1924. double PipDivisor()
  1925.   {
  1926.    return((_Digits == 3 || _Digits == 5) ? 10.0 : 1.0);
  1927.   }
  1928. double CurrentSpreadPoints()
  1929.   {
  1930.    double ask_price=0.0;
  1931.    double bid_price=0.0;
  1932.    if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,ask_price) || !SymbolInfoDouble(_Symbol,SYMBOL_BID,bid_price))
  1933.       return(0.0);
  1934.    return((ask_price - bid_price) / _Point);
  1935.   }
  1936. int VolumeDigits(const double step)
  1937.   {
  1938.    string step_text=DoubleToString(step,8);
  1939.    int end_index=StringLen(step_text) - 1;
  1940.    while(end_index >= 0 && StringGetCharacter(step_text,end_index) == '0')
  1941.       end_index--;
  1942.    const int dot_index=StringFind(step_text,".");
  1943.    if(dot_index < 0 || end_index <= dot_index)
  1944.       return(0);
  1945.    return(end_index - dot_index);
  1946.   }
  1947. double NormalizeVolumeToSymbol(double volume)
  1948.   {
  1949.    const double min_volume=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
  1950.    const double max_volume=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
  1951.    const double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
  1952.    const int digits=MathMax(DigitsLot,VolumeDigits(step));
  1953.    volume=MathMin(volume,MathMin(Maxlot,max_volume));
  1954.    volume=MathMax(volume,min_volume);
  1955.    if(step > 0.0)
  1956.       volume=MathRound(volume / step) * step;
  1957.    return(NormalizeDouble(volume,digits));
  1958.   }
  1959. double NormalizePriceToSymbol(double price)
  1960.   {
  1961.    const double tick_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
  1962.    if(tick_size > 0.0)
  1963.       price=MathRound(price / tick_size) * tick_size;
  1964.    return(NormalizeDouble(price,_Digits));
  1965.   }
  1966. int BrokerMinDistancePoints()
  1967.   {
  1968.    const long freeze_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL);
  1969.    const long stop_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
  1970.    return((int)MathMax(freeze_level,stop_level) + 1);
  1971.   }
  1972. bool IsHedgingAccount()
  1973.   {
  1974.    return((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
  1975.   }
  1976. void ResetStats(EAStats &stats)
  1977.   {
  1978.    ZeroMemory(stats);
  1979.    stats.buy_highest_any    = 0.0;
  1980.    stats.buy_lowest_position= 0.0;
  1981.    stats.sell_highest_position=0.0;
  1982.    stats.sell_lowest_any    = 0.0;
  1983.    stats.buy_pending_price  = 0.0;
  1984.    stats.sell_pending_price = 0.0;
  1985.    stats.buy_pending_ticket = 0;
  1986.    stats.sell_pending_ticket= 0;
  1987.   }
  1988. void CollectStats(EAStats &stats)
  1989.   {
  1990.    ResetStats(stats);
  1991.    for(int i=PositionsTotal()-1; i>=0; --i)
  1992.      {
  1993.       const ulong ticket=PositionGetTicket(i);
  1994.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  1995.          continue;
  1996.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  1997.          continue;
  1998.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  1999.          continue;
  2000.       const ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
  2001.       const double open_price=PositionGetDouble(POSITION_PRICE_OPEN);
  2002.       const double volume=PositionGetDouble(POSITION_VOLUME);
  2003.       const double profit=PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
  2004.       const datetime open_time=(datetime)PositionGetInteger(POSITION_TIME);
  2005.       if(type == POSITION_TYPE_BUY)
  2006.         {
  2007.          stats.buy_positions++;
  2008.          stats.buy_lots+=volume;
  2009.          stats.buy_profit+=profit;
  2010.          stats.buy_weighted_sum+=open_price * volume;
  2011.          if(open_price > stats.buy_highest_any || stats.buy_highest_any == 0.0)
  2012.             stats.buy_highest_any=open_price;
  2013.          if(open_price < stats.buy_lowest_position || stats.buy_lowest_position == 0.0)
  2014.             stats.buy_lowest_position=open_price;
  2015.          if(open_time > stats.last_buy_open_time)
  2016.             stats.last_buy_open_time=open_time;
  2017.         }
  2018.       else if(type == POSITION_TYPE_SELL)
  2019.         {
  2020.          stats.sell_positions++;
  2021.          stats.sell_lots+=volume;
  2022.          stats.sell_profit+=profit;
  2023.          stats.sell_weighted_sum+=open_price * volume;
  2024.          if(open_price > stats.sell_highest_position || stats.sell_highest_position == 0.0)
  2025.             stats.sell_highest_position=open_price;
  2026.          if(open_price < stats.sell_lowest_any || stats.sell_lowest_any == 0.0)
  2027.             stats.sell_lowest_any=open_price;
  2028.          if(open_time > stats.last_sell_open_time)
  2029.             stats.last_sell_open_time=open_time;
  2030.         }
  2031.      }
  2032.    for(int i=OrdersTotal()-1; i>=0; --i)
  2033.      {
  2034.       const ulong ticket=OrderGetTicket(i);
  2035.       if(ticket == 0 || !OrderSelect(ticket))
  2036.          continue;
  2037.       if(OrderGetString(ORDER_SYMBOL) != _Symbol)
  2038.          continue;
  2039.       if((long)OrderGetInteger(ORDER_MAGIC) != Magic)
  2040.          continue;
  2041.       const ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
  2042.       const double open_price=OrderGetDouble(ORDER_PRICE_OPEN);
  2043.       if(type == ORDER_TYPE_BUY_STOP)
  2044.         {
  2045.          stats.buy_pending++;
  2046.          if(open_price > stats.buy_highest_any || stats.buy_highest_any == 0.0)
  2047.             stats.buy_highest_any=open_price;
  2048.          if(ticket > stats.buy_pending_ticket)
  2049.            {
  2050.             stats.buy_pending_ticket=ticket;
  2051.             stats.buy_pending_price=open_price;
  2052.            }
  2053.         }
  2054.       else if(type == ORDER_TYPE_SELL_STOP)
  2055.         {
  2056.          stats.sell_pending++;
  2057.          if(open_price < stats.sell_lowest_any || stats.sell_lowest_any == 0.0)
  2058.             stats.sell_lowest_any=open_price;
  2059.          if(ticket > stats.sell_pending_ticket)
  2060.            {
  2061.             stats.sell_pending_ticket=ticket;
  2062.             stats.sell_pending_price=open_price;
  2063.            }
  2064.         }
  2065.      }
  2066.    if(stats.buy_lots > 0.0)
  2067.       stats.buy_avg_price=NormalizePriceToSymbol(stats.buy_weighted_sum / stats.buy_lots);
  2068.    if(stats.sell_lots > 0.0)
  2069.       stats.sell_avg_price=NormalizePriceToSymbol(stats.sell_weighted_sum / stats.sell_lots);
  2070.    stats.total_profit=stats.buy_profit + stats.sell_profit;
  2071.   }
  2072. double CalculateDepositBase()
  2073.   {
  2074.    double deposit_sum=0.0;
  2075.    if(!HistorySelect(0,TimeCurrent()))
  2076.       return(100.0);
  2077.    const int deals_total=(int)HistoryDealsTotal();
  2078.    for(int i=0; i<deals_total; ++i)
  2079.      {
  2080.       const ulong deal_ticket=HistoryDealGetTicket(i);
  2081.       if(deal_ticket == 0)
  2082.          continue;
  2083.       const ENUM_DEAL_TYPE deal_type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
  2084.       if(deal_type != DEAL_TYPE_BALANCE && deal_type != DEAL_TYPE_CREDIT)
  2085.          continue;
  2086.       const double deal_profit=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
  2087.       if(deal_profit > 0.0)
  2088.          deposit_sum+=deal_profit;
  2089.      }
  2090.    if(deposit_sum <= 0.0)
  2091.       deposit_sum=100.0;
  2092.    return(deposit_sum);
  2093.   }
  2094. double CalculateClosedProfit(const datetime from_time,const datetime to_time,const long magic_filter,const bool current_symbol_only)
  2095.   {
  2096.    double total=0.0;
  2097.    if(!HistorySelect(from_time,to_time))
  2098.       return(0.0);
  2099.    const int deals_total=(int)HistoryDealsTotal();
  2100.    for(int i=0; i<deals_total; ++i)
  2101.      {
  2102.       const ulong deal_ticket=HistoryDealGetTicket(i);
  2103.       if(deal_ticket == 0)
  2104.          continue;
  2105.       const ENUM_DEAL_ENTRY entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
  2106.       if(entry != DEAL_ENTRY_OUT && entry != DEAL_ENTRY_OUT_BY && entry != DEAL_ENTRY_INOUT)
  2107.          continue;
  2108.       if(current_symbol_only && HistoryDealGetString(deal_ticket,DEAL_SYMBOL) != _Symbol)
  2109.          continue;
  2110.       if(magic_filter != -1 && (long)HistoryDealGetInteger(deal_ticket,DEAL_MAGIC) != magic_filter)
  2111.          continue;
  2112.       total+=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
  2113.       total+=HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
  2114.       total+=HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
  2115.      }
  2116.    return(total);
  2117.   }
  2118. string TradingDayKey(const datetime now_value)
  2119.   {
  2120.    return(TimeToString(now_value,TIME_DATE));
  2121.   }
  2122. double TodayClosedProfit(const datetime now_value)
  2123.   {
  2124.    return(CalculateClosedProfit(TodayAt("00:00",now_value),TimeCurrent(),Magic,true));
  2125.   }
  2126. double TodayProgressProfit(const datetime now_value,const EAStats &stats)
  2127.   {
  2128.    return(TodayClosedProfit(now_value) + stats.total_profit);
  2129.   }
  2130. bool HasOpenPositions(const EAStats &stats)
  2131.   {
  2132.    return((stats.buy_positions + stats.sell_positions) > 0);
  2133.   }
  2134. bool HasActiveExposure(const EAStats &stats)
  2135.   {
  2136.    return(HasOpenPositions(stats) || (stats.buy_pending + stats.sell_pending) > 0);
  2137.   }
  2138. void RefreshDailyLocks(const datetime now_value,const EAStats &stats)
  2139.   {
  2140.    const string day_key=TradingDayKey(now_value);
  2141.    if(day_key != g_today_key)
  2142.      {
  2143.       g_today_key=day_key;
  2144.       g_daily_target_locked=false;
  2145.       g_daily_target_hit_value=0.0;
  2146.      }
  2147.    if(!EnableDailyProfitTarget || DailyProfitTarget <= 0.0)
  2148.      {
  2149.       g_daily_target_locked=false;
  2150.       g_daily_target_hit_value=0.0;
  2151.       return;
  2152.      }
  2153.    if(g_daily_target_locked)
  2154.       return;
  2155.    const double today_progress=TodayProgressProfit(now_value,stats);
  2156.    if(today_progress >= DailyProfitTarget)
  2157.      {
  2158.       g_daily_target_locked=true;
  2159.       g_daily_target_hit_value=today_progress;
  2160.      }
  2161.   }
  2162. double AccountProfitForPanel()
  2163.   {
  2164.    return(AccountInfoDouble(ACCOUNT_PROFIT));
  2165.   }
  2166. int CountPositionsWithComment(const string comment_text,const ENUM_POSITION_TYPE type)
  2167.   {
  2168.    int count=0;
  2169.    for(int i=PositionsTotal()-1; i>=0; --i)
  2170.      {
  2171.       const ulong ticket=PositionGetTicket(i);
  2172.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2173.          continue;
  2174.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  2175.          continue;
  2176.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  2177.          continue;
  2178.       if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type)
  2179.          continue;
  2180.       if(PositionGetString(POSITION_COMMENT) == comment_text)
  2181.          count++;
  2182.      }
  2183.    return(count);
  2184.   }
  2185. double SumExtremePositionProfits(const ENUM_POSITION_TYPE type,const bool positive,const int count)
  2186.   {
  2187.    if(count <= 0)
  2188.       return(0.0);
  2189.    double values[];
  2190.    ArrayResize(values,0);
  2191.    for(int i=PositionsTotal()-1; i>=0; --i)
  2192.      {
  2193.       const ulong ticket=PositionGetTicket(i);
  2194.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2195.          continue;
  2196.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  2197.          continue;
  2198.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  2199.          continue;
  2200.       if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type)
  2201.          continue;
  2202.       const double profit=PositionGetDouble(POSITION_PROFIT);
  2203.       if(positive && profit >= 0.0)
  2204.         {
  2205.          const int size=ArraySize(values);
  2206.          ArrayResize(values,size + 1);
  2207.          values[size]=profit;
  2208.         }
  2209.       if(!positive && profit < 0.0)
  2210.         {
  2211.          const int size=ArraySize(values);
  2212.          ArrayResize(values,size + 1);
  2213.          values[size]=-profit;
  2214.         }
  2215.      }
  2216.    if(ArraySize(values) == 0)
  2217.       return(0.0);
  2218.    ArraySort(values);
  2219.    double sum=0.0;
  2220.    int taken=0;
  2221.    for(int i=ArraySize(values)-1; i>=0 && taken<count; --i)
  2222.      {
  2223.       sum+=values[i];
  2224.       taken++;
  2225.      }
  2226.    return(sum);
  2227.   }
  2228. ulong FindExtremePositionTicket(const ENUM_POSITION_TYPE type,const bool positive)
  2229.   {
  2230.    bool found=false;
  2231.    double best_profit=0.0;
  2232.    ulong best_ticket=0;
  2233.    for(int i=PositionsTotal()-1; i>=0; --i)
  2234.      {
  2235.       const ulong ticket=PositionGetTicket(i);
  2236.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2237.          continue;
  2238.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  2239.          continue;
  2240.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  2241.          continue;
  2242.       if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type)
  2243.          continue;
  2244.       const double profit=PositionGetDouble(POSITION_PROFIT);
  2245.       if(positive)
  2246.         {
  2247.          if(profit < 0.0)
  2248.             continue;
  2249.          if(!found || profit > best_profit)
  2250.            {
  2251.             found=true;
  2252.             best_profit=profit;
  2253.             best_ticket=ticket;
  2254.            }
  2255.         }
  2256.       else
  2257.         {
  2258.          if(profit >= 0.0)
  2259.             continue;
  2260.          if(!found || profit < best_profit)
  2261.            {
  2262.             found=true;
  2263.             best_profit=profit;
  2264.             best_ticket=ticket;
  2265.            }
  2266.         }
  2267.      }
  2268.    return(best_ticket);
  2269.   }
  2270. double FindExtremePositionLot(const ENUM_POSITION_TYPE type,const bool positive)
  2271.   {
  2272.    const ulong ticket=FindExtremePositionTicket(type,positive);
  2273.    if(ticket == 0 || !PositionSelectByTicket(ticket))
  2274.       return(0.0);
  2275.    return(PositionGetDouble(POSITION_VOLUME));
  2276.   }
  2277. void CloseExtremePositions(const ENUM_POSITION_TYPE type,int count,const bool positive)
  2278.   {
  2279.    while(count > 0)
  2280.      {
  2281.       const ulong ticket=FindExtremePositionTicket(type,positive);
  2282.       if(ticket == 0)
  2283.          break;
  2284.       ClosePositionTicket(ticket);
  2285.       count--;
  2286.      }
  2287.   }
  2288. ulong FindNewestPositionTicket(const ENUM_POSITION_TYPE type,const bool current_symbol_only,const long magic_filter)
  2289.   {
  2290.    ulong newest_ticket=0;
  2291.    for(int i=PositionsTotal()-1; i>=0; --i)
  2292.      {
  2293.       const ulong ticket=PositionGetTicket(i);
  2294.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2295.          continue;
  2296.       if(current_symbol_only && PositionGetString(POSITION_SYMBOL) != _Symbol)
  2297.          continue;
  2298.       if(magic_filter != -1 && (long)PositionGetInteger(POSITION_MAGIC) != magic_filter)
  2299.          continue;
  2300.       if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type)
  2301.          continue;
  2302.       if(ticket > newest_ticket)
  2303.          newest_ticket=ticket;
  2304.      }
  2305.    return(newest_ticket);
  2306.   }
  2307. bool CloseByPair(const ulong position_ticket,const ulong opposite_ticket)
  2308.   {
  2309.    MqlTradeRequest request={};
  2310.    MqlTradeResult  result={};
  2311.    request.action=TRADE_ACTION_CLOSE_BY;
  2312.    request.position=position_ticket;
  2313.    request.position_by=opposite_ticket;
  2314.    request.magic=Magic;
  2315.    return(CheckOrderSendResult(OrderSend(request,result),result,"CloseByPair"));
  2316.   }
  2317. void CloseOppositePairs()
  2318.   {
  2319.    while(true)
  2320.      {
  2321.       const ulong buy_ticket=FindNewestPositionTicket(POSITION_TYPE_BUY,true,Magic);
  2322.       const ulong sell_ticket=FindNewestPositionTicket(POSITION_TYPE_SELL,true,Magic);
  2323.       if(buy_ticket == 0 || sell_ticket == 0)
  2324.          break;
  2325.       if(CloseByPair(buy_ticket,sell_ticket))
  2326.          continue;
  2327.       if(CloseByPair(sell_ticket,buy_ticket))
  2328.          continue;
  2329.       break;
  2330.      }
  2331.   }
  2332. bool TradeRetcodeOk(const uint retcode)
  2333.   {
  2334.    return(retcode == TRADE_RETCODE_DONE ||
  2335.           retcode == TRADE_RETCODE_DONE_PARTIAL ||
  2336.           retcode == TRADE_RETCODE_PLACED ||
  2337.           retcode == TRADE_RETCODE_NO_CHANGES);
  2338.   }
  2339. bool CheckTradeResult(const bool request_ok,const string action)
  2340.   {
  2341.    const uint retcode=g_trade.ResultRetcode();
  2342.    if(request_ok && TradeRetcodeOk(retcode))
  2343.       return(true);
  2344.    PrintFormat("%s failed on %s: request_ok=%s retcode=%u detail=%s",
  2345.                action,
  2346.                _Symbol,
  2347.                request_ok ? "true" : "false",
  2348.                retcode,
  2349.                g_trade.ResultRetcodeDescription());
  2350.    return(false);
  2351.   }
  2352. bool CheckOrderSendResult(const bool request_ok,const MqlTradeResult &result,const string action)
  2353.   {
  2354.    if(request_ok && TradeRetcodeOk(result.retcode))
  2355.       return(true);
  2356.    PrintFormat("%s failed on %s: request_ok=%s retcode=%u order=%I64u deal=%I64u",
  2357.                action,
  2358.                _Symbol,
  2359.                request_ok ? "true" : "false",
  2360.                result.retcode,
  2361.                result.order,
  2362.                result.deal);
  2363.    return(false);
  2364.   }
  2365. bool ClosePositionTicket(const ulong ticket)
  2366.   {
  2367.    if(ticket == 0 || !PositionSelectByTicket(ticket))
  2368.       return(false);
  2369.    return(CheckTradeResult(g_trade.PositionClose(ticket),"ClosePositionTicket"));
  2370.   }
  2371. bool DeletePendingOrder(const ulong ticket)
  2372.   {
  2373.    if(ticket == 0)
  2374.       return(false);
  2375.    return(CheckTradeResult(g_trade.OrderDelete(ticket),"DeletePendingOrder"));
  2376.   }
  2377. void DeleteEaPendingOrders()
  2378.   {
  2379.    for(int i=OrdersTotal()-1; i>=0; --i)
  2380.      {
  2381.       const ulong ticket=OrderGetTicket(i);
  2382.       if(ticket == 0 || !OrderSelect(ticket))
  2383.          continue;
  2384.       if(OrderGetString(ORDER_SYMBOL) != _Symbol)
  2385.          continue;
  2386.       if((long)OrderGetInteger(ORDER_MAGIC) != Magic)
  2387.          continue;
  2388.       const ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
  2389.       if(type != ORDER_TYPE_BUY_STOP && type != ORDER_TYPE_SELL_STOP)
  2390.          continue;
  2391.       DeletePendingOrder(ticket);
  2392.      }
  2393.   }
  2394. bool ModifyPendingPrice(const ulong ticket,const double new_price)
  2395.   {
  2396.    if(ticket == 0 || !OrderSelect(ticket))
  2397.       return(false);
  2398.    MqlTradeRequest request={};
  2399.    MqlTradeResult  result={};
  2400.    request.action=TRADE_ACTION_MODIFY;
  2401.    request.order=ticket;
  2402.    request.symbol=OrderGetString(ORDER_SYMBOL);
  2403.    request.magic=(ulong)OrderGetInteger(ORDER_MAGIC);
  2404.    request.price=new_price;
  2405.    request.sl=0.0;
  2406.    request.tp=0.0;
  2407.    request.type_time=ORDER_TIME_GTC;
  2408.    request.expiration=0;
  2409.    return(CheckOrderSendResult(OrderSend(request,result),result,"ModifyPendingPrice"));
  2410.   }
  2411. void CloseEaOrders(const int direction,const bool use_pairs,const bool arm_cooldown)
  2412.   {
  2413.    if(use_pairs && direction == 0)
  2414.       CloseOppositePairs();
  2415.    for(int i=PositionsTotal()-1; i>=0; --i)
  2416.      {
  2417.       const ulong ticket=PositionGetTicket(i);
  2418.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2419.          continue;
  2420.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  2421.          continue;
  2422.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  2423.          continue;
  2424.       const ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
  2425.       if(direction == 1 && type != POSITION_TYPE_BUY)
  2426.          continue;
  2427.       if(direction == -1 && type != POSITION_TYPE_SELL)
  2428.          continue;
  2429.       ClosePositionTicket(ticket);
  2430.      }
  2431.    for(int i=OrdersTotal()-1; i>=0; --i)
  2432.      {
  2433.       const ulong ticket=OrderGetTicket(i);
  2434.       if(ticket == 0 || !OrderSelect(ticket))
  2435.          continue;
  2436.       if(OrderGetString(ORDER_SYMBOL) != _Symbol)
  2437.          continue;
  2438.       if((long)OrderGetInteger(ORDER_MAGIC) != Magic)
  2439.          continue;
  2440.       const ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
  2441.       if(direction == 1 && type != ORDER_TYPE_BUY_STOP)
  2442.          continue;
  2443.       if(direction == -1 && type != ORDER_TYPE_SELL_STOP)
  2444.          continue;
  2445.       if(direction == 0 && type != ORDER_TYPE_BUY_STOP && type != ORDER_TYPE_SELL_STOP)
  2446.          continue;
  2447.       DeletePendingOrder(ticket);
  2448.      }
  2449.    if(arm_cooldown && NextTime > 0)
  2450.       g_pause_until=TimeCurrent() + NextTime;
  2451.   }
  2452. void ClosePositionsByProfitState(const bool close_profit)
  2453.   {
  2454.    for(int i=PositionsTotal()-1; i>=0; --i)
  2455.      {
  2456.       const ulong ticket=PositionGetTicket(i);
  2457.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2458.          continue;
  2459.       if((long)PositionGetInteger(POSITION_MAGIC) != Magic)
  2460.          continue;
  2461.       const double profit=PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
  2462.       if(close_profit && profit >= 0.0)
  2463.          ClosePositionTicket(ticket);
  2464.       if(!close_profit && profit < 0.0)
  2465.          ClosePositionTicket(ticket);
  2466.      }
  2467.   }
  2468. void CloseCurrentSymbolPositions()
  2469.   {
  2470.    for(int i=PositionsTotal()-1; i>=0; --i)
  2471.      {
  2472.       const ulong ticket=PositionGetTicket(i);
  2473.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2474.          continue;
  2475.       if(PositionGetString(POSITION_SYMBOL) != _Symbol)
  2476.          continue;
  2477.       ClosePositionTicket(ticket);
  2478.      }
  2479.   }
  2480. void CloseAllAccountPositions()
  2481.   {
  2482.    for(int i=PositionsTotal()-1; i>=0; --i)
  2483.      {
  2484.       const ulong ticket=PositionGetTicket(i);
  2485.       if(ticket == 0 || !PositionSelectByTicket(ticket))
  2486.          continue;
  2487.       ClosePositionTicket(ticket);
  2488.      }
  2489.   }
  2490. bool IsTradingEnvironmentOk(const EAStats &stats,string &reason)
  2491.   {
  2492.    reason="";
  2493.    if(!IsHedgingAccount())
  2494.      {
  2495.       reason="MT5净额账户不支持该EA,请切换到对冲账户";
  2496.       return(false);
  2497.      }
  2498.    if((int)AccountInfoInteger(ACCOUNT_LEVERAGE) < Leverage)
  2499.      {
  2500.       reason="杠杆低于限制";
  2501.       return(false);
  2502.      }
  2503.    if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED))
  2504.      {
  2505.       reason="终端未启用交易";
  2506.       return(false);
  2507.      }
  2508.    long trade_mode=SYMBOL_TRADE_MODE_DISABLED;
  2509.    if(!SymbolInfoInteger(_Symbol,SYMBOL_TRADE_MODE,trade_mode))
  2510.      {
  2511.       reason="无法读取品种交易状态";
  2512.       return(false);
  2513.      }
  2514.    if(trade_mode == SYMBOL_TRADE_MODE_DISABLED || trade_mode == SYMBOL_TRADE_MODE_CLOSEONLY)
  2515.      {
  2516.       reason="当前品种禁止开新单";
  2517.       return(false);
  2518.      }
  2519.    if(IsStopped())
  2520.      {
  2521.       reason="EA已停止";
  2522.       return(false);
  2523.      }
  2524.    if(stats.buy_positions + stats.sell_positions >= Totals)
  2525.      {
  2526.       reason="达到最大持仓数";
  2527.       return(false);
  2528.      }
  2529.    if(CurrentSpreadPoints() > MaxSpread)
  2530.      {
  2531.       reason="点差超限";
  2532.       return(false);
  2533.      }
  2534.    return(true);
  2535.   }
  2536. void UpdateLimitLines()
  2537.   {
  2538.    const datetime now_value=ReferenceNow();
  2539.    const bool limit_window_active=IsInWindow(Limit_StartTime,Limit_StopTime,now_value);
  2540.    const string buy_line=g_panel_prefix + "limit_buy_add";
  2541.    const string sell_line=g_panel_prefix + "limit_sell_add";
  2542.    if(limit_window_active && On_top_of_this_price_not_Buy_order > 0.0)
  2543.      {
  2544.       if(ObjectFind(0,buy_line) < 0)
  2545.          ObjectCreate(0,buy_line,OBJ_HLINE,0,0,On_top_of_this_price_not_Buy_order);
  2546.       ObjectSetDouble(0,buy_line,OBJPROP_PRICE,On_top_of_this_price_not_Buy_order);
  2547.       ObjectSetInteger(0,buy_line,OBJPROP_COLOR,clr1);
  2548.       ObjectSetInteger(0,buy_line,OBJPROP_STYLE,STYLE_DASH);
  2549.      }
  2550.    else if(ObjectFind(0,buy_line) >= 0)
  2551.       ObjectDelete(0,buy_line);
  2552.    if(limit_window_active && On_under_of_this_price_not_Sell_order > 0.0)
  2553.      {
  2554.       if(ObjectFind(0,sell_line) < 0)
  2555.          ObjectCreate(0,sell_line,OBJ_HLINE,0,0,On_under_of_this_price_not_Sell_order);
  2556.       ObjectSetDouble(0,sell_line,OBJPROP_PRICE,On_under_of_this_price_not_Sell_order);
  2557.       ObjectSetInteger(0,sell_line,OBJPROP_COLOR,clr2);
  2558.       ObjectSetInteger(0,sell_line,OBJPROP_STYLE,STYLE_DASH);
  2559.      }
  2560.    else if(ObjectFind(0,sell_line) >= 0)
  2561.       ObjectDelete(0,sell_line);
  2562.   }
  2563. void UpdateAverageLines(const EAStats &stats)
  2564.   {
  2565.    const string buy_line=g_panel_prefix + "avg_buy";
  2566.    const string sell_line=g_panel_prefix + "avg_sell";
  2567.    if(stats.buy_positions > 0 && stats.buy_avg_price > 0.0)
  2568.      {
  2569.       if(ObjectFind(0,buy_line) < 0)
  2570.          ObjectCreate(0,buy_line,OBJ_HLINE,0,0,stats.buy_avg_price);
  2571.       ObjectSetDouble(0,buy_line,OBJPROP_PRICE,stats.buy_avg_price);
  2572.       ObjectSetInteger(0,buy_line,OBJPROP_COLOR,clr1);
  2573.       ObjectSetInteger(0,buy_line,OBJPROP_WIDTH,2);
  2574.      }
  2575.    else if(ObjectFind(0,buy_line) >= 0)
  2576.       ObjectDelete(0,buy_line);
  2577.    if(stats.sell_positions > 0 && stats.sell_avg_price > 0.0)
  2578.      {
  2579.       if(ObjectFind(0,sell_line) < 0)
  2580.          ObjectCreate(0,sell_line,OBJ_HLINE,0,0,stats.sell_avg_price);
  2581.       ObjectSetDouble(0,sell_line,OBJPROP_PRICE,stats.sell_avg_price);
  2582.       ObjectSetInteger(0,sell_line,OBJPROP_COLOR,clr2);
  2583.       ObjectSetInteger(0,sell_line,OBJPROP_WIDTH,2);
  2584.      }
  2585.    else if(ObjectFind(0,sell_line) >= 0)
  2586.       ObjectDelete(0,sell_line);
  2587.   }
  2588. bool ShouldUsePrimaryParameters(const EAStats &stats)
  2589.   {
  2590.    if(Money == 0.0)
  2591.       return(true);
  2592.    return(stats.total_profit > g_second_loss_threshold);
  2593.   }
  2594. bool AllowBuyOrderByPriceLimit(const EAStats &stats,const double target_price,const bool limit_window_active)
  2595.   {
  2596.    if(stats.buy_positions == 0)
  2597.       return(true);
  2598.    if(!limit_window_active)
  2599.       return(true);
  2600.    if(On_top_of_this_price_not_Buy_order == 0.0)
  2601.       return(true);
  2602.    return(target_price < On_top_of_this_price_not_Buy_order);
  2603.   }
  2604. bool AllowSellOrderByPriceLimit(const EAStats &stats,const double target_price,const bool limit_window_active)
  2605.   {
  2606.    if(stats.sell_positions == 0)
  2607.       return(true);
  2608.    if(!limit_window_active)
  2609.       return(true);
  2610.    if(On_under_of_this_price_not_Sell_order == 0.0)
  2611.       return(true);
  2612.    return(target_price > On_under_of_this_price_not_Sell_order);
  2613.   }
  2614. bool CanOpenThisCycle(const bool is_buy,const EAStats &stats)
  2615.   {
  2616.    if(OpenMode == OpenMode_NoDelay || OpenMode == OpenMode_Bar)
  2617.       return(true);
  2618.    const datetime last_open=is_buy ? stats.last_buy_open_time : stats.last_sell_open_time;
  2619.    return((TimeCurrent() - last_open) >= sleep);
  2620.   }
  2621. bool TryProtectiveCloseBySide(const EAStats &stats)
  2622.   {
  2623.    const int buy_ss_count=CountPositionsWithComment(GOLDKING_ORDER_COMMENT_SECONDARY,POSITION_TYPE_BUY);
  2624.    const int sell_ss_count=CountPositionsWithComment(GOLDKING_ORDER_COMMENT_SECONDARY,POSITION_TYPE_SELL);
  2625.    if((buy_ss_count < 1 || !HomeopathyCloseAll) &&
  2626.       stats.buy_profit > g_max_loss_close_all &&
  2627.       stats.sell_profit > g_max_loss_close_all)
  2628.      {
  2629.       const double buy_target=Profit ? StopProfit * stats.buy_positions : StopProfit;
  2630.       const double sell_target=Profit ? StopProfit * stats.sell_positions : StopProfit;
  2631.       if(stats.buy_positions > 0 && stats.buy_profit > buy_target)
  2632.         {
  2633.          CloseEaOrders(1,false,false);
  2634.          return(true);
  2635.         }
  2636.       if(stats.sell_positions > 0 && stats.sell_profit > sell_target)
  2637.         {
  2638.          CloseEaOrders(-1,false,false);
  2639.          return(true);
  2640.         }
  2641.      }
  2642.    if(HomeopathyCloseAll && (buy_ss_count > 0 || sell_ss_count > 0) && stats.total_profit >= CloseAll)
  2643.      {
  2644.       CloseEaOrders(0,true,true);
  2645.       return(true);
  2646.      }
  2647.    if(stats.total_profit >= CloseAll &&
  2648.       (stats.buy_profit <= g_max_loss_close_all || stats.sell_profit <= g_max_loss_close_all))
  2649.      {
  2650.       CloseEaOrders(0,true,true);
  2651.       return(true);
  2652.      }
  2653.    return(false);
  2654.   }
  2655. bool ApplyCloseBuySellProtection(const EAStats &stats)
  2656.   {
  2657.    if(!CloseBuySell)
  2658.       return(false);
  2659.    const double buy_delta=SumExtremePositionProfits(POSITION_TYPE_BUY,true,1) - SumExtremePositionProfits(POSITION_TYPE_BUY,false,2);
  2660.    if(g_buy_protection_peak < buy_delta)
  2661.       g_buy_protection_peak=buy_delta;
  2662.    if(g_buy_protection_peak > 0.0 && buy_delta > 0.0)
  2663.      {
  2664.       const double biggest_win_lot=FindExtremePositionLot(POSITION_TYPE_BUY,true);
  2665.       if(stats.buy_lots > biggest_win_lot * 3.0 + stats.sell_lots && stats.buy_positions > 3)
  2666.         {
  2667.          CloseExtremePositions(POSITION_TYPE_BUY,1,true);
  2668.          CloseExtremePositions(POSITION_TYPE_BUY,2,false);
  2669.          g_buy_protection_peak=0.0;
  2670.          g_sell_protection_peak=0.0;
  2671.          return(true);
  2672.         }
  2673.      }
  2674.    const double sell_delta=SumExtremePositionProfits(POSITION_TYPE_SELL,true,1) - SumExtremePositionProfits(POSITION_TYPE_SELL,false,2);
  2675.    if(g_sell_protection_peak < sell_delta)
  2676.       g_sell_protection_peak=sell_delta;
  2677.    if(g_sell_protection_peak > 0.0 && sell_delta > 0.0)
  2678.      {
  2679.       const double biggest_win_lot=FindExtremePositionLot(POSITION_TYPE_SELL,true);
  2680.       if(stats.sell_lots > biggest_win_lot * 3.0 + stats.buy_lots && stats.sell_positions > 3)
  2681.         {
  2682.          CloseExtremePositions(POSITION_TYPE_SELL,1,true);
  2683.          CloseExtremePositions(POSITION_TYPE_SELL,2,false);
  2684.          g_buy_protection_peak=0.0;
  2685.          g_sell_protection_peak=0.0;
  2686.          return(true);
  2687.         }
  2688.      }
  2689.    return(false);
  2690.   }
  2691. bool TryAutoCloseLogic(const EAStats &stats)
  2692.   {
  2693.    if(Over && stats.total_profit >= CloseAll)
  2694.      {
  2695.       CloseEaOrders(0,true,true);
  2696.       return(true);
  2697.      }
  2698.    if(!Over)
  2699.      {
  2700.       if(TryProtectiveCloseBySide(stats))
  2701.          return(true);
  2702.      }
  2703.    if(StopLoss != 0.0 && stats.total_profit <= g_stop_loss_limit)
  2704.      {
  2705.       CloseEaOrders(0,false,true);
  2706.       return(true);
  2707.      }
  2708.    return(ApplyCloseBuySellProtection(stats));
  2709.   }
  2710. void TryPlacePendingOrders(const EAStats &stats,const bool allow_buy,const bool allow_sell)
  2711.   {
  2712.    const int min_distance=BrokerMinDistancePoints();
  2713.    const int first_step=MathMax(FirstStep,min_distance);
  2714.    const int buy_min_distance=MathMax(MinDistance,min_distance);
  2715.    const int sell_min_distance=MathMax(MinDistance,min_distance);
  2716.    const int buy_two_min_distance=MathMax(TwoMinDistance,min_distance);
  2717.    const int sell_two_min_distance=MathMax(TwoMinDistance,min_distance);
  2718.    const int buy_step=MathMax(Step,min_distance);
  2719.    const int sell_step=MathMax(Step,min_distance);
  2720.    const int buy_two_step=MathMax(TwoStep,min_distance);
  2721.    const int sell_two_step=MathMax(TwoStep,min_distance);
  2722.    const bool primary_params=ShouldUsePrimaryParameters(stats);
  2723.    const bool limit_window_active=IsInWindow(Limit_StartTime,Limit_StopTime,ReferenceNow());
  2724.    const bool lots_equal=(MathAbs(stats.buy_lots - stats.sell_lots) < 0.0000001);
  2725.    const bool buy_rebalance=(stats.buy_lots > 0.0 && stats.sell_lots / stats.buy_lots > 3.0 && stats.sell_lots - stats.buy_lots > 0.2);
  2726.    const bool sell_rebalance=(stats.sell_lots > 0.0 && stats.buy_lots / stats.sell_lots > 3.0 && stats.buy_lots - stats.sell_lots > 0.2);
  2727.    const double ask_price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  2728.    const double bid_price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
  2729.    bool can_process_cycle=true;
  2730.    datetime current_bar=0;
  2731.    if(OpenMode == OpenMode_Bar)
  2732.      {
  2733.       current_bar=iTime(_Symbol,TimeZone,0);
  2734.       can_process_cycle=(current_bar != 0 && current_bar != g_last_open_bar_time);
  2735.      }
  2736.    if(!can_process_cycle)
  2737.       return;
  2738.    if(allow_buy && stats.buy_pending == 0 && stats.buy_profit > g_max_loss_limit)
  2739.      {
  2740.       double target_price=0.0;
  2741.       if(stats.buy_positions == 0)
  2742.          target_price=NormalizePriceToSymbol(ask_price + first_step * _Point);
  2743.       else
  2744.         {
  2745.          target_price=NormalizePriceToSymbol(ask_price + (primary_params ? buy_min_distance : buy_two_min_distance) * _Point);
  2746.          if(stats.buy_lowest_position != 0.0 && target_price < NormalizePriceToSymbol(stats.buy_lowest_position - (primary_params ? buy_step : buy_two_step) * _Point))
  2747.             target_price=NormalizePriceToSymbol(ask_price + (primary_params ? buy_step : buy_two_step) * _Point);
  2748.         }
  2749.       const bool buy_condition=
  2750.          (stats.buy_positions == 0) ||
  2751.          (stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_step * _Point) && buy_rebalance && primary_params) ||
  2752.          (stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_two_step * _Point) && buy_rebalance && !primary_params && Money != 0.0) ||
  2753.          (stats.buy_lowest_position != 0.0 && target_price <= NormalizePriceToSymbol(stats.buy_lowest_position - buy_step * _Point) && primary_params) ||
  2754.          (stats.buy_lowest_position != 0.0 && target_price <= NormalizePriceToSymbol(stats.buy_lowest_position - buy_two_step * _Point) && !primary_params && Money != 0.0) ||
  2755.          (Homeopathy && stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_step * _Point) && lots_equal);
  2756.       if(buy_condition && AllowBuyOrderByPriceLimit(stats,target_price,limit_window_active) && CanOpenThisCycle(true,stats))
  2757.         {
  2758.          double volume=(stats.buy_positions == 0) ? lot : (stats.buy_positions * PlusLot + lot * MathPow(K_Lot,stats.buy_positions));
  2759.          volume=NormalizeVolumeToSymbol(volume);
  2760.          const bool use_secondary_comment=
  2761.             ((stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_step * _Point) && buy_rebalance && primary_params) ||
  2762.              (stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_two_step * _Point) && buy_rebalance && !primary_params && Money != 0.0) ||
  2763.              (Homeopathy && stats.buy_highest_any != 0.0 && target_price >= NormalizePriceToSymbol(stats.buy_highest_any + buy_step * _Point) && lots_equal));
  2764.          CheckTradeResult(g_trade.BuyStop(volume,target_price,_Symbol,0.0,0.0,ORDER_TIME_GTC,0,use_secondary_comment ? GOLDKING_ORDER_COMMENT_SECONDARY : GOLDKING_ORDER_COMMENT_PRIMARY),"BuyStop");
  2765.         }
  2766.      }
  2767.    if(allow_sell && stats.sell_pending == 0 && stats.sell_profit > g_max_loss_limit)
  2768.      {
  2769.       double target_price=0.0;
  2770.       if(stats.sell_positions == 0)
  2771.          target_price=NormalizePriceToSymbol(bid_price - first_step * _Point);
  2772.       else
  2773.         {
  2774.          target_price=NormalizePriceToSymbol(bid_price - (primary_params ? sell_min_distance : sell_two_min_distance) * _Point);
  2775.          if(stats.sell_highest_position != 0.0 && target_price < NormalizePriceToSymbol(stats.sell_highest_position + (primary_params ? sell_step : sell_two_step) * _Point))
  2776.             target_price=NormalizePriceToSymbol(bid_price - (primary_params ? sell_step : sell_two_step) * _Point);
  2777.         }
  2778.       const bool sell_condition=
  2779.          (stats.sell_positions == 0) ||
  2780.          (stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_step * _Point) && sell_rebalance && primary_params) ||
  2781.          (stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_two_step * _Point) && sell_rebalance && !primary_params && Money != 0.0) ||
  2782.          (stats.sell_highest_position != 0.0 && target_price >= NormalizePriceToSymbol(stats.sell_highest_position + sell_step * _Point) && primary_params) ||
  2783.          (stats.sell_highest_position != 0.0 && target_price >= NormalizePriceToSymbol(stats.sell_highest_position + sell_two_step * _Point) && !primary_params && Money != 0.0) ||
  2784.          (Homeopathy && stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_step * _Point) && lots_equal);
  2785.       if(sell_condition && AllowSellOrderByPriceLimit(stats,target_price,limit_window_active) && CanOpenThisCycle(false,stats))
  2786.         {
  2787.          double volume=(stats.sell_positions == 0) ? lot : (stats.sell_positions * PlusLot + lot * MathPow(K_Lot,stats.sell_positions));
  2788.          volume=NormalizeVolumeToSymbol(volume);
  2789.          const bool use_secondary_comment=
  2790.             ((stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_step * _Point) && sell_rebalance && primary_params) ||
  2791.              (stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_two_step * _Point) && sell_rebalance && !primary_params && Money != 0.0) ||
  2792.              (Homeopathy && stats.sell_lowest_any != 0.0 && target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - sell_step * _Point) && lots_equal));
  2793.          CheckTradeResult(g_trade.SellStop(volume,target_price,_Symbol,0.0,0.0,ORDER_TIME_GTC,0,use_secondary_comment ? GOLDKING_ORDER_COMMENT_SECONDARY : GOLDKING_ORDER_COMMENT_PRIMARY),"SellStop");
  2794.         }
  2795.      }
  2796.    if(OpenMode == OpenMode_Bar && current_bar != 0)
  2797.       g_last_open_bar_time=current_bar;
  2798.   }
  2799. void TryTrailPendingOrders(const EAStats &stats,const bool allow_buy,const bool allow_sell)
  2800.   {
  2801.    const int min_distance=BrokerMinDistancePoints();
  2802.    const int first_step=MathMax(FirstStep,min_distance);
  2803.    const int primary_min=MathMax(MinDistance,min_distance);
  2804.    const int second_min=MathMax(TwoMinDistance,min_distance);
  2805.    const int primary_step=MathMax(Step,min_distance);
  2806.    const int second_step=MathMax(TwoStep,min_distance);
  2807.    const bool primary_params=ShouldUsePrimaryParameters(stats);
  2808.    const bool buy_rebalance=(stats.buy_lots > 0.0 && stats.sell_lots / stats.buy_lots > 3.0 && stats.sell_lots - stats.buy_lots > 0.2);
  2809.    const bool sell_rebalance=(stats.sell_lots > 0.0 && stats.buy_lots / stats.sell_lots > 3.0 && stats.buy_lots - stats.sell_lots > 0.2);
  2810.    const double ask_price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  2811.    const double bid_price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
  2812.    if(allow_buy && stats.buy_pending_ticket > 0)
  2813.      {
  2814.       double target_price=(stats.buy_positions == 0) ? NormalizePriceToSymbol(ask_price + first_step * _Point)
  2815.                                                      : NormalizePriceToSymbol(ask_price + (primary_params ? primary_min : second_min) * _Point);
  2816.       if(stats.buy_positions > 0 && stats.buy_lowest_position != 0.0 && target_price < NormalizePriceToSymbol(stats.buy_lowest_position - (primary_params ? primary_step : second_step) * _Point))
  2817.          target_price=NormalizePriceToSymbol(ask_price + (primary_params ? primary_step : second_step) * _Point);
  2818.       const bool trail_ok=
  2819.          primary_params ?
  2820.          (target_price <= NormalizePriceToSymbol(stats.buy_lowest_position - primary_step * _Point) || stats.buy_lowest_position == 0.0 || (buy_rebalance && stats.buy_positions == 0) || target_price >= NormalizePriceToSymbol(stats.buy_highest_any + primary_step * _Point))
  2821.          :
  2822.          (target_price <= NormalizePriceToSymbol(stats.buy_lowest_position - second_step * _Point) || stats.buy_lowest_position == 0.0 || (buy_rebalance && stats.buy_positions == 0) || target_price >= NormalizePriceToSymbol(stats.buy_highest_any + second_step * _Point));
  2823.       if(stats.buy_pending_price != 0.0 && NormalizePriceToSymbol(stats.buy_pending_price - StepTrallOrders * _Point) > target_price && trail_ok)
  2824.          ModifyPendingPrice(stats.buy_pending_ticket,target_price);
  2825.      }
  2826.    if(allow_sell && stats.sell_pending_ticket > 0)
  2827.      {
  2828.       double target_price=(stats.sell_positions == 0) ? NormalizePriceToSymbol(bid_price - first_step * _Point)
  2829.                                                       : NormalizePriceToSymbol(bid_price - (primary_params ? primary_min : second_min) * _Point);
  2830.       if(stats.sell_positions > 0 && stats.sell_highest_position != 0.0 && target_price < NormalizePriceToSymbol(stats.sell_highest_position + (primary_params ? primary_step : second_step) * _Point))
  2831.          target_price=NormalizePriceToSymbol(bid_price - (primary_params ? primary_step : second_step) * _Point);
  2832.       const bool trail_ok=
  2833.          primary_params ?
  2834.          (target_price >= NormalizePriceToSymbol(stats.sell_highest_position + primary_step * _Point) || stats.sell_highest_position == 0.0 || (sell_rebalance && stats.sell_positions == 0) || target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - primary_step * _Point))
  2835.          :
  2836.          (target_price >= NormalizePriceToSymbol(stats.sell_highest_position + second_step * _Point) || stats.sell_highest_position == 0.0 || (sell_rebalance && stats.sell_positions == 0) || target_price <= NormalizePriceToSymbol(stats.sell_lowest_any - second_step * _Point));
  2837.       if(stats.sell_pending_price != 0.0 && NormalizePriceToSymbol(stats.sell_pending_price + StepTrallOrders * _Point) < target_price && trail_ok)
  2838.          ModifyPendingPrice(stats.sell_pending_ticket,target_price);
  2839.      }
  2840.   }
  2841. void ExecuteStrategy()
  2842.   {
  2843.    EAStats stats;
  2844.    CollectStats(stats);
  2845.    const datetime now_value=ReferenceNow();
  2846.    const datetime news_now=ReferenceNewsNow();
  2847.    RefreshDailyLocks(now_value,stats);
  2848.    RefreshNewsState(false);
  2849.    const bool session_after_stop=IsTradingSessionAfterStop(now_value);
  2850.    const bool session_ok=IsTradingSessionOpen(now_value);
  2851.    const bool wrap_up_blocked=IsDailyWrapUpWindow(news_now);
  2852.    const bool target_locked=g_daily_target_locked;
  2853.    const bool news_blocked=g_news_state.block_entries;
  2854.    if((session_after_stop || wrap_up_blocked || target_locked || news_blocked) && (stats.buy_pending > 0 || stats.sell_pending > 0))
  2855.      {
  2856.       DeleteEaPendingOrders();
  2857.       CollectStats(stats);
  2858.       RefreshDailyLocks(now_value,stats);
  2859.       RefreshNewsState(false);
  2860.      }
  2861.    UpdateLimitLines();
  2862.    UpdateAverageLines(stats);
  2863.    string env_reason="";
  2864.    const bool env_ok=IsTradingEnvironmentOk(stats,env_reason);
  2865.    bool allow_buy=g_allow_buy;
  2866.    bool allow_sell=g_allow_sell;
  2867.    if(Over && stats.buy_positions == 0)
  2868.       allow_buy=false;
  2869.    if(Over && stats.sell_positions == 0)
  2870.       allow_sell=false;
  2871.    if(g_pause_until > TimeCurrent())
  2872.      {
  2873.       allow_buy=false;
  2874.       allow_sell=false;
  2875.      }
  2876.    if(!session_ok || session_after_stop || wrap_up_blocked || target_locked || news_blocked)
  2877.      {
  2878.       allow_buy=false;
  2879.       allow_sell=false;
  2880.      }
  2881.    if(!env_ok)
  2882.      {
  2883.       allow_buy=false;
  2884.       allow_sell=false;
  2885.      }
  2886.    if(TryAutoCloseLogic(stats))
  2887.      {
  2888.       RefreshPanel(true);
  2889.       return;
  2890.      }
  2891.    if(OpenMode == OpenMode_Bar && !(allow_buy || allow_sell))
  2892.      {
  2893.       const datetime current_bar=iTime(_Symbol,TimeZone,0);
  2894.       if(current_bar != 0 && current_bar != g_last_open_bar_time)
  2895.          g_last_open_bar_time=current_bar;
  2896.      }
  2897.    if(allow_buy || allow_sell)
  2898.       TryPlacePendingOrders(stats,allow_buy,allow_sell);
  2899.    if(allow_buy || allow_sell)
  2900.       TryTrailPendingOrders(stats,allow_buy,allow_sell);
  2901.    RefreshPanel(false);
  2902.   }
  2903. double UiScale()
  2904.   {
  2905.    const long chart_width=ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0);
  2906.    const long dpi=TerminalInfoInteger(TERMINAL_SCREEN_DPI);
  2907.    double scale=1.0;
  2908.    if(dpi >= 192)
  2909.       scale=1.08;
  2910.    else if(dpi >= 160)
  2911.       scale=1.04;
  2912.    else if(dpi <= 96)
  2913.       scale=0.98;
  2914.    if(chart_width <= 1280)
  2915.       scale=MathMin(scale,0.94);
  2916.    else if(chart_width >= 2400)
  2917.       scale=MathMin(MathMax(scale,1.0),1.08);
  2918.    return(MathMax(0.90,MathMin(scale,1.10)));
  2919.   }
  2920. double UiFontScale()
  2921.   {
  2922.    const long chart_width=ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0);
  2923.    const long dpi=TerminalInfoInteger(TERMINAL_SCREEN_DPI);
  2924.    double scale=1.0;
  2925.    if(dpi >= 192)
  2926.       scale=1.05;
  2927.    else if(dpi >= 160)
  2928.       scale=1.02;
  2929.    else if(dpi <= 96)
  2930.       scale=0.97;
  2931.    if(chart_width <= 1280)
  2932.       scale=MathMin(scale,0.96);
  2933.    return(MathMax(0.92,MathMin(scale,1.06)));
  2934.   }
  2935. int ScalePx(const int value)
  2936.   {
  2937.    return((int)MathRound(value * UiScale()));
  2938.   }
  2939. int ScaleFont(const int value)
  2940.   {
  2941.    return((int)MathRound(value * UiFontScale()));
  2942.   }
  2943. void BuildPanelMetrics(PanelMetrics &m)
  2944.   {
  2945.    const long chart_width=ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0);
  2946.    const int available_w=(int)MathMax(300.0,(double)chart_width - ScalePx(36));
  2947.    m.margin_x       = ScalePx(16);
  2948.    m.margin_y       = ScalePx(18);
  2949.    m.width          = (int)MathMax(300.0,MathMin((double)ScalePx(440),(double)available_w));
  2950.    m.pad            = ScalePx(14);
  2951.    m.section_gap    = ScalePx(10);
  2952.    m.header_h       = ScalePx(56);
  2953.    m.row_h          = ScalePx(18);
  2954.    m.gap            = ScalePx(8);
  2955.    m.button_h       = ScalePx(30);
  2956.    m.inner_w        = m.width - m.pad * 2;
  2957.    m.half_w         = (m.inner_w - m.gap) / 2;
  2958.    m.card_status_h  = g_panel_open ? ScalePx(184) : ScalePx(172);
  2959.    m.card_metrics_h = g_panel_open ? ScalePx(236) : ScalePx(164);
  2960.    m.card_actions_h = g_panel_open ? (m.pad * 2 + ScalePx(22) + m.gap + m.button_h * 6 + m.gap * 5) : (m.pad * 2 + ScalePx(22) + m.gap + m.button_h);
  2961.    m.button_font    = ScaleFont(9);
  2962.    m.font_xs        = ScaleFont(9);
  2963.    m.font_sm        = ScaleFont(10);
  2964.    m.font_md        = ScaleFont(11);
  2965.    m.font_lg        = ScaleFont(15);
  2966.    m.toggle_w       = (m.width <= ScalePx(340)) ? ScalePx(56) : ScalePx(64);
  2967.    m.panel_h        = m.header_h + m.section_gap + m.card_status_h + m.section_gap + m.card_metrics_h + m.section_gap + m.card_actions_h;
  2968.   }
  2969. void EnsureRectangle(const string name,const int x,const int y,const int w,const int h,const color bg,const color border,const int corner)
  2970.   {
  2971.    if(ObjectFind(0,name) < 0)
  2972.       ObjectCreate(0,name,OBJ_RECTANGLE_LABEL,0,0,0);
  2973.    ObjectSetInteger(0,name,OBJPROP_CORNER,corner);
  2974.    ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
  2975.    ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
  2976.    ObjectSetInteger(0,name,OBJPROP_XSIZE,w);
  2977.    ObjectSetInteger(0,name,OBJPROP_YSIZE,h);
  2978.    ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg);
  2979.    ObjectSetInteger(0,name,OBJPROP_COLOR,border);
  2980.    ObjectSetInteger(0,name,OBJPROP_BORDER_TYPE,BORDER_FLAT);
  2981.    ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
  2982.    ObjectSetInteger(0,name,OBJPROP_SELECTED,false);
  2983.    ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
  2984.    ObjectSetInteger(0,name,OBJPROP_BACK,false);
  2985.   }
  2986. void EnsureLabel(const string name,const string text,const int x,const int y,const int font_size,const color clr,const int corner,const string font="Microsoft YaHei")
  2987.   {
  2988.    if(ObjectFind(0,name) < 0)
  2989.       ObjectCreate(0,name,OBJ_LABEL,0,0,0);
  2990.    ObjectSetInteger(0,name,OBJPROP_CORNER,corner);
  2991.    ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
  2992.    ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
  2993.    ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
  2994.    ObjectSetInteger(0,name,OBJPROP_FONTSIZE,font_size);
  2995.    ObjectSetString(0,name,OBJPROP_FONT,font);
  2996.    ObjectSetString(0,name,OBJPROP_TEXT,text);
  2997.    ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
  2998.    ObjectSetInteger(0,name,OBJPROP_SELECTED,false);
  2999.    ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
  3000.    ObjectSetInteger(0,name,OBJPROP_BACK,false);
  3001.   }
  3002. void EnsureButton(const string name,const string text,const int x,const int y,const int w,const int h,const color bg,const color fg,const int corner)
  3003.   {
  3004.    if(ObjectFind(0,name) < 0)
  3005.       ObjectCreate(0,name,OBJ_BUTTON,0,0,0);
  3006.    ObjectSetInteger(0,name,OBJPROP_CORNER,corner);
  3007.    ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
  3008.    ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
  3009.    ObjectSetInteger(0,name,OBJPROP_XSIZE,w);
  3010.    ObjectSetInteger(0,name,OBJPROP_YSIZE,h);
  3011.    ObjectSetInteger(0,name,OBJPROP_COLOR,fg);
  3012.    ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg);
  3013.    ObjectSetInteger(0,name,OBJPROP_BORDER_COLOR,bg);
  3014.    ObjectSetInteger(0,name,OBJPROP_FONTSIZE,ScaleFont(9));
  3015.    ObjectSetString(0,name,OBJPROP_FONT,"Microsoft YaHei");
  3016.    ObjectSetString(0,name,OBJPROP_TEXT,text);
  3017.    ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
  3018.    ObjectSetInteger(0,name,OBJPROP_SELECTED,false);
  3019.    ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
  3020.    ObjectSetInteger(0,name,OBJPROP_BACK,false);
  3021.   }
  3022. string BoolText(const bool enabled,const string on_text,const string off_text)
  3023.   {
  3024.    return(enabled ? on_text : off_text);
  3025.   }
  3026. string FormatSignedMoney(const double value)
  3027.   {
  3028.    const string sign=(value > 0.0) ? "+" : "";
  3029.    return(sign + DoubleToString(value,2));
  3030.   }
  3031. string FormatPercent(const double value)
  3032.   {
  3033.    return(DoubleToString(value,2) + "%");
  3034.   }
  3035. string FormatPanelMoment(const datetime when,const datetime now_value)
  3036.   {
  3037.    if(when <= 0)
  3038.       return("--");
  3039.    MqlDateTime stamp={};
  3040.    MqlDateTime now_stamp={};
  3041.    TimeToStruct(when,stamp);
  3042.    TimeToStruct(now_value,now_stamp);
  3043.    if(stamp.year == now_stamp.year && stamp.mon == now_stamp.mon && stamp.day == now_stamp.day)
  3044.       return(StringFormat("%02d:%02d",stamp.hour,stamp.min));
  3045.    return(StringFormat("%02d-%02d %02d:%02d",stamp.mon,stamp.day,stamp.hour,stamp.min));
  3046.   }
  3047. string NewsPauseReason(const EAStats &stats)
  3048.   {
  3049.    if(!g_news_state.block_entries)
  3050.       return("");
  3051.    const string resume_text=FormatPanelMoment(g_news_state.resume_time,g_news_state.server_now);
  3052.    if(g_news_state.in_pre_window)
  3053.       return(HasOpenPositions(stats) ? "高影响新闻前3小时,等待全部平仓" : "高影响新闻前3小时,暂停至 服" + resume_text);
  3054.    return(HasOpenPositions(stats) ? "高影响新闻后3小时,等待全部平仓" : "高影响新闻后3小时,暂停至 服" + resume_text);
  3055.   }
  3056. string WrapUpPauseReason(const EAStats &stats)
  3057.   {
  3058.    if(!IsDailyWrapUpWindow(g_news_state.server_now))
  3059.       return("");
  3060.    return(HasOpenPositions(stats) ? "日内收尾阶段,等待全部平仓"
  3061.                                   : "日内收尾阶段,今日停止交易");
  3062.   }
  3063. string SessionStateText(const datetime now_value,const EAStats &stats)
  3064.   {
  3065.    if(!EnableTradingSessionWindow)
  3066.       return("已关闭");
  3067.    if(IsTradingSessionAfterStop(now_value))
  3068.       return(HasOpenPositions(stats) ? "结束时间已到,等待平仓" : "今日已收工");
  3069.    if(!IsTradingSessionOpen(now_value))
  3070.       return("未到工作时间");
  3071.    return("工作时段内");
  3072.   }
  3073. string WrapUpStateText(const EAStats &stats)
  3074.   {
  3075.    if(!EnableDailyWrapUpPhase)
  3076.       return("已关闭");
  3077.    const string slot=DailyWrapUpStartTime + "-" + DailyWrapUpStopTime;
  3078.    if(!IsDailyWrapUpWindow(g_news_state.server_now))
  3079.       return("服" + slot + " 未触发");
  3080.    return(HasOpenPositions(stats) ? "服" + slot + " 等待平仓" : "服" + slot + " 已收尾");
  3081.   }
  3082. string GoalStateText(const double target_progress_display)
  3083.   {
  3084.    if(!EnableDailyProfitTarget)
  3085.       return("已关闭");
  3086.    if(DailyProfitTarget <= 0.0)
  3087.       return("金额<=0");
  3088.    if(g_daily_target_locked)
  3089.       return("已达 " + FormatSignedMoney(MathMax(target_progress_display,g_daily_target_hit_value)) + " / +" + DoubleToString(DailyProfitTarget,2));
  3090.    return("进度 " + FormatSignedMoney(target_progress_display) + " / +" + DoubleToString(DailyProfitTarget,2));
  3091.   }
  3092. string NewsStateText(const EAStats &stats)
  3093.   {
  3094.    const string source_prefix=(g_news_state.using_embedded_history ? "回测内置" : "实时日历");
  3095.    if(!EnableHighImpactNewsPause)
  3096.       return("已关闭");
  3097.    if(!g_news_state.calendar_available)
  3098.       return(source_prefix + " | " + (g_news_state.error_text == "" ? "新闻源不可用,已忽略" : g_news_state.error_text));
  3099.    const string event_time="服" + FormatPanelMoment(g_news_state.event_time,g_news_state.server_now);
  3100.    const string event_prefix=(g_news_state.currency == "" ? "" : g_news_state.currency + " ");
  3101.    const string event_suffix=(g_news_state.event_name == "" ? "" : " " + g_news_state.event_name);
  3102.    if(g_news_state.block_entries)
  3103.      {
  3104.       if(g_news_state.in_pre_window)
  3105.          return(source_prefix + " | " + (HasOpenPositions(stats) ? "前3h等待平仓" : "前3h暂停") + " | " + event_prefix + event_time + event_suffix);
  3106.       return(source_prefix + " | " + (HasOpenPositions(stats) ? "后3h等待平仓" : "后3h冷静期") + " | " + event_prefix + event_time + event_suffix);
  3107.      }
  3108.    if(g_news_state.has_upcoming_event)
  3109.       return(source_prefix + " | 下个高影响 | " + event_prefix + event_time + event_suffix);
  3110.    if(g_news_state.using_embedded_history)
  3111.      {
  3112.       if(g_news_state.server_now < GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_START || g_news_state.server_now > GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_END)
  3113.          return("回测内置 | 范围外 " + GOLDKING_BACKTEST_USD_HIGH_NEWS_RANGE_LABEL);
  3114.       return("回测内置 | 未触发");
  3115.      }
  3116.    return("未触发");
  3117.   }
  3118. string EntryStateText(const string stop_reason)
  3119.   {
  3120.    if(g_allow_buy && g_allow_sell)
  3121.       return("允许");
  3122.    if(!g_allow_buy && !g_allow_sell)
  3123.       return("手动停止");
  3124.    if(stop_reason != "")
  3125.       return("暂停");
  3126.    return("部分允许");
  3127.   }
  3128. string CloseReasonText()
  3129.   {
  3130.    string reason="";
  3131.    EAStats stats;
  3132.    CollectStats(stats);
  3133.    const datetime now_value=ReferenceNow();
  3134.    RefreshDailyLocks(now_value,stats);
  3135.    RefreshNewsState(false);
  3136.    if(g_daily_target_locked)
  3137.       return(HasOpenPositions(stats) ? "今日盈利达标,等待全部平仓" : "今日盈利目标已达成");
  3138.    const string news_reason=NewsPauseReason(stats);
  3139.    if(news_reason != "")
  3140.       return(news_reason);
  3141.    const string wrap_reason=WrapUpPauseReason(stats);
  3142.    if(wrap_reason != "")
  3143.       return(wrap_reason);
  3144.    if(IsTradingSessionAfterStop(now_value))
  3145.       return(HasOpenPositions(stats) ? "已到结束时间,等待全部平仓" : "今日已收工");
  3146.    if(!IsTradingSessionOpen(now_value))
  3147.       return("等待工作时段开始");
  3148.    if(!g_allow_buy && !g_allow_sell)
  3149.       return("已手动停止交易");
  3150.    if(g_pause_until > TimeCurrent())
  3151.       return("冷却中 " + IntegerToString((int)(g_pause_until - TimeCurrent())) + " 秒");
  3152.    if(!IsTradingEnvironmentOk(stats,reason))
  3153.       return(reason);
  3154.    return("");
  3155.   }
  3156. string ClipText(const string text,const int max_chars)
  3157.   {
  3158.    if(max_chars <= 0)
  3159.       return("");
  3160.    if(StringLen(text) <= max_chars)
  3161.       return(text);
  3162.    if(max_chars <= 3)
  3163.       return(StringSubstr(text,0,max_chars));
  3164.    return(StringSubstr(text,0,max_chars - 3) + "...");
  3165.   }
  3166. string TimeframeLabel(const ENUM_TIMEFRAMES timeframe)
  3167.   {
  3168.    const string enum_text=EnumToString(timeframe);
  3169.    if(StringFind(enum_text,"PERIOD_",0) == 0)
  3170.       return(StringSubstr(enum_text,7));
  3171.    return(enum_text);
  3172.   }
  3173. void DrawPanel(const EAStats &stats)
  3174.   {
  3175.    PanelMetrics m;
  3176.    BuildPanelMetrics(m);
  3177.    const int corner=CORNER_LEFT_UPPER;
  3178.    const color panel_bg=C'15,20,27';
  3179.    const color panel_border=C'45,58,74';
  3180.    const color header_bg=C'20,29,40';
  3181.    const color card_bg=C'24,33,45';
  3182.    const color muted=C'150,164,181';
  3183.    const color ok_color=C'88,199,135';
  3184.    const color warn_color=C'255,183,77';
  3185.    const color bad_color=C'239,100,97';
  3186.    const color accent=C'66,153,225';
  3187.    const color accent_alt=C'34,197,154';
  3188.    const color cream=C'244,248,252';
  3189.    const int x=m.margin_x;
  3190.    const int inner_x=x + m.pad;
  3191.    const int inner_x2=inner_x + m.half_w + m.gap;
  3192.    const int right_button_x=x + m.width - m.pad - m.toggle_w;
  3193.    const int reason_chars=(int)MathMax(24.0,MathMin(42.0,(double)m.width / 10.0 - 2.0));
  3194.    const int info_chars=(int)MathMax(26.0,MathMin(48.0,(double)m.width / 8.0));
  3195.    const datetime now_value=ReferenceNow();
  3196.    RefreshDailyLocks(now_value,stats);
  3197.    RefreshNewsState(false);
  3198.    const double spread_pips=CurrentSpreadPoints() / PipDivisor();
  3199.    const double today_profit=TodayClosedProfit(now_value);
  3200.    const double today_progress=TodayProgressProfit(now_value,stats);
  3201.    const double yesterday_profit=CalculateClosedProfit(TodayAt("00:00",now_value) - 86400,TodayAt("00:00",now_value) - 1,Magic,true);
  3202.    const double total_closed=CalculateClosedProfit(0,TimeCurrent(),Magic,true);
  3203.    const double balance=AccountInfoDouble(ACCOUNT_BALANCE);
  3204.    const double equity=AccountInfoDouble(ACCOUNT_EQUITY);
  3205.    const double margin=AccountInfoDouble(ACCOUNT_MARGIN);
  3206.    const double margin_level=(margin > 0.0) ? equity / margin * 100.0 : 0.0;
  3207.    const bool target_enabled=(EnableDailyProfitTarget && DailyProfitTarget > 0.0);
  3208.    const double target_progress_display=g_daily_target_locked ? MathMax(today_progress,g_daily_target_hit_value) : today_progress;
  3209.    const double target_remaining=target_enabled ? MathMax(0.0,DailyProfitTarget - target_progress_display) : 0.0;
  3210.    const bool session_open=IsTradingSessionOpen(now_value);
  3211.    const bool session_after_stop=IsTradingSessionAfterStop(now_value);
  3212.    const bool waiting_start=(!session_open && !session_after_stop);
  3213.    const bool wrap_up_active=IsDailyWrapUpWindow(g_news_state.server_now);
  3214.    const bool wrap_up_waiting_close=wrap_up_active && HasOpenPositions(stats);
  3215.    const bool news_waiting_close=g_news_state.block_entries && HasOpenPositions(stats);
  3216.    const bool waiting_close=(session_after_stop && HasOpenPositions(stats)) || (g_daily_target_locked && HasOpenPositions(stats)) || news_waiting_close || wrap_up_waiting_close;
  3217.    const string stop_reason=CloseReasonText();
  3218.    const string stop_reason_display=(stop_reason == "" ? "环境正常,可开新单" : stop_reason);
  3219.    const string entry_state=EntryStateText(stop_reason);
  3220.    const string session_state=SessionStateText(now_value,stats);
  3221.    const string wrap_state=WrapUpStateText(stats);
  3222.    const string goal_state=GoalStateText(target_progress_display);
  3223.    const string news_state=NewsStateText(stats);
  3224.    string work_state="工作中";
  3225.    color  work_color=ok_color;
  3226.    if(g_daily_target_locked)
  3227.      {
  3228.       work_state=waiting_close ? "盈利达标,待平仓" : "今日盈利达标";
  3229.       work_color=accent_alt;
  3230.      }
  3231.    else if(g_news_state.block_entries)
  3232.      {
  3233.       if(g_news_state.in_pre_window)
  3234.         {
  3235.          work_state=news_waiting_close ? "新闻前等待平仓" : "新闻前暂停";
  3236.          work_color=warn_color;
  3237.         }
  3238.       else
  3239.         {
  3240.          work_state=news_waiting_close ? "新闻后等待平仓" : "新闻后冷静期";
  3241.          work_color=accent;
  3242.         }
  3243.      }
  3244.    else if(wrap_up_active)
  3245.      {
  3246.       work_state=wrap_up_waiting_close ? "日内收尾,待平仓" : "日内收尾";
  3247.       work_color=warn_color;
  3248.      }
  3249.    else if(waiting_close)
  3250.      {
  3251.       work_state="已到结束时间,待平仓";
  3252.       work_color=warn_color;
  3253.      }
  3254.    else if(session_after_stop)
  3255.      {
  3256.       work_state="今日已收工";
  3257.       work_color=accent;
  3258.      }
  3259.    else if(waiting_start)
  3260.      {
  3261.       work_state="等待工作时段";
  3262.       work_color=muted;
  3263.      }
  3264.    else if(!g_allow_buy && !g_allow_sell)
  3265.      {
  3266.       work_state="手动暂停";
  3267.       work_color=bad_color;
  3268.      }
  3269.    else if(stop_reason != "")
  3270.      {
  3271.       work_state="暂停中";
  3272.       work_color=warn_color;
  3273.      }
  3274.    else if(!g_allow_buy || !g_allow_sell)
  3275.      {
  3276.       work_state="单边运行";
  3277.       work_color=accent_alt;
  3278.      }
  3279.    const string subtitle=ClipText(_Symbol + "  |  " + TimeframeLabel((ENUM_TIMEFRAMES)TimeZone) + "  |  " + AccountInfoString(ACCOUNT_CURRENCY),
  3280.                                   (int)MathMax(20.0,MathMin(34.0,(double)m.width / 12.0)));
  3281.    EnsureRectangle(g_panel_prefix + "panel",x,m.margin_y,m.width,m.panel_h,panel_bg,panel_border,corner);
  3282.    EnsureRectangle(g_panel_prefix + "header",x,m.margin_y,m.width,m.header_h,header_bg,panel_border,corner);
  3283.    EnsureRectangle(g_panel_prefix + "header_accent",x,m.margin_y,ScalePx(5),m.header_h,accent,accent,corner);
  3284.    EnsureLabel(g_panel_prefix + "title","金麒麟 MT5",inner_x + ScalePx(6),m.margin_y + ScalePx(10),m.font_lg,cream,corner);
  3285.    EnsureLabel(g_panel_prefix + "subtitle",subtitle,inner_x + ScalePx(6),m.margin_y + ScalePx(31),m.font_sm,muted,corner);
  3286.    EnsureButton(g_panel_prefix + "toggle_panel",g_panel_open ? "收起" : "展开",right_button_x,m.margin_y + ScalePx(13),m.toggle_w,m.button_h,accent,White,corner);
  3287.    int y=m.margin_y + m.header_h + m.section_gap;
  3288.    EnsureRectangle(g_panel_prefix + "card_status",x,y,m.width,m.card_status_h,card_bg,panel_border,corner);
  3289.    EnsureLabel(g_panel_prefix + "status_title","工作状态",inner_x,y + m.pad - ScalePx(1),m.font_md,cream,corner);
  3290.    EnsureLabel(g_panel_prefix + "status_line1","当前  " + work_state,inner_x,y + m.pad + ScalePx(20),m.font_sm,work_color,corner);
  3291.    EnsureLabel(g_panel_prefix + "status_line2",ClipText("交易  " + entry_state + "  |  多空  " + BoolText(g_allow_buy,"多开","多停") + "/" + BoolText(g_allow_sell,"空开","空停"),info_chars),inner_x,y + m.pad + ScalePx(40),m.font_sm,cream,corner);
  3292.    EnsureLabel(g_panel_prefix + "status_line3",ClipText("时段  " + (EnableTradingSessionWindow ? EA_StartTime + "-" + EA_StopTime : "--") + "  |  " + session_state,info_chars),inner_x,y + m.pad + ScalePx(60),m.font_sm,muted,corner);
  3293.    EnsureLabel(g_panel_prefix + "status_line4",ClipText("收尾  " + wrap_state,info_chars),inner_x,y + m.pad + ScalePx(80),m.font_xs,wrap_up_active ? warn_color : muted,corner);
  3294.    EnsureLabel(g_panel_prefix + "status_line5",ClipText("新闻  " + news_state,info_chars),inner_x,y + m.pad + ScalePx(100),m.font_xs,g_news_state.block_entries ? warn_color : muted,corner);
  3295.    EnsureLabel(g_panel_prefix + "status_line6",ClipText("目标  " + goal_state,info_chars),inner_x,y + m.pad + ScalePx(120),m.font_xs,g_daily_target_locked ? accent_alt : cream,corner);
  3296.    EnsureLabel(g_panel_prefix + "status_line7","原因  " + ClipText(stop_reason_display,reason_chars),inner_x,y + m.pad + ScalePx(140),m.font_xs,stop_reason == "" ? muted : warn_color,corner);
  3297.    y+=m.card_status_h + m.section_gap;
  3298.    EnsureRectangle(g_panel_prefix + "card_metrics",x,y,m.width,m.card_metrics_h,card_bg,panel_border,corner);
  3299.    EnsureLabel(g_panel_prefix + "metrics_title","今日目标与账户",inner_x,y + m.pad - ScalePx(1),m.font_md,cream,corner);
  3300.    int line_y=y + m.pad + ScalePx(22);
  3301.    EnsureLabel(g_panel_prefix + "metrics_a_l","今日已平  " + FormatSignedMoney(today_profit),inner_x,line_y,m.font_sm,today_profit >= 0.0 ? ok_color : bad_color,corner);
  3302.    EnsureLabel(g_panel_prefix + "metrics_a_r",
  3303.                !EnableDailyProfitTarget ? "目标  已关闭" :
  3304.                (target_enabled ? ("目标  +" + DoubleToString(DailyProfitTarget,2)) : "目标  金额<=0"),
  3305.                inner_x2,
  3306.                line_y,
  3307.                m.font_sm,
  3308.                target_enabled ? accent : muted,
  3309.                corner);
  3310.    line_y+=m.row_h + m.gap / 2;
  3311.    EnsureLabel(g_panel_prefix + "metrics_b","今日进度  " + FormatSignedMoney(target_progress_display),inner_x,line_y,m.font_sm,target_progress_display >= 0.0 ? ok_color : bad_color,corner);
  3312.    line_y+=m.row_h + m.gap / 2;
  3313.    EnsureLabel(g_panel_prefix + "metrics_c",
  3314.                !EnableDailyProfitTarget ? "今日目标  已关闭" :
  3315.                (target_enabled ? (g_daily_target_locked ? "今日目标  已达成并封盘" : "目标剩余  " + DoubleToString(target_remaining,2)) : "今日目标  金额<=0"),
  3316.                inner_x,
  3317.                line_y,
  3318.                m.font_sm,
  3319.                g_daily_target_locked ? accent_alt : muted,
  3320.                corner);
  3321.    line_y+=m.row_h + m.gap / 2;
  3322.    EnsureLabel(g_panel_prefix + "metrics_d_l","Buy  " + IntegerToString(stats.buy_positions) + "单  " + DoubleToString(stats.buy_lots,2) + "手",inner_x,line_y,m.font_sm,cream,corner);
  3323.    EnsureLabel(g_panel_prefix + "metrics_d_r","Sell  " + IntegerToString(stats.sell_positions) + "单  " + DoubleToString(stats.sell_lots,2) + "手",inner_x2,line_y,m.font_sm,cream,corner);
  3324.    line_y+=m.row_h + m.gap / 2;
  3325.    EnsureLabel(g_panel_prefix + "metrics_e_l","Buy浮盈  " + FormatSignedMoney(stats.buy_profit),inner_x,line_y,m.font_sm,stats.buy_profit >= 0.0 ? ok_color : bad_color,corner);
  3326.    EnsureLabel(g_panel_prefix + "metrics_e_r","Sell浮盈  " + FormatSignedMoney(stats.sell_profit),inner_x2,line_y,m.font_sm,stats.sell_profit >= 0.0 ? ok_color : bad_color,corner);
  3327.    line_y+=m.row_h + m.gap / 2;
  3328.    EnsureLabel(g_panel_prefix + "metrics_f_l","EA浮盈亏  " + FormatSignedMoney(stats.total_profit),inner_x,line_y,m.font_sm,stats.total_profit >= 0.0 ? ok_color : bad_color,corner);
  3329.    EnsureLabel(g_panel_prefix + "metrics_f_r","昨日已平  " + FormatSignedMoney(yesterday_profit),inner_x2,line_y,m.font_sm,yesterday_profit >= 0.0 ? ok_color : bad_color,corner);
  3330.    if(g_panel_open)
  3331.      {
  3332.       line_y+=m.row_h + m.gap / 2;
  3333.       EnsureLabel(g_panel_prefix + "metrics_g_l","累计已平  " + FormatSignedMoney(total_closed),inner_x,line_y,m.font_sm,total_closed >= 0.0 ? ok_color : bad_color,corner);
  3334.       EnsureLabel(g_panel_prefix + "metrics_g_r","保证金比  " + FormatPercent(margin_level),inner_x2,line_y,m.font_sm,margin_level >= 200.0 ? ok_color : warn_color,corner);
  3335.       line_y+=m.row_h + m.gap / 2;
  3336.       EnsureLabel(g_panel_prefix + "metrics_h_l","余额  " + FormatSignedMoney(balance),inner_x,line_y,m.font_sm,cream,corner);
  3337.       EnsureLabel(g_panel_prefix + "metrics_h_r","净值  " + FormatSignedMoney(equity),inner_x2,line_y,m.font_sm,accent_alt,corner);
  3338.       line_y+=m.row_h + m.gap / 2;
  3339.       EnsureLabel(g_panel_prefix + "metrics_i_l","点差  " + DoubleToString(spread_pips,1) + " pips",inner_x,line_y,m.font_sm,muted,corner);
  3340.       EnsureLabel(g_panel_prefix + "metrics_i_r","杠杆  " + IntegerToString((int)AccountInfoInteger(ACCOUNT_LEVERAGE)) + "x",inner_x2,line_y,m.font_sm,muted,corner);
  3341.      }
  3342.    else
  3343.      {
  3344.       line_y+=m.row_h + m.gap / 2;
  3345.       EnsureLabel(g_panel_prefix + "metrics_g_l","余额  " + FormatSignedMoney(balance),inner_x,line_y,m.font_sm,cream,corner);
  3346.       EnsureLabel(g_panel_prefix + "metrics_g_r","净值  " + FormatSignedMoney(equity),inner_x2,line_y,m.font_sm,accent_alt,corner);
  3347.       ObjectDelete(0,g_panel_prefix + "metrics_h_l");
  3348.       ObjectDelete(0,g_panel_prefix + "metrics_h_r");
  3349.       ObjectDelete(0,g_panel_prefix + "metrics_i_l");
  3350.       ObjectDelete(0,g_panel_prefix + "metrics_i_r");
  3351.      }
  3352.    y+=m.card_metrics_h + m.section_gap;
  3353.    EnsureRectangle(g_panel_prefix + "card_actions",x,y,m.width,m.card_actions_h,card_bg,panel_border,corner);
  3354.    EnsureLabel(g_panel_prefix + "actions_title","快捷操作",inner_x,y + m.pad - ScalePx(1),m.font_md,cream,corner);
  3355.    int button_y=y + m.pad + ScalePx(24);
  3356.    EnsureButton(g_panel_prefix + "stop_all",BoolText(!(g_allow_buy || g_allow_sell),"开启交易","停止交易"),inner_x,button_y,m.inner_w,m.button_h,(g_allow_buy || g_allow_sell) ? bad_color : accent_alt,White,corner);
  3357.    if(g_panel_open)
  3358.      {
  3359.       button_y+=m.button_h + m.gap;
  3360.       EnsureButton(g_panel_prefix + "stop_buy",BoolText(g_allow_buy,"停止做多","开启做多"),inner_x,button_y,m.half_w,m.button_h,g_allow_buy ? warn_color : accent_alt,White,corner);
  3361.       EnsureButton(g_panel_prefix + "stop_sell",BoolText(g_allow_sell,"停止做空","开启做空"),inner_x2,button_y,m.half_w,m.button_h,g_allow_sell ? warn_color : accent_alt,White,corner);
  3362.       button_y+=m.button_h + m.gap;
  3363.       EnsureButton(g_panel_prefix + "close_symbol","平当前品种",inner_x,button_y,m.half_w,m.button_h,accent,White,corner);
  3364.       EnsureButton(g_panel_prefix + "close_profit","平盈利单",inner_x2,button_y,m.half_w,m.button_h,accent_alt,White,corner);
  3365.       button_y+=m.button_h + m.gap;
  3366.       EnsureButton(g_panel_prefix + "close_loss","平亏损单",inner_x,button_y,m.half_w,m.button_h,bad_color,White,corner);
  3367.       EnsureButton(g_panel_prefix + "close_buy","平多单",inner_x2,button_y,m.half_w,m.button_h,C'29,78,216',White,corner);
  3368.       button_y+=m.button_h + m.gap;
  3369.       EnsureButton(g_panel_prefix + "close_sell","平空单",inner_x,button_y,m.half_w,m.button_h,C'185,74,72',White,corner);
  3370.       EnsureButton(g_panel_prefix + "close_ea","平本EA全部",inner_x2,button_y,m.half_w,m.button_h,C'121,89,214',White,corner);
  3371.       button_y+=m.button_h + m.gap;
  3372.       EnsureButton(g_panel_prefix + "close_account","平账号全部",inner_x,button_y,m.inner_w,m.button_h,C'92,141,146',White,corner);
  3373.      }
  3374.    else
  3375.      {
  3376.       ObjectDelete(0,g_panel_prefix + "stop_buy");
  3377.       ObjectDelete(0,g_panel_prefix + "stop_sell");
  3378.       ObjectDelete(0,g_panel_prefix + "close_symbol");
  3379.       ObjectDelete(0,g_panel_prefix + "close_profit");
  3380.       ObjectDelete(0,g_panel_prefix + "close_loss");
  3381.       ObjectDelete(0,g_panel_prefix + "close_buy");
  3382.       ObjectDelete(0,g_panel_prefix + "close_sell");
  3383.       ObjectDelete(0,g_panel_prefix + "close_ea");
  3384.       ObjectDelete(0,g_panel_prefix + "close_account");
  3385.      }
  3386.   }
  3387. void RefreshPanel(const bool force)
  3388.   {
  3389.    const datetime now_second=TimeCurrent();
  3390.    if(!force && now_second == g_last_panel_refresh)
  3391.       return;
  3392.    EAStats stats;
  3393.    CollectStats(stats);
  3394.    RefreshNewsState(false);
  3395.    DrawPanel(stats);
  3396.    g_last_panel_refresh=now_second;
  3397.    ChartRedraw(0);
  3398.   }
  3399. void DeleteObjectsByPrefix(const string prefix)
  3400.   {
  3401.    for(int i=ObjectsTotal(0,-1,-1)-1; i>=0; --i)
  3402.      {
  3403.       const string name=ObjectName(0,i,-1,-1);
  3404.       if(StringFind(name,prefix,0) == 0)
  3405.          ObjectDelete(0,name);
  3406.      }
  3407.   }
复制代码
举报

评论 使用道具

精彩评论6

hhf405
D
| 发表于 15 小时前 来自手机 | 显示全部楼层
怎么违规了
举报

点赞 评论 使用道具

Mceach
D
| 发表于 12 小时前 | 显示全部楼层
楼主非常牛逼,是不是带过滤那个版本啊?
举报

点赞 评论 使用道具

lgg3344520
D
| 发表于 11 小时前 | 显示全部楼层
不错,很好···谢谢
举报

点赞 评论 使用道具

marco699
D
| 发表于 9 小时前 | 显示全部楼层
这版本测试如何,有人测试过吗
举报

点赞 评论 使用道具

laojiang
D
| 发表于 8 小时前 | 显示全部楼层
支持下
举报

点赞 评论 使用道具

qazwsx1122
D
| 发表于 2 小时前 | 显示全部楼层
可以模拟测试测试,支持下
举报

点赞 评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册