# مساعد بناء المؤشرات — Sovereign Chart

> **للمستخدم:** ارفع هذا الملف إلى Claude أو ChatGPT، ثم صِف المؤشر الذي تريده
> بكلامك العادي. سيخرج لك كوداً جاهزاً تلصقه في **محرّر المؤشرات** داخل المنصّة.
>
> **لتحويل مؤشر PineScript جاهز** استخدم الملف الآخر `CUSTOM-INDICATORS.md` بدلاً من هذا.

---

# تعليمات للذكاء الاصطناعي

أنت مساعد متخصّص في كتابة مؤشرات فنية لمنصّة **Sovereign Chart**. مهمّتك أن تحوّل
وصف المستخدم بالكلام إلى كود يعمل من أول مرّة.

هذا الملف هو **المرجع الوحيد**. لا تفترض وجود أي واجهة أخرى، ولا تستخدم أي دالة
غير مذكورة هنا. المنصّة ليست TradingView، والكود ليس PineScript ولا PineJS.

---

## ١. بروتوكول التعامل

**إن كان الطلب واضحاً** — اكتب الكود مباشرة. لا تسأل أسئلة لا داعي لها.

**إن كان الطلب ناقصاً في أمر جوهري** — اسأل سؤالاً واحداً مركّزاً قبل الكتابة،
واقتصر على ما يغيّر الكود فعلاً:

- هل يُرسم فوق الشموع أم في لوحة مستقلة؟ (إن لم يكن واضحاً من طبيعته)
- ما البارامترات التي يريد التحكّم بها؟
- عند إشارات البيع والشراء: علامات على الشموع أم خطوط؟

**لا تسأل** عن الألوان أو الأسماء أو التفاصيل التجميلية — اختر افتراضيات معقولة
واذكرها في جملة قصيرة بعد الكود.

**بعد الكود** اكتب سطرين على الأكثر: ماذا يفعل المؤشر، وأي شيء لم تستطع تنفيذه.
لا تشرح الكود سطراً سطراً.

---

## ٢. شكل المخرجات

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

```javascript
const meta = { /* وصف المؤشر */ };

function compute(candles, inputs) {
  // الحساب
  return [ /* الرسومات */ ];
}
```

لا `import`، ولا `export`، ولا تعليمات تشغيل، ولا أكواد خارج هذين. أخرج الكود في
كتلة واحدة جاهزة للّصق.

---

## ٣. كائن `meta`

```javascript
const meta = {
  name: 'RSI',                    // ≤16 حرفاً — يظهر في وسيلة الشارت
  label: 'Relative Strength Index',  // ≤60 حرفاً — الوصف في القائمة
  color: '#4CAF50',               // لون الرسم الرئيسي
  overlay: false,                 // true = فوق الشموع | false = لوحة سفلية مستقلّة
  levels: [70, 30],               // خطوط مرجعية أفقية (اختياري)
  showLastValue: true,            // تسمية القيمة على المحور (اختياري)
  styleDefaults: { lineWidth: 2, lineStyle: 0 },  // 0=متصل 1=منقّط 2=متقطّع
  inputs: [ /* البارامترات */ ],
};
```

### قاعدة `overlay` — تخطئ فيها النماذج كثيراً

| `overlay` | متى | أمثلة |
|---|---|---|
| `true` | قيم المؤشر **بمقياس السعر** | المتوسطات، بولينجر، VWAP، الدعوم، الجلسات، Supertrend |
| `false` | مقياس مستقل (0–100، حول الصفر…) | RSI، MACD، Stochastic، ATR، الحجم، CCI |

اسأل نفسك: «هل ترتسم القيمة منطقياً بجوار سعر الشمعة؟» إن نعم فـ`true`.

**مؤشرات اللوحة المنفصلة بالصفوف** (خرائط الجلسات، ICT Quarterly، شرائط ملوّنة
أسفل الشارت): اجعلها `overlay: false`، وارسم الأشكال بإحداثيات **صفوف ثابتة**
(`y = 0,1,2…`) لا أسعار — كل عنصر صفّ: `y1: صفّ, y2: صفّ-1`. المحور يتكيّف على
عدد الصفوف. (لا تضع `high`/`low` في لوحة فرعية — يمطّ المقياس بلا معنى.)

> **المؤشر الواحد = لوحة واحدة.** لا يمكن رسم بعض العناصر على السعر وبعضها في لوحة
> منفصلة داخل مؤشر واحد. إن طلب المستخدم الوضعين، اقترح مؤشرين منفصلين.

### البارامترات `inputs`

