# مرجع المؤشرات المخصّصة — Sovereign Chart

> **للاستخدام مع الذكاء الاصطناعي:** ارفع هذا الملف مع كود PineScript إلى Claude أو ChatGPT
> واطلب التحويل. البرومبت الجاهز في نهاية الملف.

---

## ١. البنية

المؤشر ملف JavaScript واحد فيه شيئان فقط:

```javascript
const meta = { /* وصف المؤشر */ };
function compute(candles, inputs) { /* الحساب */ }
```

لا تبويبات، ولا `this._context`، ولا فهارس رقمية للمدخلات. هذا كل شيء.

---

## ٢. كائن `meta`

```javascript
const meta = {
  name: 'RSI',                    // ≤16 حرفاً — يظهر في وسيلة الشارت
  label: 'Relative Strength Index',
  color: '#4CAF50',               // لون الرسم الرئيسي
  overlay: false,                 // true = فوق الشموع | false = لوحة سفلية
  levels: [70, 30],               // خطوط مرجعية أفقية (اختياري)
  levelAlpha: 0.15,               // شفافيتها (اختياري)
  showLastValue: false,           // إخفاء تسمية القيمة على المحور (اختياري)
  styleDefaults: { lineWidth: 2, lineStyle: 0 },  // 0=متصل 1=منقّط 2=متقطّع
  inputs: [
    { id: 'period', type: 'int', label: 'الفترة', def: 14, min: 2, max: 200, control: 'slider' },
    { id: 'mult',   type: 'float', label: 'المضاعف', def: 3.0, min: 0.1, max: 10, step: 0.1 },
    { id: 'fast',   type: 'int', label: 'سريع', def: 12, min: 1, max: 200, group: 'سريع / بطيء' },
  ],
};
```

**قواعد `inputs`:**
- `id` يجب أن يكون معرّفاً صالحاً (`[a-zA-Z_][a-zA-Z0-9_]*`) — يُستخدم مفتاحاً في `inputs`
- `control: 'slider'` يعرض منزلقاً، وبدونه حقل رقمي
- `section` يبدأ مجموعة بعنوان · `inline` يجمع عدّة بارامترات في صفّ واحد
- `tooltip` نصّ توضيحي عند المرور
- الحدّ الأقصى ٨٠ بارامتراً

**الأنواع التسعة:**

| `type` | القيمة في `inputs` | الواجهة | تحويل PineScript |
|---|---|---|---|
| `int` / `float` | رقم | حقل أو منزلق | `input.int` / `input.float` |
| `bool` | `true`/`false` | مفتاح | `input.bool` |
| `color` | `'#2962FF'` | منتقي ألوان | `input.color` |
| `string` | نصّ | حقل نصّي | `input.string` |
| `select` | أحد `options` | قائمة منسدلة | `input.string(options=[...])` |
| `session` | `'0930-1100'` | منتقيا وقت | `input.session` |
| `time` | `'0930'` | منتقي وقت | — |
| `timezone` | `'America/New_York'` | قائمة مناطق | `input.timezone` |
| `symbol` | `'US30'` أو `''` | **قائمة رموز المنصّة** | `input.symbol` |
| `source` | `'close'` … أو ناتج مؤشر آخر | قائمة المصادر | `input.source` |

> **`source`** — يصل `compute` **مصفوفة قيم** لا نصّاً، وقائمته تشمل نواتج
> المؤشرات النشطة الأخرى فتُركَّب المؤشرات بعضها على بعض. التفصيل في القسم ٣.٦.
>
> ```javascript
> { id: 'src', type: 'source', label: 'المصدر', def: 'close' }
> ```

> **`symbol`** — لا تكتب قائمة أزواج بيدك في `select`. هذا النوع يفتح قائمة
> رموز المنصّة نفسها (ببحثها وتصنيفاتها ومفضّلتها) كما يفعل `input.symbol` في
> TradingView، فتبقى القائمة صحيحة كلّما أُضيف زوج. قيمته نصّ رمز يُمرَّر إلى
> `request.security` مباشرةً، و**الفارغ `''` يعني «اتبع رمز الشارت»** — وهو خيار
> ظاهر في أعلى القائمة، فلا يعلق المستخدم على رمز ثابت.
>
> ```javascript
> { id: 'partner', type: 'symbol', label: 'الرمز المقارَن', def: 'US30' }
> ```

```javascript
{ id: 'useAsia',   type: 'bool',    label: 'آسيا',  def: true,        inline: 'asia', section: 'الجلسات' },
{ id: 'asiaName',  type: 'string',  label: 'الاسم', def: 'Asia',      inline: 'asia' },
{ id: 'asiaSess',  type: 'session', label: 'الوقت', def: '2000-0000', inline: 'asia' },
{ id: 'asiaColor', type: 'color',   label: 'اللون', def: '#2962FF',   inline: 'asia' },
```

### المنطقة الزمنية — مترجم أوقات الجلسات

ثلاث طبقات زمنية منفصلة، تماماً كما في TradingView:

| الطبقة | من يحدّدها |
|---|---|
| طابع الشمعة | المغذّي (Binance بـUTC، وMT5 بتوقيت خادمه ‎+GMT3 — يُصحَّح تلقائياً) |
| **منطقة المؤشر** | أنت: بها يُفسَّر نصّ `session` |
| منطقة المحور | المستخدم من ترس المحور — وهي وحدها ما يظهر أسفل الشارت |

الفرق بين الأخيرتين هو الإزاحة التي يراها المستخدم: جلسة مكتوبة `1300-2200`
بتوقيت نيويورك تُرسم عند 20:00 على محور مضبوط ببغداد. هذا مقصود لا خلل.

منطقة المؤشر تُعلَن بإحدى طريقتين:

```javascript
var meta = {
  timezone: 'chart',            // إعلان ثابت، أو…
  inputs: [
    { id: 'zone', type: 'timezone', label: 'المنطقة الزمنية', def: 'America/New_York' }
  ]
};
```

المدخل يتقدّم على الإعلان الثابت — فالمستخدم يملك الكلمة الأخيرة. القيم:
معرّف IANA (`'Europe/London'`)، أو `'UTC'`، أو `'chart'` (يتبع منطقة المحور،
فما يكتبه المستخدم هو ما يراه) أو `'exchange'` (نيويورك للفوركس، UTC للكريبتو).

> **تحذير توافقية:** مؤشر لا يعلن منطقته يبقى على السلوك القديم — الافتراض
> نيويورك، وبلا تصحيح توقيت مغذّي MT5. أضِف `timezone` وستنزاح جلساته عمّا
> اعتاده مستخدموه، فاذكر ذلك عند تحديث مؤشر منشور.

داخل `compute` كل شيء يتبع تلك المنطقة تلقائياً:

```javascript
TA.inSession(c[i].time, S.ny)                  // بمنطقة المؤشر
TA.inSession(c[i].time, S.ny, 'Asia/Tokyo')    // بمنطقة صريحة تتجاوزها
TA.tz(c[i].time).h                             // الساعة بمنطقة المؤشر
TA.tzName()                                    // اسم المنطقة السارية — لوسم على الشارت
```

> **الوسيط الصريح نهائيّ** — كما هو الوسيط الثالث في `time()` عند Pine. مؤشر
> لا يعلن `meta.timezone` يتبع منطقة المحور، لكنها **افتراضه** عند النداء
> الأعزل فقط ولا تدهس منطقةً مكتوبة في النداء. لو كانت تدهسها لانزاحت جلسات
> كل مؤشر محوَّل من Pine بفارق محور المستخدم عن المنطقة المكتوبة في أصله.

المناطق الجاهزة دائماً: `UTC`، نيويورك، شيكاغو، لندن، برلين، دبي، الهند،
شنغهاي، طوكيو، سيدني — إضافةً إلى منطقة المؤشر ومنطقة المحور. غيرها يحتاج
إعلانها في `timezone`. الاختصارات `'NY'`/`'LDN'`/`'TOK'`/`'SYD'` مدعومة.

**قواعد `levels`:** إمّا أرقام `[70, 30]`، أو كائنات `[{ value: 0, alpha: 0.1 }]`.

> لا تحدّد `color` صريحاً للمستويات إلا لضرورة — اللون الافتراضي يتكيّف مع
> الثيم الفاتح والداكن تلقائياً، والصريح لا يتكيّف.

---

## ٣. دالة `compute`

```javascript
function compute(candles, inputs) {
  // candles: [{ time, open, high, low, close, volume }, ...]  مرتّبة تصاعدياً
  // inputs : { period: 14, mult: 3.0, ... }  قيم المستخدم الحالية
  return [ /* رسومات */ ];
}
```

### شكل الرسم الواحد

```javascript
{
  id: 'main',
  type: 'line',        // انظر «أنواع السلاسل» أدناه
  primary: true,       // الرسم الرئيسي — يأخذ لون المستخدم وسُمكه
  data: [{ time: 1700000000, value: 42.5 }, ...]
}
```

### أنواع السلاسل

**قيمة لكل شمعة** — `data: [{ time, value }]` (فجوة = نقطة بلا `value`):

| `type` | الشكل | مقابل Pine |
|---|---|---|
| `line` | خطّ متصل | `plot()` |
| `histogram` | أعمدة (لون لكل عمود في النقطة) | `plot(style=histogram/columns)` |
| `area` | خطّ بتعبئة متدرّجة نحو القاع | `plot(style=area)` |
| `baseline` | لونان حول مرجع (`baseValue`) — أخضر فوق/أحمر تحت | `plot(style=baseline)` |
| `stepline` | خطّ يقفز بلا قطر — للمستويات الثابتة | `plot(style=stepline)` |

`baseline` يحتاج مرجعاً: `{ type: 'baseline', baseValue: 0, data: [...] }`.

**شموع OHLC** — `data: [{ time, open, high, low, close }]` (لون اختياري لكل شمعة
عبر `color`/`wickColor`/`borderColor`؛ فجوة = نقطة بـ`time` فقط):

