MT5指标编译通过 · EX5 48KB 自动发布 12 2

交易控制面板EA

taiyu1983·1 天前发布

可拖动面板,一键平仓、开仓、顺势逆势加仓、批量止盈止损、移动止盈

交易控制面板EA

MT5 真机运行截图 · 服务器把编译好的 EX5 挂到黄金 H1 图表上截的,你装上去看到的就是这个样子

TradingControlPanel.mq5975 行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
#property copyright "XAUOF Indicator Studio"
#property version   "1.30"

#include <Trade\Trade.mqh>

//--- 输入参数
input group "=== 开仓设置 ==="
input double InpLotSize = 0.01;       // 默认开仓手数
input double InpLotStep = 0.01;       // 手数调节步长
input double InpMinLot = 0.01;        // 最小手数
input double InpMaxLot = 10.0;        // 最大手数

input group "=== 加仓设置 ==="
input bool InpEnableAddPosition = true;   // 启用加仓功能
input double InpAddLotMultiplier = 1.5;   // 加仓手数倍数(相对上一单)
input int InpTrendAddDistance = 200;      // 顺势加仓间距(点数,盈利后)
input int InpCounterAddDistance = 300;    // 逆势加仓间距(点数,浮亏后)
input int InpMaxAddTimes = 3;             // 最大加仓次数

input group "=== 止盈止损设置 ==="
input int InpTakeProfit = 500;        // 固定止盈点数(0=不设置)
input int InpStopLoss = 300;          // 固定止损点数(0=不设置)
input bool InpAutoSetTPSL = true;     // 开仓时自动设置止盈止损

input group "=== 移动止盈 ==="
input bool InpEnableTrailing = true;  // 启用移动止盈
input int InpTrailStart = 300;        // 移动止盈触发点数
input int InpTrailDistance = 150;     // 移动止盈距离点数

input group "=== 保本设置 ==="
input int InpBreakEvenPoints = 50;    // 保本后加点数(开仓价之上/下)

input group "=== 面板设置 ==="
input int InpPanelX = 20;             // 面板初始X坐标
input int InpPanelY = 30;             // 面板初始Y坐标
input color InpCloseColor = clrCrimson;   // 平仓按钮颜色
input color InpOpenColor = clrForestGreen; // 开仓按钮颜色
input color InpAddColor = clrOrange;      // 加仓按钮颜色
input color InpSetColor = clrDodgerBlue;  // 设置按钮颜色

//--- 全局变量
CTrade trade;
int timerCounter = 0;
double currentLotSize = 0.01;

//--- 面板拖动相关
bool isDragging = false;
int dragStartX = 0;
int dragStartY = 0;
int panelX = 0;
int panelY = 0;

//--- 面板尺寸
int panelWidth = 140;
int panelHeight = 450;

