🚀 بهترین برنامه نویس و طراح ربات معامله گر فارکس و سفارش ربات و اکسپرت معامله گر متاتریدر به زبان MQL4 و MQL5 | متااکسپرت

تفاوت OrderSend در MQL4 و MQL5

تفاوت OrderSend در MQL4 و MQL5: تحلیلی عمیق بر تکامل ارسال سفارشات در متاتریدر

ورود به دنیای الگوریتمیک تریدینگ (Algorithmic Trading) نیازمند تسلط کامل بر ابزارهای برنامه‌نویسی فراهم شده توسط پلتفرم‌های معاملاتی است. متاتریدر، چه در نسخه ۴ و چه در نسخه ۵، هسته اصلی این برنامه‌نویسی را تشکیل می‌دهد و زبان MQL (MetaQuotes Language) ابزار اصلی تعامل با سرور معاملاتی است. در میان توابع حیاتی برای ساخت یک اکسپرت ادوایزر (Expert Advisor – EA)، تابع ارسال سفارش (Order Send) یکی از بنیادین‌ترین و در عین حال پیچیده‌ترین بخش‌ها محسوب می‌شود. این تابع دروازه ورود معاملات شما به بازار است و نحوه عملکرد آن به طور چشمگیری بین MQL4 و MQL5 دستخوش تغییرات اساسی شده است. درک این تفاوت‌ها نه تنها برای توسعه‌دهندگان تازه‌کار ضروری است، بلکه برای کسانی که قصد مهاجرت (Migration) پروژه‌های قدیمی‌تر خود به پلتفرم جدیدتر را دارند، حیاتی به شمار می‌رود. این مقاله به تشریح عمیق معماری، پارامترها، و رویکردهای نوین در ارسال سفارش در هر دو نسخه می‌پردازد تا تصویری جامع و کاربردی ارائه دهد.

درک مفهوم ارسال سفارش و اهمیت آن در معاملاتی خودکار

ارسال سفارش (Order Send) فرآیندی است که در آن یک دستور معاملاتی (مانند خرید، فروش، تغییر حد سود یا ضرر) از طریق نرم‌افزار کلاینت (متاتریدر) به کارگزار (Broker) و سپس به بازار (Market) منتقل می‌شود تا اجرا گردد. در محیط معاملات خودکار (Automated Trading)، این تابع قلب تپنده سیستم تصمیم‌گیری است. یک EA پس از تحلیل داده‌ها و تصمیم‌گیری برای ورود یا خروج، باید این فرمان را به شکلی مطمئن و با پارامترهای دقیق به سرور ارسال کند. اگر این ارسال به درستی انجام نشود، کل منطق معاملاتی، هر چقدر هم که پیچیده و سودآور باشد، بی‌اثر خواهد ماند.

در نسخه‌های قدیمی‌تر مانند MQL4، این فرآیند عمدتاً مبتنی بر فراخوانی‌های مستقیم توابع سیستمی بود که نیازمند مدیریت دقیق تمام جزئیات ورود و خروج سفارش در داخل کدهای برنامه‌نویس بود. در مقابل، MQL5 با معرفی رویکردهای شی‌گرا (Object-Oriented) و کتابخانه‌های کلاس استاندارد، تلاش کرده است تا این پیچیدگی‌ها را کپسوله (Encapsulate) کرده و فرآیند ارسال سفارش را ایمن‌تر و انعطاف‌پذیرتر سازد.

نحوه کار OrderSend در MQL4 و ساختار پارامترهای آن

در MQL4، تابع اصلی برای ارسال دستورات معاملاتی، تابع OrderSend() بود. این تابع بر اساس یک مدل عملیاتی مبتنی بر توابع ساختاریافته (Procedural) طراحی شده بود که مستقیماً با ساختارهای داده‌ای داخلی متاتریدر سروکار داشت.

ساختار اصلی تابع OrderSend در MQL4 به شرح زیر است:

