完美一键设置止盈止损的EA源码发布


//+------------------------------------------------------------------+//| OneClickPanelSLTP.mq4|//| Generated by AutoGen Assistant|//| |//+------------------------------------------------------------------+#property copyright "Your Name"#property link ""#property version "1.80"#property strict// 输入参数(面板外观和位置)input int InpPanelCorner = 0; // 面板角落 (0=左上,1=右上,2=左下,3=右下)input int InpPanelX = 10; // 面板X偏移input int InpPanelY = 50; // 面板Y偏移input int InpPanelWidth = 340; // 面板宽度input int InpPanelHeight = 430; // 面板高度input color InpPanelColor = clrLightGray; // 面板背景色// 对象名称前缀#define PREFIX "OneClickPanel_"#define BTN_APPLY PREFIX + "ApplyBtn"#define BTN_CLEAR PREFIX + "ClearBtn"#define BTN_MODE PREFIX + "ModeBtn" // 模式切换按钮#define ED_SL PREFIX + "EditSL"#define ED_TP PREFIX + "EditTP"#define LBL_SL PREFIX + "LabelSL"#define LBL_TP PREFIX + "LabelTP"#define LBL_TYPE PREFIX + "LabelType"#define LBL_TIME PREFIX + "LabelTime"#define RADIO_TYPE_BUY PREFIX + "RadioTypeBuy"#define RADIO_TYPE_SELL PREFIX + "RadioTypeSell"#define RADIO_TYPE_ALL PREFIX + "RadioTypeAll"#define RADIO_TIME_TODAY PREFIX + "RadioTimeToday"#define RADIO_TIME_ALL PREFIX + "RadioTimeAll"#define RADIO_TIME_CUSTOM PREFIX + "RadioTimeCustom"#define LBL_DATE_START PREFIX + "LabelDateStart"#define ED_DATE_START PREFIX + "EditDateStart"#define LBL_DATE_END PREFIX + "LabelDateEnd"#define ED_DATE_END PREFIX + "EditDateEnd"#define RECT_BG PREFIX + "RectBG"// 全局变量int g_orderType = 0; // 0=所有, 1=仅多单, 2=仅空单int g_timeFilter = 1; // 0=所有订单, 1=仅今天订单, 2=自定义范围bool g_priceMode = false; // true=价格模式, false=点数模式//+------------------------------------------------------------------+//| 专家初始化函数 |//+------------------------------------------------------------------+intOnInit(){// 创建面板背景矩形if(!ObjectCreate(0, RECT_BG, OBJ_RECTANGLE_LABEL, 0, 0, 0))return(INIT_FAILED);ObjectSetInteger(0, RECT_BG, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, RECT_BG, OBJPROP_XDISTANCE, InpPanelX);ObjectSetInteger(0, RECT_BG, OBJPROP_YDISTANCE, InpPanelY);ObjectSetInteger(0, RECT_BG, OBJPROP_XSIZE, InpPanelWidth);ObjectSetInteger(0, RECT_BG, OBJPROP_YSIZE, InpPanelHeight);ObjectSetInteger(0, RECT_BG, OBJPROP_BGCOLOR, InpPanelColor);ObjectSetInteger(0, RECT_BG, OBJPROP_BORDER_COLOR, clrBlack);ObjectSetInteger(0, RECT_BG, OBJPROP_STATE, false);ObjectSetInteger(0, RECT_BG, OBJPROP_SELECTABLE, false);ObjectSetInteger(0, RECT_BG, OBJPROP_HIDDEN, true);// 计算内部布局的参考点int startX = InpPanelX + 15;int startY = InpPanelY + 15;int labelW = 85; // 标签宽度int editW = InpPanelWidth - 115;int rowHeight = 38;int radioRowHeight = 32;int btnHeight = 32;// --- 模式切换按钮(放在止损/止盈上方)---int modeBtnY = startY;ObjectCreate(0, BTN_MODE, OBJ_BUTTON, 0, 0, 0);ObjectSetInteger(0, BTN_MODE, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, BTN_MODE, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, BTN_MODE, OBJPROP_YDISTANCE, modeBtnY);ObjectSetInteger(0, BTN_MODE, OBJPROP_XSIZE, InpPanelWidth - 30);ObjectSetInteger(0, BTN_MODE, OBJPROP_YSIZE, 26);ObjectSetString(0, BTN_MODE, OBJPROP_TEXT, "当前模式: 点数模式 (点击切换)");ObjectSetInteger(0, BTN_MODE, OBJPROP_BGCOLOR, clrLightBlue);ObjectSetInteger(0, BTN_MODE, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, BTN_MODE, OBJPROP_FONTSIZE, 10);ObjectSetInteger(0, BTN_MODE, OBJPROP_HIDDEN, true);ObjectSetInteger(0, BTN_MODE, OBJPROP_SELECTABLE, false);ObjectSetInteger(0, BTN_MODE, OBJPROP_ZORDER, 1);// --- 第1行:止损 ---int slY = modeBtnY + 30;ObjectCreate(0, LBL_SL, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_SL, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_SL, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, LBL_SL, OBJPROP_YDISTANCE, slY);ObjectSetString(0, LBL_SL, OBJPROP_TEXT, "止损点数:");ObjectSetInteger(0, LBL_SL, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, LBL_SL, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_SL, OBJPROP_HIDDEN, true);ObjectCreate(0, ED_SL, OBJ_EDIT, 0, 0, 0);ObjectSetInteger(0, ED_SL, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, ED_SL, OBJPROP_XDISTANCE, startX + labelW);ObjectSetInteger(0, ED_SL, OBJPROP_YDISTANCE, slY - 3);ObjectSetInteger(0, ED_SL, OBJPROP_XSIZE, editW);ObjectSetInteger(0, ED_SL, OBJPROP_YSIZE, 26);ObjectSetString(0, ED_SL, OBJPROP_TEXT, "50");ObjectSetInteger(0, ED_SL, OBJPROP_FONTSIZE, 11);ObjectSetInteger(0, ED_SL, OBJPROP_BGCOLOR, clrWhite);ObjectSetInteger(0, ED_SL, OBJPROP_HIDDEN, true);ObjectSetInteger(0, ED_SL, OBJPROP_READONLY, false);// --- 第2行:止盈 ---int tpY = slY + rowHeight;ObjectCreate(0, LBL_TP, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_TP, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_TP, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, LBL_TP, OBJPROP_YDISTANCE, tpY);ObjectSetString(0, LBL_TP, OBJPROP_TEXT, "止盈点数:");ObjectSetInteger(0, LBL_TP, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, LBL_TP, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_TP, OBJPROP_HIDDEN, true);ObjectCreate(0, ED_TP, OBJ_EDIT, 0, 0, 0);ObjectSetInteger(0, ED_TP, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, ED_TP, OBJPROP_XDISTANCE, startX + labelW);ObjectSetInteger(0, ED_TP, OBJPROP_YDISTANCE, tpY - 3);ObjectSetInteger(0, ED_TP, OBJPROP_XSIZE, editW);ObjectSetInteger(0, ED_TP, OBJPROP_YSIZE, 26);ObjectSetString(0, ED_TP, OBJPROP_TEXT, "100");ObjectSetInteger(0, ED_TP, OBJPROP_FONTSIZE, 11);ObjectSetInteger(0, ED_TP, OBJPROP_BGCOLOR, clrWhite);ObjectSetInteger(0, ED_TP, OBJPROP_HIDDEN, true);ObjectSetInteger(0, ED_TP, OBJPROP_READONLY, false);// --- 第3行:订单类型标签 ---int typeLabelY = tpY + rowHeight + 5;ObjectCreate(0, LBL_TYPE, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_TYPE, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_TYPE, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, LBL_TYPE, OBJPROP_YDISTANCE, typeLabelY);ObjectSetString(0, LBL_TYPE, OBJPROP_TEXT, "订单类型:");ObjectSetInteger(0, LBL_TYPE, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, LBL_TYPE, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_TYPE, OBJPROP_HIDDEN, true);int radioTypeY = typeLabelY + 23;CreateRadioButton(RADIO_TYPE_BUY, "多单", startX, radioTypeY, false);CreateRadioButton(RADIO_TYPE_SELL, "空单", startX + 85, radioTypeY, false);CreateRadioButton(RADIO_TYPE_ALL, "所有", startX + 170, radioTypeY, true);// --- 第4行:订单时间标签 ---int timeLabelY = radioTypeY + radioRowHeight + 10;ObjectCreate(0, LBL_TIME, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_TIME, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_TIME, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, LBL_TIME, OBJPROP_YDISTANCE, timeLabelY);ObjectSetString(0, LBL_TIME, OBJPROP_TEXT, "订单时间:");ObjectSetInteger(0, LBL_TIME, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, LBL_TIME, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_TIME, OBJPROP_HIDDEN, true);int radioTimeY = timeLabelY + 23;CreateRadioButton(RADIO_TIME_TODAY, "今天", startX, radioTimeY, true);CreateRadioButton(RADIO_TIME_ALL, "所有", startX + 85, radioTimeY, false);CreateRadioButton(RADIO_TIME_CUSTOM, "自定义", startX + 170, radioTimeY, false);// --- 自定义日期输入框区域 ---int dateY = radioTimeY + radioRowHeight + 10;ObjectCreate(0, LBL_DATE_START, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_YDISTANCE, dateY);ObjectSetString(0, LBL_DATE_START, OBJPROP_TEXT, "起始日期:");ObjectSetInteger(0, LBL_DATE_START, OBJPROP_FONTSIZE, 10);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_HIDDEN, true);ObjectCreate(0, ED_DATE_START, OBJ_EDIT, 0, 0, 0);ObjectSetInteger(0, ED_DATE_START, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, ED_DATE_START, OBJPROP_XDISTANCE, startX + 70);ObjectSetInteger(0, ED_DATE_START, OBJPROP_YDISTANCE, dateY - 2);ObjectSetInteger(0, ED_DATE_START, OBJPROP_XSIZE, 110);ObjectSetInteger(0, ED_DATE_START, OBJPROP_YSIZE, 24);ObjectSetString(0, ED_DATE_START, OBJPROP_TEXT, TimeToString(TimeCurrent(), TIME_DATE));ObjectSetInteger(0, ED_DATE_START, OBJPROP_FONTSIZE, 10);ObjectSetInteger(0, ED_DATE_START, OBJPROP_BGCOLOR, clrWhite);ObjectSetInteger(0, ED_DATE_START, OBJPROP_HIDDEN, true);ObjectSetInteger(0, ED_DATE_START, OBJPROP_READONLY, false);ObjectCreate(0, LBL_DATE_END, OBJ_LABEL, 0, 0, 0);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_XDISTANCE, startX + 190);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_YDISTANCE, dateY);ObjectSetString(0, LBL_DATE_END, OBJPROP_TEXT, "结束日期:");ObjectSetInteger(0, LBL_DATE_END, OBJPROP_FONTSIZE, 10);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_HIDDEN, true);ObjectCreate(0, ED_DATE_END, OBJ_EDIT, 0, 0, 0);ObjectSetInteger(0, ED_DATE_END, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, ED_DATE_END, OBJPROP_XDISTANCE, startX + 260);ObjectSetInteger(0, ED_DATE_END, OBJPROP_YDISTANCE, dateY - 2);ObjectSetInteger(0, ED_DATE_END, OBJPROP_XSIZE, 110);ObjectSetInteger(0, ED_DATE_END, OBJPROP_YSIZE, 24);ObjectSetString(0, ED_DATE_END, OBJPROP_TEXT, TimeToString(TimeCurrent(), TIME_DATE));ObjectSetInteger(0, ED_DATE_END, OBJPROP_FONTSIZE, 10);ObjectSetInteger(0, ED_DATE_END, OBJPROP_BGCOLOR, clrWhite);ObjectSetInteger(0, ED_DATE_END, OBJPROP_HIDDEN, true);ObjectSetInteger(0, ED_DATE_END, OBJPROP_READONLY, false);// --- 应用按钮 ---int btnY1 = InpPanelY + InpPanelHeight - 90;ObjectCreate(0, BTN_APPLY, OBJ_BUTTON, 0, 0, 0);ObjectSetInteger(0, BTN_APPLY, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, BTN_APPLY, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, BTN_APPLY, OBJPROP_YDISTANCE, btnY1);ObjectSetInteger(0, BTN_APPLY, OBJPROP_XSIZE, InpPanelWidth - 30);ObjectSetInteger(0, BTN_APPLY, OBJPROP_YSIZE, btnHeight);ObjectSetString(0, BTN_APPLY, OBJPROP_TEXT, "设置止盈止损");ObjectSetInteger(0, BTN_APPLY, OBJPROP_BGCOLOR, clrDodgerBlue);ObjectSetInteger(0, BTN_APPLY, OBJPROP_COLOR, clrWhite);ObjectSetInteger(0, BTN_APPLY, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, BTN_APPLY, OBJPROP_HIDDEN, true);ObjectSetInteger(0, BTN_APPLY, OBJPROP_SELECTABLE, false);ObjectSetInteger(0, BTN_APPLY, OBJPROP_ZORDER, 1);// --- 清除按钮 ---int btnY2 = InpPanelY + InpPanelHeight - 50;ObjectCreate(0, BTN_CLEAR, OBJ_BUTTON, 0, 0, 0);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_XDISTANCE, startX);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_YDISTANCE, btnY2);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_XSIZE, InpPanelWidth - 30);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_YSIZE, btnHeight);ObjectSetString(0, BTN_CLEAR, OBJPROP_TEXT, "清除止盈止损");ObjectSetInteger(0, BTN_CLEAR, OBJPROP_BGCOLOR, clrOrangeRed);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_COLOR, clrWhite);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_FONTSIZE, 12);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_HIDDEN, true);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_SELECTABLE, false);ObjectSetInteger(0, BTN_CLEAR, OBJPROP_ZORDER, 1);// 初始根据时间筛选模式控制日期输入框的可见性UpdateDateInputsState();// 根据模式更新标签文字UpdateModeUI();Print("一键设置面板EA已启动,支持点数/价格模式切换。价格模式下完全按输入值设置,不做自动修正。");return(INIT_SUCCEEDED);}//+------------------------------------------------------------------+//| 创建单选按钮 |//+------------------------------------------------------------------+voidCreateRadioButton(string name, string text, int x, int y, bool selected){ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);ObjectSetInteger(0, name, OBJPROP_CORNER, InpPanelCorner);ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);ObjectSetInteger(0, name, OBJPROP_XSIZE, 70);ObjectSetInteger(0, name, OBJPROP_YSIZE, 28);ObjectSetString(0, name, OBJPROP_TEXT, text);ObjectSetInteger(0, name, OBJPROP_BGCOLOR, selected ? clrLightBlue : clrLightGray);ObjectSetInteger(0, name, OBJPROP_COLOR, clrBlack);ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 11);ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);ObjectSetInteger(0, name, OBJPROP_STATE, selected);ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);}//+------------------------------------------------------------------+//| 根据当前模式更新界面文本 |//+------------------------------------------------------------------+voidUpdateModeUI(){string modeText = g_priceMode ? "当前模式: 价格模式 (点击切换)" : "当前模式: 点数模式 (点击切换)";ObjectSetString(0, BTN_MODE, OBJPROP_TEXT, modeText);string slLabel = g_priceMode ? "止损价格:" : "止损点数:";string tpLabel = g_priceMode ? "止盈价格:" : "止盈点数:";ObjectSetString(0, LBL_SL, OBJPROP_TEXT, slLabel);ObjectSetString(0, LBL_TP, OBJPROP_TEXT, tpLabel);ChartRedraw(0);}//+------------------------------------------------------------------+//| 根据当前时间筛选模式,控制日期输入框的显示 |//+------------------------------------------------------------------+voidUpdateDateInputsState(){bool visible = (g_timeFilter == 2);ObjectSetInteger(0, LBL_DATE_START, OBJPROP_HIDDEN, !visible);ObjectSetInteger(0, ED_DATE_START, OBJPROP_HIDDEN, !visible);ObjectSetInteger(0, LBL_DATE_END, OBJPROP_HIDDEN, !visible);ObjectSetInteger(0, ED_DATE_END, OBJPROP_HIDDEN, !visible);ChartRedraw(0);}//+------------------------------------------------------------------+//| 专家反初始化函数 |//+------------------------------------------------------------------+voidOnDeinit(constint reason){// 删除所有创建的对象string objects[] = {RECT_BG, BTN_MODE, LBL_SL, ED_SL, LBL_TP, ED_TP, LBL_TYPE, LBL_TIME,RADIO_TYPE_BUY, RADIO_TYPE_SELL, RADIO_TYPE_ALL,RADIO_TIME_TODAY, RADIO_TIME_ALL, RADIO_TIME_CUSTOM,LBL_DATE_START, ED_DATE_START, LBL_DATE_END, ED_DATE_END,BTN_APPLY, BTN_CLEAR};for(int i=0; i<ArraySize(objects); i++)ObjectDelete(0, objects[i]);Print("EA已卸载,面板已清除");}//+------------------------------------------------------------------+//| 图表事件处理 |//+------------------------------------------------------------------+voidOnChartEvent(constint id,const long &lparam,const double &dparam,const string &sparam){if(id == CHARTEVENT_OBJECT_CLICK){// 模式切换按钮if(sparam == BTN_MODE){g_priceMode = !g_priceMode;UpdateModeUI();Print("模式切换为: ", g_priceMode ? "价格模式 (完全按输入值设置)" : "点数模式 (自动调整最小距离)");}// 应用按钮else if(sparam == BTN_APPLY){Print("设置按钮被点击");ApplySettings();}// 清除按钮else if(sparam == BTN_CLEAR){Print("清除按钮被点击");ClearSLTP();}// 订单类型单选else if(sparam == RADIO_TYPE_BUY){SetRadioState(RADIO_TYPE_BUY, true);SetRadioState(RADIO_TYPE_SELL, false);SetRadioState(RADIO_TYPE_ALL, false);g_orderType = 1;}else if(sparam == RADIO_TYPE_SELL){SetRadioState(RADIO_TYPE_BUY, false);SetRadioState(RADIO_TYPE_SELL, true);SetRadioState(RADIO_TYPE_ALL, false);g_orderType = 2;}else if(sparam == RADIO_TYPE_ALL){SetRadioState(RADIO_TYPE_BUY, false);SetRadioState(RADIO_TYPE_SELL, false);SetRadioState(RADIO_TYPE_ALL, true);g_orderType = 0;}// 时间筛选单选else if(sparam == RADIO_TIME_TODAY){SetRadioState(RADIO_TIME_TODAY, true);SetRadioState(RADIO_TIME_ALL, false);SetRadioState(RADIO_TIME_CUSTOM, false);g_timeFilter = 1;UpdateDateInputsState();}else if(sparam == RADIO_TIME_ALL){SetRadioState(RADIO_TIME_TODAY, false);SetRadioState(RADIO_TIME_ALL, true);SetRadioState(RADIO_TIME_CUSTOM, false);g_timeFilter = 0;UpdateDateInputsState();}else if(sparam == RADIO_TIME_CUSTOM){SetRadioState(RADIO_TIME_TODAY, false);SetRadioState(RADIO_TIME_ALL, false);SetRadioState(RADIO_TIME_CUSTOM, true);g_timeFilter = 2;UpdateDateInputsState();}}}//+------------------------------------------------------------------+//| 设置单选按钮的选中状态 |//+------------------------------------------------------------------+voidSetRadioState(string name, bool state){ObjectSetInteger(0, name, OBJPROP_STATE, state);if(state)ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clrLightBlue);elseObjectSetInteger(0, name, OBJPROP_BGCOLOR, clrLightGray);ChartRedraw(0);}//+------------------------------------------------------------------+//| 获取当前时间筛选的起始和结束时间 |//+------------------------------------------------------------------+boolGetTimeRange(datetime &startTime, datetime &endTime){if(g_timeFilter == 0) // 所有{startTime = 0;endTime = D'01.01.3000';return true;}else if(g_timeFilter == 1) // 今天{datetime now = TimeCurrent();startTime = StringToTime(TimeToString(now, TIME_DATE));endTime = startTime + 24*3600 - 1;return true;}else // 自定义{string startStr = ObjectGetString(0, ED_DATE_START, OBJPROP_TEXT);string endStr = ObjectGetString(0, ED_DATE_END, OBJPROP_TEXT);startTime = ParseDate(startStr);endTime = ParseDate(endStr);if(startTime == 0 || endTime == 0){Print("日期解析失败,请使用格式 YYYY.MM.DD 或 YYYY-MM-DD");return false;}endTime = endTime + 24*3600 - 1;return true;}}//+------------------------------------------------------------------+//| 简单日期解析,返回0表示失败 |//+------------------------------------------------------------------+datetime ParseDate(string dateStr){StringTrimLeft(dateStr);StringTrimRight(dateStr);if(StringLen(dateStr) == 0) return 0;StringReplace(dateStr, "-", ".");if(StringLen(dateStr) == 10 && StringGetChar(dateStr,4) == '.' && StringGetChar(dateStr,7) == '.'){string timeStr = dateStr + " 00:00";return StringToTime(timeStr);}return 0;}//+------------------------------------------------------------------+//| 检查订单时间是否在范围内 |//+------------------------------------------------------------------+boolIsOrderInRange(datetime openTime){datetime start, end;if(!GetTimeRange(start, end)) return false;return (openTime >= start && openTime <= end);}//+------------------------------------------------------------------+//| 根据模式获取止损和止盈的目标值 |//| 价格模式:直接返回输入的价格 |//| 点数模式:返回计算后的价格,并进行最小距离检查 |//+------------------------------------------------------------------+boolGetSLTPValues(int orderType, double &slValue, double &tpValue, string &errorMsg){string slText = ObjectGetString(0, ED_SL, OBJPROP_TEXT);string tpText = ObjectGetString(0, ED_TP, OBJPROP_TEXT);if(g_priceMode){// 价格模式:直接读取价格,不做任何自动调整slValue = StringToDouble(slText);tpValue = StringToDouble(tpText);if(slValue == 0 && slText != "0"){errorMsg = "止损价格无效";return false;}if(tpValue == 0 && tpText != "0"){errorMsg = "止盈价格无效";return false;}return true;}else{// 点数模式:读取点数,转换为价格,并进行最小距离检查(后续在调用处处理)int slPoints = (int)StringToInteger(slText);int tpPoints = (int)StringToInteger(tpText);if(slPoints <= 0 && slPoints != 0){errorMsg = "止损点数无效";return false;}if(tpPoints <= 0 && tpPoints != 0){errorMsg = "止盈点数无效";return false;}if(slPoints > 0){if(orderType == OP_BUY)slValue = Bid - slPoints * Point;elseslValue = Ask + slPoints * Point;}elseslValue = 0;if(tpPoints > 0){if(orderType == OP_BUY)tpValue = Bid + tpPoints * Point;elsetpValue = Ask - tpPoints * Point;}elsetpValue = 0;return true;}}//+------------------------------------------------------------------+//| 遍历符合条件的订单并执行操作 |//+------------------------------------------------------------------+voidProcessOrders(bool setSLTP, int dummySL, int dummyTP) // 参数为占位,实际值通过GetSLTPValues获取{int total = OrdersTotal();int modified = 0;int errors = 0;for(int i = total-1; i >= 0; i--){if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){// 只处理当前品种的订单if(OrderSymbol() != Symbol())continue;// 时间筛选if(g_timeFilter != 0 && !IsOrderInRange(OrderOpenTime()))continue;int orderType = OrderType();if(orderType == OP_BUY && g_orderType == 2) continue;if(orderType == OP_SELL && g_orderType == 1) continue;if(orderType != OP_BUY && orderType != OP_SELL) continue;double openPrice = OrderOpenPrice();double newSL = OrderStopLoss();double newTP = OrderTakeProfit();bool modify = false;if(setSLTP){double slValue = 0, tpValue = 0;string errorMsg;if(!GetSLTPValues(orderType, slValue, tpValue, errorMsg)){Print("获取止损/止盈数值失败: ", errorMsg);continue;}// 处理止损if(slValue != 0){newSL = slValue;// 仅在点数模式下进行最小距离自动修正,价格模式下不修正,完全按用户输入if(!g_priceMode){double minDist = MarketInfo(OrderSymbol(), MODE_STOPLEVEL) * Point;if(orderType == OP_BUY && newSL > 0 && newSL > openPrice - minDist)newSL = openPrice - minDist;if(orderType == OP_SELL && newSL > 0 && newSL < openPrice + minDist)newSL = openPrice + minDist;}if(newSL != OrderStopLoss())modify = true;}// 处理止盈if(tpValue != 0){newTP = tpValue;if(!g_priceMode){double minDist = MarketInfo(OrderSymbol(), MODE_STOPLEVEL) * Point;if(orderType == OP_BUY && newTP > 0 && newTP < openPrice + minDist)newTP = openPrice + minDist;if(orderType == OP_SELL && newTP > 0 && newTP > openPrice - minDist)newTP = openPrice - minDist;}if(newTP != OrderTakeProfit())modify = true;}}else{// 清除模式if(OrderStopLoss() != 0 || OrderTakeProfit() != 0){newSL = 0;newTP = 0;modify = true;}}if(modify){if(OrderModify(OrderTicket(), openPrice, newSL, newTP, 0, clrNONE)){modified++;if(setSLTP)Print("订单 ", OrderTicket(), " 修改成功。 SL=", newSL, " TP=", newTP);elsePrint("订单 ", OrderTicket(), " 止盈止损已清除");}else{errors++;Print("订单 ", OrderTicket(), " 修改失败,错误: ", GetLastError());}}}}if(setSLTP)Print("设置操作完成,成功: ", modified, " 失败: ", errors);elsePrint("清除操作完成,成功: ", modified, " 失败: ", errors);}//+------------------------------------------------------------------+//| 应用设置 |//+------------------------------------------------------------------+voidApplySettings(){// 验证输入框内容非空string slText = ObjectGetString(0, ED_SL, OBJPROP_TEXT);string tpText = ObjectGetString(0, ED_TP, OBJPROP_TEXT);if(StringLen(slText) == 0 || StringLen(tpText) == 0){Print("止损或止盈输入为空");return;}// 在点数模式下,检查是否都是数字if(!g_priceMode){int slPoints = (int)StringToInteger(slText);int tpPoints = (int)StringToInteger(tpText);if(slPoints == 0 && slPoints != 0){Print("止损点数无效: ", slText);return;}if(tpPoints == 0 && tpPoints != 0){Print("止盈点数无效: ", tpText);return;}if(slPoints == 0 && tpPoints == 0){Print("止损和止盈点数均为0,无需操作");return;}}else{// 价格模式下,检查是否为有效数字double slPrice = StringToDouble(slText);double tpPrice = StringToDouble(tpText);if(slPrice == 0 && slText != "0"){Print("止损价格无效: ", slText);return;}if(tpPrice == 0 && tpText != "0"){Print("止盈价格无效: ", tpText);return;}if(slPrice == 0 && tpPrice == 0){Print("止损和止盈价格均为0,无需操作");return;}}ProcessOrders(true, 0, 0);}//+------------------------------------------------------------------+//| 清除止盈止损 |//+------------------------------------------------------------------+voidClearSLTP(){ProcessOrders(false, 0, 0);}//+------------------------------------------------------------------+
夜雨聆风