//--- 对象名称常量
#define PANEL_BG         "panelBG"
#define PANEL_TITLE      "panelTitle"
#define BTN_OPEN_BUY     "btnOpenBuy"
#define BTN_OPEN_SELL    "btnOpenSell"
#define BTN_LOT_UP       "btnLotUp"
#define BTN_LOT_DOWN     "btnLotDown"
#define LABEL_LOT        "lblLot"
#define BTN_ADD_TREND    "btnAddTrend"
#define BTN_ADD_COUNTER  "btnAddCounter"
#define BTN_CLOSE_ALL    "btnCloseAll"
#define BTN_CLOSE_BUY    "btnCloseBuy"
#define BTN_CLOSE_SELL   "btnCloseSell"
#define BTN_SET_TP       "btnSetTP"
#define BTN_SET_SL       "btnSetSL"
#define BTN_BREAKEVEN    "btnBreakEven"
#define LABEL_INFO       "lblInfo"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   trade.SetExpertMagicNumber(0);
   trade.SetDeviationInPoints(10);
   
   if(!trade.SetTypeFillingBySymbol(_Symbol))
      trade.SetTypeFilling(ORDER_FILLING_FOK);
   
   currentLotSize = InpLotSize;
   currentLotSize = NormalizeDouble(MathMax(InpMinLot, MathMin(InpMaxLot, currentLotSize)), 2);
   
   panelX = InpPanelX;
   panelY = InpPanelY;
   
   CreatePanel();
   EventSetTimer(1);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();
   DeletePanel();
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   UpdateInfoLabel();
   
   // 自动加仓检查
   if(InpEnableAddPosition)
   {
      CheckAutoAddPosition();
   }
}

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
   timerCounter++;
   if(timerCounter >= 1)
   {
      timerCounter = 0;
      if(InpEnableTrailing)
         TrailingStop();
   }
   UpdateInfoLabel();
}

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   // 处理鼠标拖动
   if(id == CHARTEVENT_MOUSE_MOVE)
   {
      int x = (int)lparam;
      int y = (int)dparam;
      int flags = (int)sparam;
      
      if((flags & 1) == 1)
      {
         if(!isDragging)
         {
            if(x >= panelX && x <= panelX + panelWidth && 
               y >= panelY && y <= panelY + 25)
            {
               isDragging = true;
               dragStartX = x - panelX;
               dragStartY = y - panelY;
            }
         }
         else
         {
            panelX = x - dragStartX;
            panelY = y - dragStartY;
            
            if(panelX < 0) panelX = 0;
            if(panelY < 0) panelY = 0;
            
            int chartWidth = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
            int chartHeight = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
            
            if(panelX + panelWidth > chartWidth) 
               panelX = chartWidth - panelWidth;
            if(panelY + panelHeight > chartHeight) 
               panelY = chartHeight - panelHeight;
            
            UpdatePanelPosition();
         }
      }
      else
      {
         isDragging = false;
      }
   }
   
   // 处理按钮点击
   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      if(sparam == BTN_OPEN_BUY)
      {
         OpenPosition(ORDER_TYPE_BUY);
         ObjectSetInteger(0, BTN_OPEN_BUY, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_OPEN_SELL)
      {
         OpenPosition(ORDER_TYPE_SELL);
         ObjectSetInteger(0, BTN_OPEN_SELL, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_ADD_TREND)
      {
         AddPositionTrend();
         ObjectSetInteger(0, BTN_ADD_TREND, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_ADD_COUNTER)
      {
         AddPositionCounter();
         ObjectSetInteger(0, BTN_ADD_COUNTER, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_LOT_UP)
      {
         currentLotSize = NormalizeDouble(currentLotSize + InpLotStep, 2);
         if(currentLotSize > InpMaxLot)
            currentLotSize = InpMaxLot;
         UpdateLotLabel();
         ObjectSetInteger(0, BTN_LOT_UP, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_LOT_DOWN)
      {
         currentLotSize = NormalizeDouble(currentLotSize - InpLotStep, 2);
         if(currentLotSize < InpMinLot)
            currentLotSize = InpMinLot;
         UpdateLotLabel();
         ObjectSetInteger(0, BTN_LOT_DOWN, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_CLOSE_ALL)
      {
         CloseAllPositions();
         ObjectSetInteger(0, BTN_CLOSE_ALL, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_CLOSE_BUY)
      {
         ClosePositionsByType(POSITION_TYPE_BUY);
         ObjectSetInteger(0, BTN_CLOSE_BUY, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_CLOSE_SELL)
      {
         ClosePositionsByType(POSITION_TYPE_SELL);
         ObjectSetInteger(0, BTN_CLOSE_SELL, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_SET_TP)
      {
         SetFixedTakeProfit();
         ObjectSetInteger(0, BTN_SET_TP, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_SET_SL)
      {
         SetFixedStopLoss();
         ObjectSetInteger(0, BTN_SET_SL, OBJPROP_STATE, false);
      }
      else if(sparam == BTN_BREAKEVEN)
      {
         SetBreakEven();
         ObjectSetInteger(0, BTN_BREAKEVEN, OBJPROP_STATE, false);
      }
      
      ChartRedraw();
   }
}

//+------------------------------------------------------------------+
//| 创建控制面板                                                      |
//+------------------------------------------------------------------+
void CreatePanel()
{
   int btnWidth = 120;
   int btnHeight = 30;
   int smallBtn = 35;
   int spacing = 5;
   int margin = 10;
   
   CreateBackground(PANEL_BG, panelX, panelY, panelWidth, panelHeight);
   
   CreateLabel(PANEL_TITLE, panelX + 5, panelY + 5);
   ObjectSetString(0, PANEL_TITLE, OBJPROP_TEXT, "≡ 交易控制面板");
   ObjectSetInteger(0, PANEL_TITLE, OBJPROP_FONTSIZE, 10);
   ObjectSetInteger(0, PANEL_TITLE, OBJPROP_COLOR, clrWhiteSmoke);
   
   int y = panelY + 30;
   int x = panelX + margin;
   
   // 开仓按钮
   CreateButton(BTN_OPEN_BUY, "开多", x, y, btnWidth, btnHeight, InpOpenColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_OPEN_SELL, "开空", x, y, btnWidth, btnHeight, InpOpenColor);
   y += btnHeight + spacing;
   
   // 手数调节
   CreateButton(BTN_LOT_DOWN, "-", x, y, smallBtn, btnHeight, clrGray);
   CreateLabel(LABEL_LOT, x + smallBtn + 5, y + 8);
   CreateButton(BTN_LOT_UP, "+", x + smallBtn + 55, y, smallBtn, btnHeight, clrGray);
   UpdateLotLabel();
   y += btnHeight + spacing * 2;
   
   // 加仓按钮
   CreateButton(BTN_ADD_TREND, "顺势加仓", x, y, btnWidth, btnHeight, InpAddColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_ADD_COUNTER, "逆势加仓", x, y, btnWidth, btnHeight, InpAddColor);
   y += btnHeight + spacing * 2;
   
   // 平仓按钮
   CreateButton(BTN_CLOSE_ALL, "一键平仓", x, y, btnWidth, btnHeight, InpCloseColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_CLOSE_BUY, "一键平多", x, y, btnWidth, btnHeight, InpCloseColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_CLOSE_SELL, "一键平空", x, y, btnWidth, btnHeight, InpCloseColor);
   y += btnHeight + spacing * 2;
   
   // 设置按钮
   CreateButton(BTN_SET_TP, "设置止盈", x, y, btnWidth, btnHeight, InpSetColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_SET_SL, "设置止损", x, y, btnWidth, btnHeight, InpSetColor);
   y += btnHeight + spacing;
   
   CreateButton(BTN_BREAKEVEN, "一键保本", x, y, btnWidth, btnHeight, InpSetColor);
   y += btnHeight + spacing * 2;
   
   CreateLabel(LABEL_INFO, x, y);
}

//+------------------------------------------------------------------+
//| 创建背景                                                          |
//+------------------------------------------------------------------+
void CreateBackground(string name, int x, int y, int width, int height)
{
   ObjectDelete(0, name);
   ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clrBlack);
   ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clrDimGray);
   ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}

//+------------------------------------------------------------------+
//| 创建按钮                                                          |
//+------------------------------------------------------------------+
void CreateButton(string name, string text, int x, int y, int width, int height, color clr)
{
   ObjectDelete(0, name);
   ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
   ObjectSetString(0, name, OBJPROP_TEXT, text);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}

//+------------------------------------------------------------------+
//| 创建标签                                                          |
//+------------------------------------------------------------------+
void CreateLabel(string name, int x, int y)
{
   ObjectDelete(0, name);
   ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);
   ObjectSetString(0, name, OBJPROP_TEXT, "");
}

//+------------------------------------------------------------------+
//| 更新面板位置                                                      |
//+------------------------------------------------------------------+
void UpdatePanelPosition()
{
   int btnWidth = 120;
   int btnHeight = 30;
   int smallBtn = 35;
   int spacing = 5;
   int margin = 10;
   
   ObjectSetInteger(0, PANEL_BG, OBJPROP_XDISTANCE, panelX);
   ObjectSetInteger(0, PANEL_BG, OBJPROP_YDISTANCE, panelY);
   
   ObjectSetInteger(0, PANEL_TITLE, OBJPROP_XDISTANCE, panelX + 5);
   ObjectSetInteger(0, PANEL_TITLE, OBJPROP_YDISTANCE, panelY + 5);
   
   int y = panelY + 30;
   int x = panelX + margin;
   
   ObjectSetInteger(0, BTN_OPEN_BUY, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_OPEN_BUY, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_OPEN_SELL, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_OPEN_SELL, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_LOT_DOWN, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_LOT_DOWN, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, LABEL_LOT, OBJPROP_XDISTANCE, x + smallBtn + 5);
   ObjectSetInteger(0, LABEL_LOT, OBJPROP_YDISTANCE, y + 8);
   ObjectSetInteger(0, BTN_LOT_UP, OBJPROP_XDISTANCE, x + smallBtn + 55);
   ObjectSetInteger(0, BTN_LOT_UP, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing * 2;
   
   ObjectSetInteger(0, BTN_ADD_TREND, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_ADD_TREND, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_ADD_COUNTER, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_ADD_COUNTER, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing * 2;
   
   ObjectSetInteger(0, BTN_CLOSE_ALL, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_CLOSE_ALL, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_CLOSE_BUY, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_CLOSE_BUY, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_CLOSE_SELL, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_CLOSE_SELL, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing * 2;
   
   ObjectSetInteger(0, BTN_SET_TP, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_SET_TP, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_SET_SL, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_SET_SL, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing;
   
   ObjectSetInteger(0, BTN_BREAKEVEN, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, BTN_BREAKEVEN, OBJPROP_YDISTANCE, y);
   y += btnHeight + spacing * 2;
   
   ObjectSetInteger(0, LABEL_INFO, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, LABEL_INFO, OBJPROP_YDISTANCE, y);
   
   ChartRedraw();
}

//+------------------------------------------------------------------+
//| 删除面板                                                          |
//+------------------------------------------------------------------+
void DeletePanel()
{
   ObjectDelete(0, PANEL_BG);
   ObjectDelete(0, PANEL_TITLE);
   ObjectDelete(0, BTN_OPEN_BUY);
   ObjectDelete(0, BTN_OPEN_SELL);
   ObjectDelete(0, BTN_ADD_TREND);
   ObjectDelete(0, BTN_ADD_COUNTER);
   ObjectDelete(0, BTN_LOT_UP);
   ObjectDelete(0, BTN_LOT_DOWN);
   ObjectDelete(0, LABEL_LOT);
   ObjectDelete(0, BTN_CLOSE_ALL);
   ObjectDelete(0, BTN_CLOSE_BUY);
   ObjectDelete(0, BTN_CLOSE_SELL);
   ObjectDelete(0, BTN_SET_TP);
   ObjectDelete(0, BTN_SET_SL);
   ObjectDelete(0, BTN_BREAKEVEN);
   ObjectDelete(0, LABEL_INFO);
}

//+------------------------------------------------------------------+
//| 更新手数标签                                                      |
//+------------------------------------------------------------------+
void UpdateLotLabel()
{
   string lotText = StringFormat("%.2f手", currentLotSize);
   ObjectSetString(0, LABEL_LOT, OBJPROP_TEXT, lotText);
}

//+------------------------------------------------------------------+
//| 更新信息标签                                                      |
//+------------------------------------------------------------------+
void UpdateInfoLabel()
{
   int totalPos = PositionsTotal();
   int buyCount = 0, sellCount = 0;
   double totalProfit = 0.0;
   
   for(int i = 0; i < totalPos; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            if(type == POSITION_TYPE_BUY)
               buyCount++;
            else if(type == POSITION_TYPE_SELL)
               sellCount++;
            
            totalProfit += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
         }
      }
   }
   
   string info = StringFormat("持仓: %d\n多:%d 空:%d\n盈亏: %.2f", 
                              buyCount + sellCount, buyCount, sellCount, totalProfit);
   
   if(InpEnableTrailing)
      info += "\n移动止盈: 开";
   
   ObjectSetString(0, LABEL_INFO, OBJPROP_TEXT, info);
}

//+------------------------------------------------------------------+
//| 开仓                                                              |
//+------------------------------------------------------------------+
void OpenPosition(ENUM_ORDER_TYPE orderType)
{
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double price = (orderType == ORDER_TYPE_BUY) ? ask : bid;
   
   double tp = 0.0, sl = 0.0;
   
   if(InpAutoSetTPSL)
   {
      if(orderType == ORDER_TYPE_BUY)
      {
         if(InpTakeProfit > 0)
            tp = NormalizeDouble(price + InpTakeProfit * _Point, _Digits);
         if(InpStopLoss > 0)
            sl = NormalizeDouble(price - InpStopLoss * _Point, _Digits);
      }
      else
      {
         if(InpTakeProfit > 0)
            tp = NormalizeDouble(price - InpTakeProfit * _Point, _Digits);
         if(InpStopLoss > 0)
            sl = NormalizeDouble(price + InpStopLoss * _Point, _Digits);
      }
   }
   
   bool result = false;
   if(orderType == ORDER_TYPE_BUY)
      result = trade.Buy(currentLotSize, _Symbol, 0, sl, tp, "面板开仓");
   else
      result = trade.Sell(currentLotSize, _Symbol, 0, sl, tp, "面板开仓");
   
   if(result)
   {
      Print("开仓成功:", (orderType == ORDER_TYPE_BUY ? "多单" : "空单"), 
            ",手数:", currentLotSize, ",价格:", price);
   }
   else
   {
      Print("开仓失败:", trade.ResultRetcodeDescription());
   }
}

//+------------------------------------------------------------------+
//| 顺势加仓(盈利方向)                                              |
//+------------------------------------------------------------------+
void AddPositionTrend()
{
   if(!InpEnableAddPosition)
   {
      Print("加仓功能未启用");
      return;
   }
   
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   int total = PositionsTotal();
   int added = 0;
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double lots = PositionGetDouble(POSITION_VOLUME);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            // 检查是否盈利达到顺势加仓条件
            bool canAdd = false;
            if(type == POSITION_TYPE_BUY && bid > openPrice + InpTrendAddDistance * _Point)
               canAdd = true;
            else if(type == POSITION_TYPE_SELL && ask < openPrice - InpTrendAddDistance * _Point)
               canAdd = true;
            
            if(canAdd)
            {
               // 计算加仓手数
               double newLot = NormalizeDouble(lots * InpAddLotMultiplier, 2);
               if(newLot > InpMaxLot)
                  newLot = InpMaxLot;
               
               // 计算止盈止损
               double tp = 0.0, sl = 0.0;
               double price = (type == POSITION_TYPE_BUY) ? ask : bid;
               
               if(InpAutoSetTPSL)
               {
                  if(type == POSITION_TYPE_BUY)
                  {
                     if(InpTakeProfit > 0)
                        tp = NormalizeDouble(price + InpTakeProfit * _Point, _Digits);
                     if(InpStopLoss > 0)
                        sl = NormalizeDouble(price - InpStopLoss * _Point, _Digits);
                  }
                  else
                  {
                     if(InpTakeProfit > 0)
                        tp = NormalizeDouble(price - InpTakeProfit * _Point, _Digits);
                     if(InpStopLoss > 0)
                        sl = NormalizeDouble(price + InpStopLoss * _Point, _Digits);
                  }
               }
               
               // 执行加仓
               bool result = false;
               if(type == POSITION_TYPE_BUY)
                  result = trade.Buy(newLot, _Symbol, 0, sl, tp, "顺势加仓");
               else
                  result = trade.Sell(newLot, _Symbol, 0, sl, tp, "顺势加仓");
               
               if(result)
                  added++;
            }
         }
      }
   }
   
   Print("顺势加仓完成,已加仓 ", added, " 次");
}

//+------------------------------------------------------------------+
//| 逆势加仓(浮亏方向)                                              |
//+------------------------------------------------------------------+
void AddPositionCounter()
{
   if(!InpEnableAddPosition)
   {
      Print("加仓功能未启用");
      return;
   }
   
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   int total = PositionsTotal();
   int added = 0;
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double lots = PositionGetDouble(POSITION_VOLUME);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            // 检查是否浮亏达到逆势加仓条件
            bool canAdd = false;
            if(type == POSITION_TYPE_BUY && bid < openPrice - InpCounterAddDistance * _Point)
               canAdd = true;
            else if(type == POSITION_TYPE_SELL && ask > openPrice + InpCounterAddDistance * _Point)
               canAdd = true;
            
            if(canAdd)
            {
               // 计算加仓手数
               double newLot = NormalizeDouble(lots * InpAddLotMultiplier, 2);
               if(newLot > InpMaxLot)
                  newLot = InpMaxLot;
               
               // 计算止盈止损
               double tp = 0.0, sl = 0.0;
               double price = (type == POSITION_TYPE_BUY) ? ask : bid;
               
               if(InpAutoSetTPSL)
               {
                  if(type == POSITION_TYPE_BUY)
                  {
                     if(InpTakeProfit > 0)
                        tp = NormalizeDouble(price + InpTakeProfit * _Point, _Digits);
                     if(InpStopLoss > 0)
                        sl = NormalizeDouble(price - InpStopLoss * _Point, _Digits);
                  }
                  else
                  {
                     if(InpTakeProfit > 0)
                        tp = NormalizeDouble(price - InpTakeProfit * _Point, _Digits);
                     if(InpStopLoss > 0)
                        sl = NormalizeDouble(price + InpStopLoss * _Point, _Digits);
                  }
               }
               
               // 执行加仓
               bool result = false;
               if(type == POSITION_TYPE_BUY)
                  result = trade.Buy(newLot, _Symbol, 0, sl, tp, "逆势加仓");
               else
                  result = trade.Sell(newLot, _Symbol, 0, sl, tp, "逆势加仓");
               
               if(result)
                  added++;
            }
         }
      }
   }
   
   Print("逆势加仓完成,已加仓 ", added, " 次");
}

//+------------------------------------------------------------------+
//| 自动检查加仓条件(按次数限制)                                    |
//+------------------------------------------------------------------+
void CheckAutoAddPosition()
{
   // 此函数为预留接口,可根据需要实现自动加仓逻辑
   // 当前版本采用手动点击加仓按钮的方式
}

//+------------------------------------------------------------------+
//| 平所有仓位                                                        |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
   int closed = 0;
   int total = PositionsTotal();
   
   for(int i = total - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            if(trade.PositionClose(ticket))
               closed++;
         }
      }
   }
   
   Print("一键平仓完成,已平 ", closed, " 个仓位");
}