int OrderSend(
   string symbol,         // نماد معاملاتی
   int cmd,               // نوع دستور (BUY, SELL, SLTP, etc.)
   double volume,         // حجم معامله
   double price,          // قیمت ورود
   int slippage,          // میزان انحراف مجاز (اسلیپیج)
   double stoploss,       // حد ضرر
   double takeprofit,     // حد سود
   string comment=NULL,   // توضیحات
   int magic=0,           // شماره جادویی
   datetime expiration=0  // تاریخ انقضا
);

تحلیل عمیق پارامترها نشان می‌دهد که برنامه‌نویس باید تمامی جزئیات معامله را به صورت دستی و دقیق در فراخوانی تابع مشخص می‌کرد.

نوع دستور (cmd): این پارامتر با استفاده از ثابت‌هایی مانند OP_BUY، OP_SELL، OP_BUYLIMIT، OP_SELLSTOP و غیره تعریف می‌شد. برنامه‌نویس باید به طور دقیق تعیین می‌کرد که آیا معامله یک سفارش بازار (Market Order) است یا یک سفارش در انتظار (Pending Order).

قیمت (price): برای سفارشات بازار، این قیمت باید به درستی انتخاب می‌شد (Bid برای فروش و Ask برای خرید).

حد سود و ضرر (stoploss, takeprofit): این مقادیر باید حتماً با استفاده از تابع NormalizeDouble و با در نظر گرفتن نقاط (Points) و اندازه قیمت (Digits) نماد، نرمال‌سازی می‌شدند تا از خطاهای مربوط به دقت ممیز شناور جلوگیری شود. عدم توجه به این جزئیات یکی از شایع‌ترین دلایل شکست در ارسال سفارشات در MQL4 بود.

شماره جادویی (magic): این پارامتر کلیدی برای شناسایی معاملات متعلق به یک EA خاص بود و به توابع OrderSelect() و OrderClose() کمک می‌کرد تا فقط پوزیشن‌های خودی مدیریت شوند.

محدودیت‌ها و مشکلات رایج OrderSend در MQL4

با وجود سادگی ظاهری، OrderSend در MQL4 با چندین چالش بزرگ روبرو بود که توسعه‌دهندگان را ملزم به نوشتن کدهای پیچیده مدیریت خطا می‌کرد:

۱. عدم انعطاف‌پذیری در مدیریت پوزیشن‌ها: MQL4 به طور ذاتی بر مدل هجینگ (Hedging) متمرکز بود و اگر کارگزار از مدل نتینگ (Netting) پشتیبانی می‌کرد، مدیریت پوزیشن‌های متعدد برای یک نماد و جهت خاص بسیار دشوار بود. شما باید به صورت دستی تعداد پوزیشن‌های باز را با استفاده از حلقه‌های for و OrderSelect بررسی می‌کردید.

۲. ارتباط مستقیم با سرور: تابع OrderSend مستقیماً با سرور ارتباط برقرار می‌کرد و مدیریت توالی دستورات (مثلاً باز کردن یک معامله و بلافاصله تغییر SL/TP) اغلب منجر به شرایط رقابتی (Race Conditions) می‌شد.

۳. مدیریت تراکنش‌های پیچیده: برای انجام عملیاتی مانند بستن بخشی از یک معامله یا اصلاح قیمت‌ها، برنامه‌نویس مجبور بود چندین فراخوانی متوالی (مانند بستن و سپس باز کردن مجدد) را مدیریت کند که ریسک خطا را افزایش می‌داد.

۴. وابستگی شدید به وضعیت جاری: خروجی تابع تنها یک تیکت (Ticket) بود، اما تأیید اجرای واقعی معامله (Execution Confirmation) اغلب نیازمند بررسی مجدد وضعیت حساب با استفاده از تابع OrderSelect بود. این تأخیر می‌توانست در شرایط نوسان بالا مشکل‌ساز باشد.

تغییرات معماری معاملاتی در متاتریدر ۵

انتقال از متاتریدر ۴ به ۵ صرفاً یک ارتقاء زبانی نبود؛ بلکه یک بازنگری کامل در معماری زیربنای معاملاتی (Trading Architecture) را به همراه داشت. متاتریدر ۵ با هدف همگام‌سازی با استانداردهای مدرن بازارهای مالی، به‌ویژه در مورد بازارهای آتی و فارکس مبتنی بر مدل FIFO (First In, First Out)، طراحی شد.

