برنامه‌نویسی ربات معامله‌گر

کنترل اسلیپیج و Deviation در اکسپرت هنگام اجرای واقعی

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

مشاوره و سفارش ربات:واتس‌اپتلگرام۰۹۱۷۱۷۹۲۵۸۱

پاسخ کوتاه: اسلیپیج فاصلهٔ قیمتی است که اکسپرت خواسته، با قیمتی که معامله واقعاً در آن باز شده است. در حالت اجرای فوری (Instant) و اجرای با درخواست (Request)، فیلد deviation بیشترین فاصلهٔ پذیرفتنی را بر حسب پوینت تعیین می‌کند. در اجرای بازار (Market)، قیمت را بروکر تعیین می‌کند. آنجا راه کنترل، اندازه‌گیری اسلیپیج واقعی و دوری از لحظه‌های پرخطر است.

اسلیپیج و Deviation چه فرقی دارند؟

اسلیپیج (Slippage) نتیجه است. فرض کنید اکسپرت خرید را با قیمت ۱٫۰۸۵۰۰ می‌فرستد و معامله با ۱٫۰۸۵۰۳ باز می‌شود؛ این ۳ پوینت اسلیپیج به ضرر شماست. Deviation تنظیم است: بیشترین فاصله‌ای که اکسپرت پیش از فرستادن سفارش اعلام می‌کند و حاضر است بپذیرد.

واحد هر دو پوینت است، نه پیپ. روی نمادهای پنج‌رقمی مثل EURUSD هر پیپ ۱۰ پوینت است، پس deviation برابر ۱۰ یعنی یک پیپ. اسلیپیج همیشه به ضرر نیست؛ در اجرای بازار، قیمت گاهی به سود شما هم جابه‌جا می‌شود.

اول حالت اجرای نماد را بشناسید

متاتریدر ۵ چهار حالت اجرا دارد و هر نماد در حساب شما یکی از آن‌ها را دارد. اکسپرت حالت را با SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE) می‌خواند:

حالت اجرا قیمت اجرا را چه کسی تعیین می‌کند نقش deviation
اجرای فوری (Instant) قیمتی که اکسپرت فرستاده؛ اگر بروکر آن را نپذیرد، ری‌کوت (Requote) می‌دهد از فیلدهای لازم سفارش است: بیشترین فاصلهٔ پذیرفتنی
اجرای با درخواست (Request) قیمتی که پیش از سفارش از بروکر گرفته شده از فیلدهای لازم سفارش است
اجرای بازار (Market) بروکر، بی‌مذاکره با معامله‌گر جزو فیلدهای لازم این حالت نیست
اجرای بورسی (Exchange) قیمت پیشنهادهای جاری بازار جزو فیلدهای لازم این حالت نیست

حساب‌های ECN معمولاً اجرای بازار دارند. پس عدد deviation در کد، روی چنین حسابی جلوی اسلیپیج را نمی‌گیرد. تفاوت نوع حساب‌ها را در تست ربات روی حساب‌های ECN و Standard آورده‌ایم.

Deviation در MQL5 و MQL4

  • MQL5: در ساختار MqlTradeRequest، فیلد deviation بیشترین انحراف قیمت بر حسب پوینت است. با کلاس CTrade همین عدد با SetDeviationInPoints() تنظیم می‌شود.
  • MQL4: پارامتر slippage در تابع OrderSend همین کار را می‌کند. طبق مستندات، اگر قیمت درخواستی کمی کهنه باشد، سفارش فقط وقتی با قیمت جاری باز می‌شود که قیمت جاری در بازهٔ «قیمت درخواستی به‌علاوه یا منهای slippage» باشد. اگر قیمت کاملاً کهنه باشد، خطای ۱۳۸ (ERR_REQUOTE) برمی‌گردد، هر عددی که برای slippage گذاشته باشید.

