آموزش دستورات پایه فرمول‌نویسی اختیار معامله | متغیر، شرط، حلقه و تابع در دیده‌بان آپشن‌باز

دستورات پایه‌ای که برای نوشتن ستون و فیلتر در دیده‌بان اختیار معامله لازم دارید، با مثال اجراشده: متغیر و ثابت، عملگرها، if و else، شرط کوتاه، آرایه و حلقه، تابع، و کار با متن و عدد. زبان فرمول‌نویسی آپشن‌باز جاوااسکریپت است و همین چند دستور بیشتر کارها را پوشش می‌دهد.

نویسنده: بخش محتواتاریخ انتشار: 1405/05/21آخرین به‌روزرسانی: 1405/05/2199 دقیقه مطالعه
اشتراک‌گذاری:

ستون‌ها و فیلترهای دیده‌بان آپشن‌باز با جاوااسکریپت نوشته می‌شوند — همان زبانی که صفحه‌های وب با آن کار می‌کنند، نه یک زبان اختصاصیِ ساخته‌شده برای این سایت و نه فرمول‌نویسی سبک اکسل. این مقاله همان چند دستوری را که در فرمول‌های واقعی دیده‌بان به کار می‌روند توضیح می‌دهد: متغیر، ثابت، شرط، حلقه، آرایه، تابع و کار با متن و عدد. هدف این نیست که برنامه‌نویس شوید؛ هدف این است که وقتی یک فرمول آماده را باز می‌کنید بفهمید هر خطش چه می‌گوید و بتوانید تغییرش بدهید. فهرست فیلدها و توابع آماده در راهنمای فرمول‌نویسی داخل سایت است و اینجا تکرار نمی‌شود.

فرمول‌نویسی آپشن‌باز با چه زبانی نوشته می‌شود؟

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

فرمول شما هر بار که قیمت‌ها به‌روز می‌شوند اجرا می‌شود، و یک بار به ازای هر قرارداد جدول. یعنی وقتی یک زنجیره 40 قرارداد دارد، فرمول شما 40 بار اجرا می‌شود و هر بار متغیر ‌option به یکی از آن‌ها اشاره می‌کند.

کد شما ویرایشگر فرمول 1 موتور فرمول کد را می‌خواند 2 هر قرارداد یک بار اجرا 3 خروجی سلول یا فیلتر 4 یک کد، به ازای هر قرارداد یک بار اجرا می‌شود و هر بار option به همان قراردادِ آن سطر اشاره می‌کند
کد شما یک بار نوشته می‌شود و به ازای هر قرارداد یک بار اجرا می‌شود؛ خروجی هر اجرا یا یک سلول است یا یک تصمیمِ فیلتر.

یک فرمول دقیقاً چه شکلی است؟

یک فرمول می‌تواند به سه شکل نوشته شود، و تفاوتشان فقط سر return است.

عبارت تک‌خطی option.iv * 100 موتور خودش return می‌گذارد بدنه با return let iv = option.iv; return iv * 100; همان مقدار چاپ می‌شود بدنه بدون return let iv = option.iv; iv * 100; سلول هشدار می‌دهد
سه شکل نوشتن یک فرمول. اگر بدنه چند دستوری باشد و return نداشته باشد، فرمول خطا نمی‌دهد — سلول یک هشدار نشان می‌دهد و همان‌جا می‌ماند.

یک) عبارت تک‌خطی. اگر کل فرمول یک عبارت باشد، لازم نیست return بنویسید؛ موتور خودش نتیجه را برمی‌گرداند:

option.iv * 100

دو) بدنهٔ چندخطی با return. به‌محض اینکه چند دستور پشت سر هم بنویسید، خودتان باید بگویید چه چیزی برگردد:

let iv = option.iv; return roundNumber(iv * 100, 1) + '٪';

سه) بدنهٔ چندخطی بدون return — که کار نمی‌کند. این حالت خطا نمی‌دهد و دقیقاً به همین دلیل گیج‌کننده است. فرمول کامپایل می‌شود، سلول هم پر می‌شود، ولی چیزی که در آن می‌بینید یک هشدار است نه محاسبهٔ شما:

let iv = option.iv; iv * 100;

اگر یک ستون تازه ساختید و همهٔ سطرها یک هشدار نارنجی نشان دادند، اولین چیزی که باید چک کنید همین است: خط آخر return دارد؟

ستون یا فیلتر — یک زبان، دو نقش

ستون و فیلتر با همان زبان و همان فیلدها نوشته می‌شوند. تفاوت فقط در چیزی است که برمی‌گردانید:

یک زبان، دو نقش — تفاوت فقط در چیزی است که برمی‌گردانید ستون محاسباتی هرچه برگردانی، در سلول چاپ می‌شود ضملت8010 +7.7% طملت8010 −2.1% ضملت8200 +13.4% فیلتر فقط true می‌ماند، بقیه حذف می‌شوند ضملت8010 true طملت8010 false ضملت8200 true
ستون و فیلتر با همان زبان نوشته می‌شوند؛ ستون یک متن یا عدد برمی‌گرداند و فیلتر فقط بله یا خیر.