بزرگترین تحول، تغییر رویکرد از مدل سنتی سفارش (Traditional Order Model) به مدل پوزیشن (Position Model) بود.

تفاوت مدل سفارش در MQL4 و MQL5:

  • MQL4 (مدل سفارش): هر بار که شما OrderSend را فراخوانی می‌کردید، یک رکورد جدید به نام سفارش (Order) در تاریخچه معاملاتی ایجاد می‌شد. در حساب‌های هجینگ، چندین سفارش می‌توانست به طور همزمان برای یک نماد فعال باشد.
  • MQL5 (مدل پوزیشن): در حالت پیش‌فرض (و در حساب‌های نتینگ)، تنها یک پوزیشن (Position) فعال برای هر نماد نگهداری می‌شود. ارسال دستور خرید جدید، پوزیشن موجود را اصلاح می‌کند (حجم را افزایش می‌دهد یا آن را در جهت معکوس تعدیل می‌کند). اگر دستور برای بستن بخشی از پوزیشن باشد، حجم پوزیشن کاهش می‌یابد.

این تغییر پارادایم، استفاده از توابع قدیمی MQL4 را غیرممکن ساخت، زیرا مفاهیم اصلی مانند تیکت سفارش در پوزیشن‌های نتینگ دیگر نقش مرکزی را ایفا نمی‌کنند؛ بلکه شناسه پوزیشن اهمیت پیدا می‌کند.

حذف OrderSend کلاسیک و معرفی CTrade (Trade Class) در MQL5

با توجه به تغییرات معماری، تابع OrderSend کلاسیک در MQL5 برای حفظ سازگاری با عقب‌مانده (Legacy Support) باقی ماند، اما به شدت منسوخ (Deprecated) تلقی می‌شود و استفاده از آن در EAهای جدید به هیچ وجه توصیه نمی‌شود. متاتریدر ۵ یک رویکرد کاملاً شی‌گرا را از طریق کتابخانه‌های استاندارد معرفی کرد که ارتباط با بازار را ساده‌تر و ایمن‌تر می‌سازد.

کلاس اصلی برای مدیریت معاملات در MQL5، کلاس CTrade است که بخشی از کتابخانه استاندارد MQL5 (Standard Library) محسوب می‌شود. این کلاس مجموعه‌ای از توابع سطح بالا (High-Level Functions) را ارائه می‌دهد که عملیات پیچیده را در یک فراخوانی ساده کپسوله می‌کنند.

استفاده از CTrade مزایای عمده‌ای دارد:

۱. انتزاع (Abstraction): برنامه‌نویس دیگر نگران جزئیات پایین‌دستی ارسال داده‌های خام به سرور نیست.
2. مدیریت خودکار وضعیت: کلاس به طور خودکار وضعیت‌های میانی و نهایی تراکنش‌ها را رصد می‌کند. 3. قابلیت اطمینان بالا: CTrade به طور داخلی از مکانیزم‌های بررسی و تأیید تراکنش استفاده می‌کند.

برای استفاده از این کلاس، ابتدا باید شیئی از آن ساخته شده و سپس متدهای آن فراخوانی شوند:

#include <Trade\Trade.mqh>
CTrade trade; // تعریف شیء

نحوه ارسال سفارش با OrderSend در MQL5 و تفاوت آن با MQL4

در MQL5، تابع OrderSend همچنان وجود دارد، اما ساختار پارامترها به طور کامل تغییر یافته است تا از مدل جدید تراکنش‌های متاتریدر ۵ پشتیبانی کند. این تابع اکنون از یک ساختار داده‌ای به نام MqlTradeRequest برای تعریف درخواست و یک ساختار MqlTradeResult برای دریافت نتیجه استفاده می‌کند.

ساختار تابع OrderSend در MQL5:

long OrderSend(
   MqlTradeRequest& request,     // ساختار درخواست
   MqlTradeResult& result        // ساختار نتیجه
);

