یک قالب جهانی برای اکسپرت متاتریدر

یک قالب جهانی برای اکسپرت

یک قالب جهانی برای اکسپرت

بسیاری از تریدرها با این مشکل مواجه هستند که مجبورند اکسپرت خودشان را بنویسند.  چه اتفاقی می‌اُفتد؟ حد سود را در کد اکسپرت چگونه تعیین کنیم؟ حد ضرر و تریلینگ اِستاپ را چطور؟ چگونه مفید بودنِ یک استراتژی را بررسی کنیم؟ در این مقاله به بررسی توابع اصلی جهت ساخت یک اکسپرت می‌پردازیم. شاید مثلاً کد تریلینگ به‌درد کسی بخورد…

متغیرهای اکسپرت

چه متغیرهایی در هر اکسپرت نیاز هستند؟ چه باید بکنیم که تستر پارامترها را نیز بررسی کند؟ – پارامترهایی که توسط متغیرهای منطقی (bool) تعیین شده‌اند. اول، می‌خواهم یک کد اکسپرت کلی را معرفی کنم که با تمام اَرزها کار می‌کند، برای سرعت‌های بالاتر، پیشنهاد می‌شود متغیرها را متناسب با نوع اَرز خود تنظیم کنید. دوم، ۰ برای غیرفعال، و ۱ برای فعال (زیرا می‌خواهیم تمام پارامترها را در یک بهینه‌ساز بررسی کنیم. اگر کد نهایی خیلی کم بهینه‌سازی شد، پیشنهاد می‌کنیم که این پارامتر را تغییر دهید). سوم اینکه، متغیرهای خطوط (اِستاپ‌)، توسط اعداد صحیح، مقداردهی اولیه می‌شوند، و در کد، جاییکه نیاز باشد، به اعداد کسری تغییر می‌کنند. در حالت واقعی روی اَرزهای مختلف ترید می‌کنیم و در اینجا هم یک قالب داریم [که این کار را انجام می‌دهد]! چهارم، اگر پارامترهای اِستاپ برابر با صفر باشند، اِستاپ‌ها کار نخواهند کرد!

تعریف متغیرها

اکنون بیایید تعریف متغیرها را شروع کنیم. با آن‌هایی شروع می‌کنیم که متمایل به بهینه‌سازی و قابل اطمینان هستند – یعنی متغیرهای اکسترنال.

extern double MaxLot;
extern double TakeProfit;
extern double TrailingStop;
extern double StopLoss;
extern double MinProfit;
extern double ProfitPoints;
extern int    Slippage=0;
extern int Condition1=1;
extern double LotSpliter=1.0;
extern int CloseByOtherSideCondition;

وقتی می‌خواهیم محدودیتی برای حداکثر لاتیج مورد استفاده بگذاریم، متغیر MaxLot حداکثر مقدار لات را تعیین خواهد کرد (آنگاه سِرور لاتیج را محدوود می‌کند، اما در این‌باره بعداً صحبت می‌کنیم). وقتی حد سود، حد ضرر و تریلینگ اِستاپ [مقداری] بیشتر از صفر داشته باشند، در کد ما فعال خواهند بود و عمل خواهند کرد.

وقتی ProfitPoints مقداری بیش از صفر داشته باشد، MinProfit و ProfitPoints هم عمل خواهند کرد؛ و همه‌ی این‌ها طبق این اصل است: قیمت به ProfitPoints می‌رسد و تا MinProfit برمی‌گردد.

ConditionX شرایط ورود را فعال می‌کند.

LotSpliter تقسیم‌کننده‌ی لات‌ها است، و فقط از بخشی از لات‌های موجود، استفاده می‌کند، برای مثال ۰.۱، که فقط آنقدری را شامل می‌شود که ۱۰ مرتبه کوچک‌تر است از مقدار دردسترس برای کل سرمایه.

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

‌حال برویم سراغ متغیرهای داخلی، که البته آن‌ها را همراه با توضیح اکسپرت، ارائه‌ می‌کنیم.

double Lot;
double PP=0;
double slu,sld,a,b;
double tp,sl;

کد مقداردهی اولیه

اکنون بیایید ببینیم، چه چیز را می‌توان فقط با شروع یک اکسپرت محاسبه، و بعداً درون یک کد از آن استفاده کرد.

int init()
  {
   tp=TakeProfit;
   sl=StopLoss;
   return(0);
  }

