حذف داده پرت در قیمت ارز؛ میانه، میانگین وزنی و قیمتگذاری لحظهای با مثال
حذف داده پرت در قیمت ارز با مثال: چرا میانگین ساده فریب میخورد، میانه و میانگین وزنی، باند درصدی و MAD، کنترل جهش ناگهانی و برچسب کممنبع در EZRate.

- میانگین ساده با یک عدد اشتباه بزرگ جابهجا میشود؛ میانه تا وقتی بیشتر منابع درست باشند، پایدار میماند.
- نرخهایی که بیش از حد مجاز (مثلاً ±۱٪) از میانه فاصله دارند، داده پرتاند و کنار گذاشته میشوند.
- کنترل جهش، نرخ جدیدی را که ناگهان فاصلهٔ زیادی دارد تا تأیید شدن منتشر نمیکند؛ کممنبع بودن هم صریح اعلام میشود.
هر سامانهای که از چند منبع قیمت جمع میکند، با یک سؤال ریاضی ساده اما مهم روبهروست: از دهها عدد که بعضیشان اشتباه یا ساختگیاند، چطور یک عدد قابل اتکا بسازیم؟ در این مقاله حذف داده پرت در قیمت ارز را با مثال عددی توضیح میدهیم؛ همان منطقی که پشت نرخهای EZRate است.
این مقاله بخشی از مجموعهٔ کشف قیمت دلار در بازار آزاد است.
مثال: ده قیمت در یک دقیقه
فرض کنید در یک دقیقه این ده قیمت فروش دلار (تومان، فرضی) از منابع مختلف رسیده است:
| منبع | قیمت | توضیح |
|---|---|---|
| ۱ | ۱۰۰٬۱۰۰ | |
| ۲ | ۱۰۰٬۲۰۰ | |
| ۳ | ۱۰۰٬۱۵۰ | |
| ۴ | ۱۰۰٬۲۵۰ | |
| ۵ | ۱۰۰٬۰۵۰ | |
| ۶ | ۱۰۰٬۳۰۰ | |
| ۷ | ۱۰۰٬۲۰۰ | |
| ۸ | ۱۰٬۰۱۵ | بهجای تومان، عدد دیگری تایپ شده (یک صفر کم) |
| ۹ | ۱۰۴٬۰۰۰ | نرخ ساختگی برای جهت دادن به بازار |
| ۱۰ | ۱۰۰٬۱۰۰ |
میانگین ساده
جمع ده عدد تقسیم بر ده حدود ۹۱٬۵۳۷ تومان میشود. این عدد از همهٔ قیمتهای واقعی بازار بیش از ۸ درصد پایینتر است. فقط یک اشتباه تایپی کافی بود تا میانگین کاملاً بیمعنی شود.
میانه
اگر ده عدد را مرتب کنیم، دو عدد وسط ۱۰۰٬۱۵۰ و ۱۰۰٬۲۰۰ هستند و میانه ۱۰۰٬۱۷۵ تومان است؛ دقیقاً وسط قیمتهای واقعی. دو عدد اشتباه، یکی خیلی کوچک و یکی خیلی بزرگ، روی میانه اثری نداشتند. این ویژگی «مقاومت» میانه است: تا وقتی کمتر از نیمی از دادهها خراب باشند، میانه درست میماند.
حذف دادههای پرت
با داشتن میانه، میتوانیم عددهای پرت را تشخیص دهیم و کنار بگذاریم. سادهترین روش، باند درصدی است: هر عددی که بیش از مثلاً یک درصد از میانه فاصله دارد، پرت است.
پرت است اگر: |قیمت − میانه| ÷ میانه > آستانه (مثلاً ۰٫۰۱)
در مثال ما باند یک درصدی حول ۱۰۰٬۱۷۵ از ۹۹٬۱۷۳ تا ۱۰۱٬۱۷۷ است. منبع ۸ (۱۰٬۰۱۵) و منبع ۹ (۱۰۴٬۰۰۰) بیرون باند قرار میگیرند و حذف میشوند. هشت قیمت باقی میماند.

