مبانی نوشتن شاخص های کاربر | IFCM ایران
IFC Markets کارگزار CFD آنلاین

مبانی نوشتن شاخص های کاربر

مقدمه

مقالۀ حاضر به این منظور تهیه شده است تا مبانی ایجاد شاخص های کاربر را به روشنی توضیح داده و اشتباهاتی را بررسی کند که ممکن است برنامه نویس ها در اولین قدم های شان در توسعه در NTL+ (زبان NetTradeX) با آنها مواجه شوند.


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


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


نوشتن کد اسکریپت

الگوریتمی که استفاده خواهیم کرد ساده و گرافیکی است و همین کافی است که بتوان عمکردش را در نمودار قیمت ها به راحتی بررسی کرد. ما برای هر میلۀ i و آمارهای شکل، میله های n قبلی را تجزیه و تحلیل می کنیم که در آنجا اگر میله ها صعودی باشند، 1 را به نتیجه اضافه خواهیم کرد و اگر میله ها ریزشی باشند 1 را کسر خواهیم کرد.

img

در اینجا کد شاخص را بررسی می کنیم:


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

#set_indicator_separate
double ExtMapBuffer1[];
int ExtCountedBars=0;
extern int period = 10;

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


آرایۀ ExtCountedBars در واقع عرض های نقاطی که در نمودار هستند را ذخیره می کند ضمن اینکه طول های شان توسط شاخص عناصر آرایه تعریف می شود. سپس مقدار متغیر ExtCountedBars را به 0 می رسانیم؛ این عدد میله های محاسبه شده را ذخیره می کند. به این ترتیب، نیازی به محاسبۀ معمول برای تمام میله ها نیست در نتیجه محاسبۀ مقادیر شاخص و همچنین حرکت نمودار شاخص سرعت زیادی پیدا می کنند. خط بعدی بیانگر متغییر جهانی period است که تعداد فواصل زمانی را ذخیره می کند و شاخص در آن آمارش را محاسبه می کند. لطفاً توجه داشته باشید که کاربرد تغییر دهندۀ extern این امکان را برای مان فراهم می کند که با استفاده از ابزار امکانات شاخص و بدون هیچ جمع آوری مجدد ضروری، پارامترهای period را تغییر دهیم.


همینک به عملکرد Initialize() می پردازیم که در آن تنظیمات مبنایی برای شاخص مان را تعیین خواهیم کرد.


int Initialize() { Indicator.SetIndexCount(1); Indicator.SetIndexBuffer(0,ExtMapBuffer1); Indicator.SetIndexStyle(0,ltHistogram,lsSolid,5,clrBlue); return(0); }

روش SetIndexCount در شکل شاخص، کمیت حافظه ها برای مقادیر شاخص را تنظیم می کند. ما یک حافظه با مقادیر ExtMapBuffer1 داریم، پس "یک" را به عنوان تنها پارامتر تعیین می کنیم. ما همچنین باید رقم حافظه را به یک آرایه با مقادیر حافظه مرتبط کنیم. این رابطه در خط Indicator.SetIndexBuffer(0,ExtMapBuffer1) تعریف می شود که در آن مشخص شده است که خصوصیات شاخص صفر به منظور صدور مقادیر ذخیره شده در حافظۀ ExtMapBuffer1 بکار می روند


در خط بعدی، مشخصات شاخص مان را تنظیم می کنیم. اولین پارامتر روش SetIndexStyle عدد حافظه است که مقدارش "0" است که در SetIndexBuffer مشخص کرده ایم. پارامتر دوم نوع طراحی را نشان می دهد - یک نمودار ستونی. در سومین پارامتر، خط روش lsSolid را تعیین می کنیم (در واقع، در اینجا هر مقداری را می توانیم مشخص کنیم چراکه مقدار این پارامتر فقط روی خط و نمودارهای میله ای با ضخامت 1 تاثیر می گذارد). در پارامترهای بعدی، ضخامت 5 را برای خط و رنگ آبی را با استفاده از مقدار ثابت متناظر clrBlue تنظیم می کنیم (همچنین می توانیم رنگ را در فرمت RGB مشخص کنیم، بطور مثل:0x0000FF )


سپس عمکلرد Run() می آید که بررسی های پایه را اجرا می کند و عملکرد کاربر draw() را راه می اندازد که کل محاسبه را انجام می دهد.


int Run() { ExtCountedBars=Indicator.Calculated; if (ExtCountedBars < 0) { System.Print("Error"); return(-1); } draw(); return(0); }

ما تعداد میله ها که از آخرین فراخوان تاکنون تغییر نکرده اند را در متغییر جهانی ExtCountedBars ذخیره می کنیم. ما تا اینجا این مقادیر را محاسبه کرده ایم به همین آنها نباید دوباره محسابه شوند. سپس تعریف می کنیم که تحویل شاخص در ExtCountedBars< 0 را متوقف کنیم. سپس عملکرد draw() فراخوانده می شود که مقادیر را محاسبه خواهد کرد و آنها در حافظۀ شاخص قرار می دهد.


