بِرک‌پوینت‌ها در تستر: غیرممکن نیست…

بِرک‌پوینت‌ها در تستر: غیرممکن نی

بِرک‌پوینت‌ها در تستر: غیرممکن نیست…

تنها چیزی که در MQL4 دلم برای آن تنگ می‌شود، اِشکال‌زدایی معمولی اکسپرت است. تمام انسان‌ها عواطف انسانی دارند، بنابراین، اشتباه ممکن است رخ دهد. در برنامه‌نویسی عادی، برک‌پوینت‌ها را تعیین می‌کنیم، برنامه را اجرا کرده و سپس، وقتی کار به برک‌پوینت می‌رسد، متوقف می‌شود. بنابراین می‌توانیم نگاهی بر محتوای متغیرهایی که راه‌انداز ما هستند، داشته باشیم.

نمایش داده‌های اِشکال‌زدایی به‌لطف توابعی مانند Print، Comment، و غیره، حالا دیگر ممکن شده‌است. اما بعضی‌وقت‌ها ممکن است بخواهیم برنامه را به‌صورت موقت، در جاهای خاص و در لحظه‌ای خاص، متوقف کرده، تا شرایط را بازبینی کنیم. جزئیات زیادی در اینجا هست… معمولاً برنامه برای ترید روی حساب دِمو یا حساب واقعی اجرا می‌شود. و این یعنی فقط قادر هستیم نتایجِ چندین ماه را ببینیم… از این رو، حالت اِشکال‌زدایی فقط در حالت تست اکسپرت (در تستر) معقولانه و منطقی است.

چگونه کار میکند…

از آن زمانی که حالت “تست ویژوال” به تستر اضافه شد، پیگیری پاسخ‌های اکسپرت حین گذر سریع برنامه، در تستر، برای ما ممکن شد. اگر بخواهیم کار را موقتاً متوقف کنیم، دکمه‌ی “Pause” را روی کیبورد می‌زنیم یا با موس، روی همین گزینه در نوارابزار تستر کلیک می‌کنیم. توسعه‌دهندگان نرم‌افزار ، کتابخانه‌ای را فرآهم کرده‌اند با نام WinUser32.mqh، که شامل برخی از توابع بسیار جالب است. یکی از این توابع keybd_event است. و به ما اجازه می‌دهد هر دکمه‌ای که دوست داشته باشیم را، بفشاریم.

این ایده آن زمان به‌نوعی شیر یا خط شد – می‌توانیم تابعی بنویسیم که pause را برنامه‌ریزی‌شده بفشارد و اطلاعات مورد نیاز مربوط به اِشکال‌زدایی را، چاپ کند. از آنجایی که اکسپرت ما از DLL استفاده می‌کند، باید ابتدا این قابلیت را در اکسپرت فعال کنیم. Ctrl+O را می‌زنیم و چک‌باکس‌ها را انتخاب/لغوِ انتخاب می‌کنیم:

بِرک‌پوینت‌ها در تستر: غیرممکن نی
بِرک‌پوینت‌ها در تستر: غیرممکن نیست…

آنگاه باید جایی در ابتدای کد، استفاده از WinUser32 را اعلام کنیم:

#include <WinUser32.mqh>

بعد از این کار، اعلام خودِ تابع BreakPoint را داریم. جزئیات دیگری هم در اینجا هست اما ساده‌ترین تحقق، فرض را بر این می‌گذارد که هیچ پارامتر عبورکرده/برگشت‌داده‌شده نداریم:

void BreakPoint()

این تابع باید فقط در حالت ویژوال تست، فعال شود، بنابراین، برای این تابع یک گزینه‌ی بررسی می‌گذاریم: اگر تستر در حالت ویژوال تست نبود، رهایش می‌کنیم:

if (!IsVisualMode()) return(0);

آنگاه برخی از داده‌ها را تصویرسازی (Visualize) می‌کنیم. به‌نظر من، توصیفی‌ترین حالت، استفاده از Comment() خواهد بود. فرض را بر این بگذارید که فقط به Bid و Ask نیاز داریم.

string Comm="";
Comm=Comm+"Bid="+Bid+"\n";
Comm=Comm+"Ask="+Ask+"\n";
   
Comment(Comm);

“\n” در اینجا یعنی داده‌هایی که در ادامه می‌آیند، در رشته‌ی بعدی نشان داده می‌شوند. در آخر، بیایید Pause را بفشاریم.

keybd_event(19,0,0,0);
Sleep(10);
keybd_event(19,0,2,0);

