> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# التدرجات والمراكز (Ticks and Positions)

> كيف يقسّم CLMM الأسعار إلى تدرجات (ticks)، وكيف تضغط مصفوفات التدرجات (tick-arrays) التخزين، والقواعد التي تحكم موضع أي مركز (position).

<Info>
  **هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.**

  [عرض النسخة الإنجليزية →](/products/clmm/ticks-and-positions)
</Info>

## لماذا توجد التدرجات (Ticks)؟

تتركز سيولة CLMM في نطاقات سعرية محددة. ولجعل هذه النطاقات قابلةً للمعالجة على السلسلة، تُكمَّم الأسعار إلى **تدرجات (ticks)** صحيحة، بحيث يمثّل كل تدرج مضاعفًا ثابتًا للتدرج السابق:

$$
\text{price}(i) = 1.0001^{\,i}
$$

يقابل كل تدرج حركةً سعريةً بنسبة 0.01%، أي ما يعادل نقطة أساس واحدة تقريبًا. وفيما يلي جدول التعيين:

| مؤشر التدرج `i`      | مضاعف السعر         |
| -------------------- | ------------------- |
| `0`                  | `1.0000`            |
| `100`                | `1.0100` (≈ +1.00%) |
| `-100`               | `0.9900` (≈ −0.99%) |
| `10000`              | `2.7181` (≈ e)      |
| `MAX_TICK = 443636`  | ≈ `1.84e19`         |
| `MIN_TICK = -443636` | ≈ `5.42e-20`        |

اختيار `MIN_TICK` و`MAX_TICK` مدروس لضمان أن قيمة `sqrt_price_x64` تتسع في نوع البيانات `u128` عند طرفي النطاق. يفرض كل pool شرطَي: `tick_lower >= MIN_TICK` و`tick_upper <= MAX_TICK`. من الناحية العملية، تُقيّد واجهة الويب النطاق إلى قيم أضيق بكثير لمنع المستخدمين من تجميد سيولتهم في تدرجات لا يمكن الوصول إليها.

## التباعد بين التدرجات (Tick Spacing)

يُحدد `AmmConfig` الخاص بكل pool قيمةَ **التباعد بين التدرجات (tick spacing)**، وهي التدرجات الوحيدة المسموح باستخدامها كنقاط نهاية للمراكز. فإن كان `tick_spacing = 60`، لم تكن التدرجات الصالحة إلا: `…, −120, −60, 0, 60, 120, …`. أي محاولة لفتح مركز بنقطة نهاية `31` ستؤدي إلى إلغاء العملية برسالة `InvalidTickIndex`.

القيم الشائعة للتباعد المنشورة:

| مستوى الرسوم | `trade_fee_rate` | التباعد بين التدرجات | أضخم خطوة سعرية لكل موضع تدرج |
| ------------ | ---------------- | -------------------- | ----------------------------- |
| 0.01%        | `100`            | 1                    | 0.01%                         |
| 0.05%        | `500`            | 10                   | 0.10%                         |
| 0.25%        | `2500`           | 60                   | 0.60%                         |
| 1.00%        | `10000`          | 120                  | 1.21%                         |

كلما اتسع التباعد، قلّت مصفوفات التدرجات اللازمة للتهيئة، وانخفضت تكلفة فتح مركز واسع، وأصبح الحد السعري أقل دقةً. تعيش أزواج التداول المتقلبة عادةً في مستويات التباعد 120، بينما تستقر الأزواج المستقرة (stables) في مستويات التباعد 1.

## مصفوفات التدرجات (Tick Arrays)

لا يخزّن الـ pool حالة كل تدرج في حسابات منفصلة. عوضًا عن ذلك، تُحزم `TICK_ARRAY_SIZE` تدرجات متجاورة (60 في Raydium CLMM الحالي) في حساب `TickArrayState` واحد. يُحدّد أول تدرج في المصفوفة قيمة `start_tick_index`، وتغطي المصفوفة تمامًا `TICK_ARRAY_SIZE * tick_spacing` وحدةً من وحدات التدرج الصحيحة.