این تغییر نشان‌دهنده انتقال از رویکرد “ارسال پارامترهای منفرد” به “ارسال یک ساختار درخواست کامل” است، که انعطاف‌پذیری و دقت تعریف تراکنش را به شدت افزایش می‌دهد. در واقع، اگرچه نام تابع حفظ شده است، اما عملکرد درونی آن کاملاً مبتنی بر ساختارها است و به جای کلاس CTrade که سطح بالاتر است، API سطح پایین (Low-Level API) برای ارسال سفارش محسوب می‌شود.

بررسی ساختار MqlTradeRequest و MqlTradeResult

آشنایی با ساختارهای MqlTradeRequest و MqlTradeResult برای درک نحوه ارسال سفارش در MQL5 ضروری است.

ساختار MqlTradeRequest

این ساختار تمام اطلاعات لازم برای اجرای یک عملیات معاملاتی را حمل می‌کند. پارامترهای کلیدی عبارتند از:

  • action: نوع عملیات درخواستی (مانند TRADE_ACTION_DEAL برای اجرای بازار، TRADE_ACTION_PENDING برای سفارشات در انتظار، یا TRADE_ACTION_CLOSE_BY برای بستن متقابل).
  • symbol: نماد معاملاتی.
  • volume: حجم معامله.
  • type: نوع سفارش (مانند ORDER_TYPE_BUY یا ORDER_TYPE_SELL).
  • price: قیمت مورد نظر.
  • deviation: حداکثر انحراف مجاز (معادل Slippage).
  • sl, tp: حد ضرر و حد سود.
  • comment: توضیحات.
  • magic: شماره جادویی.
  • position: برای عملیات تعدیل پوزیشن (مانند بستن جزئی)، شناسه پوزیشن قبلی در اینجا مشخص می‌شود.
  • type_filling: نحوه پر شدن سفارش (مانند ORDER_FILLING_FOK یا ORDER_FILLING_IOC که در MQL4 وجود نداشت).

برنامه‌نویس باید این ساختار را با دقت مقداردهی اولیه کند و سپس آن را به تابع OrderSend ارسال نماید. این ساختار به طور صریح اجازه می‌دهد تا مشخص شود که آیا این درخواست مربوط به باز کردن یک پوزیشن جدید است یا بستن/تعدیل یک پوزیشن موجود.

ساختار MqlTradeResult

این ساختار حاوی پاسخ سرور پس از پردازش درخواست است:

  • retcode: کد بازگشتی اصلی (مانند TRADE_RETCODE_DONE در صورت موفقیت).
  • deal: شناسه معامله جدید (Deal ID) در صورت اجرای موفق.
  • order: شناسه سفارش (در صورتی که یک سفارش معلق ایجاد شده باشد).
  • volume: حجمی که واقعاً اجرا شده است.

تفاوت کلیدی با MQL4: در MQL4، خروجی تابع یک عدد صحیح (تیکت) بود. در MQL5، خروجی یک ساختار حاوی جزئیات کامل اجرای تراکنش است که امکان اشکال‌زدایی (Debugging) و بررسی دقیق‌تر وضعیت پس از ارسال را فراهم می‌آورد.

تفاوت حساب هجینگ (Hedging) و نتینگ (Netting) و تأثیر آن بر ارسال سفارش

یکی از بزرگترین نقاط تفاوت معماری MQL4 و MQL5 در نحوه مدیریت حساب‌های مختلف نهفته است. کارگزاری‌ها معمولاً از دو مدل اصلی پیروی می‌کنند که مستقیماً بر تابع OrderSend تأثیر می‌گذارد.

۱. مدل هجینگ (Hedging Model) – غالب در MQL4

در حساب‌های هجینگ، می‌توانید برای یک نماد خاص، چندین پوزیشن با جهت‌های مخالف داشته باشید. به عنوان مثال، می‌توانید همزمان ۱۰ لات خرید و ۵ لات فروش برای EURUSD باز کنید.

  • در MQL4: هر OrderSend یک سفارش جدید ایجاد می‌کرد که منجر به ایجاد یک رکورد جدید در تاریخچه معاملات می‌شد. مدیریت این پوزیشن‌ها نیاز به پیمایش تمام سفارشات باز داشت.

