زیگزاگ جهانی

ساخت وبلاگ

زیگزاگ (شکل 1) یکی از محبوب ترین شاخص ها در بین کاربران Metatrader 5 است. تا به امروز ، تعداد زیادی از انواع Zigzag ایجاد شده است. با این حال ، برخی از آنها خیلی کند هستند و همین امر باعث می شود آنها برای ایجاد متخصصان نامناسب باشند. برخی دیگر دائماً خطاهایی ایجاد می کنند ، که باعث می شود حتی برای مشاهده بصری استفاده از آنها را دشوار کند. برای شاخص هایی که سریع و بدون خطا کار می کنند ، عوارض هنگام استفاده از آنها در توسعه EA یا شاخص دیگر بوجود می آیند. این اتفاق می افتد زیرا استخراج و تفسیر داده های زیگزاگ چندان آسان نیست.

شکل 1. نشانگر Zigzag

در این مقاله الزامات برای ترسیم یک زیگزاگ و همچنین روشهای مختلف برای ترسیم آن ، نتیجه گیری و به دست آوردن یک الگوریتم یکپارچه در نظر گرفته شده است. این الگوریتم به عنوان پایه ای برای ایجاد شاخص جهانی استفاده می شود ، که امکان انتخاب انواع مختلف زیگزاگ را از طریق پنجره Properties فراهم می کند.

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

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

ویژگی های نشانگر Zigzag

شاخص Zigzag (شکل 1) یک پلی خط است که قیمت محلی و پایین قیمت را به هم وصل می کند. مبتدیان ممکن است بلافاصله فکر کنند: خرید در پایین و فروش در تاپ ها بسیار عالی خواهد بود! این ایده وسوسه انگیز به نظر می رسد ، اما افسوس ، زیگزاگ فقط در تاریخ بسیار وسوسه انگیز به نظر می رسد. در واقعیت ، اوضاع تا حدودی متفاوت است. مشخص می شود که پس از شکل گیری در واقع ، یک قسمت بالا یا پایین فقط چندین میله تشکیل داده است. شکل 2 وضعیتی را نشان می دهد که آخرین بخش از شاخص تشکیل آن را متوقف کند (تغییر) ، قیمت معکوس شد و در جهت مخالف (بالا) حرکت کرد.

شکل 2. زیگزاگ به سمت پایین هدایت می شود ، اما قیمت به سمت بالا معکوس می شود

با این حال ، چندین میله بعداً قیمت کاهش می یابد (شکل 3) ، و آخرین بخش زیگزاگ همچنان به سمت پایین کشیده می شود.

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

این بار نشانگر به حداقل خود رسیده است، اما این را می توان تنها چند میله بعد تایید کرد (شکل 4).

شکل 4. ده میله طول کشیده است تا زیگ زاگ یک قطعه جدید به سمت بالا بکشد و شکل پایین مشخص شود.

این ویژگی های زیگ زاگ به بهترین وجه در شکل 5 توضیح داده شده است. نشانگر شروع به ترسیم بخش های جدید رو به بالا روی میله ها با نقاط آبی و بخش های رو به پایین جدید روی میله ها با نقاط قرمز کرده بود.

شکل.

با وجود این ویژگی خاص، زیگ زاگ محبوبیت و جذابیت خود را از دست می دهد. حداقل، به طور قابل توجهی تجزیه و تحلیل بصری نمودارها را تسهیل می کند، به فیلتر کردن نویز و تشخیص مسیر اصلی حرکت قیمت کمک می کند. در یک کاربرد عملی تر، این نشانگر ممکن است برای تشخیص سطوح حمایت/مقاومت یا برای شناسایی الگوها استفاده شود. و می توان از آن به عنوان پایه ای برای ترسیم خطوط روند استفاده کرد، درست مانند هر ابزار گرافیکی دیگری برای تجزیه و تحلیل تکنیکال، مشابه سطوح فیبوناچی، فن و غیره. فهرست کردن همه چیزهایی که ممکن است ذهن یک معامله گر پیچیده برای استفاده از ZigZag به ذهنش برسد غیرممکن است..

انواع طرح زیگزاگ

واضح است که زیگ زاگ دو حالت دارد: یا به سمت بالا یا پایین هدایت می شود. هنگامی که خط به سمت بالا هدایت می شود - در صورت ظاهر شدن یک High جدید، قیمت را کنترل کنید، و هنگامی که خط به سمت پایین است - منتظر بمانید تا یک Low جدید ظاهر شود. همچنین لازم است بر تحقق شرایطی که نشان دهنده تغییر جهت است نظارت شود. بنابراین، برای ترسیم یک ZigZag، لازم است:

  1. داده های منبع را بدست آورید.
  2. شرایط تغییر جهت خط را فرموله کنید.
  3. نظارت بر وقوع بالا و پایین های جدید.

داده‌های منبع می‌تواند یک سری (مثلاً قیمت بسته میله) یا دو سری (مثلاً قیمت بالا و پایین نوار) باشد. اگر از یک سری داده استفاده شود، آنگاه می‌تواند نه تنها قیمت بسته، بلکه تقریباً هر شاخصی باشد، چه نوسانگر یا میانگین متحرک. هنگام ترسیم ZigZag بر اساس داده های نشانگر، می توان از دو سری داده استفاده کرد: یکی با داده های نشانگر بر اساس نوار Highs و دیگری بر اساس Lows.