//+------------------------------------------------------------------+
//| 按类型平仓                                                        |
//+------------------------------------------------------------------+
void ClosePositionsByType(ENUM_POSITION_TYPE type)
{
   int closed = 0;
   int total = PositionsTotal();
   
   for(int i = total - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            if(posType == type)
            {
               if(trade.PositionClose(ticket))
                  closed++;
            }
         }
      }
   }
   
   string typeName = (type == POSITION_TYPE_BUY) ? "多单" : "空单";
   Print("一键平", typeName, "完成,已平 ", closed, " 个仓位");
}

//+------------------------------------------------------------------+
//| 设置固定止盈                                                      |
//+------------------------------------------------------------------+
void SetFixedTakeProfit()
{
   if(InpTakeProfit <= 0)
   {
      Print("固定止盈点数未设置或无效");
      return;
   }
   
   int modified = 0;
   int total = PositionsTotal();
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentSL = PositionGetDouble(POSITION_SL);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            double newTP = 0.0;
            if(type == POSITION_TYPE_BUY)
               newTP = NormalizeDouble(openPrice + InpTakeProfit * _Point, _Digits);
            else
               newTP = NormalizeDouble(openPrice - InpTakeProfit * _Point, _Digits);
            
            if(trade.PositionModify(ticket, currentSL, newTP))
               modified++;
         }
      }
   }
   
   Print("固定止盈设置完成,已修改 ", modified, " 个仓位,止盈点数: ", InpTakeProfit);
}