۲. مدل نتینگ (Netting Model) – استاندارد در MQL5

در حساب‌های نتینگ (که در بازارهایی مانند آتی رایج است)، تنها یک پوزیشن خالص (Net Position) برای هر نماد می‌تواند فعال باشد.

  • اگر پوزیشن فعلی شما ۱۰ لات خرید باشد و شما ۵ لات خرید دیگر ارسال کنید، پوزیشن جدید به ۱۵ لات خرید تبدیل می‌شود.
  • اگر پوزیشن فعلی ۱۰ لات خرید باشد و شما ۱۰ لات فروش ارسال کنید، پوزیشن بسته شده و پوزیشن خالص صفر می‌شود.
  • اگر پوزیشن فعلی ۱۰ لات خرید باشد و شما ۱۲ لات فروش ارسال کنید، پوزیشن ۱۰ لات خرید بسته شده و ۲ لات فروش باز می‌شود.

تأثیر بر MQL5:

MQL5 با استفاده از ساختار MqlTradeRequest، این دو مدل را پشتیبانی می‌کند. وقتی با استفاده از کلاس CTrade یا تابع سطح پایین OrderSend کار می‌کنید، باید پارامتر position را به درستی مقداردهی کنید.

  • در حساب‌های نتینگ، برای بستن یا تعدیل، باید شناسه پوزیشن (Position ID) مربوط به پوزیشن فعلی را در درخواست مشخص کنید.
  • در MQL5، شما می‌توانید در هنگام تعریف درخواست، یک position_id را مشخص کنید. این تضمین می‌کند که عملیات بر روی پوزیشن مورد نظر اعمال شود، نه اینکه یک سفارش جدید ایجاد شود.

نکته حیاتی برای مهاجرت: اگر EA قدیمی شما بر اساس مدل هجینگ MQL4 طراحی شده باشد، انتقال مستقیم آن به یک سرور نتینگ بدون بازنویسی منطق مدیریت پوزیشن‌ها تقریباً غیرممکن است، زیرا منطق بستن یک سفارش خاص در MQL4 دیگر در MQL5 (در حالت نتینگ) وجود ندارد؛ بلکه شما با پوزیشن‌ها سروکار دارید.

مدیریت خطاها و کدهای خطا (Error Codes) در هر دو نسخه

قابلیت اطمینان یک EA به شدت وابسته به نحوه مدیریت شکست‌های احتمالی در ارسال سفارش است. کدهای خطا در MQL4 و MQL5 تفاوت‌های ساختاری مهمی دارند.

مدیریت خطا در MQL4

در MQL4، پس از فراخوانی OrderSend(), اگر مقدار بازگشتی کمتر از صفر باشد، ارسال موفقیت‌آمیز نبوده است. برای فهمیدن دلیل شکست، از تابع GetLastError() استفاده می‌شد.

کدهای خطای رایج MQL4:

  • 130 (Invalid volume): حجم نامعتبر.
  • 129 (Invalid price): قیمت نامعتبر (غالباً به دلیل عدم نرمال‌سازی).
  • 131 (Invalid stops): SL/TP در محدوده مجاز نباشد.
  • 132 (Invalid requotes): قیمت تغییر کرده و نیاز به قیمت‌گذاری مجدد است.

برنامه‌نویسان مجبور بودند در یک حلقه while وضعیت را بررسی کنند تا مطمئن شوند سفارش اجرا شده یا کد خطا به حالتی بازگشته که قابل حل باشد (مثلاً Requote).

مدیریت خطا در MQL5 با MqlTradeResult

در MQL5، اطلاعات خطا بسیار غنی‌تر است و مستقیماً در ساختار MqlTradeResult در فیلد retcode قرار دارد.

کدهای بازگشتی در MQL5 به دو دسته اصلی تقسیم می‌شوند:

۱. کدهای بازگشتی اولیه (Initial Return Codes): این‌ها توسط خود تابع OrderSend برگردانده می‌شوند. اگر این کد یکی از کدهای TRADE_RETCODE_DONE (موفقیت)، TRADE_RETCODE_REQUOTE (نیاز به قیمت‌گذاری مجدد) یا TRADE_RETCODE_PENDING (موفقیت در تنظیم سفارش معلق) باشد، تراکنش تا حدی موفق بوده است.