| `type` | الشكل | مقابل Pine |
|---|---|---|
| `candle` | شموع يابانية مخصّصة (Heikin Ashi، فريم أعلى…) | `plotcandle()` |
| `bar`    | أعمدة OHLC | `plotbar()` |

**تعبئة بين حدّين (`band`)** — سحابة بين خطّين، بديل `fill()` الأنظف. تعمل على
الشارت الرئيسي وفي اللوحة السفلية معاً:

```javascript
{ id: 'cloud', type: 'band', color: 'rgba(38,166,154,0.15)',
  data: [{ time: t, upper: 105, lower: 95 }, { time: t2 }, ...] }  // نقطة بلا upper/lower = فجوة
```

مثال سحابة Bollinger:

```javascript
const b = TA.bb(TA.src(candles), 20, 2);   // { basis, upper, lower, offset }
return [
  { id: 'basis', type: 'line', primary: true, data: TA.pt(candles, b.basis, b.offset) },
  { id: 'band',  type: 'band', color: 'rgba(90,200,250,0.12)',
    data: candles.map((c, i) => { const k = i - b.offset;
      return k >= 0 ? { time: c.time, upper: b.upper[k], lower: b.lower[k] } : { time: c.time }; }) },
];
```

**خلفية الشمعة (`bgcolor`)** — عمود ملوّن كامل الارتفاع خلف الشمعة، بديل
`bgcolor()` في Pine. التفصيل والقواعد في القسم ٣.٥:

```javascript
{ id: 'regime', type: 'bgcolor',
  data: [{ time: t, color: 'rgba(38,166,154,0.08)' }, ...] }   // شمعة بلا لون: لا تُدرجها
```

**رسم ثانوي بنمط ثابت** (لا يتأثر بإعدادات المستخدم):

```javascript
{
  id: 'signal', type: 'line',
  style: { color: '#FF9800', lineWidth: 1, lineStyle: 0, title: '' },
  data: [...]
}
```

**تلوين كل عمود على حدة** (للهيستوغرام) — اللون داخل نقطة البيانات:

```javascript
{ id: 'hist', type: 'histogram',
  data: [{ time: t, value: v, color: v >= 0 ? '#26a69a' : '#ef5350' }, ...] }
```

**فجوات وخطوط قُطرية:** نقطة بلا `value` = فجوة. الخط يصل بين النقاط ذات القيم
متجاوزاً الفجوات — بهذا تُرسم أنماط zigzag والقمم/القيعان.

```javascript
data.push({ time: t });              // فجوة
data.push({ time: t, value: 100 });  // نقطة
```

---

## ٣.١ الأشكال — صناديق وخطوط ونصوص

نموذج «قيمة لكل شمعة» لا يستطيع رسم مستطيل يمتد من شمعة ٥٠ إلى شمعة ٩٠، ولا كتابة
نصّ عند سعر معيّن. لذلك يوجد نوع مخرجات ثالث:

```javascript
{ id: 'zones', type: 'shapes', shapes: [ /* … */ ] }
```

الإحداثيات بـ **(وقت يونكس بالثواني، سعر)** — نفس `time` الموجود في الشموع.

> **`xloc: 'bar_index'` — الإحداثي برقم الشمعة** (مقابل `xloc.bar_index` في Pine)
>
> أضِف `xloc: 'bar_index'` إلى الشكل فيصير كل إحداثي أفقي فيه **رقم شمعة** لا وقتاً:
>
> ```javascript
> { kind: 'line', xloc: 'bar_index', x1: i, x2: i + 20, y1: p1, y2: p2 }
> ```
>
> يسري على `box` و`line` و`label` و`circle` و`fill` (حقل `t`) و`linefill`.
> الأرقام خارج المدى تُسقَط بخطوة الفريم (`n + 5` = خمس شمعات بعد الأخيرة، والسالب
> قبل الأولى) — لكن الأوقات المستقبلية تبقى خارج المقياس الزمني كما هي موضّح في
> ملاحظة الإسقاط أدناه. بلا `xloc` يبقى `x` وقتاً حرفياً، فلا يتغيّر أي مؤشر قائم.

### `box` — مستطيل

```javascript
{ kind: 'box',
  x1: startTime, y1: topPrice, x2: endTime, y2: bottomPrice,
  bgColor: 'rgba(41,98,255,0.3)',   // التعبئة
  borderColor: '#2962FF',
  borderWidth: 1,
  style: 'solid',                    // 'solid' | 'dotted' | 'dashed'
  text: 'Asia',                      // نصّ في وسط الصندوق (اختياري)
  textColor: '#2962FF',
  font: 'mono' }                     // 'sans' (افتراضي) | 'mono' | 'serif'
```

### `line` — خط بين نقطتين

```javascript
{ kind: 'line',
  x1: t1, y1: p1, x2: t2, y2: p2,
  color: '#26a69a',
  width: 1,
  style: 'dotted',
  extend: 'right' }                  // 'none' | 'left' | 'right' | 'both'
```

الخط القُطري يُرسم بجعل `y1 ≠ y2` — بهذا تُرسم خطوط الاتجاه وربط القمم بالقيعان.

> **الإسقاط المستقبلي:** `extend: 'right'` يمدّ الخطّ إلى حافة اللوحة **محافظاً على
> ميله** (لخطوط الاتجاه والتنبؤ). عرّف الخطّ بنقطتين حقيقيتين ضمن البيانات ثم
> مدّده — لا تضع طرفاً عند وقت مستقبلي (بعد آخر شمعة) لأن الأوقات المستقبلية خارج
> المقياس الزمني فتُقصّ إلى الحافة بلا ميل. للإسقاط عند نقطة مستقبلية محدّدة، يجب
> أن تشغل تلك الأوقات سلسلة (شموع/خطّ تنبؤ) حتى تدخل المحور.

### `label` — نصّ عند نقطة

```javascript
{ kind: 'label',
  x: time, y: price,
  text: 'NYAM.H',
  textColor: '#089981',
  bgColor: 'rgba(0,0,0,0.6)',        // خلفية للنصّ (اختياري)
  size: 11,                          // 7 – 28
  position: 'above',                 // 'above' | 'below' | 'middle'
  align: 'left',                     // 'left' | 'center' | 'right'
  font: 'mono',                      // 'sans' (افتراضي) | 'mono' | 'serif'
  bold: true }
```

#### أنماط التسمية — `style` (مقابل `label.style_*`)

بلا `style` (أو `style: 'none'`) يبقى السلوك أعلاه: نصّ حرّ عند النقطة. ومع نمط
`label_*` تُرسم **بطاقة بمؤشّر مثلّث يشير إلى النقطة** — وهي تسمية Pine المعتادة:

```javascript
{ kind: 'label',
  x: time, y: price,
  text: 'CHoCH',
  style: 'label_right',              // البطاقة يسار النقطة والمؤشّر يشير يميناً
  bgColor: '#2962FF',                // لون البطاقة (افتراضي أزرق)
  textColor: '#ffffff',
  borderColor: '#ffffff' }           // إطار اختياري
```

| `style` | موضع البطاقة | مقابل Pine |
|---|---|---|
| `label_right` | يسار النقطة | `label.style_label_right` |
| `label_left` | يمينها | `label.style_label_left` |
| `label_up` | تحتها | `label.style_label_up` |
| `label_down` | فوقها | `label.style_label_down` |
| `label_center` | عليها تماماً (بلا مؤشّر) | `label.style_label_center` |
| `label_upper_left` / `label_upper_right` | قطرياً أعلى | نفس الأسماء |
| `label_lower_left` / `label_lower_right` | قطرياً أسفل | نفس الأسماء |

داخل البطاقة `align` يوسّط النصّ افتراضاً، و`position` (above/below) لا أثر له —
النمط هو من يحدّد الموضع. نمطٌ غير معروف يسقط إلى `'none'` بدل أن يُرفض الشكل.

### `polyline` — مسار حرّ ومضلّع (بديل `polyline.new`)

`box` محاذٍ للمحورين و`fill` يحتاج حدّين على نفس الوقت — فلا يرسم أيّهما مثلّثاً
ولا رباعيّاً مائلاً. هذا الشكل مسارٌ واحد عبر N نقاط، يُملأ أو يُحدّ أو الاثنان،
وعليه تُبنى البروفايلات «ثلاثية الأبعاد» والمثلّثات ومسارات الزيجزاج المصمتة.

```javascript
{ kind: 'polyline',
  points: [ { x: t1, y: p1 }, { x: t2, y: p2 }, { x: t3, y: p3 } ],
  color: '#2962FF',                  // لون الحدّ ('width: 0' = بلا حدّ)
  width: 1,
  style: 'solid',                    // 'solid' | 'dotted' | 'dashed'
  fillColor: 'rgba(41,98,255,0.25)', // اختياري — بدونه مسار بلا تعبئة
  closed: true,                      // يُغلق الضلع الأخير (لازم للمضلّع)
  curved: false }                    // تنعيم تربيعي (مقابل curved=true)
```

- **الحدّ ٢٠٠٠ نقطة** للمضلّع الواحد؛ والمسار نداءُ رسمٍ واحد مهما طال، فمضلّع
  من ٥٠٠ نقطة أرخص من ٥٠٠ صندوق.
- نقطة إحداثيها خارج مدى البيانات **تُتخطّى** ولا تقطع المسار — القطع كان
  سيفتح المضلّع فتسيل تعبئته.
- `xloc: 'bar_index'` يسري على `x` في كل النقاط.
- مضلّع بنقطة واحدة صالحة يُسقَط (لا مسار من نقطة).

### `circle` — نقطة دائرية

```javascript
{ kind: 'circle',
  x: time, y: price,
  radius: 4,                         // 1 – 30 بكسل
  color: '#26a69a',                  // التعبئة
  borderColor: '#ffffff',            // اختياري
  borderWidth: 1 }
```

### `fill` — تعبئة بين حدّين (سحابة)

بديل `fill()` في PineScript. شكل واحد يحمل سلسلة نقاط، كل نقطة تحدّد الحدّ
العلوي والسفلي عند وقت معيّن.