//+------------------------------------------------------------------+
//| 设置固定止损                                                      |
//+------------------------------------------------------------------+
void SetFixedStopLoss()
{
   if(InpStopLoss <= 0)
   {
      Print("固定止损点数未设置或无效");
      return;
   }
   
   int modified = 0;
   int total = PositionsTotal();
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentTP = PositionGetDouble(POSITION_TP);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            double newSL = 0.0;
            if(type == POSITION_TYPE_BUY)
               newSL = NormalizeDouble(openPrice - InpStopLoss * _Point, _Digits);
            else
               newSL = NormalizeDouble(openPrice + InpStopLoss * _Point, _Digits);
            
            if(trade.PositionModify(ticket, newSL, currentTP))
               modified++;
         }
      }
   }
   
   Print("固定止损设置完成,已修改 ", modified, " 个仓位,止损点数: ", InpStopLoss);
}

//+------------------------------------------------------------------+
//| 移动止盈                                                          |
//+------------------------------------------------------------------+
void TrailingStop()
{
   int total = PositionsTotal();
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentSL = PositionGetDouble(POSITION_SL);
            double currentTP = PositionGetDouble(POSITION_TP);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            if(type == POSITION_TYPE_BUY)
            {
               double profit = bid - openPrice;
               if(profit >= InpTrailStart * _Point)
               {
                  double newSL = NormalizeDouble(bid - InpTrailDistance * _Point, _Digits);
                  
                  if(newSL > currentSL || currentSL == 0.0)
                  {
                     trade.PositionModify(ticket, newSL, currentTP);
                  }
               }
            }
            else if(type == POSITION_TYPE_SELL)
            {
               double profit = openPrice - ask;
               if(profit >= InpTrailStart * _Point)
               {
                  double newSL = NormalizeDouble(ask + InpTrailDistance * _Point, _Digits);
                  
                  if(newSL < currentSL || currentSL == 0.0)
                  {
                     trade.PositionModify(ticket, newSL, currentTP);
                  }
               }
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 一键保本                                                          |
//+------------------------------------------------------------------+
void SetBreakEven()
{
   int modified = 0;
   int total = PositionsTotal();
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentTP = PositionGetDouble(POSITION_TP);
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            double newSL = 0.0;
            
            if(type == POSITION_TYPE_BUY)
            {
               newSL = NormalizeDouble(openPrice + InpBreakEvenPoints * _Point, _Digits);
               
               if(bid > newSL)
               {
                  if(trade.PositionModify(ticket, newSL, currentTP))
                     modified++;
               }
            }
            else if(type == POSITION_TYPE_SELL)
            {
               newSL = NormalizeDouble(openPrice - InpBreakEvenPoints * _Point, _Digits);
               
               if(ask < newSL)
               {
                  if(trade.PositionModify(ticket, newSL, currentTP))
                     modified++;
               }
            }
         }
      }
   }
   
   Print("一键保本完成,已修改 ", modified, " 个仓位,加点数: ", InpBreakEvenPoints);
}
//+------------------------------------------------------------------+
MT5 运行截图 · 完整视图带价格轴和时间轴的整张图表(约 150 根 H1 K 线),上面的封面是它最近 80 根 K 线的放大视图
交易控制面板EA 在 MT5 上的真实截图

