یک‌بار دیگر زیگزاگ‌ها

یک‌بار دیگر زیگزاگ‌ها

مقدمه

انواع و اقسام زیگزاگ‌ها را داریم و این خود یعنی وجود سودِ مداوم و ماندگار در این اندیکاتور. سودی که اَرزشش را دارد وقت صرف آن کنیم. شاید این تنها اندیکاتوری باشد که مستقیماً روی احساسات تریدر اثرگذار است و با ارائه‌ی حرکات اصلی بازار با یک حالت گرافیکی شفاف و قشنگ، تریدر را مجبور به واکنش‌های سریع می‌کند.

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

بیایید کمی بحث کنیم. باورتان بشود یا نشود، این تازه آغاز قصه است.

متن ترانه

تمام ماهایی که آمده‌ایم و در این بازار مانده‌ایم، دیر یا زود می‌فهمیم که کار به آن سادگی‌هایی که اوایل فکر می‌کردیم، نیست.‌ به‌محض اینکه می‌فهمیم، مطالعه را آغاز می‌کنیم (البته آن‌هایی که می‌توانند، این کار را انجام می‌دهند). اما، به‌نوعی، آنچه می‌خوانیم به‌نظرمان عجیب و غریب می‌آید. در مدت زمان کوتاهی، سراغ سادهترین چیزها می‌رویم، نه درستترین آن‌ها.

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

همه‌‌ی ما مبانی تحلیل تکنیکال را می‌دانیم و یادمان هست، و تا حالا این مبانی رد نشده‌اند، اما هنوز سفت و محکم ثابت هم نشده‌اند، با این حال:

قیمت همه‌چیزِ ماست!

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

بدتر این است که، ساده‌سازی می‌کنیم … ساده‌سازی Gann (!!!)، تا جایی که یادم هست Gann (ویلیام دلبرت گَن) کسی بوده که راه‌حل مشکل قیمت/زمان[۱] را پیدا کرد (یا اینکه خیلی به پیدا کردن آن نزدیک شده بود، مطمئن نیستم) … واقعاً هذیان است … چطور ممکن است چیزی را ساده‌سازی کرد که هنوز کسی آن را کامل درک نکرده؟

و سپس، وقتی می‌فهمیم همه‌چیز به‌نوعی دارد اشتباه پیش می‌رود، کمی بدتر ار ۵۰-۵۰، شروع می‌کنیم با صدای بلند فریاد زدن که اساتید دروغ می‌گویند، استراتژی Guru دروغ می‌گوید، روش‌ها کارآمد نیست، کتاب‌ چاپ کرده‌اند که فقط پول بگیرند، استراتژی‌های طلایی را هیچ‌وقت نمی‌گویند و …. . و این نتیجه‌ی فراموش کردن ما است که وقتی به یک اکسترمم نگاه می‌کنیم، آن اکسترمم معادل مینی‌مَکس[۲] نیست، بلکه واقعاً یک ماکسیمم یا مینیمم است، و فقط نمایش دیگری از ماهیت درونی آن است که هنوز باید به آن برسیم.

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

درآمد خواستن ما، ما را مجبور نمی‌کند که گاهی‌اوقات صبر کنیم و کمی تفکر انجام دهیم. تفکر چیز خوبیست. کم‌کم شروع به فکر کردن می‌کنید و درستی این مطلب بر شما آشکار می‌شود که “انسان موجودی است که زندگی می‌کند و بارها و بارها در طول این زندگی، یک کار تکراری را انجام می‌دهد به امید اینکه نتایج متفاوتی بگیرد”. چوب که خُرد نمی‌کنیم! می‌کنیم؟ 🙂

اشتیاق به صحبت مرا خیلی از بحث دور کرد. شاید به‌خاطر این است که خودم هم همینطور هستم. وقت آن است که بحث را جمع کنیم. بیایید این مطلب را واقعاً با تمام وجود درک کنیم که اساتید یا استراتژی‌ها همه‌چیز را به ما نمی‌گویند و نخواهند گفت؛ به‌خصوص اینکه آن‌ها می‌دانند یک قاشق غذاخوری از یک مطلب نه خوشمزه است و نه گفتنش کارآمد.