۲. کدهای خطا پس از پردازش (Post-Processing Error Codes): اگر کد بازگشتی اولیه نشان‌دهنده نیاز به بررسی بیشتر باشد (مانند Requote)، باید محتوای retcode در MqlTradeResult بررسی شود.

کدهای خطای مهم MQL5:

  • TRADE_RETCODE_DONE (0): سفارش با موفقیت پردازش شد.
  • TRADE_RETCODE_REQUOTE (2): سرور قیمت جدیدی را پیشنهاد می‌دهد (نیازمند تلاش مجدد با قیمت جدید).
  • TRADE_RETCODE_NO_MONEY (4): موجودی کافی نیست.
  • TRADE_RETCODE_INVALID_VOLUME (12): حجم نامعتبر.
  • TRADE_RETCODE_PRICE_CHANGED (13): قیمت در حین ارسال تغییر کرده است.

مزیت اصلی در MQL5 این است که اطلاعات خطا مستقیماً در شیء نتیجه قرار دارد و نیازی به فراخوانی جداگانه GetLastError() نیست (اگرچه این تابع همچنان برای خطاهای سطح پایین پلتفرم در دسترس است). کلاس CTrade این مدیریت خطا را به سطح بالاتری می‌برد؛ متدهایی مانند trade.Buy() یا trade.Sell() مستقیماً مقدار بولی (Boolean) موفقیت یا عدم موفقیت را برمی‌گردانند و جزئیات خطا در متدهای داخلی کلاس قابل دسترسی است.

مقایسه عملی OrderSend در MQL4 و MQL5 با مثال کدنویسی

برای درک بهتر تفاوت‌ها، یک سناریوی ساده: باز کردن یک معامله خرید به حجم ۰.۱ لات در قیمت فعلی با انحراف ۱ واحدی (Point).

سناریو در MQL4 (بازار):

در MQL4، ما نیاز به دریافت قیمت Ask و استفاده از OrderSend داریم:

// MQL4 Example: Market Buy Order
int ticket = -1;
double ask = MarketInfo(Symbol(), MODE_ASK);
double sl_level = ask - 50 * Point(); // 50 نقاط حد ضرر

ticket = OrderSend(
   Symbol(),
   OP_BUY,
   0.1,
   ask,
   3, // Slippage = 3 points
   sl_level,
   0.0, // No Take Profit
   "MQL4 EA Trade",
   12345,
   0
);

if(ticket > 0)
{
   Print("OrderSend MQL4 Successful. Ticket: ", ticket);
}
else
{
   Print("OrderSend MQL4 Failed. Error: ", GetLastError());
}

سناریو در MQL5 با استفاده از CTrade (توصیه شده):

در MQL5، ما از کلاس سطح بالا استفاده می‌کنیم که مدیریت قیمت و خطا را بسیار ساده‌تر می‌کند:

// MQL5 Example: CTrade Market Buy Order
#include <Trade\Trade.mqh>
CTrade trade; 

void OnStart()
{
   double volume = 0.1;
   double sl_level = 0.0; // Set SL later or rely on trade object settings

   // تنظیمات حد ضرر (اختیاری: تنظیمات SL/TP پیش‌فرض در شیء trade)
   double current_ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   sl_level = current_ask - 50 * _Point; 

   // ارسال سفارش خرید
   bool result = trade.Buy(
      volume,               // حجم
      _Symbol,              // نماد
      current_ask,          // قیمت ورود
      0,                    // SL (صفر یعنی تنظیم نشود)
      0,                    // TP (صفر یعنی تنظیم نشود)
      "MQL5 CTrade Buy"     // توضیحات
   );

   if(result)
   {
      Print("CTrade Buy Successful. Deal ID: ", trade.ResultDeal());
   }
   else
   {
      Print("CTrade Buy Failed. Error Code: ", trade.ResultRetcode());
      Print("Error Description: ", trade.ResultRetcodeDescription());
   }
}

سناریو در MQL5 با استفاده از OrderSend سطح پایین (ساختارها):

