قیمت تعدیلشده چیست و چرا مهم است؟
قیمت تعدیلشده، سابقهٔ قیمت یک سهم است که اثر افزایش سرمایه و سود نقدی از آن برداشته شده است. بدون تعدیل، نمودار در روز بازگشایی پس از این رویدادها یک افت ناگهانی نشان میدهد که معاملهای پشت آن نیست. هر محاسبهٔ بازده، میانگین متحرک یا بکتست روی قیمت خام، این افت را زیان واقعی حساب میکند.
در روشا با adjusted=true قیمت تعدیلشده را میگیرید. این نوشته روش محاسبه را با اعداد واقعی نماد فولاد نشان میدهد و در پایان کدی میدهد که محاسبه را خودتان بازبینی کنید.
چرا سابقهٔ خام قیمت میپرد؟
دو رویداد شرکتی قیمت سهم را بدون معامله جابهجا میکنند:
- افزایش سرمایه. تعداد سهام شرکت زیاد میشود و ارزش شرکت میان سهام بیشتری تقسیم میشود. قیمت هر سهم پس از بازگشایی پایینتر است.
- سود نقدی. پس از مجمع، سود تقسیمی از قیمت سهم کم میشود، چون خریدار پس از مجمع آن سود را نمیگیرد.
نمونهٔ واقعی: قیمت پایانی فولاد در ۲۳ بهمن ۱۳۹۷ برابر ۴٬۸۸۸ ریال بود. نماد چند روز متوقف شد و در ۳۰ بهمن با قیمت پایانی ۲٬۸۲۰ ریال برگشت. این افت ۴۲ درصدی حاصل افزایش سرمایه است، نه فروش سهامداران.
date close prev_close volume2019-02-12 4888.0 4906.0 144481552019-02-13 4888.0 4888.0 02019-02-18 4888.0 4888.0 02019-02-19 2820.0 2820.0 02019-02-20 3046.0 2820.0 137718369ضریب تعدیل چطور حساب میشود؟
TSETMC برای هر رویداد دو عدد منتشر میکند: قیمت پایانی پیش از تعدیل و قیمت پایانی پس از تعدیل. ضریب تعدیل، نسبت این دو است:
ضریب رویداد = close_adjusted ÷ close_unadjustedرویدادها را از نقطهٔ پایانی adjustments میگیرید. رویداد بالا اینطور ثبت شده است:
{"d":"2019-02-19","close_adjusted":2820.0,"close_unadjusted":4888.0}ضریب این رویداد ۲٬۸۲۰ ÷ ۴٬۸۸۸ = ۰٫۵۷۶۹ است. این عدد با یک افزایش سرمایهٔ حدود ۷۳ درصدی سازگار است (۱ ÷ ۱٫۷۳۳).
سه قاعده، کل روش را میسازد:
- هر رویداد روزهایی را تغییر میدهد که هنوز بر مبنای قیمت قدیماند. یعنی همهٔ روزهای پیش از تاریخ رویداد (D)، و خودِ روز D اگر نماد در آن روز متوقف بوده و هنوز قیمت قدیم را نشان میدهد. نشانهٔ آن ساده است: اگر
prev_closeخام روز D باclose_adjustedرویداد برابر باشد، روز D از قیمت جدید شروع شده و دست نمیخورد؛ وگرنه روز D هم تعدیل میشود. در دادههای TSETMC تا سال ۱۳۹۸ حالت اول و از ۱۳۹۹ حالت دوم رایج است. - ضریبها در هم ضرب میشوند. ضریب نهایی هر روز، حاصلضرب ضریب همهٔ رویدادهایی است که آن روز را تغییر میدهند.
- حجم تعدیل نمیشود. فقط شش ستون قیمت تغییر میکند:
open،high،low،close،lastوprev_close.volume،valueوtradesهمان اعداد خام هستند.
نتیجه با دو رقم اعشار گرد میشود. به این روش «تعدیل رو به عقب» میگویند: قیمت امروز همان قیمت واقعی بازار میماند و گذشته به مقیاس امروز درمیآید.
یک مثال عددی کامل
فولاد تا آبان ۱۴۰۵ بیستوسه رویداد تعدیل دارد. نُه رویداد آخر و ضریب تجمعی آنها این است:
| تاریخ رویداد | close_adjusted | close_unadjusted | ضریب رویداد | ضریب تجمعی روزهای پیش از آن |
|---|---|---|---|---|
| 2019-02-19 | 2820 | 4888 | 0.576923 | 0.321100 |
| 2019-07-22 | 3997 | 4297 | 0.930184 | 0.556574 |
| 2020-08-05 | 20720 | 20945 | 0.989258 | 0.598348 |
| 2021-08-03 | 10550 | 10950 | 0.963470 | 0.604846 |
| 2022-08-03 | 9470 | 11170 | 0.847807 | 0.627778 |
| 2023-07-22 | 4960 | 5460 | 0.908425 | 0.740473 |
| 2024-07-21 | 4800 | 5200 | 0.923077 | 0.815118 |
| 2025-08-04 | 2580 | 2860 | 0.902098 | 0.883044 |
| 2026-08-03 | 2549 | 2604 | 0.978879 | 0.978879 |
ستون آخر از پایین به بالا ساخته میشود. برای نمونه ۰٫۸۸۳۰۴۴ = ۰٫۹۰۲۰۹۸ × ۰٫۹۷۸۸۷۹.
حالا دو روز دو طرف رویداد بهمن ۱۳۹۷ را حساب کنیم:
- ۲۳ بهمن ۱۳۹۷ (پیش از رویداد): قیمت خام ۴٬۸۸۸ ریال است. همهٔ نُه رویداد پس از این روز هستند. ۴٬۸۸۸ × ۰٫۳۲۱۱۰۰ = ۱٬۵۶۹٫۵۴ ریال.
- ۳۰ بهمن ۱۳۹۷ (روز رویداد): قیمت خام ۲٬۸۲۰ ریال است و این روز از قیمت جدید شروع شده، پس رویداد خودش روی آن اثر ندارد. هشت رویداد پس از این روز هستند. ۲٬۸۲۰ × ۰٫۵۵۶۵۷۴ = ۱٬۵۶۹٫۵۴ ریال.
هر دو روز در سری تعدیلشده ۱٬۵۶۹٫۵۴ ریال هستند. پرش ۴۲ درصدی از بین رفته و بازده این چند روز صفر است، که درست است: نماد متوقف بود. پاسخ API با adjusted=true همین را میدهد:
date close prev_close volume2019-02-12 1569.54 1575.32 144481552019-02-19 1569.54 1569.54 02019-02-20 1695.32 1569.54 137718369چطور قیمت تعدیلشده را از روشا بگیرم؟
پارامتر adjusted=true را به سابقهٔ روزانه اضافه کنید:
curl "https://poolick.ir/v1/instruments/46348559193224090/daily?adjusted=true&limit=5" \ -H "Authorization: Bearer $ROSHA_KEY"فیلد adjusted در پاسخ میگوید ردیفها تعدیلشدهاند یا نه. در MCP همین کار را ابزار get_daily_history با adjusted=true انجام میدهد. فایل CSV رایگان صفحهٔ هر نماد هم قیمت تعدیلشده دارد.
چطور محاسبه را خودم بازبینی کنم؟
کد زیر رویدادها و سابقهٔ خام را میگیرد، ضریبها را با همان سه قاعده حساب میکند و نتیجه را با پاسخ adjusted=true مقایسه میکند:
import osimport time
import requests
BASE = "https://poolick.ir"HEADERS = {"Authorization": f"Bearer {os.environ['ROSHA_KEY']}"}REF = "46348559193224090" # فولاد
def get(path, **kwargs): """GET with one retry on 429, waiting as long as Retry-After says.""" for _ in range(2): r = requests.get(BASE + path, headers=HEADERS, timeout=30, **kwargs) if r.status_code != 429: break time.sleep(int(r.headers.get("Retry-After", "1"))) r.raise_for_status() return r.json()
events = get(f"/v1/instruments/{REF}/adjustments")raw = get(f"/v1/instruments/{REF}/daily", params={"limit": 5000})["rows"]adjusted = get( f"/v1/instruments/{REF}/daily", params={"limit": 5000, "adjusted": "true"})["rows"]
prev_close = {r["d"]: r["prev_close"] for r in raw}
def applies(event, day): """True if `day` is still on the old price basis of `event`.""" if day != event["d"]: return day < event["d"] # On the event day itself: already on the new basis if it opens from the adjusted close. opened_from = prev_close.get(day) return opened_from is not None and abs(opened_from - event["close_adjusted"]) > 0.5
def factor(day): f = 1.0 for e in events: if e["close_unadjusted"] and applies(e, day): f *= e["close_adjusted"] / e["close_unadjusted"] return f
worst = max( abs(round(r["close"] * factor(r["d"]), 2) - a["close"]) for r, a in zip(raw, adjusted))print(len(events), "events,", len(raw), "rows, largest difference:", worst, "rials")خروجی برای فولاد در آبان ۱۴۰۵:
23 events, 4680 rows, largest difference: 0.0 rialsتاریخها رشتهٔ ISO هستند و مقایسهٔ رشتهای آنها همان مقایسهٔ تاریخی است.
چند نکته که در عمل مهم است
- سری تعدیلشده ثابت نیست. با هر رویداد تازه، همهٔ قیمتهای پیش از آن دوباره ضرب میشوند. اگر داده را در پایگاه دادهٔ خود نگه میدارید، قیمت خام و جدول رویدادها را ذخیره کنید و تعدیل را هنگام خواندن بسازید. روش آن در همگامسازی روزانه آمده است.
- قیمت تعدیلشده یک عدد محاسبهای است. هیچ معاملهای با ۱٬۵۶۹٫۵۴ ریال انجام نشده است. برای تطبیق با صورتمعامله یا ارزش روز پرتفوی در گذشته، قیمت خام را به کار ببرید.
- روزهای توقف را جدا کنید. در روزهایی که نماد معامله نشده،
open،highوlowتهی وvolumeصفر است. تاریخ ثبت رویداد معمولاً در همین روزهای توقف است. برای محاسبهٔ بازده و اندیکاتور، فقط ردیفهای دارای معامله را به کار ببرید. - ضریب از دادهٔ TSETMC میآید. روشا ضریب را خودش برآورد نمیکند. اگر TSETMC رویدادی را ثبت نکرده باشد، در سری تعدیلشده هم نیست.
- صندوقها جدا هستند. این روش برای نمادهای TSETMC است. سود تقسیمی صندوقها در فیلد
dividendsصندوق میآید.
تعریف کوتاه این مفهوم در واژهنامه است. این نوشته آموزشی است و هیچ بخشی از آن توصیهٔ سرمایهگذاری نیست.