# مهاجرت از اسکرپینگ TSETMC

> راهنمای جایگزینی اسکرپر TSETMC یا کتابخانه‌هایی مثل pytse-client و finpy-tse با API روشا؛ جدول تطبیق کارها با endpointها و تغییرهای داده.
> Source: https://poolick.ir/docs/guides/migrate-from-scraping/

اگر امروز دادهٔ بورس را با اسکرپر خودتان از TSETMC یا با کتابخانه‌ای متن‌باز مثل pytse-client یا finpy-tse می‌گیرید، می‌توانید همان داده را با یک درخواست HTTP از روشا بگیرید. این صفحه می‌گوید هر کار رایج به کدام endpoint می‌رسد، چه چیزهایی در داده فرق دارد و چه چیزهایی همچنان کار خود شماست.

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

## هر کار به کدام endpoint می‌رسد؟

| کاری که پیش‌تر می‌کردید | در روشا |
|---|---|
| پیدا کردن شناسهٔ نماد (`insCode`) از روی نماد فارسی | [`GET /v1/instruments?q=…`](/docs/api/instruments/) |
| گرفتن مشخصات نماد: نام، ISIN، بازار، گروه صنعت، تعداد سهام | [`GET /v1/instruments/{ref}`](/docs/api/instruments/) |
| دانلود سابقهٔ روزانهٔ قیمت و حجم | [`GET /v1/instruments/{ref}/daily`](/docs/api/daily/) |
| تعدیل قیمت بابت افزایش سرمایه و سود نقدی | همان endpoint با `adjusted=true` |
| گرفتن فهرست رویدادهای تعدیل | [`GET /v1/instruments/{ref}/adjustments`](/docs/api/adjustments/) |
| سابقهٔ خرید و فروش حقیقی و حقوقی | [`GET /v1/instruments/{ref}/client-type`](/docs/api/client-type/) |
| سابقهٔ شاخص کل و شاخص‌های دیگر | [`GET /v1/indices/{ref}/daily`](/docs/api/indices/) |
| قیمت لحظه‌ای و عمق بازار در ساعات معامله | [`GET /v1/instruments/{ref}/quote`](/docs/api/intraday/) (خانوادهٔ `intraday`) |
| ریزمعاملات یک روز | [`GET /v1/instruments/{ref}/trades`](/docs/api/intraday/) (خانوادهٔ `intraday`) |
| ساختن کندل درون‌روز از ریزمعاملات | [`GET /v1/instruments/{ref}/bars`](/docs/api/intraday/) (خانوادهٔ `intraday`) |
| تشخیص روزهای معاملاتی و تعطیلی‌ها | [`GET /v1/calendar`](/docs/api/calendar/) |
| NAV، خالص دارایی و بازده صندوق‌ها | [`GET /v1/funds`](/docs/api/funds/) و [`GET /v1/funds/{ref}/history`](/docs/api/funds/) (منبع: فیپیران) |
| پرسیدن از داده به زبان طبیعی | [سرور MCP](/docs/mcp/) |

## نمونه: سابقهٔ تعدیل‌شده در DataFrame

رایج‌ترین کار، گرفتن سابقهٔ تعدیل‌شدهٔ یک نماد در DataFrame است. با روشا برنامهٔ کامل آن این است:

```python

BASE = "https://poolick.ir"
HEADERS = {"Authorization": f"Bearer {os.environ['ROSHA_KEY']}"}

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()

data = get(
    "/v1/instruments/فولاد/daily",
    params={"adjusted": "true", "limit": 5000},
)
df = pd.DataFrame(data["rows"]).set_index("d")
df.index = pd.to_datetime(df.index)
print(df[["open", "high", "low", "close", "volume"]].tail())
```

نمونه‌های بیشتر در [پایتون و pandas](/docs/python/) است.

## چه چیزهایی در داده فرق دارد؟

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

| موضوع | در روشا | چه چیزی را بررسی کنید |
|---|---|---|
| واحد پول | ریال | اگر کد شما با تومان کار می‌کند، بر ۱۰ تقسیم کنید |
| شناسهٔ نماد | `ins_code` به شکل **رشته** | ستون‌ها و کلیدهای خود را متنی کنید؛ عدد ۶۴ بیتی اعشاری رقم‌های آخر را عوض می‌کند |
| تعدیل | پرچم `adjusted` در همان endpoint؛ پیش‌فرض `false` | پیش‌فرض، قیمت خام است. برای بازده `adjusted=true` بفرستید |
| دامنهٔ تعدیل | افزایش سرمایه و سود نقدی با هم، بر اساس رویدادهای TSETMC؛ حجم تعدیل نمی‌شود | اگر پیش‌تر فقط یکی را تعدیل می‌کردید، اعداد فرق خواهد کرد |
| `close` و `last` | `close` قیمت پایانی رسمی؛ `last` قیمت آخرین معامله | نام ستون‌های خود را با این دو تطبیق دهید |
| تاریخ | پاسخ میلادی ISO، به‌همراه `jdate` شمسی در ردیف‌های روزانه؛ درخواست هر سه قالب را می‌پذیرد | ایندکس تاریخ خود را با `d` یا `jdate` بسازید |
| ترتیب | از قدیم به جدید؛ `limit` یعنی N ردیف آخر | اگر کد شما ترتیب نزولی فرض می‌کند، آن را برگردانید |

