
اصلاح و Modify سفارشات در MQL: راهنمای جامع برنامهنویسی الگوریتمی
در دنیای معاملهگری الگوریتمی (Algorithmic Trading) با استفاده از زبانهای برنامهنویسی MQL4 و MQL5، توانایی مدیریت و اصلاح سفارش (Order Modification) یکی از حیاتیترین مهارتهایی است که هر برنامهنویسی باید به طور کامل بر آن مسلط باشد. سفارشها، چه سفارشات در حال انتظار (Pending Orders) و چه سفارشات باز (Open Positions)، اغلب نیاز به تنظیم مجدد پارامترهایی مانند حد ضرر (Stop Loss – SL)، حد سود (Take Profit – TP) یا حتی زمان انقضا دارند. این عملیات نه تنها برای مدیریت ریسک (Risk Management) در لحظه ضروری است، بلکه قلب تپنده استراتژیهای پیشرفتهای مانند تریلینگ استاپ (Trailing Stop) و بریک ایون (Break Even) محسوب میشود. عدم درک صحیح از چگونگی اصلاح سفارش میتواند منجر به خطاهای عملکردی، سوء مدیریت سرمایه و در نهایت، زیانهای ناخواسته شود. این مقاله با نگاهی عمیق و تخصصی، به بررسی جزئیات فنی اصلاح سفارش در محیطهای MetaTrader 4 و MetaTrader 5 میپردازد و تفاوتهای بنیادین آنها را روشن میسازد.
تفاوتهای بنیادین در پارادایمهای MQL4 و MQL5 برای مدیریت سفارشات
پیش از ورود به جزئیات فنی اصلاح سفارش، درک تفاوت اساسی در نحوه مدیریت سفارشات در MQL4 و MQL5 امری ضروری است. MQL4 به عنوان نسل قدیمیتر پلتفرم MetaTrader 4، از سیستمی مبتنی بر Handle یا Ticket سفارشها برای شناسایی و مدیریت معاملات استفاده میکند. هر سفارشی که در MQL4 ارسال میشود، یک Ticket منحصربهفرد دریافت میکند که هویت آن معامله را در طول عمرش حفظ میکند. عملیات اصلاح سفارش در MQL4 عمدتاً از طریق تابع OrderModify() انجام میپذیرد. این تابع مستقیماً با Ticket سفارش کار کرده و امکان تغییر SL، TP و Magic Number را فراهم میکند.
در مقابل، MQL5 با معرفی سیستم معاملاتی OrderSend() و ساختار دادهای MqlTradeRequest و MqlTradeResult، رویکردی شیءگرا و جامعتر را اتخاذ کرده است. در MQL5، هر معامله نه تنها یک Position، بلکه یک Ticket نیز دارد، اما نحوه تعامل با آنها متفاوت است. MQL5 از ساختار Trade Transaction برای اجرای عملیات استفاده میکند و عملیات اصلاح سفارش اغلب با استفاده از ساختار MqlTradeRequest انجام میشود که باید حاوی تمام پارامترهای مورد نظر برای تغییر باشد. این تغییر پارادایم به MQL5 اجازه میدهد تا مدیریت معاملات پیچیدهتری، از جمله مدیریت پوزیشنهای چندگانه (Multiple Positions) برای یک نماد معاملاتی (برخلاف MQL4 که معمولاً فقط یک پوزیشن فعال برای هر نماد را پشتیبانی میکرد)، را به شکلی کارآمدتر انجام دهد. درک این تفاوتها برای توسعهدهندگان که قصد مهاجرت یا توسعه همزمان برای هر دو پلتفرم را دارند، حیاتی است.
مکانیزم اصلاح سفارشات در MQL4: تمرکز بر OrderModify()
در MQL4، تابع اصلی برای اصلاح سفارش، تابع OrderModify() است. این تابع برای تغییر پارامترهای یک سفارش باز (پوزیشن) یا یک سفارش در حال انتظار استفاده میشود. ساختار اصلی این تابع به شرح زیر است:
bool OrderModify(
long ticket, // شماره تیکت سفارش برای اصلاح
double new_price, // قیمت جدید (برای سفارش در حال انتظار) یا قیمت فعلی (بدون تغییر)
double new_stoploss, // حد ضرر جدید
double new_takeprofit, // حد سود جدید
datetime expiration, // زمان انقضا (فقط برای سفارشات در حال انتظار)
color arrow_color // رنگ فلش در نمودار (اغلب به عنوان 0 استفاده میشود)
);
برای اصلاح سفارشات باز (Open Positions)، پارامتر new_price معمولاً باید با قیمت فعلی سفارش یکسان باشد، مگر اینکه قصد بستن معامله (Closing Trade) را داشته باشیم که البته این کار به طور مستقیم با OrderModify() انجام نمیشود (برای بستن از OrderClose() استفاده میشود). تمرکز اصلی OrderModify() بر تنظیم دقیق SL و TP است.
اصلاح SL و TP در MQL4
فرض کنید یک پوزیشن خرید (Buy) باز داریم و میخواهیم حد ضرر آن را به سطحی بالاتر منتقل کنیم تا ریسک را کاهش دهیم یا حد سود را تنظیم کنیم. اولین گام یافتن Ticket صحیح است. پس از یافتن، باید اطمینان حاصل کنیم که پارامترهای جدید با قوانین بروکر مطابقت دارند؛ به ویژه، فاصله SL و TP از قیمت فعلی بازار (Current Market Price) باید حداقل به اندازه حداقل فاصله مجاز (Minimum Distance) یا Stop Level باشد.
مثال کد برای انتقال SL به نقطه بریک ایون (با فرض اینکه اندکی فاصله امنی نیز در نظر گرفته شود):
void ModifySLtoBreakEven(long ticket_to_modify)
{
// 1. دریافت اطلاعات فعلی سفارش
if (OrderSelect(ticket_to_modify, SELECT_BY_TICKET, MODE_TRADES))
{
double open_price = OrderOpenPrice();
double current_sl = OrderStopLoss();
double current_tp = OrderTakeProfit();
int type = OrderType();
double new_sl = 0.0;
double price_to_use = OrderClosePrice(); // قیمت فعلی برای حفظ باقی پارامترها
// محاسبات بر اساس نوع سفارش (Buy یا Sell)
if (type == OP_BUY)
{
// محاسبه سطح بریک ایون + مقداری اسپرد/کمیسیون برای اطمینان
// فرض می کنیم 10 پیپ (یا 100 نقطه در متاتریدر 5 رقمی) برای اطمینان در نظر گرفته می شود.
new_sl = NormalizeDouble(open_price + (SymbolInfoDouble(_Symbol, SYMBOL_POINT) * 100), _Digits);
// اطمینان از اینکه SL جدید بالاتر از SL فعلی است (در صورت نیاز به افزایش حمایت)
if (new_sl > current_sl || current_sl == 0)
{
if (OrderModify(ticket_to_modify, price_to_use, new_sl, current_tp, 0, clrBlue))
{
Print("سفارش ", ticket_to_modify, " با موفقیت به SL بریک ایون منتقل شد.");
}
else
{
Print("خطا در OrderModify برای تیکت ", ticket_to_modify, ". خطا: ", GetLastError());
}
}
}
// منطق مشابه برای OP_SELL...
}
}
مدیریت خطایابی در OrderModify()
مهمترین نکته در MQL4، مدیریت خطای 130 (Invalid Stops) است. این خطا زمانی رخ میدهد که حد ضرر یا حد سود جدید در فاصله غیرمجاز از قیمت فعلی (که برای سفارشات باز، قیمت پیشنهاد/تقاضا است) قرار گیرد. برای جلوگیری از این امر، باید همیشه از مقادیر صحیح Stop Level و Digits استفاده کنیم. استفاده از توابع NormalizeDouble() برای گرد کردن قیمتها به تعداد اعشار صحیح بروکر، و SymbolInfoDouble(_Symbol, SYMBOL_POINT) برای تعیین اندازه یک نقطه (Point)، حیاتی است. همچنین، تغییر همزمان SL و TP در یک تماس OrderModify() ممکن است در برخی شرایط خاص باعث شکست شود؛ گاهی اوقات توصیه میشود این کار را در دو مرحله مجزا یا با ارسال مجدد یکی از پارامترهای قدیمی انجام دهید.
ساختار اصلاح سفارشات در MQL5: قدرت MqlTradeRequest
MQL5 با تمرکز بر تراکنشها و انعطافپذیری بیشتر، عملیات اصلاح سفارش را به شیوهای ساختاریافتهتر انجام میدهد. در MQL5، ما از توابع PositionModify() یا ارسال مجدد درخواست با استفاده از Trade.TradeRequest استفاده میکنیم. تفاوت کلیدی این است که در MQL5، شما اغلب کل ساختار درخواست (Request Structure) را با مقادیر جدید پر میکنید و سپس آن را ارسال میکنید.
استفاده از PositionModify() برای پوزیشنهای باز
برای پوزیشنهای باز در MQL5، تابع PositionModify() ابزار مستقیمتری است:
bool PositionModify(
ulong position_ticket, // تیکت پوزیشن
double new_stoploss, // حد ضرر جدید
double new_takeprofit // حد سود جدید
);
توجه کنید که PositionModify() فقط برای تنظیم SL و TP پوزیشنهای باز استفاده میشود و انعطاف کمتری در تغییر قیمت ورود (که در MQL5 معمولاً نیازمند بستن و باز کردن مجدد است) دارد.
مثال کد MQL5 برای انتقال SL به بریک ایون یک پوزیشن:
#include <MQL5/Trade/Trade.mqh>
CTrade trade; // نمونه سازی از کلاس CTrade
void ModifyPositionSL(ulong ticket_to_modify)
{
// 1. دریافت اطلاعات پوزیشن
ulong position_handle = PositionGetTicket(ticket_to_modify);
if (position_handle == 0)
{
Print("پوزیشن با تیکت ", ticket_to_modify, " یافت نشد.");
return;
}
double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double new_sl = 0.0;
// محاسبه سطح بریک ایون (با در نظر گرفتن StopLevel و Point)
double point_size = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_STOP_LEVEL);
if (type == POSITION_TYPE_BUY)
{
// محاسبه SL جدید: قیمت ورود + (حداقل فاصله مجاز از قیمت فعلی)
// در اینجا برای سادگی، از یک فاصله ایمن استفاده می کنیم.
new_sl = NormalizeDouble(open_price + stop_level * point_size * 2, _Digits);
// اطمینان از اینکه SL جدید معتبر است
if (new_sl > PositionGetDouble(POSITION_SL))
{
if (trade.PositionModify(ticket_to_modify, new_sl, PositionGetDouble(POSITION_TP)))
{
Print("پوزیشن ", ticket_to_modify, " با موفقیت به SL جدید تنظیم شد.");
}
else
{
Print("خطا در PositionModify: ", trade.ResultRetcode(), " - ", trade.ResultComment());
}
}
}
// منطق مشابه برای POSITION_TYPE_SELL...
}
اصلاح سفارشات در انتظار (Pending Orders) در MQL5
برای سفارشات در حال انتظار (Pending Orders) در MQL5، ما از ساختار MqlTradeRequest و تابع عمومی OrderSend() استفاده میکنیم، مشابه زمان ارسال اولیه سفارش.
MqlTradeRequest request;
MqlTradeResult result;
// پر کردن ساختار درخواست
request.action = TRADE_ACTION_MODIFY; // عملیات اصلاح
request.order = pending_ticket; // تیکت سفارش در حال انتظار
request.symbol = _Symbol;
request.price = new_limit_price; // قیمت جدید حد (برای مثال)
request.sl = new_sl;
request.tp = new_tp;
request.type_filling = ORDER_FILLING_IOC; // یا روش پر شدن مورد نظر
// ارسال درخواست اصلاح
if (!OrderSend(request, result))
{
// مدیریت خطا
}
در این حالت، TRADE_ACTION_MODIFY مشخص میکند که هدف ما تغییر پارامترهای سفارش موجود است. این روش برای Pending Orders بسیار انعطافپذیر است و امکان تغییر Limit Price یا Stop Price را فراهم میکند.
پارامترهای حیاتی در اصلاح سفارشات: عمق فنی
عملیات اصلاح سفارش فراتر از صرفاً جابجایی SL و TP است. درک دقیق پارامترهایی که میتوانند تحت تأثیر قرار گیرند، مزیت رقابتی بزرگی در برنامهنویسی الگوریتمی فراهم میکند.
قیمت اصلاح (Modification Price)
هنگامی که یک سفارش باز (Position) را اصلاح میکنید، پارامتری که به عنوان قیمت ورودی تعیین میشود (در MQL4 به عنوان new_price یا در MQL5 از طریق بازنویسی ساختار) اغلب نادیده گرفته میشود مگر اینکه در حال تغییر یک سفارش در حال انتظار باشید. برای Position، قیمت اصلاح باید به گونهای تنظیم شود که نشان دهد شما صرفاً پارامترهای SL/TP را تغییر میدهید و نه قیمت ورود. در MQL4، ارسال قیمت باز شدن اصلی سفارش در new_price بهترین روش است. در MQL5، استفاده از PositionModify() این پیچیدگی را از بین میبرد زیرا فقط SL و TP را هدف قرار میدهد.
حد ضرر (Stop Loss) و حد سود (Take Profit)
این دو پارامتر، اجزای اصلی اصلاح سفارش هستند. برای اجرای موفقیتآمیز، باید فاصله این پارامترها از قیمت بازار فعلی (Bid برای Sell و Ask برای Buy) همواره از Stop Level (حداقل فاصله مجاز) بیشتر باشد. Stop Level در MQL5 از طریق SymbolInfoInteger(_Symbol, SYMBOL_STOP_LEVEL) و در MQL4 به صورت ضمنی یا با استفاده از توابع خاصی قابل دسترسی است. نادیده گرفتن این قانون، منجر به خطای Invalid Stops خواهد شد.
زمان انقضا (Expiration Time)
تنها در سفارشات در حال انتظار (Pending Orders) مانند Buy Limit، Sell Limit، Buy Stop و Sell Stop، پارامتر Expiration معنیدار است. این پارامتر که به صورت Timestamp (زمان یونیکس) در تابع OrderModify() (MQL4) یا در ساختار MqlTradeRequest (MQL5) وارد میشود، مشخص میکند که در صورت عدم اجرا تا چه زمانی سفارش باید فعال بماند. اگر زمان انقضا صفر (یا یک تاریخ بسیار قدیمی) تنظیم شود، سفارش به صورت نامحدود باقی میماند.
نقش اصلاح سفارش در استراتژیهای پیشرفته معاملاتی
اصلاح سفارش ستون فقرات اجرای استراتژیهای مدیریت پوزیشن فعال (Active Position Management) است. یک ربات معاملهگر (EA) موفق، تنها سفارش ارسال نمیکند؛ بلکه دائماً وضعیت بازار را رصد کرده و سفارشات خود را بهروزرسانی میکند.
پیادهسازی تریلینگ استاپ (Trailing Stop)
تریلینگ استاپ یک مکانیسم پویا است که حد ضرر را به صورت خودکار با حرکت سودآور بازار، جابجا میکند تا سود کسب شده را قفل کند. در MQL4 و MQL5، این عملیات نیازمند یک حلقه تکرار (معمولاً در تابع OnTick()) است که پیوسته وضعیت پوزیشن را چک کرده و در صورت تحقق شرایط تریل، OrderModify() یا PositionModify() را فراخوانی کند.
برای مثال، در یک پوزیشن Buy، هرگاه قیمت بازار از SL فعلی، مقداری بیشتر حرکت کرد (مثلاً به اندازه TrailingStep)، SL باید به اندازه TrailingStep بالاتر از قیمت جدید بازار منتقل شود.
[ \text{New SL} = \text{Current Market Price} – (\text{Trailing Step} \times \text{Point Size}) ]
نکته بهینهسازی: برای جلوگیری از ارسال Requestهای متعدد و غیرضروری به سرور بروکر (که منجر به کاهش عملکرد و احتمال رد شدن درخواستها به دلیل حجم بالا میشود)، باید یک مکانیزم Cooldown یا Check Last Modified Time پیادهسازی شود. بهینهترین حالت این است که تنها زمانی OrderModify() فراخوانی شود که SL جدید واقعاً با SL قبلی تفاوت معناداری داشته باشد (مثلاً به اندازه حداقل یک Tick Size یا بیشتر) و یا حداقل برای مدتی مشخص (مثلاً 5 ثانیه) هیچ Modify دیگری انجام نشده باشد.
انتقال به بریک ایون (Break Even)
انتقال حد ضرر به نقطه ورود (Open Price) یا کمی بالاتر از آن، استراتژی کلاسیک مدیریت ریسک صفر است. همانطور که در مثالهای کد ذکر شد، پس از رسیدن پوزیشن به سود مشخصی (که معمولاً شامل پوشش اسپرد و کمیسیون میشود)، SL باید به سطحی تنظیم شود که اگر بازار برگشت، معامله بدون ضرر بسته شود. در MQL5، به دلیل مدیریت بهتر Positionها، این کار شفافتر است.
اصلاح قیمتهای محدود (Limit Price Adjustments)
در استراتژیهای Arbitrage یا Mean Reversion، ممکن است نیاز باشد سفارشات در حال انتظار را با توجه به نوسانات قیمتی کوچک یا تغییرات در سطوح حمایتی/مقاومتی، تنظیم کنیم. در این حالت، در MQL4 از OrderModify() برای تغییر new_price (قیمت فعالسازی) و در MQL5 از TRADE_ACTION_MODIFY استفاده میشود. دقت در محاسبات قیمت فعالسازی در MQL5 بسیار مهم است زیرا MQL5 نسبت به MQL4 در تفسیر قیمتهای غیرمعمول سختگیرانهتر است.
ملاحظات پیشرفته: اسپرد، اسلیپیج و نرخ اصلاح
اصلاح سفارش در بازارهای پرنوسان میتواند با چالشهایی روبرو شود که مستقیماً بر موفقیت عملیات تأثیر میگذارند.
تأثیر اسپرد بر اصلاح
هنگامی که در حال تنظیم حد ضرر یا حد سود هستید، همیشه باید اسپرد (Spread) فعلی را در محاسبات خود لحاظ کنید.
- حداقل فاصله SL/TP از قیمت فعلی: اگر قیمت بازار در زمان فراخوانی OrderModify() تغییر کند یا اسپرد به طور ناگهانی افزایش یابد، SL که محاسبات آن بر اساس اسپرد لحظه ارسال سفارش انجام شده بود، ممکن است اکنون در محدوده غیرمجاز قرار گیرد و باعث رد شدن درخواست شود.
- محاسبات بریک ایون: همانطور که در مثالها نشان داده شد، بریک ایون واقعی باید بالاتر از قیمت ورود (Buy) یا پایینتر از قیمت ورود (Sell) باشد، به اندازهای که نه تنها اسپرد اولیه، بلکه هزینههای احتمالی بسته شدن پوزیشن (که ممکن است توسط بروکر در زمان Modify مجدداً محاسبه شود) را پوشش دهد.
اسلیپیج در عملیات اصلاح
اگرچه اسلیپیج (Slippage) معمولاً با عملیات باز کردن یا بستن سفارش مرتبط است، اما در MQL5 هنگام استفاده از Trade Transaction برای Modify، میتوان پارامتری به نام maximum slippage را تعریف کرد. اگرچه برای SL/TP Modification این پارامتر کمتر حیاتی است، اما در سناریوهایی که اصلاح شامل تغییر قیمت ورودی (که در MQL5 بسیار نادر و پیچیده است) میشود، اسلیپیج میتواند بر اجرای دقیق قیمت درخواستی تأثیر بگذارد. در MQL4، اسلیپیج مستقیماً در OrderModify() با پارامتر deviation کنترل میشود.
[ \text{Deviation in MQL4} = \text{Maximum allowed price difference in points} ]
اگر قیمت بازار بیش از Deviation از قیمت مورد انتظار فاصله بگیرد، تابع OrderModify() با خطا مواجه میشود. این مکانیسم در MQL5 نیز تحت پارامتر deviation در ساختار MqlTradeRequest وجود دارد.
نرخ نوسانات بازار و مدیریت تکرار درخواستها
در شرایط نوسانات بالا (High Volatility)، مانند زمان انتشار اخبار اقتصادی مهم، بازار با اسپرد بسیار گسترده و Requotes یا Rejections شدید مواجه است. در این شرایط، فراخوانی مکرر OrderModify() برای اجرای تریلینگ استاپ احتمالاً منجر به تعداد زیادی Error 130 (Invalid Stops) یا Error 131 (Invalid Price) میشود، زیرا قیمت بازار در کسری از ثانیه تغییر میکند و شرایط Stop Level نقض میشود. راهکار حرفهای این است که در این زمانها، ربات را مجبور به مکث (Pause) در عملیات Modify کنیم و تنها پس از تثبیت نسبی بازار، اصلاحات را با احتیاط و پس از بررسی مجدد سطوح قیمت انجام دهیم.
نکات بهینهسازی عملکرد ربات معاملهگر هنگام اصلاح سفارشات
برنامهنویسی الگوریتمی کارآمد نیازمند حداقلسازی ترافیک غیرضروری با سرور بروکر است. هر فراخوانی OrderModify() یا PositionModify() یک درخواست شبکه است که زمانبر و مستعد خطا است.
اجرای اصلاحات فقط در زمان نیاز واقعی
بزرگترین اشتباه در پیادهسازی تریلینگ استاپ، فراخوانی OrderModify() در هر تیک (Tick) جدید است، حتی اگر قیمت فقط یک نقطه (Point) جابجا شده باشد.
بهینهسازی کلیدی: یک متغیر داخلی در EA خود تعریف کنید که آخرین سطح SL تنظیم شده را ذخیره کند. تنها زمانی که SL جدید مورد نظر (بر اساس منطق تریلینگ یا بریک ایون) حداقل به اندازه حداقل فاصله مجاز برای اصلاح (مثلاً 2 تا 5 پوینت) با سطح SL ذخیره شده تفاوت داشت، آنگاه تابع Modify فراخوانی شود.
مدیریت تیکتها و Position Handles در MQL5
در MQL5، استفاده از PositionGetTicket() برای اطمینان از اینکه تیکت مورد نظر هنوز یک پوزیشن فعال است، ضروری است. همچنین، اگر استراتژی شما شامل بستن پوزیشنها و باز کردن سریع آنها برای تغییرات اساسی است (که گاهی اوقات تنها راه Modify در MQL5 محسوب میشود)، باید مطمئن شوید که توالی Close و Open به درستی مدیریت میشود تا در فاصله زمانی کوتاه بین آنها، شرایط بازار به نفع شما تغییر نکند.
بررسی وضعیت اجرای تراکنشها
در MQL5، پس از فراخوانی PositionModify() یا OrderSend() با Action MODIFY، باید به دقت ResultRetcode را بررسی کنیم. کدهای خطای متداول هنگام اصلاح عبارتند از:
- TRADE_RETCODE_SL_HEDGED: حد ضرر در موقعیتی قرار دارد که با حد ضرر پوزیشن موجود همپوشانی دارد (مخصوصاً در سیستمهای Hedging اگر قوانین بروکر اجازه ندهد).
- TRADE_RETCODE_INVALID_STOPS: رایجترین خطا، ناشی از نقض Stop Level.
برنامهنویس باید یک نقشه خطای داخلی داشته باشد تا در صورت دریافت خطاهای اصلاح، بتواند منطق خود را برای تلاش مجدد یا ثبت خطا تنظیم کند.
مثالهای کد: اصلاح پیشرفته سفارشات در MQL4 و MQL5
برای تکمیل درک، در اینجا یک مقایسه عملی در قالب توابع کمکی (Helper Functions) ارائه میشود که وظیفه اصلاح SL یک پوزیشن باز را بر عهده دارند.
تابع اصلاح SL در MQL4 (با رعایت Stop Level)
این تابع از GetTicketInformation برای تضمین صحت دادهها استفاده میکند و سپس با OrderModify تلاش میکند.
// نیازمند کتابخانه کمکی برای دریافت Stop Level در MQL4 است.
// در اینجا فرض می کنیم ابزاری برای GetStopLevel وجود دارد.
double GetStopLevelPoints(string symbol)
{
// در MQL4، این ممکن است نیاز به QuerySymbolsInfo داشته باشد یا مستقیماً SYMBOL_STOPLEVEL استفاده شود.
// برای سادگی، فرض می کنیم مقدار نقطهای را برمی گرداند.
return MarketInfo(symbol, MODE_STOPLEVEL);
}
void AdjustSL_MQL4(long ticket)
{
if (!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) return;
double open_price = OrderOpenPrice();
double current_tp = OrderTakeProfit();
int type = OrderType();
double required_distance = GetStopLevelPoints(_Symbol) * _Point * 10; // فاصله امن اضافی
double new_sl = 0.0;
if (type == OP_BUY)
{
// سطح SL باید بالاتر از قیمت فعلی باشد، حداقل به اندازه فاصله امن
new_sl = NormalizeDouble(open_price + required_distance, _Digits);
// اگر SL جدید بالاتر از SL فعلی باشد (یا SL تنظیم نشده باشد) اقدام کن
if (new_sl > OrderStopLoss())
{
if (OrderModify(ticket, OrderClosePrice(), new_sl, current_tp, 0, clrGreen))
{
Print("MQL4 SL Modified Successfully for Ticket: ", ticket);
}
else
{
Print("MQL4 SL Modification Failed. Error: ", GetLastError());
}
}
}
// منطق OP_SELL مشابه است...
}
تابع اصلاح SL در MQL5 (با استفاده از CTrade Class)
این تابع از ساختار مدرن MQL5 استفاده میکند و از کلاس CTrade برای مدیریت تراکنشها بهره میبرد.
#include <MQL5/Trade/Trade.mqh>
CTrade trade_modifier;
void AdjustSL_MQL5(ulong position_ticket)
{
if (!PositionSelectByTicket(position_ticket)) return;
double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double new_sl = 0.0;
// فاصله امن بر اساس Stop Level بروکر
double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_STOP_LEVEL);
double point_size = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if (type == POSITION_TYPE_BUY)
{
// محاسبه SL جدید: قیمت ورود + فاصله امن (StopLevel * Point * Multiplier)
new_sl = NormalizeDouble(open_price + stop_level * point_size * 3, _Digits);
// اطمینان از اینکه SL جدید معتبر و بهبود یافته است
if (new_sl > PositionGetDouble(POSITION_SL))
{
if (trade_modifier.PositionModify(position_ticket, new_sl, PositionGetDouble(POSITION_TP)))
{
Print("MQL5 SL Modified Successfully for Position: ", position_ticket);
}
else
{
Print("MQL5 SL Modification Failed. Retcode: ", trade_modifier.ResultRetcode());
}
}
}
// منطق POSITION_TYPE_SELL مشابه است...
}
این مثالها نشان میدهند که در MQL5، دسترسی به پارامترهای پوزیشن از طریق توابع دسترسی (PositionGetDouble) و انجام اصلاح از طریق متدهای شیءگرا (مانند trade_modifier.PositionModify) بسیار ساختاریافتهتر است، در حالی که MQL4 به توابع گلوبال و پارامترهای مبتنی بر Ticket وابسته است.
جمعبندی رویکردها و انتخاب صحیح
انتخاب بین استفاده از توابع MQL4 و ساختارهای MQL5 برای اصلاح سفارش صرفاً یک تصمیم سینتکسی نیست، بلکه بازتابی از پارادایمهای زیربنایی است.
در MQL4، تمرکز بر Ticket است و OrderModify() ابزاری قدرتمند اما نسبتاً ساده برای تغییر سه پارامتر اصلی است. مدیریت خطا در این محیط بیشتر به معنای بررسی GetLastError() و اطمینان از رعایت Deviation است.
در MQL5، با داشتن مفاهیمی مانند Positionها و تراکنشهای صریح، اصلاح یک عملیات Trade Transaction پیچیدهتر است که نیاز به پر کردن ساختار درخواست دارد، مگر اینکه از تابع تسهیل شده PositionModify() استفاده شود که به طور خاص برای تنظیم SL/TP بهینه شده است. در MQL5، تمرکز بر دقت در محاسبه Stop Level و مدیریت صحیح کلاس CTrade است.
برنامهنویسان حرفهای باید همیشه به یاد داشته باشند که اصلاح سفارش یک عملیات حساس به زمان است. هر تأخیر یا خطای محاسباتی در تعیین SL یا TP جدید، به طور مستقیم بر موقعیت (Exposure) سیستم معاملاتی در برابر ریسکهای بازار تأثیر میگذارد. تسلط بر این مفاهیم، سنگ بنای توسعه EAهای مقاوم و سودآور در هر دو محیط MetaTrader است.
دیدگاهها (0)