بیایید به موضوع خودمان برگردیم.

زیگزاگ فراکتال مولتی‌فریم

اندیکاتوری نیاز داشتم که فقط مینیمم‌ها و ماکسیمم‌های بازار را نشان ندهد، بلکه نقاط اکسترمم بازار را نشان دهد که به‌صورت منطقی از حرکات قیمت گرفته شده‌اند (LREP – آیا این مخفف ممکن است فراگیر شود؟)، و در صورت امکان تایید شوند. بحث تبدیل این اندیکاتور به تولیدکننده‌ی سیگنال، در ابتدا مطرح نبود. اول از همه، سعی کردم با زیگزاگ استاندارد کار کنم (نه آن اندیکاتوری که در متاتریدر ۴ تعبیه شده‌است، بلکه “استاندارد” به‌معنای کلی)، اما موردی پیش آمد که مرا به حالت هشدار برد و مجبورم کرد این ایده را کنار بگذارم:

  • یکنواختی همه‌ی الگوریتم‌ها علی‌رغم بحث و گفتگوهای فراوان در اینترنت و تنوع بسیار زیاد ورژن‌ها (البته شاید در نظر من موضوع اینگونه است اما هیچ‌گاه این الگوریتم را به‌صورت شفاف و دی‌کد شده[۳] هیچ کجا ندیدم)؛
  • نبود یک مفهوم واحد از اینکه [این اندیکاتور] دنبال “چه چیزی” باید باشد؛
  • تکرارپذیری منزجرکننده، و از همه بدتر، ترسیم مجددِ ضعیف و قابل پیش‌بینی؛
  • وابستگی مستقیم به تایم‌فریم و/یا وابستگی به گردشِ قیمتِ قبلاً مشخص‌شده؛

تا جاییکه شخصاً به من مربوط می‌شود، مورد آخر کاملاً غیرقابل قبول است و اصلاً برای من جذابیتی ندارد. موضوع شخصی نیست، بلکه بحث فنی است.

دِمارک را با نقاط TDاَش و ویلیام را با “فراکتال“هایش به‌یاد می‌آورم (نمی‌دانم چه کسی از چه کسی پیروی کرده اما هر دو مانند دو هسته در یک میوه هستند). به‌نظر می‌رسید “منحصربه‌فرد” باشد – حداقل استدلال آن با حرکات قبلی و بعدی قیمت بود. شاید هر کسی این رویکرد را برای انتخاب این نقاط، دوست نداشته باشد. با این حال، اما هیچ‌کس تا الان چیزی دقیق‌تر و مناسب‌تر برای شناسایی اولیه‌ی آن‌ها اختراع نکرده است، البته بجز اصطلاحاتی مانند “اکسترمم ارزشمند”، “ماکسیسمم محلی”، و غیره.

‌چیزهایی که برای خودمان هستند شاید بهترین نباشند، اما مطمئناً بیشتر “‌هم‌سرشت” ما هستند. به همین دلیل است که دنبال کد قرضی نگشتم و اندیکاتور فراکتال خودم که ساده هم هست را، دقیق‌تر، نوشتم، تشابه آن: اصول انتخاب نقاط، کمی با اصول استاندارد متفاوت است. سعی کردم با تایم‌فریم‌های مختلف و با استفاده از iCustom آن را فرا بخوانم، اما بعد فهمیدم منطقی‌تر این است که همه‌چیز را روی تایم‌فریم (TF) کنونی (که روی آن کار می‌کنیم) محاسبه کنیم. بعد از آن، منطق برنامه‌نویسی خودش همه‌چیز را به فعالیت وا می‌دارد: ساخت ماژول که خود را در آینده نشان می‌دهد، و TF عام. در اینجا نتیجه‌ی حاصل‌شده را داریم.