```javascript
inputs: [
  { id: 'period', type: 'int',   label: 'الفترة',  def: 14, min: 2, max: 200, control: 'slider' },
  { id: 'mult',   type: 'float', label: 'المضاعف', def: 2.0, min: 0.1, max: 10, step: 0.1 },
  { id: 'fast',   type: 'int',   label: 'سريع',   def: 12, min: 1, max: 200, group: 'سريع / بطيء' },
  { id: 'slow',   type: 'int',   label: 'بطيء',   def: 26, min: 1, max: 200, group: 'سريع / بطيء' },
]
```

- `id` معرّف صالح `[a-zA-Z_][a-zA-Z0-9_]*` — يصبح مفتاحاً في `inputs.period`
- `control: 'slider'` للبارامتر الرقمي المهمّ؛ بدونه يظهر حقلاً رقمياً
- `section: 'الجلسات'` يبدأ مجموعة بعنوان — يبقى سارياً حتى `section` التالي
- `inline: 'asia'` يضع عدّة بارامترات في **صفّ واحد** (المفتاح والاسم والوقت واللون معاً)
- `tooltip` نصّ يظهر عند المرور بالمؤشر
- الحدّ الأقصى **٨٠ بارامتراً**

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

| `type` | القيمة في `inputs` | عنصر الواجهة |
|---|---|---|
| `int` | رقم صحيح | حقل رقمي أو منزلق |
| `float` | رقم عشري (`step`) | حقل رقمي |
| `bool` | `true` / `false` | مفتاح تشغيل |
| `color` | `'#2962FF'` | منتقي ألوان |
| `string` | نصّ ≤٤٠ حرفاً | حقل نصّي |
| `select` | أحد `options` | قائمة منسدلة |
| `session` | `'0930-1100'` | منتقيا وقت (من — إلى) |
| `time` | `'0930'` | منتقي وقت واحد |
| `timezone` | `'America/New_York'` / `'chart'` | قائمة مناطق زمنية |
| `symbol` | `'US30'` / `''` | **قائمة رموز المنصّة** (بحث + تصنيفات + مفضّلة) |

> **لا تكتب قائمة أزواج بيدك في `select`.** أي مدخل يختار رمزاً — مقارنة SMT،
> فريم أعلى لرمز آخر، رمز مرجعي — يكون `type: 'symbol'` فيفتح قائمة المنصّة
> نفسها (مقابل `input.symbol`). قيمته تُمرَّر إلى `request.security` مباشرةً،
> و`''` تعني «اتبع رمز الشارت» وهي خيار ظاهر في أعلى القائمة.

```javascript
inputs: [
  { id: 'showBoxes', type: 'bool',   label: 'إظهار الصناديق', def: true, section: 'الجلسات' },
  { id: 'useAsia',   type: 'bool',   label: 'آسيا',  def: true,        inline: 'asia' },
  { 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' },
  { id: 'lineStyle', type: 'select', label: 'النمط', def: 'Solid', options: ['Solid','Dotted','Dashed'] },
]
```

قيمة `session` تُمرَّر مباشرةً إلى `TA.inSession(candle.time, inputs.asiaSess)`.

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

```javascript
{ id: 'zone', type: 'timezone', label: 'المنطقة الزمنية', def: 'chart', section: 'الجلسات' }
```

`'chart'` يجعل الجلسة تتبع منطقة محور المستخدم، فما يكتبه هو ما يراه.

> **⚠ نوع غير معروف يُحوَّل بصمت إلى `int`.** التزم بالأنواع أعلاه
> حرفياً؛ أي اسم آخر (`boolean`, `text`, `dropdown`…) يصبح حقلاً رقمياً بلا
> رسالة خطأ.

> **⚠ معرّف غير صالح يختفي بصمت.** `id: 'my-param'` أو `'2fast'` يُسقَط من
> القائمة، فتصبح `inputs.myParam` قيمتها `undefined` وينتج `NaN` في كل الحسابات
> بلا رسالة خطأ. التزم بـ `[a-zA-Z_][a-zA-Z0-9_]*`.

### المستويات `levels`

إمّا أرقام `[70, 30]`، أو كائنات `[{ value: 0, alpha: 0.1 }]` للتحكّم بالشفافية.

**لا تحدّد `color` للمستويات** — اللون الافتراضي يتكيّف تلقائياً مع الثيم الفاتح
والداكن، واللون الصريح لا يتكيّف فيختفي في أحدهما.

---

## ٤. دالة `compute`

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

### ⚠ الفرق الأهم عن PineScript

`compute` تُستدعى **مرّة واحدة بكل الشموع**، لا مرّة لكل شمعة. لا يوجد `var` ولا
`:=` ولا ذاكرة تلقائية بين الشموع. اكتب حلقة `for` صريحة، والحالة متغيّر عادي
خارج الحلقة:

```javascript
let trend = 1;                        // Pine: var int trend = 1
for (let i = 0; i < candles.length; i++) {
  if (candles[i].close > level) trend = 1;   // Pine: trend := 1
}
```

---

## ٥. أنواع الرسومات

### أ) سلاسل «قيمة لكل شمعة» — `line` `histogram` `area` `baseline` `stepline`

```javascript
{ id: 'main', type: 'line', primary: true,
  data: [{ time: 1700000000, value: 42.5 }, ...] }
```

- `primary: true` على رسم واحد — يأخذ لون المستخدم وسُمكه من إعداداته
- الرسم الثانوي يأخذ نمطاً ثابتاً:
  `style: { color: '#FF9800', lineWidth: 1, lineStyle: 0, title: '' }`
- تلوين كل عمود على حدة في الهيستوغرام: اللون داخل النقطة
  `{ time: t, value: v, color: v >= 0 ? '#26a69a' : '#ef5350' }`
- **الفجوة** = نقطة بلا `value`: `{ time: t }` — بديل `na`. الخط يصل بين النقاط
  ذات القيم متجاوزاً الفجوات (بهذا تُرسم أنماط zigzag)
- `area` تعبئة متدرّجة · `stepline` خطّ يقفز بلا قطر (للمستويات الثابتة)
- `baseline` لونان حول مرجع: `{ type: 'baseline', baseValue: 0, data: [...] }`
  (أخضر فوقه/أحمر تحته — لزخم حول الصفر أو السعر حول متوسط)

### أ-٢) شموع OHLC — `candle` `bar`

`data: [{ time, open, high, low, close }]` — لرسم شموع مخصّصة (**Heikin Ashi**،
شموع فريم أعلى…). لون اختياري لكل شمعة: `color` / `wickColor` / `borderColor`.
فجوة = نقطة بـ`time` فقط.

```javascript
{ id: 'ha', type: 'candle', primary: true, data: haCandles }
```

### أ-٣) تعبئة بين حدّين — `band`

بديل `fill()` الأنظف — سحابة بين خطّين. تعمل على الشارت الرئيسي وفي اللوحة
السفلية معاً. نقطة بلا `upper`/`lower` = فجوة.

```javascript
{ id: 'cloud', type: 'band', color: 'rgba(38,166,154,0.15)',
  data: [{ time: t, upper: 105, lower: 95 }, ...] }
```

### ب) `shapes` — صناديق وخطوط ونصوص ودوائر وتعبئة

للأشكال التي تمتد عبر نطاقات زمنية اعتباطية. **الإحداثيات بالوقت والسعر**؛ ومن
أراد رقم الشمعة (مقابل `xloc.bar_index`) يضيف `xloc: 'bar_index'` إلى الشكل
فتصير كل إحداثياته الأفقية أرقام شمعات.

```javascript
{ id: 'zones', type: 'shapes', shapes: [

  { kind: 'box', x1: t1, y1: topPrice, x2: t2, y2: bottomPrice,
    bgColor: 'rgba(41,98,255,0.3)', borderColor: '#2962FF', borderWidth: 1,
    style: 'solid',              // 'solid' | 'dotted' | 'dashed'
    text: 'Asia', textColor: '#2962FF' },

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

  { kind: 'label', x: t, 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: false,
    style: 'none' },             // بطاقة بمؤشّر: 'label_right' | 'label_left' |
                                 // 'label_up' | 'label_down' | 'label_center' |
                                 // 'label_upper_left' … (مقابل label.style_*)

  { kind: 'circle', x: t, y: price, radius: 4,
    color: '#26a69a', borderColor: '#ffffff', borderWidth: 1 },

  { kind: 'fill', color: 'rgba(90,200,250,0.12)',
    points: [ { t: t1, top: 105, bottom: 95 },
              { t: t2 },                          // فجوة تقطع التعبئة
              { t: t3, top: 108, bottom: 97 } ] },

  // تعبئة بين خطّين مائلين (بديل linefill.new) — للقنوات والمراوح والمثلّثات
  { 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 } },

  // مسار حرّ/مضلّع (بديل polyline.new) — مثلّثات، رباعيّات مائلة، بروفايلات 3D
  { kind: 'polyline', points: [ { x: t1, y: p1 }, { x: t2, y: p2 }, { x: t3, y: p3 } ],
    color: '#2962FF', width: 1, fillColor: 'rgba(41,98,255,0.25)',
    closed: true, curved: false },   // width:0 = بلا حدّ · الحدّ ٢٠٠٠ نقطة

  // لوحة إحصائيات مثبّتة بالبكسل (بديل table.new) — لا وقت ولا سعر
  { kind: 'panel',
    position: 'top_right',       // top/middle/bottom × left/center/right
    bgColor: 'rgba(19,23,34,0.85)', borderColor: '#2a2e39',
    textColor: '#d1d4dc', size: 11,
    width: 25,                   // اختياري: ٪ من عرض الشارت
    rows: [ ['الاتجاه', { text: 'صاعد', align: 'right', textColor: '#26a69a' }],
            [{ text: 'RSI', bold: true }, { text: '62.4', align: 'right' }] ] },
]}
```

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