یک ستون محاسباتی هرچه برگرداند در سلول چاپ می‌شود — عدد، متن، یا حتی متنِ رنگی که با تابع style() ساخته‌اید:

// ستون: فاصله قیمت پایه تا قیمت اعمال let uaPrice = ua.ti.lastPrice; if (!uaPrice || !option.strike) return ''; return calcRateChange(uaPrice, option.strike) + '٪';

یک فیلتر فقط true یا false برمی‌گرداند. هر قراردادی که false بگیرد از جدول حذف می‌شود:

// فیلتر: فقط قراردادهای نزدیک پول let uaPrice = ua.ti.lastPrice; if (!uaPrice || !option.strike) return false; return Math.abs(calcRateChange(uaPrice, option.strike)) <= 10;
ستون محاسباتیفیلتر
چه چیزی برمی‌گرداندعدد یا متن (هرچه در سلول می‌خواهید)فقط بله یا خیر
نتیجه‌اش کجا دیده می‌شودیک ستون تازه در جدولکم و زیاد شدن سطرهای جدول
وقتی داده نداریدreturn '' تا سلول خالی بماندreturn false تا سطر حذف شود

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

داده از کجا می‌آید — آبجکت‌ها در یک نگاه

قبل از اینکه سراغ دستورها برویم، باید بدانید داده‌ها کجا نشسته‌اند. موتور چند آبجکت آماده را داخل فرمول شما می‌گذارد و شما با نقطه به فیلدهایشان می‌رسید:

آبجکتچیستنمونه فیلد
optionخودِ قرارداد اختیار معاملهٔ همان سطرoption.strike · option.type · option.iv
option.tiتابلوی معاملاتی همان قراردادoption.ti.lastPrice · option.ti.sell1Price
uaنماد پایهua.namad · ua.hv · ua.ivRank
ua.tiتابلوی معاملاتی نماد پایهua.ti.lastPrice · ua.ti.volume
contextتنظیمات لحظه‌ای دیده‌بان، مثل مبنای قیمتcontext.priceBase

کنار این آبجکت‌ها، دهها تابع آماده هم داخل فرمول در دسترس‌اند — از breakeven() و calcBS() تا commaSeparator() و style(). فهرست کامل فیلدها و توابع با مثال، در راهنمای فرمول‌نویسی داخل سایت است؛ اگر فیلدی می‌خواهید که اصلاً وجود ندارد، می‌توانید با فیلدهای شخصی خودتان بسازیدش. باقی این مقاله دربارهٔ فیلدها نیست — دربارهٔ دستورهایی است که با آن‌ها کار می‌کنند.

متغیر و ثابت

متغیر یک جعبه است که یک مقدار را در آن می‌گذارید تا بعداً چند بار استفاده‌اش کنید. در جاوااسکریپت دو کلمه برای ساختنش هست: let و const.

let — جعبهٔ قابل تغییر let sum = 0; sum = sum + 120; const — جعبهٔ قفل‌شده const MAX = 10; MAX = 20; مقدار را کجا نگه داریم؟ ثابت‌های تنظیمات فرمول همیشه با const نوشته می‌شوند — چون قرار نیست وسط محاسبه عوض شوند
let برای مقداری که در جریان محاسبه عوض می‌شود و const برای مقداری که تا آخر ثابت می‌ماند.

let برای مقداری است که در جریان محاسبه عوض می‌شود، و const برای مقداری که تا آخر فرمول ثابت می‌ماند. اگر بخواهید مقدار یک const را عوض کنید، فرمول خطا می‌دهد — و این دقیقاً کاری است که از آن انتظار دارید: عددی که قرار بود ثابت بماند، سهواً وسط محاسبه عوض نمی‌شود.

const MAX_DISTANCE = 10; let gap = Math.abs(calcRateChange(ua.ti.lastPrice, option.strike)); return gap <= MAX_DISTANCE ? 'نزدیک' : 'دور';

در عمل، let برای محاسبات میانی است و const برای تنظیمات فرمول. و اینجا یک قرارداد خانگی آپشن‌باز هست که خوب است بدانید: هر const که اسمش با FILTER_، SHOW_ یا SETTING_ شروع شود، به‌طور خودکار در پنل تنظیمات همان فرمول یک گزینه می‌شود.

const FILTER_MIN_DISTANCE = 0; // حداقل فاصله تا اعمال title=درصد، بدون علامت step=1 const FILTER_MAX_DISTANCE = 10; // حداکثر فاصله تا اعمال title=درصد، بدون علامت step=1 let gap = Math.abs(calcRateChange(ua.ti.lastPrice, option.strike)); if (FILTER_MIN_DISTANCE !== '' && gap < FILTER_MIN_DISTANCE) return false; if (FILTER_MAX_DISTANCE !== '' && gap > FILTER_MAX_DISTANCE) return false; return true;