شرایط تغییر جهت مهمترین نکته ای است که انواع مختلف زیگ زاگ ها را تعریف می کند. این شرایط می تواند بسیار متفاوت باشد. به عنوان مثال، چنین شرایطی ممکن است تشکیل یک High/Low بیش از n نوار در نوار فعلی باشد. به عبارت دیگر، اگر مقدار سری منبع در نوار فعلی بیش از n نوار آخر حداکثر یا حداقل باشد، آنگاه جهت ZigZag را مشخص می کند. این اصل در اندیکاتور کلاسیک ZigZag استفاده می شود. روش دیگر - بر اساس اندازه یک بازگشت از مقدار حداکثر یا حداقل ثابت است. اندازه برگشت را می توان در نقاط (اگر سری منبع در صورت قیمت) یا در واحدهای معمولی (اگر شاخصی باشد) اندازه گیری کرد. روش‌های موجود به این دو محدود نمی‌شوند، می‌توان جهت را با استفاده از هر نشانگر تعیین کرد - Stochastic، ADX، و غیره. اگر Stochastic بالاتر از 50 باشد، ZigZag به سمت بالا و اگر زیر 50 باشد - به سمت پایین است. اکنون، جهت را بر اساس ADX تعیین کنید: اگر خط PDI بالای خط MDI باشد، خط ZigZag به سمت بالا هدایت می شود و PDI پایین آن زیر MDI است.

بنابراین، با ترکیب انواع مختلف برای نقطه 1 و نقطه 2، می توان انواع متعددی از زیگ زاگ را به دست آورد. از این گذشته، هیچ چیز مانع استفاده از داده های RSI برای نقطه 1 و تعیین جهت بر اساس Stochastic و غیره نمی شود. نقطه 3 فقط برای اینکه نشانگر شبیه یک زیگزاگ به نظر برسد ضروری است، اگرچه گزینه های ترسیم می توانند بسیار متفاوت باشند.

از آنجایی که در اینجا وظیفه به دست آوردن یک نشانگر جهانی است، لازم است الگوریتم را با دقت هر چه بیشتر به دو قسمت تقسیم کنیم: بخشی که برای همه زیگ زاگ ها یکسان است (آن را مشترک می نامیم) و بخشی که به نوع ZigZag بستگی دارد (آن را فردی بنامیم.). بخش جداگانه بافرهای نشانگر را با داده های منبع پر می کند: داده های قیمت یا شاخص. بافر دیگری (تعیین جهت خط ZigZag) با مقادیر 1 ی ا-1 پر می شود. این سه بافر به قسمت مشترک منتقل می شوند که از آنها برای رسم خود نشانگر استفاده می کند.

برای روشن شدن موضوع، ابتدا یک نشانگر جداگانه ایجاد کنید که بر اساس High/Low نوار عمل می کند و جهت خود را بر اساس High/Low نوار n-ام تغییر می دهد.

ZigZag ساده بر اساس High/Low

در متائیتور یک شاخص جدید ایجاد کنید (منوی اصلی - پرونده - جدید یا Ctrl+N را فشار دهید). در جادوگر ایجاد نشانگر ، نام "ihighlowzigzag" را وارد کنید ، یک پارامتر خارجی "دوره" (نوع int ، با مقدار 12) ایجاد کنید ، onCalculate (. باز ، بالا ، کم ، نزدیک) رویداد را انتخاب کنید ، یک بافر را با یک بافر ایجاد کنید. نام "Zigzag" (نوع بخش ، با رنگ قرمز) و سه بافر دیگر با نام "Direction" ، "Lasthighbar" و "Lastlowbar" (نوع خط ، با رنگ - هیچ).

بافر "زیگزاگ" برای نمایش زیگزاگ استفاده می شود ، بافر باقیمانده کمکی هستند. برای همه بافرهای کمکی ، نوع indicator_data را در تماس با عملکرد setIndexBuffer () در داخل عملکرد oninit () به شاخص_ک محاسبه کنید. در بالای پرونده ، مقدار خاصیت indindator_plots را تغییر دهید: مقدار را روی 1 تنظیم کنید. پس از آن ، نشانگر فقط یک بافر "Zigzag" را ترسیم می کند ، و شاخص هیچ خط اضافی را ترسیم نمی کند ، بلکه در یکسان است. زمان ، بافرهای اضافی برای عملکرد با عملکرد ICUSTOM () در دسترس خواهد بود.

اول ، شاخص نوار برای شروع محاسبه (متغیر "شروع") در عملکرد Onccalute () تعیین می شود ، به طوری که محاسبه بر روی همه میله ها فقط با شروع شاخص انجام می شود ، و به طوری که محاسبات بیشتر فقط انجام می شوددر هر نوار جدیدعلاوه بر این ، عناصر بافر را آغاز کنید:

int start ؛// متغیر برای شاخص میله ها برای شروع محاسبه از if (prev_calculated == 0)< // at startup // initialize the buffer elements DirectionBuffer[ 0 ]= 0 ; LastHighBarBuffer[ 0 ]= 0 ; LastLowBarBuffer[ 0 ]= 0 ; start= 1 ; // calculation starting from the elements following the initialized ones >دیگر< // during operation start=prev_calculated- 1 ; > >

اکنون ، چرخه نشانگر اصلی:

همانطور که در بالا توضیح داده شد ، برای دستیابی به جهانی بودن ، لازم است کد را به محاسبه جهت زیگزاگ و نقشه برداری آن تقسیم کنید. اکنون این اصل نیز تأیید خواهد شد. ابتدا کد را برای تعیین جهت بنویسید. برای تعیین جهت ، از توابع arraymaximum () و arrayminimum () استفاده کنید. اگر یک بالا یا پایین در نوار محاسبه شده تعیین شود ، به عنصر آرایه جهت مقدار 1 ی ا-1 اختصاص داده می شود. برای داشتن اطلاعات در مورد جهت فعلی زیگزاگ در هر نوار ، قبل از محاسبه جهت ، مقدار را از عنصر قبلی بافر جهت بگیرید و آن را به عنصر فعلی اختصاص دهید:

// مقدار جهت قبلی تعیین شده // را از عنصر قبلی DirectionBuffer [i] = DirectionBuffer [I- 1] دریافت کنید.

// محاسبه نوار اولیه برای // توابع arraymaximum () و arrayminimum () int ps = i-period+ 1 ؛// تعیین میله های زیاد و پایین در // دامنه "دوره" میله int hb = arraymaximum (بالا ، ps ، دوره) ؛int lb = arrayminimum (کم ، ps ، دوره) ؛

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

به طور کلی ، در ترمینال Metatrader 5 ، می توان یک زیگزاگ را ایجاد کرد که بخش های عمودی را ترسیم می کند ، و این امکان را فراهم می کند تا دو تغییر در جهت نشانگر در همان نوار نمایش داده شود. با این حال ، چنین انواع زیگزاگ در این مقاله در نظر گرفته نمی شود.

بگذارید نوشتن کد را در حلقه اصلی ادامه دهیم: قطعه زیر مسئول ترسیم خط زیگزاگ خواهد بود. دو بافر دیگر مانند بافر جهت رفتار می شوند:

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

حتما بافر زیگزاگ را پاک کنید:

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

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

switch (( int )DirectionBuffer[i]) case 1 : switch (( int )DirectionBuffer[i- 1 ]) case 1 : // continuation of an upward movement . break ; case - 1 : // beginning of a new upward movement . break ; > break ; case - 1 : switch (( int )DirectionBuffer[i- 1 ]) case - 1 : // continuation of a downward movement . break ; case 1 : // beginning of a new downward movement . break ; >زنگ تفريح ؛

نوشتن چهار بلوک کد باقی مانده است. دو مورد از آنها در جزئیات در نظر گرفته می شوند: آغاز یک حرکت جدید رو به بالا و ادامه حرکت رو به بالا. شروع یک حرکت صعودی جدید هنگامی اتفاق می افتد که مقدار در بافر جهت ا ز-1 به 1 تغییر کند. وقتی این اتفاق می افتد ، الگوریتم نقطه جدیدی از زیگزاگ را ترسیم می کند و شاخص نوار را ذخیره می کند ، جایی که جهت جدید شروع شده است:

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

// continuation of an upward movement if (high[i]>High [(int) lasthighbarbuffer [i]])< // new High // remove the old ZigZag point ZigZagBuffer[( int )LastHighBarBuffer[i]]= EMPTY_VALUE ; // place a new point ZigZagBuffer[i]=high[i]; // index of the bar with the new top LastHighBarBuffer[i]=i; >

این استفراموش نکنید که حلقه را با یک بریس پایانی ببندید. این برای آزمایش شاخص در حالت بصری تستر استراتژی باقی مانده است. شاخص کاملاً عملیاتی "Ihighlowzigzag" را می توان در ضمیمه یافت.

زیگزاگ ساده بر اساس نزدیک

اکنون اجازه دهید ما نشانگر تازه ایجاد شده را برای کار بر اساس قیمت نزدیک تجدید نظر کنیم. نیازی به شروع از ابتدا نیست: نشانگر "ihighlowzigzag" را با نام "iClosezigzag" ذخیره کنید و تماس ها را به آرایه های "بلند" و "پایین" جایگزین کنید و تماس با آرایه "نزدیک" را جایگزین کنید. این به ظاهر کار را کامل می کند ، اما آزمایش عملکرد نادرست شاخص را نشان می دهد (شکل 6).

شکل 6. عملکرد نادرست زیگزاگ بر اساس "نزدیک" ، که از شاخص بر اساس بالا/پایین تبدیل شده است

بگذارید ببینیم چرا این اتفاق می افتد. اگر قیمت بالای نوار فعلی در محدوده خاصی از میله ها قرار داشته باشد ، مهم نیست که این نوار همچنان در صدر قرار دارد ، مهم نیست که قیمت نزدیک نوار چگونه تغییر کند. اگر بالا با قیمت نزدیک تشکیل شود ، ممکن است قیمت نزدیک در هنگام تشکیل نوار تغییر کند و بالاترین میزان وجود آن را متوقف کند. هنگام تعیین یک بالا/پایین جدید در همان جهت ، شرط حذف نقطه قدیمی نیز برآورده می شود - این جایی است که مشکل در انتظار است. ارتفاع جدید لغو شد ، نقطه جدید حذف شد ، اما قدیمی نیز حذف شد. بنابراین ، لازم است موقعیت نقطه قدیمی را بازگرداند. اطلاعات مربوط به موقعیت آخرین افراط و تفریط در بافرها موجود است: Lasthighbarbuffer و Lastlowbaruffer. دو نکته جدید از آنها بازگردانده می شود. قبل از اپراتور سوئیچ ، دو خط کد را به حلقه اصلی نشانگر اضافه کنید:

Zigzagbuffer [(int) lasthighbarbuffer [i]] = Close [(int) lasthighbarbuffer [i]] ؛Zigzagbuffer [(int) Lastlowbarbuffer [i]] = Close [(int) lastlowbarbuffer [i]] ؛

پس از این تجدید نظر ، شاخص باید به درستی کار کند. شاخص "Iclosezigzag" حاصل را می توان در پیوست های مقاله یافت.

شروع به ایجاد زیگزاگ جهانی

  1. پر کردن بافر با داده های منبع. از دو بافر استفاده خواهد شد. آنها مورد نیاز هستند تا بتوانند با قیمت های بالا و پایین پر شوند. برای به دست آوردن یک زیگزاگ بر اساس نزدیک یا هر شاخص دیگر ، هر دو بافر باید با همان مقادیر پر شوند.
  2. پر کردن بافر جهت بر اساس تجزیه و تحلیل داده های منبع.
  3. ترسیم زیگزاگ.

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

کلاس برای داده های منبع

ایجاد "csorcedata. mqh" شامل پرونده ، کلاس csorcedata را به آن اضافه کنید. این کلاس والدین خواهد بود. این شامل یک روش "محاسبه" مجازی شبیه به عملکرد onCcculate () شاخص است ، اما با تغییرات خاصی. دو آرایه اضافی به روش منتقل می شوند: Bufferhigh [] و Bufferlow []. این بافرها پر از داده هایی هستند که بیشتر برای محاسبه زیگزاگ استفاده می شوند. از آنجا که نه تنها قیمت ، بلکه مقادیر هر شاخص دیگر ممکن است به عنوان داده منبع عمل کند ، لازم است فرآیند بارگذاری شاخص را کنترل کنید. برای انجام این کار ، روش مجازی CheckHandle () (نوع BOOL) را اضافه کنید:

اکنون چندین کلاس کودک ایجاد کنید. یکی برای قیمت بالا/پایین:

یکی دیگر برای قیمت نزدیک. این فقط در کد داخل حلقه متفاوت خواهد بود:

نام این کلاس "CCLOSE: Public Csorcedata" است. روش CheckHandle () تاکنون استفاده نشده است.

ما همچنین برای به دست آوردن داده از شاخص ها ، چند کلاس ایجاد خواهیم کرد. اجازه دهید شاخص ها را با تعداد مختلف پارامترها و مکان های مختلف (در نمودار قیمت یا در Subwindow جداگانه) - RSI و میانگین متحرک انتخاب کنیم. بگذارید کلاسهای خود را برای آنها بنویسیم.

یک کلاس برای RSI ایجاد کنید ، آن را "CRSI: عمومی Csorcedata" نامگذاری کنید. متغیر را برای دسته شاخص به بخش خصوصی اضافه کنید:

سازنده را اضافه کنید: پارامترهای RSI به آن منتقل می شوند و شاخص در درون آن بارگذاری می شود:

void CRSI( int period, ENUM_APPLIED_PRICE price) m_handle= iRSI ( Symbol (), Period (),period,price); >

اکنون ، روش checkhandle ():

روش محاسبه از یک چرخه استفاده نمی کند ، بلکه یک کپی ساده از بافرها است:

int to_copy; if (prev_calculated== 0 ) to_copy=rates_total; > else to_copy=rates_total-prev_calculated; to_copy++; >