عند `tick_spacing = 60` و`TICK_ARRAY_SIZE = 60`:

* تمتد كل مصفوفة تدرجات `60 × 60 = 3600` تدرجًا صحيحًا.
* قيمة `start_tick_index` مضاعف لـ 3600: `…, -7200, -3600, 0, 3600, 7200, …`.

نقطة نهاية المركز `t = 2040` عند `tick_spacing = 60` تقع في مصفوفة التدرجات ذات `start_tick_index = 0`، في حين تقع `t = 4200` في المصفوفة ذات `start_tick_index = 3600`.

### متى تُنشأ المصفوفة؟

إنشاء مصفوفات التدرجات مؤجَّل (lazy)؛ إذ يُهيّئ المصفوفةَ **أول** مركز يُشير إلى أي تدرج داخلها، ويدفع هو أيضًا رسوم الإيجار (rent). عمليات الـ swap لا تُهيّئ مصفوفات التدرجات، بل تتخطى المصفوفات غير المُهيَّأة باستخدام الخريطة النقطية (bitmap). يفحص تدفق فتح المركز في SDK النطاق المختار، ويحسب قائمة مصفوفات التدرجات التي يلمسها، ثم يُضيف تعليمات `init_tick_array` في نفس العملية مع `OpenPosition` إن وُجدت مصفوفات مفقودة.

### مصفوفات التدرجات لا تُغلق

بمجرد تهيئة مصفوفة تدرجات، تبقى قائمةً طوال عمر الـ pool. لا يكشف البرنامج عن أي مسار لإغلاق مصفوفة تدرجات، حتى حين يعود `initialized_tick_count` إلى الصفر. لا استرداد للإيجار من مصفوفات التدرجات؛ فالإيجار الذي دفعه أول مركز لمسَ المصفوفةَ يصبح محجوزًا في ذلك الحساب إلى الأبد. هذا مقايضة مقصودة: إعادة استخدام مصفوفة تدرجات موجودة مجانية لكل مركز لاحق، فبالتالي لا يدفع الـ pool النشط تكلفة الإيجار إلا مرةً واحدة لكل فتحة `(pool, start_tick_index)` بصرف النظر عن معدل الدوران.

### الخريطة النقطية (Bitmap)

يجب أن يكون البحث عن "أقرب تدرج مُهيَّأ على يسار/يمين التدرج الحالي" سريعًا، إذ قد تتجاوز عملية swap تدرجاتٍ كثيرة. يخزّن الـ pool خريطةً نقطيةً بمقدار bit لكل مصفوفة تدرجات، مُضمَّنةً مباشرةً في `PoolState`، تغطي نطاق ±1,024 مصفوفة حول التدرج 0. خارج هذا النطاق (المراكز ذات النطاق الكامل والإعدادات الخاصة)، تتولى `TickArrayBitmapExtension` التعامل مع الفائض.

تسير عملية swap عبر الخريطة النقطية: `lowest_set_bit_above(tick_current_array_index)` يُعطي المصفوفة التالية التي تحوي تدرجًا مُهيَّأً في الاتجاه الذي تتجه نحوه. داخل تلك المصفوفة، يُحدّد فحص بِتِّي مشابه التدرجَ المُهيَّأ التالي.

## `liquidity_gross` و`liquidity_net`

يخزّن كل تدرج **مُهيَّأ** قيمتَين للسيولة:

* **`liquidity_gross`** — مجموع `L` لجميع المراكز التي تُشير إلى هذا التدرج كنقطة نهاية (سواء أكانت حدًا أدنى أم أعلى). حين تصل `liquidity_gross` إلى الصفر، يصبح التدرج غير مُهيَّأ ويمكن حذفه من الخريطة النقطية.
* **`liquidity_net`** — التغيُّر **الموقَّع** في `liquidity` على مستوى الـ pool عندما يتجاوز السعر هذا التدرج **في الاتجاه التصاعدي** (من اليسار إلى اليمين في فضاء التدرجات). إن كان هذا التدرج حدًا أدنى لمركز بحجم `L`، فإنه يُضيف `+L`؛ وإن كان حدًا أعلى لذلك المركز، فإنه يُضيف `−L`.

