برای بهینه سازی Expert Advisors (بهینه سازی اکسپرت ) با استفاده از موتور PSO، لازم است برنامه هایی را که میتوانند معاملات را بر اساس تاریخ بر روی مجموعهای از پارامترهای ورودی شبیه سازی کرده و آمار را محاسبه کنند، پیاده سازی کنید.
مجازی سازی و بهینه سازی (Expert Advisors (MQL4 API در MetaTrader 5
این مسئله معضلی را برای بسیاری از توسعه دهندگان برنامه هنگامی که بهینه ساز خود را روی و / یا به جای نسخه استاندارد مینویسند، ایجاد می کند. چگونه میتوان یک محیط معاملاتی، شامل اول از همه، قیمتها و همچنین وضعیت حساب و بایگانی معاملات را فراهم کرد؟ اگر از حالت محاسبات ریاضی استفاده شود، باید به نوعی داده های مورد نیاز را به Expert Advisor (به عوامل) منتقل کنیم. این امر مستلزم ایجاد یک لایه میانی API است که “به طور شفاف” بسیاری از عملکردهای معاملهای را تقلید میکند – این به بهینه سازی Expert Advisors اجازه میدهد تا مانند حالت معمول آنلاین کار کند.
برای جلوگیری از این مسئله، من تصمیم گرفتم از یک راه حل معامله مجازی موجود استفاده کنم که کاملاً در MQL ایجاد شده و از ساختار داده های استاندارد قبلی، به ویژه tickها و bar ها استفاده کرده است. این کتابخانه مجازی توسط fxsaber است. این امکان را میدهد که مجوز یک بهینه سازی Expert Advisors در مورد تاریخچه موجود هم به صورت آنلاین (به عنوان مثال برای خود بهینه سازی دوره ای در نمودار) و هم در تستر، پاس مجازی را محاسبه کنید. در حالت دوم، ما میتوانیم از هر حالت معمول tick (“هر tick ” ، “هر tick بر اساس tick های واقعی”) یا حتی “OHLC در ” M1 – برای تخمین سریع، اما تقریبیتر سیستم استفاده کنیم (فقط 4 tick در دقیقه).
پس از قرار دادن فایل هدر Virtual.mqh (با وابستگی های لازم بارگیری میشود) در کد EA، میتوان با استفاده از خطوط زیر آزمایش مجازی را به راحتی سازمان داد:
MqlTick _ticks[]; // global array ... // copy/collect ticks[] VIRTUAL::Tester(_ticks, OnTick /*, TesterStatistics(STAT_INITIAL_DEPOSIT)*/ ); Print(VIRTUAL::ToString(INT_MAX)); // output virtual trades in the log const double result = TesterStatistics(STAT_PROFIT); // get required performance meter VIRTUAL::ResetTickets(); // optional VIRTUAL::Delete(); // optional
تمام عملیات با استفاده از روش استاتیک VIRTUAL :: Tester انجام میشود. داده های زیر باید به این روش منتقل شوند: یک آرایه از پیش پر شده از tick ها از دوره تاریخی و جزئیات مورد نظر، یک اشاره گر برای تابع OnTick ( اگر حاوی منطق تغییر معامله آنلاین به مجازی باشد، میتوانید از یکhandler استاندارد استفاده کنید)، و سپرده اولیه (اختیاری است – اگر سپرده مشخص نشده باشد، از مانده حساب جاری استفاده میشود. اگر قطعه فوق در handler OnTester قرار گیرد (ما آن را در آنجا قرار خواهیم داد)، سپرده اولیه تستر قابل پاس است. برای اطلاع از نتیجه معاملات مجازی، تابع آشنای TesterStatistics را فراخوانی کنید، که بعد از اتصال کتابخانه، مانند بسیاری دیگر از توابع MQL API واقعاً “همپوشانی شده” است (در صورت تمایل میتوانید کد منبع را بررسی کنید) این “همپوشانی” به اندازه کافی هوشمند است که میتواند فراخوان ها را به تابع هسته اصلی که در آن معامله انجام میشود منتقل کند. لطفا توجه داشته باشید که تمام شاخص های استاندارد TesterStatistics در هنگام تجارت مجازی در کتابخانه محاسبه نمیشوند.
توجه داشته باشید که این کتابخانه براساس API معاملاتی MetaTrader 4 ساخته شده است. به عبارت دیگر، این فقط برای Expert Advisor ها مناسب است که اگرچه با MQL5 نوشته شده اند، اما از توابع “قدیمی” در کد خود استفاده میکنند. آن ها می توانند در محیط MetaTrader 5 به لطف کتابخانه معروف دیگری توسط همین نویسنده -MT4Orders اجرا شوند.
آزمایش با استفاده از اصلاح ExprBot.mq5 EA انجام می شود، که در اصل در مقاله محاسبه عبارات ریاضی (قسمت 2) ارائه شده است. EA با استفاده از MT4Orders اجرا میشود. نسخه جدیدی به نام ExprBotPSO.mq5 در پیوست موجود است.
Expert Advisor از موتور parser برای محاسبه سیگنال های معاملاتی بر اساس عبارات استفاده میکند. مزایای این بعداً توضیح داده خواهد شد. استراتژی معامله یکسان است: تقاطع دو میانگین متحرک، با در نظر گرفتن آستانه واگرایی مشخص شده. در اینجا تنظیمات EA همراه با عبارات سیگنال وجود دارد:
input string SignalBuy = "EMA_OPEN_{Fast}(0)/EMA_OPEN_{Slow}(0) > 1 + Threshold"; input string SignalSell = "EMA_OPEN_{Fast}(0)/EMA_OPEN_{Slow}(0) < 1 - Threshold"; input string Variables = "Threshold=0.001"; input int Fast = 10; input int Slow = 21;
اگر در مورد نحوه جایگزینی متغیرهای ورودی در عبارات و چگونگی تلفیق توابع EMA داخلی با شاخص مربوطه سوالی دارید، مطالعه مقاله ذکر شده را توصیه میکنم. ربات جدید از همان اصول استفاده میکند. کمی بهبود خواهد یافت.
بیشتر بخوانید : ثبت سفارش اندیکاتور و اکسپرت
علاوه بر پارامترهای ورودی برای سیگنال ها، که بعداً در مورد آنها بحث خواهیم کرد، EA دارای پارامترهایی برای مدیریت تست مجازی و الگوریتم PSO است.که عبارتند از:
- VirtualTester – فلگی که امکان تست مجازی و / یا بهینه سازی را فراهم میکند. به طور پیش فرض false است که به معنای عملکرد نرمال است.
- Estimator – متغیری که توسط آن بهینه سازی انجام میشود. به طور پیش فرض STAT_PROFIT است.
- InternalOptimization – فلگ بهینه سازی را در حالت مجازی امکان پذیر میکند. به طور پیش فرض false است، که به معنی معامله pass مجازی واحد است. True بهینه سازی داخلی را با استفاده از روش PSO آغاز میکند.
- PSO_Enable – PSO را فعال یا غیرفعال می کنید.
- PSO_Cycles – تعداد چرخه های محاسبه مجدد PSO در هر pass ؛ هرچه این مقدار بزرگتر باشد، کیفیت جستجوی PSO بهتر است، اما pass واحد بدون بازخورد (ورود به سیستم) طولانیتر اجرا میشود.
- PSO_SwarmSize – اندازه ازدحام؛ به طور پیش فرض 0 است که به معنای انتخاب تجربی خودکار بر اساس تعداد پارامترها است.
- PSO_GroupCount – تعداد گروه ها ؛ این یک پارامتر افزایشی برای سازماندهی چندین pass است – با مقدار 0 به تعداد هسته ها / عوامل شروع کنید و سپس افزایش دهید.
- PSO_RandomSeed – تصادفی سازی؛ شماره گروه در هر گروه به آن اضافه میشود، بنابراین همه آنها متفاوت شروع میشوند.
در حالت VirtualTester ، EA تیک های موجود در OnTick را در یک آرایه جمع میکند. سپس، در OnTester، کتابخانه Virtual با استفاده از این آرایه معامله میشود و همان OnTick handler را با یک فلگ تنظیم شده خاص فراخوانی میکند که امکان اجرای کد با عملیات مجازی را فراهم میکند.
بنابراین، چرخهای از PSO_Cycles از محاسبه مجدد ازدحام با اندازه ذرات PSO_SwarmSize برای هر مقدار PSO_GroupCount افزایش یافته اجرا میشود. بنابراین، ما نقاط PSO_GroupCount * PSO_Cycles * PSO_SwarmSize = N را در فضای بهینه سازی آزمایش میکنیم. هر نقطه یک اجرای مجازی از سیستم معاملاتی است.
برای دستیابی به بهترین نتیجه ، پارامترهای PSO مناسب را با استفاده از آزمون و خطا پیدا کنید. تعداد مولفه ها را میتوان برای تعداد N آزمایش تغییر داد. تعداد نهایی آزمایش ها کمتر از N خواهد بود زیرا به همان نقاط میتوان رسید (به یاد داشته باشید، نقاط در یک درخت باینری در ازدحام جمع میشوند)
عوامل فقط هنگام ارسال کار بعدی، دادهها را رد و بدل میکنند. وظایفی که به طور موازی اجرا میشوند، هنوز نتایج یکدیگر را نمی بینند و همچنین میتوانند چندین مختصات یکسان را با احتمال زیاد محاسبه کنند.
البته بهینه سازExspBotPSO Expert Advisor شامل کلاس های functor است که به طور کلی مشابه کلاس هایی است که در مثال های قبلی در نظر گرفتیم. اینها شامل متد “test” است که یک نمونه ازدحام ایجاد میکند، بهینه سازی را در آن انجام میدهد و نتایج را در متغیرهای عضو ذخیره میکند (optimum، result[]).
class BaseFunctor: public Functor { ... public: virtual bool test(void) { Swarm swarm(PSO_SwarmSize, PSO_GroupCount, params, max, min, steps); if(MQLInfoInteger(MQL_OPTIMIZATION)) { if(!swarm.restoreIndex()) return false; } optimum = swarm.optimize(this, PSO_Cycles); swarm.getSolution(result); if(MQLInfoInteger(MQL_OPTIMIZATION)) { swarm.exportIndex(PSO_GroupCount); } return true; } };
این اولین باری است که شاهد استفاده از متدهای restoreIndex و exportIndex هستیم که در بخش های قبلی شرح داده شده است. وظایف بهینه سازی Expert Advisor معمولاً به محاسبات زیادی احتیاج دارند (پارامترها و گروه ها، هر گروه یک tester pass است)، بنابراین عوامل نیاز به تبادل اطلاعات دارند.
آزمایش EA مجازی با توجه به ترتیب اعلام شده در متد ” calculate ” انجام میشود. یک کلاس جدید- Settings – وجود دارد که در مقداردهی اولیه فضای بهینه سازی استفاده می شود.
class WorkerFunctor: public BaseFunctor { string names[]; public: WorkerFunctor(const Settings &s): BaseFunctor(s.size()) { s.getNames(names); for(int i = 0; i < params; i++) { max[i] = s.get<double>(i, SET_COLUMN_STOP); min[i] = s.get<double>(i, SET_COLUMN_START); steps[i] = s.get<double>(i, SET_COLUMN_STEP); } } virtual double calculate(const double &vec[]) { VIRTUAL::Tester(_ticks, OnTick, TesterStatistics(STAT_INITIAL_DEPOSIT)); VIRTUAL::ResetTickets(); const double r = TesterStatistics(Estimator); VIRTUAL::Delete(); return r; } };
نکته این است که برای شروع بهینه سازی، کاربر پارامترهای ورودی EA را به روش معمول پیکربندی میکند. با این حال، الگوریتم swarm فقط برای موازی سازی کارها (با افزایش تعداد گروه) از tester استفاده میکند. بنابراین، EA باید بتواند تنظیمات پارامترهای بهینه سازی را بخواند، آنها را در یک فایل کمکی که به هر عامل ارسال میشود ذخیره کند، این تنظیمات را در tester تنظیم مجدد کند و بهینه سازی را با شماره گروه اختصاص دهد. کلاس Settings پارامترهای یک فایل کمکی را میخواند. فایل، ” ” EA_name.mq5.csv است، که باید با استفاده از یک دستورالعمل متصل شود.
#define PPSO_SHARED_SETTINGS __FILE__ + ".csv" #property tester_file PPSO_SHARED_SETTINGS
می توانید کلاس Settings را در پیوست مشاهده کنید. این یک خط فایل CSV را یکی یکی میخواند. این فایل باید دارای ستون های زیر باشد:
#define MAX_COLUMN 4 #define SET_COLUMN_NAME 0 #define SET_COLUMN_START 1 #define SET_COLUMN_STEP 2 #define SET_COLUMN_STOP 3
همه آنها در آرایه های داخلی به خاطر سپرده میشوند و از طریق متدهای “get” با نام یا index در دسترس هستند. متد isVoid () نشانهای از عدم تنظیمات را برمیگرداند (فایل قابل خواندن نیست، خالی است یا دارای فرمت wring است).
Settings در فایلی در OnTesterInit handler نوشته میشوند (به زیر مراجعه کنید).
من توصیه میکنم از قبل یک فایل خالی ” ” EA_name.mq5.csv را به صورت دستی در فولدر MQL5 / Files ایجاد کنید. در غیر این صورت، ممکن است با اولین تنظیم بهینه سازی مشکلاتی ایجاد شود.
متاسفانه، حتی اگر این فایل به طور خودکار در هنگام اولین شروع ایجاد شود، فایل را به عوامل نمیفرستد، به همین دلیل است که مقدار اولیه EA روی آنها با خطای INIT_PARAMETERS_INCORRECT خاتمه مییابد. یک راهاندازی مجدد بهینه سازی نیز آن را ارسال نخواهد کرد، زیرا tester اطلاعات مربوط به منابع متصل را ذخیره میکند و فایل تازه اضافه شده را تا زمانی که کاربر دوباره EA را در لیست کشویی تنظیمات tester انتخاب نکند، در نظر نمیگیرد. فقط پس از آن فایل میتواند به روز شود و برای عوامل ارسال شود. بنابراین، ایجاد فایل از قبل آسانتر است.
string header[]; void OnTesterInit() { int h = FileOpen(PPSO_SHARED_SETTINGS, FILE_ANSI|FILE_WRITE|FILE_CSV, ','); if(h == INVALID_HANDLE) { Print("FileSave error: ", GetLastError()); } MqlParam parameters[]; string names[]; EXPERT::Parameters(0, parameters, names); for(int i = 0; i < ArraySize(names); i++) { if(ResetOptimizableParam<double>(names[i], h)) { const int n = ArraySize(header); ArrayResize(header, n + 1); header[n] = names[i]; } } FileClose(h); // 5008 bool enabled; long value, start, step, stop; if(ParameterGetRange("PSO_GroupCount", enabled, value, start, step, stop)) { if(!enabled) { const int cores = TerminalInfoInteger(TERMINAL_CPU_CORES); Print("PSO_GroupCount is set to default (number of cores): ", cores); ParameterSetRange("PSO_GroupCount", true, 0, 1, 1, cores); } } // remove CRC indices from previous optimization runs Swarm::removeIndex(); }
تابع اضافی ResetOptimizableParam برای جستجوی پارامترهایی که فلگ بهینه سازی برای آنها فعال است و برای تنظیم مجدد این فلگها استفاده می شود. همچنین، در OnTesterInit، ما نام این پارامترها را با استفاده از کتابخانه Expert توسط fxsaber به خاطر میآوریم، که به شما امکان میدهد نتایج را به روش بصری شفافتری نمایش دهید. با این حال، کتابخانه در درجه اول مورد نیاز بود زیرا برای فراخوانی توابع استاندارد ParameterGetRange / ParameterSetRange ، name ها باید از قبل شناخته شوند، اما MQL API به شما اجازه نمیدهد لیستی از پارامترها را دریافت کنید. همچنین این کد جهانیتر میشود و بنابراین شما میتوانید این کد را بدون هیچ گونه تغییر خاصی در هر EA قرار دهید.
template<typename T> bool ResetOptimizableParam(const string name, const int h) { bool enabled; T value, start, step, stop; if(ParameterGetRange(name, enabled, value, start, step, stop)) { // disable all native optimization except for PSO-related params // preserve original settings in the file h if((StringFind(name, "PSO_") != 0) && enabled) { ParameterSetRange(name, false, value, start, step, stop); FileWrite(h, name, start, step, stop); // 5007 return true; } } return false; }
در OnInit handler ، که بر روی عامل اجرا میشود، settings از شی سراسری Settings به شرح زیر خوانده میشود:
Settings settings; int OnInit() { ... FileReader f(PPSO_SHARED_SETTINGS); if(f.isReady() && f.read(settings)) { const int n = settings.size(); Print("Got settings: ", n); } else { if(MQLInfoInteger(MQL_OPTIMIZATION)) { Print("FileLoad error: ", GetLastError()); return INIT_PARAMETERS_INCORRECT; } else { Print("WARNING! Virtual optimization inside single pass - slowest mode, debugging only"); } } ... }
همانطور که بعداً خواهید دید، این شی به شی WorkerFunctor ایجاد شده در handler OnTester handler منتقل میشود، که در آن تمام محاسبات و بهینه سازی انجام میشود. قبل از شروع محاسبات، ما باید tickها را جمعآوری کنیم. این کار در OnTester handler انجام میشود.
bool OnTesterCalled = false; void OnTick() { if(VirtualTester && !OnTesterCalled) { MqlTick _tick; SymbolInfoTick(_Symbol, _tick); const int n = ArraySize(_ticks); ArrayResize(_ticks, n + 1, n / 2); _ticks[n] = _tick; return; // skip all time scope and collect ticks } ... // trading goes on here }
چرا ما به جای فراخوانی تابع CopyTicksRange مستقیماً در OnTester از متد بالا استفاده میکنیم؟ در مرحله اول، این تابع فقط در حالتهای tick به tick کار میکند، در حالی که ما نیاز به پشتیبانی از حالت سریع OHLC M1 (4 tick در دقیقه) داریم. ثانیاً، اندازه آرایه برگشتی به دلایلی در حالت تولید tick به 131072 محدود شده است (هنگام کار با tickهای واقعی چنین محدودیتی وجود ندارد).
متغیر OnTesterCalled در ابتدا برابر با false است و بنابراین پیشینه tick جمعآوری میشود. OnTesterCalled بعداً، در OnTester، قبل از شروع PSO، روی true تنظیم میشود. سپس شی Swarm شروع به محاسبه functor در یک حلقه میکند، که در آن VIRTUAL :: Tester با اشاره به همان OnTick فراخوانی میشود. این بار، OnTesterCalled برابر با true خواهد بود و کنترل نه به حالت جمع آوری tick، بلکه به یک حالت منطقی معاملاتی منتقل میشود. کمی بعد این مورد بررسی خواهد شد. در آینده، با توسعه بیشتر کتابخانه PSO، مکانیزمهایی ممکن است ساده به نظر برسند که با جایگزینی OnTick handler در فایل header کتابخانه، ادغام در Expert Advisors موجود را ساده میکنند.تا آن زمان، از OnTester (به صورت ساده) استفاده میشود.
double OnTester() { if(VirtualTester) { OnTesterCalled = true; // MQL API implies some limitations for CopyTicksRange function, so ticks are collected in OnTick const int size = ArraySize(_ticks); PrintFormat("Ticks size=%d error=%d", size, GetLastError()); if(size <= 0) return 0; if(settings.isVoid() || !InternalOptimization) // fallback to a single virtual test without PSO { VIRTUAL::Tester(_ticks, OnTick, TesterStatistics(STAT_INITIAL_DEPOSIT)); Print(VIRTUAL::ToString(INT_MAX)); Print("Trades: ", VIRTUAL::VirtualOrdersHistoryTotal()); return TesterStatistics(Estimator); } settings.print(); const int n = settings.size(); if(PSO_Enable) { MathSrand(PSO_GroupCount + PSO_RandomSeed); // reproducable randomization WorkerFunctor worker(settings); Swarm::Stats stats; if(worker.test(&stats)) { double output[]; double result = worker.getSolution(output); if(MQLInfoInteger(MQL_OPTIMIZATION)) { FrameAdd(StringFormat("PSO%d/%d", stats.done, stats.planned), PSO_GroupCount, result, output); } ArrayResize(output, n + 1); output[n] = result; ArrayPrint(output); return result; } } ... return 0; } return TesterStatistics(Estimator); }
کد فوق ایجاد WorkerFunctor توسط مجموعهای از پارامترها از شی ‘ settings ‘ و راهندازی یک گروه با استفاده از متد ‘test’ آن را نشان میدهد. نتایج به دست آمده در یک به ترمینال ارسال میشود و در آنجا در OnTesterPass دریافت میشود.
OnTesterPass handler مشابه آنچه در تست PPSOی EA وجود دارد، است با این تفاوت که داده های دریافت شده در فریم ها نه در لاگ، بلکه در یک فایل CSV با عنوان PPSO-EA-name-date_time چاپ میشوند.
بگذارید در نهایت به استراتژی معاملاتی برگردیم. این تقریباً همان چیزی است که در مقاله Calculating Mathematical Expressions (قسمت 2) استفاده شده است. با این حال، برخی تنظیمات برای فعال کردن معامله مجازی مورد نیاز است. فرمول های سیگنال قبلی، شاخص های EMA را بر اساس قیمتهای باز در یک نوار صفر محاسبه میکنند:
input string SignalBuy = "EMA_OPEN_{Fast}(0)/EMA_OPEN_{Slow}(0) > 1 + Threshold"; input string SignalSell = "EMA_OPEN_{Fast}(0)/EMA_OPEN_{Slow}(0) < 1 - Threshold";
اکنون، آنها را باید از پیشینه barها بخوانید (زیرا محاسبات در انتهای pass، از OnTester انجام میشود). تعداد bar “فعلی” در گذشته را میتوان به راحتی تعیین کرد: کتابخانه Virtual ، تابع سیستم TimeCurrent را نادیده میگیرد و بنابراین میتوان موارد زیر را در OnTick نوشت:
const int bar = iBarShift(_Symbol, PERIOD_CURRENT, TimeCurrent());
شماره bar فعلی باید به عنوان متغیر، به عنوان مثال ” Bar ، به جدول متغیر عبارات اضافه شود، و سپس فرمولهای سیگنال را میتوان به صورت زیر نوشت:
input string SignalBuy = "EMA_OPEN_{Fast}(Bar)/EMA_OPEN_{Slow}(Bar) > 1 + Threshold"; input string SignalSell = "EMA_OPEN_{Fast}(Bar)/EMA_OPEN_{Slow}(Bar) < 1 - Threshold";
نسخه به روز شده parser ها هنگام تغییر متغیر (شماره bar) و محاسبه فرمول با این مقدار، فراخوانی میانی از متد “with” جدید (همچنین در OnTick) دارد:
const int bar = iBarShift(_Symbol, PERIOD_CURRENT, TimeCurrent()); // NEW bool buy = p1.with("Bar", bar).resolve(); // WAS: bool buy = p1.resolve(); bool sell = p2.with("Bar", bar).resolve(); // WAS: bool sell = p2.resolve();
به علاوه، کد معاملاتی OnTick تغییری ندارد.با این حال ، تغییرات بیشتری لازم است.
فرمول های فعلی از دورههای EMA ثابت مشخص شده در settings استفاده میکنند و در عبارات به متغیرها تبدیل میشوند. با این حال، دورهها باید در طول فرآیند بهینه سازی تغییر کنند، این به معنای استفاده از نمونه های مختلف شاخص است. مسئله این است که، بهینه سازی مجازی با تنظیم پارامترها توسط swarm، _درون_ گذر tester، در انتهای آن، در تابع OnTester انجام میشود. برای ایجاد indicator handles در اینجا خیلی دیر است.
این یک مشکل سراسری برای هرگونه بهینه سازی Expert Advisors مجازی است.
برای هرگونه مشکل سراسری بهینه سازی Expert Advisors مجازی سه راه حل وجود داد:
- اصلاً از شاخص ها استفاده نکنید؛ سیستمهای معاملاتی که از هیچ شاخصی استفاده نمیکنند در اینجا یک مزیت دارند.
- محاسبه شاخص ها به روش خاص، به طور مستقل در EA ؛ بسیاری از این روش استفاده میکنند زیرا این، حتی در مقایسه با شاخص های استاندارد، سریعترین راه است، اما بسیار پر کار است.
- از قبل مجموعهای از شاخص ها را برای همه ترکیبات پارامترها از settings ایجاد کنید. منابع فشرده ممکن است نیاز به محدود کردن دامنه پارامترها داشته باشد.
آخرین روش برای سیستم هایی که سیگنال ها را به صورت tick به tick محاسبه میکنند، مورد سوال است. در واقع، تمام barهای تاریخ مجازی از قبل بسته شدهاند و شاخص ها قبلاً محاسبه شدهاند. به عبارت دیگر، فقط سیگنال های bar در دسترس هستند. اگر سیستمی را بدون کنترل باز شدن bar بر روی چنین سابقهای اجرا کنیم، در مقایسه با tickهای غیر مجازی، معاملات بسیار کمتری با کیفیت پایین تر تولید میشود.
بهینه سازی Expert Advisors ما از طریق barها معامله میکند، بنابراین این مشکلی نیست. این وضعیت میتواند برای برخی از بهینه سازی Expert Advisors استاندارد در MetaTrader 5 معمول باشد – لازم است بدانید که چگونه یک رویداد باز شدن bar جدید شناسایی میشود. روش با یک کنترل حجم سیگنال tick برای سابقه مجازی مناسب نیست، زیرا همه barها از قبل با tick پر شدهاند. بنابراین، توصیه میشود با مقایسه زمان آن با bar جدید، یک bar جدید تعریف کنید.
expression engine برای حل مسئله توصیف شده با استفاده از گزینه سوم توسعه یافته است. علاوه بر توابع MA indicator (MAIndicatorFunc)، من توابع MA Fan (MultiMAIndicatorFunc ، Indicators.mqh را ببینید) را ایجاد کردهام. نام آنها باید با پیشوند “” M_ شروع شود و باید شامل حداقل دوره، مرحله دوره و حداکثر دوره باشد ، به عنوان مثال:
input string SignalBuy = "M_EMA_OPEN_9_6_27(Fast,Bar)/M_EMA_OPEN_9_6_27(Slow,Bar) > 1 + T"; input string SignalSell = "M_EMA_OPEN_9_6_27(Fast,Bar)/M_EMA_OPEN_9_6_27(Slow,Bar) < 1 - T";
متد Calculation و نوع قیمت مانند قبل در name نشان داده شده است. در اینجا یک EMA fan بر اساس قیمت OPEN با دوره های از 9 تا 27 (گنجانده شده) با یک مرحله 6 ایجاد میشود.
نوآوری دیگر در کتابخانه expression مجموعهای از متغیرها است که دسترسی به آمار معاملاتی را از TesterStatistics فراهم میکند (به TesterStats.mqh مراجعه کنید). بر اساس این مجموعه، می توان ورودی Formula را به EA اضافه کرد، که امکان تنظیم مقدار هدف را به عنوان یک عبارت دلخواه فراهم میکند. وقتی این متغیر پر میشود، Estimator نادیده گرفته میشود. به طور خاص، به جای STAT_PROFIT_FACTOR (که برای بدون تلف تعریف نشده است) میتوان یک شاخص ” smoother ” با فرمول مشابه در ” Estimator ” تنظیم کرد: “(GROSSPROFIT- (1 / (TRADES + 1)))) / – ((GROSSLOSS- 1 / ((TRADES +1) “.
اکنون، همه چیز برای اجرای بهینه سازی معامله مجازی با استفاده از روش PSO آماده است.
تست عملی بهینه سازی Expert Advisors
بگذارید یک تستر آماده کنیم. باید از بهینه سازی slow یعنی تکرار کامل تمام پارامترها استفاده کند. در مورد ما slow نخواهد بود، زیرا فقط تعداد گروه در هر بار تغییر مییابد، در حالی که تکرار انتخابی پارامترهای EA توسط یک گروه در چرخه آن انجام میشود. به سه دلیل نمیتوان از ژنتیک استفاده کرد. اول، تضمین نمیکند که تمام ترکیبات پارامترها (تعداد مشخصی از گروهها در مورد ما) محاسبه شوند. دوم، به دلیل ماهیت خاص آن، به تدریج به سمت پارامترهایی “shift” میکند که نتیجه جذابتری دارند، بدون در نظر گرفتن این واقعیت که هیچ وابستگی بین تعداد گروه و موفقیت آن وجود ندارد، زیرا تعداد گروه فقط تصادفی سازی ساختار داده PSO است. سوم، تعداد گروه ها معمولاً آنقدر زیاد نیستند که بتوانند از رویکرد ژنتیکی استفاده کنند.بهینه سازی با حداکثر معیار سفارشی انجام میشود.
ابتدا با استفاده از کتابخانه مجازی غیرفعال شده (ExprBotPSO-standard-optimization.set file) ، Expert Advisor را به طور منظم بهینه کنید. تعداد ترکیب پارامترها برای بهینه سازی برای اهداف نمایشی کم است. پارامترهای Fast و Slow از 9 تا 45 با یک مرحله 6، پارامتر Tاز 0 تا 01.0 با یک مرحله 0025.0 مرحلهای تغییر میکند.
EURUSD ، H1، از ابتدای سال 2020، از tickهای واقعی استفاده می کند. نتایج زیر را میتوان بدست آورد:
↑جدول نتایج بهینهسازی استاندارد↑
طبق log ها ، تقریباً 21 دقیقه بهینه سازی روی ابزار دو عامل انجام میشود.
Experts optimization frame expert ExprBotPSO (EURUSD,H1) processing started Tester Experts\ExprBotPSO.ex5 on EURUSD,H1 from 2020.01.01 00:00 to 2020.08.01 00:00 Tester complete optimization started ... Core 2 connected Core 1 connected Core 2 authorized (agent build 2572) Core 1 authorized (agent build 2572) ... Tester optimization finished, total passes 245 Statistics optimization done in 20 minutes 55 seconds Statistics shortest pass 0:00:05.691, longest pass 0:00:23.114, average pass 0:00:10.206
اکنون، Expert Trading را با معامله مجازی و PSO بهینه سازی کنید (ExprBotPSO-virtual-pso-optimization.set). تعداد گروه های برابر با 4 با تکرار پارامتر PSO_GroupCount از 0 به 3 تعیین میشود. سایر پارامترهای عملیاتی که بهینه سازی برای آنها فعال است، در بهینه سازی استاندارد به زور غیرفعال میشوند، اما برای بهینه سازی مجازی داخلی با استفاده از الگوریتم PSO به عامل های موجود در فایلهای CSV منتقل میشوند.
دوباره، از شبیه سازی توسط tickهای واقعی استفاده کنید، اگرچه استفاده از tickهای تولید شده یا OHLC M1 نیز برای محاسبات سریع امکان پذیر است. در اینجا نمیتوان از محاسبات ریاضی استفاده کرد زیرا tickها برای معامله مجازی در تستر جمع میشوند.
موارد زیر را میتوانید در logهای مربوط به تستر بدست آورید:
Tester input parameter 'Fast' set to: enable=false, value=9, start=9, step=6, stop=45 Tester input parameter 'Slow' set to: enable=false, value=21, start=9, step=6, stop=45 Tester input parameter 'T' set to: enable=false, value=0, start=0, step=0.0025, stop=0.01 Experts optimization frame expert ExprBotPSO (EURUSD,H1) processing started Tester Experts\ExprBotPSO.ex5 on EURUSD,H1 from 2020.01.01 00:00 to 2020.08.01 00:00 Tester complete optimization started ... Core 1 connected Core 2 connected Core 2 authorized (agent build 2572) Core 1 authorized (agent build 2572) ... Tester optimization finished, total passes 4 Statistics optimization done in 4 minutes 00 seconds Statistics shortest pass 0:01:27.723, longest pass 0:02:24.841, average pass 0:01:56.597 Statistics 4 frames (784 bytes total, 196 bytes per frame) received
واقعی و مجازی اندکی متفاوت است.
22:22:52.261 ExprBotPSO (EURUSD,H1) 2 tmp-files deleted 22:25:07.981 ExprBotPSO (EURUSD,H1) 0 PSO75/1500 0 1974.400000000025 22:25:23.348 ExprBotPSO (EURUSD,H1) 2 PSO84/1500 2 402.6000000000062 22:26:51.165 ExprBotPSO (EURUSD,H1) 3 PSO70/1500 3 455.000000000003 22:26:52.451 ExprBotPSO (EURUSD,H1) 1 PSO79/1500 1 458.3000000000047 22:26:52.466 ExprBotPSO (EURUSD,H1) Solution: 1974.400000000025 22:26:52.466 ExprBotPSO (EURUSD,H1) 39.00000 15.00000 0.00500
هر “pass” اکنون یک بسته بهینهسازی مجازی است، بنابراین طولانیتر شده است. اما تعداد کل آنها کمتر است و زمان کلی به طور قابل توجهی کاهش مییابد – فقط 4 دقیقه.
پیامها از فریمها در logها دریافت میشوند (بهترین خواندن هر گروه را نشان میدهد). با این حال، نتایج معاملات واقعی و مجازی اندکی متفاوت است.
نتایج دقیقاً مطابقت نخواهند داشت (حتی اگر یک استراتژی بدون indicator ، تیک به تیک داشته باشیم)، زیرا تستر دارای ویژگی های عملکرد خاصی است که در کتابخانه MQL قابل تکرار نیستند. اینجا تنها تعداد کمی از آنها هستند:
- سفارشات محدود در نزدیکی قیمت بازار را میتوان به روش های مختلف انجام داد
- حاشیه محاسبه نمیشود یا کاملاً دقیق محاسبه نمیشود
- commission به طور خودکار محاسبه نمیشود (محدودیت MQL API)، اما میتواند از طریق پارامترهای ورودی اضافی برنامه ریزی شود
- حسابداری سفارشات و معاملات در حالت نت ممکن است متفاوت باشد
- فقط نماد فعلی پشتیبانی میشود
توجه:برای کسب اطلاعات بیشتر در مورد کتابخانه مجازی، لطفاً به اسناد و بحث های مربوطه مراجعه کنید.
برای اهداف اشکال زدایی و درک عملکرد swarm، آزمایش EA از حالت بهینه سازی مجازی در یک هسته در یک تستر طبیعی پشتیبانی میکند. نمونهای از تنظیمات در فایل ExprBotPSO-virtual-internal-optimization-single-pass.set است که در زیر پیوست شده است. فراموش نکنید که بهینه سازی را در تستر غیرفعال کنید.
نتایج متوسط با جزئیات در tester log نوشته میشوند. در هر چرخه، موقعیت و مقدار تابع هدف هر ذره از PSO_Cycles داده شده خارج میشود. اگر ذره به مختصات از قبل بررسی شده برخورد کند، از محاسبه صرف نظر میشود.
Ticks size=15060113 error=0 [,0] [,1] [,2] [,3] [0,] "Fast" "9" "6" "45" [1,] "Slow" "9" "6" "45" [2,] "T" "0" "0.0025" "0.01" PSO[3] created: 15/3 PSO Processing... Fast:9.0, Slow:33.0, T:0.0025, 1.31285 Fast:21.0, Slow:21.0, T:0.0025, -1.0 Fast:15.0, Slow:33.0, T:0.0075, -1.0 Fast:27.0, Slow:39.0, T:0.0025, 0.07673 Fast:9.0, Slow:9.0, T:0.005, -1.0 Fast:33.0, Slow:21.0, T:0.01, -1.0 Fast:39.0, Slow:45.0, T:0.0025, -1.0 Fast:15.0, Slow:15.0, T:0.0025, -1.0 Fast:33.0, Slow:21.0, T:0.0, 0.32895 Fast:33.0, Slow:39.0, T:0.0075, -1.0 Fast:33.0, Slow:15.0, T:0.005, 384.5 Fast:15.0, Slow:27.0, T:0.0, 2.44486 Fast:39.0, Slow:27.0, T:0.0025, 11.41199 Fast:9.0, Slow:15.0, T:0.0, 1.08838 Fast:33.0, Slow:27.0, T:0.0075, -1.0 Cycle 0 done, skipped 0 of 15 / 384.5000000000009 ... Fast:45.0, Slow:9.0, T:0.0025, 0.86209 Fast:21.0, Slow:15.0, T:0.005, -1.0 Cycle 15 done, skipped 13 of 15 / 402.6000000000062 Fast:21.0, Slow:15.0, T:0.0025, 101.4 Cycle 16 done, skipped 14 of 15 / 402.6000000000062 Fast:27.0, Slow:15.0, T:0.0025, 8.18754 Fast:39.0, Slow:15.0, T:0.005, 1974.40002 Cycle 17 done, skipped 13 of 15 / 1974.400000000025 Fast:45.0, Slow:9.0, T:0.005, 1.00344 Cycle 18 done, skipped 14 of 15 / 1974.400000000025 Cycle 19 done, skipped 15 of 15 / 1974.400000000025 PSO Finished 89 of 1500 planned calculations: true 39.00000 15.00000 0.00500 1974.40000 final balance 10000.00 USD OnTester result 1974.400000000025
از آنجا که فضای بهینه سازی کم است، با 19 چرخه، کاملاً پوشانده شد. مطمئناً، اوضاع برای مشکلات واقعی با میلیونها ترکیب متفاوت خواهد بود. در چنین مشکلاتی، یافتن ترکیبات مناسب PSO_Cycles ، PSO_SwarmSize و PSO_GroupCount بسیار مهم است.
فراموش نکنید که با PSO ، یک tester pass برای هر یک از PSO_GroupCount تا حداکثر PSO_Cycles * PSO_SwarmSize پاس مجازی واحد را انجام میدهد، به همین دلیل است که نشانه پیشرفت به طور قابل توجهی کندتر از حد معمول است.
بسیاری از معامله گران تلاش میکنند تا با چندین بار اجرای متوالی بهترین نتیجه را از بهینه سازی ژنتیکی داخلی کسب کنند. این آزمایشات مختلفی را به دلیل مقداردهی اولیه تصادفی جمع آوری میکند و پس از چندین بار اجرا میتوان پیشرفت کرد. در مورد PSO ، PSO_GroupCount به عنوان آنالوگ راه اندازی چندین ژنتیک عمل میکند. تعداد اجراهای منفرد، که در ژنتیک میتواند به 10000 برسد، باید در PSO بین دو مولفه محصول PSO_Cycles * PSO_SwarmSize ، به عنوان مثال 100 * 100 توزیع شود. PSO_Cycles مشابه نسلها در ژنتیک است و PSO_SwarmSize اندازه جمعیت است.
مجازی سازی اکسپرت ادوایزر MQL5 API
تاکنون، ما نمونهای از بهینه سازی Expert Advisors را که با استفاده از API معاملات MQL4 نوشته شده است، مطالعه کردهایم. این با مشخصات پیاده سازی کتابخانه مجازی در ارتباط بود. با این حال، من می خواستم امکان استفاده از PSO را برای EA ها با توابع “جدید” MQL5 API پیاده سازی کنم. برای این منظور، من یک لایه میانی تجربی برای هدایت فراخوانهای MQL5 API به MQL4 API ایجاد کردهام. به عنوان فایل MT5Bridge.mqh در دسترس است که برای کار کردن به کتابخانه مجازی و / یا سفارشات MT4 نیاز دارد.
#include <fxsaber/Virtual/Virtual.mqh> #include <MT5Bridge.mqh> #include <Expert\Expert.mqh> #include <Expert\Signal\SignalMA.mqh> #include <Expert\Trailing\TrailingParabolicSAR.mqh> #include <Expert\Money\MoneySizeOptimized.mqh> ...
پس از افزودن Virtual و MT5Bridge در ابتدای کد، قبل از # سایر موارد، توابع MQL5 API از طریق توابع تعریف شده ” ” Bridge فراخوانی میشوند، که از آنها توابع MQL4 API ” مجازی” فراخوانی میشوند. در نتیجه، امکان آزمایش و بهینه سازی وجود دارد. به طور خاص ، اکنون می توان بهینه سازی PSO را مشابه مثال فوق ExprBotPSO اجرا کرد. این امر مستلزم نوشتن (تا حدودی کپی کردن) یک عامل و کنترل کننده برای آزمایش کننده است. اما بیشترین زمان و فرآیند زمانبر، مربوط به انطباق سیگنال های indicator برای پارامترهای متغیر است.
MT5Bridge.mqh دارای وضعیت آزمایشی است زیرا عملکرد آن به طور گسترده آزمایش نشده است. این یک تحقیق اثبات مفهوم است. می توانید از کد منبع برای دیباگ کردن و رفع اشکال استفاده کنید.
نتیجه
ما الگوریتم بهینه سازی Expert Advisors ( بهینه سازی اکسپرت ) ازدحام ذرات را در نظر گرفتهایم و آن را در MQL با پشتیبانی از چند نخی با استفاده از عوامل آزمایش، پیاده سازی کردهایم. در دسترس بودن تنظیمات PSO باز، در مقایسه با استفاده از بهینه سازی ژنتیکی داخلی، انعطاف پذیری بیشتری را در تنظیم فرآیند ایجاد میکند. علاوه بر تنظیمات ارائه شده در پارامترهای ورودی، منطقی است که سایر ضرایب سازگار را که از آنها به عنوان آرگومان های روش “بهینه سازی” با مقادیر پیش فرض استفاده کردهایم، استفاده کنید: اینرسی (0.8) ، selfBoost (0.4) و groupBoost (0.4). این باعث انعطاف پذیری الگوریتم میشود اما انتخاب تنظیمات برای یک کار خاص را دشوارتر میکند. کتابخانه PSO که در زیر پیوست شده است میتواند در حالت محاسبات ریاضی (اگر مکانیزم ذکر قیمت سهام، شاخصها و معاملات مجازی خود را دارید) و همچنین در حالتهای tick-bar ، از کلاس های شبیه سازی معامله شخص ثالث، مانند مجازی استفاده میکند.
مقاله زیر نیز برای شما مفید است:
این مقاله ترجمه شده توسط تیم آکادمی ایران ام کیو ال می باشد.
پاسخها