یعنی کسی که این فیلتر را نصب می‌کند، برای عوض کردن «حداکثر فاصله تا اعمال» لازم نیست کد را باز کند؛ عدد را از پنل تنظیمات عوض می‌کند. همهٔ جزئیات این پنل در راهنمای تنظیمات ویژوال آمده، و فرمول‌های آمادهٔ دیده‌بان همگی با همین قرارداد نوشته شده‌اند.

نام‌هایی که نباید برای متغیر خودتان انتخاب کنید

option، ua، context، pos و positions از قبل توسط موتور پر شده‌اند. اگر متغیری با همین نام‌ها بسازید، از آن خط به بعد نام شما جای آبجکت اصلی را می‌گیرد و دسترسی به داده‌ها را از دست می‌دهید:

let option = 5; return option.strike;

بدترین بخشش این است که هیچ خطایی نمی‌بینید: فرمول سالم اجرا می‌شود و سلول فقط خالی می‌ماند، انگار داده‌ای وجود ندارد. یک پیشوند کوچک — مثلاً ‌myOption — کل ماجرا را حل می‌کند.

عملگرها

عملگرها سه دسته‌اند: حسابی (که عدد می‌سازند)، مقایسه‌ای (که بله/خیر می‌سازند) و منطقی (که بله/خیرها را به هم می‌بندند).

هر مقایسه یک جواب بله/خیر می‌دهد option.state == "ITM" true option.iv > 0.5 true option.ti.volume >= 1000 false && همه باید true باشند با && هر سه شرط باید برقرار باشد؛ با || یکی کافی است؛ و ! جواب را وارونه می‌کند
عملگرهای مقایسه‌ای جواب بله/خیر می‌سازند و عملگرهای منطقی آن‌ها را به هم می‌بندند — همان چیزی که یک فیلتر در نهایت برمی‌گرداند.
عملگرمعنینمونه
+ - * /جمع، تفریق، ضرب، تقسیمoption.strike + option.ti.lastPrice
%باقی‌مانده تقسیمdays % 7
==مساوی است؟option.type == 'call'
!=مساوی نیست؟option.state != 'OTM'
>بزرگ‌تر است؟option.iv > 0.5
<کوچک‌تر است؟option.daysUntilMaturity < 30
>=بزرگ‌تر یا مساویoption.openInterest >= 100
<=کوچک‌تر یا مساویgap <= 10
&&و — هر دو شرط باید برقرار باشندiv > 0.3 && iv < 0.8
||یا — یکی از دو شرط کافی استstate == 'ITM' || state == 'ATM'
!نه — جواب را وارونه می‌کند!option.ti.lastPrice

دو مساوی یا سه مساوی؟

== فقط مقدار را می‌سنجد و === علاوه بر مقدار، نوع را هم می‌سنجد. در بیشتر فرمول‌ها هر دو یک جواب می‌دهند و فرقی نمی‌کند کدام را بنویسید — به‌جز یک مورد که بدجوری گاز می‌گیرد.

چرا گذاشتن عدد 0 در یک فیلتر، آن را خاموش می‌کند 0 == '' true پس شرطِ «خالی است؟» فعال می‌شود 0 === '' false سه‌مساوی نوع را هم می‌سنجد برای «فقط بالای صفر» عدد کوچکی مثل 0.1 بگذارید، نه صفر
تلهٔ صفر: در جاوااسکریپت دو مساوی نوع را نادیده می‌گیرد، پس عدد صفر با رشتهٔ خالی برابر می‌شود و گاردِ «تنظیم نشده» را فعال می‌کند.

در جاوااسکریپت 0 == '' برابر true است. فرمول‌های آماده معمولاً با شرطِ «اگر این تنظیم خالی است، نادیده‌اش بگیر» نوشته می‌شوند، و آن شرط با == سنجیده می‌شود. یعنی اگر در پنل تنظیمات عدد صفر بگذارید، فرمول فکر می‌کند تنظیم را خالی گذاشته‌اید و آن فیلتر را کلاً خاموش می‌کند:

const FILTER_MIN_VOLUME = 0; // 0 == '' در جاوااسکریپت true است، پس این شرط با عدد صفر هم فعال می‌شود if (FILTER_MIN_VOLUME == '') return 'فیلتر خاموش شد'; return 'فیلتر فعال است';

راه‌حل ساده است: هر جا منظورتان «فقط بالای صفر» است، عدد کوچکی مثل 0.1 بگذارید نه صفر. و اگر خودتان فرمول می‌نویسید، گاردِ خالی‌بودن را با !== '' بنویسید تا صفر از آن رد شود.

شرط — if، else و شرط کوتاه