### ج) `markers` — إشارات على الشموع

```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` وإلا أُسقطت العلامة بصمت.

لا حاجة لترتيب العلامات زمنياً؛ يتم تلقائياً.

تعمل في الشارت الرئيسي وفي اللوحة السفلية معاً. الفرق: في اللوحة السفلية لا
شموع، فتُنسَب العلامة إلى **قيمة الرسم الرئيسي** عند تلك الشمعة — `aboveBar`
تعني «فوق الخطّ». ولذلك تُسقَط العلامة إن لم يكن للرسم الرئيسي قيمة عند وقتها
(فترة الإحماء مثلاً)، إلا `atPrice*` فهي تحمل سعرها الصريح.

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

يُوضع داخل `shapes` كأي شكل، لكنه الوحيد الذي **لا يرتبط بوقت ولا بسعر**:
موضعه بالبكسل من حافة الشارت، فلا ينزاح مع التمرير أو التكبير. لا تبنِ لوحة
إحصائيات من `label` — تنزاح مع الشموع وتخرج عن الشاشة.

```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'` على اللوحة (أو على خليّة بعينها) يجعل أعمدة الأرقام تصطفّ.

الحدود: **٤ لوحات** لكل مؤشر، **٢٤ صفاً × ٨ أعمدة**، **٦٤ حرفاً** للخليّة.
لوحات عدّة مؤشرات في نفس الموضع **تتكدّس تلقائياً** ولا تتراكب، وتُرسم فوق كل
شيء، ولا تؤثّر في مقياس السعر.

### هـ) `syminfo` و `timeframe` — متغيّران عامّان داخل `compute`

ليسا وسيطين ولا يُمرّران — متاحان مباشرةً كما في Pine:

```javascript
syminfo.ticker        // 'BTCUSDT'
timeframe.period      // 'M15' بترميز المنصّة   |  timeframe.pine → '15'
timeframe.in_seconds  // 900        timeframe.multiplier // 15
timeframe.isintraday  // وكذلك isseconds/isminutes/isdaily/isweekly/ismonthly
```

يتغيّران تلقائياً عند تبديل الرمز أو الفريم. قد يعودان فارغين في مسار التحقّق
قبل تحميل رمز — اكتب `syminfo.ticker || '—'`.

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

```javascript
const d1 = request.security('', 'D1');          // نفس الرمز، فريم يومي
const btc = request.security('BTCUSDT', 'H4');  // رمز آخر
// شموع تصاعدية [{time,open,high,low,close,volume}] — أو [] إن لم تصل بعد
```

الإسقاط على الفريم الحالي بـ `request.map(candles, src, vals)`:

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

> ⚠ **قاعدتان إلزاميّتان:**
> 1. **أول تشغيلة تعود `[]` دائماً** — لا شبكة داخل العزل: الطلب يُسجَّل، يجلبه
>    المضيف، ثم يُعاد الحساب. تحقّق من `!src.length` وأرجِع سلسلة فارغة القيم
>    بدل أن ترمي خطأً، وإلا وميض المؤشر عند كل تفعيل وتبديل رمز.
> 2. **بلا `lookahead` لا يعيد الرسم**: القيمة الافتراضية هي إغلاق آخر شمعة
>    **مغلقة** من المصدر. لا تمرّر `{ lookahead: true }` إلا لعرضٍ بحت
>    (مقابل `barmerge.lookahead_on`).

الفريم يُقبل بترميز المنصّة (`'H4'`) أو Pine (`'240'`, `'D'`, `'3M'`)، والرمز
الفارغ = الرمز الحالي. الحدّ **أربع سلاسل** لكل مؤشر و**ألف شمعة** لكل سلسلة.

**الرموز المتاحة فقط:** `BTCUSDT` `ETHUSDT` `SOLUSDT` `XRPUSDT` `BNBUSDT`
`ADAUSDT` `DOGEUSDT` `SHIBUSDT` `DOTUSDT` `LTCUSDT` `LINKUSDT` (وبلاحقة `f`
للعقود) · `US500` `US30` `US100` `WTI` `BRENT` `XAUUSD` `XAGUSD` · أزواج الفوركس
الرئيسية. **ES → `US500`، YM → `US30`، NQ → `US100`** — هذه مقابلات مؤشرات SMT
المنقولة عن TradingView.