اولین رشته، دکمه را می‌فشارد، درحالیکه آخرین رشته، آن را آزاد می‌کند. دکمه‌ی Sleep هم در اینجا نیاز است. زیرا ممکن است بر اثر سریع زدنِ دکمه‌ی Pause، هیچ اتفاقی نیفتد (به‌نوعی حواس‌مان نباشد و سریع دکمه را بزنیم و به‌خاطر سریع زدن، کار دُرست انجام نشود). ۱۹، کد مجازی توقف (pause) است، و ۲ در رشته‌ی آخر نشان می‌دهد که [دکمه‌ی] آزادسازی باید شبیه‌سازی شود.

تمام کاری که الان باید بکنیم این است که برک‌پوینت را در کد اکسپرت، جایگزین کنیم، آن‌هم بلافاصله بعد از آنکه پوزیشن بلندمدت، یا همان مثال مقاله‌ی Expert Advisor Sample، باز شد.

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
BreakPoint();

در اینجا کد کامل را جهت وارد کردن، مشاهده می‌کنید:

//We will use a function, described in header file
#include 
 
//Breakpoint neither receive nor send back any parameters
void BreakPoint()
{
   //It is expecting, that this function should work
   //only in tester
   if (!IsVisualMode()) return(0);
   
   //Preparing a data for printing
   //Comment() function is used as 
   //it give quite clear visualisation
   string Comm="";
   Comm=Comm+"Bid="+Bid+"\n";
   Comm=Comm+"Ask="+Ask+"\n";
   
   Comment(Comm);
   
   //Press/release Pause button
   //۱۹ is a Virtual Key code of "Pause" button
   //Sleep() is needed, because of the probability
   //to misprocess too quick pressing/releasing
   //of the button
   keybd_event(19,0,0,0);
   Sleep(10);
   keybd_event(19,0,2,0);
}

برای نظارت بر متغیرهای لوکال چه کاری باید انجام دهیم؟

مشکل در “قابل رویت نبودنِ” چنین متغیرهایی در خارج از اعلام‌های آن‌ها است. در این شرایط، داده‌ها باید منتقل شوند (عبور کنند). فرض کنید، می‌خواهیم متغیر MacdCurrent را از همان مقاله که کمی قبل‌تر گفته شد، رصد کنیم. برای انجام این کار، تابع را اینگونه اصلاح می‌کنیم:

void BreakPoint(double MacdCurrent)
{
   if (!IsVisualMode()) return(0);
nbsp;  
   Comment("MacdCurrent = ",MacdCurrent);

برکپوینتهای انتخابی

شاید بعضی‌وقت‌ها آرزو کنیم ای کاش برنامه وقتی به یک رشته‌ی خاص می‌رسد، همیشه توقف نداشته باشد، بلکه توقفش زمانی باشد که الزام‌های اضافی، دیده شوند. این اتفاق معمولاً در حلقه‌ها می‌اُفتد. برای مثال، می‌خواهیم روند اجرایی، وقتی شمارنده به مقدارِ از پیش تعیین‌شده‌ی خاصی که می‌رسد، شکسته شود. برای این کار، می‌باستی یک الزام اضافی را منتقل کنیم:

void BreakPoint(double MacdCurrent, bool Condition)
{
nbsp;  if (!IsVisualMode() || (!Condition)) return(0);
nbsp;  //Or - which is the same:
   //if (!(IsVisualMode()&&Condition)) return(0);
   
   Comment("MacdCurrent = ",MacdCurrent);

فراخوانی آن به این شکل است:

for(cnt=0;cnt<total;cnt++)     
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      BreakPoint(MacdCurrent, cnt==1);

نتیجهگیری

حال چرا نمی‌آییم کتابخانه‌ای بسازیم، آن را به برنامه وصل کنیم و از آن استفاده کنیم؟ موضوع این است که حالت‌های بسیار زیادی داریم، که برای آن‌ها بهتر است، تابع BreakPoint را اصلاح کنیم. علاوه بر این‌ها، تمام مطالبی که در بالا گفته شدند، فقط ایده‌ی کلی هستند. می‌توان به شکل‌های بسیار زیادی این مطالب را به‌کار بست.

در پایان، می‌خواهم از Klot تشکر کنم که اولین بار او بود که حدس زد چگونه می‌شود Pause‌زدن را برنامه‌ریزی‌شده، انجام داد.

 

مقالات پیشنهادی :

M23admin

→ خواندن مطلب قبلی

ویژگی‌ها و محدودیت‌های تست گرفتن در متاتریدر ۴

خواندن مطلب بعدی ←

خطای ۱۴۶ (“TRADE CONTEXT BUSY”) و چگونگی کنار آمدن با آن

۳۴ مورد نظر

نوشتن نظر شما

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