مثال توضيحي: مركزان على نفس الـ pool.

* المركز A: `tick_lower = -120`، `tick_upper = 0`، سيولة `L_A = 100`.
* المركز B: `tick_lower = -60`، `tick_upper = 60`، سيولة `L_B = 50`.

حالة التدرجات تفصيليًا:

| التدرج | يمسّه            | `liquidity_gross` | `liquidity_net` |
| ------ | ---------------- | ----------------- | --------------- |
| `-120` | الحد الأدنى لـ A | 100               | +100            |
| `-60`  | الحد الأدنى لـ B | 50                | +50             |
| `0`    | الحد الأعلى لـ A | 100               | −100            |
| `60`   | الحد الأعلى لـ B | 50                | −50             |

قيمة `liquidity` على مستوى الـ pool لمختلف قيم `tick_current`:

* `tick_current = -180`: `liquidity = 0` (قبل أي مركز)
* `tick_current = -90`: `liquidity = 100` (داخل A فقط)
* `tick_current = -30`: `liquidity = 150` (داخل A و B معًا)
* `tick_current = 30`: `liquidity = 50` (داخل B فقط)
* `tick_current = 90`: `liquidity = 0` (بعد كلا المركزين)

عند كل تجاوز لتدرج أثناء عملية swap، يُضيف البرنامج `liquidity_net` (التي قد تكون سالبة) إلى `PoolState.liquidity`. هذه هي الآلية ذاتها المستخدمة في Uniswap v3.

## المراكز بوصفها NFTs

مركز Raydium CLMM هو NFT. عند فتح مركز، يُصكّ mint جديد كليًا بمعروض 1 في محفظة المُنشئ، وتكون صلاحية mint بيد برنامج CLMM. يربط البرنامج ملكية المركز بـ **من يملك رصيدًا في ATA لذلك الـ mint** وقت استدعاء CPI.

التبعات:

* **المراكز قابلة للنقل.** يمكن لأي محفظة بيع مركز أو توزيعه بنقل الـ NFT، ويصبح الحائز الجديد قادرًا على استدعاء `CollectRewards` و`IncreaseLiquidity` وغيرها.
* **المراكز قابلة للعنونة خارج CLMM.** تعرض المنصات والمحافظ المراكز كسائر الـ NFTs. يضبط SDK اسمًا `name` ورمزًا `symbol` مناسبَين في بيانات الـ mint الوصفية.
* **عنوان PDA للمركز مُشتق من mint الـ NFT.** يمكنك العثور على `PersonalPositionState` دون معرفة من يحتفظ به حاليًا.

### مراكز Token-2022

يمكن لـ pools CLMM الأحدث أن تُصكّ المراكز عبر Token-2022 بدلًا من SPL Token الكلاسيكي. يوفر البرنامج تعليمتَي فتح متوازيتَين — `OpenPosition` و`OpenPositionWithToken22Nft` — بدلالات متطابقة تمامًا، باستثناء برنامج الرمز المالك لـ mint الـ NFT. يتباين التوافق بين المحافظ والمنصات؛ وتتابع واجهة Raydium كلا النوعين.

## قواعد النطاق المسموح به

يفرض البرنامج عند `OpenPosition` الشروط التالية:

1. `tick_lower < tick_upper`.
2. `tick_lower % tick_spacing == 0` و`tick_upper % tick_spacing == 0`.
3. `MIN_TICK <= tick_lower` و`tick_upper <= MAX_TICK`.
4. قدّم المُنشئ مصفوفات التدرجات التي تحوي `tick_lower` و`tick_upper` — إما مُهيَّأةً مسبقًا أو عبر `init_tick_array` في نفس العملية.
5. حساب امتداد الخريطة النقطية، إن امتد هذا المركز إلى نطاق الامتداد.