اگر مجبور به استفاده از تابع سطح پایین باشیم، باید ساختارها را مقداردهی کنیم:

// MQL5 Example: Low-Level OrderSend with Structs
MqlTradeRequest request;
MqlTradeResult result;

// 1. پر کردن ساختار درخواست
request.action   = TRADE_ACTION_DEAL;         // اجرای بازار
request.symbol   = _Symbol;
request.volume   = 0.1;
request.type     = ORDER_TYPE_BUY;
request.price    = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.deviation = 3;                         // 3 points slippage
request.sl       = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - 50 * _Point;
request.magic    = 12345;
request.comment  = "MQL5 Low-Level Trade";

// 2. ارسال درخواست
long ticket = OrderSend(request, result);

if(ticket > 0)
{
   if(result.retcode == TRADE_RETCODE_DONE)
   {
      Print("Low-Level OrderSend Successful. Deal ID: ", result.deal);
   }
   else
   {
      Print("OrderSend succeeded structurally, but failed execution. Retcode: ", result.retcode);
   }
}
else
{
   Print("OrderSend failed structurally. Result Retcode: ", result.retcode);
}

همانطور که مشاهده می‌شود، در MQL5، استفاده از CTrade بسیار تمیزتر و مقاوم‌تر است، زیرا بسیاری از جزئیات مانند تعیین قیمت دقیق (Bid/Ask) به صورت هوشمندانه توسط کلاس مدیریت می‌شود، در حالی که در سطح پایین، باید تمام فیلدهای MqlTradeRequest را به صورت دستی پر کرد.

نکات مهم برای مهاجرت اکسپرت از MQL4 به MQL5

مهاجرت یک سیستم معاملاتی موفق از MQL4 به MQL5 نیازمند بیش از صرفاً تبدیل سینتکس توابع است. نیاز به بازنگری عمیق در مدل معاملاتی است.

۱. مدیریت پوزیشن‌ها: این بزرگترین چالش است. منطقی که در MQL4 برای شمارش و بستن سفارشات مجزا با استفاده از OrderSelect نوشته شده بود، باید به منطق مدیریت پوزیشن‌ها در MQL5 تبدیل شود. باید از توابعی مانند PositionSelect() و متدهای کلاس CPositionInfo برای بررسی وضعیت پوزیشن‌های فعال استفاده شود.

۲. تغییر ساختار داده‌ها: تمام ساختارهای داده‌ای مانند HistoryOrderSelect، PositionSelect و غیره در MQL5 تغییر کرده‌اند. آرایه‌ها و ساختارها باید با نسخه‌های MQL5 جایگزین شوند.

۳. نرمال‌سازی مجدد: اگرچه MQL5 در زمینه مدیریت دقت بهتر عمل می‌کند، اما همچنان توصیه می‌شود از توابع استاندارد مانند NormalizeDouble() و توابع مربوط به نماد مانند SymbolInfoDouble() برای اطمینان از صحت قیمت‌ها استفاده شود.

۴. استفاده از CTrade: حتی اگر تابع OrderSend سطح پایین را مستند کنید، بهترین رویه این است که تمام منطق اصلی ارسال سفارش را به کلاس CTrade منتقل کنید. این امر کد شما را با استانداردهای مدرن همسو کرده و قابلیت نگهداری (Maintainability) را افزایش می‌دهد.

۵. بررسی تنظیمات سرور: قبل از شروع به کدنویسی، باید مشخص شود که آیا حساب مقصد از مدل هجینگ یا نتینگ پشتیبانی می‌کند. این تعیین می‌کند که آیا باید از متدهای تعدیل پوزیشن‌های MQL5 استفاده کنید یا خیر.

بهترین روش‌های ارسال سفارش در ربات‌های حرفه‌ای

برنامه‌نویسان الگوریتمی پیشرفته در MQL5 به ندرت مستقیماً تابع سطح پایین OrderSend را فراخوانی می‌کنند. بهترین روش‌ها بر پایه سطح انتزاع و قابلیت اطمینان بنا شده‌اند:

۱. استفاده حداکثری از کلاس CTrade