```javascript
{ kind: 'fill',
  color: 'rgba(90,200,250,0.12)',
  points: [
    { t: time1, top: 105, bottom: 95 },
    { t: time2 },                     // نقطة بلا top/bottom = فجوة تقطع التعبئة
    { t: time3, top: 108, bottom: 97 },
  ] }
```

الفجوة تُنهي المقطع الحالي وتبدأ آخر — استخدمها أثناء فترة الإحماء وإلا امتدّت
التعبئة عبر الفراغ. الحدّ الأقصى **٦٠٬٠٠٠ نقطة** لكل تعبئة.

### `linefill` — تعبئة بين خطّين مائلين (بديل `linefill.new`)

`fill` تحتاج سلسلة نقاط بمحاذاة الشموع، وهي الأنسب للسحب والأشرطة. أمّا التعبئة
بين **خطّين اعتباطيّين** — قناة، مروحة، مثلّث — فهذه:

```javascript
{ kind: 'linefill',
  color: 'rgba(41,98,255,0.15)',
  extend: 'right',                   // يسري على الخطّين معاً
  line1: { x1: t1, y1: p1, x2: t2, y2: p2 },
  line2: { x1: t1, y1: p3, x2: t2, y2: p4 } }
```

- `a`/`b` مرادفان لـ `line1`/`line2`.
- لكل خطّ أن يحمل `extend` خاصّاً به، وإلا ورث تمديد الشكل.
- الخطّان **لا يُرسمان** — أضِف شكلَي `line` إن أردت حدوداً مرئية.
- `xloc: 'bar_index'` يسري على الأربعة إحداثيات.
- خطّ ناقص طرفاً يُسقط التعبئة كلّها (لا نصف مضلّع).

### `panel` — لوحة إحصائيات مثبّتة (بديل `table.new`)

الشكل الوحيد هنا الذي **لا** يرتبط بوقت ولا بسعر: موضعه بالبكسل من حافة
الشارت، فلا ينزاح مع التمرير أو التكبير.

```javascript
{ kind: 'panel',
  position: 'top_right',             // top/middle/bottom × left/center/right
  bgColor: 'rgba(19,23,34,0.85)',
  borderColor: '#2a2e39',
  borderWidth: 1,
  textColor: '#d1d4dc',              // لون النصّ الافتراضي لكل الخلايا
  size: 11,                          // حجم الخطّ الافتراضي (7 – 28)
  width: 25,                         // اختياري: ٪ من عرض الشارت لكل اللوحة
  height: 12,                        // اختياري: ٪ من ارتفاعه
  rows: [
    // خليّة نصّية مباشرة، أو كائن بخصائصها
    ['الاتجاه', { text: 'صاعد', align: 'right', textColor: '#26a69a' }],
    [{ text: 'RSI', bold: true }, { text: '62.4', align: 'right' }],
  ] }
```

خصائص الخليّة: `text`، `textColor`، `bgColor`، `align`، `size`، `bold`، `font`،
و`width`/`height` كنسبة مئوية من الشارت (بديل `table.cell(width=, height=)`).
بلا نسبة يُقاس العمود من أعرض نصّ فيه. `font` على اللوحة يسري على كل خلاياها،
وعلى الخليّة يتقدّم عليه — و`'mono'` هو ما يجعل أعمدة الأرقام تصطفّ.

> **قواعد اللوحة:**
> - **٤ لوحات** لكل مؤشر كحدّ أقصى، **٢٤ صفاً × ٨ أعمدة**، و**٦٤ حرفاً** للخليّة.
>   تُحتسب من سقف الـ ١٥٠٠ شكل بعدد خلاياها لا كشكل واحد.
> - لوحات عدّة مؤشرات في **نفس الموضع تتكدّس تلقائياً** ولا تتراكب؛ وترتيبها
>   ثابت لا يتبدّل بين إطار وآخر. لوحات الأسفل تتكدّس صعوداً.
> - تُرسم فوق كل شيء دائماً، ولا تؤثّر في مقياس السعر إطلاقاً.
> - نصّ أعرض من خليّته يُقصّ عند حدّها ولا يزحف على جارتها.

> **قيود الأشكال:**
> - تعمل على الشارت الرئيسي (`overlay: true`) **وفي اللوحة السفلية**
>   (`overlay: false`) معاً — الإحداثيات بالسعر، فمؤشر أشكال بحت في لوحة مستقلّة
>   يضبط قيم `y` ضمن نطاقه الخاص.
> - الحدّ الأقصى **١٥٠٠ شكل**. احترم بارامتراً مثل `maxDays` بدل رسم كل التاريخ.
> - الأشكال غير تفاعلية وتُحذف تلقائياً مع المؤشر.

### الرسم في لوحة فرعية مستقلّة (صفوف مكدّسة) — اقرأه قبل تحويل أي مؤشر «لوحة»

مؤشرات كثيرة (ICT Quarterly، خرائط الجلسات، مقاييس أسفل الشارت) تُرسم في
**لوحة منفصلة** بصفوف ملوّنة لا على السعر. لتحويلها صحيحاً:

1. **`overlay: false`** — هذا وحده يوجّه المؤشر إلى اللوحة السفلية. `overlay: true`
   يرسم على الشموع دائماً مهما فعلت.
2. **إحداثي `y` = رقم صفّ ثابت، لا سعر.** أعطِ كل دورة/صفّاً رقماً: الأول `[0,1]`،
   الثاني `[1,2]`… والمحور يتكيّف تلقائياً على عدد الصفوف. **لا تستخدم `high`/`low`
   (السعر) في اللوحة الفرعية** — سيمطّ المقياس (مثلاً 0..1860) ويصبح بلا معنى.
3. `box` و`label` و`band` و`bgcolor` و`markers` كلها تعمل في اللوحة الفرعية.
   العلامات هناك تُبنى أشكالاً وتُنسَب إلى **قيمة الرسم الرئيسي** عند تلك
   الشمعة لا إلى الشمعة (لا شموع في اللوحة)، فـ`aboveBar` تعني «فوق الخطّ».
   ولذلك: علامة عند وقتٍ لا قيمة للرسم الرئيسي فيه تُسقَط — إلا `atPrice*`
   التي تحمل سعرها الصريح.

> **قيد معماري حاسم: المؤشر الواحد = لوحة واحدة.** إن كان المصدر يرسم بعض العناصر
> **على السعر** وبعضها **في لوحة منفصلة معاً** (مثل مفتاح `Display on chart` لكل
> دورة)، فهذا **مستحيل في مؤشر واحد** عندنا. اختر أحد الوضعين (غالباً اللوحة
> بالصفوف)، **وأسقِط مفتاح الازدواج** بدل تركه خياراً ميتاً، واذكر ذلك في تعليق.

```javascript
// صفّ لكل دورة مُفعّلة — لا سعر
let rows = 0; const R = {};
if (inputs.showDaily)  R.daily  = ++rows;
if (inputs.showNinety) R.ninety = ++rows;
if (inputs.showMicro)  R.micro  = ++rows;

// صندوق الربع في صفّه، ملوّن حسب الربع:
shapes.push({ kind: 'box', x1: t1, x2: t2, y1: R.daily, y2: R.daily - 1,
  bgColor: 'rgba(139,188,252,0.35)', borderColor: '#8bbcfc' });
shapes.push({ kind: 'label', x: t1, y: R.daily - 0.5, text: 'Q3',
  textColor: '#8bbcfc', size: 9, position: 'middle' });
```

---

## ٣.٢ العلامات — بديل `plotshape`

الأسهم والمثلثات فوق الشموع وتحتها، لإشارات الدخول والخروج:

```javascript
{ id: 'signals', type: 'markers', markers: [
    { time: t,
      position: 'belowBar',        // 'aboveBar' | 'belowBar' | 'inBar'
      shape: 'arrowUp',            // 'arrowUp' | 'arrowDown' | 'circle' | 'square'
      color: '#26a69a',
      text: 'BUY',                 // اختياري، ≤24 حرفاً
      size: 1 },                   // 0.1 – 5
]}
```

للتموضع عند سعر محدّد بدل ربطه بالشمعة، استخدم `atPriceTop` أو `atPriceBottom`
أو `atPriceMiddle` — وهذه **تشترط** حقل `price`:

```javascript
{ time: t, position: 'atPriceMiddle', shape: 'circle', color: '#fff', price: 65400 }
```

> الحدّ الأقصى **٢٠٠٠ علامة**، ولا حاجة لترتيبها زمنياً — يتم تلقائياً.
>
> تعمل في الشارت الرئيسي وفي اللوحة السفلية معاً. الفرق أن الشارت الرئيسي
> يضعها فوق/تحت **الشمعة** (إضافة المكتبة نفسها)، واللوحة السفلية فوق/تحت
> **قيمة الرسم الرئيسي** — انظر القاعدة ٣ في القسم السابق.

جدول تحويل أشكال PineScript:

| PineScript | هنا |
|---|---|
| `shape.triangleup` / `shape.arrowup` | `shape: 'arrowUp'` |
| `shape.triangledown` / `shape.arrowdown` | `shape: 'arrowDown'` |
| `shape.circle` | `shape: 'circle'` |
| `shape.square` / `shape.diamond` / `shape.flag` | `shape: 'square'` |
| `location.abovebar` / `location.belowbar` | `position: 'aboveBar'` / `'belowBar'` |
| `location.absolute` | `position: 'atPriceMiddle'` + `price` |

يمكن الجمع بين الأشكال والسلاسل في نفس المؤشر:

```javascript
return [
  { id: 'ma',    type: 'line',   primary: true, data: TA.pt(candles, ma, 19) },
  { id: 'zones', type: 'shapes', shapes: boxes },
];
```

---

## ٣.٣ الرمز والفريم — `syminfo` و `timeframe`

متغيّران عامّان داخل `compute` (لا يُمرّران كوسيط، تماماً كما في PineScript):