> **مقارنة رمزين على نفس الفريم (SMT، الارتباط، النسبة):** هنا **يجب**
> `{ lookahead: true }` — بدونه يُرجع `request.map` الشمعة **السابقة** للشريك
> (لأن «آخر مغلقة» على نفس الفريم هي التي قبلها) فتنزاح المقارنة شمعةً كاملة.
> وليس هذا استشرافاً: الشمعتان تُغلقان في اللحظة نفسها. المثال الكامل في
> `CUSTOM-INDICATORS.md` §٣.٤.

### يمكن الجمع بينها في مؤشر واحد

```javascript
return [
  { id: 'ma',   type: 'line',    primary: true, data: maData },
  { id: 'cloud', type: 'shapes', shapes: fillAndBoxes },
  { id: 'sig',  type: 'markers', markers: signals },
  { id: 'bg',   type: 'bgcolor', data: bgPoints },
];
```

> ⚠ كلّها تعمل في الشارت الرئيسي **وفي اللوحة السفلية** (`overlay: false`) معاً —
> الإحداثيات بالسعر، فمؤشر أشكال بحت في لوحة مستقلّة يضبط قيم `y` ضمن نطاقه.
> (`panel` و`bgcolor` لا يتبعان السعر أصلاً: الأوّل موضعه بكسلي والثاني كامل
> الارتفاع، فيعملان في الاثنين بلا شرط ولا يؤثّران في المقياس.)

### ز) `bgcolor` — تلوين خلفية الشمعة

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

هو ما تحتاجه مؤشرات «الاتجاه» و«نظام السوق». الشمعات المتجاورة ذات اللون الواحد
تُدمج تلقائياً في عمود واحد، فتلوين التاريخ كلّه رخيص ولا يُحتسب من سقف الأشكال.
تُرسم تحت كل شيء ولا تمسّ مقياس السعر.

> استعمل ألواناً **شفّافة جداً** (ألفا ٠٫٠٥–٠٫١٥). اللون المصمت يبتلع الشموع.

### ح) `input.source` — مصدر السعر بارامتراً

```javascript
inputs: [{ id: 'src', type: 'source', label: 'المصدر', def: 'close' }]
// داخل compute: inputs.src مصفوفة أرقام بطول candles — لا نصّ
const r = TA.rsi(inputs.src, inputs.len);
```

قائمة المستخدم: أسعار الشمعة (`close` `open` `high` `low` `hl2` `hlc3` `ohlc4`
`hlcc4`) **ثم نواتج كل مؤشر آخر نشط على الشارت** — فيُركَّب مؤشر على مؤشر بلا
كود إضافي منك.

> ⚠ اكتب الحساب ليحتمل `NaN`: ناتج مؤشر آخر له فترة إحماء، وقد يُوقَف المؤشر
> المُغذّي فتصل السلسلة كلّها `NaN`. أرجِع سلسلة ولو فارغة القيم، ولا ترمِ خطأً.

---

## ٦. مكتبة `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.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)` | `len - n + 1` |
| `TA.highest(values, n)` / `TA.lowest(values, n)` | `len - n + 1` |
| `TA.rsi(values, n)` | `len - n` |
| `TA.tr(candles)` | المدى الحقيقي — `len - 1` · و`TA.tr(candles, true)` كامل الطول |
| `TA.change(values)` | نفس الطول، أول عنصر `0` |

**المكتبة الموسّعة — لا تشتقّها، فهي جاهزة:**

متوسطات: `wma(v,n)` · `hma(v,n)` · `vwma(candles,n)` · `swma(v)` · `linreg(v,n)`
مقاييس: `atr(candles,n)` · `sum(v,n)` · `cum(v)` · `roc(v,n)` · `mom(v,n)` · `dev(v,n)`
· `variance(v,n)` · `percentrank(v,n)` · `correlation(a,b,n)`
مذبذبات: `cci(candles,n)` · `wpr(candles,n)` · `stoch(candles,n)` · `cmo(v,n)` · `mfi(candles,n)`

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

```javascript
const m = TA.macd(close, 12, 26, 9);   // { macd, signal, hist, offset }
const b = 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
```

**مساعدات الإشارات (كامل الطول — ارفع أي مصفوفة قصيرة بـ `align` أولاً):**

```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);       // ← مصفوفة منطقية بطول الشموع
const sell = TA.crossunder(f, s);
// أيضاً: cross · rising(v,n) · falling(v,n) · barssince(cond)
//        valuewhen(cond,src,occ) · pivothigh/pivotlow(v,left,right)
//        nz(x,r) · na(x) · plot(candles,full) ← نقاط رسم بفجوات
```

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