إن فشل أيٌّ من هذه الشروط، تُلغى التعليمة برسالة `InvalidTickIndex` أو `NotApproved` أو `InsufficientLiquidity` بحسب القيد المنتهَك. راجع [`reference/error-codes`](/ar/reference/error-codes).

## "ضمن النطاق" مقابل "خارج النطاق"

يكون المركز **ضمن النطاق (in range)** حين يتحقق الشرط: `tick_lower <= tick_current < tick_upper`. المراكز ضمن النطاق فقط هي التي تُساهم في `PoolState.liquidity`، وبالتالي هي وحدها التي تكسب رسوم الـ swap.

المركز الخارج عن النطاق:

* يحتوي 100% من رمز **واحد** (الرمز الذي مرّ السعر بنطاقه). تحديدًا، إن كان `tick_current < tick_lower`، يحتوي المركز على token1 فقط (إذ "بِيع" إليه بتحرك السعر بعيدًا)؛ وإن كان `tick_current >= tick_upper`، يحتوي على token0 فقط.
* **لا** يكسب رسوم الـ swap.
* **يواصل** تراكم المكافآت إن كانت تدفقات مكافآت الـ pool تُصدر للسيولة خارج النطاق — غير أن السلوك الافتراضي في Raydium هو "الإصدار للسيولة ضمن النطاق فقط"، توافقًا مع اصطلاح Uniswap v3. راجع [`products/clmm/fees`](/ar/products/clmm/fees).

يُمضي مزودو السيولة في CLMM معظم اهتمامهم في إبقاء مراكزهم ضمن النطاق مع تحرك السعر.

## أخطاء التكامل الشائعة

* **نقاط نهاية لا تتوافق مع التباعد.** الكود الذي يحسب تدرجًا من سعر مستهدف يجب أن يُدوّره إلى أقرب مضاعف لـ `tick_spacing` قبل تمريره إلى `OpenPosition`. أدوات SDK (`TickUtils.getTickWithPriceAndTickspacing`) تتكفل بذلك؛ أما الحسابات المكتوبة يدويًا فغالبًا لا تفعل.
* **مصفوفات تدرجات مفقودة.** قد يستلزم فتح مركز واسع تهيئة عدة مصفوفات تدرجات؛ فنسيان تمريرها كحسابات قابلة للكتابة يُلغي العملية. تُعيد دالة `openPositionFromBase` في SDK القائمة المطلوبة تلقائيًا.
* **تدرج قديم بعد عملية swap.** قد يتجاوز `tick_current` تدرجاتٍ كثيرة في swap واحدة. إن كانت واجهتك تعرض "التدرج الحالي" من استدعاء RPC سابق ثم تفتح مركزًا في استدعاء لاحق، فقد يكون الموضع النسبي مقارنةً بالسعر الحي منحرفًا بعشرات التدرجات. أعد الجلب مباشرةً قبل التوقيع.
* **NFTs المراكز ذات البيانات الوصفية الإضافية.** إن كنت تبني محفظة تتعرف على مراكز Raydium، فاكتشفها من خلال صلاحية الـ mint (= PDA برنامج CLMM)، لا من خلال حقل بيانات وصفية ثابت.

## ما التالي؟

* [الرياضيات](/ar/products/clmm/math) — خطوات حساب الـ swap واشتقاق نمو الرسوم التي تشارك فيها حدود التدرجات.
* [الحسابات](/ar/products/clmm/accounts) — تخطيط `TickArrayState` و`PositionState`.
* [الرسوم والمكافآت](/ar/products/clmm/fees) — كيف يتحكم كون المركز ضمن النطاق في تراكم الرسوم.
* [`algorithms/clmm-math`](/ar/algorithms/clmm-math) — الاشتقاق المشترك لصيغ السيولة المركّزة.

المصادر:

* [`raydium-io/raydium-clmm` — وحدات `tick_array` و`tick` و`position`](https://github.com/raydium-io/raydium-clmm)
* ورقة "Uniswap v3 Core" البيضاء، §6 (التدرجات)، §7 (نمو الرسوم)