```javascript
syminfo.ticker          // 'BTCUSDT'
syminfo.tickerid        // مثله

timeframe.period        // 'M15' — بترميز المنصّة
timeframe.pine          // '15'  — مقابله في Pine، لنقل الكود حرفياً
timeframe.in_seconds    // 900
timeframe.multiplier    // 15
timeframe.isintraday    // true
timeframe.isseconds / isminutes / isdaily / isweekly / ismonthly
```

مقابلة `timeframe.pine`: `M15 → '15'`، `H4 → '240'`، `D1 → 'D'`، `W1 → 'W'`،
`MN1 → 'M'` — فالشرط `timeframe.pine == '240'` المنقول عن Pine يعمل كما هو.

> **يتغيّران تلقائياً** عند تبديل الرمز أو الفريم، ويُعاد حساب المؤشر عندها.
>
> **قد يعودان فارغين** في مسار التحقّق قبل تحميل رمز (كما في اختبار المحرّر على
> الشموع الاصطناعية) — لا تفترض وجود قيمة: `syminfo.ticker || '—'`.

---

## ٣.٤ بيانات رمز آخر أو فريم آخر — `request.security`

```javascript
const htf = request.security('', 'H4');        // نفس الرمز، فريم أربع ساعات
const btc = request.security('BTCUSDT', 'D1'); // رمز آخر
const h4  = request.security('H4');            // اختصار: وسيط واحد = فريم
```

تُرجع **مصفوفة شموع** `[{ time, open, high, low, close, volume }]` تصاعدياً —
ثم احسب عليها بمكتبة `TA` كأي شموع، وأسقِط الناتج على الفريم الحالي بـ
`request.map`:

```javascript
function compute(candles, inputs) {
  const d1 = request.security('', 'D1');
  if (!d1.length) return [{ id: 'ema', type: 'line', data: TA.plot(candles, candles.map(() => NaN)) }];

  const ema = TA.ema(TA.src(d1), 20);          // أقصر من d1 بـ19
  const full = TA.align(d1, ema, 19);          // ← بطول d1
  const onChart = request.map(candles, d1, full);   // ← بطول الشموع الحالية
  return [{ id: 'ema', type: 'line', data: TA.plot(candles, onChart) }];
}
```

| الدالة | الوصف |
|---|---|
| `request.security(sym, tf)` | شموع الرمز/الفريم المطلوب (فارغة إن لم تصل بعد) |
| `request.ready(sym, tf)` | هل وصلت؟ للتمييز عن «لا بيانات» |
| `request.map(candles, src, vals, opts)` | إسقاط سلسلة المصدر على الشموع الحالية |
| `request.step(src)` | مدّة شمعة المصدر بالثواني |

**الترميز:** الرمز الفارغ = الرمز الحالي، والفريم الفارغ = فريم الشارت. الفريم
يُقبل بترميز المنصّة (`'H4'`، `'D1'`، `'MN1'`) أو بترميز Pine (`'240'`، `'D'`،
`'3M'`)، و`'BINANCE:BTCUSDT'` يُقرأ رمزاً صحيحاً.

**الرموز المتاحة** — وما عداها لا يُجلب أبداً (كود المؤشر مشارَك، فلا يقرّر هو
ما يُطلب من الشبكة):

| السوق | الرموز |
|---|---|
| كريبتو سبوت | `BTCUSDT` `ETHUSDT` `SOLUSDT` `XRPUSDT` `BNBUSDT` `ADAUSDT` `DOGEUSDT` `SHIBUSDT` `DOTUSDT` `LTCUSDT` `LINKUSDT` |
| كريبتو عقود | نفسها بلاحقة `f` — `BTCUSDTf` … |
| مؤشرات وسلع | `US500` `US30` `US100` `WTI` `BRENT` `XAUUSD` `XAGUSD` |
| فوركس | `EURUSD` `GBPUSD` `USDJPY` `USDCAD` `USDCHF` `EURJPY` `GBPJPY` `EURAUD` `EURCAD` `EURNZD` `GBPAUD` `GBPCAD` `GBPNZD` |

> مقابلة العقود الأمريكية عندنا: **ES → `US500`**، **YM → `US30`**،
> **NQ → `US100`** — وهي ما تُستعمل في مؤشرات SMT المنقولة عن TradingView.

### مقارنة رمزين على **نفس** الفريم (SMT وما شابهه)

هنا تنقلب القاعدة الثانية: `request.map` بلا `lookahead` يُرجع آخر شمعة **مغلقة**،
وعلى نفس الفريم تلك هي الشمعة **السابقة** — فتنزاح المقارنة شمعةً كاملة. مقارنة
رمزين متزامنين تحتاج `{ lookahead: true }`، وهذا ليس استشرافاً: الشمعتان تُغلقان
في اللحظة نفسها.

```javascript
const meta = {
  name: 'SMT', label: 'SMT Divergence', overlay: true,
  inputs: [
    // نوع `symbol` يفتح قائمة رموز المنصّة — لا تكتب قائمة أزواج بيدك
    { id: 'partner', type: 'symbol', label: 'الرمز المقارَن', def: 'US30' },
    { id: 'left',  type: 'int', label: 'يسار',  def: 3, min: 1, max: 20 },
    { id: 'right', type: 'int', label: 'يمين',  def: 3, min: 1, max: 20 },
  ],
};

function compute(candles, inputs) {
  const other = request.security(inputs.partner, '');     // نفس الفريم
  const shapes = [];
  if (other.length) {                                     // ← أول تشغيلة تعود []
    const oHigh = request.map(candles, other, other.map(c => c.high), { lookahead: true });
    const ph = TA.pivothigh(TA.src(candles, 'high'), inputs.left, inputs.right);
    let prev = -1;
    for (let i = 0; i < candles.length; i++) {
      if (!isFinite(ph[i])) continue;
      if (prev >= 0 && isFinite(oHigh[i]) && isFinite(oHigh[prev])) {
        const mine = ph[i] > ph[prev], theirs = oHigh[i] > oHigh[prev];
        // قمّة أعلى هنا وقمّة أدنى هناك (أو العكس) = دايفرجنس
        if (mine !== theirs) shapes.push({
          kind: 'label', x: candles[i].time, y: ph[i], text: 'SMT',
          style: 'label_down', bgColor: mine ? '#ef5350' : '#26a69a',
        });
      }
      prev = i;
    }
  }
  return [{ id: 'smt', type: 'shapes', shapes }];
}
```

> ### القاعدتان اللتان لا تُخالَفان
>
> **١. أول تشغيلة تعود فارغة — دائماً.** العزل لا يملك شبكة ولا انتظاراً:
> `request.security` تُسجّل الطلب وتعود بمصفوفة فارغة، فيجلبها المضيف في
> الخلفية ثم **يعيد حساب المؤشر** فتصل. اكتب الكود ليحتمل `[]` (كما في المثال
> أعلاه) وإلا وميضَ خطأً عند كل تفعيل وتبديل رمز.
>
> **٢. `request.map` بلا `lookahead` لا يعيد الرسم.** الافتراض أن قيمة الشمعة
> الحالية هي قيمة آخر شمعة **مغلقة** من المصدر — أي ما كان معلوماً فعلاً في
> حينه. `{ lookahead: true }` يُظهر الشمعة الجارية، فيبدو التاريخ أدقّ ممّا كان
> ممكناً: صالح للعرض، لا لإشارة دخول.

**الحدود:** أربع سلاسل لكل مؤشر (الخامسة تعود فارغة أبداً)، وألف شمعة لكل سلسلة،
وتُحدَّث كل دقيقة. السلاسل من سوق آخر تُزاح تلقائياً إلى اصطلاح توقيت الشارت
(مغذّي MT5 يسبق UTC بثلاث ساعات) فتقع على شموعها الصحيحة. وفي **جلسة الباك
تيست** تُقصّ السلسلة عند ساعة الإعادة فلا يرى المؤشر مستقبلاً لم يكن معلوماً.

> **في المحرّر** ينتظر زرّ التشغيل وصول البيانات مرّة واحدة ليريك نتيجة مكتملة؛
> فإن لم تصل ظهر سطر في لوحة التصحيح يسمّي ما نقص. وبوّابة النشر تحكم على الكود
> بشموع اصطناعية قديمة التواريخ — فقد يخرج الإسقاط كلّه `NaN` هناك؛ أرجِع سلسلة
> ولو فارغة القيم كي تمرّ.

---

## ٣.٥ تلوين خلفية الشمعة — بديل `bgcolor`

عمودٌ ملوّن كامل الارتفاع خلف الشمعة. هو ما تحتاجه مؤشرات «الاتجاه» و«نظام
السوق»: أخضر حين يكون النظام صاعداً، أحمر حين يكون هابطاً، بلا لون في الحياد.

```javascript
{ id: 'regime', type: 'bgcolor', data: [
    { time: t, color: 'rgba(38,166,154,0.08)' },
    // الشمعة التي لا تُلوَّن: لا تُدرجها أصلاً — لا نقطة بلا لون
] }
```

مثال كامل داخل `compute`:

```javascript
const ema = TA.align(candles, TA.ema(TA.src(candles, 'close'), inputs.len), inputs.len - 1);
const bg = [];
for (let i = 0; i < candles.length; i++) {
  if (!isFinite(ema[i])) continue;                       // فترة الإحماء بلا لون
  bg.push({ time: candles[i].time,
            color: candles[i].close > ema[i] ? 'rgba(38,166,154,0.10)'
                                             : 'rgba(239,83,80,0.10)' });
}
return [
  { id: 'ema', type: 'line', primary: true, data: TA.pt(candles, ema) },
  { id: 'bg',  type: 'bgcolor', data: bg },
];
```