همانطور که در مثال‌ها دیدیم، CTrade بهترین ابزار است. این کلاس به شما اجازه می‌دهد تا با کمترین کد، عملیات پیچیده را انجام دهید. برای مثال، بستن یک پوزیشن خاص در MQL4 نیاز به چندین مرحله پیمایش سفارشات داشت، اما در MQL5 با CTrade این کار با یک متد انجام می‌شود.

۲. مدیریت Requotes و تلاش مجدد

در بازارهای پرنوسان، تقریباً محال است که یک سفارش با قیمت اولیه پذیرفته شود. یک سیستم حرفه‌ای باید به طور خودکار تلاش مجدد (Retry Mechanism) را پیاده‌سازی کند.

اگر trade.Buy() با کد خطای TRADE_RETCODE_REQUOTE یا TRADE_RETCODE_PRICE_CHANGED شکست خورد، ربات باید:

  • قیمت فعلی (Ask یا Bid) را مجدداً با استفاده از SymbolInfoDouble بخواند.
  • پارامتر قیمت در ساختار درخواستی (یا متد CTrade) را با قیمت جدید به‌روزرسانی کند.
  • تلاش مجدد را در یک حلقه تکرار کند (با در نظر گرفتن یک سقف برای تلاش‌های مجدد تا از اجرای بی‌پایان جلوگیری شود).

۳. استفاده از توابع معاملاتی تخصصی

MQL5 توابعی اختصاصی برای عملیات خاص ارائه می‌دهد که OrderSend اولیه آن‌ها را پوشش نمی‌داد:

  • PositionOpen()/PositionClose()/PositionModify(): این توابع مستقیماً بر روی پوزیشن‌ها عمل می‌کنند و برای سیستم‌های نتینگ حیاتی هستند. برای مثال، برای بستن جزئی یک پوزیشن، شما به جای تلاش برای باز کردن یک سفارش مخالف با حجم کمتر، از متدهای تغییر پوزیشن استفاده می‌کنید.
  • HistoryDealSelect() و HistoryPositionSelect(): برای بررسی دقیق تاریخچه معاملات و پوزیشن‌های بسته شده، ابزارهای قدرتمندتری نسبت به توابع قدیمی MQL4 در اختیار دارید.

۴. کپسوله‌سازی منطق ارسال سفارش

به جای پراکنده کردن فراخوانی‌های trade.Buy() در سراسر کد EA، بهتر است یک کلاس سفارشی (مثلاً MyTradeManager) ایجاد کنید که کلاس CTrade را درون خود داشته باشد و متدهای ساده‌ای مانند OpenBuyOrder(volume, sl, tp) را ارائه دهد. این کلاس مسئول تمام اعتبارسنجی‌ها، نرمال‌سازی‌ها، و مدیریت حلقه تلاش مجدد خواهد بود و این امر باعث می‌شود منطق استراتژی اصلی شما تمیز و متمرکز بر تحلیل بازار باقی بماند.

در نهایت، تفاوت بین OrderSend در MQL4 و اکوسیستم معاملاتی MQL5، تفاوت بین برنامه‌نویسی رویه‌ای و برنامه‌نویسی شی‌گرا در مدیریت تراکنش‌ها است. MQL4 برنامه‌نویس را مجبور می‌کرد که تمام جزئیات ارتباط با سرور را مدیریت کند، در حالی که MQL5 از طریق کلاس‌هایی مانند CTrade و ساختارهای داده‌ای دقیق مانند MqlTradeRequest، این فرآیند را به یک عملیات مدل‌سازی شده و شیءگرا تبدیل کرده است که نه تنها کارایی را بالا می‌برد بلکه مقاومت سیستم در برابر نوسانات بازار و تغییرات زیرساختی کارگزار را نیز به شدت افزایش می‌دهد. تسلط بر این انتقال، کلید موفقیت در توسعه EAهای نسل جدید است.

دیدگاه‌ها (0)

  • نظرات نامربوط به محتوا تأیید نخواهند شد.
  • لطفاً از افزودن نظرات تکراری خودداری کنید.
  • نظرات مربوط به دوره‌ها فقط برای خریداران محصول است.

*
*