(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{"TE/p":function(e,t,n){"use strict";n.r(t),n.d(t,"_frontmatter",(function(){return i})),n.d(t,"default",(function(){return d}));var a=n("Fcif"),l=n("dV/x"),r=(n("mXGw"),n("/FXl")),b=n("TjRS");n("l1C2");const c=["components"],i={};void 0!==i&&i&&i===Object(i)&&Object.isExtensible(i)&&!Object.prototype.hasOwnProperty.call(i,"__filemeta")&&Object.defineProperty(i,"__filemeta",{configurable:!0,value:{name:"_frontmatter",filename:"src/components/en/Scripting.mdx"}});const o={_frontmatter:i},p=b.a;function d(e){let{components:t}=e,n=Object(l.a)(e,c);return Object(r.b)(p,Object(a.a)({},o,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h1",{id:"-api-for-custom-indicators"},"๐Ÿ“˜ API for Custom Indicators"),Object(r.b)("h2",{id:"-ai-for-generation-of-custom-indicators"},"๐Ÿค– AI for generation of Custom Indicators"),Object(r.b)("p",null,"Use the following document with ChatGPT, Claude, Gemini or other LLMs:"),Object(r.b)("p",null,"๐Ÿ‘‰ ",Object(r.b)("a",{parentName:"p",href:"../../public/AI.txt"},"AI.txt")),Object(r.b)("p",null,"Example Prompt:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre"},"Read the attached [AI.txt] https://mobchart.com/docs/public/AI.txt file and use it as the only reference for the MobChart scripting API.\n\nCreate a custom indicator that plots a 20-period EMA and a 50-period EMA on the chart. Color the candles green when EMA20 is above EMA50 and red otherwise.\n\nUse only the documented API. Do not invent functions. Return the complete indicator code.\n")),Object(r.b)("h2",{id:"-security-principles-and-current-limitations"},"๐Ÿ”’ Security Principles and Current Limitations"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"The script execution environment is based on a secure JavaScript sandbox. "),Object(r.b)("li",{parentName:"ul"},"Your script has an execution time limit of ",Object(r.b)("inlineCode",{parentName:"li"},"1500ms"),"."),Object(r.b)("li",{parentName:"ul"},"The length of the returned data array must not exceed ",Object(r.b)("strong",{parentName:"li"},"1500"),". Therefore, the indicator cannot extend deeper than ",Object(r.b)("strong",{parentName:"li"},"1500 candles"),"."),Object(r.b)("li",{parentName:"ul"},"You can make up to ",Object(r.b)("strong",{parentName:"li"},"8 data source requests")," within a single indicator.")),Object(r.b)("hr",null),Object(r.b)("h2",{id:"๏ธ-indicator-development"},"โš’๏ธ Indicator Development"),Object(r.b)("p",null,"Indicator development is done within a separate widget, which can be placed next to the chart where the indicator will be enabled."),Object(r.b)("img",{src:"../../public/code_chart_widgets.png"}),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-creating-an-indicator"},"๐Ÿงญ Creating an Indicator"),Object(r.b)("h3",{id:"definetitle-description-type-ispublic-ispubliccode"},Object(r.b)("inlineCode",{parentName:"h3"},"define(title, description, type, isPublic, isPublicCode)")),Object(r.b)("p",null,"Registers the indicator in the system."),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Parameter"),Object(r.b)("th",{parentName:"tr",align:null},"Type"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"title")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")),Object(r.b)("td",{parentName:"tr",align:null},"Indicator name")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"description")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")),Object(r.b)("td",{parentName:"tr",align:null},"Short description")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"type")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"'onchart'")," ","|"," ",Object(r.b)("inlineCode",{parentName:"td"},"'offchart'")),Object(r.b)("td",{parentName:"tr",align:null},"Indicator placement (on chart or in a separate panel)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"isPublic")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"true")," ","|"," ",Object(r.b)("inlineCode",{parentName:"td"},"false")),Object(r.b)("td",{parentName:"tr",align:null},"Whether the indicator is public")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"isPublicCode")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"true")," ","|"," ",Object(r.b)("inlineCode",{parentName:"td"},"false")),Object(r.b)("td",{parentName:"tr",align:null},"Whether the source code is public")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'define("My Indicator", "Shows EMA line", "onchart", true, false);\n')),Object(r.b)("hr",null),Object(r.b)("p",null,"Indicator placement for ",Object(r.b)("strong",{parentName:"p"},"onchart")," and ",Object(r.b)("strong",{parentName:"p"},"offchart"),":"),Object(r.b)("img",{src:"../../public/onchart_offchart.png"}),Object(r.b)("h2",{id:"๏ธ-input-parameters"},"โš™๏ธ Input Parameters"),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"input"))," and ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"style"))," classes allow you to create user-configurable settings (similar to ",Object(r.b)("inlineCode",{parentName:"p"},"input()")," in PineScript)."),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number(title, defaultValue, min, max, step)")),Object(r.b)("td",{parentName:"tr",align:null},"Numeric input")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"range(title, defaultValue, min, max, step)")),Object(r.b)("td",{parentName:"tr",align:null},"Range input")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"select(title, defaultValue, values)")),Object(r.b)("td",{parentName:"tr",align:null},"Dropdown selection")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"color(title, defaultValue)")),Object(r.b)("td",{parentName:"tr",align:null},"Color picker")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"boolean(title, defaultValue)")),Object(r.b)("td",{parentName:"tr",align:null},"Boolean input")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example (input) for main parameters:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const length = input.number("Period", 14, 1, 100, 1);\nconst type = input.select("Type", \'sma\', [\'sma\', \'ema\']);\nconst color = input.color("Line Color", "#FF0000");\n')),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Or (style) for visual parameters:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const length = style.number("Size", 14, 1, 100, 1);\nconst color = style.select("Background Color", \'#FF0000\', ["#FF0000", "#AA0000", "#BB0000"]);\nconst color = style.color("Background Color", "#FF0000");\n')),Object(r.b)("img",{src:"../../public/input_style.png"}),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-data-sources"},"๐Ÿงฎ Data Sources"),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"source"))," class is used to fetch market data from the server side. "),Object(r.b)("p",null,"We ",Object(r.b)("strong",{parentName:"p"},"do not always")," guarantee that the returned data exactly matches the candles visible on the chart."),Object(r.b)("p",null,"For example, during script execution, ",Object(r.b)("strong",{parentName:"p"},"ohlcv()")," might return 400 candles, while ",Object(r.b)("strong",{parentName:"p"},"depths()")," might return only 300 limit orders (for the heatmap).",Object(r.b)("br",{parentName:"p"}),"\n","Use additional checks for the ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"startTime"))," parameter in your code."),Object(r.b)("p",null,"Currently, the length of the returned data array must not exceed ",Object(r.b)("strong",{parentName:"p"},"1500"),".",Object(r.b)("br",{parentName:"p"}),"\n","Therefore, the indicator cannot extend deeper than ",Object(r.b)("strong",{parentName:"p"},"1500 candles"),"."),Object(r.b)("p",null,"Currently, ",Object(r.b)("strong",{parentName:"p"},"8 data source requests")," are allowed within a single indicator."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"exchange"),", ",Object(r.b)("inlineCode",{parentName:"p"},"ticker"),", and ",Object(r.b)("inlineCode",{parentName:"p"},"timeframe")," parameters are by default tied to the current chart where the indicator is opened.",Object(r.b)("br",{parentName:"p"}),"\n","The ",Object(r.b)("inlineCode",{parentName:"p"},"lookback")," parameter (history of bars from the current date, but ",Object(r.b)("strong",{parentName:"p"},"no more than 1500"),") can be set at your discretion."),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},'"ohlcv" Method'),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"ohlcv(exchange, ticker, timeframe, lookback?)")),Object(r.b)("td",{parentName:"tr",align:null},"Candle data")))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'[\n {\n "open": 115886.17,\n "high": 115911.96,\n "low": 115764.27,\n "close": 115815.16,\n "volume": 228.41528,\n "startTime": 1757699100000\n },\n {...},\n ...\n] \n')),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},'"depths" Method'),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"depths(exchange, ticker, timeframe, lookback?)")),Object(r.b)("td",{parentName:"tr",align:null},"Limit orders")))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'[\n {\n "data": {\n "asks": {\n "109425": 5.467,\n "109495": 3.564,\n ...\n },\n "bids": {\n "33000": 3.746,\n "35000": 16.49,\n ...\n }\n },\n "startTime": 1757699100000\n },\n {...},\n ...\n]\n\n')),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},'"clusters" Method'),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"clusters(exchange, ticker, timeframe, lookback?)")),Object(r.b)("td",{parentName:"tr",align:null},"Cluster data")))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'[\n {\n "data": {\n "totalBuy": 16053385,\n "totalSell": 20490989,\n "0.8654": { "buy": 286845, "sell": 336689 },\n "0.8653": { "buy": 271848, "sell": 259167 },\n "0.8652": { "buy": 318814, "sell": 373497 },\n ...\n },\n "startTime": 1757699100000\n },\n {...},\n ...\n]\n\n')),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},'"liquidations" Method'),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"liquidations(exchange, ticker, timeframe, lookback?)")),Object(r.b)("td",{parentName:"tr",align:null},"Liquidations data")))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'[\n {\n "data": {\n "totalBuy": 16053385,\n "totalSell": 20490989,\n "0.8654": { "buy": 286845, "sell": 336689 },\n "0.8653": { "buy": 271848, "sell": 259167 },\n "0.8652": { "buy": 318814, "sell": 373497 },\n ...\n },\n "startTime": 1757699100000\n },\n {...},\n ...\n]\n\n')),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},'"moreData" Method'),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"moreData(exchange, ticker, timeframe, lookback?)")),Object(r.b)("td",{parentName:"tr",align:null},"Some additional data")))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'[\n { \n "data": {\n "FR": 0.00003777, // Funding Rate\n "OI": { // Open Interest Candle\n "open": 85645.708,\n "close": 83496.225,\n "high": 85801.04,\n "low": 83397.918\n },\n "LS": { "l": 0.5426, "s": 0.4574 }, // Long/Short Ratio\n "taLS": { "l": 0.552, "s": 0.448 }, // Top Traders Account Ratio\n "tpLS": { "l": 0.5996, "s": 0.4004 } // Top Traders Position Ratio\n },\n "startTime": 1757699100000\n },\n {...},\n ...\n]\n\n')),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},"const candles = source.ohlcv(); // The exchange, ticker, and timeframe parameters default to the current chart.\nconst closes = candles.map(c => c.close);\n")),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-global-variables"},"๐ŸŒ Global Variables"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Variable"),Object(r.b)("th",{parentName:"tr",align:null},"Description"),Object(r.b)("th",{parentName:"tr",align:null},"Example"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"currentExchange")),Object(r.b)("td",{parentName:"tr",align:null},"Current exchange on the chart"),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"binance"),", ",Object(r.b)("inlineCode",{parentName:"td"},"binanceFutures"),", ",Object(r.b)("inlineCode",{parentName:"td"},"coinbase"),", ...")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"currentTicker")),Object(r.b)("td",{parentName:"tr",align:null},"Current ticker on the chart (format depends on the exchange)"),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"BTCUSDT"),", ",Object(r.b)("inlineCode",{parentName:"td"},"ADA-USD"),", ",Object(r.b)("inlineCode",{parentName:"td"},"BTC/USDC"),", ...")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"currentTimeframe")),Object(r.b)("td",{parentName:"tr",align:null},"Current timeframe on the chart"),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"1m"),", ",Object(r.b)("inlineCode",{parentName:"td"},"5m"),", ",Object(r.b)("inlineCode",{parentName:"td"},"15m"),", ...")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},"const candles = source.ohlcv(currentExchange, currentTicker, currentTimeframe);\nconst closes = candles.map(c => c.close);\n")),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-logging"},"๐Ÿงพ Logging"),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"logger"))," class is used for outputting information and debugging."),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"log(...args)")),Object(r.b)("td",{parentName:"tr",align:null},"Adds an entry to the log (with limits on length and quantity)")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const candles = source.ohlcv();\nlogger.log("First candle:", candles?.[0]);\n')),Object(r.b)("img",{src:"../../public/code_editor_log.png"}),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-visualization"},"๐Ÿ“ˆ Visualization"),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"plot"))," class is responsible for drawing graphical elements and data series."),Object(r.b)("h3",{id:"-geometric-shapes"},"๐Ÿ”น Geometric Shapes"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"box(title, date1, price1, date2, price2, fill, opacity, stroke, strokeOpacity, strokeWidth)")),Object(r.b)("td",{parentName:"tr",align:null},"Rectangle")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"square(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth)")),Object(r.b)("td",{parentName:"tr",align:null},"Square")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"diamond(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth)")),Object(r.b)("td",{parentName:"tr",align:null},"Diamond")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"triangle(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth)")),Object(r.b)("td",{parentName:"tr",align:null},"Triangle")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"circle(title, date1, price1, radius = 10, fill, opacity, stroke, strokeOpacity, strokeWidth)")),Object(r.b)("td",{parentName:"tr",align:null},"Circle")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"text(title, value, date1, price1, fontSize, fill, opacity)")),Object(r.b)("td",{parentName:"tr",align:null},"Text on chart")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"straightLine(title, date1, price1, date2, price2, stroke, strokeOpacity, strokeWidth, strokeDasharray)")),Object(r.b)("td",{parentName:"tr",align:null},"Straight line")))),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Parameter"),Object(r.b)("th",{parentName:"tr",align:null},"Data Type"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"title")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")),Object(r.b)("td",{parentName:"tr",align:null},"Element name (unique identifier on the chart)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"date1")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")," (timestamp, ms)"),Object(r.b)("td",{parentName:"tr",align:null},"Starting timestamp")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"price1")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Starting price (Y-axis coordinate)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"date2")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")," (timestamp, ms)"),Object(r.b)("td",{parentName:"tr",align:null},"Ending timestamp (for lines and rectangles)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"price2")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Ending price (for lines and rectangles)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"size")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Shape size (in pixels)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"radius")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Circle radius (default 10)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"fill")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")," (hex, e.g., ",Object(r.b)("inlineCode",{parentName:"td"},'"#FF0000"'),")"),Object(r.b)("td",{parentName:"tr",align:null},"Fill color of the shape")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"opacity")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")," (0โ€“1)"),Object(r.b)("td",{parentName:"tr",align:null},"Fill opacity")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"stroke")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")," (hex, e.g., ",Object(r.b)("inlineCode",{parentName:"td"},'"#000000"'),")"),Object(r.b)("td",{parentName:"tr",align:null},"Stroke color")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"strokeOpacity")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")," (0โ€“1)"),Object(r.b)("td",{parentName:"tr",align:null},"Stroke opacity")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"strokeWidth")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Stroke width (in pixels)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"strokeDasharray")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"array")," (e.g., ",Object(r.b)("inlineCode",{parentName:"td"},"[5,5]"),")"),Object(r.b)("td",{parentName:"tr",align:null},"Dashed line style")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"fontSize")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number")),Object(r.b)("td",{parentName:"tr",align:null},"Text size (in pixels)")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"value")),Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"string")),Object(r.b)("td",{parentName:"tr",align:null},"Text value (for ",Object(r.b)("inlineCode",{parentName:"td"},"text")," method)")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'plot.text("Text object", "Hello world!", 1757699100000, 115000, 10, "#00C8FF", 0.5);\nplot.straightLine(`${namePrefix} Open`, level.timeStart, level.open, level.timeEnd, level.open, color);\nplot.circle(`${namePrefix} High`, level.timeStart, level.high, 3, color);\n')),Object(r.b)("p",null,"No more than ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"3000"))," shapes can be displayed on the chart."),Object(r.b)("hr",null),Object(r.b)("h3",{id:"-data-series"},"๐Ÿ”น Data Series"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"lineSeries(title, values, stroke, strokeOpacity, strokeWidth, strokeDasharray)")),Object(r.b)("td",{parentName:"tr",align:null},"Line chart")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"barSeries(title, values, fill, opacity)")),Object(r.b)("td",{parentName:"tr",align:null},"Bar chart")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"candleSeries(title, openValues, closeValues, highValues, lowValues, fill, opacity)")),Object(r.b)("td",{parentName:"tr",align:null},"Candles")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'plot.lineSeries("EMA", ta.ema(closes, 20), "#00C8FF");\nplot.barSeries("Premium %", premiumPercents, ((d) => d > 0 ? color1 : color2), 1);\nplot.candleSeries(\n "Candles",\n opens, closes, highs, lows,\n (v, i) => {\n return opens?.[i] > closes?.[i] ? colorBuy : colorSell\n }\n);\n')),Object(r.b)("p",null,"No more than ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"10"))," data series can be displayed on the chart."),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-technical-analysis"},"๐Ÿ“Š Technical Analysis"),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"ta"))," class includes a set of functions similar to PineScript."),Object(r.b)("h3",{id:"-helper-functions"},"๐Ÿ”น Helper Functions"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"highest(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Highest value over a period")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"lowest(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Lowest value over a period")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"variance(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Variance")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"stdev(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Standard deviation")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"crossover(series1, series2)")),Object(r.b)("td",{parentName:"tr",align:null},"Checks for upward crossover")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"crossunder(series1, series2)")),Object(r.b)("td",{parentName:"tr",align:null},"Checks for downward crossover")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"cross(series1, series2)")),Object(r.b)("td",{parentName:"tr",align:null},"Any crossover")))),Object(r.b)("h3",{id:"-moving-averages"},"๐Ÿ”น Moving Averages"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"sma(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Simple moving average")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"ema(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Exponential moving average")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"wma(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Weighted moving average")))),Object(r.b)("h3",{id:"-indicators"},"๐Ÿ”น Indicators"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"rsi(values, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Relative Strength Index")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"macd(values, fast, slow, signalPeriod)")),Object(r.b)("td",{parentName:"tr",align:null},"MACD")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"bollinger(values, period, mult)")),Object(r.b)("td",{parentName:"tr",align:null},"Bollinger Bands")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"stoch(highs, lows, closes, period, smoothK, smoothD)")),Object(r.b)("td",{parentName:"tr",align:null},"Stochastic Oscillator")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"atr(highs, lows, closes, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Average True Range")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"adx(highs, lows, closes, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Average Directional Index")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"cci(highs, lows, closes, period)")),Object(r.b)("td",{parentName:"tr",align:null},"Commodity Channel Index")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"vwap(highs, lows, closes, volumes)")),Object(r.b)("td",{parentName:"tr",align:null},"Volume Weighted Average Price")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const candles = source.ohlcv();\nconst closes = candles.map(c => c.close);\nconst rsiValues = ta.rsi(closes, 14);\nplot.lineSeries("RSI", rsiValues, "#00C8FF");\n')),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-alerts"},"๐Ÿ”” Alerts"),Object(r.b)("p",null,"Users can create alerts for your indicator from the ",Object(r.b)("strong",{parentName:"p"},"Alerts")," tab in the indicator settings on the chart.\nAlerts are checked on the server side every ",Object(r.b)("strong",{parentName:"p"},"30 seconds"),", notifications are sent to ",Object(r.b)("strong",{parentName:"p"},"Telegram")," and/or a user defined ",Object(r.b)("strong",{parentName:"p"},"Webhook URL"),"."),Object(r.b)("h3",{id:"๏ธ-alert-settings--alertinput"},"โš™๏ธ Alert Settings โ€” ",Object(r.b)("inlineCode",{parentName:"h3"},"alertInput")),Object(r.b)("p",null,"The ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"alertInput"))," class declares alert settings. It works exactly like ",Object(r.b)("inlineCode",{parentName:"p"},"input"),", but the fields are shown in the ",Object(r.b)("strong",{parentName:"p"},"Alerts")," tab and every user configures their own values for their alert."),Object(r.b)("p",null,"Scripts without ",Object(r.b)("inlineCode",{parentName:"p"},"alertInput")," declarations can not be used for alerts."),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"number(title, defaultValue, min, max, step)")),Object(r.b)("td",{parentName:"tr",align:null},"Numeric input")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"range(title, defaultValue, min, max, step)")),Object(r.b)("td",{parentName:"tr",align:null},"Range input")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"select(title, defaultValue, values)")),Object(r.b)("td",{parentName:"tr",align:null},"Dropdown selection")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"color(title, defaultValue)")),Object(r.b)("td",{parentName:"tr",align:null},"Color picker")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"boolean(title, defaultValue)")),Object(r.b)("td",{parentName:"tr",align:null},"Boolean input")))),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const alertVolumeThreshold = alertInput.number("Volume threshold", 1000, 0, 10000000, 1);\n')),Object(r.b)("h3",{id:"-firing-alerts--alertfire"},"๐Ÿšจ Firing Alerts โ€” ",Object(r.b)("inlineCode",{parentName:"h3"},"alert.fire")),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",{parentName:"tr",align:null},"Method"),Object(r.b)("th",{parentName:"tr",align:null},"Description"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",{parentName:"tr",align:null},Object(r.b)("inlineCode",{parentName:"td"},"fire(title, message, date)")),Object(r.b)("td",{parentName:"tr",align:null},"Fires an alert notification")))),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"All three parameters are ",Object(r.b)("strong",{parentName:"li"},"required")," โ€” a call with a missing ",Object(r.b)("inlineCode",{parentName:"li"},"title"),", ",Object(r.b)("inlineCode",{parentName:"li"},"message")," or ",Object(r.b)("inlineCode",{parentName:"li"},"date")," is skipped (a warning is written to the log)."),Object(r.b)("li",{parentName:"ul"},"Keep the alert ",Object(r.b)("strong",{parentName:"li"},"title constant"),", do not generate unique titles. Each title fires only once per run (max ",Object(r.b)("strong",{parentName:"li"},"20")," titles per run)."),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"date")," is the candle ",Object(r.b)("inlineCode",{parentName:"li"},"startTime")," the signal belongs to: the same title notifies again only when it fires for a ",Object(r.b)("strong",{parentName:"li"},"newer")," candle. Signals from candles older than the moment the user created their alert are ignored (anti-spam).")),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"Example:")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'if (candle.volume > alertVolumeThreshold) {\n alert.fire("High volume", `vol ${candle.volume}`, candle.startTime);\n}\n')),Object(r.b)("h3",{id:"-shape-alerts--plotshapealert"},"๐Ÿ“ Shape Alerts โ€” ",Object(r.b)("inlineCode",{parentName:"h3"},"plot.(...).alert(...)")),Object(r.b)("p",null,"All geometric shapes (",Object(r.b)("inlineCode",{parentName:"p"},"box"),", ",Object(r.b)("inlineCode",{parentName:"p"},"square"),", ",Object(r.b)("inlineCode",{parentName:"p"},"diamond"),", ",Object(r.b)("inlineCode",{parentName:"p"},"triangle"),", ",Object(r.b)("inlineCode",{parentName:"p"},"circle"),", ",Object(r.b)("inlineCode",{parentName:"p"},"straightLine"),", ",Object(r.b)("inlineCode",{parentName:"p"},"text"),") return a handle with an ",Object(r.b)("inlineCode",{parentName:"p"},".alert()")," method.\nThe alert fires with the shape's ",Object(r.b)("inlineCode",{parentName:"p"},"date1")," automatically, so the anti-spam logic works without extra code โ€” this is the recommended way for per-candle signals."),Object(r.b)("p",null,"Two forms:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'// simple: fires every time the shape is plotted for a new date\nplot.box(...).alert("High volume", `vol ${candle.volume}`);\n\n// callback: return nothing to skip, [title, message] to fire\nplot.box(...).alert((shape) => {\n if (candle.volume > alertVolumeThreshold)\n alert.fire("High volume", `vol ${candle.volume}`, candle.startTime);\n});\n')),Object(r.b)("p",null,"The callback receives the shape data (",Object(r.b)("inlineCode",{parentName:"p"},"date1"),", ",Object(r.b)("inlineCode",{parentName:"p"},"price1"),", ",Object(r.b)("inlineCode",{parentName:"p"},"date2"),", ",Object(r.b)("inlineCode",{parentName:"p"},"price2"),", ...)."),Object(r.b)("h3",{id:"-series-alerts--plotseriesalert"},"๐Ÿ“ˆ Series Alerts โ€” ",Object(r.b)("inlineCode",{parentName:"h3"},"plot.(...).alert(...)")),Object(r.b)("p",null,"Data series (",Object(r.b)("inlineCode",{parentName:"p"},"lineSeries"),", ",Object(r.b)("inlineCode",{parentName:"p"},"barSeries"),", ",Object(r.b)("inlineCode",{parentName:"p"},"candleSeries"),") also return the ",Object(r.b)("inlineCode",{parentName:"p"},".alert()")," handle.\nThe callback receives the ",Object(r.b)("strong",{parentName:"p"},"latest data point")," and the latest candle date, the alert fires with that date."),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"lineSeries")," / ",Object(r.b)("inlineCode",{parentName:"li"},"barSeries")," โ€” the callback receives the last ",Object(r.b)("strong",{parentName:"li"},"value")," (a number)"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"candleSeries")," โ€” the callback receives the last candle ",Object(r.b)("inlineCode",{parentName:"li"},"{open, close, high, low}"))),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'plot.lineSeries("RSI", rsiValues, color).alert((rsi, date) => {\n if (rsi > alertRsiThreshold) alert.fire("RSI high", `RSI ${rsi.toFixed(1)}`, latestCandle.startTime);\n});\n')),Object(r.b)("p",null,"A condition that stays true notifies once per ",Object(r.b)("strong",{parentName:"p"},"new candle"),". For one-time signals use crossover-style conditions (",Object(r.b)("inlineCode",{parentName:"p"},"ta.crossover"),")."),Object(r.b)("h3",{id:"-full-example"},"๐Ÿงฉ Full Example"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const title = "Volume alerts";\nconst description = "Shows boxes on high-volume candles";\ndefine(title, description, "onchart", true, true);\n\nconst color = style.color("Color", "#00C8FF");\nconst volumeThreshold = input.number("Volume threshold", 1000, 0, 10000000, 1);\nconst alertVolumeThreshold = alertInput.number("Alert volume threshold", 5000, 0, 10000000, 1);\nconst alertCloseThreshold = alertInput.number("Alert close threshold", 100000, 0, 10000000, 1);\n\nconst candles = source.ohlcv();\nconst latestCandle = candles.at(-1);\nconst closes = candles.map(c => c.close);\n\n// series alert: checks the latest close\nplot.lineSeries("Closes", closes, color).alert((close, date) => {\n if (close > alertCloseThreshold) alert.fire("Close above threshold", `close ${close}`, latestCandle.startTime);\n});\n\nfor (let i = 0; i < candles.length; i++) {\n const candle = candles[i];\n\n if (candle.volume > volumeThreshold) {\n const right = i < candles.length - 1 ? candles[i + 1].startTime : candle.startTime + 60000;\n\n // shape alert: checked against the user\'s alert threshold\n plot.box(`Volume ${i}`, candle.startTime, candle.high, right, candle.low, "#00C8FF", 0.3)\n .alert(() => {\n if (candle.volume > alertVolumeThreshold)\n alert.fire("High volume", `vol ${candle.volume}`, candle.startTime);\n });\n }\n}\n')),Object(r.b)("hr",null),Object(r.b)("h2",{id:"-examples-of-indicators"},"๐Ÿง  Examples of indicators"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const title = "Your first indicator";\nconst description = "Shows closes lines on the chart";\nconst indicatorType = "onchart";\n\ndefine(title, description, type, true, true);\n\nconst color = input.color("Line Color", "#00C8FF");\nconst candles = source.ohlcv();\nconst closes = candles.map(c => c.close);\nplot.lineSeries("Closes", closes, color);\n\n')),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'define("Example Indicator", "Demonstrates basic plotting", "onchart", true, true);\n\nconst color = input.color("Line Color", "#00FF99");\nconst candles = source.ohlcv();\nconst closes = candles.map(c => c.close);\n\nconst ema20 = ta.ema(closes, 20);\nplot.lineSeries("EMA 20", ema20, color);\n\n')),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const title = "Colored Volume Bars"; \nconst description = "Volumes colored based on candle direction."; \nconst indicatorType = "onchart"; \nconst isPublic = true; \nconst isPublicCode = true; \n\ndefine(title, description, indicatorType, isPublic, isPublicCode); \n\n// Get OHLC candles\nconst candles = source.ohlcv(); \n\nconst colorUp = style.color("Color 1", "#2BB462"); // Greenish color for rising prices\nconst colorDown = style.color("Color 2", "#FB4C51"); // Reddish color for falling prices\nconst volumes = candles.map(candle => candle.volume); \n\nplot.barSeries("Volume", volumes, (value, index) => {\n const currentCandle = candles[index]; \n return currentCandle.close >= currentCandle.open ? colorUp : colorDown; \n});\n\n')),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},"define('Coinbase Premium Index', 'Coinbase Premium Index', 'offchart', true, false);\n\nconst color1 = style.color(\"Color 1\", \"#2BB462\");\nconst color2 = style.color(\"Color 2\", \"#FB4C51\");\n\n// Get OHLC candles\nconst cbCandles = source.ohlcv('coinbase', 'BTC-USD');\nconst binanceCandles = source.ohlcv('binance', 'BTCUSDT');\n\n// Extract closes\nconst cbCloses = cbCandles.map(c => c.close);\nconst binanceCloses = binanceCandles.map(c => c.close);\n\n// --- Coinbase Premium Index calculation ---\nconst premiumPercent = cbCloses.map((cb, i) => {\n const b = binanceCloses[i];\n return ((cb - b) / b) * 100;\n});\n\n// Plot premium index\nplot.barSeries(\"Premium %\", premiumPercent, ((d) => d > 0 ? color1 : color2)) // Percentage difference\n\n")),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-js"},'const title = "Candles";\nconst description = "Simple candles draw";\nconst indicatorType = "offchart";\nconst isPublic = true;\nconst isPublicCode = true;\ndefine(title, description, indicatorType, isPublic, isPublicCode);\n\nconst colorBuy = style.color("Buy Color", "#2BB462");\nconst colorSell = style.color("Sell Color", "#7a3d3f");\nconst candles = source.ohlcv();\nconst closes = candles.map(c => c.close);\nconst opens = candles.map(c => c.open);\nconst highs = candles.map(c => c.high);\nconst lows = candles.map(c => c.low);\nplot.candleSeries(\n "Candles",\n opens, closes, highs, lows,\n (v, i) => {\n return opens?.[i] > closes?.[i] ? colorBuy : colorSell\n }\n);\n\n')))}void 0!==d&&d&&d===Object(d)&&Object.isExtensible(d)&&!Object.prototype.hasOwnProperty.call(d,"__filemeta")&&Object.defineProperty(d,"__filemeta",{configurable:!0,value:{name:"MDXContent",filename:"src/components/en/Scripting.mdx"}}),d.isMDXComponent=!0}}]); //# sourceMappingURL=component---src-components-en-scripting-mdx-3ff7b1640c94defe90cd.js.map