> **قواعد الخلفية:**
> - تُرسم **تحت كل شيء** — تحت أشكال المؤشر نفسه وتحت الشموع.
> - **لا تؤثّر في مقياس السعر إطلاقاً**: لا سعر لها أصلاً، تمتدّ من أعلى
>   اللوحة إلى أسفلها.
> - الشمعات المتجاورة ذات اللون الواحد **تُدمج تلقائياً** في عمود واحد، فلا
>   تقلق من تلوين التاريخ كلّه: ٣٠٠٠ شمعة بلونين تصير عشرات الأعمدة لا
>   ٣٠٠٠ شكل. (ولا تُحتسب من سقف الـ ١٥٠٠ شكل — هي ليست أشكالاً.)
> - استعمل ألواناً **شفّافة جداً** (٠٫٠٥–٠٫١٥). اللون المصمت يبتلع الشموع.
> - تعمل في الشارت الرئيسي وفي اللوحة السفلية معاً.

---

## ٣.٦ مصدر السعر — `input.source`

مدخل يختار به المستخدم ما يتغذّى عليه المؤشر. الفرق عن `select`: القيمة تصل
`compute` **مصفوفة قيم جاهزة** بطول الشموع، تماماً كما في PineScript — لا نصّاً
تترجمه بنفسك.

```javascript
var meta = {
  name: 'MYRSI', label: 'RSI بمصدر', overlay: false, color: '#5ac8fa',
  inputs: [
    { id: 'len', type: 'int', label: 'الطول', def: 14, min: 2, max: 200 },
    { id: 'src', type: 'source', label: 'المصدر', def: 'close' },
  ],
};

function compute(candles, inputs) {
  // inputs.src مصفوفة أرقام بطول candles — لا 'close' ولا 'hlc3'
  const r = TA.rsi(inputs.src, inputs.len);
  return [{ id: 'main', type: 'line', primary: true,
            data: TA.pt(candles, TA.align(candles, r, inputs.len)) }];
}
```

القائمة التي يراها المستخدم:

| المجموعة | الخيارات |
|---|---|
| أسعار الشمعة | `close` `open` `high` `low` `hl2` `hlc3` `ohlc4` `hlcc4` |
| **نواتج المؤشرات النشطة** | كل رسم من كل مؤشر آخر مُفعَّل على الشارت الآن |

المجموعة الثانية هي **تركيب المؤشرات**: RSI على متوسّط متحرّك، متوسّط على CVD،
Bollinger على ناتج مؤشرك المخصّص. لا تكتب لها شيئاً — يكفي أن تعلن مدخل
`source` واحداً، والباقي اختيار المستخدم من لوحة الإعدادات.

> **قواعد المصدر:**
> - `TA.src(candles, 'hl2')` يبقى موجوداً لمن يريد مصدراً ثابتاً في الكود بلا
>   مدخل. المدخل هو ما يجعله **اختيار المستخدم**.
> - **اكتب الكود ليحتمل `NaN`.** ناتج مؤشر آخر يبدأ بفترة إحماء، والمؤشر
>   المُغذّي قد يُوقَف فتصل السلسلة كلّها `NaN`. لا ترمِ خطأً — أرجِع سلسلة
>   ولو فارغة القيم.
> - **تأخّر دورة رسم واحدة.** المصدر هو آخر ما رُسم فعلاً للمؤشر المُغذّي، لا
>   إعادة حساب له. أثره محصور في آخر شمعة أثناء التيك الحيّ، والدورتان
>   تتقاربان فوراً. (هذا ما يمنع التكرار الدائري: أ يقرأ ب يقرأ أ.)
> - **تبديل الرمز أو الفريم آمن**: المحاذاة بالوقت لا بالفهرس، فبيانات السوق
>   القديم لا تطابق أوقات الشموع الجديدة فتخرج فجوةً لا قيمةً كاذبة.
> - المؤشرات المدمجة (SMA وRSI وما إليها) تبقى على مصدرها النصّي القديم —
>   تركيب المؤشرات ميزةُ المؤشرات المخصّصة.

---

## ٤. مكتبة `TA`

كل الدوال متاحة عالمياً بلا استيراد.

### تحويل

| الدالة | الوصف |
|---|---|
| `TA.src(candles, 'close')` | استخراج مصفوفة أسعار (`open`/`high`/`low`/`close`/`volume`) |
| `TA.pt(candles, values, offset)` | **مهمّة** — تربط مصفوفة قيم بأوقات الشموع |
| `TA.hl2(c)` `TA.hlc3(c)` `TA.ohlc4(c)` | متوسطات السعر |

**`TA.pt` و`offset`:** الدوال ذات النافذة تُرجع مصفوفة أقصر من الشموع.
`offset` هو فهرس الشمعة المقابلة لأول قيمة.

```javascript
const closes = TA.src(candles);
const ma = TA.sma(closes, 20);        // الطول = candles.length - 19
TA.pt(candles, ma, 19);               // ← 19 = 20 - 1
```

قاعدة الإزاحة: `sma/ema/stdev/highest/lowest` ← `n - 1` · `rma/rsi` ← `n` · `tr` ← `1`

### متوسطات ومقاييس

| الدالة | ملاحظة |
|---|---|
| `TA.sma(values, n)` | الطول: `len - n + 1` |
| `TA.ema(values, n)` | الطول: `len - n + 1` |
| `TA.rma(values, n)` | متوسط Wilder — الطول: `len - n + 1` |
| `TA.stdev(values, n)` | انحراف معياري (منحاز) |
| `TA.highest(values, n)` / `TA.lowest(values, n)` | القمة/القاع خلال `n` |
| `TA.change(values)` | الفرق عن السابق — نفس الطول، أول عنصر `0` |
| `TA.tr(candles)` | المدى الحقيقي — الطول: `len - 1` (بديل `ta.tr`) |
| `TA.tr(candles, true)` | كامل الطول، الشمعة ٠ = `high - low` (بديل `ta.tr(true)`) |
| `TA.rsi(values, n)` | جاهز — الطول: `len - n` |

### المكتبة الموسّعة

اصطلاحان لا ثالث لهما:

- **دوال النافذة** تُرجع مصفوفة أقصر بإزاحة معروفة (مثل `sma`) — استخدمها مع
  `TA.pt(candles, out, offset)` أو `TA.align`.
- **مساعدات الإشارات** (`crossover`, `rising`, `barssince`, `pivot*`, `valuewhen`)
  تعمل على مصفوفات **بطول الشموع نفسه** — ارفع أي مصفوفة قصيرة إليها بـ `TA.align`.

**متوسطات:**

| الدالة | الإزاحة |
|---|---|
| `TA.wma(v, n)` | `n - 1` — متوسط مرجّح خطّياً |
| `TA.hma(v, n)` | `(n-1) + (⌊√n⌋-1)` — Hull |
| `TA.vwma(candles, n)` | `n - 1` — مرجّح بالحجم |
| `TA.swma(v)` | `3` — أوزان `[1,2,2,1]/6` |
| `TA.linreg(v, n)` | `n - 1` — قيمة انحدار خطّي |

**مقاييس ونطاقات:**

| الدالة | الإزاحة / الملاحظة |
|---|---|
| `TA.atr(candles, n)` | **`n - 1`** — مطابِقة لـ`ta.atr`: `TA.rma(TA.tr(c, true), n)` |
| `TA.sum(v, n)` | `n - 1` — مجموع متحرّك |
| `TA.cum(v)` | كامل الطول — مجموع تراكمي |
| `TA.roc(v, n)` / `TA.mom(v, n)` | `n` — تغيّر نسبي / مطلق |
| `TA.dev(v, n)` | `n - 1` — انحراف مطلق متوسط |
| `TA.variance(v, n)` | `n - 1` |
| `TA.percentrank(v, n)` | `n` |
| `TA.correlation(a, b, n)` | `n - 1` — `a,b` بطول واحد |

**مذبذبات:**

| الدالة | الإزاحة |
|---|---|
| `TA.cci(candles, n)` | `n - 1` |
| `TA.wpr(candles, n)` | `n - 1` — Williams %R |
| `TA.stoch(candles, n)` | `n - 1` — %K الخام (نعّمه بـ `sma` لـ %D) |
| `TA.cmo(v, n)` | `n` — Chande Momentum |
| `TA.mfi(candles, n)` | `n` — Money Flow Index |

**حزم — تُرجع كائناً فيه `offset` مشترك لكل مصفوفاته:**

```javascript
const m = TA.macd(close, 12, 26, 9);   // { macd, signal, hist, offset } — الإزاحة slow-1
TA.pt(candles, m.hist, m.offset);      // ارسمها بالإزاحة المشتركة
const band = TA.bb(close, 20, 2);      // { basis, upper, lower, offset }
TA.dc(candles, 20);                    // Donchian { upper, lower, basis, offset }
TA.kc(candles, 20, 2);                 // Keltner  { basis, upper, lower, offset }
TA.vwap(candles);                      // كامل الطول — يُصفَّر كل يوم NY
```

> الإزاحة المشتركة هي إزاحة **أبكر** مصفوفة في الحزمة، والمصفوفات التي تبدأ
> بعدها تحمل `NaN` في مقدّمتها — تماماً كما تكون `na` في Pine. في `TA.macd`
> إزاحة الجميع `slow - 1`، وتظلّ `signal` و`hist` بـ`NaN` حتى `sig - 1` شمعة
> بعدها. لا تقصّ المقدّمة بيدك: `TA.pt` و`TA.plot` يحوّلان `NaN` فجوةً.

**مساعدات الإشارات (كامل الطول):**

| الدالة | الوصف |
|---|---|
| `TA.align(candles, short, offset)` | مصفوفة قصيرة ← بطول الشموع (`NaN` في الإحماء) |
| `TA.plot(candles, full)` | مصفوفة كاملة ← نقاط رسم (فجوة عند `NaN`) |
| `TA.crossover(a, b)` / `TA.crossunder(a, b)` / `TA.cross(a, b)` | تقاطعات ← مصفوفة منطقية |
| `TA.rising(v, n)` / `TA.falling(v, n)` | صعود/هبوط `n` شمعة متتالية |
| `TA.barssince(cond)` | عدد الشموع منذ آخر `true` |
| `TA.valuewhen(cond, src, occ)` | قيمة `src` عند آخر تحقّق (`occ`= رقم الحدوث) |
| `TA.pivothigh(v, left, right)` / `TA.pivotlow(...)` | قمم/قيعان محورية — قيمة عند المحور، `NaN` عداه |
| `TA.nz(x, r)` / `TA.na(x)` | بديل `na`: استبدال / فحص |