تصویر، ظاهر شدن خود را با پارامترهای TF   ۱۴۴۰، ۳۶۰، ۶۰،  نشان می‌دهد. نمودار H1 برای حالت نمایشی‌اَش انتخاب شده‌است تا شما ببینید که خط سیاه (۶۰) تمام نقاط فراکتال را نمی‌گیرد و بعضی از آن‌ها را رد می‌کند. اولین تصویر برای دیدن رأس (نوک/tip) است، و تصویر دوم، خیلی عادی از میانه‌های نمودار گرفته شده‌است.

زیگزاگ ها

زیگزاگ ها

طرح رنگی [استفاده‌شده] بهترین طرح نیست. در تصویر پیوستی طرح رنگی مورد نظر خودم را می‌توانید ببینید.

کد

بیایید ببینیم کد چگونه اجرا شده‌است – آیا واقعاً نباید در نمایش‌های صامت بازی کنیم؟ 🙂

اندیکاتور، روی تایم‌فریم کنونی (TF)، دنباله‌ای از گره‌های زیگزاگ[۴] را ایجاد می‌کند که این گره‌ها روی سه تایم‌فریم تقلیدی بزرگ‌تر، محاسبه شده‌اند. این اندیکاتور روی تمام تایم‌فریم‌ها و با تمام تایم‌فریم‌ها کار می‌کند، که شامل تایم‌فریم‌های کلی با این محدودیت‌های اِعمال‌شده‌ در کد می‌شود:

  • تایم‌فریم بزرگتر باید توسط تایم‌فریمی که روی آن کار انجام می‌شود، قابل تقسیم باشد؛ اگر اینگونه نباشد، نزدیکترین مقادیر صحیح، به اجبار تنظیم می‌شوند؛
  • تایم‌فریمی که روی آن کار انجام می‌شود، بزرگتر از حداقل تایم‌فریم بزرگتر نیست؛
  • دوره‌ها در پارامترها به‌شکل دقیقه مشخص می‌شوند و باید ترتیب آن‌ها کاهشی باشد؛
  • دوره‌ی بزرگترین تایم‌فریم فراتر از ۴۳۲۰۰ (یک ماه) نمی‌رود – محدودیت اینقدر نیست و بیشتر از این هم ممکن است؛

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

در اینجا این بخش را داریم:

//-----------------------------------------------------------------------
// MF_Fractal_ZZ_3in1.mq4
//-----------------------------------------------------------------------
#property copyright "Copyright © ۲۰۰۸, BiViSi Corp."
#property link      "riderfin@bk.ru"
#property link      "ICQ 499949112"

#property indicator_chart_window    
#property indicator_buffers 3
//---- style of the indicator line
#property indicator_color1 Blue 
#property indicator_color2 Red
#property indicator_color3 Yellow        
#property indicator_style1 0
#property indicator_style2 0
#property indicator_style3 0
#property indicator_width1 5
#property indicator_width2 3
#property indicator_width3 1
//---- INOUT PARAMETERS OF THE INDICATOR
extern int VolExt=50; // VolExt+1" calculation of the last control points
extern int TFLarge=1440;
extern int TFMidle=240;
extern int TFSmall=60;
//---- Variables 
double Large[],Midle[],Small[];  // control points (indicator bufers)
datetime PrevTimePer[4];         // the time of the last calculation of every TF
datetime PrevTimeCalc=0; 
double P60,CP60;
int CurPeriod, ErrorTF=0, NumberExt, Per,  largelast=0, midlelast=0, smalllast=0;
//-----------------------------------------------------------------------
int init() 
{
   // initialization
   IndicatorBuffers(3); // for perspective" entry :)
   SetIndexBuffer(0,Large); SetIndexStyle(0,DRAW_SECTION);
   SetIndexEmptyValue(0,0.0);
   SetIndexBuffer(1,Midle); SetIndexStyle(1,DRAW_SECTION);
   SetIndexEmptyValue(1,0.0); 
   SetIndexBuffer(2,Small); SetIndexStyle(2,DRAW_SECTION);
   SetIndexEmptyValue(2,0.0);
   ArrayInitialize(PrevTimePer,0);
   CurPeriod=Period(); CP60=CurPeriod*60;
   // restrictions:
   // control of TF and inputted parameters
   if (MathCeil(TFSmall/CurPeriod) != TFSmall/CurPeriod) 
      TFSmall=MathCeil(TFSmall/CurPeriod)*CurPeriod;
   if (MathCeil(TFMidle/CurPeriod) != TFMidle/CurPeriod)
      TFMidle=MathCeil(TFMidle/CurPeriod)*CurPeriod;
   if (MathCeil(TFLarge/CurPeriod) != TFLarge/CurPeriod)
       TFLarge=MathCeil(TFLarge/CurPeriod)*CurPeriod;
   if (CurPeriod > TFSmall) 
      {Alert ("The chart period must be less than or equal to ", TFSmall," min.");
       ErrorTF=1;return;}
   if (TFSmall >= TFMidle || TFMidle >= TFLarge || TFLarge>43200)
      {Alert ("Incorrect choice of timeframes for calulation!!!"); ErrorTF=1;return;}
   return;              
}
//--------------------------------------------------------------------

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