روشهای دیگر تشخیص پرت
| روش | ایده | مزیت | محدودیت |
|---|---|---|---|
| باند درصدی | فاصلهٔ نسبی از میانه | ساده و قابل توضیح | آستانهٔ ثابت در روزهای پرنوسان ممکن است تنگ باشد |
| MAD (میانهٔ قدر مطلق انحرافها) | پراکندگی را هم با میانه میسنجد | با نوسان بازار خودش تطبیق میکند | با تعداد داده کم ناپایدار است |
| Z-score | فاصله بر حسب انحراف معیار | رایج در آمار | خود انحراف معیار به دادههای پرت حساس است |
برای دادههای قیمت با تعداد منبع محدود، ترکیب میانه و باند درصدی، تعادل خوبی بین سادگی، شفافیت و مقاومت میدهد.
میانگین وزنی و میانهٔ وزنی
همهٔ منابع همارزش نیستند. منبعی که حجم معاملات بیشتری دارد یا سابقهٔ دقیقتری داشته، میتواند وزن بیشتری بگیرد. در میانهٔ وزنی، به جای شمردن تعداد عددها، وزنها شمرده میشوند و عددی انتخاب میشود که نیمی از وزن کل زیر آن باشد. این روش هم مقاومت میانه را دارد و هم کیفیت منابع را در نظر میگیرد.
کنترل جهش ناگهانی
گاهی همهٔ منابع یک لحظه همجهت عدد غیرعادی میدهند؛ مثلاً چند کانال همزمان یک نرخ ساختگی را بازنشر میکنند یا یک خبر نادرست موج کوتاهی میسازد. باند حول میانه این را تشخیص نمیدهد چون میانه هم جابهجا شده است. راه حل، مقایسه با آخرین نرخ منتشرشده است: اگر نرخ جدید بیش از یک آستانه (که در پنل مدیریت تنظیم میشود) با آخرین نرخ فاصله داشت، منتشر نمیشود و نرخ قبلی میماند؛ مگر اینکه سطح جدید برای مدت مشخصی ادامه پیدا کند و تأیید شود. این همان کاری است که بازارهای مالی با «ترمز نوسان» انجام میدهند.
وقتی داده کافی نیست
میانهٔ دو عدد معنای آماری زیادی ندارد. اگر بعد از حذف دادههای پرت کمتر از پنج منبع معتبر بماند، EZRate نرخ قبلی را حفظ و آن را با برچسب «کممنبع» نمایش میدهد. این صداقت آماری است: گفتن «مطمئن نیستیم» بهتر از نمایش با اطمینان عددی است که از دو پیام ساخته شده. این وضعیت بیشتر شبها و روزهای تعطیل پیش میآید (ساعت کاری بازار).
نسخهٔ کد
from statistics import median
def robust_rate(prices, band=0.01, min_sources=5):
if not prices:
return None, 0
m = median(prices)
kept = [p for p in prices if abs(p - m) / m <= band]
if len(kept) < min_sources:
return None, len(kept) # کممنبع: نرخ قبلی را نگه دارید
return median(kept), len(kept)
prices = [100100, 100200, 100150, 100250, 100050, 100300, 100200, 10015, 104000, 100100]
print(robust_rate(prices)) # (100175.0, 8)این نسخهٔ سادهشده است. نسخهٔ عملیاتی وزن منابع، پنجرهٔ زمانی، تشخیص واحد و کنترل جهش را هم دارد. نسخهٔ انگلیسی با تمرکز بر الگوریتمهای آماری در Outlier Detection in Price Feeds و روش جمعآوری داده در OTC Market Data Aggregation آمده است. روش رسمی EZRate در روششناسی آمده است و میتوانید آن را بررسی کنید.

نرخهای لحظهای مرتبط با این مطلب: قیمت دلار، قیمت طلای ۱۸ عیار، قیمت سکه امامی.

نظرات (۰)
نظرها پس از تأیید نمایش داده میشوند؛ برای ارسال، ورود به حساب لازم است.