شرط، پرکاربردترین دستور در کل کتابخانهٔ فرمول‌های دیده‌بان است — تقریباً هیچ فرمول واقعی‌ای نیست که دست‌کم یک if نداشته باشد.

نردبان if / else if / else

شرط‌ها از بالا به پایین سنجیده می‌شوند و اولین شرطی که درست باشد برنده است؛ بقیه اصلاً بررسی نمی‌شوند. پس ترتیب نوشتنشان معنی دارد — اگر در مثال زیر شرط iv > 0.3 را اول بنویسید، دیگر هیچ‌وقت به «خیلی بالا» نمی‌رسید:

نردبان شرط — از بالا به پایین، اولین شرطِ درست برنده است iv > 0.8 خیلی بالا iv > 0.5 بالا iv > 0.3 متوسط else کم به شرط دوم فقط وقتی می‌رسیم که شرط اول برقرار نبوده باشد
زنجیرهٔ if / else if / else: هر شرط فقط وقتی سنجیده می‌شود که شرط‌های بالاترش رد شده باشند، پس ترتیب نوشتنشان مهم است.
let iv = option.iv; if (iv == null) return ''; if (iv > 0.8) return style('خیلی بالا', 'red'); else if (iv > 0.5) return style('بالا', 'orange'); else if (iv > 0.3) return style('متوسط', 'blue'); else return style('کم', '#6b7280');

شرط کوتاه (ternary)

وقتی فقط دو حالت دارید، نوشتن چهار خط if و else زیادی است. علامت ? همان کار را در یک خط می‌کند: شرط، بعد ?، بعد جوابِ حالت درست، بعد :، بعد جوابِ حالت دیگر. چون یک عبارت است نه یک دستور، می‌شود مستقیم داخل یک محاسبهٔ دیگر گذاشتش — و می‌شود مثل نمونهٔ زیر زنجیره‌اش کرد:

شرط کوتاه — یک سؤال، دو جواب option.type == "call" شرط ? : اگر درست بود اگر نبود همان کارِ if و else را می‌کند، ولی چون یک عبارت است می‌شود مستقیم برش گرداند برای دو حالت عالی است؛ از سه حالت به بالا نردبان if خواناتر است
شرط کوتاه (ternary): علامت ؟ شرط را می‌پرسد و دو نتیجه با : از هم جدا می‌شوند.
let state = option.state; let color = state === 'ITM' ? '#16a34a' : state === 'OTM' ? '#dc2626' : '#6b7280'; return style(state, color);

زنجیره کردن بیش از دو تا شرط کوتاه پشت سر هم خوانایی را از بین می‌برد. از سه حالت به بالا یا نردبان if بنویسید یا switch:

switch (option.state) { case 'ITM': return style('در سود', 'green'); case 'ATM': return style('سر به سر', 'orange'); default: return style('خارج از سود', 'red'); }

الگوی «دروازهٔ محافظ» — return زودهنگام

این الگو در تقریباً همهٔ فرمول‌های آمادهٔ دیده‌بان تکرار شده و ارزش یاد گرفتن دارد. به‌جای اینکه کل محاسبه را داخل یک if بزرگ بپیچید، همان اول کار هر حالتی را که نمی‌توانید محاسبه کنید با یک return می‌بندید. آنچه باقی می‌ماند، محاسبه‌ای است که مطمئنید داده‌اش سالم است:

دروازه‌های محافظ — قبل از محاسبه، داده را بسنجید هر قرارداد زنجیره قیمت پایه ندارد قیمت اعمال ندارد سرخط عرضه خالی محاسبهٔ اصلی با دادهٔ سالم هر دروازه با یک return زودهنگام بسته می‌شود، پس محاسبهٔ اصلی هیچ‌وقت دادهٔ ناقص نمی‌بیند
الگوی return زودهنگام: هر شرطِ «داده ندارم» همان اول کار بسته می‌شود تا محاسبهٔ پایین‌تر تمیز بماند.
let uaPrice = ua.ti.lastPrice; let ask = option.ti.sell1Price; if (!uaPrice || !ask) return false; let intrinsicValue = option.type === 'call' ? uaPrice - option.strike : option.strike - uaPrice; if (intrinsicValue <= 0) return false; let discount = ((intrinsicValue - ask) / intrinsicValue) * 100; return discount >= 1;

در دیده‌بان این محافظ‌ها تزئینی نیستند. خیلی از فیلدهای تابلو می‌توانند صفر یا خالی باشند — قراردادی که امروز اصلاً معامله نشده، نمادی که دامنهٔ نوسان ندارد، سرخط عرضه‌ای که خالی است. بدون دروازه، همان صفرها به تقسیم بر صفر و عددهای بی‌معنی در جدول تبدیل می‌شوند.

آرایه و حلقه

آرایه — تکه‌های خروجی را کنار هم بچینید