void draw() { int pos=Chart.Bars-ExtCountedBars-1; int value; while(pos>=0) { value=0; for(int i=pos;i < pos+period && i < Chart.Bars-1;i++) { if(Open[i] < Close[i]) value+=1; else value-=1; } ExtMapBuffer1[pos]=value; pos--; } }

در خط 'int pos=Chart.Bars-ExtCountedBars-1' ، موقعیت شروع برای محاسبۀ مقادیر را با حرکت از دادۀ قبلی به بعدی تعیین می کنیم. همراه با تعداد میله ها که در مجموع به Chart.Bars می رسند، عنصر دورتر شاخص Chart.Bars-1 را خواهد داشت. با احتساب تعداد میله هایی که تاکنون محاسبه شده اند، شاخص Chart.Bars-ExtCountedBars-1 خواهد بود. متغییر value برای جمع آوری آمارها استفاده می شود. سپس در چرخۀ از Chart.Bars-ExtCountedBars-1 تا 0 ، برای هر میله و نه بیشتر از بازگشت موقعیت های Period آمار را جمع آوری می کنیم.


قرار دادن تمام کد در کنار یکدیگر:


#set_indicator_separate double ExtMapBuffer1[]; int ExtCountedBars=0; extern int period = 10; int Initialize() { Indicator.SetIndexCount(1); Indicator.SetIndexBuffer(0,ExtMapBuffer1); Indicator.SetIndexStyle(0,ltHistogram,lsDot,5,clrBlue); return(0); } int Run() { ExtCountedBars=Indicator.Calculated; if (ExtCountedBars < 0) { System.Print("Error"); return(-1); } draw(); System.Print("ExtCountedBars="+ExtCountedBars); return(0); } void draw() { int pos=Chart.Bars-ExtCountedBars-1; int value; while(pos>=0) { value=0; for(int i=pos;i < pos+period && i < Chart.Bars-1;i++) { if(Open[i] < Close[i]) value+=1; else value-=1; } ExtMapBuffer1[pos]=value; pos--; } }

همینک شاخص را اندکی پیشرفت می دهیم: ستون های منفی در یک رنگ و ستون های مثبت در رنگی دیگر نمایش داده خواهند شد. همزمان، هر ستون نیز دو رنگ خواهد داد. برای این منظور به 4 حافظه نیاز داریم:


#set_indicator_separate double ExtMapBuffer1[]; double ExtMapBuffer2[]; double ExtMapBuffer3[]; double ExtMapBuffer4[]; int ExtCountedBars=0; extern int period = 10; int Initialize() { Indicator.SetIndexCount(4); Indicator.SetIndexBuffer(0,ExtMapBuffer1); Indicator.SetIndexStyle(0,ltHistogram,lsDot,5,clrBlue); Indicator.SetIndexBuffer(1,ExtMapBuffer2); Indicator.SetIndexStyle(1,ltHistogram,lsDot,5,clrGreen); Indicator.SetIndexBuffer(2,ExtMapBuffer3); Indicator.SetIndexStyle(2,ltHistogram,lsDot,5,clrRed); Indicator.SetIndexBuffer(3,ExtMapBuffer4); Indicator.SetIndexStyle(3,ltHistogram,lsDot,5,clrLime); return(0); } int Run() { ExtCountedBars=Indicator.Calculated; if (ExtCountedBars < 0) { System.Print("Error"); return(-1); } draw(); return(0); } void draw() { int pos=Chart.Bars-ExtCountedBars-1; int value; while(pos>=0) { value=0; for(int i=pos;i < pos+period && i < Chart.Bars-1;i++) { if(Open[i] < Close[i]) value+=1; else value-=1; } if(value>0) { ExtMapBuffer1[pos]=value; ExtMapBuffer2[pos]=0; ExtMapBuffer3[pos]=1; ExtMapBuffer4[pos]=0; } if(value==0) { ExtMapBuffer1[pos]=0; ExtMapBuffer2[pos]=0; ExtMapBuffer3[pos]=0; ExtMapBuffer4[pos]=0; } if(value < 0) { ExtMapBuffer1[pos]=0; ExtMapBuffer2[pos]=value; ExtMapBuffer3[pos]=0; ExtMapBuffer4[pos]=-1; } } pos--; } }

شکل جدید شاخص با میله های رنگی:

img

در هنگام نوشتن کد شاخص ممکن است پیغام "run function call failed" (فراخوان ناموفق عملکرد اجرا) را مشاهده کنید. این پیغام خطا به احتمال زیاد زمانی رخ می دهد که مقادیر در عناصری با شاخص هایی وجود ندارند ذخیره شده اند. به این ترتیب اگر با چنین پیغامی مواجه شدید باید با دقت مقادیر برای شاخص های آرایۀ حافظه را تصحیح کنید.


خلاصه

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

Close support
Call to instagram Call to Telegram Call to WhatsApp Call Back