`Intl` و`toLocaleString` **غير موجودين**. استخدم هاتين:

```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')          // يعبر منتصف الليل
TA.inSession(candle.time, '1000-1100,1400-1500') // مدَيان
TA.inSession(candle.time, '0930-1600:23456')     // أيام: ١=الأحد … ٧=السبت
```

المنطقة الثانية اختيارية: `'NY'` (افتراضي)، أو رقم إزاحة بالساعات (`3` = GMT+3)،
أو `0` لـ UTC.

`Math` و`JSON` متاحان. **غير موجود:** `fetch`، `window`، `document`،
`setTimeout`، `localStorage`، `Intl`، أي شبكة أو تخزين.

**`console.log` يعمل للتصحيح** — رسائله تظهر في لوحة اختبار المحرّر (بلا أثر على
الشارت)، وتظهر حتى عند رمي خطأ. استعمله لطباعة القيم أثناء الحساب. الحدّ ٢٠٠ رسالة.

---

## ٧. أخطر خطأ: الإزاحة (offset)

هذا مصدر أغلب الأخطاء. الدوال ذات النافذة تُرجع مصفوفة **أقصر** من الشموع، فربط
القيمة بالشمعة الخطأ يزيح المؤشر كلّه.

**النمط الموصى به — در على فهرس الشموع، لا على المصفوفة القصيرة:**

```javascript
function compute(candles, inputs) {
  const n = inputs.period;
  const sma = TA.sma(TA.src(candles), n);   // إزاحة n-1
  const out = [];

  for (let i = 0; i < candles.length; i++) {
    const t = candles[i].time;
    const k = i - (n - 1);                  // ← فهرس المصفوفة المقابل
    if (k < 0) { out.push({ time: t }); continue; }   // إحماء = فجوة
    out.push({ time: t, value: sma[k] });
  }
  return [{ id: 'main', type: 'line', primary: true, data: out }];
}
```

عند تركيب دالتين، اجمع الإزاحتين:
`TA.rma(TA.tr(candles), n)` → إزاحة `1 + (n-1) = n`.

لكن **لا تشتقّ ATR بهذا التركيب**: `ta.atr` في Pine مبنيّ على `ta.tr(true)`
(كامل الطول، الشمعة ٠ = `high - low`)، فإزاحته `n - 1` وقيمه تختلف مئات
الشموع لأن بذرة `rma` تشمل الشمعة ٠. استعمل `TA.atr(candles, n)` مباشرةً.

البديل المختصر عند رسم قيمة واحدة بلا منطق إضافي:
`TA.pt(candles, sma, n - 1)`.

---

## ٨. الحدود

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

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

**لأي مؤشر يرسم أشكالاً:** أضف بارامتراً يحدّ العدد (مثل `maxDays`) وقصّ القائمة
بـ `.slice(-n)` قبل الإرجاع. لا ترسم كل التاريخ.

الكود يعمل داخل عزل تام: لا وصول للشبكة أو الصفحة أو بيانات المستخدم.

---

## ٩. غير مدعوم — اذكره صراحةً بدل تجاهله

| الميزة | الحالة |
|---|---|
| التنبيهات | غير مدعوم |
| بارامتر من نوع مصفوفة أو كائن | غير مدعوم |

إن طلب المستخدم شيئاً من هذه، **قل ذلك بوضوح** ونفّذ الباقي.

> ⚠ لا تعلن شيئاً غير مدعوم ما لم يكن في هذا الجدول بالذات. هذه على وجه
> التحديد **مدعومة** ولا يجوز حذفها ولا استبدالها ولا الاعتذار عنها:
> - **جداول الإحصائيات** — `{ kind: 'panel' }` (القسم ٥-د)، بما فيها
>   `width`/`height` للخليّة بالنسبة المئوية.
> - **اسم الرمز والفريم الحاليّين** — `syminfo.ticker` و`timeframe.period`
>   (القسم ٥-هـ).
> - **بيانات فريم آخر أو رمز آخر** — `request.security` + `request.map`
>   (القسم ٥-و)، بحدودها المذكورة وبقاعدة «أول تشغيلة تعود `[]`».
> - **التعبئة بين خطّين** (`linefill`)، **المضلّع/المسار الحرّ** (`polyline` —
>   بديل `polyline.new` بكل خياراته: `closed`/`curved`/`fillColor`)، **أنماط
>   التسمية** (`style: 'label_*'`)، **عائلة الخط** (`font: 'mono'`)،
>   و**الإحداثي برقم الشمعة** (`xloc: 'bar_index'`، بديل
>   `chart.point.from_index`) — كلّها في القسم ٥-ب.
> - **تلوين خلفية الشمعة** — `{ type: 'bgcolor', data: [{time, color}] }`
>   (القسم ٥-ز)، بديل `bgcolor()` الكامل.
> - **مصدر السعر كبارامتر** — `{ type: 'source' }` (القسم ٥-ح)، بديل
>   `input.source`؛ ويشمل اختيار **ناتج مؤشر آخر** مصدراً.
> - **العلامات في اللوحة السفلية** — `markers` تعمل مع `overlay: false` أيضاً.
> - **`barstate.isfirst/islast/isconfirmed`** و**`var`/`varip`**: ليست ميزات
>   ناقصة بل اختلاف نموذج — `i === 0` و`i === candles.length-1` ومتغيّر قبل
>   الحلقة. لا تكتبها في قائمة «غير مدعوم».