آرایه یک فهرست است. رایج‌ترین کاربردش در ستون‌ها این است که هر تکهٔ خروجی را با push به فهرست اضافه کنید و آخر کار با join همه را به یک متن تبدیل کنید. مزیتش نسبت به چسباندن مستقیم متن‌ها این است که هر تکه را می‌توانید با یک if جداگانه روشن و خاموش کنید:

آرایه — تکه‌های خروجی را کنار هم بچینید ذاتی 1,200 push زمانی 340 push 22% push join(' | ') به‌هم‌چسباندن ذاتی 1,200 | زمانی 340 | 22% همان چیزی که در سلول دیده می‌شود مزیتش این است که هر تکه با یک if جدا روشن و خاموش می‌شود
الگوی رایج ستون‌ها: هر تکهٔ خروجی با push به یک آرایه اضافه می‌شود و در آخر با join یک سلول می‌سازد.
let premium = basePremium(); let uaPrice = ua.ti.lastPrice; if (!premium || !uaPrice) return ''; let raw = option.type === 'call' ? uaPrice - option.strike : option.strike - uaPrice; let intrinsicValue = Math.max(0, raw); let timeValueAmount = premium - intrinsicValue; let parts = []; parts.push(style('ذاتی ' + commaSeparator(roundNumber(intrinsicValue, 0)), '#16a34a')); parts.push(style('زمانی ' + commaSeparator(roundNumber(timeValueAmount, 0)), '#ea580c')); return parts.join(' | ');

حلقه — یک کار روی همهٔ قراردادها

تا اینجا هر فرمول فقط با قرارداد همان سطر کار داشت. گاهی به همهٔ قراردادهای زنجیره نیاز دارید — مثلاً برای جمع کل موقعیت باز، یا برای ستون max pain که باید به ازای هر قیمت اعمال، زیان کل را حساب کند. اینجاست که حلقه لازم می‌شود:

حلقه — یک کار، روی همهٔ قراردادهای زنجیره strike 7,000 1 strike 7,500 2 strike 8,000 3 strike 8,500 4 جمع‌کننده sum += ... حلقه فقط ترتیب اجراست؛ نتیجه در متغیری بیرون از حلقه جمع می‌شود ستون «max pain» دقیقاً همین کار را می‌کند: برای هر قیمت اعمال، زیان کل را جمع می‌زند
حلقه وقتی لازم می‌شود که فرمول به همهٔ قراردادهای زنجیره نیاز دارد، نه فقط به قرارداد همان سطر.
let all = optionSE('', 'all'); let totalOI = 0; for (let i = 0; i < all.length; i++) { if (all[i].openInterest > 0) totalOI += all[i].openInterest; } return commaSeparator(totalOI);

سه بخش داخل پرانتز for به ترتیب یعنی: از کجا شروع کن، تا کِی ادامه بده، و هر بار چقدر جلو برو. متغیر totalOI عمداً بیرون از حلقه تعریف شده، چون قرار است بعد از تمام شدن حلقه هم باقی بماند.

اگر با حلقه راحت نیستید، جاوااسکریپت راه کوتاه‌تری هم دارد. filter فهرست را غربال می‌کند، forEach روی همهٔ اعضا یک کار را تکرار می‌کند و map هر عضو را به چیز دیگری تبدیل می‌کند:

let calls = optionSE('', 'all').filter(function (o) { return o.type === 'call'; }); let sum = 0; calls.forEach(function (o) { sum += o.openInterest; }); return commaSeparator(sum);

و sort فهرست را مرتب می‌کند. برای مرتب کردن عددها حتماً باید تابع مقایسه بدهید، وگرنه جاوااسکریپت اعداد را مثل متن مرتب می‌کند و 100 قبل از 20 می‌آید:

let strikes = optionSE('', 'all').map(function (o) { return o.strike; }); strikes.sort(function (a, b) { return a - b; }); return commaSeparator(strikes[0]);

حلقه روی زنجیره را ارزان حساب نکنید

فرمول شما به ازای هر قرارداد یک بار اجرا می‌شود. اگر داخل آن یک حلقه روی کل زنجیره بگذارید، تعداد محاسبات ضرب می‌شود — یک زنجیرهٔ 40 قراردادی می‌شود 1,600 بار. برای یک زنجیره اهمیتی ندارد، ولی وقتی چند نماد را هم‌زمان در دیده‌بان باز کرده‌اید، همین ستون می‌تواند جدول را کند کند. اگر حلقه لازم است، اول با یک شرط سبک قراردادهای بی‌ربط را کنار بگذارید.

تابع

تابع یک تکه محاسبه است که اسم دارد و می‌توانید هر جا لازم شد صدایش بزنید. داخل همان فرمول تعریفش می‌کنید و بلافاصله استفاده‌اش می‌کنید:

تابع — یک بار بنویس، چند جا استفاده کن ستون سود فیلتر ارزانی ستون امتیاز function bsDiff() محاسبه یک‌جا می‌ماند و با یک ویرایش، همه‌جا عوض می‌شود اگر یک محاسبه را در دو فرمول کپی کنید، روزی یکی‌شان اصلاح می‌شود و دیگری نه
تابع محاسبه را یک‌جا نگه می‌دارد. در آپشن‌باز می‌شود آن را با نوع تابع ذخیره کرد تا همهٔ ستون‌ها و فیلترها بتوانند صدایش بزنند.
function priceOf(o) { let b = o.ti.buy1Price; let s = o.ti.sell1Price; if (b && s) return (b + s) / 2; return o.ti.lastPrice; } return commaSeparator(priceOf(option));

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

تابع عمومی — یک بار بنویس، در چند فرمول استفاده کن

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

function bsDiff() { let ask = option.ti.sell1Price; if (!ask) return null; return calcRateChange(calcBS().bs, ask); }

و بعد در یک ستون:

let d = bsDiff(); if (d == null) return ''; return style(d + '٪', Math.abs(d) <= 10 ? 'green' : 'red');

و در یک فیلتر، با همان تابع:

let d = bsDiff(); return d != null && d >= -10 && d <= 10;

سودش فقط کمتر تایپ کردن نیست. اگر روزی تعریف «ارزانی نسبت به قیمت تئوری» را عوض کنید، یک جا عوضش می‌کنید و هر سه فرمول با هم به‌روز می‌شوند. محاسبه‌ای که در دو فرمول کپی شده باشد، دیر یا زود یکی‌اش اصلاح می‌شود و دیگری نه.

کار با متن و عدد

ساختن متن سلول

متن‌ها را می‌شود با + به هم چسباند، ولی وقتی چند تکه شد خواندنش سخت می‌شود. راه تمیزتر، رشتهٔ قالب‌بندی‌شده است: متن را بین دو بک‌تیک می‌گذارید و هر جا مقدار محاسباتی می‌خواهید، آن را داخل ${...} می‌نویسید:

let spread = askBidSpread(); let lev = roundNumber(leverage(), 1); return `اسپرد ${spread}٪ | اهرم ${lev}`;

گرد کردن و قالب عدد

Math توابع ریاضی استاندارد جاوااسکریپت را دارد و همه‌شان در فرمول در دسترس‌اند:

تابعچه می‌کند
Math.abs(x)قدر مطلق — علامت منفی را برمی‌دارد
Math.round(x)گرد کردن به نزدیک‌ترین عدد صحیح
Math.floor(x)گرد کردن به پایین
Math.ceil(x)گرد کردن به بالا
Math.max(a, b)بزرگ‌ترین مقدار
Math.min(a, b)کوچک‌ترین مقدار
Math.sqrt(x)جذر
Math.pow(x, y)توان

برای نمایش عدد در سلول، دو تابع خودِ آپشن‌باز معمولاً بهتر از ابزار استاندارد جاوااسکریپت جواب می‌دهند: roundNumber(x, n) که برخلاف toFixed خروجی عدد می‌دهد نه متن، و commaSeparator(x) که جداکنندهٔ هزارگان می‌گذارد.

let iv = option.iv * 100; return iv.toFixed(1) + '٪ | ' + commaSeparator(roundNumber(option.strike, 0));

مقیاس‌ها را قاطی نکنید

option.iv، option.wiv و ua.hv اعشاریاند — 0.42 یعنی 42 درصد. ولی ua.ivRank و ua.ivPercentile روی مقیاس 0 تا 100 هستند. قاطی کردن این دو، خطای صد برابری می‌سازد که هیچ پیام خطایی هم ندارد — عدد فقط غلط است. توضیح این دو مفهوم در مقالهٔ نوسان ضمنی و تاریخی است.

وقتی داده اصلاً وجود ندارد

خیلی از فیلدهای تابلو می‌توانند خالی باشند — قراردادی که دیروز معامله نشده lastDayVolume ندارد، نمادی که صف است سرخط مقابل ندارد. سه ابزار برای این حالت هست:

!x برای «مقدار ندارد یا صفر است»؛ کوتاه‌ترین گارد و همانی که در فرمول‌های آماده بیشتر از همه دیده می‌شود. x == null فقط null و undefined را می‌گیرد و صفر را نمی‌گیرد — دقیقاً همان چیزی که برای فیلدی مثل «روز معاملاتی باقی‌مانده» لازم دارید، چون صفر آنجا یک مقدار معتبر است نه دادهٔ گم‌شده:

let vol = option.ti.lastDayVolume; // == null هم null را می‌گیرد هم undefined را — ولی 0 را نه if (vol == null) return style('دیروز داده ندارد', '#6b7280'); return commaSeparator(vol);

و ?? که یعنی «اگر خالی بود، این را بگذار». برای وقتی مناسب است که می‌خواهید محاسبه ادامه پیدا کند نه اینکه متوقف شود:

let iv = option.iv ?? 0; let oi = option.openInterest ?? 0; return roundNumber(iv * 100, 1) + '٪ | ' + commaSeparator(oi);

کامنت، و کاری که فقط در آپشن‌باز می‌کند

هر چیزی که بعد از // بیاید تا آخر آن خط، کامنت است و اجرا نمی‌شود. برای چند خط، متن را بین /* و */ می‌گذارید. کامنت در هر زبانی برای یادداشت است، ولی در آپشن‌باز یک کار دوم هم می‌کند:

کامنت در آپشن‌باز یک کار اضافه هم می‌کند const FILTER_MAX_DISTANCE = ''; // label title=tooltip step=1 سه چیز از یک کامنت خوانده می‌شود حداکثر فاصله تا اعمال 10 پنل تنظیمات برچسب همان متن کامنت است، تولتیپ از title و گام دکمه‌های بالا/پایین از step کاربر بدون باز کردن کد، همان عدد را از پنل تنظیمات عوض می‌کند
کامنتِ کنار یک ثابتِ FILTER_ / SHOW_ / SETTING_ برچسب همان گزینه در پنل تنظیمات می‌شود — پس کامنت اینجا فقط یادداشت نیست.

کامنتِ کنار یک const که اسمش با FILTER_، SHOW_ یا SETTING_ شروع شود، برچسب همان گزینه در پنل تنظیمات می‌شود. سه چیز از آن خوانده می‌شود: متن اول برچسب است، هرچه بعد از title= بیاید تولتیپ راهنما می‌شود، و step= تعیین می‌کند دکمه‌های بالا و پایین عدد را چقدر جابه‌جا کنند. اگر مقدار به‌جای عدد یکی از چند گزینهٔ ثابت باشد، گزینه‌ها را داخل کروشه می‌نویسید.

یعنی وقتی برای فرمول خودتان کامنت می‌نویسید، در واقع دارید رابط کاربری‌اش را هم می‌سازید — و کسی که آن را نصب می‌کند بدون باز کردن کد می‌تواند تنظیمش کند. قواعد کامل این پنل در راهنمای تنظیمات ویژوال فرمول آمده است.

شش اشتباه رایج

اشتباهچه می‌بینیددرستش
بدنهٔ چندخطی بدون returnهمهٔ سلول‌ها یک هشدار نارنجیخط آخر را با return شروع کنید
گذاشتن عدد صفر در یک تنظیم فیلترفیلتر انگار اصلاً اعمال نمی‌شود0.1 بگذارید، نه 0
نام‌گذاری متغیر با نام‌های رزروخطای عجیب روی فیلدی که مطمئنید وجود داردmyOption به‌جای option
محاسبه بدون گارد روی فیلد خالیNaN، Infinity یا عددهای پرت در جدولاول دروازه‌های محافظ، بعد محاسبه
استفاده از !x برای فیلدی که صفرش معتبر استقراردادهای سررسید امروز بی‌صدا حذف می‌شوندx == null بنویسید
قاطی کردن مقیاس اعشاری و صددرصدیعددی که صد برابر کوچک یا بزرگ استiv اعشاری، ivRank از 100

از اینجا به بعد

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

یک) از یک فرمول آماده شروع کنید. در تب «آماده» چند ستون و فیلتر نصب‌شدنی هست که هرکدام همان الگوهای این مقاله را دارند. یکی را نصب کنید، بازش کنید و خط‌به‌خط بخوانید — فهرست کاملشان با توضیح هر تنظیم در فرمول‌های آمادهٔ دیده‌بان است.

دو) نمونه‌های آمادهٔ کد را بخوانید. نمونه کدهای کاربردی ستون و نمونه کدهای فیلترنویسی ده‌ها فرمول کوتاه دارند که می‌توانید مستقیم کپی کنید و تغییر بدهید.

سه) کار را به یک هوش مصنوعی بسپارید. اگر می‌دانید چه می‌خواهید ولی نمی‌دانید چطور بنویسیدش، پرامپت آمادهٔ فرمول‌نویسی کل مرجع موتور را در قالب یک متن قابل‌کپی دارد: آن را به ChatGPT یا Claude بدهید و بعد خواسته‌تان را توصیف کنید. با دانستن همین دستورها می‌توانید نتیجه‌اش را بخوانید، بسنجید و اصلاحش کنید — که دقیقاً همان چیزی است که یک نسخهٔ اولِ تولیدشده لازم دارد.

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

جمع‌بندی

