ربات معامله گر غیر تجاری RenkoTicks.mq5 برای اجرای نمودار رنکو در MetaTrader 5 استفاده خواهد شد. ربات معامله گر رنکو را به عنوان شاخص های نماد دلخواه تولید می کند در حالیکه تیک های واقعی را پردازش می کند (در MetaTrader 5 از طرف کارگزار شما در دسترس است). می توانیم از شاخص های (میله های) هر نماد مرجعی و هر بازه زمانی که نمودار فعال بر روی RenkoTicks در حال اجرا است، استفاده کنیم.
نمودار رنکو در MetaTrader 5
هنگام تولید رنکو، یک جایگزین برای نمادهای دلخواه می توانند یک شاخص یا طراح (با استفاده از اشیا یا یک قاب) باشند اما در هر دو مورد امکان ندارد تا از شاخص ها یا اسکریپت های روی شبه نمودار حاصل استفاده شود.
تمام میله های رنکو بر روی بازه زمانی M1 شکل می گیرند. این کار عمدا انجام می شود زیرا بعض اوقات میله های رنکو می توانند خیلی سریع یکی پس از دیگری، مثلا در زمان های نوسانات شدید، تشکیل شوند و زمان بین میله ها باید حتی الامکان کوتاه باشد. یک دقیقه حداقل فاصله ممکن نمودار رنکو در MetaTrader 5 می باشد. به همین خاطر باید نمودارهای رنکو همواره دارای بازه زمانی M1 باشند. هیچ معنی ندارد که نمودار رنکو به بازه زمانی دیگری انتقال یابد. زمان هر میله یک دقیقه ای ابتدایی با زمان آغاز تشکیل میله های رنکو مناسب مطابقت دارد. زمان تکمیل چنین میله دقیقه ای جعلی می باشد و می بایست در عوض آغاز میله یک دقیقه ای بعدی بررسی شود.
متاسفانه، گاهی اوقات چندین میله رنکو باید در طول یک دقیقه تشکیل شود. از آنجاییکه نمودار رنکو در MetaTrader 5 این اجازه را نمی دهد، ربات معامله گر میله هایی با توالی منطبق بر میله M1 تولید می کند که به طور مصنوعی با گذشت هر دقیقه افزایش می یابد. در نتیجه، زمان رسمی میله های رنکو شاید با زمان واقعی همسان نباشند (می تواند جلوتر از آن باشد). به عنوان مثال، اندازه رنکو برابر با 100 در یکصد هزارم، نوسانی برابر با 300 در یکصد هزارم در ساعت 12:00 رخ می دهد و 10 ثانیه طول می کشد تا میله های رنکو در زمان های 12:00:00، 12:00:05، 12:00:10 ساخته شوند. در عوض، ربات معامله گر میله ها را در 12:00، 12:01، 12:02 تولید می کند.
وقتی این امر در تاریخچه شاخص اتفاق می افتد، مشکل بعدی بروز می دهد: چنین میله های رنکو منتقل شده از گذشته با میله های دیگر متشکل از میله های بعدی نمودار اصلی همپوشانی می نماید. فرض کنید یک نوسان 100 نقطه ای دیگر در زمان 12:02 رخ دهد و بنابراین می بایست یک میله رنکو در زمان آغازین 12:02 بسازیم اما این زمان قبلا اشغال شده است! برای حل چنین تداخلی، ربات معامله گر حالت مخصوصی دارد که افزایش تحمیلی به زمان میله بعدی ساخته شده به اندازه یک دقیقه، در صورت نیاز، ایجاد می کند.
این حالت با پارامتر SkipOverFlows تنظیم می شود که به صورت پیش فرض false است (میله ها همپوشانی نمیشوند بلکه در عوض در صورت لزوم به آینده منتقل می شوند). اگر SkipOverFlows مقدار true بگیرد، میله های دارای زمان های همپوشانی یکدیگر را بازنویسی می کنند و در نتیجه رنکو حاصل کاملا صحیح نخواهد بود.
لطفا توجه نمایید که چنین وضعیتی با نواسانات شدید و تولید چندین میله ahead در زمان واقعی امکان پذیر است- در این حالت میله ها عملا در آینده شکل می گیرند! در مثال ما، میله های رنکو با زمان گشایش 12:00، 12:01، 12:02 در زمان 12:00:10 وجود خواهند داشت! این امر باید در تحلیل و معامله لحاظ شود.
چندین روش برای حل این مشکل، مثلا با افزایش اندازه میله رنکو، وجود دارد. با این وجود یک نقطه ضعف مشهود دارد- این کار دقت رنکو را کاهش میدهد یعنی اینکه نوسانات شاخص شدیدتری را ثبت و میله های کمتری ایجاد می کند. یک روش ممکن دیگر تجمیع (شیفت به سمت چپ) میله های قبلی می باشد اما به طراحی مجدد شاخص ها و اشیا نیاز دارد.
برحسب خصوصیات پلاتفرم مشخص، ربات معامله گر تیک های تخیلی را با زمان برابر با زمان گشایش آخرین میله رنکو تولید می کند. تنها هدف این تیک های ساختگی اجرای گرداننده OnTick در معامله ربات معامله گر می باشد. اگر تیک ها از نماد اصلی به نماد دلخواه بدون تغییر بازخوانی شوند، ساختار رنکو را از بین می برد. مجددا، می توانیم نوسان شدید را به عنوان مثال در نظر بگیریم و به ارسال یک نمودار رنکو در MetaTrader 5 با میله ای با زمان واقعی 12:00:00 بپردازیم. اما زمان این تیک مرتبط با آخرین (کنونی) میله 0 نخواهد بود بلکه مرتبط با میله شماره 2 با زمان گشایش 12:00 خواهد بود در نتیجه، چنین تیکی زمان 12:00 میله بار (که در تاریخچه می باشد) را از بین می برد یا یک خطا تولید خواهد کرد.
رنکو می تواند با یک وضعیت متضاد، یعنی وقتی نوسانات خیلی آرام باشد، از بین برود. اگر شاخص در محدوده یک میله به مدت طولانی باشد، میله رنکو با همان زمان گشایش می ایستد، در حالی که تیک های جدید ممکن است زمانی بیش از یک دقیقه از میله رنکو صفرم داشته باشند. اگر چنین تیک هایی به نمودار رنکو ارسال شوند میله های کاذب در آینده خواهند ساخت.
توجه داشته باشیدکه تیک های رنکو تاریخچه در یک حالت مینیمالیستی، یک بار در هر باکس، تشکیل می شوند. در زمان فعالیت آنلاین، تمام تیک ها به رنکو ارسال می شوند.
مشابه نمادهای دلخواه دیگر، این رویکرد به ما اجازه استفاده از هر شاخص، اسکریپت و اشیائی در نمودار رنکو در MetaTrader 5 را می دهد تا با استفاده از ربات معامله گر بهترین معامله صورت پذیرد.
پارامترهای اصلی
- پارامتر RenkoBoxSize- اندازه میله رنکو در نقاط، با پیش فرض 100.
- پارامتر ShowWicks- دنباله نمایشگر پرچم، با پیش فرض true.
- پارامتر EmulateOnLineChart- تیک های ارسال کنند پرچم، با پیش فرض true.
- پارامتر OutputSymbolName- نام نماد دلخواه برای رنکو تولید شده، با پیش فرض یک رشته خالی- نام به شکل Symbol_T_Type_Size شکل می گیرد که در آن Symbol نماد فعال حاضر می باشد، T نشانه حالت تیک است، Type- r (رنکو) با دنیاله یا b (بلوک) بدون دنباله است، Size- RenkoBoxSize می باشد؛ به عنوان مثال: EURUSD_T_r100.
- پارامتر Reset- پرچمی برای محاسبه مجدد کل نمودار رنکو است که به طور پیش فرض بر روی false تنظیم می شود. اگر آن را بر روی true تنظیم کنید، توصیه می شود برای نتیجه منتظر بمانید و برای تنظیم آن به حالت False از محاسبه مجدد در زمان شروع مجدد هر ترمینال اجتناب نمایید. این حالت هنگامی مفید است که تولید میله های رنکو در بعضی از موقعیت ها ناموفق باشد. معمولا این گزینه همواره غیرفعال می باشد هنگامی که ربات معامله گر می تواند محاسبه را از آخرین میله رنکو موجود ادامه دهد.
- پارامتر StartFrom,StopAt- دوره تاریخچه از ابتدا تا انتها؛ به طور پیش فرض از صفر استفاده می شود. بدین معنی که تمام تاریخچه موجود استفاده خواهد شد. هنگام اولین استفاده ربات معامله گر، توصیه می شود StartFrom را با گذشته اخیر تنظیم کنید تا سرعت سیستم را در زمان تولید میله های رنکو توسط تیک های واقعی بسنجید.
- پارامتر SkipOverflows- پرچمی برای پردازش جعبه های تداخلی همپوشان؛ به طور پیش فرض بر روی false تنظیم است. بدین معنی که زمان میله جدید با تحمیل به اندازه یک دقیقه افزایش می یابد اگر محاسبه لازم قبلا توسط باکس قبلی اشغال شده باشد.
- پارامتر CloseTimeMode- اگر true باشد باکس ها همگی در زمان پایان (یک تیک در هر باکس) تشکیل می شوند؛ به طور پیش فرض بر روی false تنظیم است.
کلاس نمودار رنکو در MetaTrader 5 جریان تیک را رسیدگی می کند و میله های رنکو جدید را بر این اساس می سازد. اجزا اصلی آن در شبه کد زیر مشخص می شود:
class Renko { protected: bool incrementTime(const datetime time); void doWriteStruct(const datetime dtTime, const double dOpen, const double dHigh, const double dLow, const double dClose, const double dVol, const double dRealVol, const int spread); public: datetime checkEnding(); void continueFrom(const datetime time); void doReset(); void onTick(const MqlTick &t); void updateChartWindow(const double bid = 0, const double ask = 0);
کد نهم
روش های حفاظت شده incrementTime و doWriteStruct به ترتیب، به زمان آزاد بعدی و نزدیک ترین زمان به زمان مشخص انتقال می یابند، M1 برای باکس رنکو بعدی نمونه برداری می شود، و میله را خودش با فراخوانی CustomRsteUpdate می نویسد. سه روش اول در بخش عمومی مسئولیت آغاز الگوریتم در ابتدای امر به عهده دارند. ربات معامله گرمی تواند وجود شاخص های رنکو قبلی را بررسی نماید (این امر با روش checkEnding انجام می شود که پایان زمان تاریخچه و زمان را برمی گرداند) و بر اساس اینکه وجود دارند یا خیر، ربات معامله گر از لحظه مشخص با استفاده از روش continueFrom ادامه می دهد (با مرتب سازی مجدد مقادیر متغیرهای داخلی) و یا از doReset برای رسیدگی به تیک ها از یک حالت Empty استفاده کند.
روش onTick در هر تیک (هم در تاریخچه و هم آنلاین) فراخوانده می شود و در صورت لزوم یک میله رنکو با استفاده از doWriteStruct می سازد (اینجانب الگوریتمی از تابع معروف RenkoLiveChart.mq4 ربات معامله گر با چند تصحیح استفاده نمودم). اگر تقلید تیک در تنظیمات ربات معامله گر مشخص باشد، updateChartWindow نیز فراخوانده می شود. کدهای مرجع کامل در زیر ضمیمه شده اند.
کلاس TickProvider مسئول تحویل تیک ها به شی رنکو می باشد:
class TickProvider { public: virtual bool hasNext() = 0; virtual void getTick(MqlTick &t) = 0; bool read(Renko &r) { while(hasNext() && !IsStopped()) { MqlTick t; getTick(t); r.onTick(t); } return IsStopped(); }
کد دهم
از آنجاییکه یک رابط معمول برای خوانش/دریافت تیک ها از دو منبع مختلف شناسایی میکند یک مفهوم انتزاعی است: تاریخچه تیک نماد پایه در ربات معامله گر و ردیف شناسه OnTick هنگام فعالیت آنلاین. روش read یک لوپ تیک جهانی است که از روش های مجازی hasNext() و getTick() استفاده می کند.
تاریخچه تیک در کلاس HistoryTickProvider به روش آشنایی خوانده می شود: ازCopyTickRange و بافر متوسط MqlTick array() استفاده می کند که در آن تیک ها اوسط روز درخواست می شوند:
class HistoryTickProvider : public TickProvider { private: datetime start; datetime stop; ulong length; // in seconds MqlTick array[]; int size; int cursor; int numberOfDays; int daysCount; protected: void fillArray() { cursor = 0; do { size = CopyTicksRange(_Symbol, array, COPY_TICKS_ALL, start * 1000, MathMin(start + length, stop) * 1000); Comment("Processing: ", DoubleToString(daysCount * 100.0 / (numberOfDays + 1), 0), "% ", TTSM(start)); if(size == -1) { Print("CopyTicksRange failed: ", GetLastError()); } else { if(size > 0 && array[0].time_msc < start * 1000) // prevent older than requested data returned { start = stop; size = 0; } else { start = (datetime)MathMin(start + length, stop); if(size > 0) daysCount++; } } } while(size == 0 && start < stop); } public: HistoryTickProvider(const datetime from, const long secs, const datetime to = 0): start(from), stop(to), length(secs), cursor(0), size(0) { if(stop == 0) stop = TimeCurrent(); numberOfDays = (int)((stop - start) / DAY_LONG); daysCount = 0; fillArray(); } bool hasNext() override { return cursor < size; } void getTick(MqlTick &t) override { if(cursor < size) { t = array[cursor++]; if(cursor == size) { fillArray(); } } } };
کد یازدهم
کلاس تهیه کننده تیک آنلاین CurrentTickProvider:
class CurrentTickProvider : public TickProvider { private: bool ready; public: bool hasNext() override { ready = !ready; return ready; } void getTick(MqlTick &t) override { SymbolInfoTick(_Symbol, t); } };
کد دوازدهم
بخش اصلی پردازش تیک به شکل کوتاه مشابه زیر می باشد:
const long DAY_LONG = 60 * 60 * 24; bool _FirstRun = true; Renko renko; CurrentTickProvider online; void OnTick(void) { if(_FirstRun) { // find existing renko tail to supersede StartFrom const datetime trap = renko.checkEnding(); if(trap > TimeCurrent()) { Print("Symbol/Timeframe data not ready..."); return; } if((trap == 0) || Reset) renko.doReset(); else renko.continueFrom(trap); HistoryTickProvider htp((trap == 0 || Reset) ? StartFrom : trap, DAY_LONG, StopAt); const bool interrupted = htp.read(renko); _FirstRun = false; if(!interrupted) { Comment("RenkoChart (" + (string)RenkoBoxSize + "pt): open ", _SymbolName, " / ", renko.getBoxCount(), " bars"); } else { Print("Interrupted. Custom symbol data is inconsistent - please, reset or delete"); } } else if(StopAt == 0) // process online if not stopped explicitly { online.read(renko); } }
کد سیزدهم
در اولین شروع، انتهای تاریخچه رنکو جستجو می شود، شی HistoryTickProvider با زمان شروع StarFrom یا از تاریخچه (در صورت پیدا شدن) ساخته می شود و سپس تمام تیک ها خوانده می شوند. تمام تیک های بعدی از طریق شی CurrentTickProvider به صورت آنلاین پردازش می شوند (در محتوای جهانی ساخته می شود، دقیقا مشابه شی رنکو).
حال یک نمودار رنکو در MetaTrader 5 بر اساس EURUSD با میله ای به اندازه 100 در یک صد هزارم با زمان آغازین 2019 تولید می کنیم. بدین منظور، ربات معامله گر را بر روی نمودار EURUSD H1 با تنظیمات پیش فرض به غیر از StartForm اجرا می کنیم. بازه زمانی تنها وقتی مهم است که ربات معامله گر با تاریخچه رنکو در دسترس مجددا راه اندازی شود- در این مورد محاسبه مجدد رنکو با شروع همسان با زمان میله تا یکی مانده به آخر بلوک های رنکو آغاز خواهد شد.
به عنوان مثال، برای EURUSD H1 اصلی به شکل زیر است:
نمودار EURUSD H1 با تیک های رنکو ربات معامله گر
نمودار زیر را دریافت خواهیم نمود:
نمودار رنکو EURUSD با اندازه بلوک 100 نقطه
برای شفافیت بصری دو MA اضافه نموده ام.
حالا که شاخصی برای نماد رنکو دریافت نموده ایم، وقت آن است که یک ربات معامله گر راهنمای آزمایشی برای معامله ارائه دهیم.
پارت سوم این مقاله:
این مقاله ترجمه شده توسط تیم آکادمی ایران ام کیو ال می باشد.
پاسخها