> **النمط الموصى به مع التقاطعات:** ارفع المتوسطين لكامل الطول ثم قاطِع:
> ```javascript
> const f = TA.align(candles, TA.ema(close, 12), 11);
> const s = TA.align(candles, TA.ema(close, 26), 25);
> const buy = TA.crossover(f, s);          // مصفوفة منطقية بطول الشموع
> ```

### الوقت والجلسات

`Intl` **غير موجود** في بيئة التنفيذ، فلا تحاول استخدام `toLocaleString` أو
`Intl.DateTimeFormat` — استخدم هاتين بدلاً منهما. التوقيت الصيفي الأمريكي محسوب فيهما.

| الدالة | الوصف |
|---|---|
| `TA.tz(unixSeconds, zone)` | تفكيك الوقت لمنطقة زمنية |
| `TA.inSession(unixSeconds, 'HHMM-HHMM', zone)` | هل الوقت داخل جلسة؟ نفس صيغة Pine كاملةً |

نصّ الجلسة يقبل **صيغة Pine بحذافيرها**:

| الصيغة | المعنى |
|---|---|
| `'0930-1600'` | مدى واحد — البداية شاملة والنهاية **حصرية** |
| `'2000-0400'` | يعبر منتصف الليل |
| `'0000-0000'` | اليوم كامل |
| `'1000-1100,1400-1500'` | مدَيان أو أكثر بفواصل |
| `'0930-1600:23456'` | لاحقة أيام — **١=الأحد** … ٧=السبت (هنا الإثنين..الجمعة) |

في المدى العابر لمنتصف الليل تُنسب الجلسة إلى **يوم بدايتها**، كما في Pine:
`'2000-0400:23456'` يشمل فجر السبت (امتداد الجمعة) ويستبعد فجر الإثنين
(امتداد الأحد الممنوع). يحرس هذا `npm run test:session`.

`zone` إمّا معرّف IANA (`'Europe/London'`)، أو اختصار (`'NY'`/`'LDN'`/`'TOK'`/`'SYD'`)،
أو رقم إزاحة بالساعات (`3` = GMT+3)، أو تُترك فارغة فتؤخذ **منطقة المؤشر**
المعلَنة في `meta.timezone` أو في مدخل `type:'timezone'` (انظر «مترجم أوقات
الجلسات» أعلاه). مؤشر لم يعلن منطقته يبقى افتراضه نيويورك للتوافقية.

```javascript
const t = TA.tz(candle.time);          // { y, mo, d, h, mi, dow, key }
t.h                                     // الساعة بمنطقة المؤشر
t.dow                                   // 0 = الأحد
t.key                                   // 20240724 — مفتاح اليوم، لتجميع الجلسات

TA.inSession(candle.time, '0930-1100')  // جلسة نيويورك الصباحية
TA.inSession(candle.time, '2000-0000')  // جلسة آسيا (تعبر منتصف الليل)
```

> **تنبيه:** أيام تغيّر التوقيت الصيفي، بعض الساعات لا توجد أصلاً (تقفز 02:00 → 03:00
> في مارس). جلسة تبدأ 02:00 ستبدأ 03:00 ذلك اليوم — هذا صحيح وليس خطأ.

`Math` و`JSON` متاحان بالكامل. أي شيء آخر (`fetch`, `window`, `setTimeout`,
`Intl`, `Date` بمناطق زمنية محلية) غير موجود.

> **`console.log` يعمل للتصحيح.** رسائله (و`console.warn`/`console.error`) تظهر في
> لوحة الاختبار داخل المحرّر بعد الضغط على «اختبار» — وحدها، بلا أي أثر على الشارت،
> وتظهر حتى لو رمى الكود خطأً (الرسائل قبل الخطأ). هذا بديلنا لغياب أدوات التصحيح
> في PineScript: اطبع أي قيمة أثناء الحساب وراجعها. الحدّ ٢٠٠ رسالة.

---

## ٥. جدول التحويل من PineScript

| PineScript | Sovereign JS |
|---|---|
| `input.int(14, "الفترة")` | مدخل `type:'int'` ثم `inputs.period` |
| `input.bool` / `input.color` / `input.session` | `type: 'bool'` / `'color'` / `'session'` |
| `input.string(options=[…])` | `type: 'select'` مع `options` |
| `group=` / `inline=` في Pine | `section:` / `inline:` |
| `close` / `high` / `hlc3` | `TA.src(candles)` / `TA.src(candles,'high')` / `TA.hlc3(candles)` |
| `ta.sma(close, n)` | `TA.sma(TA.src(candles), n)` |
| `ta.rma(x, n)` | `TA.rma(x, n)` |
| `ta.atr(n)` | `TA.atr(candles, n)` |
| `ta.highest(high, n)` | `TA.highest(TA.src(candles,'high'), n)` |
| `ta.change(x)` | `TA.change(x)` |
| `ta.macd` / `ta.bb` / `ta.cci` / `ta.mfi` / `ta.wpr` | `TA.macd` / `TA.bb` / `TA.cci` / `TA.mfi` / `TA.wpr` |
| `ta.wma` / `ta.hma` / `ta.vwma` / `ta.vwap` | `TA.wma` / `TA.hma` / `TA.vwma` / `TA.vwap` |
| `ta.crossover(a, b)` | `TA.crossover(a, b)` (مصفوفتان بطول الشموع — `TA.align` أولاً) |
| `ta.barssince` / `ta.valuewhen` / `ta.pivothigh` | `TA.barssince` / `TA.valuewhen` / `TA.pivothigh` |
| `x[1]` (قيمة سابقة) | `arr[i - 1]` |
| `var float s = na` + `s := …` | متغيّر عادي في حلقة `for` |
| `time("", "0930-1100", "America/New_York")` | `TA.inSession(candle.time, '0930-1100', 'America/New_York')` |
| `input.timezone(…)` | مدخل `type:'timezone'` (أو `meta.timezone`) |
| `input.symbol(…)` | مدخل `type:'symbol'` — يفتح قائمة رموز المنصّة، والفارغ = رمز الشارت |
| `hour` / `dayofweek` (بمنطقة زمنية) | `TA.tz(candle.time).h` / `.dow` |
| `syminfo.timezone` | `'exchange'` كقيمة للمنطقة |
| `plot(x)` | رسم `{ type: 'line', data: … }` |
| `plot(x, style=histogram)` | `{ type: 'histogram', data: … }` |
| `hline(70)` | `meta.levels: [70]` |
| `box.new(l, t, r, b)` | `{ kind: 'box', x1, y1, x2, y2 }` |
| `line.new(x1, y1, x2, y2)` | `{ kind: 'line', x1, y1, x2, y2 }` |
| `label.new(x, y, txt)` | `{ kind: 'label', x, y, text }` |
| `label.style_label_right` / `_left` / `_up` … | `style: 'label_right'` / `'label_left'` / `'label_up'` … |
| `font.family_default` / `font.family_monospace` | `font: 'sans'` / `'mono'` (وأيضاً `'serif'`) |
| `linefill.new(l1, l2, color)` | `{ kind: 'linefill', line1, line2, color }` |
| `xloc.bar_index` / `xloc.bar_time` | `xloc: 'bar_index'` على الشكل / الافتراض (الوقت) |
| `request.security(sym, tf, expr)` | `request.security(sym, tf)` ثم احسب بـ`TA` وأسقِط بـ`request.map` (القسم ٣.٤) |
| `barmerge.lookahead_on` | `request.map(…, { lookahead: true })` |
| `polyline.new(points, curved, closed, fill_color)` | `{ kind: 'polyline', points, curved, closed, fillColor }` |
| `chart.point.from_index(i, price)` | `xloc: 'bar_index'` مع `x: i` |
| `chart.point.from_time(t, price)` | الافتراض — `x: t` |
| `.set_right()` / `.set_x2()` وما شابه | احسب القيمة النهائية مباشرة — لا تحديث تدريجي |
| `.delete()` / حدود `max_boxes_count` / `max_polylines_count` / `max_lines_count` | لا تُنشئ الشكل أصلاً — قصّ القائمة قبل الإرجاع (السقف ١٥٠٠ شكل) |
| `line.all` / `box.all` / `polyline.all` | لا مقابل ولا حاجة: الأشكال تُبنى من الصفر في كل حساب |
| `barstate.isfirst` / `barstate.islast` | `i === 0` / `i === candles.length - 1` داخل حلقتك |
| `barstate.isconfirmed` | `i < candles.length - 1` (الأخيرة وحدها غير مؤكّدة) |
| `var` / `varip` | متغيّر عادي قبل حلقة `for` |
| `plotshape(cond, style=shape.triangleup)` | `{ type: 'markers', markers: [...] }` (القسم ٣.٢) |
| `plot(x, style=area/stepline/baseline)` | `{ type: 'area' / 'stepline' / 'baseline' }` |
| `plotcandle(o,h,l,c)` / `plotbar(...)` | `{ type: 'candle' / 'bar', data: [{time,open,high,low,close}] }` |
| `fill(p1, p2, color)` | `{ type: 'band', data: [{time, upper, lower}] }` (يعمل في اللوحة السفلية) — أو `{ kind: 'fill' }` في shapes |
| `plot(x, style=plot.style_circles)` | `{ kind: 'circle' }` أو `markers` بـ `shape:'circle'` |
| `table.new(pos)` + `table.cell(...)` | `{ kind: 'panel', position, rows }` |
| `table.cell(width=, height=)` | `width` / `height` على الخليّة (٪ من الشارت) |
| `syminfo.ticker` / `syminfo.tickerid` | `syminfo.ticker` |
| `timeframe.period` | `timeframe.period` (ترميز المنصّة) أو `timeframe.pine` |
| `timeframe.isintraday` / `.isdaily` / `.multiplier` | نفس الأسماء |
| `bgcolor(color)` | `{ type: 'bgcolor', data: [{time, color}] }` (القسم ٣.٥) |
| `input.source(close)` | `{ id, type: 'source', def: 'close' }` — تصل `compute` **مصفوفةً** (القسم ٣.٦) |
| `input.source` من مؤشر آخر | مدعوم: يختار المستخدم ناتج أي مؤشر نشط من نفس القائمة |
| `alert()` / `alertcondition()` | **غير مدعوم** |