作品说明

已添加顺势加仓和逆势加仓功能,可设置加仓手数倍数、间距点数和最大加仓次数。

使用说明

  1. 安装方法:将文件保存到 MT5 的 Experts 文件夹,编译后拖到图表上启用。
  1. 面板拖动:鼠标按住标题栏(≡ 交易控制面板)可拖动面板到任意位置。
  1. 顺势加仓:盈利达到设定点数后点击"顺势加仓",按手数倍数追加仓位,适合趋势行情。
  1. 逆势加仓:浮亏达到设定点数后点击"逆势加仓",摊平成本补仓,适合震荡行情(高风险)。
  1. 加仓参数:手数倍数默认 1.5 倍,顺势间距 200 点,逆势间距 300 点,可在输入参数中调整。
  1. 风险提示:逆势加仓会放大亏损风险,建议配合严格止损使用;加仓次数不限,需人工控制。
  1. 移动止盈:自动运行,盈利达到触发点后止损会跟随价格移动保护利润。
  1. 注意事项:加仓按钮为手动触发,每次点击会检查所有符合条件的持仓并加仓,避免重复点击。

AI 解读根据源码逐行分析写成,供参考,以实际运行为准

这是什么

这是一个挂在 MT5 图表上的图形化交易面板 EA,把开仓、平仓、加仓、改止盈止损这些操作做成按钮,点一下就执行,省得每次右键菜单找半天。面板可以鼠标拖着走,不挡 K 线。