if ( CopyBuffer (m_handle, 0 , 0 ,to_copy,BufferHigh) retu ( 0 ); >

if ( CopyBuffer (m_handle, 0 , 0 ,to_copy,BufferLow) retu ( 0 ); >بازگشت (نرخ_توتال) ؛

لطفاً توجه داشته باشید: در صورت عدم موفقیت کپی (با عملکرد CopyBuffer () تماس بگیرید) روش 0 را برمی گرداند ، و در صورت کپی موفق - نرخ_توتال. این کار به منظور امکان محاسبه مجدد بعدی شاخص در صورت کپی شکست خورده انجام می شود.

به طور مشابه ، برای میانگین متحرک ، کلاس به نام "CMA: عمومی Csorcedata" ایجاد کنید. تفاوت ها فقط در سازنده است:

void CMA( int period, int shift, ENUM_MA_METHOD method, ENUM_APPLIED_PRICE price) m_handle= iMA ( Symbol (), Period (),period,shift,method,price); >

در این حالت ، روشهای محاسبه () کاملاً یکسان بودند ، اما شاخص های دیگر ممکن است به ویژه با تعداد بافر تفاوت های خاصی داشته باشند. پرونده کاملاً عملیاتی "csorcedata. mqh" را می توان در ضمیمه یافت. اگرچه ، لازم به ذکر است که می توان آن را فقط به صورت آزمایشی کاملاً عملیاتی تلقی کرد ، زیرا این امر حاکی از گسترش بیشتر از طریق افزودن روش های جدید کودک برای سایر شاخص ها است.

کلاس برای جهت

این کلاس در پرونده "czzdirection. mqh" ، نام کلاس پایه - "czzDirection" قرار خواهد گرفت. کلاس شامل یک روش محاسبه مجازی () خواهد بود. این پارامترهایی که امکان تعیین میله های محاسبه (نرخ های_توتال ، متغیرهای prev_calculated) ، بافر با داده های منبع و بافر برای جهت را تعیین می کند ، منتقل می شود. همانطور که قبلاً ذکر شد ، جهت Zigzag را می توان با استفاده از یک شاخص تعیین کرد ، بنابراین امکان استفاده از شاخص ها نیز اضافه می شود. روش مجازی checkhandle () را اضافه کنید:

class CZZDirection private : public : virtual int Calculate( const int rates_total, const int prev_calculated, double &BufferHigh[], double &BufferLow[], double &BufferDirection[]) retu ( 0 ); > virtual bool CheckHandle() retu ( true ); > >;

حال بگذارید یک کلاس کودک برای تعیین جهت ، مانند شاخص "Ihighlowzigzag" بنویسیم. تعیین جهت با استفاده از این روش به پارامتر "دوره" نیاز دارد. بنابراین ، M_Period و سازنده با پارامتر دوره به بخش خصوصی اضافه می شوند:

class CNBars: public CZZDirection private : int m_period; public : void CNBars( int period) m_period=period; >int محاسبه (const int rates_total ، const int prev_cccolled ، double & bufferhigh [] ، double & bufferlow [] ، double & bufferdirection []) int int شروع می شود.

if (prev_calculated== 0 ) BufferDirection[ 0 ]= 0 ; start= 1 ; > else start=prev_calculated- 1 ; >

int ps = i-m_period+ 1 ؛int hb = arraymaximum (Bufferhigh ، ps ، m_period) ؛int lb = arrayminimum (بافر ، PS ، m_period) ؛

کلاس کودک دیگری برای تعیین جهت بر اساس نشانگر CCI ایجاد می شود. موقعیت CCI بالاتر از صفر با جهت رو به بالا زیگزاگ ، زیر صفر - جهت رو به پایین مطابقت دارد:

class CCCIDir: public CZZDirection private : int m_handle; public : void CCCIDir( int period, ENUM_APPLIED_PRICE price) m_handle= iCCI ( Symbol (), Period (),period,price); > bool CheckHandle() retu (m_handle!= INVALID_HANDLE ); > int Calculate( const int rates_total, const int prev_calculated, double &BufferHigh[], double &BufferLow[], double &BufferDirection[] ) int start; if (prev_calculated== 0 ) BufferDirection[ 0 ]= 0 ; start= 1 ; > else start=prev_calculated- 1 ; >

Double Buf [1] ؛if (copybuffer (m_handle ، 0 ، rates_total- 1 ، 1 ، buf)

if (buf[ 0 ]> 0 ) BufferDirection[i]= 1 ; >دیگری اگر (buf [0]< 0 ) BufferDirection[i]=- 1 ; > > retu (rates_total); > >;

پارامترهای CCI به سازنده کلاس منتقل می شود و سپس بارگیری می شود. از روش checkhandle () استفاده می شود که باید پس از ایجاد جسم فراخوانی شود. حلقه اصلی CCI را بررسی می کند و بافر بافر را پر می کند.

پرونده "czzdirection. mqh" را می توان در پیوست ها یافت.

کلاس برای ترسیم

گزینه های مختلفی برای ترسیم زیگزاگ وجود دارد. می توان آن را با یک خط واحد ترسیم کرد ، می تواند رنگ شود ، می تواند در قله های آن نقاط و غیره داشته باشد. بشرکلاس در پرونده "czzdraw. mqh" ، نام کلاس - "czzdraw" قرار خواهد گرفت. کلاس شامل یک روش محاسبه مجازی () با همان پارامترهای کلاس برای جهت است. علاوه بر این ، از سه آرایه از Zigzag عبور خواهد کرد: Bufferlasthighbar (برای شاخص آخرین HIGH) ، Bufferlastlowbar (برای شاخص آخرین کم) ، بافر (خود زیگزاگ).

برای (int i = start ؛ i

Bufferzigzag [(int) bufferlasthighbar [i]] = bufferhigh [(int) bufferlasthighbar [i]] ؛Bufferzigzag [(int) bufferlastlowbar [i]] = bufferlow [(int) bufferlastlowbar [i]] ؛

switch (( int )BufferDirection[i]) case 1 : switch (( int )BufferDirection[i- 1 ]) case 1 : if (BufferHigh[i]>BufferHigh[( int )BufferLastHighBar[i]]) BufferZigZag[( int )BufferLastHighBar[i]]= EMPTY_VALUE ; BufferZigZag[i]=BufferHigh[i]; BufferLastHighBar[i]=i; > break ; case - 1 : BufferZigZag[i]=BufferHigh[i]; BufferLastHighBar[i]=i; break ; >زنگ تفريح ؛مورد - 1: سوئیچ ((int) BufferDirection [I- 1]) مورد - 1: if (bufferlow [i] break ; case 1 : BufferZigZag[i]=BufferLow[i]; BufferLastLowBar[i]=i; break ; > break ; > > retu (rates_total); > >;

این کلاس در جزئیات مورد بحث قرار نمی گیرد ، همانطور که همه این موارد قبلاً در بخش های "زیگزاگ ساده بر اساس بالا/پایین" و "زیگزاگ ساده بر اساس بخش های نزدیک" شرح داده شده است. پرونده "czzdraw. mqh" را می توان در پیوست ها یافت.

سه کلاس را ادغام کنید

سرانجام ، نوشتن یک شاخص با استفاده از سه کلاس ایجاد شده در بالا لازم است. کلاس برای داده های منبع امکان استفاده از داده های قیمت و داده های نشانگر RSI را فراهم می کند ، که معمولاً در یک زیر مجموعه کار می کند. داده های قیمت را می توان در یک زیر مجموعه نمایش داده کرد ، اما RSI را نمی توان در نمودار قیمت نمایش داد. بنابراین ، ما یک شاخص برای زیر مجموعه ایجاد خواهیم کرد.

در متائیتور یک شاخص جدید ایجاد کنید (منوی اصلی - پرونده - جدید یا Ctrl+N را فشار دهید). در جادوگر ایجاد نشانگر ، نام "iUnizigzagsw" را وارد کنید ، یک پارامتر خارجی "دوره" (نوع int ، با مقدار 12) ایجاد کنید ، کنترل کننده رویداد onCalculate (. باز ، بالا ، پایین ، نزدیک) را انتخاب کنید ، بافر های زیر را ایجاد کنید:

 

نامسبکرنگ
عالیخطسبز
کمخطسبز
زیگ زاگبخشقرمز
جهتخطهیچ یک
قاتلخطهیچ یک
نوارخطهیچ یک

پس از ایجاد شاخص جدید ، سه پرونده با کلاس را درج کنید:

شاخص باید پارامترهایی برای انتخاب نوع داده منبع و نوع تعیین جهت داشته باشد. برای این منظور دو شمارش ایجاد کنید:

enum ESorce Src_HighLow= 0 , Src_Close= 1 , Src_RSI= 2 , Src_MA= 3 >; enum EDirection Dir_NBars= 0 , Dir_CCI= 1 >;

برای این نوع دو پارامتر خارجی ایجاد کنید:

پارامترهای مربوطه برای داده های منبع RSI و MA و همچنین برای شاخص CCI مورد نیاز است. آنها را اضافه کنید:

ورودی int rsiperiod = 14 ؛input enum_applied_price rsiprice = price_close ؛ورودی int maperiod = 14 ؛ورودی int mashift = 0 ؛ورودی enum_ma_method mamethod = mode_sma ؛ورودی enum_applied_price maprice = price_close ؛ورودی int cciperiod = 14 ؛input enum_applied_price cciprice = price_typical ؛

پارامتر اضافی برای تعیین جهت بیش از N-BARS نیز لازم است:

اکنون چیز جالب تر - سه نشانگر مطابق با انواع کلاس پایه (زیر پارامترهای خارجی):

کلاس های کودک مربوطه را مطابق با متغیرهای SrcSelect و Dirlect ، در عملکرد OnInit بارگیری کنید. اول ، srcSelect:

switch (SrcSelect) case Src_HighLow: src= new CHighLow(); break ; case Src_Close: src= new CClose(); break ; case Src_RSI: src= new CRSI(RSIPeriod,RSIPrice); break ; case Src_MA: src= new CMA(MAPeriod,MAShift,MAMethod,MAPrice); break ; >

پس از بارگیری ، دسته را بررسی کنید:

پس از آن ، The Direlect:

switch (DirSelect) case Dir_NBars: dir= new CNBars(ZZPeriod); break ; case Dir_CCI: dir= new CCCIDir(CCIPeriod,CCIPrice); break ; >

بررسی دسته:

اشیاء را در عملکرد Ondeinit () حذف کنید:

void OnDeinit ( const int reason) if ( CheckPointer (src)== POINTER_DYNAMIC ) delete (src); > if ( CheckPointer (dir)== POINTER_DYNAMIC ) delete (dir); > if ( CheckPointer (zz)== POINTER_DYNAMIC ) delete (zz); > >

و اکنون ، لمس نهایی - عملکرد Onccalulate (). روشهای محاسبه () کلاسهای csorcedata و czzDirection ممکن است 0 برگردد ، بنابراین نتیجه را بررسی کنید. در صورت بروز خطا (مقدار 0 را دریافت کرده است) ، همچنین 0 را برگردانید ، به طوری که یک محاسبه کامل در تیک بعدی انجام می شود:

rv = src. calculate (نرخ_توتال ، prev_cccolution ، زمان ، باز ، بالا ، کم ، نزدیک ، تیک_ولوم ، حجم ، پخش ، بافر بالا ، کمربند) ؛

if (rv == 0) بازگشت (0) ؛

rv = dir. calculate (نرخ_توتال ، prev_calculated ، highbuffer ، lowbuffer ، directionbuffer) ؛

if (rv == 0) بازگشت (0) ؛

zz. calculate (نرخ_توتال ، prev_cccolution ، highbuffer ، lowbuffer ، directionbuffer ، lasthighbarbuffer ، lastlowbarbuffer ، Zigzagbuffer) ؛

شاخص "iUnizigzagsw" را می توان در پیوست ها یافت.

نوع برای نمودار قیمت

نشانگر حاصل شامل همه انواع قبلاً ایجاد شده است ، هم با داده های منبع مربوط به نمودار قیمت و برای زیر مجموعه ، بنابراین برای زیر مجموعه ایجاد شده است. با این حال ، خوب است که زیگزاگ را در نمودار قیمت نیز ببینید. در این حالت ، لازم است که منبع داده RSI را فدا کنید. یک کپی از شاخص با نام "iUnizigzag" ایجاد کنید ، ویژگی indinaiz_separate_window را به شاخص_چارت_ویندو تغییر دهید ، نوع src_rsi را از شمارش esorce حذف کنید ، نوع RSI را از عملکرد OnInit () حذف کنید و نوع را برای نمودار قیمت بدست آورید. شاخص تکمیل شده "iUnizigzag" را می توان در پیوست ها یافت.

نوع برای قیمت

می توان شاخص هایی را برای ترمینال Metatrader ایجاد کرد ، که مبتنی بر داده های منبع کاملاً تعریف شده بلکه در هر شاخص دیگری که در نمودار قرار دارد ، کار می کند. هنگام وصل کردن چنین شاخصی به نمودار یا Subwindow ، "Apply to" Parameter "را به" داده های شاخص قبلی "یا" داده های شاخص اول "تنظیم کنید. بگذارید نشانگر "iUnizigzagsw" را اصلاح کنیم تا بتواند آن را روی یک شاخص دیگر "قرار دهد". نشانگر را تحت نام "iUnizigzagpricesw" ذخیره کنید و همه چیز مربوط به کلاس Csorcedata را حذف کنید ، نوع عملکرد Oncalculate را تغییر دهید ، و در شروع عملکرد ، یک حلقه برای جمع کردن بافر های بافر و Lowbuffer با مقادیر قیمت بنویسیدآرایه:

int OnCalculate ( const int rates_total, const int prev_calculated, const int begin, const double &price[] ) int start; if (prev_calculated== 0 ) start= 0 ; > else start=prev_calculated- 1 ; >

برای (int i = start ؛ iint rv ؛rv = dir. calculate (نرخ_توتال ، prev_calculated ، highbuffer ، lowbuffer ، directionbuffer) ؛

if (rv== 0 ) retu ( 0 ); zz.Calculate(rates_total, prev_calculated, HighBuffer, LowBuffer, DirectionBuffer, LastHighBarBuffer, LastLowBarBuffer, ZigZagBuffer); retu (rates_total); >

به همین ترتیب ، می توان بر اساس آرایه قیمت ، یک نوع از آثار را در نمودار قیمت ایجاد کرد. برای انجام این کار ، کافی است که شاخص indindator_separate_window را به شاخص "iUnizigzagpricesw" تغییر دهید. شاخص "iUnizigzagpricesw" را می توان در ضمیمه یافت. نشانگر Iunizigzagprice را نیز می توان در آنجا یافت ، این نوع برای نمودار قیمت بر اساس آرایه قیمت است.

تماس از یک متخصص

به طور معمول ، هنگام فراخوانی زیگزاگ از یک متخصص ، آخرین قسمت بالا یا پایین را در یک چرخه جستجو می کند ، بر روی میله ها تکرار می شود و مقادیر موجود در بافر را برای ترسیم زیگزاگ بررسی می کند. همه اینها با هم بسیار کند است. زیگزاگ توسعه یافته در این مقاله دارای بافرهای اضافی است که به شما امکان می دهد به سرعت تمام داده های مورد نیاز را بدست آورید. بافر DirectionBuffer حاوی داده هایی در مورد جهت آخرین بخش زیگزاگ است. بافرهای Lasthighbarbuffer و Lastlowbarbuffer حاوی شاخص های میله ها هستند که در آن آخرین قسمت بالا و پایین ثبت شده است. دانستن شاخص نوار هنگام شمارش از یک طرف و تعداد میله ها ، می توان شاخص نوار را برای شمارش از طرف دیگر محاسبه کرد (نشانگر از چپ به راست شمارش می شود ، و عملکرد کپی کننده ()از راست به چپ در حال شمارش است). با استفاده از شاخص نوار ، می توان مقدار زیگزاگ را در این نوار دریافت کرد.

از کد زیر می توان برای به دست آوردن داده ها از شاخص استفاده کرد. بگذارید با شاخص "iUnizigzagsw" آزمایش کنیم. شاخص را در عملکرد OnInit () بارگذاری کنید:

دسته = icustom (نماد () ، دوره () ، "iunizigzagsw" ، srcselect ، dirlect ، rsiperiod ، rsiprice ، maperiod ، mashift ، mamethod ، maprice ، cciperiod ، cciprice ، zzperiod) ؛

string cs= "" ; // direction double dir[ 1 ]; if ( CopyBuffer (handle, 3 , 0 , 1 ,dir) Print ( "Error obtaining data from the ZigZag" ); retu ; > if (dir[ 0 ]== 1 ) cs=cs+ "Direction Up" ; > if (dir[ 0 ]==- 1 ) cs=cs+ "Direction Down" ; >نظر (CS ، " n" ، getTickCount ()) ؛

اکنون مقادیر چندین تاپ/پایین را دریافت کنید. اگر خط نشانگر به سمت بالا هدایت شود ، ما شاخص نوار را با جدیدترین قسمت از بافر Lasthighbarbuffer دریافت می کنیم. سپس از آن برای محاسبه شاخص نوار هنگام شمارش از راست به چپ استفاده کنید. این شاخص را می توان برای به دست آوردن مقدار بافر زیگزاگفر استفاده کرد. ما می توانیم فراتر برویم: مقدار را از بافر Lastlowbarbuffer برای نوار دریافت کنید ، جایی که مقدار زیگزاگ به دست آمده است. این شاخص نوار با پایین قبلی خواهد بود. و به همین ترتیب ، تماس های متناوب به بافر Lasthighbarbuffer و Lastlowbarbuffer اجازه می دهد تا داده ها را در تمام قسمت های پایین/پایین خط نشانگر جمع آوری کنند. در زیر نمونه ای از کد برای گرفتن دو نکته جدید زیگزاگ هنگام هدایت به سمت بالا آورده شده است:

if (dir[ 0 ]== 1 ) // index of the bar with the latest top when counting to the left of zero if ( CopyBuffer (handle, 4 , 0 , 1 ,lhb) Print ( "Error obtaining data from the ZigZag 2" ); retu ; >// شاخص نوار هنگام شمارش در سمت راست صفر ind = میله- (int) LHB [0]- 1 ؛

// value of the ZigZag at the ind bar if ( CopyBuffer (handle, 2 ,ind, 1 ,zz) Print ( "Error obtaining data from the ZigZag 3" ); retu ; > //=== // index of the bottom preceding this top if ( CopyBuffer (handle, 5 ,ind, 1 ,llb) Print ( "Error obtaining data from the ZigZag 4" ); retu ; >// شاخص نوار هنگام شمارش در سمت راست صفر ind = میله- (int) llb [0]- 1 ؛

// value of the ZigZag at the ind bar if ( CopyBuffer (handle, 2 ,ind, 1 ,zz1) Print ( "Error obtaining data from the ZigZag 5" ); retu ; >

cs=cs+ " " +( string )zz1[ 0 ]+ " " +( string )zz[ 0 ]; >دیگری اگر (dir [0] ==- 1)

مثال کامل را می توان در کارشناس ضمیمه "Eunizigzagsw" یافت. EA با پیام در مورد جهت زیگزاگ ، و همچنین دو عدد با مقادیر دو نقطه جدید زیگزاگ در خط دوم ، یک نظر نمودار را منتشر می کند (شکل 7). خط سوم به سادگی شماره ای است که توسط عملکرد GetTickCount () بازگردانده شده است تا روشن شود که متخصص کار می کند.

شکل 7. گوشه سمت چپ بالا حاوی خروجی پیام توسط متخصص است

البته داده های مربوط به آخرین نقاط شاخص را می توان با گرفتن مقادیر خود در صفر یا نوار اول از بافر Lasthighbarbuffer و Lastlowbarbuffer بدست آورد ، اما نکته این مثال استخراج متوالی داده ها از هر تعداد از نقاط زیگزاگ است.

تماس از یک شاخص دیگر

اگر یکی از شاخص ها بر اساس دیگری باشد ، در مورد زیگزاگ ، ساده تر نیست که با استفاده از ICUSTOM () با نشانگر تماس نگیرید ، بلکه کپی آن را انجام دهید و آن را اصلاح کنید. این رویکرد ممکن است در برخی موارد (از نظر سرعت اصلاح و سادگی) توجیه شود ، در برخی - نه (از نظر استفاده مجدد از کد و انعطاف پذیری). به شاخص های ایجاد شده در این مقاله می توان هنگام توسعه شاخص های دیگر از طریق عملکرد ICUSTOM دسترسی پیدا کرد.

به خودی خود ، زیگزاگ تاریخ دیگر چیزی نیست که در واقع در زمان شکل گیری آن تاریخ اتفاق افتاده است. با این حال ، بافر Lasthighbarbuffer و Lastlowbarbuffer وجود دارد که داده ها را در حالت های میانی زیگزاگ ذخیره می کنند. برای شفافیت ، اجازه دهید یک نشانگر ایجاد کنیم که هنگام تغییر خط نشانگر (تغییر در مقدار بافر جهت دار) ، فلش را ترسیم کند و نقاط را روی میله هایی قرار دهد که در آن بالا/پایین ترین سطح زیگزاگ ثبت شده است (تغییر در آنمقادیر بافر Lasthighbarbuffer و Lastlowbarbuffer). کد این شاخص به تفصیل مورد بحث قرار نمی گیرد ، می توان آن را تحت عنوان "iUnizigzagsgswevents" در پیوست ها یافت. ظاهر نشانگر در شکل 8 نشان داده شده است.

شکل 8. نشانگر Iunizigzagsgswevents

نتیجه

از آنجا که مقاله پس از همه یک ماده آموزشی است و راه حل های آماده و کاملی را ارائه نمی دهد ، تمام شاخص های ایجاد شده در مقاله حداقل انتخابی برای داده های منبع و انواع برای تعیین جهت دارند. با این حال ، روند ایجاد شاخص ها با جزئیات بسیار شرح داده شده است ، بنابراین پس از درک مقاله می توانید تمام کلاسهای مورد نیاز کودک خود را ایجاد کنید. علاوه بر این ، تلاش برای به دست آوردن یک شاخص کاملاً جهانی ، نه در مرحله آفرینش ، نه در مرحله آفرینش ، مانند زمان استفاده بیشتر. هنگام افزودن شاخص های مختلف به عنوان منابع داده یا برای تعیین جهت ، لازم است پارامترها را برای آن شاخص ها به پنجره Properties اضافه کنید. در پایان ، تعداد پارامترها خیلی بزرگ می شود و استفاده از چنین شاخصی بسیار ناخوشایند خواهد بود. ایجاد شاخص های جداگانه با استفاده از کلاسهای جهانی به دست آمده در مقاله ارگونومیک تر خواهد بود.

فارکس اسلامی...
ما را در سایت فارکس اسلامی دنبال می کنید

برچسب : نویسنده : هدایت هاشمی بازدید : 69 تاريخ : پنجشنبه 3 فروردين 1402 ساعت: 22:09