دو تفاوت کوچک‌تر:

- **ی و ک:** نام‌ها و نمادها با «ی» و «ک» فارسی ذخیره شده‌اند و ورودی جست‌وجو هم یکسان‌سازی می‌شود. اگر در کد خود نمادها را با حروف عربی مقایسه می‌کنید، مقایسه را یکسان‌سازی کنید.
- **روز بدون معامله:** `open`، `high` و `low` در آن روز `null` است، نه صفر.

## چه چیزهایی دیگر لازم نیست؟

این کارها را روشا پیش از رسیدن داده به شما انجام داده است:

- نگه‌داری اسکرپر در برابر تغییر صفحه‌ها و پاسخ‌های منبع؛
- تبدیل نماد فارسی به `insCode` و انتخاب بین نماد قدیم و جدید (با `ref` یا جست‌وجو)؛
- یکسان‌سازی حروف عربی و فارسی؛
- محاسبهٔ ضریب تعدیل و اعمال آن؛
- ساختن کندل از ریزمعاملات؛
- تبدیل تاریخ شمسی به میلادی در ورودی.

## چه چیزهایی کار خودتان می‌ماند؟

روشا دادهٔ خام و تعدیل‌شده می‌دهد؛ این بخش‌ها همچنان با شماست:

- **ذخیره‌سازی:** اگر به نسخهٔ محلی نیاز دارید، خودتان نگهش می‌دارید. روش در [همگام‌سازی روزانه با پایگاه داده](/docs/guides/daily-sync/).
- **اندیکاتورها و مدل‌ها:** میانگین متحرک، RSI، بازده و هر محاسبهٔ دیگر را خودتان انجام می‌دهید.
- **رعایت سقف‌ها:** rate limit و سهمیهٔ روزانهٔ پلن را باید رعایت کنید و برای `429` به اندازهٔ `Retry-After` صبر کنید. [محدودیت‌ها و پلن‌ها](/docs/limits/).
- **نگهداری کلید:** کلید را در متغیر محیطی نگه دارید و در مرورگر نگذارید. [احراز هویت و کلیدها](/docs/authentication/).
- **بررسی `source` در quote:** خارج از ساعات بازار، quote آخرین ردیف روزانه است.
- **داده‌هایی که روشا ندارد:** دادهٔ بنیادی و اطلاعیه‌های کدال، و قیمت ارز و طلا در روشا نیست. اگر به آن‌ها نیاز دارید، منبع فعلی خود را برای همان بخش نگه دارید.

## چه چیزهایی محدودیت دارد؟

پیش از تصمیم، این محدودیت‌ها را بدانید:

- **دادهٔ روزانه یک بار در روز تازه می‌شود:** ساعت ۱۸:۱۵ تهران، شنبه تا چهارشنبه. ارقام آخرین روز ممکن است تا اجرای بعدی اصلاح شود. [به‌روزرسانی داده‌ها](/docs/freshness/).
- **quote زنده هر ۳۰ ثانیه تازه می‌شود** (پس از ۱۳:۰۵ هر ۲ دقیقه) و جریان tick به tick نیست.
- **ریزمعاملات برای همهٔ روزهای گذشته موجود نیست.** پاسخ خالی یعنی ریزمعاملات آن روز ذخیره نشده است. اگر به بازهٔ مشخصی نیاز دارید، پیش از شروع با [پشتیبانی](/contact/) هماهنگ کنید.
- **هر پاسخ حداکثر ۵٬۰۰۰ ردیف دارد.** برای سابقهٔ بلندتر با تاریخ صفحه‌بندی کنید.
- **دادهٔ لحظه‌ای به پلنی با `intraday` نیاز دارد** (تا آبان ۱۴۰۵: حرفه‌ای و سازمانی). [قیمت‌ها](/pricing/).

## گام‌های پیشنهادی مهاجرت

1. [کلید رایگان بگیرید](/panel/signup/) و [شروع سریع](/docs/quickstart/) را اجرا کنید.
2. برای نمادهایی که دنبال می‌کنید، `ins_code` را یک بار با جست‌وجو بگیرید و ذخیره کنید.
3. برای چند نماد و چند روز، خروجی روشا را با خروجی فعلی خود مقایسه کنید. به واحد (ریال)، `close` در برابر `last` و حالت تعدیل دقت کنید.
4. لایهٔ دریافت داده را در کد خود با تابع `get` جایگزین کنید و بقیهٔ کد را دست نزنید.
5. کار زمان‌بندی‌شدهٔ خود را به پس از ۱۸:۱۵ تهران ببرید.