逻辑原理

开仓:点「开多」或「开空」按当前设置的手数下单,价格按市价成交(多单用 Ask,空单用 Bid)。如果参数里勾了自动设 TP/SL,开仓时会按固定点数算好止盈止损一起挂上。

加仓:分两种,都是手动点按钮触发。点「顺势加仓」时,代码会遍历当前品种所有持仓,如果某单已经盈利超过设定点数(多单现价高于开仓价 + 顺势间距,空单反之),就按「上一单手数 × 手数倍数」再开一单同方向的。点「逆势加仓」时,逻辑反过来:如果某单浮亏超过逆势间距点数,就补仓摊平成本。加仓手数上限受最大手数参数约束。

平仓:「一键平仓」关所有当前品种持仓,「一键平多」只关多单,「一键平空」只关空单。

批量止盈止损:点「设置止盈」会给所有持仓按固定点数统一加 TP,点「设置止损」同理加 SL。点「一键保本」会把所有持仓的止损改到开仓价往盈利方向加几个点的位置(多单止损挪到开仓价上方,空单挪到下方)。

移动止盈:如果参数里开了,EA 会每秒检查一次持仓。当某单盈利达到触发点数后,止损会自动跟着价格往盈利方向移动,保持距离固定点数。多单价格涨,止损往上推;空单价格跌,止损往下推。