### فروق جوهرية

1. **لا تنفيذ لكل شمعة.** PineScript يُنفَّذ مرّة لكل شمعة وله ذاكرة تلقائية؛
   هنا تُستدعى `compute` **مرّة واحدة** بكل الشموع. اكتب حلقة `for` صريحة.

2. **الحالة يدوية.** بديل `var` في Pine هو متغيّر خارج الحلقة:

```javascript
// Pine:  var float trend = 1.0
//        trend := close > x ? 1 : -1
let trend = 1;
for (let i = 0; i < n; i++) {
  trend = closes[i] > x[i] ? 1 : -1;
}
```

3. **`na` تصبح فجوة** — لا تُرجع `NaN`، أعِد `{ time }` بلا `value`.

4. **الأشكال تُبنى مرّة واحدة نهائية.** في Pine تُنشئ `box.new` صندوقاً ثم تُحدّثه
   بـ `set_right()` على كل شمعة. هنا مرّر على الشموع أولاً لتحديد بداية الشكل
   ونهايته، ثم أنشئه مرّة واحدة بقيمه النهائية.

```javascript
// Pine:  if newSession: box.new(...)  ثم  box.set_right(time) على كل شمعة
// هنا: اجمع مدى الجلسة أولاً
const runs = [];
let cur = null;
for (const c of candles) {
  if (TA.inSession(c.time, '0930-1100')) {
    if (!cur) { cur = { t1: c.time, t2: c.time, hi: c.high, lo: c.low }; runs.push(cur); }
    else { cur.t2 = c.time; cur.hi = Math.max(cur.hi, c.high); cur.lo = Math.min(cur.lo, c.low); }
  } else cur = null;
}
// ثم أنشئ الصناديق دفعة واحدة
const boxes = runs.slice(-maxDays).map(r =>
  ({ kind: 'box', x1: r.t1, y1: r.hi, x2: r.t2, y2: r.lo, bgColor: '...' }));
```

5. **بديل `max_boxes_count` و`.delete()`** — لا تُدِر دورة حياة الأشكال. قصّ
   القائمة بـ `.slice(-n)` قبل الإرجاع، والتزم بحدّ ١٥٠٠ شكل.

---

## ٦. الحدود

| الحدّ | القيمة | عند التجاوز |
|---|---|---|
| زمن التنفيذ | ٢ ثانية | «تجاوز الكود المهلة» |
| الذاكرة | 64MB | «تجاوز حدّ الذاكرة» |
| عدد النقاط | ٢٠٠٬٠٠٠ | «تجاوز الحدّ الأقصى للنقاط» |
| عدد الأشكال | ١٬٥٠٠ | تُتجاهل الزائدة بصمت |
| عدد العلامات | ٢٬٠٠٠ | تُتجاهل الزائدة بصمت |
| نقاط التعبئة الواحدة | ٦٠٬٠٠٠ | تُقتطع |
| عدد اللوحات (`panel`) | ٤ لكل مؤشر | تُتجاهل الزائدة |
| صفوف/أعمدة اللوحة | ٢٤ × ٨ | تُقتطع |
| نصّ خليّة اللوحة | ٦٤ حرفاً | يُقتطع |
| عدد الرسومات | ٨ | تُتجاهل الزائدة |
| حجم الكود | 120KB | يُرفض الحفظ |

خلايا اللوحة تُحتسب من سقف الـ ١٬٥٠٠ شكل بعددها لا كشكل واحد — لوحة ١٠×٣
تستهلك ٣٠ منه.

الكود يعمل داخل عزل QuickJS: لا وصول للشبكة أو الصفحة أو التخزين.
القيم غير الصالحة (ألوان، سُمك، نصوص) تُنقَّى تلقائياً بدل رفض المؤشر.

---

## ٧. مثال كامل — Supertrend

```javascript
const meta = {
  name: 'Supertrend',
  label: 'Supertrend (ATR Trailing Stop)',
  color: '#26a69a',
  overlay: true,
  inputs: [
    { id: 'period', type: 'int', label: 'فترة ATR', def: 10, min: 1, max: 100, control: 'slider' },
    { id: 'mult', type: 'float', label: 'المضاعف', def: 3.0, min: 0.5, max: 10, step: 0.1 },
  ],
};

function compute(candles, inputs) {
  const n = inputs.period, mult = inputs.mult;
  const hl2 = TA.hl2(candles);
  const atr = TA.atr(candles, n);          // إزاحة n-1 — مطابِقة لـ ta.atr

  const up = [], dn = [];
  let prevUp = null, prevDn = null, trend = 1;

  for (let i = 0; i < candles.length; i++) {
    const t = candles[i].time;
    const k = i - (n - 1);                  // فهرس ATR المقابل للشمعة i
    if (k < 0 || i === 0) { up.push({ time: t }); dn.push({ time: t }); continue; }  // إحماء (وi=0 لأن السطر أدناه يقرأ الشمعة السابقة)

    let u = hl2[i] - mult * atr[k];
    let d = hl2[i] + mult * atr[k];

    // القيود الزاحفة — بديل  up := close[1] > up1 ? max(up, up1) : up
    const pc = candles[i - 1].close;
    if (prevUp !== null && pc > prevUp) u = Math.max(u, prevUp);
    if (prevDn !== null && pc < prevDn) d = Math.min(d, prevDn);

    if (prevUp !== null) {
      if (trend === -1 && candles[i].close > prevDn) trend = 1;
      else if (trend === 1 && candles[i].close < prevUp) trend = -1;
    }

    // فجوة على الجانب غير النشط ← الخط ينقطع عند انعكاس الاتجاه
    if (trend === 1) { up.push({ time: t, value: u }); dn.push({ time: t }); }
    else             { dn.push({ time: t, value: d }); up.push({ time: t }); }

    prevUp = u; prevDn = d;
  }

  return [
    { id: 'up', type: 'line', primary: true, data: up },
    { id: 'dn', type: 'line', style: { color: '#ef5350', lineWidth: 2, title: '' }, data: dn },
  ];
}
```

> **نمط مُوصى به:** لاحظ أن الحلقة تدور على **فهرس الشموع** لا على فهرس المصفوفة
> المحسوبة، وتُحوّل بـ `k = i - offset`. هذا أقلّ عرضة لأخطاء الإزاحة من الدوران
> على المصفوفة القصيرة، ويجعل ربط كل نقطة بشمعتها بديهياً.

---

## ٧.١ مثال بالأشكال — صناديق الجلسات

يوضّح النمط الكامل: كشف الجلسة بالتوقيت، تجميع الشموع، قصّ القائمة، ثم بناء
الصناديق والخطوط والتسميات دفعة واحدة.

```javascript
const meta = {
  name: 'Sessions', label: 'Killzone Sessions', color: '#2196F3', overlay: true,
  inputs: [
    // بها تُفسَّر أوقات SESSIONS أدناه — بلا هذا المدخل يكون الافتراض نيويورك
    { id: 'zone', type: 'timezone', label: 'المنطقة الزمنية', def: 'chart' },
    { id: 'maxDays', type: 'int', label: 'حدّ الجلسات', def: 3, min: 1, max: 20, control: 'slider' },
  ],
};

const SESSIONS = [
  { session: '2000-0000', text: 'Asia',  hi: 'AS.H',   lo: 'AS.L',   rgb: [41, 98, 255] },
  { session: '0200-0500', text: 'London', hi: 'LO.H',  lo: 'LO.L',   rgb: [255, 82, 82] },
  { session: '0930-1100', text: 'NY AM',  hi: 'NYAM.H', lo: 'NYAM.L', rgb: [8, 153, 129] },
];

function compute(candles, inputs) {
  if (!candles.length) return [{ id: 'kz', type: 'shapes', shapes: [] }];
  const lastTime = candles[candles.length - 1].time;
  const shapes = [];

  for (const S of SESSIONS) {
    const rgb = S.rgb.join(',');
    const boxColor = `rgba(${rgb},0.3)`, lineColor = `rgba(${rgb},1)`;

    // ١) تجميع الشموع المتتالية داخل الجلسة
    const runs = [];
    let cur = null;
    for (const c of candles) {
      if (TA.inSession(c.time, S.session)) {
        if (!cur) { cur = { t1: c.time, t2: c.time, hi: c.high, lo: c.low }; runs.push(cur); }
        else { cur.t2 = c.time; cur.hi = Math.max(cur.hi, c.high); cur.lo = Math.min(cur.lo, c.low); }
      } else cur = null;
    }

    // ٢) آخر maxDays جلسة فقط — بديل max_boxes_count و .delete()
    for (const K of runs.slice(-inputs.maxDays)) {
      shapes.push({ kind: 'box', x1: K.t1, y1: K.hi, x2: K.t2, y2: K.lo,
                    bgColor: boxColor, borderColor: boxColor,
                    text: S.text, textColor: lineColor });

      // ٣) خطوط القمة/القاع تمتد حتى الاختراق
      let hiEnd = lastTime, loEnd = lastTime, hiHit = false, loHit = false;
      for (const c of candles) {
        if (c.time <= K.t2) continue;
        if (!hiHit && c.high > K.hi) { hiEnd = c.time; hiHit = true; }
        if (!loHit && c.low < K.lo)  { loEnd = c.time; loHit = true; }
        if (hiHit && loHit) break;
      }

      shapes.push({ kind: 'line', x1: K.t1, y1: K.hi, x2: hiEnd, y2: K.hi, color: lineColor });
      shapes.push({ kind: 'line', x1: K.t1, y1: K.lo, x2: loEnd, y2: K.lo, color: lineColor });
      shapes.push({ kind: 'label', x: K.t1, y: K.hi, text: S.hi, textColor: lineColor, position: 'above', size: 10 });
      shapes.push({ kind: 'label', x: K.t1, y: K.lo, text: S.lo, textColor: lineColor, position: 'below', size: 10 });
    }
  }
  return [{ id: 'kz', type: 'shapes', shapes: shapes }];
}
```