کدهایی که اکسپرت باید بشناسد

  • ۱۰۰۰۹ (TRADE_RETCODE_DONE): معامله انجام شد. قیمت تأییدشدهٔ بروکر در result.price است.
  • ۱۰۰۱۰ (TRADE_RETCODE_DONE_PARTIAL): فقط بخشی از حجم پر شد؛ مثلاً با نوع پرشدن IOC.
  • ۱۰۰۰۸ (TRADE_RETCODE_PLACED): سفارش ثبت شد و معامله بعداً انجام می‌شود.
  • ۱۰۰۰۴ (TRADE_RETCODE_REQUOTE): ری‌کوت؛ قیمت‌های تازه در result.bid و result.ask است.
  • ۱۰۰۲۰ (TRADE_RETCODE_PRICE_CHANGED): قیمت عوض شده است.
  • ۱۰۰۲۱ (TRADE_RETCODE_PRICE_OFF): قیمتی برای پردازش درخواست وجود ندارد.

بعد از ری‌کوت یا تغییر قیمت، یکی دو تلاش دوباره با قیمت تازه کافی است. حلقهٔ بی‌سقف تلاش در لحظهٔ خبر، پشت سر هم سفارش می‌فرستد و معامله را در بدترین قیمت باز می‌کند. مدیریت کامل خطاها در مدیریت خطاهای OrderSend در ربات آمده است.

اسلیپیج واقعی را اندازه بگیرید

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

نمونهٔ زیر یک خرید بازار با سقف deviation می‌فرستد و فقط بعد از ری‌کوت یا تغییر قیمت دوباره تلاش می‌کند. اسلیپیج هر معامله را بر حسب پوینت ثبت می‌کند. وقتی میانگینش از حد شما بیشتر شد، تابع دوم می‌گوید ورود تازه را متوقف کنید:

// Market buy with a deviation limit, two retries on requotes and a slippage log in points.
#include <Trade/Trade.mqh>

input ulong  InpDeviationPoints = 10;  // accepted price deviation, in points
input int    InpMaxRetries      = 2;   // new attempts after a requote or a price change
input double InpMaxAvgSlippage  = 15;  // average slippage that stops new entries, in points

CTrade trade;
double slipSum   = 0;
int    slipCount = 0;

bool BuyWithDeviation(const double lots)
{
   trade.SetDeviationInPoints(InpDeviationPoints);
   ENUM_SYMBOL_TRADE_EXECUTION mode =
      (ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE);

   for(int attempt = 0; attempt <= InpMaxRetries; attempt++)
   {
      double asked = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      trade.Buy(lots, _Symbol, asked);
      uint rc = trade.ResultRetcode();

      if(rc == TRADE_RETCODE_DONE || rc == TRADE_RETCODE_DONE_PARTIAL)
      {
         double slip = (trade.ResultPrice() - asked) / _Point;  // above zero: worse than asked
         slipSum += slip;
         slipCount++;
         PrintFormat("buy at %s, asked %s, slippage %.1f points, mode %s",
                     DoubleToString(trade.ResultPrice(), _Digits),
                     DoubleToString(asked, _Digits), slip, EnumToString(mode));
         return true;
      }
      if(rc == TRADE_RETCODE_PLACED)
      {
         Print("order placed, the deal comes later: read DEAL_PRICE in OnTradeTransaction");
         return true;
      }
      if(rc != TRADE_RETCODE_REQUOTE && rc != TRADE_RETCODE_PRICE_CHANGED)
      {
         PrintFormat("buy refused: %u %s", rc, trade.ResultRetcodeDescription());
         return false;  // a new attempt at once does not fix other errors
      }
      Sleep(300);       // wait for a fresh quote before trying again
   }
   return false;
}

// Call before each new entry: true once 20 fills average more than the limit.
bool SlippageTooHigh()
{
   return slipCount >= 20 && slipSum / slipCount > InpMaxAvgSlippage;
}

اگر پاسخ سرور ۱۰۰۰۸ باشد، معامله بعداً انجام می‌شود. قیمتش را در OnTradeTransaction از DEAL_PRICE بخوانید.