زبان فرمول‌نویسی آپشن‌باز جاوااسکریپت است و برای استفاده از آن لازم نیست برنامه‌نویس باشید. عملاً با چند دستور می‌شود بیشتر کارها را کرد: متغیر برای نگه داشتن مقدار، if و شرط کوتاه برای تصمیم‌گیری، آرایه برای چیدن خروجی، حلقه برای وقتی که به کل زنجیره نیاز دارید، و تابع برای اینکه یک محاسبه را دو بار ننویسید. مهم‌ترین چیزی که از این مقاله باید همراهتان بماند سه‌تاست: بدنهٔ چندخطی return می‌خواهد، فیلتر فقط بله/خیر برمی‌گرداند، و قبل از هر محاسبه‌ای باید مطمئن شوید داده‌اش خالی نیست.

بهترین جای تمرین، خود دیده‌بان است: یک ستون آماده نصب کنید، کدش را باز کنید و یک عدد را عوض کنید تا ببینید جدول چطور تغییر می‌کند. دیده‌بان آپشن را باز کنید (راهنمای دیده‌بان) و از دکمهٔ «فرمول نویسی» شروع کنید.

مقالات مرتبط

راهنمای فرمول‌نویسی و استراتژی‌های آماده در دیده‌بان آپشن

آموزش سیستم فرمول‌نویسی دیده‌بان: کارگاه شخصی و کتابخانه استراتژی‌های آماده اختیار معامله — هر دو با همان موتور فرمول؛ افزودن به جدول، فیلتر و میزکار.

ستون محاسباتی در دیده‌بان | ساخت ستون با فرمول‌نویسی و مثال

چطور در دیده‌بان آپشن‌باز ستون محاسباتی بسازید: از دکمه فرمول‌نویسی تا نوع ستون، return، افزودن به جدول، و چند مثال عملی (اسپرد، ارزش ذاتی، فاصله تا اعمال، دلتا).

نمونه کدهای کاربردی در ایجاد ستون

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

نمونه کدهای کاربردی فیلترنویسی دیده‌بان اختیار معامله

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

دستور العمل ایجاد ستون و فیلتر با رابط گرافیکی

این راهنما به شما کمک می‌کند فرمول‌های معاملاتی خود را طوری بنویسید که در حین معاملات، بتوانید به راحتی و بدون نیاز به تغییر کد، از طریق یک رابط گرافیکی ساده ساختار کد و خروجی را تغییر دهید

مدیریت خروجی و فیلتر فرمول | راهنمای تنظیمات ویژوال دیده‌بان

آموزش گام‌به‌گام طراحی تنظیمات ویژوال: آیکن تنظیمات، کنترل‌های عدد، تیک، لیست کشویی، چندانتخابی، مرتب‌سازی و ترتیب چیدمان ستون‌ها.

فرمول‌های آماده دیده‌بان اختیار معامله | ستون و فیلتر آپشن بدون کدنویسی

فهرست کامل ستون‌ها و فیلترهای آماده دیده‌بان اختیار معامله در آپشن‌باز: نصب بدون کدنویسی، تنظیمات هر فرمول، و اینکه هر کدام چه چیزی از بازار آپشن را نشان می‌دهد.

فرمول‌نویسی با هوش مصنوعی | پرامپت اختصاصی و مرجع کامل توابع

پرامپت آماده و چیت‌شیت جامع تمام توابع، فیلدها و ساختار موتور فرمول‌نویسی دیده‌بان برای کپی و ارسال به ChatGPT، Claude و Cursor.

ایجاد فیلدهای شخصی و دسترسی به آنها در فرمول‌نویسی

آموزش ساخت پرتفوی اختصاصی، تعریف فیلدهای شخصی (تعداد، قیمت خرید/فروش، یادداشت) و دسترسی پویا به آن‌ها در فرمول‌ها و ستون‌های دیده‌بان.

ستون محاسباتی نمودار استراتژی | فرمول‌نویسی روی موقعیت‌های اختیار معامله

ساخت ستون دلخواه در جدول موقعیت‌های نمودار استراتژی آپشن‌باز: فیلدهای position و strategy، بیش از 50 مثال آماده شامل جمع و تفریق بین سطرها با positions، قیمت خریدار/فروشنده بر اساس جهت موقعیت، یونانی‌ها، سربه‌سر و بازده روی وجه تضمین.

راهنمای دیده‌بان آپشن‌باز | فیلتر و فرمول‌نویسی

راهنمای جامع دیده‌بان آپشن‌باز: جدول زنده قراردادها، فیلتر سریع روی سرستون (سربه‌سر، IV و …)، پنل فیلتر، فرمول‌نویسی، آلارم و اتصال به نمودار استراتژی.

راهنمای جامع نوسان‌پذیری و تلاطم ضمنی IV و تلاطم تاریخی HV در معاملات آپشن

راهنمای IV و HV در آپشن — تفاوت نوسان ضمنی و تاریخی، تفسیر گران/ارزان بودن پرمیوم و فیلتر قراردادها در دیده‌بان آپشن‌باز.

دیدگاه‌ها و پرسش‌ها

ثبت پرسش/نظر شما

پرسش‌ها و نظرات کاربران

هنوز نظری ثبت نشده است.