امتناع از استفاده از ساختارهایی از نوع int IC=IndicatorCounted(); و غیره، بستگی به خود الگوریتم محاسبه دارد که سرعت کافی را بدون آن فرآهم می‌کند ( Force #1-3را در کد ببینید)، و کمی زودتر درباره‌ی آن اگر بخواهیم بگوییم، می‌توان آن افزایش نیز داد.

//--------------------------------------------------------------------
int start()
{
   if ( ErrorTF==1 ) return; // incorrect timeframe
   FractalCalc(); 
   return;
}
//======================================================================
// Searching of the 5 bar fractals and zigzag nodes claculation
// on the emulation of the larger TF, deleting of the odd ones and representation on the current TF
//======================================================================
void FractalCalc ()
{   
   // Force  №۱ - caculation only on the fully formed bar of the working TF
   if (PrevTimeCalc == Time[0]) return; else PrevTimeCalc=Time[0];
   int y, x, k, i, j, extr=0; 
   // the time of the last bar of the current TF, that closes bar №۱-۵ of the larger TF
   int t1, t2, t3, t4, t5;                     
   // the number of the last bar of the cur. TF, that closes bar №۱-۵ of the larger TF
   int limit1, limit2, limit3, limit4, limit5; 
   // the numver of bars of the cur. TF with the peaks and bases that correspond with the bars 1-5 of the larger TF
   int up1,up2,up3,up4,up5,dn1,dn2,dn3,dn4,dn5;
      
   for (y=1; y<=3; y++) // cycle of the calculated TF
      {
      if (y==1) Per=TFLarge; if (y==2) Per=TFMidle; if (y==3) Per=TFSmall;
      P60=Per*60;
      // Force №۲ - calculate the fissures only with the forming of the bar of the larger TF
      if (PrevTimePer[y] !=0)
         { 
         if (Per<43200 && (Time[0] - PrevTimePer[y])<P60 )continue;
         if (Per==43200 && Month()==TimeMonth(PrevTimePer[y]))continue;
         }
      // Processing of bars absence
      // If linearly PrevTimePer[y]=Time[0], then in case of bar absence
      // the shift of whole calculation chain by the absence size will take place on the working TF
      PrevTimePer[y]=MathCeil(Time[0]/Per/60)*P60; 
      
      NumberExt=0;  extr=0;
      k=Per/CurPeriod;
      // limitation of cycle depending on currently calculated TF
      // and on the last fractal
      i=MathCeil(Bars/k)-5;
      // Force #3 - calculation starting with the last fissure
      if(y==1 && largelast !=0) i=largelast+k;
      if(y==2 && midlelast !=0) i=midlelast+k;
      if(y==3 && smalllast !=0) i=smalllast+k;
      for (x=1; x<=i; x++) 
         {
         // find peaks and bases
         // the time of the beginning of the las bar of the cur. TF, that closes bar №۱ of the larger TF
         if (PrevTimePer[y] !=0) t1=PrevTimePer[y]-x*P60+(k-1)*CP60;
         else t1=MathCeil(Time[0]/Per/60)*P60-x*P60+(k-1)*CP60;
         t2=t1-P60; t3=t2-P60; t4=t3-P60; t5=t4-P60;
         limit1=iBarShift(NULL,0,t1, false); limit2=iBarShift(NULL,0,t2, false);
         limit3=iBarShift(NULL,0,t3, false); limit4=iBarShift(NULL,0,t4, false);
         limit5=iBarShift(NULL,0,t5, false);         
         up1=iHighest(NULL,0,MODE_HIGH,k,limit1); up2=iHighest(NULL,0,MODE_HIGH,k,limit2);
         up3=iHighest(NULL,0,MODE_HIGH,k,limit3); up4=iHighest(NULL,0,MODE_HIGH,k,limit4);
         up5=iHighest(NULL,0,MODE_HIGH,k,limit5);
         dn1=iLowest(NULL,0,MODE_LOW,k,limit1); dn2=iLowest(NULL,0,MODE_LOW,k,limit2);
         dn3=iLowest(NULL,0,MODE_LOW,k,limit3); dn4=iLowest(NULL,0,MODE_LOW,k,limit4);
         dn5=iLowest(NULL,0,MODE_LOW,k,limit5);

         // searching for control points
         if(High[up3]>High[up2] && High[up3]>High[up1] && High[up3]>=High[up4] && High[up3]>=High[up5])
            {
            if (y==1){Large[up3]=High[up3];largelast=up3;}
            if (y==2){Midle[up3]=High[up3];midlelast=up3;}
            if (y==3){Small[up3]=High[up3];smalllast=up3;}
            NumberExt++;  extr++;
            }
         if(Low[dn3]<Low[dn2] && Low[dn3]<Low[dn1] && Low[dn3]<=Low[dn4] && Low[dn3]<=Low[dn5])
            {
            if (y==1){Large[dn3]=Low[dn3];largelast=dn3;}
            if (y==2){Midle[dn3]=Low[dn3];midlelast=dn3;}
            if (y==3){Small[dn3]=Low[dn3];smalllast=dn3;}
            NumberExt++; extr++;
            }
         if (NumberExt>VolExt) break;   
         } 
      }

همانطور که می‌توانید ببینید، بیشترِ کد، هدفش را روی محاسبات و محافظت در برابر شرایط ناخواسته گذاشته است – برای مثال، از دست رفتن کانکشن سرور و کندل گمشده در هیستوری. این شرایط محتمل هستند.

بلوک بعدی نوعی “کندن علف‌های هرز” را برعهده دارد: حذف اکسترمم‌های عجیب (وقتی چند مبنا (پایه) بین دو قله داریم، و بالعکس)، تا زیگزاگی صحیح شکل بگیرد. ماکسیمم/مینیمم‌ها از ۲ یا تعداد بیشتری قله/پایه که پشت سر هم می‌آیند، انتخاب می‌شوند، و در صورت برابر بودن، آنکه کمترین عدد/شماره را دارد، انتخاب می‌شود… اکسترمم‌های عجیب، صفر تعیین می‌شوند. البته، الگوریتم جایی برای بحث و جدل باقی می‌گذارد، و امکان جایگزینی هست اما تصمیم گرفتم این کار را لحظه‌ای انجام دهم.

کد شامل ورودی‌هایی کامنت‌گذاری‌شده است که این امکان را می‌دهند از شر اختلاف نظر در مورد ظهور قله‌ها/پایه‌ها روی تایم‌فریم‌های مختلف، خلاص شویم. با این حال لازم است یک بار دیگر قلم مو را برداشته و جاهایی را اصلاح کنیم. کد در حالت کنونی درست کار نمی‌کند. موقتاً از انجام این کار دست کشیده‌ام، اما اگر دوست دارید خودتان می‌توانید امتحان کنید.

همین بخش یک قابلیت دیگر برای سرعت بخشیدن به عملکرد خود دارد: اگر از ساختار                                        if (NumberExt>VolExt) break;، که مربوط به تغییری است که قبلاً محاسبه شده، استفاده شود، اما من فعلاً دست نگه داشته‌ام.

و زمانی که شروع می‌کنیم به بحث درباره‌ی سرعت، واضح‌ترین و راحت‌ترین روش کاهش VolExt در ورودی‌های اندیکاتور است؛ به‌ندرت کسی بیشتر از ۱۰-۱۵ واحد برای ترید نیاز داشته باشد، البته برای تحلیل اینگونه نیست، بجز برای حریص‌‌های واقعی 🙂

   if (extr==0) return;
   for (y=1; y<=3; y++)
      {
      if (y==1) j=ArraySize(Large);if (y==2)j=ArraySize(Midle);
      if (y==3)j=ArraySize(Small);      
      int min=0, max=0, extmin=0, extmax=0;
      NumberExt=0;      
      for (x=1;x<=j;x++)
         {
         if (y==1)
            {
            if (Large[x] == 0.0 ) continue;
            if (Large[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Large[max]>=Large[x])Large[x]=0.0;
                  else {Large[max]=0.0;max=x;}
                  extmax--;  
                  }
               else max=x;
               }
            if (Large[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Large[min]<=Large[x])Large[x]=0.0;
                  else {Large[min]=0.0;min=x;}
                  extmin--;  
                  }
               else min=x;
               }
            }         
         if (y==2)
            {
            if (Midle[x] == 0.0 ) continue;
            if (Midle[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Midle[max]>=Midle[x])Midle[x]=0.0;
                  else {Midle[max]=0.0;max=x;}
                  extmax--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Midle[max]>Midle[x])Midle[x]=0.0; 
                  if (Midle[max]==Midle[x])
                     {
                     if (Large[x] == High[x]) {Midle[max]=0.0;max=x;}
                     else Midle[x]=0.0; 
                     }
                  if (Midle[max]<Midle[x]){Midle[max]=0.0;max=x;}
                  */
                  }
               else max=x;
               }
            if (Midle[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Midle[min]<=Midle[x])Midle[x]=0.0;
                  else {Midle[min]=0.0;min=x;}
                  extmin--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Midle[min]<Midle[x])Midle[x]=0.0; 
                  if (Midle[min]==Midle[x])
                     {
                     if (Large[x] == Low[x]) {Midle[min]=0.0;min=x;}
                     else Midle[x]=0.0; 
                     }
                  if (Midle[min]>Midle[x]){Midle[min]=0.0;min=x;}
                  */
                  }
               else min=x;
               }
            }         
         if (y==3)
            {
            if (Small[x] == 0.0 ) continue;
            if (Small[x] == High[x])
               {
               NumberExt++; extmax++; extmin=0;
               if (extmax==2)
                  {
                  if (Small[max]>=Small[x])Small[x]=0.0;
                  else {Small[max]=0.0;max=x;}
                  extmax--;  
                  // it can be easier as the above one, but.... remove disagreements
                  /*
                  if (Small[max]>Small[x])Small[x]=0.0; 
                  if (Small[max]==Small[x])
                     {
                     if (Midle[x] == High[x]) {Small[max]=0.0;max=x;}
                     else Small[x]=0.0; 
                     }
                  if (Small[max]<Small[x]){Small[max]=0.0;max=x;}
                  */
                  }
               else max=x;
               }
            if (Small[x] == Low[x])
               {
               NumberExt++; extmax=0; extmin++;
               if (extmin==2)
                  {
                  if (Small[min]<=Small[x])Small[x]=0.0;
                  else {Small[min]=0.0;min=x;}
                  extmin--;  
                  // it can be easier as the above one, but.... remove diagreements
                  /*
                  if (Small[min]<Small[x])Small[x]=0.0; 
                  if (Small[min]==Small[x])
                     {
                     if (Midle[x] == Low[x]) {Small[min]=0.0;min=x;}
                     else Small[x]=0.0; 
                     }
                  if (Small[min]>Small[x]){Small[min]=0.0;max=x;}
                  */
                  }
               else min=x;
               }
            }         
         if (NumberExt>VolExt) break;
         }
      }         

}