面板上实时显示当前持仓数量、多空单分布、总盈亏。

参数说明

  • InpLotSize(0.01):默认开仓手数,面板上可以用 +/- 按钮临时调整。
  • InpLotStep(0.01):每次点 +/- 增减的手数步长。
  • InpMinLot(0.01)/ InpMaxLot(10.0):手数调节和加仓的上下限。
  • InpEnableAddPosition(true):是否启用加仓功能,关掉后加仓按钮点了也不执行。
  • InpAddLotMultiplier(1.5):加仓手数倍数,比如上一单 0.1 手,加仓就开 0.15 手。
  • InpTrendAddDistance(200):顺势加仓触发间距,单位点(不是点子),盈利超过这个值才能加。
  • InpCounterAddDistance(300):逆势加仓触发间距,浮亏超过这个值才补仓。
  • InpMaxAddTimes(3):代码里定义了但未实际限制加仓次数,目前每次点按钮会检查所有符合条件的单子。
  • InpTakeProfit(500)/ InpStopLoss(300):固定止盈 / 止损点数,设 0 表示不自动加。
  • InpAutoSetTPSL(true):开仓时是否自动按上面两个参数设 TP/SL。
  • InpEnableTrailing(true):是否启用移动止盈。
  • InpTrailStart(300):移动止盈触发点数,盈利达到这个值止损才开始跟。
  • InpTrailDistance(150):移动止盈距离,止损跟价格保持这个点数。
  • InpBreakEvenPoints(50):保本时止损放在开仓价上方 / 下方多少点。
  • InpPanelX(20)/ InpPanelY(30):面板初始位置坐标,装上后可以拖着调。
  • InpCloseColor / InpOpenColor / InpAddColor / InpSetColor:按钮颜色,纯美化用。