از مقادیر این متغیرها برای تغییرات خطوط اِستاپ (stop levels) استفاده می‌کنیم. اگر بخواهیم همیشه با لاتیج یکسان کار کنیم، می‌توانیم [مقدار] یک لات را هم محاسبه کنیم، و مقدار مازاد را نشان دهیم (بعداً در مقاله، محاسبه‌ی لاتیج را آنالیز می‌کنیم). همچنین می‌توانیم یک کامنت قابل نمایش ایجاد کنیم که حاوی توضیح اکسپرت یا کپی‌رایت باشد. این کار را اینگونه انجام می‌دهیم:

Comment("cloud trade \n v2.0.11");

“\n” – یعنی رفتن به خط نمایش بعدی، “carriage return”.

کد فریم‌ورک

وقتی هیچ‌ معامله‌ای نداریم، کد، بدین شکل خواهد بود:

if(OrdersTotal()==0)
   {   
      preinit();
      if(U()==1)
      {
         OrderBuy();
         return(0);
      }
      if(U()==2)
      {
         OrderSell();
         return(0);
      }
      return(0);
   }

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

اکنون، بیایید کد را در حالتی ببینیم که یک معامله داریم:

if(OrderType()==OP_BUY)
        {
         if((slu)>PP)
           {
            PP=slu;
           }
         if(((slu)>0.001) && (OrderStopLoss()<(b-TrailingStop))
          && (OrderOpenPrice()<(b-TrailingStop))
           && (OrderProfit()>MathAbs(OrderSwap())))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, b-TrailingStop, 0, 0, 0);
              }
           }
        }
      if(OrderType()==OP_SELL)
        {
         if((sld)>PP)
           {
            PP=sld;
           }
         if(((sld)>0.001) && (OrderStopLoss()>(a+TrailingStop))
          && (OrderOpenPrice()>(a+TrailingStop)))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, a+TrailingStop, 0, 0, 0);
              }
           }
        }
      if(ProfitPoints!=0)
        {
         if(OrderType()==OP_BUY && PP>=ProfitPoints && (slu)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && PP>=ProfitPoints && (sld)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }
      if(CloseByOtherSideCondition==1)
        {
         if(OrderType()==OP_BUY && U()==2)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && U()==1)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }

در ابتدا فقط، تنها معامله‌ی موجود را برای انجام کارهای بیشتر روی آن، انتخاب می‌کنیم (این کد در یکی از بخش‌های مقاله، جداگانه آنالیز خواهد شد). آنگاه متغیرها را به قیمت‌ها اختصاص می‌دهیم، تا معامله، برای مثال، در یک تریلینگ اِستاپ در جهت اشتباه، یا در قیمت‌های جدید که سودده نیستند، تغییر نکند. ابتدا باید معامله را از نظر احتمال تریلینگ اِستاپ بررسی کنیم، و در همین زمان برای تابع بعدی، یعنی minimal profit که کاربرد آن را قبل‌تر توضیح دادیم، داده جمع‌آوری کنیم. سپس تابعِ بستن یک معامله هنگامی که شرایط برعکس انتظار است، و بازشدن یک معامله‌ی جدید مطابق با روند جدید (بازشدن معامله‌ی جدید در جهت عکسِ معامله‌ی قبلی) را داریم.

وابعی که در مقاله تحلیل شدند

اکنون بیایید توابعی را با هم ببینیم که برای کوتاه کردن کد، درنظر گرفته شده‌اند؛ همچنین این توابع فرمان‌هایی (Commands) که بیشترین استفاده‌ها از آن‌ها می‌شود را درون بلوک‌ها جای می‌دهند، بطوریکه بعداً می‌توان آن‌ها را بلوک‌های کامل نامید. بیایید چنین شرایطی را تعریف کرده و آن‌ها را بررسی کنیم:

//+------------------------------------------------------------------+
//|  returns a signal to buy or to sell                              |
//+------------------------------------------------------------------+
int U()
  {
      if((U1()==2 && Condition1==1)
       || (U2()==2 && Condition2==1)){return(2);}
      if((U1()==1 && Condition1==1)
       || (U2()==1 && Condition2==1)){return(1);}
   return(0);
  }
//+------------------------------------------------------------------+
//|  returns a signal based on stochastic values                     |
//+------------------------------------------------------------------+
int U1()
  {
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)>=80)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)
           >=iStochastic(Symbol(),Period(),
              Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(2);
           }
        }
     }
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)<=20)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           >=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)
              <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(1);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| find trend direction using fractals                              |