نتیجه‌گیری

نتیجه همه‌ی مباحث این است که اندیکاتوری داریم با الگوریتمی که شاید شفاف باشد، اما هیچ‌کس قبلاً از آن استفاده نکرده است، و ما آن را از معایب زیگزاگ استاندارد گرفتیم و این مزیت‌ها را به آن دادیم:

  • تکرارِ ترسیم مجددِ گره‌ها به‌نسبت کمتر شده‌است، و ترسیم مجدد هم برای سوئینگ و هم برای حرکت قبلی قیمت، منطقی‌تر شده‌است. همزمان، اگر روی تایم‌فریم‌های مختلف، گره‌ها با یکدیگر منطبق شوند و یا همزمان اتفاق بیفتند، آنگاه ۹۰ تا ۹۵ درصد احتمال دارد که هیچ‌گونه ترسیم مجددی نداشته باشیم؛
  • امکان مشاهده‌ی هر چیزی که روی سه تایم‌فریم بزرگتر، روی یک نمودار، اتفاق می‌اُفتد، و در نتیجه، امکان شناسایی روندهای اصلی بدون استفاده از هیچ‌گونه ساختار یا ابزار اضافی؛
  • استفاده از هر نوع تایم‌فریم معمولی (از M5 تا MN1) برای محاسبات زیگزاگ، مطابق با هر سلیقه و نیازی؛
  • کارایی، سرعت بالای محاسبات، الگوریتم و کد شفاف که به‌سادگی قابل اصلاح و ارتقاء هستند.