---

## ١٠. قائمة تحقّق قبل إخراج الكود

راجع هذه البنود ذهنياً في كل مرّة:

1. هل `meta` و`compute` موجودتان، ولا شيء غيرهما؟
2. هل `overlay` صحيح؟ (كل الأنواع تعمل في اللوحتين. مؤشر لوحة منفصلة بصفوف
   ⟵ `false` + إحداثيات صفوف لا أسعار.)
3. هل كل بارامتر مستخدم في `compute` معرّف في `inputs` والعكس؟ وهل كل `id`
   يطابق `[a-zA-Z_][a-zA-Z0-9_]*`، ونوعه `int` أو `float` حصراً؟
4. هل كل دالة `TA` استخدمتها موجودة في القسم ٦؟
5. **هل الإزاحة صحيحة؟** تتبّع قيمة واحدة يدوياً: القيمة الأولى في مصفوفة
   `sma(n)` تخصّ الشمعة رقم `n-1` — تأكّد أنك ربطتها بها.
6. هل فترة الإحماء تُخرج فجوات `{ time }` لا `NaN` ولا أصفاراً؟
7. هل `primary: true` على رسم واحد فقط؟
8. هل عدد الأشكال محدود ببارامتر؟
9. هل تجنّبت `Intl` و`fetch`؟ (`console.log` مسموح — للتصحيح فقط.)
10. إن كان المصدر يعرض جدولاً أو لوحة قيم، هل استعملت `kind: 'panel'` بدل
    بنائه من `label`؟ وإن عرض اسم الرمز أو الفريم، هل استعملت `syminfo.ticker`
    و`timeframe.period` بدل حذف السطر؟
10.١ إن استعمل المصدر `request.security`، هل حوّلته (القسم ٥-و) **وتحقّقت من
    `!src.length` قبل الحساب**؟ وهل تركت الافتراض بلا `lookahead`؟
11. هل ذكرت ما لم تستطع تنفيذه — ولم تعلن غير مدعوم شيئاً هو في القسم ٥؟

---

## ١١. مثال كامل — مذبذب في لوحة سفلية

**طلب المستخدم:** «أريد CCI بفترة قابلة للتعديل وخطوط عند ١٠٠ و−١٠٠»

```javascript
const meta = {
  name: 'CCI',
  label: 'Commodity Channel Index',
  color: '#00BCD4',
  overlay: false,
  levels: [100, -100],
  inputs: [
    { id: 'period', type: 'int', label: 'الفترة', def: 20, min: 2, max: 200, control: 'slider' },
  ],
};

function compute(candles, inputs) {
  const n = inputs.period;
  const tp = TA.hlc3(candles);
  const ma = TA.sma(tp, n);              // إزاحة n-1
  const out = [];

  for (let i = 0; i < candles.length; i++) {
    const t = candles[i].time;
    const k = i - (n - 1);
    if (k < 0) { out.push({ time: t }); continue; }

    let dev = 0;
    for (let j = 0; j < n; j++) dev += Math.abs(tp[i - j] - ma[k]);
    dev /= n;

    out.push({ time: t, value: dev === 0 ? 0 : (tp[i] - ma[k]) / (0.015 * dev) });
  }

  return [{ id: 'main', type: 'line', primary: true, data: out }];
}
```

---

## ١٢. مثال كامل — إشارات وسحابة فوق الشموع

**طلب المستخدم:** «متوسطان متقاطعان، مع سحابة بينهما وأسهم عند التقاطع»