---

## ٨. البرومبت الجاهز — على مرحلتين

المؤشرات الجادّة تتجاوز مئة مدخل. حين يُطلب من النموذج إخراج الإعدادات
والخوارزمية في ردّ واحد، تتنافسان على انتباهه وعلى طول المخرَج — فيقدّم
الخوارزمية ويختصر الإعدادات. **الفصل يُنهي هذا التنافس**، ويتيح لك مراجعة قائمة
الإعدادات قبل أن يُكتب الحساب أصلاً.

### المرحلة ١ — استخراج الإعدادات

> ارفع هذا الملف + كود PineScript، وانسخ ما بين السطرين.

---

```
اقرأ مؤشر PineScript المرفق واستخرج إعداداته فقط. لا تكتب أي كود حساب الآن.

المطلوب شيئان:

أولاً — جدول أمانة يسرد كل `input` في المصدر:

| المدخل في Pine | النوع | المقابل عندنا | ملاحظة |

القاعدة: اعرض كل مدخل **يغيّر ما يُرسم فعلاً** — حتى لو كان معطّلاً افتراضياً
(input.bool(false))، فاعرضه كـ bool بقيمة def: false.
لا تعرض المدخلات المرتبطة بميزات غير مدعومة (التنبيهات وحدها عملياً)، بل اكتب في
عمود الملاحظة سبب استحالتها. أمّا مدخلات `bgcolor` و`input.source` فاعرضها:
كلاهما مدعوم (القسمان ٣.٥ و٣.٦)، و`input.source` يصير `type:'source'`.
أمّا مدخلات الجدول (`table`) — موضعه وألوانه وحجم خطّه — فاعرضها كلّها: الجدول
مدعوم عبر `kind:'panel'`. وكذلك مدخلات عرض الرمز/الفريم: كلاهما متاح. ومدخل
الفريم الأعلى (`input.timeframe` أو نصّ فريم) اعرضه كـ `select` أو `string`
ومرّره إلى `request.security` — جلب فريم/رمز آخر صار مدعوماً (القسم ٣.٤).

ثانياً — انتهِ بسطر عددي صريح:
«حُوِّل N من M مدخلاً. غير محوَّل: X لميزات غير مدعومة، Y لسبب آخر (اذكره).»

ثم أخرج `const meta = {...}` كاملاً وحده — بلا `compute`.

استخدم الأنواع التسعة من القسم ٢ (int / float / bool / color / string /
select / session / time / symbol — والأخير لكل مدخل يختار رمزاً)، ونظّم المدخلات بـ `section` للأقسام و`inline` لجمع
ما يخصّ عنصراً واحداً في صفّ (المفتاح والاسم والوقت واللون معاً).
الحدّ الأقصى ٨٠ مدخلاً؛ إن تجاوز المصدر ذلك، أسقِط الأقل أثراً واذكر ما أسقطت.
```

---

### المرحلة ٢ — كتابة الحساب

> بعد مراجعة `meta` وتعديل ما تريد، أرسل هذا في نفس المحادثة.

---

```
مُعتمَد. الآن اكتب `function compute(candles, inputs)` لهذا الـ meta.

اتبع المرجع المرفق (CUSTOM-INDICATORS.md) بدقّة، والتزم بالتالي:

0. استخدم كل مدخل عرّفناه في meta. أي مدخل لا يؤثّر في المخرَج = خيار ميت
   في الواجهة؛ إن تعذّر تنفيذ أحدها فاذكره صراحةً بدل تركه معلّقاً.
1. أخرج ملفاً واحداً فيه `const meta = {...}` و `function compute(candles, inputs)` فقط.
2. استخدم دوال TA المتاحة في المرجع فقط. لا تخترع دوالاً غير موجودة.
   إن احتجت دالة غير موجودة (مثل ATR) فاشتقّها من الموجود.
3. انتبه لطول المصفوفات والإزاحة (offset) — هذا أكثر مصدر للأخطاء.
   تحقّق أن كل نقطة تُربط بالشمعة الصحيحة عبر TA.pt أو بفهرس صريح.
4. حوّل منطق `var` و `:=` في Pine إلى متغيّرات خارج حلقة for صريحة،
   لأن compute تُستدعى مرّة واحدة بكل الشموع لا مرّة لكل شمعة.
5. بدل NaN/na استخدم نقطة بلا value: { time } — تُرسم كفجوة.
6. اضبط overlay: true إن كان المؤشر يُرسم على السعر، و false إن كان له مقياس مستقل.
7. حوّل hline إلى meta.levels، ولا تحدّد ألواناً صريحة للمستويات.
8. للصناديق والخطوط والتسميات والدوائر والتعبئة واللوحات استخدم "shapes"
   (القسم ٣.١)، ولإشارات plotshape استخدم "markers" (القسم ٣.٢).
   الإحداثيات بالوقت والسعر لا بفهرس الشمعة. لا تحاكِ box.new بالتحديث التدريجي:
   احسب بداية الشكل ونهايته أولاً ثم أنشئه مرّة واحدة. كل الأنواع — الأشكال
   والتعبئة والعلامات وخلفية bgcolor — تعمل في اللوحة السفلية أيضاً
   (overlay: false). ولـ bgcolor() استخدم `{ type:'bgcolor' }` (القسم ٣.٥)،
   ولـ input.source استخدم `{ type:'source' }` (القسم ٣.٦).
9. للجلسات والأوقات استخدم TA.inSession و TA.tz — لا تستخدم Intl أو
   toLocaleString، فهي غير موجودة. وأضِف مدخل `type:'timezone'` لأي مؤشر
   جلسات، وإلا فُسِّرت أوقاته بتوقيت نيويورك مهما كان محور المستخدم.
10. احترم بارامتراً يحدّ عدد الأشكال (مثل maxDays) وقصّ القائمة بـ slice(-n).
    الحدّ الأقصى ١٥٠٠ شكل، وخلايا اللوحة تُحتسب منه.
10.١ حوّل table.new/table.cell إلى `{ kind:'panel', position, rows }` داخل
    "shapes" (القسم ٣.١) — لوحة مثبّتة بالبكسل لا تنزاح مع التمرير، وwidth/height
    في الخليّة نسبة مئوية من الشارت كما في Pine. لا تستبدلها بـ label: التسمية
    مرساة بوقت وسعر فتنزاح عن مكانها وتخرج عن الشاشة.
10.٢ `syminfo.ticker` و`timeframe.period` متاحان داخل compute (القسم ٣.٣)،
    و`timeframe.pine` يعطي ترميز Pine نفسه ('15'/'240'/'D'). لا تحذف السطور
    التي تستعملهما ولا تستبدلها بنصّ ثابت.
11. لا تستخدم fetch أو window أو setTimeout — غير موجودة في العزل. (`console.log`
    يعمل للتصحيح: يظهر في لوحة اختبار المحرّر فقط، بلا أثر على الشارت.)
11.١ `request.security` مدعومة (القسم ٣.٤): حوّلها إلى
    `request.security(sym, tf)` + حساب بـ`TA` + `request.map`، واجعل الكود
    يحتمل مصفوفة فارغة في أول تشغيلة. و`barmerge.lookahead_on` يقابله
    `{ lookahead: true }` — بدونه لا يعيد المؤشر الرسم، وهو الافتراض الصحيح.
12. إن كان في المصدر ميزات غير مدعومة (التنبيهات عملياً) فاذكرها صراحةً في
    تعليق أعلى الملف بدل تجاهلها بصمت، وحوّل ما تبقّى. ولا تعلن شيئاً غير مدعوم
    قبل أن تجده في جدول التحويل (القسم ٥) كذلك — الجداول والرمز والفريم وجلب
    فريم/رمز آخر وخلفية bgcolor ومصدر السعر والعلامات في اللوحة السفلية كلّها
    مدعومة.
13. الخيارات المعطّلة افتراضياً في المصدر نفّذها فعلياً في الحساب — قيمتها
    الافتراضية false تكفي لإخفائها، ولا داعي لحذف الكود.
14. **إن كان المصدر يُرسم في لوحة منفصلة بصفوف** (ICT Quarterly، خرائط الجلسات،
    مقاييس أسفل الشارت): اجعل `overlay: false`، واستخدم إحداثيات صفوف ثابتة
    (`y = 0,1,2…`) **لا أسعار** (high/low). راجع قسم «الرسم في لوحة فرعية
    مستقلّة». إن كان المصدر يجمع بين الرسم على السعر والرسم في لوحة معاً (مفتاح
    display-on-chart لكل دورة)، فذلك مستحيل في مؤشر واحد: اختر اللوحة بالصفوف
    وأسقِط مفتاح الازدواج، واذكر ذلك في تعليق أعلى الملف.

أخرج الكود فقط، جاهزاً للصق في المحرّر.
```

---

### إن أردت التحويل في ردّ واحد

للمؤشرات الصغيرة (أقل من ١٠ مدخلات) الفصل ليس ضرورياً — أرسل البرومبتين معاً
مسبوقين بـ «نفّذ المرحلتين في ردّ واحد». للمؤشرات الكبيرة **لا تفعل**؛ هذا بالضبط
ما ينتج لوحة إعدادات فقيرة.

---

**إن لم يعمل الكود من أول مرّة:** انسخ رسالة الخطأ من لوحة المحرّر وأعدها للذكاء
الاصطناعي — أغلب المشاكل تُحلّ في محاولة أو اثنتين، وأكثرها شيوعاً خطأ في الإزاحة.

**إن خرجت الإعدادات فقيرة رغم ذلك:** اطلب جدول الأمانة صراحةً — «كم مدخلاً في
المصدر وكم حوّلت؟». الرقم يكشف الحذف الصامت فوراً.