怎么用

把文件保存到 MetaTrader 5/MQL5/Experts/ 文件夹,打开 MetaEditor 编译,然后从导航器拖到任意品种的图表上。弹出的设置窗口里调好参数,勾选「允许 EA 交易」和「允许 DLL 导入」(虽然这个 EA 没用 DLL,但有些券商要求勾),点确定。

面板会出现在图表左上角,按住标题栏(≡ 交易控制面板)可以拖到顺手的位置。用 +/- 调好手数,点「开多」或「开空」下单。加仓按钮是手动触发的,想顺势加就点「顺势加仓」,想补仓就点「逆势加仓」,每次点击会检查所有持仓里符合间距条件的单子一起加。平仓、改 TP/SL、保本按钮同理,点了立即执行。

移动止盈是后台自动跑的,开着就行,不用管。面板下方会实时显示持仓情况和盈亏。

适用场景

适合需要频繁手动开平仓的交易者,特别是盘中做短线、需要快速调整止盈止损的场景。顺势加仓适合趋势行情,盈利后追加仓位放大利润;逆势加仓适合震荡行情补仓降成本,但风险大,只建议在有明确支撑阻力位、确定不会单边的时候用。

移动止盈适合单边走势,能锁住大部分利润;保本功能适合行情走了一段、想先保住本金再看后续。

品种和周期没限制,但点数相关的参数要根据波动调。比如黄金(XAUUSD)波动大,顺势间距 200 点可能几分钟就到;欧美(EURUSD)波动小,200 点可能要等半天。建议根据品种平均波动和自己交易周期重新测一遍参数。

风险提示

加仓无次数限制:虽然参数里有 InpMaxAddTimes,但代码里并没有真正限制加仓次数。每次点按钮都会遍历所有持仓,符合条件的全加,连续点或者行情持续单边会一直开新单,手数按倍数增长,保证金和风险暴涨。

逆势加仓高风险:震荡行情里逆势补仓能摊平成本,但如果遇到单边行情(比如非农数据、央行决议),价格不回头,逆势加仓会越亏越多、越补越大,很容易爆仓。建议配合严格的总止损或者只在明确的区间震荡里用。

移动止盈可能过早止损:触发点和距离设太小,价格稍微回调就被扫出来,错过后面的大行情。设太大又起不到保护作用。需要根据品种波动和策略调试。

滑点和成交:市价单在快速行情或流动性差的时候滑点可能比较大,实际成交价和预期有偏差。代码里设了 10 点的偏离容忍(trade.SetDeviationInPoints(10)),超过这个可能下单失败。

手数倍增:加仓倍数 1.5 看着不大,但几次下来手数增长很快。0.01 → 0.015 → 0.023 → 0.035,四次加仓总手数就翻了 3 倍多,保证金占用和单跳盈亏都是指数级上升。

无持仓时间和价格检查:代码只检查盈亏点数,不管仓位开了多久、当前是什么行情。比如开仓后价格剧烈波动来回扫,可能反复触发加仓条件。

常见问题

加仓会自动执行吗?
不会。顺势加仓和逆势加仓都是点按钮手动触发,每次点击会检查所有持仓里符合间距条件的单子一起加仓。
加仓最多能加几次?
代码里虽然有 InpMaxAddTimes 参数,但实际没有限制次数。每次点按钮,所有符合盈亏间距条件的持仓都会加仓,需要自己控制点击次数。
逆势加仓适合什么情况?
适合明确的区间震荡行情,有支撑阻力位、价格来回走的时候。单边趋势行情千万别用,会越补越亏。
移动止盈会重绘吗?
不会重绘。移动止盈是实时修改订单的止损价格,修改后就生效,不会因为价格回调而撤销已经推上去的止损。
这个 EA 能用在 MT4 吗?
不能。代码是 MQL5 写的,用了 MT5 的 CTrade 类和持仓系统,MT4 架构不同无法直接运行。

MT5 Trading Control Panel EA

A draggable trading panel for MT5 with one-click open/close, trend/counter-trend position adding, batch TP/SL modification, trailing stop, and break-even functions. Designed for manual traders who need quick order execution.

Source code is shown above. Compiled EX5 files are available to VIP members.

评论

后可以留言,比如反馈用着怎么样、想加什么功能。

还没有人评论,来抢个沙发。