Deviation را چقدر بگذاریم؟

  • با هدف سود هر معامله بسنجید: رباتی که هدفش ۸ پیپ است، تحمل ۵ پیپ اسلیپیج را ندارد. رباتی روندی با هدف ۱۰۰ پیپ، چند پوینت را راحت تحمل می‌کند.
  • میان دو خطر تعادل بگیرید: deviation خیلی کوچک یعنی ری‌کوت پشت ری‌کوت و ورودهای ازدست‌رفته. deviation خیلی بزرگ یعنی پذیرفتن قیمت‌های بد.
  • عدد را از اندازه‌گیری بگیرید: چند صد معامله‌ای را که اکسپرت روی حساب واقعی با حجم کم ثبت کرده ببینید، بعد سقف را تعیین کنید. اسپرد عادی نماد (SYMBOL_SPREAD، بر حسب پوینت) هم نقطهٔ شروع خوبی برای مقایسه است.

وقتی اجرای بازار است: اسلیپیج را چطور کم کنیم

  • لحظهٔ خبر را رد کنید: چند دقیقه پیش و پس از خبرهای مهم، اسلیپیج و اسپرد بیشترند. روشش در غیرفعال کردن معامله در زمان اخبار آمده است.
  • فیلتر اسپرد: اگر اسپرد لحظه‌ای چند برابر حالت عادی است، وارد نشوید. ساعت رول‌اور، حوالی نیمه‌شب سرور بروکر، معمولاً اسپرد بالایی دارد.
  • سفارش لیمیت به‌جای بازار: سفارش Buy Limit یا Sell Limit با قیمت خودش یا بهتر پر می‌شود، ولی ممکن است اصلاً پر نشود. این را باید در منطق استراتژی پذیرفت. تفاوتش با سفارش بازار را در نقش Market Order در ربات معامله‌گر نوشته‌ایم.
  • فاصلهٔ سرور تا بروکر: هر تأخیری یعنی قیمت فرصت بیشتری برای جابه‌جا شدن دارد. سرور مجازی نزدیک سرور بروکر این فاصله را کم می‌کند: مزایا و معایب VPS برای ربات.
  • حد ضرر هم اسلیپیج دارد: حد ضرر وقتی فعال شد با قیمت بازار اجرا می‌شود و در بازار پرشتاب ممکن است بدتر از قیمت خودش بسته شود. در محاسبهٔ ریسک، کمی جا برایش بگذارید.

اشتباه‌های رایج

  • deviation صفر در اجرای فوری: هر جابه‌جایی کوچک قیمت ری‌کوت می‌دهد.
  • اعتماد به deviation روی حسابی با اجرای بازار، در حالی که آنجا قیمت را بروکر تعیین می‌کند.
  • قاطی کردن پیپ و پوینت روی نمادهای ۳ و ۵ رقمی: سقفی که فکر می‌کنید یک پیپ است، یک‌دهم پیپ می‌شود.
  • تلاش دوباره بی‌سقف بعد از ری‌کوت.
  • نخواندن result.price و فرض اینکه معامله با قیمت درخواستی باز شده است. نتیجهٔ بک‌تست و حساب واقعی همین‌جا از هم دور می‌شوند. مدل کردن اسلیپیج در خود بک‌تست را در تاثیر اسپرد و اسلیپیج در بک‌تست ببینید.

برای سفارش ربات

اگر اکسپرتی می‌خواهید که اسلیپیج را ثبت کند و با آن تصمیم بگیرد، این‌ها را بفرستید:

  • بروکر و نوع حساب، و اگر می‌دانید، حالت اجرای نماد؛
  • نمادها؛
  • هدف سود و حد ضرر معمول استراتژی.

فاصلهٔ نتیجه‌های دمو و حساب واقعی را در تفاوت تنظیمات ربات در دمو و حساب واقعی توضیح داده‌ایم. مسیر ثبت درخواست در سفارش ربات متاتریدر آمده است.

جمع‌بندی

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

هشدار ریسک: این مطلب جنبه آموزشی دارد و توصیه سرمایه‌گذاری نیست. معامله در بازارهای مالی با ریسک از دست دادن سرمایه همراه است و نتایج گذشته یا بک‌تست تضمینی برای آینده نیست.

نویسنده

تیم متااکسپرت در طراحی و برنامه‌نویسی ربات‌های معامله‌گر و اکسپرت‌های متاتریدر با MQL4 و MQL5 تخصص دارد و تجربه‌های عملی خود را در قالب این مقالات منتشر می‌کند.

دیدگاه‌ها

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

کد امنیتی