
اول فرق «ارسال شد» و «اجرا شد» را روشن کنیم
در MQL5 یک اشتباه رایج این است که مقدار true برگشتی از OrderSend را معادل «معامله با موفقیت اجرا شد» بگیریم. مستندات رسمی MetaQuotes صریح میگوید true در OrderSend فقط نشان میدهد بررسی پایهٔ ساختار درخواست با موفقیت طی شده و درخواست برای پردازش پذیرفته شده است؛ این مقدار بهتنهایی تأیید نمیکند که معامله نهایی انجام شده باشد. برای فهم نتیجه باید فیلدهای MqlTradeResult، بهویژه retcode، و در صورت لزوم رویدادهای بعدی سرور را بررسی کرد [۱، ۲].
این تفاوت برای اکسپرت مهم است، چون اگر برنامه بلافاصله بعد از true یک فلگ داخلی مثل «position_opened=true» ثبت کند، ممکن است با وضعیت واقعی حساب از هم جدا شود. درخواست میتواند پذیرفته شود اما هنوز در صف پردازش باشد، به شکل سفارش قرار گرفته باشد، فقط بخشی از آن انجام شده باشد یا با یک کد بازگشت مشخص نتیجهٔ دیگری داشته باشد. بنابراین وضعیت داخلی اکسپرت باید از شواهد سرور پیروی کند، نه از یک bool.
یک زنجیرهٔ چهارمرحلهای برای کنترل سفارش بساز
مرحلهٔ اول، اعتبارسنجی خود برنامه است: نماد، حجم، جهت، قیمتهای لازم و قواعدی که خود اکسپرت تعیین کرده باید قبل از تماس با سرور روشن باشند. مرحلهٔ دوم OrderCheck است. این تابع درخواست را پیش از ارسال بررسی میکند و نتیجه را در MqlTradeCheckResult مینویسد. مستندات رسمی میگوید این ساختار میتواند retcode، برآورد مارجین لازم، مارجین آزاد، سطح مارجین و توضیح خطا را برگرداند؛ با این حال موفقیت OrderCheck هم تضمین اجرای نهایی سفارش نیست [۳، ۴].
مرحلهٔ سوم OrderSend و تحلیل MqlTradeResult است. فیلد retcode پاسخ سرور معاملاتی را نشان میدهد و order، deal، volume، price، comment، request_id و retcode_external میتوانند برای ثبت نتیجه و عیبیابی استفاده شوند. فهرست رسمی کدهای سرور بین حالتهایی مانند درخواست انجامشده، سفارش قرارگرفته، اجرای جزئی، رد شدن، timeout و حجم نامعتبر تفاوت میگذارد [۲، ۵]. مرحلهٔ چهارم، برای سیستمهایی که باید چرخهٔ واقعی اجرا را دنبال کنند، OnTradeTransaction است؛ این رویداد میتواند برای یک درخواست چند بار فراخوانی شود چون ایجاد سفارش، انجام معامله، انتقال به تاریخچه و ایجاد یا تغییر پوزیشن رویدادهای جداگانهاند [۶].
مثال آموزشی: true داریم اما هنوز نباید پوزیشن را قطعی بدانیم
یک مثال کاملاً فرضی در حساب آزمایشی در نظر بگیر. اکسپرت درخواست یک سفارش بازار با حجم ۰٫۰۳ لات میسازد. فرض میکنیم این حجم با مشخصات همان نماد سازگار است. OrderCheck بدون خطای ساختاری عبور میکند. سپس OrderSend مقدار true برمیگرداند، اما retcode در MqlTradeResult نشان میدهد سفارش برای پردازش پذیرفته یا قرار داده شده است، نه اینکه الزاماً همین لحظه یک deal نهایی ثبت شده باشد. در این نقطه، ثبت وضعیت «FILLED» در منطق داخلی زودهنگام است.
یک طراحی محتاطانه میتواند وضعیت داخلی را مثلاً از NEW به SENT تغییر دهد، request_id و retcode را در لاگ ثبت کند و فقط وقتی شواهد مربوط به deal یا پوزیشن مطابق قواعد سیستم دیده شد، حالت را به CONFIRMED ببرد. این نامها فقط مثال معماریاند و API رسمی نیستند. نکته این است که یک مسیر وضعیت داشته باشی که تفاوت «درخواست ساخته شد»، «درخواست ارسال شد»، «پاسخ سرور رسید» و «اثر معاملاتی تأیید شد» را گم نکند.
لاگ اکسپرت را طوری بنویس که فردا قابل بازسازی باشد
برای هر درخواست یک شناسهٔ قابل ردیابی در لاگ نگه دار و حداقل زمان، نماد، نوع درخواست، حجم، request_id، retcode، retcode_external، order، deal و comment را ثبت کن. لازم نیست هر تیک را به دیسک بمباران کنی؛ هدف این است که وقتی سفارش ناموفق یا تکراری شد، بتوانی ترتیب تصمیم و پاسخ را بازسازی کنی. MqlTradeResult مستقیماً request_id و کدهای پاسخ را در اختیار برنامه میگذارد، و مستندات میگوید retcode_external به سامانهٔ خارجی و کارگزار وابسته است، پس معنی آن را نباید برای همهٔ بروکرها ثابت فرض کرد [۲].
در OnTradeTransaction نیز نوع تراکنش را همراه شناسههای مرتبط ثبت کن. چون یک درخواست میتواند چند رویداد ایجاد کند، صرف دیدن اولین callback دلیل کافی برای بستهشدن چرخه نیست. همچنین بین «خطای برنامه» و «پاسخ سرور» تفکیک بگذار. GetLastError برای خطاهای محیط برنامه مفید است، اما جای retcode پاسخ معامله را نمیگیرد. این تفکیک کوچک، عیبیابی را از حدسزدن به یک فرایند قابل بررسی تبدیل میکند.
تست پذیرش پیشنهادی؛ بدون ریسک پول واقعی
برای یک تمرین عملی، در Strategy Tester یا حساب دمو یک ماتریس کوچک بساز. سناریوی اول یک درخواست معتبر است و باید مسیر OrderCheck تا پاسخ سرور را لاگ کند. سناریوی دوم عمداً از یک حجم ناسازگار با گام حجم استفاده میکند تا ببینی کنترل قبل از ارسال یا retcode مربوط به حجم چگونه ثبت میشود. سناریوی سوم فقط بررسی میکند که اگر OrderSend true شد ولی نتیجهٔ نهایی هنوز تأیید نشده، اکسپرت سفارش دوم مشابه را بلافاصله ارسال نکند. هدف این تست سودآوری نیست؛ هدف سنجش رفتار نرمافزار است.
منابع این مقاله در ۲۶ سپتامبر ۲۰۲۶ دوباره بررسی شدهاند. کدهای بازگشت و رفتار اجرای واقعی میتوانند به نوع سفارش، نماد، تنظیمات حساب، کارگزار و سامانهٔ معاملاتی بیرونی وابسته باشند؛ بنابراین یک retcode را خارج از زمینه به عنوان حکم عمومی تفسیر نکن. برای ادامه، مسیر رایگان اتوترید BamaUp و چکلیست ارزیابی اکسپرت را ببین. این نوشته آموزشی است و توصیهٔ معامله، وعدهٔ سود یا دستور استفاده از پول واقعی نیست.