ممکن است از من بپرسید چرا نباید این اصلاحات را خودم یک‌باره انجام دهم. تا الان هرچه یاد گرفته‌ام کافیست…برای امروز بس است 🙂

و می‌دانم که یک کد کارآمد که تمام شده‌است را می‌توان بی‌نهایت بار اصلاح کرد. درست مانند تراشیدن مداد است…ممکن است فراموش کنید که قرار بود با آن چیزی رسم کنید. دوست دارم رسم کردن را آغاز کنم. خیلی به این کار علاقه دارم! 🙂

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

فقط می‌توانم بگویم که آنچه باقی مانده و خشک شده‌است، شامل ۵ بافر اندیکاتور رایگان می‌شود، و احتمال اضافه کردن برخی از ماژول‌های جدید به‌شکلی کاملاً ساده، و پاسخی کاملاً مناسب برای فراخوانی از طریق  iCustom() … حالش را ببرید!

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

ANG3110 – به‌خاطر با ارزش‌ترین چیز، یعنی ایده‌ای که به‌شکلی کاملاً مناسب مرا به نوشتن این اندیکاتور سوق داد؛

Korey – به‌خاطر پشتیبانی‌ها و کمک‌هایش برای عیب‌شناسی ТimeCurrent و بهینه‌سازی محاسبات؛

هیئت مدیره – که خواسته یا ناخواسته، آگاهانه یا غیرآگاهانه، ایده‌هایی را مطرح کرده‌اند که می‌خواهم درباره‌ی آن‌ها فکر کنم.

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

[۱]) The Price/Time problem

[۲]) مینی‌مَکس یعنی کمترین مقدار از میان مجموعه‌ای از ماکسیمم‌ها.

[۳]) Decoded

[۴]) ZigZag nodes

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

M23admin

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

جادوی فیلتر کردن

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

بهینه‌سازی ربات معاملاتی در ترید واقعی

۲۵ مورد نظر

نوشتن نظر شما

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