تحلیل داده با اتکا به بردارهای ویژه و مقادیر ویژه در متاتریدر ۵ | رویکردی نوین برای کشف روابط پنهان
تحلیل مؤلفههای اصلی (PCA) در متاتریدر 5 یکی از ابزارهای قدرتمند در کاهش ابعاد دادهها محسوب میشود، اما کاربرد آن تنها به کاهش ابعاد محدود نمیشود. در قلب PCA، مفاهیم ارزشهای ویژه و بردارهای ویژه قرار دارند که نقش مهمی در شناسایی روابط پنهان در دادهها ایفا میکنند. در این مقاله، به بررسی روشهای استفاده از ساختار ویژه (Eigenstructure) برای آشکارسازی روابط مخفی میان دادهها پرداختهایم.
شناسایی متغیرهای پنهان: تحلیل عوامل اصلی (Factor Analysis)
تحلیل عاملی ابزاری است که برای کشف متغیرهای پنهان استفاده میشود و به شناسایی عواملی کمک میکند که میان متغیرهای مشهود تأثیرگذار هستند. این تحلیل به خصوص در حوزههایی که متغیرهایی مانند احساسات بازار یا ریسک غیرقابل اندازهگیری به طور مستقیم وجود دارند، کاربردی است. با استفاده از تحلیل عاملی، میتوان متغیرهایی را شناسایی کرد که در ظاهر مستقل به نظر میرسند اما عملاً تحت تأثیر یک عامل پنهان مشترک قرار دارند.
تفاوت تحلیل عاملی و تحلیل مؤلفههای اصلی (PCA)
در حالی که تحلیل عاملی و PCA هر دو برای کاهش ابعاد دادهها استفاده میشوند، اما تفاوتهایی اساسی در هدف و نحوه عملکرد دارند. PCA، مجموعهای از متغیرهای وابسته را به متغیرهای غیر وابسته به نام مؤلفههای اصلی تبدیل میکند که حداکثر واریانس دادهها را پوشش میدهند. این مؤلفهها اطلاعات بیشتری را از دادهها با استفاده از ترکیب متغیرهای اصلی ارائه میدهند. در مقابل، تحلیل عاملی به تأثیر متغیرهای پنهان بر متغیرهای مشهود تمرکز دارد و به شناسایی این متغیرها به جای کاهش ابعاد میپردازد.
ارزشهای ویژه و بردارهای ویژه در تحلیل دادهها
ارزشهای ویژه و بردارهای ویژه از جمله مفاهیم ریاضیاتی کلیدی هستند که در تحلیل دادهها اهمیت دارند. این مفاهیم به ما کمک میکنند تا روابط درونی دادهها و ساختار آنها را شناسایی کنیم. به عنوان مثال، بردارهای ویژه زمانی که در یک ماتریس همبستگی استاندارد به کار میروند، اطلاعاتی در خصوص وابستگیهای اصلی دادهها فراهم میکنند. برای تجسم، فرض کنید ماتریسی از متغیرهای مختلف داریم. با استفاده از بردارهای ویژه، میتوانیم اطلاعات را به گونهای بازسازی کنیم که واریانس بیشتری را با استفاده از متغیرهای کمتر پوشش دهیم.
برای درک بهتر پاراگرافهای پیشین، یک نمودار پراکندگی را در نظر بگیرید که محور افقی وزن و محور عمودی قد یک نمونه از افراد را نشان میدهد. اگر خطی از میان نقاط بگذرد که با پراکندگی دادهها همخوانی داشته باشد، این خط الگوی اصلی را نمایش میدهد: افراد بلندتر معمولاً وزن بیشتری دارند. اکنون، یک بردار ویژه را مانند یک فلش در نظر بگیرید که به این جهت اصلی اشاره دارد و بزرگترین روند یا الگوی غالب را نشان میدهد. مقدار ویژه مرتبط نشاندهنده قدرت این پدیده است. اگر فلش دیگری عمود بر اولی رسم کنیم، الگوی ثانویه را نشان میدهد، مانند اینکه چگونه بعضی افراد نسبت به قد خود وزن بیشتری یا کمتری دارند.
این فلشها (بردارهای ویژه) و اعداد (مقادیر ویژه) به ما کمک میکنند که مهمترین الگوهای مجموعه دادهها را بفهمیم و قواعد پنهان در دادهها را کشف کنیم. در این تحلیل، با بررسی مولفههای اصلی مجموعه داده و تحلیل ساختار ویژه ماتریس همبستگی آغاز میکنیم. دادههای اولیه استاندارد میشوند تا اثر مقیاسهای مختلف حذف شود، و ماتریس همبستگی متغیرهای استاندارد شده محاسبه میشود. در اینجا هدف، تعیین ارتباط هر متغیر مشاهدهشده با مقادیر ویژه ماتریس همبستگی است. این کار شامل محاسبه همبستگیها بین مقادیر ویژه و متغیرهای مشاهدهشده میشود و ماتریسی خاص به نام ماتریس بارگذاری فاکتور تشکیل میشود که با ضرب هر بردار ویژه در جذر مقدار ویژه متناظر آن به دست میآید. این تحلیل به ما کمک میکند تا متغیرهای مرتبط با فاکتورها را شناسایی کرده و تعداد فاکتورهای تاثیرگذار بر متغیرهای مشاهدهشده را ارزیابی کنیم.
مثال: تحلیل فاکتورهای اصلی بر شاخصهای مالی
در این بخش، با استفاده از MQL5، تحلیل فاکتورهای اصلی (PFA) را بر روی مجموعهای از شاخصهای مالی پیادهسازی میکنیم. این دادهها شامل چند شاخص مالی خواهد بود که در محدودههای زمانی مشخص جمعآوری شدهاند. برای نمونه، از دو شاخص پرکاربرد میانگین متحرک (MA) که اطلاعاتی درباره روند فراهم میکند و محدوده واقعی متوسط (ATR) که معیار سادهای از نوسانات است، استفاده خواهیم کرد.
برای انجام تحلیلهای گسترده که نیاز به بررسی ماتریسهای بزرگ دارند، چاپ مستقیم این دادهها در تب “اکسپرتها”ی متاتریدر 5 به دلیل حجم بالای اطلاعات کافی نیست. هدف از این تحلیلها این است که کاملاً در محیط متاتریدر 5 انجام شود و نیازی به تغییر به سایر پلتفرمها مانند پایتون یا R نباشد. بنابراین، یک رابط کاربری گرافیکی برای پیادهسازی تحلیل فاکتور اصلی (PFA) اضافه شد. در اینجا، گرافیکی از مجموعه دادههای مورد استفاده در این مثال نمایش داده شده است که هر ستون شامل مقادیر شاخص برای یک بازه زمانی خاص است، مانند “ATR_2” که نمایانگر شاخص ATR با طول پنجره ۲ است.
این تحلیل بر اساس دادههای قیمت روزانه بیتکوین (BTCUSD) بین سالهای ۲۰۱۹ تا ۲۰۲۲ انجام شده و شامل مقادیر قدیمیتر شاخصها در مقیاسهای زمانی مختلف است. این روش به تحلیلگران و معاملهگران کمک میکند تا الگوها و روندهای پنهان در دادهها را بدون نیاز به خروج از محیط متاتریدر شناسایی کنند و فرآیند تحلیل دادهها را در بستری واحد تسریع و بهینه کنند.
پیش از شروع به استخراج فاکتورهای اصلی، بهتر است ارزیابی کنیم که آیا یک مجموعهداده مناسب تحلیل فاکتور است یا خیر. برای این کار دو آزمون آماری وجود دارد که بررسی میکند آیا متغیرها قابل توضیح با عوامل پنهان هستند یا نه. اولین آزمون، آزمون KMO (Kaiser-Meyer-Olkin) است که برای سنجش کفایت نمونه دادهها برای تحلیل فاکتور استفاده میشود. این معیار، درجهی همبستگی بین متغیرها و نسبت واریانس مشترک را که ممکن است به عوامل زیرین نسبت داده شود، ارزیابی میکند.
مقدار KMO از ۰ تا ۱ است که در آن:
- مقادیر نزدیک به ۱ نشان میدهند دادهها برای تحلیل فاکتور بسیار مناسب هستند.
- مقادیر زیر ۰.۶ نشان میدهند که دادهها برای این نوع تحلیل مناسب نیستند.
از نظر ریاضی، شاخص KMO بهصورت زیر تعریف میشود:
در اینجا، توضیح پارامترهای مورد نیاز تابع KMO برای تحلیل فاکتورها آورده شده است:
- r(ij)r(ij) ضریب همبستگی بین متغیرهای ii و jj است.
- p(ij)p(ij) ضریب همبستگی جزئی بین متغیرهای ii و jj است.
در کد MQL5 زیر، پیادهسازی آزمون KMO را مشاهده میکنیم. تابع kmo()
به سه ورودی نیاز دارد:
- ماتریس
in
شامل دادههای متغیرهای مورد بررسی. kmo_per_item
که مقدار KMO برای هر متغیر را در خود ذخیره میکند.kmo_total
که شاخص KMO کل را نشان میدهد و میزان کفایت متغیرهای ترکیبی را ارزیابی میکند.
این تابع به ما کمک میکند میزان همبستگی و مناسب بودن دادهها را برای تحلیل فاکتور شناسایی کنیم و تعیین کنیم که آیا تحلیل بر روی این دادهها معنادار است یا خیر.
//+---------------------------------------------------------------------------+ //| Calculate the Kaiser-Meyer-Olkin criterion | //| In general, a KMO < 0.6 is considered inadequate. | //+---------------------------------------------------------------------------+ void kmo(matrix &in, vector &kmo_per_item, double &kmo_total) { matrix partial_corr = partial_correlations(in); matrix x_corr = (stdmat(in)).CorrCoef(false); np::fillDiagonal(x_corr,0.0); np::fillDiagonal(partial_corr,0.0); partial_corr = pow(partial_corr,2.0); x_corr = pow(x_corr,2.0); vector partial_corr_sum = partial_corr.Sum(0); vector corr_sum = x_corr.Sum(0); kmo_per_item = corr_sum/(corr_sum+partial_corr_sum); double corr_sum_total = x_corr.Sum(); double partial_corr_sum_total = partial_corr.Sum(); kmo_total = corr_sum_total/(corr_sum_total + partial_corr_sum_total); return; }
آزمون اسپریتی بارلت (BTS): ابزاری ضروری برای ارزیابی قابلیت استفاده از دادهها در تحلیل فاکتورها
آزمون اسپریتی بارلت (BTS) یک روش آماری برای بررسی ارتباط متغیرها در یک مجموعه داده است. این آزمون با بررسی انحراف ماتریس همبستگی از ماتریس واحد، تعیین میکند که آیا متغیرها ارتباطی معنادار دارند یا خیر. نتایج مثبت این آزمون میتواند به تحلیل فاکتورها کمک کند و راهگشای کشف الگوهای پنهان در دادهها باشد. این ابزار به ویژه برای پژوهشگران و تحلیلگران دادهها اهمیت دارد و به شناسایی ساختارهای نهفته در مجموعه دادههای مالی و دیگر زمینهها کمک میکند.
آزمون اسپریتی بارلت (BTS) به عنوان یکی از روشهای مهم در تحلیل دادهها، به پژوهشگران و تحلیلگران این امکان را میدهد تا درک بهتری از ساختار دادهها پیدا کنند. با استفاده از این آزمون، میتوان متغیرهایی را شناسایی کرد که دارای ارتباط معناداری با یکدیگر هستند و به این ترتیب، زمینهساز تحلیلهای پیچیدهتری مانند تحلیل فاکتور خواهند شد. بهویژه در زمینههای مالی، تحلیلهای دقیق میتوانند به تصمیمگیریهای بهتری منجر شوند.
این آزمون بر اساس آزمون خی-مربع است و آمار آزمون آن با توجه به روابط بین متغیرها محاسبه میشود. با انجام این آزمون، میتوان به راحتی متغیرهایی را شناسایی کرد که بر یکدیگر تأثیر دارند و این به ما اجازه میدهد تا به دقت بیشتری به تحلیل دادهها بپردازیم.
بهطور خلاصه، آزمون اسپریتی بارلت ابزاری است که به تحلیلگران دادهها کمک میکند تا اطلاعات عمیقتری از مجموعههای داده به دست آورند و در نهایت به بهبود کیفیت تحلیلهای خود کمک کند. این امر به ویژه در دنیای امروز که دادهها به سرعت در حال افزایش هستند، بسیار مهم است.
جایی که:
- n نمایانگر تعداد مشاهدات است.
- p تعداد متغیرها را نشان میدهد.
- |R| دترمینان ماتریس همبستگی R است.
آمار آزمون بارلت به توزیع خی-مربع با درجات آزادی (p(p-1))/2 وابسته است. اگر آمار آزمون بارلت بزرگ و مقدار p مربوطه کوچک باشد (معمولاً p-value < 0.05)، فرض صفر رد میشود. این نشاندهنده این است که ماتریس همبستگی بهطور معناداری از یک ماتریس واحد متفاوت است و متغیرها با یکدیگر مرتبط هستند و برای تحلیل فاکتور مناسبند. برعکس، اگر مقدار p بزرگ باشد، فرض صفر رد نمیشود که نشاندهنده نزدیکی ماتریس همبستگی به یک ماتریس واحد و عدم همبستگی معنادار بین متغیرها است.
کد زیر تابع ‘bartlet_sphericity()’ را تعریف میکند که آزمون BTS را پیادهسازی میکند. این تابع نتایج خود را به دو پارامتر ورودی آخر خروجی میدهد. این دو مقدار، اسکالر هستند: ‘statistic’ نمایانگر آمار خی-مربع و ‘p_value’ نمایانگر مقدار احتمال محاسبهشده است.
//+------------------------------------------------------------------+ //| Compute the Bartlett sphericity test. | //+------------------------------------------------------------------+ void bartlet_sphericity(matrix &in, double &statistic, double &p_value) { long n,p; n = long(in.Rows()); p = long(in.Cols()); matrix x_corr = (stdmat(in)).CorrCoef(false); double corr_det = x_corr.Det(); double neg = -log(corr_det); statistic = (corr_det>0.0)?neg*(double(n)-1.0-(2.0*double(p)+5.0)/6.0):DBL_MAX; double degrees_of_freedom = double(p)*(double(p)-1.0)/2.0; int error; p_value = 1.0 - MathCumulativeDistributionChiSquare(statistic,degrees_of_freedom,error); if(error) Print(__FUNCTION__, " MathCumulativeDistributionChiSquare() error ", error); return; }
استخراج عوامل اصلی در تحلیل دادهها | اهمیت نتایج آزمونها
اگر یکی از آزمونها یا هر دو نتایج مثبتی را نشان دهند، این امکان را فراهم میکند که به مرحله استخراج عوامل اصلی بپردازیم. با بررسی مجموعه دادههای نشانگرها، میتوانیم تأیید کنیم که هر دو آزمون مناسب بودن متغیرها را برای استخراج عوامل تأیید کردهاند. این مرحله از تحلیل، به ما کمک میکند تا الگوهای پنهان در دادهها را شناسایی کنیم و تصمیمگیریهای بهتری را در زمینههای مختلف، از جمله مالی و اقتصادی، انجام دهیم.
استانداردسازی دادهها | گامی اساسی در تحلیل دادهها
در تحلیل دادهها، استانداردسازی یک مرحله کلیدی به شمار میآید که به اطمینان از این موضوع کمک میکند که هر نشانگر بهطور مساوی در نتایج تأثیرگذار باشد. با استانداردسازی دادهها، تفاوتهای مقیاس بین نشانگرها کاهش مییابد و این امکان را میدهد که به تحلیلهای دقیقتری دست یابیم. این گام، به ویژه در زمینههای مالی و اقتصادی، میتواند به ما کمک کند تا الگوهای پنهان را شناسایی کرده و تصمیمات بهتری اتخاذ کنیم.
//+------------------------------------------------------------------+ //| standardize a matrix | //+------------------------------------------------------------------+ matrix stdmat(matrix &in) { vector mean = in.Mean(0); vector std = in.Std(0); std+=1e-10; matrix out = in; for(ulong row =0; row<out.Rows(); row++) if(!out.Row((in.Row(row)-mean)/std,row)) { Print(__FUNCTION__, " error ", GetLastError()); return matrix::Zeros(in.Rows(), in.Cols()); } return out; }
محاسبه ماتریس همبستگی | کلید درک روابط بین متغیرها
ماتریس همبستگی، که از دادههای استاندارد شده محاسبه میشود، ابزاری حیاتی برای تحلیل دادهها به شمار میآید. این ماتریس نشان میدهد که چگونه متغیرهای مختلف با یکدیگر مرتبط هستند و این ارتباطات میتوانند به شناسایی الگوها و روندهای موجود در دادهها کمک کنند. با استفاده از ماتریس همبستگی، میتوانیم روابط پنهان میان متغیرها را کشف کنیم و تصمیمات بهتری اتخاذ کنیم.
m_data = stdmat(in); m_corrmat = m_data.CorrCoef(false);
محاسبه مقادیر ویژه و بردارهای ویژه در تحلیل دادهها
در این مرحله، مقادیر ویژه و بردارهای ویژه ماتریس همبستگی را محاسبه میکنیم. برای این منظور، از تجزیه بردار ویژه کتابخانه Aglib استفاده میشود. این انتخاب به خاطر مشکلاتی است که با استفاده از روش “Eig()” برای ماتریسهای بومی به وجود آمده است. استفاده از Aglib به ما کمک میکند تا محاسبات دقیقی داشته باشیم و از اختلالات احتمالی جلوگیری کنیم.
CMatrixDouble cdata(m_corrmat); CMatrixDouble vects; CRowDouble vals; if(!CEigenVDetect::SMatrixEVD(cdata,cdata.Cols(),1,true,vals,vects)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; }
تجزیه بردارها و مقادیر ویژه در ماتریسهای متقارن
بهترین روش برای درک مشکل، ارائه یک مثال است. در اینجا کدی را معرفی میکنیم که اسکریپتی را تعریف میکند تا بردارها و مقادیر ویژه یک ماتریس متقارن را تجزیه کند. این کد به ما امکان میدهد تا ساختار و ویژگیهای موجود در دادهها را بهصورت دقیق تحلیل کنیم و از نتایج بهدستآمده در فرآیندهای تحلیلی خود بهرهبرداری کنیم.
//+------------------------------------------------------------------+ //| TestEigenDecompostion.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include<Math\Alglib\linalg.mqh> //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- matrix dataset = { {1,0.5,-0.2}, {0.5,1,-0.8}, {-0.2,-0.8,1} }; matrix evectors; vector evalues; dataset.Eig(evectors,evalues); Print("Eigen decomposition of \n", dataset); Print(" EVD using built in Eig() \n", evectors); Print(evalues); CMatrixDouble data(dataset); CMatrixDouble vects; CRowDouble vals; CEigenVDetect::SMatrixEVD(data,data.Rows(),1,true,vals,vects); Print(" EVD using Alglib implementation \n", vects.ToMatrix()); Print(vals.ToVector()); } //+------------------------------------------------------------------+
خروجی اسکریپت تجزیه ماتریس متقارن
خروجی این اسکریپت در زیر ارائه میشود. این نتایج نهتنها شامل اطلاعات مربوط به بردارها و مقادیر ویژه است، بلکه به ما کمک میکند تا درک عمیقتری از ساختار و روابط موجود در دادهها پیدا کنیم. تحلیل این خروجیها میتواند به تصمیمگیریهای بهتر و دقیقتر در زمینههای مختلف منجر شود.
تفاوتهای ارائه بردارها و مقادیر ویژه در Alglib و MQL5
در این مقاله، به تفاوتهای موجود در نحوه ارائه بردارها و مقادیر ویژه پرداخته میشود. پیادهسازی Alglib با مرتبسازی دادهها بهصورت صعودی، کار با آنها را راحتتر میکند. در حالی که روش MQL5 “Eig()” چنین ترتیبی ندارد. در اینجا، بررسیها نشان میدهد که علامتهای مقادیر آخرین بردار ویژه مخالف علامتهای مقادیر متناظر در Alglib هستند. این اختلاف، ما را به بررسی دقیقتری با استفاده از Numpy در پایتون هدایت میکند.
ماتریس بارهای عاملی با ضرب هر بردار ویژه در جذر مقدار ویژه متناظر محاسبه میشود. برای جلوگیری از تولید مقادیر نامعتبر، مقادیر ویژه منفی با 0 جایگزین میشوند، که به این ترتیب بعد مربوطه در ماتریس بارهای عاملی حذف میشود.
m_structmat = m_eigvectors; vector copyevals = m_eigvalues; if(!copyevals.Clip(0.0,DBL_MAX)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } for(ulong i = 0; i<m_structmat.Cols(); i++) if(!m_structmat.Col(m_eigvectors.Col(i)*sqrt(copyevals[i]),i)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } if(!m_structmat.Clip(-1.0,1.0)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; }
در این مقاله، به بررسی کلاس Cpfa
میپردازیم که بهمنظور انجام تحلیل عاملی اصلی (PFA) در متاتریدر 5 توسعه یافته است. کدهای نمونهای که تا کنون بررسی شدهاند، نشاندهنده قابلیتهای این کلاس هستند. در ادامه، کد کامل کلاس و جدول مربوط به روشهای عمومی آن ارائه خواهد شد.
//+------------------------------------------------------------------+ //| Principal factor extraction | //+------------------------------------------------------------------+ class Cpfa { private: bool m_fitted; //flag showing if principal factors were extracted matrix m_corrmat, //correlation matrix m_data, //standardized data is here m_eigvectors, //matrix of eigen vectors of correlation matrix m_structmat; //factor loading matrix vector m_eigvalues, //vector of eigen values m_cumeigvalues; //eigen values sorted in descending order long m_indices[];//original order of column indices in input data matrix public: //+------------------------------------------------------------------+ //| constructor | //+------------------------------------------------------------------+ Cpfa(void) { } //+------------------------------------------------------------------+ //| destructor | //+------------------------------------------------------------------+ ~Cpfa(void) { } //+------------------------------------------------------------------+ //| fit() called with input matrix and extracts principal factors | //+------------------------------------------------------------------+ bool fit(matrix &in) { m_fitted = false; m_data = stdmat(in); m_corrmat = m_data.CorrCoef(false); CMatrixDouble cdata(m_corrmat); CMatrixDouble vects; CRowDouble vals; if(!CEigenVDetect::SMatrixEVD(cdata,cdata.Cols(),1,true,vals,vects)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } m_eigvectors = vects.ToMatrix(); m_eigvalues = vals.ToVector(); double sum = 0.0; double total = m_eigvalues.Sum(); if(!np::reverseVector(m_eigvalues) || !np::reverseMatrixCols(m_eigvectors)) return m_fitted; m_cumeigvalues = m_eigvalues; for(ulong i=0 ; i<m_cumeigvalues.Size() ; i++) { sum += m_eigvalues[i] ; m_cumeigvalues[i] = 100.0 * sum/total; } m_structmat = m_eigvectors; vector copyevals = m_eigvalues; if(!copyevals.Clip(0.0,DBL_MAX)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } for(ulong i = 0; i<m_structmat.Cols(); i++) if(!m_structmat.Col(m_eigvectors.Col(i)*sqrt(copyevals[i]),i)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } if(!m_structmat.Clip(-1.0,1.0)) { Print(__FUNCTION__, "error ", GetLastError()); return m_fitted; } m_fitted = true; return m_fitted; } //+------------------------------------------------------------------+ //| returns factor loading matrix | //+------------------------------------------------------------------+ matrix get_factor_loadings(void) { if(!m_fitted) { Print(__FUNCTION__, " invalid function call "); return matrix::Zeros(1,1); } return m_structmat; } //+------------------------------------------------------------------+ //| get the eigenvector and values of correlation matrix | //+------------------------------------------------------------------+ bool get_eigen_structure(matrix &out_eigvectors, vector &out_eigvalues) { if(!m_fitted) { Print(__FUNCTION__, " invalid function call "); return false; } out_eigvalues = m_eigvalues; out_eigvectors = m_eigvectors; return true; } //+------------------------------------------------------------------+ //| returns variance contributions for each factor as a percent | //+------------------------------------------------------------------+ vector get_cum_var_contributions(void) { if(!m_fitted) { Print(__FUNCTION__, " invalid function call "); return vector::Zeros(1); } return m_cumeigvalues; } //+------------------------------------------------------------------+ //| get the correlation matrix of the dataset | //+------------------------------------------------------------------+ matrix get_correlation_matrix(void) { if(!m_fitted) { Print(__FUNCTION__, " invalid function call "); return matrix::Zeros(1,1); } return m_corrmat; } //+------------------------------------------------------------------+ //| returns the rotated factor loadings | //+------------------------------------------------------------------+ matrix rotate_factorloadings(ENUM_FACTOR_ROTATION factor_rotation_type) { if(!m_fitted) { Print(__FUNCTION__, " invalid function call "); return matrix::Zeros(1,1); } CRotator rotator; if(!rotator.fit(m_structmat,factor_rotation_type,4,true)) return matrix::Zeros(1,1); else return rotator.get_transformed_loadings(); }
تفسیر بارگذاریهای عوامل و اهمیت آنها در تحلیل دادهها
بارگذاریهای عوامل ابزاری کلیدی برای درک ارتباط بین متغیرهای مشاهدهشده و عوامل پنهان (latent factors) در یک مدل تحلیل عاملی هستند. این بارگذاریها به ما این امکان را میدهند تا بفهمیم که هر متغیر چقدر با یک عامل خاص مرتبط است و تا چه حد میتواند بر نتایج تأثیر بگذارد.
برای سادهتر شدن تفسیر، بردارهای ویژه (eigenvectors) بر اساس بزرگی مقادیر ویژه (eigenvalues) آنها به ترتیب نزولی مرتب میشوند. این روش باعث میشود که اولین بردار ویژه، مرتبط با بزرگترین مقدار ویژه، به عاملی که بیشترین تأثیر را بر متغیرهای مشاهدهشده دارد، اشاره کند. به این ترتیب، ردیفهای ماتریس بارگذاری عوامل در همان ترتیبی قرار دارند که ستونهای مجموعه داده اصلی نشان میدهند. هر ردیف به یک متغیر خاص مربوط میشود و ستونها نمایانگر عواملی هستند که به ترتیب نزولی واریانس توضیح دادهشده را نمایش میدهند.
در تفسیر بارگذاریهای عوامل، همبستگیهای بالای ۰.۴ یا پایینتر از -۰.۴ بهعنوان همبستگیهای معنادار تلقی میشوند. به این معنا که هر متغیری که بارگذاریهای آن در محدوده -۰.۴ تا ۰.۴ قرار گیرد، نشاندهنده این است که عامل مربوطه تأثیر چندانی بر آن متغیر ندارد.
بهطور کلی، تفسیر صحیح بارگذاریهای عوامل به تحلیلگران این امکان را میدهد که عوامل اصلی را شناسایی کرده و بر اساس آنها تصمیمات بهتری بگیرند. بنابراین، در هر مطالعهای که شامل تحلیل عاملی باشد، درک و تفسیر بارگذاریهای عوامل میتواند بهطور قابلملاحظهای بر کیفیت نتایج نهایی تأثیر بگذارد.
متغیرها
متغیر | عامل | مقدار |
---|---|---|
X1 | عامل ۱ | 0.80000 |
X2 | عامل ۱ | -0.30000 |
X3 | عامل ۱ | 0.00000 |
X4 | عامل ۱ | 0.50000 |
X5 | عامل ۱ | 0.50000 |
X1 | عامل ۲ | 0.30000 |
X2 | عامل ۲ | -0.93000 |
X3 | عامل ۲ | 0.34200 |
X4 | عامل ۲ | 0.10000 |
X5 | عامل ۲ | -0.33000 |
X1 | عامل ۳ | 0.10000 |
X2 | عامل ۳ | 0.00002 |
X3 | عامل ۳ | -1.00000 |
X4 | عامل ۳ | -0.38000 |
X5 | عامل ۳ | 0.44000 |
دادههایی که دارای ساختار عاملی ساده هستند، شامل متغیرهایی هستند که به طور چشمگیری بر یک عامل بارگذاری میشوند و بارگذاری کمی بر سایر عوامل دارند. جدول بالا بارگذاریهای عوامل یک مجموعه داده فرضی را نمایش میدهد. متغیرهای X1 تا X4 نشان میدهند که به طور معناداری بر عوامل مختلف بارگذاری شدهاند، در حالی که متغیر X5 به دلیل بارگذاری متوسط بر دو عامل بهطور همزمان، سیگنالهای مختلطی را نشان میدهد. ویژگیهای متغیرهای اندازهگیری شده به همراه بارگذاریهای عوامل میتوانند سرنخهایی در مورد ماهیت عاملهای پنهان ارائه دهند. به عنوان مثال، اگر چندین شاخص اقتصادی به طور چشمگیری بر یک عامل بارگذاری شوند، این عامل ممکن است نمایانگر یک روند اقتصادی زیرین یا احساسات بازار باشد. برعکس، اگر یک متغیر به طور متوسط بر چندین عامل بارگذاری شود، این میتواند نشان دهد که آن متغیر تحت تأثیر چندین عامل زیرین قرار دارد که هر یک به جنبه متفاوتی از رفتار متغیر کمک میکند.
تفسیر بارگذاریهای عوامل متغیرهای ATR
با نگاهی به بارگذاریهای عوامل متغیرهای ATR که قبلاً جمعآوری شدهاند، میتوان مشاهده کرد که بیشتر متغیرها بارگذاریهای بالایی بر روی عامل ۱ دارند، که نشاندهنده این است که این متغیرها عمدتاً تحت تأثیر این عامل قرار دارند. عامل ۱ بخش قابل توجهی از واریانس این متغیرها را توضیح میدهد، که درصد واریانس توضیح دادهشده توسط عدد موجود در پرانتز (۹۱.۸۹٪) مشخص شده است. با وجود اینکه عامل ۱ بهعنوان عامل غالب شناخته میشود، برخی متغیرها نیز بارگذاریهای قابل توجهی بر روی عوامل دیگر دارند. برای مثال، متغیرهای ATR_4، ATR_6، ATR_10، ATR_14 و دیگران بارگذاریهای متوسطی بر روی عامل ۲ دارند که نشاندهنده تأثیر ثانویه این عامل است. همچنین، متغیرهای ATR_2، ATR_4، ATR_6، و ATR_8 بارگذاریهای کوچکتر اما معناداری بر روی عامل ۳ دارند. عوامل ۴ و فراتر از آن بارگذاریهای کمتری در بین متغیرهای مختلف دارند، که نشاندهنده این است که این عوامل نسبت به سه عامل اول واریانس کمتری را در مجموعه داده توضیح میدهند.
اگر بارگذاریهای عوامل به دلیل ساختار پیچیده عوامل دشوار باشد، میتوان بارگذاریها را با تبدیل کردن آنها به منظور بهبود قابلیت تفسیر، سادهسازی کرد. این نوع تبدیل تحت عنوان چرخش عوامل شناخته میشود. دو نوع چرخش وجود دارد که میتوان به ماتریس بارگذاریهای عوامل اعمال کرد.
- چرخشهای عمود (Orthogonal rotations) که استقلال عوامل را حفظ میکند. نمونههایی از این نوع چرخش شامل چرخش واریمکس (Varimax) و اکوماکس (Equamax) است. چرخشهای عمود باید زمانی اعمال شوند که فرض بر این باشد که عوامل مستقل هستند.
- چرخشهای مایل (Oblique rotations) که اجازه میدهند بین عوامل وابستگی وجود داشته باشد. نمونههایی از این چرخشها شامل چرخش پروماکس (Promax) و اوبلیمن (Oblimin) است. چرخشهای مایل مناسب زمانی هستند که مشکوک به وجود ارتباط میان عوامل هستیم.
تبدیل همبستگیها از طریق چرخش، همبستگیهای خام ماتریس ساختار عامل را به مقادیر افراطی (-۱، ۰، ۱) سوق میدهد تا تفسیر همبستگیها آسانتر شود و تأثیرات بر متغیرهای مشاهدهشده تقویت شود.
برای تسهیل در انجام چرخشها، کلاس CRotator معرفی میشود که چرخشهای پروماکس و واریمکس را پیادهسازی میکند.
//+------------------------------------------------------------------+ //| class implementing factor rotations | //| implements varimax and promax rotations | //+------------------------------------------------------------------+ class CRotator { private: bool m_normalize, //normalization flag m_done; //rotation flag int m_power, //exponent to which to raise the promax loadings m_maxIter; //maximum number of iterations. Used for 'varimax' double m_tol; //convergence threshold. Used for 'varimax' matrix m_loadings, //the rotated factor loadings m_rotation_mtx, //the rotation matrix m_phi; //factor correlations matrix. ENUM_FACTOR_ROTATION m_rotation_type; //rotation method employed //+------------------------------------------------------------------+ //| implements varimax rotation | //+------------------------------------------------------------------+ bool varimax(matrix &in) { ulong rows,cols; rows = in.Rows(); cols = in.Cols(); matrix X = in; vector norm_mat(X.Rows()); if(m_normalize) { for(ulong i = 0; i<X.Rows(); i++) norm_mat[i]=sqrt((pow(X.Row(i),2.0)).Sum()); X = X.Transpose()/np::repeat_vector_as_rows_cols(norm_mat,X.Rows()); X = X.Transpose(); } m_rotation_mtx = matrix::Eye(cols,cols); double d = 0,old_d; matrix diag,U,V,transformed,basis; vector S,ones; for(int i =0; i< m_maxIter; i++) { old_d = d; basis = X.MatMul(m_rotation_mtx); ones = vector::Ones(rows); diag.Diag(ones.MatMul(pow(basis,2.0))); transformed = X.Transpose().MatMul(pow(basis,3.0) - basis.MatMul(diag)/double(rows)); if(!transformed.SVD(U,V,S)) { Print(__FUNCTION__, " error ", GetLastError()); return false; } m_rotation_mtx = U.Inner(V); d = S.Sum(); if(d<old_d*(1.0+m_tol)) break; } X = X.MatMul(m_rotation_mtx); if(m_normalize) { matrix xx = X.Transpose(); X = xx * np::repeat_vector_as_rows_cols(norm_mat,xx.Rows()); } else X = X.Transpose(); m_loadings = X.Transpose(); return true; } //+------------------------------------------------------------------+ //| implements promax rotation | //+------------------------------------------------------------------+ bool promax(matrix &in) { ulong rows,cols; rows = in.Rows(); cols = in.Cols(); matrix X = in; matrix weights,h2; h2.Init(1,1); if(m_normalize) { matrix array = X; matrix m = array.MatMul(array.Transpose()); vector dg = m.Diag(); h2.Resize(dg.Size(),1); h2.Col(dg,0); weights = array/np::repeat_vector_as_rows_cols(sqrt(dg),array.Cols(),false); } else weights = X; if(!varimax(weights)) return false; X = m_loadings; ResetLastError(); matrix Y = X * pow(MathAbs(X),double(m_power-1)); matrix coef = (((X.Transpose()).MatMul(X)).Inv()).MatMul(X.Transpose().MatMul(Y)); vector diag_inv = ((coef.Transpose()).MatMul(coef)).Inv().Diag(); if(GetLastError()) { diag_inv = ((coef.Transpose()).MatMul(coef)).PInv().Diag(); ResetLastError(); } matrix D; D.Diag(sqrt(diag_inv)); coef = coef.MatMul(D); matrix z = X.MatMul(coef); if(m_normalize) z = z * np::repeat_vector_as_rows_cols(sqrt(h2).Col(0),z.Cols(),false); m_rotation_mtx = m_rotation_mtx.MatMul(coef); matrix coef_inv = coef.Inv(); m_phi = coef_inv.MatMul(coef_inv.Transpose()); m_loadings = z; return true; } public: //+------------------------------------------------------------------+ //| constructor | //+------------------------------------------------------------------+ CRotator(void) { } //+------------------------------------------------------------------+ //| destructor | //+------------------------------------------------------------------+ ~CRotator(void) { } //+------------------------------------------------------------------+ //| performs rotation on supplied factor loadings passed to /in/ | //+------------------------------------------------------------------+ bool fit(matrix &in, ENUM_FACTOR_ROTATION rot_type=MODE_VARIMX, int power = 4, bool normalize = true, int maxiter = 500, double tol = 1e-05) { m_rotation_type = rot_type; m_power = power; m_maxIter = maxiter; m_tol = tol; m_done=false; if(in.Cols()<2) { m_loadings = in; m_rotation_mtx = matrix::Zeros(in.Rows(), in.Cols()); m_phi = matrix::Zeros(in.Rows(),in.Cols()); m_done = true; return true; } switch(m_rotation_type) { case MODE_VARIMX: m_done = varimax(in); break; case MODE_PROMAX: m_done = promax(in); break; default: return m_done; } return m_done; } //+------------------------------------------------------------------+ //| get the rotated loadings | //+------------------------------------------------------------------+ matrix get_transformed_loadings(void) { if(m_done) return m_loadings; else return matrix::Zeros(1,1); } //+------------------------------------------------------------------+ //| get the rotation matrix | //+------------------------------------------------------------------+ matrix get_rotation_matrix(void) { if(m_done) return m_rotation_mtx; else return matrix::Zeros(1,1); } //+------------------------------------------------------------------+ //| get the factor correlation matrix | //+------------------------------------------------------------------+ matrix get_phi(void) { if(m_done && m_rotation_type==MODE_PROMAX) return m_phi; else return matrix::Zeros(1,1); } };
مرور کلی بر متدهای عمومی کلاس CRotator
توضیحات تکمیلی
- متد fit: این متد امکان چرخش بارگذاریهای عوامل را با استفاده از دو روش واریمکس و پروماکس فراهم میکند. این متد شامل پارامترهایی برای تنظیم قدرت چرخش و تعداد تکرارها است که به بهینهسازی فرآیند چرخش کمک میکند.
- get_transformed_loadings: با استفاده از این متد، میتوان ماتریس بارگذاریهای چرخشیافته را دریافت کرد که به تفسیر بهتر دادهها کمک میکند.
- get_rotation_matrix: این متد ماتریس چرخشی که در فرآیند تبدیل استفاده شده را باز میگرداند، که برای تجزیه و تحلیل دقیقتر مفید است.
- get_phi: این متد به ویژه در چرخش پروماکس استفاده میشود و ماتریس همبستگی بین عوامل را ارائه میدهد.
این متدها به تحلیلگران کمک میکنند تا بارگذاریهای عوامل را به شیوهای قابل فهم و معنادار بهینهسازی کنند. اگر سوال دیگری دارید یا نیاز به توضیحات بیشتری است، خوشحال میشوم کمک کنم!
CRotator rotator;
if(!rotator.fit(m_structmat,MODE_PROMAX,4,false))
return;
Print(" Rotated Loadings Matrix ", rotator.get_transformed_loadings());
بارگذاریهای عوامل چرخشیافته پروماکس تأثیرات عوامل ۱ و ۲ را بر دو دسته متغیرها به وضوح نشان میدهند. عامل ۱ تأثیر غالبی بر متغیرهای MA دارد.
این متن مختصر و مفید است، اما میتوانیم آن را کمی بیشتر گسترش دهیم و بهینهسازی کنیم:
تأثیرات و چالشهای بارگذاریهای چرخشیافته پروماکس
بارگذاریهای چرخشیافته پروماکس تأثیرات بیشتری را بر روی متغیرهای ATR نمایان میسازد. تأثیر حداقلی سایر عوامل بهخوبی با شناسایی الگوهای کمتر مهم در دادهها تقویت میشود. این راهحل چرخشیافته درک بهتری از ساختار زیرین مجموعه دادهها را فراهم میکند و تسهیلگر تفسیر بهتری است. با این حال، باید به چندین محدودیت و چالش در استفاده از چرخش توجه کرد:
- سادهسازی ساختار زیرین: چرخش ممکن است ساختار زیرین را بیش از حد سادهسازی کند و متغیرها را وادار کند که بهطور برجستهای بر یک عامل بارگذاری شوند، که میتواند روابط پیچیدهتر را پنهان کند.
- انتخاب نوع چرخش: انتخاب بین چرخشهای عمود و مایل بستگی به فرضیات نظری درباره استقلال عوامل دارد، که ممکن است همیشه واضح یا توجیهشده نباشد.
- کاهش مقدار واریانس توضیحداده شده: در برخی موارد، چرخش میتواند منجر به کاهش جزئی در واریانس توضیحداده شده شود، زیرا هدف چرخش بیشتر بر روی تفسیرپذیری متمرکز است تا حداکثر کردن واریانس توضیحداده شده.
- چالش در تفسیر بارگذاریها: با وجود تعداد زیاد متغیرها و عوامل، تفسیر بارگذاریهای چرخشیافته همچنان میتواند چالشبرانگیز باشد، بهویژه اگر ساختار سادهای وجود نداشته باشد.
- هزینههای محاسباتی: چرخشها، بهویژه روشهای تکراری مانند واریمکس، میتوانند برای مجموعههای داده بزرگ پرهزینه باشند و ممکن است بر عملکرد در برنامههای کاربردی زمان واقعی تأثیر بگذارند.
این بحث ما در زمینه استخراج عوامل اصلی را به پایان میرساند. در ادامه به بررسی تکرار در متغیرها بر اساس عوامل نهان خواهیم پرداخت و اینکه چگونه عوامل نهان میتوانند روابط پنهان را نمایان سازند.
تکرار در متغیرها بر اساس عوامل نهان
هنگام کار با تعداد زیادی متغیر، شناسایی مجموعههایی از متغیرها که بهطور قابل توجهی تکراری هستند، بسیار مفید است. این بدان معناست که برخی از متغیرها اطلاعات مشابهی ارائه میدهند و ممکن است نیازی به در نظر گرفتن همه آنها نداشته باشیم. معمولاً اطلاعات مهم از خود تکرار ناشی میشود، زیرا میتواند نشاندهنده تأثیر مشترکی باشد که بر چندین متغیر تأثیر میگذارد. با شناسایی گروههای متغیرهای بسیار تکراری، میتوانیم تجزیه و تحلیل خود را با تمرکز بر روی چند متغیر نماینده یا یک عامل واحد که با گروه ارتباط خوبی دارد، سادهتر کنیم.
یک روش رایج برای شناسایی متغیرهای تکراری، استفاده از نمودارهای پراکنده در محورهای اصلی یا چرخشیافته عمود است. متغیرهایی که در این نمودار به هم نزدیک هستند، احتمالاً تکراری هستند. با این حال، این روش محدودیتهایی دارد. اولاً، این روش بهصورت ذهنی است و معمولاً تنها میتوان دو بعد را در یک زمان برای تجزیه و تحلیل مؤثر مدیریت کرد.
یک روش شهودی برای شناسایی تکرار شامل در نظر گرفتن عوامل زیرین غیرقابل مشاهده است. بهعنوان مثال، اگر سه عامل (V1، V2، V3) باعث ایجاد متغیرهای مشاهدهشده (X1، X2، X3) شوند و ما متوجه شویم که یکی از عوامل (V3) فقط نویز است، آنگاه X1 و X2 ممکن است وقتی V3 نادیده گرفته شود، تکراری باشند. به عبارت دیگر، اگر X2 فقط یک نسخه مقیاسبندیشده از X1 باشد، آنها از نظر عوامل مهم (V1 و V2) تکراری هستند.
برای اندازهگیری دقیق تکرار، متغیرهای مشاهدهشده را بهعنوان بردارهایی در فضایی که توسط عوامل زیرین تعریف شده است، در نظر میگیریم. وقتی متغیرهای مشاهدهشده را داریم، میتوانیم آنها را بهعنوان بردارهایی در یک فضای چندبعدی نمایش دهیم که هر بعد به یک عامل زیرین مربوط میشود. این بردارها نشان میدهند که هر متغیر چگونه به عوامل مرتبط است. زاویه بین این بردارها نشاندهنده میزان شباهت متغیرها از نظر اطلاعاتی است که درباره عوامل زیرین حمل میکنند. زاویه کوچکتر به معنای این است که بردارها تقریباً در یک جهت قرار دارند که نشاندهنده تکرار بالاست. به عبارت دیگر، متغیرها اطلاعات مشابهی را ارائه میدهند.
برای کمیسازی این تکرار، میتوانیم از حاصلضرب نقطهای بردارهای نرمالشده (بردارهایی با طول ۱) استفاده کنیم. این حاصلضرب نقطهای از -۱ تا ۱ متغیر است، جایی که حاصلضرب نقطهای ۱ به معنای یکسان بودن بردارها است و نشاندهنده تکرار کامل است. در حالی که حاصلضرب نقطهای -۱ به معنای این است که بردارها در جهات مخالف قرار دارند که میتوان آن را نیز تکراری در نظر گرفت، زیرا دانستن یکی به ما معکوس دیگری را میدهد. حاصلضرب نقطهای ۰ به معنای این است که بردارها عمود هستند (مستقل) و نشاندهنده عدم تکرار است.
ضریبهایی که برای محاسبه متغیرهای مشاهدهشده از عوامل زیرین استفاده میشود، میتواند با استفاده از مولفههای اصلی پیدا شود. مولفههای اصلی غالب (با مقادیر ویژه بزرگ) معمولاً بیشتر اطلاعات مفید را در خود دارند، در حالی که مولفههای با مقادیر ویژه کوچک معمولاً نویز هستند. ماتریس بارگذاری عوامل که همبستگی عوامل با متغیرها را نشان میدهد، میتواند برای محاسبه متغیرهای مشاهدهشده استاندارد شده از مولفههای اصلی استفاده شود. برای اهداف عملی، معمولاً از ارزش مطلق حاصلضرب نقطهای برای اندازهگیری تکرار استفاده میکنیم، زیرا درک میکنیم که بردارهای معکوس نیز نشاندهنده تکرار هستند. نرمالسازی بردارها اطمینان میدهد که طول آنها ۱ است و اجازه میدهد حاصلضرب نقطهای بهعنوان یک اندازهگیری مستقیم از کسینوس زاویه بین آنها باشد.
برای محاسبه میزان ارتباط دو متغیر از نظر یک عامل نهان، معمولاً ابتدا باید تعداد مولفههای اصلی را که آنها را مهم میدانیم، تعیین کنیم. محاسبات خوشهبندی بر روی دادهها در اولین ستونهای ماتریس بارگذاری عوامل متمرکز خواهد شد. هر ردیف در این ستونها مجدداً مقیاسدهی میشود تا مجموع آنها برابر ۱ شود. درجه شباهت بین دو متغیر به ارزش مطلق حاصلضرب نقطهای دو ردیف متناظر از ماتریس بارگذاری عوامل تبدیلشده تبدیل میشود.
گام بعدی گروهبندی این دادهها به مجموعههایی است که شامل متغیرهای بسیار مشابه بر اساس ارتباط آنها با یک عامل نهان هستند. یکی از بهترين الگوريتمهاي خوشهبندي، که به خاطر توانایی در تولید نتایج خوب شناخته شده است، خوشهبندی سلسلهمراتبی (Hierarchical Clustering) است. در خوشهبندی سلسلهمراتبی، که بهعنوان خوشهبندی انبوهی (Agglomerative Hierarchical Clustering) نیز شناخته میشود، گروهبندی با اختصاص هر متغیر به یک گروه با یک عضو آغاز میشود. هر جفت گروه ممکن آزمایش میشود تا نزدیکترین دو گروه شناسایی شود. این گروهها به یک گروه ترکیب میشوند. این فرآیند تا زمانی که تنها یک گروه باقی بماند یا درجه شباهت بسیار کوچک شود، تکرار میشود.
پیادهسازی خوشهبندی انبوهی در نسخه MQL5 کتابخانه Alglib ارائه شده است. این پیادهسازی بهطور خاص برای مقاصد ما مناسب است، زیرا امکان اجرای یک معیار فاصله سفارشی را فراهم میکند. این قابلیت از طریق سه کلاس Alglib ارائه میشود. برای استفاده از پیادهسازی خوشهبندی سلسلهمراتبی Alglib، به یک نمونه از ساختار CAHCReport برای ذخیره نتایج عملیات نیاز داریم.
CAHCReport m_rep;
کلاس CClusterizerState
موتور خوشهبندی را در خود جای داده است. بدون این کلاس، انجام خوشهبندی امکانپذیر نیست.
CClusterizerState m_cs;
این فرآیند با راهاندازی موتور خوشهبندی آغاز میشود، که از طریق فراخوانی متد استاتیک ClusterizerCreate()
کلاس CClustering
انجام میگیرد.
CClustering::ClusterizerCreate(m_cs);
//+------------------------------------------------------------------+ //| cluster a set of points | //+------------------------------------------------------------------+ class CCluster { private: CClusterizerState m_cs; CAHCReport m_rep; matrix m_pd[]; //+------------------------------------------------------------------+ //| Preprocesses input matrix before clusterization | //+------------------------------------------------------------------+ bool customDist(matrix &structure, ulong num_factors, matrix& out[], bool calculate_custom_distances = true) { int nvars; double dotprod, length; nvars = int(structure.Rows()); int ndim = (num_factors && num_factors<=structure.Cols())?int(num_factors):int(structure.Cols()); if(out.Size()<2) if(out.Size()<2 && (ArrayResize(out,2)!=2 || !out[0].Resize(nvars,ndim) || !out[1].Resize(nvars,nvars))) { Print(__FUNCTION__, " error ", GetLastError()); return false; } if(calculate_custom_distances) { for(int i=0 ; i<nvars ; i++) { length = 0.0 ; for(int j=0 ; j<ndim ; j++) length += structure[i][j] * structure[i][j] ; length = 1.0 / sqrt(length) ; for(int j=0 ; j<ndim ; j++) out[0][i][j] = length * structure[i][j] ; } out[1].Fill(0.0); for(int irow1=0 ; irow1<nvars-1 ; irow1++) { for(int irow2=irow1+1 ; irow2<nvars ; irow2++) { dotprod = 0.0 ; for(int i=0 ; i<ndim ; i++) dotprod += out[0][irow1][i] * out[0][irow2][i] ; out[1][irow1][irow2] = fabs(dotprod) ; } } } else { out[0] = np::sliceMatrixCols(structure,0,ndim); } return true; } public: //+------------------------------------------------------------------+ //| constructor | //+------------------------------------------------------------------+ CCluster(void) { CClustering::ClusterizerCreate(m_cs); } //+------------------------------------------------------------------+ //| destructor | //+------------------------------------------------------------------+ ~CCluster(void) { } //+------------------------------------------------------------------+ //| cluster a set | //+------------------------------------------------------------------+ bool cluster(matrix &in_points, ulong factors=0, ENUM_LINK_METHOD linkage=MODE_COMPLETE, ENUM_DIST_CRIT dist = DIST_CUSTOM) { if(!customDist(in_points,factors,m_pd,dist==DIST_CUSTOM)) return false; CMatrixDouble pp(m_pd[0]); CMatrixDouble pd(m_pd[1]); CClustering::ClusterizerSetPoints(m_cs,pp,pp.Rows(),pp.Cols(),dist<22?dist:DIST_EUCLIDEAN); if(dist==DIST_CUSTOM) CClustering::ClusterizerSetDistances(m_cs,pd,pd.Cols(),true); CClustering::ClusterizerSetAHCAlgo(m_cs,linkage); CClustering::ClusterizerRunAHC(m_cs,m_rep); return m_rep.m_terminationtype==1; } //+------------------------------------------------------------------+ //| output clusters to vector array | //+------------------------------------------------------------------+ bool get_clusters(vector &out[]) { if(m_rep.m_terminationtype!=1) { Print(__FUNCTION__, " no cluster information available"); return false; } if(ArrayResize(out,m_rep.m_pz.Rows())!=m_rep.m_pz.Rows()) { Print(__FUNCTION__, " error ", GetLastError()); return false; } for(int i = 0; i<m_rep.m_pm.Rows(); i++) { int zz = 0; for(int j = 0; j<m_rep.m_pm.Cols()-2; j+=2) { int from = m_rep.m_pm.Get(i,j); int to = m_rep.m_pm.Get(i,j+1); if(!out[i].Resize((to-from)+zz+1)) { Print(__FUNCTION__, " error ", GetLastError()); return false; } for(int k = from; k<=to; k++,zz++) out[i][zz] = m_rep.m_p[k]; } } return true; } };
تابع cluster()
خوشهبندی سلسلهمراتبی را بر روی یک مجموعه از نقاط ورودی انجام میدهد. این تابع چهار پارامتر میگیرد: یک ارجاع به یک ماتریس از نقاط ورودی، تعداد عواملی که باید در نظر گرفته شوند، روش پیوندی که باید استفاده شود، و معیار فاصله. ابتدا، اگر معیار فاصله مشخص شده، سفارشی باشد، یک ماتریس فاصله سفارشی محاسبه میشود. اگر محاسبه فاصله ناموفق باشد، تابع مقدار false
را برمیگرداند. سپس، دو ماتریس، pp
و pd
، از دادههای فاصله محاسبه شده مقداردهی میشوند. این تابع سپس نقاط را برای خوشهبندی با استفاده از معیار فاصله تنظیم میکند و اگر معیار فاصله به گزینه سفارشی تنظیم نشده باشد، به طور پیشفرض از فاصله اقلیدسی استفاده میکند. اگر معیار فاصله سفارشی باشد، فاصلهها برای خوشهبندی به تناسب تنظیم میشوند.
پس از تنظیم فاصله و نقاط، تابع الگوریتم خوشهبندی سلسلهمراتبی را با روش پیوندی مشخص شده پیکربندی میکند. سپس الگوریتم خوشهبندی سلسلهمراتبی تجمعی را اجرا میکند و نوع توقف فرآیند خوشهبندی را بررسی میکند. اگر نوع توقف برابر با 1 باشد، که نشاندهنده خوشهبندی موفقیتآمیز است، تابع مقدار true
را برمیگرداند، در غیر این صورت مقدار false
را برمیگرداند.
تابع get_clusters()
خوشهها را از نتایج یک فرآیند خوشهبندی سلسلهمراتبی استخراج و خروجی میکند. این تابع یک پارامتر میگیرد: یک آرایه از وکتورها out[]
که با خوشهها پر خواهد شد. ابتدا، این تابع بررسی میکند که آیا نوع توقف فرآیند خوشهبندی برابر با 1 است که نشاندهنده خوشهبندی موفقیتآمیز میباشد. اگر نه، یک پیام خطا چاپ میکند و مقدار false
را برمیگرداند. سپس، تابع از هر سطر ماتریس m_rep.m_pm
، که اطلاعات خوشهبندی را در بر دارد، عبور میکند. برای هر سطر، یک متغیر zz
برای پیگیری شاخص در وکتور خروجی مقداردهی میشود. سپس از ستونهای سطر جاری عبور کرده و جفت ستونها (که نمایانگر شاخصهای شروع و پایان خوشهها هستند) را پردازش میکند. برای هر جفت، دامنه شاخصها (از from
تا to
) محاسبه و وکتور خروجی جاری برای جای دادن عناصر خوشه تغییر اندازه مییابد. اگر تغییر اندازه ناموفق باشد، یک پیام خطا چاپ میکند و مقدار false
را برمیگرداند. در نهایت، تابع وکتور خروجی جاری را با عناصر خوشه پر میکند و از from
تا to
عبور کرده و zz
را برای هر عنصر افزایش میدهد. اگر فرآیند بهطور موفقیتآمیز به پایان برسد، تابع مقدار true
را برمیگرداند که نشاندهنده استخراج و ذخیره موفقیتآمیز خوشهها در آرایه out
است.
قطعه کد زیر نحوه استفاده از کلاس CCluster
را نشان میدهد.
vector clusters[]; CCluster fc; if(!fc.cluster(fld,Num_Dimensions,AppliedClusterAlgorithm,AppliedDistanceCriterion)) return; if(!fc.get_clusters(clusters)) return; for(uint i =0; i<clusters.Size(); i++) { Print("cluster at ", i, "\n variable indices ", clusters[i]); }
متاتریدر 5 ابزارهای مناسبی برای تجسم نتایج خوشهبندی سلسلهمراتبی تجمعی (AHC) بهطور مستقیم ندارد. در حالی که کنسول ترمینال میتواند برخی از خروجیها را نمایش دهد، این روش برای مشاهده نتایج پیچیدهای مانند نتایج AHC کاربرپسند نیست. نتایج AHC بهترین شکل بصری را از طریق دندروگرامها ارائه میدهند که ساختار سلسلهمراتبی گروهبندی دادهها را نشان میدهند. دندروگرام نحوه تشکیل خوشهها را از طریق ادغام نقاط داده یا خوشهها بهطور مرحلهای نشان میدهد. در زیر، یک دندروگرام که بهصورت دستی رسم شده است، گروهبندیها را از مجموعه دادههای شاخصهای ما نمایش میدهد.
دندروگرام خوشهها را نشان میدهد که متغیرها در آن به یکدیگر شباهت بیشتری دارند. متغیرهایی که در سطوح پایینتر (نزدیک به پایین دندروگرام) ادغام میشوند، نسبت به متغیرهایی که در سطوح بالاتر ادغام میشوند، بیشتر به هم شبیهاند. به عنوان مثال، MA_12 و MA_24 نسبت به ATR_18 شباهت بیشتری دارند. دندروگرام از رنگهای مختلف برای نشان دادن خوشههای مختلف استفاده میکند. خوشههای سبز، قرمز، آبی و زرد گروههایی از متغیرها را که به یکدیگر نزدیکتر هستند، برجسته میکنند. هر رنگ نمایانگر یک مجموعه از متغیرها است که شباهت یا افزونگی بالایی را نشان میدهند.
ارتفاعی که دو خوشه در آن ادغام میشوند، نشاندهنده عدم شباهت بین آنهاست. هرچه ارتفاع پایینتر باشد، خوشهها بیشتر به یکدیگر شبیهاند. خوشههایی که در سطوح بالاتر ادغام میشوند، مانند ادغام سیاه در بالا، نشاندهنده تفاوتهای بیشتری بین این خوشهها هستند. این خوشهبندی سلسلهمراتبی میتواند در تصمیمگیری برای انتخاب متغیرها مفید باشد. با تجزیه و تحلیل خوشهها، میتوان تصمیم گرفت که بر روی متغیرهای نماینده خاصی در هر خوشه برای تحلیلهای بیشتر تمرکز کرد و بدین ترتیب، مجموعه داده را بدون از دست دادن اطلاعات مهم سادهتر کرد.
کد MQL5 استفاده شده برای جمعآوری و تجزیه و تحلیل مجموعه دادههای شاخصها در اسکریپت EDA.mq5 قرار دارد. این کد از تمامی ابزارهای کدی که در مقاله توضیح داده شده، استفاده میکند و در فایل pfa.mqh تعریف شده است.
//+------------------------------------------------------------------+ //| EDA.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #resource "\\Indicators\\Slope.ex5" #resource "\\Indicators\\CMMA.ex5" #include<pfa.mqh> #include<ErrorDescription.mqh> #property script_show_inputs //+------------------------------------------------------------------+ //|indicator type | //+------------------------------------------------------------------+ enum SELECT_INDICATOR { CMMA=0,//CMMA SLOPE//SLOPE }; //--- input parameters input uint period_inc=2;//lookback increment input uint max_lookback=50; input ENUM_MA_METHOD AppliedMA = MODE_SMA; input datetime SampleStartDate=D'2019.12.31'; input datetime SampleStopDate=D'2022.12.31'; input string SetSymbol="BTCUSD"; input ENUM_TIMEFRAMES SetTF = PERIOD_D1; input ENUM_FACTOR_ROTATION AppliedFactorRotation = MODE_PROMAX; input ENUM_DIST_CRIT AppliedDistanceCriterion = DIST_CUSTOM; input ENUM_LINK_METHOD AppliedClusterAlgorithm = MODE_COMPLETE; input ulong Num_Dimensions = 10; //---- string csv_header=""; //csv file header int size_sample, //training set size size_observations, //size of of both training and testing sets combined maxperiod, //maximum lookback indicator_handle=INVALID_HANDLE; //long moving average indicator handle //--- vector indicator[]; //indicator indicator values; //--- matrix feature_matrix; //full matrix of features; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //---get relative shift of sample set int samplestart,samplestop,num_features; samplestart=iBarShift(SetSymbol!=""?SetSymbol:NULL,SetTF,SampleStartDate); samplestop=iBarShift(SetSymbol!=""?SetSymbol:NULL,SetTF,SampleStopDate); num_features = int((max_lookback/period_inc)*2); //---check for errors from ibarshift calls if(samplestart<0 || samplestop<0) { Print(ErrorDescription(GetLastError())); return; } //---set the size of the sample sets size_observations=(samplestart - samplestop) + 1 ; maxperiod=int(max_lookback); //---check for input errors if(size_observations<=0 || maxperiod<=0) { Print("Invalid inputs "); return; } //---allocate memory if(ArrayResize(indicator,num_features)<num_features) { Print(ErrorDescription(GetLastError())); return; } //----get the full collection of indicator values int period_len; int k=0; //--- for(SELECT_INDICATOR select_indicator = 0; select_indicator<2; select_indicator++) { for(int iperiod=0; iperiod<int(indicator.Size()/2); iperiod++) { period_len=int((iperiod+1) * period_inc); int try=10; while(try) { switch(select_indicator) { case CMMA: indicator_handle=iCustom(SetSymbol!=""?SetSymbol:NULL,SetTF,"\\Indicators\\CMMA.ex5",AppliedMA,period_len); break; case SLOPE: indicator_handle=iCustom(SetSymbol!=""?SetSymbol:NULL,SetTF,"\\Indicators\\Slope.ex5",period_len); break; } if(indicator_handle==INVALID_HANDLE) try--; else break; } if(indicator_handle==INVALID_HANDLE) { Print("Invalid indicator handle ",EnumToString(select_indicator)," ", GetLastError()); return; } Comment("copying data to buffer for indicator ",period_len); try = 0; while(!indicator[k].CopyIndicatorBuffer(indicator_handle,0,samplestop,size_observations) && try<10) { try++; Sleep(5000); } if(try<10) ++k; else { Print("error copying to indicator buffers ",GetLastError()); Comment(""); return; } if(indicator_handle!=INVALID_HANDLE && IndicatorRelease(indicator_handle)) indicator_handle=INVALID_HANDLE; } } //---resize matrix if(!feature_matrix.Resize(size_observations,indicator.Size())) { Print(ErrorDescription(GetLastError())); Comment(""); return; } //---copy collected data to matrix for(ulong i = 0; i<feature_matrix.Cols(); i++) if(!feature_matrix.Col(indicator[i],i)) { Print(ErrorDescription(GetLastError())); Comment(""); return; } //--- Comment(""); //---test dataset for principal factor analysis suitability //---kmo test vector kmo_vect; double kmo_stat; kmo(feature_matrix,kmo_vect,kmo_stat); Print("KMO test statistic ", kmo_stat); //---Bartlett sphericity test double bs_stat,bs_pvalue; bartlet_sphericity(feature_matrix,bs_stat,bs_pvalue); Print("Bartlett sphericity test p_value ", bs_pvalue); //---Extract the principal factors Cpfa fa; //--- if(!fa.fit(feature_matrix)) return; //--- matrix fld = fa.get_factor_loadings(); //--- matrix rotated_fld = fa.rotate_factorloadings(AppliedFactorRotation); //--- Print(" factor loading matrix ", fld); //--- Print("\n rotated factor loading matrix ", rotated_fld); //--- matrix egvcts; vector egvals; fa.get_eigen_structure(egvcts,egvals,false); Print("\n vects ", egvcts); Print("\n evals ", egvals); //--- vector clusters[]; CCluster fc; if(!fc.cluster(fld,Num_Dimensions,AppliedClusterAlgorithm,AppliedDistanceCriterion)) return; if(!fc.get_clusters(clusters)) return; for(uint i =0; i<clusters.Size(); i++) { Print("cluster at ", i, "\n variable indices ", clusters[i]); } } //+------------------------------------------------------------------+
همبستگی در سریهای زمانی
هنگام تحلیل متغیرها در طول زمان، روابط آنها ممکن است به طور غیرمنتظرهای تغییر کند. متغیرهایی که معمولاً مرتبط هستند ممکن است به طور ناگهانی از هم دور شوند، که این میتواند علامتی از یک مشکل بالقوه باشد. به عنوان مثال، تغییرات دما میتواند بر تقاضای برق تأثیر بگذارد که سپس بر قیمتهای گاز طبیعی تأثیر میگذارد. اگر الگوی معمول آنها تغییر کند، ممکن است نشاندهنده وقوع یک وضعیت غیرعادی باشد. به همین ترتیب، متغیرهایی که معمولاً به طور مستقل رفتار میکنند، ممکن است به طور ناگهانی به یکدیگر حرکت کنند، مانند زمانی که بخشهای مختلف بازار سهام به طور همزمان به دلیل اخبار اقتصادی مثبت افزایش مییابند.
اندازهگیری همبستگی شامل کمیتسازی این است که یک مجموعه از متغیرهای سری زمانی چقدر در یک پنجره زمانی متحرک مرتبط هستند. یکی از روشهای ابتدایی بررسی این است که چقدر واریانس توسط بزرگترین ویژهمقدار (eigenvalue) گرفته میشود. با این حال، این روش میتواند محدودکننده باشد زیرا تنها یک بعد را در نظر میگیرد. یک روش جامعتر شامل جمعآوری بزرگترین ویژهمقدارها است، بهویژه زمانی که روابط متعددی بین متغیرها وجود دارد. این روش تصویری دقیقتر از همبستگی کلی در یک سیستم با روابط پیچیده ارائه میدهد، اما نیاز به دانستن این دارد که کدام عوامل مرتبطتر هستند، چیزی که ممکن است غیرممکن باشد یا به سادگی خیلی ذهنی است.
برای سناریوهایی که تعداد روابط ناشناخته یا در حال نوسان است، به ویژه با تعداد زیادی از متغیرها، به یک رویکرد عمومیتر نیاز داریم. در سناریوهایی با ابعاد ناشناخته، میتوانیم ویژهمقدارهای مرتبشده از بزرگترین تا کوچکترین را به عنوان اعضای یک ارکستر تجسم کنیم. کلید تولید موسیقی زیبا، تنظیم صحیح سازهای مختلف به طور یکنواخت است. اگر اعضای فردی ارکستر نتوانند در سطح مناسب به طور همبسته عمل کنند، موسیقی به دست آمده ضعیف خواهد بود. همبستگی پایین خواهد بود. تصور کنید خروجی صوتی هر عضو ارکستر به عنوان یک ارزش وزنی است که به موسیقیای که مخاطبان میشنوند، کمک میکند. عدم تعادل در این مقادیر نمایانگر همبستگی است. ما یک جمع وزنی محاسبه میکنیم، که در آن وزنها نشاندهنده حجم تولیدی یک ساز هستند.
اگر هر ساز (متغیر) به طور مستقل ملودی خاص خود را اجرا کند، صدای کلی نامنظم و هرج و مرجآمیز خواهد بود که نمایانگر عدم وجود همبستگی است. اما زمانی که سازها به طور کامل هماهنگ شده و در هارمونی مینوازند، قطعهای زیبا و منسجم تولید میکنند که نشاندهنده همبستگی کامل است. همبستگی در این تمثیل مانند هارمونی ارکستر است و نشان میدهد که سازها (متغیرها) چقدر خوب با هم اجرا میکنند. اگر هارمونی به طور ناگهانی تغییر کند، نشان میدهد که اتفاق غیرعادیای در حال رخ دادن است، چه در مورد سازها و چه در مورد قطعه موسیقی.
دو حالت متضاد را در نظر بگیرید. اگر متغیرها کاملاً مستقل باشند، ماتریس همبستگی این متغیرها یک ماتریس واحد خواهد بود و همه ویژهمقدارها برابر با (1.0) خواهند بود. جمع وزنی (به دلیل وزنهای متقارن) صفر خواهد بود که نشاندهنده عدم وجود همبستگی است. از طرف دیگر، اگر همبستگی کامل بین متغیرها وجود داشته باشد، فقط یک ویژهمقدار غیرصفر وجود خواهد داشت که برابر با تعداد متغیرهاست. جمع وزنی به تعداد متغیرها تبدیل میشود و پس از نرمالسازی (تقسیم بر تعداد متغیرها) همبستگی برابر با 1.0 خواهد بود که نشاندهنده همبستگی کامل است. این روش یک معیار 0-1 از همبستگی را بر اساس عدم تعادل در توزیع ویژهمقدارها ارائه میدهد، بدون اینکه فرضیاتی درباره ابعاد مطرح شود.
برای نشان دادن همبستگی، یک اندیکاتور تولید خواهیم کرد که همبستگی قیمتهای پایانی نمادهای مختلف را در یک پنجره زمانی اندازهگیری کند. این اندیکاتور Coherence.mq5 نام خواهد داشت. کاربران میتوانند با اضافه کردن نامهای نماد به صورت یک لیست جدا شده با ویرگول، همبستگی بین نمادهای مختلف را اندازهگیری کنند. این اندیکاتور از رویکرد متفاوتی برای محاسبه همبستگی بین چندین متغیر استفاده میکند. این بار از ضریب همبستگی غیرپارامتریک اسپیرمن استفاده خواهیم کرد.
covar[0][0] = 1.0 ; for(int i=1 ; i<npred ; i++) { for(int j=0 ; j<i ; j++) { for(int k=0 ; k<lookback ; k++) { nonpar1[k] = iClose(stringbuffer[i],PERIOD_CURRENT,ibar+k); nonpar2[k] = iClose(stringbuffer[j],PERIOD_CURRENT,ibar+k); } if(!MathCorrelationSpearman(nonpar1,nonpar2,covar[i][j])) Print(" MathCorrelationSpearman failed ", GetLastError(), " :", ibar); } covar[i][i] = 1.0 ; }
تحلیل انسجام در سریهای زمانی
در هنگام تحلیل متغیرها در طول زمان، روابط آنها ممکن است به طور غیرمنتظرهای تغییر کند. متغیرهایی که معمولاً مرتبط هستند ممکن است ناگهان از هم جدا شوند که میتواند نشانهای از بروز یک مشکل باشد. به عنوان مثال، تغییرات دما میتواند بر تقاضای برق تأثیر بگذارد و این امر بر قیمتهای گاز طبیعی تأثیرگذار خواهد بود. اگر الگوی معمول آنها تغییر کند، ممکن است نشانهای از وقوع یک رویداد غیرعادی باشد. همچنین، متغیرهایی که معمولاً مستقل عمل میکنند ممکن است ناگهان با هم حرکت کنند، مانند زمانی که بخشهای مختلف یک بازار سهام به طور همزمان به دلیل اخبار مثبت اقتصادی افزایش پیدا میکنند.
اندازهگیری انسجام
اندازهگیری انسجام به معنای کمیتسنجی میزان ارتباط یک مجموعه از متغیرهای سری زمانی در یک پنجره زمانی متحرک است. یکی از روشهای ابتدایی، بررسی مقدار واریانس است که توسط بزرگترین مقدار ویژه (eigenvalue) ضبط میشود. با این حال، این روش میتواند محدود باشد زیرا فقط یک بعد را در نظر میگیرد. رویکرد جامعتری شامل جمعزدن بزرگترین مقادیر ویژه است، بهویژه زمانی که روابط متعددی میان متغیرها وجود داشته باشد. این روش تصویری دقیقتر از انسجام کلی در یک سیستم با روابط پیچیده ارائه میدهد، اما نیاز به دانستن عوامل مرتبط قبل از انجام آن دارد که ممکن است غیرممکن یا کاملاً ذهنی باشد.
برای سناریوهایی که در آن تعداد روابط ناشناخته یا متغیر است، به ویژه در مواردی که تعداد زیادی متغیر وجود دارد، رویکرد عمومیتری مورد نیاز است. در سناریوهایی با بعد ناشناخته، میتوان مقادیر ویژه مرتبشده از بزرگترین به کوچکترین را به عنوان اعضای یک ارکستر تجسم کرد. کلید تولید موسیقی زیبا، تنظیم صحیح سازهای مختلف بهطور هماهنگ است. اگر اعضای ارکستر بهدرستی در سطح مناسب هماهنگ نباشند، نتیجه موسیقی بسیار بد خواهد بود و انسجام ضعیفی خواهد داشت. تصور کنید که خروجی صوتی هر عضو ارکستر بهعنوان یک مقدار وزنی که به موسیقی گوشدهندگان کمک میکند، عمل میکند. عدم تعادل در این مقادیر نمایانگر انسجام است. ما یک مجموع وزنی محاسبه میکنیم، که وزنها نشاندهنده حجم صدا هستند که یک ساز میتواند تولید کند.
اگر هر ساز (متغیر) بهطور مستقل نغمهای جداگانه اجرا کند، صدای کلی نامنظم و آشفته خواهد بود که نمایانگر صفر انسجام است. با این حال، زمانی که سازها بهطور کامل هماهنگ هستند و در هارمونی اجرا میکنند، یک قطعه موسیقی زیبا و منسجم تولید میکنند که نشاندهنده انسجام کامل است. انسجام در این مثال مشابه هارمونی ارکستر است و نشاندهنده این است که سازها (متغیرها) چگونه به خوبی با هم اجرا میکنند. اگر هارمونی ناگهان تغییر کند، نشان میدهد که چیزی غیرمعمول در حال وقوع است.
به دو حالت افراطی توجه کنید: اگر متغیرها کاملاً مستقل باشند، ماتریس همبستگی این متغیرها یک ماتریس واحد خواهد بود و تمامی مقادیر ویژه برابر با 1.0 خواهند بود. مجموع وزنی (به دلیل وزنهای متقارن) صفر خواهد بود و نمایانگر صفر انسجام است. بهطور متناوب، اگر همبستگی کامل بین متغیرها وجود داشته باشد، فقط یک مقدار ویژه غیرصفر وجود خواهد داشت که برابر با تعداد متغیرهاست. مجموع وزنی برابر با تعداد متغیرها میشود که پس از نرمالسازی (تقسیم بر تعداد متغیرها) انسجام برابر با 1.0 را نشان میدهد و نشاندهنده همبستگی کامل است. این روش یک اندازهگیری از 0 تا 1 برای انسجام بر اساس عدم تعادل در توزیع مقادیر ویژه ارائه میدهد، بدون اینکه فرضیاتی درباره بعدی بودن آن انجام دهد.
تولید نشانگر انسجام
برای نشان دادن انسجام، ما یک نشانگر به نام Coherence.mq5 تولید خواهیم کرد که انسجام قیمتهای پایانی نمادهای مختلف را در یک پنجره زمانی اندازهگیری میکند. کاربران میتوانند با اضافه کردن نامهای نماد بهعنوان یک لیست جداشده با کاما، انسجام بین نمادهای مختلف را اندازهگیری کنند. این نشانگر از رویکرد متفاوتی برای محاسبه همبستگی بین چندین متغیر استفاده میکند و در اینجا از ضریب همبستگی غیرپارامتری اسپیرمن استفاده میشود.
کد کامل
کد کامل در انتهای مقاله پیوست شده است. بیایید ببینیم که این نشانگر با طولهای مختلف پنجره چگونه به نظر میرسد و انسجام بین ارزهای دیجیتال BTCUSD، DOGUSD و XRPUSD را اندازهگیری کنیم.
نگاهی به نمودار 60 روزه انسجام میاندازیم که پیشفرضهای شخصی ما را در مورد اینکه این نمادها با انسجام قابل توجهی حرکت میکنند، کنار گذاشت. جالب است که این انسجام چقدر نوسان دارد و مقادیر در کل طیف مقادیر ممکن متغیر است.
با افزایش طول پنجرهها، شروع به مشاهده دورههای ثبات در انسجام میکنیم، اما دوباره ماهیت این انسجام غیرمنتظره است. دورههای قابل توجهی وجود دارد که تقریباً انسجام صفر است.
نتیجهگیری
استفاده از مقادیر ویژه و بردارهای ویژه در این تکنیکهای پیشرفته، انعطافپذیری و اهمیت بنیادین آنها را در علم دادهها نشان میدهد. آنها چارچوب محکمی برای کاهش بعد، شناسایی الگوها و کشف ساختارهای پنهان در مجموعههای داده پیچیده ارائه میدهند. با فراتر رفتن از تحلیل مؤلفههای اصلی (PCA)، ابزارهای غنیتری را که بینشهای ظریفتری ارائه میدهند، بهدست میآوریم. این متن نشان میدهد که مقادیر ویژه و بردارهای ویژه بیشتر از مجردات ریاضی هستند و به عنوان سنگبنای تکنیکهای تحلیلی پیشرفتهای عمل میکنند که تجار مدرن میتوانند از آنها برای کسب برتری استفاده کنند. تمام کدهای نشاندادهشده در مقاله در فایل فشردهای پیوست شدهاند.
نظرات کاربران