//+------------------------------------------------------------------+
int U2()
  {
   double fu=0,fd=0;
   int f=0,shift=2;
   while(f<2)
     {
      if(iFractals(Symbol(),Period(),MODE_UPPER,shift)>0)
        {
         fu=fu+1;
         f=f+1;
        }
      if(iFractals(Symbol(),Period(),MODE_LOWER,shift)>0)
        {
         fd=fd+1;
         f=f+1;
        }
      shift=shift+1;
     }
   if(fu==2){return(2);}
   if(fd==2){return(1);}
   return(0);
  }

اولین تابع، شرایط را بررسی می‌کند، و دو تابع بعدی شرایط را تعیین می‌کنند.

اکنون بیایید تابعی را با هم ببینیم، که stop level‌ها را، اگر اشتباه تعیین شده‌ باشند، محاسبه، و مقدار یک لات را نیز تعیین می‌کند:

//+------------------------------------------------------------------+
//| preliminary initialization of variables                          |
//+------------------------------------------------------------------+
int preinit()
  {
   Lot=NormalizeDouble(MathFloor(LotSpliter*AccountBalance()*AccountLeverage()
      /Ask/MathPow(10,Digits+1)*10)/10,1);
   if(MaxLot>0 && Lot>MaxLot){Lot=MaxLot;}
   if(Lot>MarketInfo(Symbol(),MODE_MAXLOT)){Lot=MarketInfo(Symbol(),MODE_MAXLOT);}
   PP=0;
   StopLoss=sl;
   TakeProfit=tp;
   if(TakeProfit!=0 && TakeProfit<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      TakeProfit=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   if(StopLoss!=0 && StopLoss<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      StopLoss=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   return(0);
  }

اکنون توابع را تعیین می‌کنیم، تا معاملات بر اساس stop levelهای از پیش تعیین‌شده، باز شوند:

//+------------------------------------------------------------------+
//| returns true in case of a successful opening of Buy              |
//+------------------------------------------------------------------+
bool OrderBuy()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4),
        NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage, 0,
       NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask,
       Slippage, 0, 0, 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4), 0, 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }
//+------------------------------------------------------------------+
//|   returns true in case of a successful opening of Sell           |
//+------------------------------------------------------------------+
bool OrderSell()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }

تابع بعدی یک معامله را با یک تیکت مشخص‌شده، حجم و قیمت مشخص‌شده، می‌بندد:

//+-------------------------------------------------------------------------+
//|  returns true in case of a successful closing of an order with Ticket   |
//+-------------------------------------------------------------------------+
bool CloseOnlyOrder(int Ticket, double Lots ,double priceClose)
  {
   bool res=false;
   res=OrderClose(Ticket, Lots, priceClose, Slippage, 0);
   return(res);

اکنون بیایید تابع انتخاب یک معامله با شماره‌ی پوزیشن، جهت عملیات بیشتر روی آن‌ را، با هم ببینیم:

//+--------------------------------------------------------------------------------+
//| returns true in case of a successful choosing of an order in the position pos  |
//+--------------------------------------------------------------------------------+
bool SelectOnlyOrder(int pos)
  {
   bool res=false;
   res=OrderSelect(pos,SELECT_BY_POS,MODE_TRADES);
   return(res);
  }
//+------------------------------------------------------------------+

چند توصیه برای کدنویسی

اول از همه، به‌جای true و false، آپشن‌های ۰ و ۱ پیش روی خود بگذارید. این کار به شما کمک می‌کند اکسپرت خود را بهتر بهینه‌سازی کنید. دوم، وقتی بازار در جهت مخالفِ شرایط حرکت می‌کند، از Stop Loss جهت محدود کردن ضررهای ممکن، صرف‌نظر نکنید. سوم، اکسپرت‌ها را بدون Stop Loss تست نکنید، این کار ممکن است سریعاً سرمایه‌ی شما را از بین ببرد. چهارم، از توابع و بلوک‌هایی استفاده کنید که به شما کمک می‌کنند فهمیدن کد را آسان‌تر کنید.

نتیجه‌گیری

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

این مقاله دارای فایل پیوست است.

فایل پیوست مقاله را از اینجا میتوانید دانلود کنید .

 

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

M23admin

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

اکسپرت‌هایی برمبنای استراتژی‌های محبوب ترید و کیمیای بهینه‌سازی ربات ترید

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

چگونه در MQL4 یک ربات ترید سالم و قابل اطمینان را توسعه دهیم

۲۳ مورد نظر

نوشتن نظر شما

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