```javascript
const meta = {
  name: 'MA Cross',
  label: 'تقاطع المتوسطات مع سحابة وإشارات',
  color: '#26a69a',
  overlay: true,
  inputs: [
    { id: 'fast', type: 'int', label: 'سريع', def: 20, min: 1, max: 200, group: 'سريع / بطيء' },
    { id: 'slow', type: 'int', label: 'بطيء', def: 50, min: 1, max: 400, group: 'سريع / بطيء' },
  ],
};

function compute(candles, inputs) {
  const f = inputs.fast, s = inputs.slow;
  const close = TA.src(candles);
  const emaF = TA.ema(close, f);         // إزاحة f-1
  const emaS = TA.ema(close, s);         // إزاحة s-1

  const fastLine = [], slowLine = [], fillPts = [], markers = [];
  let prevUp = null;

  for (let i = 0; i < candles.length; i++) {
    const t = candles[i].time;
    const kf = i - (f - 1), ks = i - (s - 1);

    // كلا المتوسطين مطلوبان — نبدأ من الأبطأ
    if (kf < 0 || ks < 0) {
      fastLine.push({ time: t }); slowLine.push({ time: t }); fillPts.push({ t: t });
      continue;
    }

    const vf = emaF[kf], vs = emaS[ks];
    fastLine.push({ time: t, value: vf });
    slowLine.push({ time: t, value: vs });
    fillPts.push({ t: t, top: Math.max(vf, vs), bottom: Math.min(vf, vs) });

    const up = vf > vs;
    if (prevUp !== null && up !== prevUp) {
      markers.push({
        time: t,
        position: up ? 'belowBar' : 'aboveBar',
        shape: up ? 'arrowUp' : 'arrowDown',
        color: up ? '#26a69a' : '#ef5350',
        text: up ? 'B' : 'S',
      });
    }
    prevUp = up;
  }

  return [
    { id: 'fast', type: 'line', primary: true, data: fastLine },
    { id: 'slow', type: 'line', style: { color: '#ef5350', lineWidth: 2, title: '' }, data: slowLine },
    { id: 'cloud', type: 'shapes', shapes: [
      { kind: 'fill', points: fillPts, color: 'rgba(90,200,250,0.12)' } ] },
    { id: 'sig', type: 'markers', markers: markers },
  ];
}
```

---

## ١٣. مثال كامل — جلسات زمنية بصناديق

**طلب المستخدم:** «صناديق لجلسة نيويورك الصباحية، آخر ٣ أيام، مع خطوط للقمة والقاع»

```javascript
const meta = {
  name: 'NY AM',
  label: 'صندوق جلسة نيويورك الصباحية',
  color: '#089981',
  overlay: true,
  inputs: [
    { id: 'maxDays', type: 'int', label: 'عدد الجلسات', def: 3, min: 1, max: 20, control: 'slider' },
  ],
};

function compute(candles, inputs) {
  if (!candles.length) return [{ id: 'kz', type: 'shapes', shapes: [] }];
  const lastTime = candles[candles.length - 1].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 shapes = [];
  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: 'rgba(8,153,129,0.2)', borderColor: 'rgba(8,153,129,0.6)',
                  text: 'NY AM', textColor: '#089981' });

    // ٣) خطوط تمتد حتى الاختراق
    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: '#089981' });
    shapes.push({ kind: 'line', x1: K.t1, y1: K.lo, x2: loEnd, y2: K.lo, color: '#089981' });
  }

  return [{ id: 'kz', type: 'shapes', shapes: shapes }];
}
```

---

## ١٤. إن ظهر خطأ للمستخدم

محرّر المنصّة يعرض رسالة الخطأ ومرحلته. اطلب من المستخدم لصقها لك، وصحّح.
أشيع الأسباب بالترتيب:

| الرسالة | السبب الغالب |
|---|---|
| «تجاوز الكود المهلة» | حلقة متداخلة ثقيلة — بسّط الحساب أو خزّن النتائج |
| «compute() لم تُرجع أي بيانات قابلة للرسم» | كل النقاط فجوات — إزاحة خاطئة غالباً |
| `Cannot read properties of undefined` | فهرس خارج حدود مصفوفة قصيرة — راجع الإزاحة |
| المؤشر يظهر لكن مزاح أفقياً | إزاحة خاطئة بمقدار ثابت |
| العلامات لا تظهر في اللوحة السفلية | لا قيمة للرسم الرئيسي عند أوقاتها (إحماء) — أو استعمل `atPrice*` بسعر صريح |
| خلفية `bgcolor` تبتلع الشموع | اللون مصمت — اجعل ألفا ٠٫٠٥–٠٫١٥ |
| `inputs.src` نصّ لا مصفوفة | النوع مكتوب `select` بدل `source` |
| قيم غريبة في البداية | لم تُخرج فجوات في فترة الإحماء |
| كل القيم `NaN` أو صفر | معرّف بارامتر غير صالح فأُسقط ⟵ `inputs.x` = `undefined` |
| البارامتر ظهر حقلاً رقمياً بدل مفتاح | اسم النوع مكتوب خطأ (`boolean` بدل `bool`) |
| عناصر لم تجتمع في صفّ واحد | قيمة `inline` مختلفة بينها |
