openalgo-charts
Version:
From-scratch, dependency-free canvas charting engine for OpenAlgo: professional-grade interactive rendering, advanced on-chart trading, and a one-call widget tier that adds the toolbar, drawing rail, dialogs and shortcuts.
2 lines (1 loc) • 22 kB
JavaScript
if("undefined"==typeof OpenAlgoCharts)throw new Error("openalgo-charts.transform.standalone.js needs openalgo-charts.standalone.js loaded before it");this.OpenAlgoCharts=this.OpenAlgoCharts||{},this.OpenAlgoCharts.transform=function(e,t){"use strict";function i(e,t,i){const r=e.boxSize;return"number"==typeof r&&r>0?r:void 0!==t.boxSize&&t.boxSize>0?t.boxSize:i}function r(e,t,r,s,o,n,l=1/0){if(0===t.length)return;const h=function(e){let t=1/0;for(const{bar:i}of e){const e=i.high-i.low;e>0&&e<t&&(t=e)}return Number.isFinite(t)?t:0}(t),a=Math.max(3,Math.floor(s*o*.7))/2,u=l===1/0?1/0:l*o;e.save(),e.lineWidth=Math.max(1,Math.floor(o));for(const{x:s,bar:l}of t){const t=i(l,n,h);if(!(t>0))continue;const c=Math.round(l.low/t),b=Math.round(l.high/t)-1;if(b<c)continue;if(b-c+1>4e3)continue;const _=l.close>=l.open;e.strokeStyle=_?n.upColor??"#26a69a":n.downColor??"#ef5350";const f=s*o;for(let i=c;i<=b;i++){const s=r((i+1)*t)*o,n=r(i*t)*o;n<0||s>u||(e.beginPath(),_?(e.moveTo(f-a,s),e.lineTo(f+a,n),e.moveTo(f+a,s),e.lineTo(f-a,n)):e.ellipse(f,(s+n)/2,a,Math.abs(n-s)/2,0,0,2*Math.PI),e.stroke())}}e.restore()}function s(e){return Object.assign(Object.create(Object.getPrototypeOf(e)),e)}function o(e){let t=-1/0;const i=[];for(const r of e){let e=r.time;e<=t&&(e=t+1),t=e,i.push(e===r.time?r:{...r,time:e})}return i}class n{constructor(){Object.defineProperty(this,"_prevOpen",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_prevClose",{enumerable:!0,configurable:!0,writable:!0,value:NaN})}reset(){this._prevOpen=NaN,this._prevClose=NaN}clone(){return s(this)}push(e){const t=(e.open+e.high+e.low+e.close)/4,i=Number.isNaN(this._prevOpen)?(e.open+e.close)/2:(this._prevOpen+this._prevClose)/2,r=Math.max(e.high,i,t),s=Math.min(e.low,i,t);return this._prevOpen=i,this._prevClose=t,[{time:e.time,open:i,high:r,low:s,close:t,volume:e.volume,oi:e.oi}]}}class l{constructor(e){if(Object.defineProperty(this,"_box",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_edge",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),e.boxSize<=0)throw new Error("openalgo-charts: Renko boxSize must be > 0");this._box=e.boxSize}reset(){this._edge=NaN}clone(){return s(this)}push(e){const t=e.close,i=[];if(Number.isNaN(this._edge))return this._edge=Math.floor(t/this._box)*this._box,i;for(;t>=this._edge+this._box;){const t=this._edge,r=this._edge+this._box;i.push({time:e.time,open:t,high:r,low:t,close:r}),this._edge=r}for(;t<=this._edge-this._box;){const t=this._edge,r=this._edge-this._box;i.push({time:e.time,open:t,high:t,low:r,close:r}),this._edge=r}return i}}class h{constructor(e){if(Object.defineProperty(this,"_range",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_cur",{enumerable:!0,configurable:!0,writable:!0,value:null}),e.range<=0)throw new Error("openalgo-charts: range must be > 0");this._range=e.range}reset(){this._cur=null}clone(){const e=s(this);return e._cur=null===this._cur?null:{...this._cur},e}push(e){const t=e.close,i=[];return null===this._cur?this._cur={time:e.time,open:t,high:t,low:t,close:t}:(this._cur.high=Math.max(this._cur.high,t),this._cur.low=Math.min(this._cur.low,t),this._cur.close=t,this._cur.time=e.time),this._cur.high-this._cur.low>=this._range&&(i.push(this._cur),this._cur=null),i}flush(){if(null===this._cur)return[];const e=this._cur;return this._cur=null,[e]}}class a{constructor(e={lines:3}){Object.defineProperty(this,"_n",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_lines",{enumerable:!0,configurable:!0,writable:!0,value:[]}),this._n=Math.max(1,e.lines)}reset(){this._lines=[]}clone(){const e=s(this);return e._lines=this._lines.slice(),e}push(e){const t=e.close;if(0===this._lines.length)return this._lines.push({open:t,close:t}),[];const i=this._lines.slice(-this._n);let r=-1/0,s=1/0;for(const e of i)r=Math.max(r,e.open,e.close),s=Math.min(s,e.open,e.close);const o=this._lines[this._lines.length-1];let n=null;return(t>r||t<s)&&(n={open:o.close,close:t}),null===n?[]:(this._lines.push(n),this._lines.length>this._n&&this._lines.splice(0,this._lines.length-this._n),[{time:e.time,open:n.open,high:Math.max(n.open,n.close),low:Math.min(n.open,n.close),close:n.close}])}}class u{constructor(e){Object.defineProperty(this,"_period",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_prevClose",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_sum",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_n",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_atr",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),this._period=Math.max(1,Math.floor(e))}reset(){this._prevClose=NaN,this._sum=0,this._n=0,this._atr=NaN}push(e){const t=Number.isNaN(this._prevClose)?e.high-e.low:Math.max(e.high-e.low,Math.abs(e.high-this._prevClose),Math.abs(e.low-this._prevClose));this._prevClose=e.close,this._n<this._period?(this._sum+=t,this._n+=1,this._atr=this._sum/this._n):this._atr=(this._atr*(this._period-1)+t)/this._period}value(){return this._atr}}class c{constructor(e){Object.defineProperty(this,"_reversal",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_method",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_mode",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_fixedBox",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_percent",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_atrMult",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_atr",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_box",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_dir",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_top",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_bot",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_time",{enumerable:!0,configurable:!0,writable:!0,value:0});const t=e.mode??"fixed";if(this._mode=t,this._reversal=Math.max(1,Math.floor(e.reversal??3)),this._method=e.method??"hl",this._fixedBox=e.boxSize??NaN,this._percent=e.percent??NaN,this._atrMult=e.atrMultiplier??1,this._atr=new u(e.atrPeriod??14),"fixed"===t&&!(this._fixedBox>0))throw new Error("openalgo-charts: P&F boxSize must be > 0");if("percent"===t&&!(this._percent>0))throw new Error("openalgo-charts: P&F percent must be > 0")}get boxSize(){return this._fixedBox}reset(){this._box=NaN,this._dir=0,this._top=NaN,this._bot=NaN,this._time=0,this._atr.reset()}clone(){const e=s(this);return Object.assign(e,{_atr:s(this._atr)}),e}_resolveBox(e){let t=NaN;if(t="fixed"===this._mode?this._fixedBox:"percent"===this._mode?Math.abs(e)*this._percent/100:this._atr.value()*this._atrMult,t>0&&Number.isFinite(t))return t;if(this._box>0)return this._box;const i=.01*Math.abs(e);return i>0?i:1}_column(){const e=this._box,t=this._bot*e,i=(this._top+1)*e,r=this._dir>=0;return{time:this._time,open:r?t:i,close:r?i:t,high:i,low:t,boxSize:e,boxes:this._top-this._bot+1}}push(e){"atr"===this._mode&&this._atr.push(e);const t="hl"===this._method,i=t?e.high:e.close,r=t?e.low:e.close;if(Number.isNaN(this._top)){this._box=this._resolveBox(e.close);const t=Math.floor(e.close/this._box);return this._top=t,this._bot=t,this._dir=0,this._time=e.time,[]}const s=Math.floor(i/this._box),o=Math.floor(r/this._box);if(0===this._dir){const t=s-this._top,i=this._bot-o;return t<=0&&i<=0||(t>=i?(this._top=s,this._dir=1):(this._bot=o,this._dir=-1),this._time=e.time),[]}const n=[];if(this._dir>0){if(s>this._top)this._top=s;else if(this._top-o>=this._reversal){const t=this._top*this._box;n.push(this._column()),this._box=this._resolveBox(r),this._top=Math.ceil(t/this._box)-1,this._bot=Math.floor(r/this._box),this._dir=-1,this._time=e.time}}else if(o<this._bot)this._bot=o;else if(s-this._bot>=this._reversal){const t=(this._bot+1)*this._box;n.push(this._column()),this._box=this._resolveBox(i),this._bot=Math.floor(t/this._box),this._top=Math.floor(i/this._box),this._dir=1,this._time=e.time}return n}flush(){return 0===this._dir||Number.isNaN(this._top)?[]:[this._column()]}}function b(e,t,i){return{time:e,open:t,high:t,low:t,close:t,volume:i?1:0}}class _{constructor(e){if(Object.defineProperty(this,"_reversal",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_dir",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_ext",{enumerable:!0,configurable:!0,writable:!0,value:NaN}),Object.defineProperty(this,"_prevShoulder",{enumerable:!0,configurable:!0,writable:!0,value:-1/0}),Object.defineProperty(this,"_prevWaist",{enumerable:!0,configurable:!0,writable:!0,value:1/0}),Object.defineProperty(this,"_thick",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_time",{enumerable:!0,configurable:!0,writable:!0,value:0}),e.reversal<=0)throw new Error("openalgo-charts: Kagi reversal must be > 0");this._reversal=e.reversal}reset(){this._dir=0,this._ext=NaN,this._prevShoulder=-1/0,this._prevWaist=1/0,this._thick=!1,this._time=0}clone(){return s(this)}push(e){const t=e.close;if(this._time=e.time,Number.isNaN(this._ext))return this._ext=t,[];const i=[];return this._dir>=0?t>this._ext?(this._ext=t,t>this._prevShoulder&&(this._thick=!0)):this._ext-t>=this._reversal&&(i.push(b(e.time,this._ext,this._thick)),this._prevShoulder=this._ext,this._dir=-1,this._ext=t):t<this._ext?(this._ext=t,t<this._prevWaist&&(this._thick=!1)):t-this._ext>=this._reversal&&(i.push(b(e.time,this._ext,this._thick)),this._prevWaist=this._ext,this._dir=1,this._ext=t),i}flush(){return Number.isNaN(this._ext)?[]:[b(this._time,this._ext,this._thick)]}}function f(e){const t=new Map;for(const i of e)t.set(i.time,i);return Array.from(t.values()).sort((e,t)=>e.time-t.time)}function m(e){let t=-1/0,i=1/0;for(const r of e)r.high>t&&(t=r.high),r.low<i&&(i=r.low);const r=Math.max((t-i)/40,Math.abs(e[e.length-1]?.close??0)/1e3);return r>0&&Number.isFinite(r)?Number(r.toPrecision(2)):1}const p=(e,t)=>"number"==typeof e&&e>0?e:t();class d{constructor(e,t,i,r){Object.defineProperty(this,"_given",{enumerable:!0,configurable:!0,writable:!0,value:e}),Object.defineProperty(this,"_resolve",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"_make",{enumerable:!0,configurable:!0,writable:!0,value:i}),Object.defineProperty(this,"_oneToOne",{enumerable:!0,configurable:!0,writable:!0,value:r}),Object.defineProperty(this,"_source",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_state",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_elements",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_index",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_committed",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_resolved",{enumerable:!0,configurable:!0,writable:!0,value:null})}setData(e){this._source=f(e),this._resolved=null,this._rebuild()}prepend(e){this._source=f([...this._source,...e]),this._rebuild()}update(e){const t=this._source.length,i=this._source[t-1];if(void 0===i||e.time<i.time)return this._source=f([...this._source,e]),this._rebuild(),0;const r=this._committed;return e.time>i.time?(this._commit(t-1),this._source.push(e)):this._source[t-1]=e,this._formTail(),r}source(){return this._source}elements(){return this._elements}sourceIndex(){return this._oneToOne?null:this._index}_rebuild(){this._elements.length=0,this._index.length=0,this._committed=0;const e=this._source.length;if(0!==e){this._resolved??(this._resolved=this._resolve(this._given,this._source)),this._state=this._make(this._resolved);for(let t=0;t<e-1;t++)this._commit(t);this._formTail()}else this._state=null}_commit(e){this._elements.length=this._committed,this._index.length=this._committed;for(const t of this._state.push(this._source[e]))this._append(t,e);this._committed=this._elements.length}_formTail(){this._elements.length=this._committed,this._index.length=this._committed;const e=this._source.length;if(0===e||null===this._state)return;const t=this._state.clone();for(const i of t.push(this._source[e-1]))this._append(i,e-1);for(const i of t.flush?.()??[])this._append(i,e-1)}_append(e,t){const i=this._elements[this._elements.length-1]?.time??-1/0;this._elements.push(e.time>i?e:{...e,time:i+1}),this._index.push(t)}}const g=(e,t)=>({key:e,type:"number",label:`${t} (0 = from history)`,default:0,min:0});function v(e,i,r,s,o,n,l=!1){t.registerSeriesTransform(e,{name:i,renderer:r,inputs:s,create:t=>new d(function(e,t,i){const r=e=>{throw new TypeError(`openalgo-charts: invalid series transform: ${e}`)};(null===i||"object"!=typeof i||Array.isArray(i))&&r("options must be an object");const s={};for(const[o,n]of Object.entries(i)){const i=t.find(e=>e.key===o);void 0===i&&r(`${e} option "${o}" is not one it takes`),("number"===i.type?"number"==typeof n&&Number.isFinite(n)&&(void 0===i.min||n>=i.min)&&(void 0===i.max||n<=i.max)&&(1!==i.step||Number.isInteger(n)):"select"===i.type&&i.options.some(e=>e.value===n))||r(`${e} option "${o}" cannot be ${String(n)}`),s[o]=n}return s}(e,s,t),o,n,l)})}const x=(e,t)=>e[t];const w={abs:1,sqrt:1,ln:1,log:1,log10:1,exp:1,min:2,max:2,pow:2};class y extends Error{constructor(e,t){super(`openalgo-charts: ${e}`),Object.defineProperty(this,"position",{enumerable:!0,configurable:!0,writable:!0,value:t}),this.name="ExpressionError"}}const N=/[A-Za-z_]/,M=/[A-Za-z0-9_.:!#&]/;const O={"+":1,"-":1,"*":2,"/":2,"^":3};function k(e,t){let i=0;const r=()=>e[i];function s(){const e=r();if(void 0===e)throw new y("expression ended early",t.length);if("num"===e.t)return i++,{k:"num",v:e.v};if("sym"===e.t){i++;const s=e.v.toLowerCase();if(s in w&&"op"===r()?.t&&"("===r()?.v){i++;const o=[];if("op"!==r()?.t||")"!==r()?.v)for(;o.push(n(0)),"op"===r()?.t&&","===r()?.v;)i++;if("op"!==r()?.t||")"!==r()?.v)throw new y(`${s}( is not closed`,r()?.i??t.length);i++;const l=w[s];if(o.length!==l)throw new y(`${s}() takes ${l} argument${1===l?"":"s"}, got ${o.length}`,e.i);return{k:"fn",name:s,args:o}}return{k:"sym",name:e.v}}if("("===e.v){i++;const t=n(0);if("op"!==r()?.t||")"!==r()?.v)throw new y("( is not closed",e.i);return i++,t}if("-"===e.v)return i++,{k:"neg",a:o()};if("+"===e.v)return i++,o();throw new y(`unexpected "${e.v}"`,e.i)}function o(){return s()}function n(e){let t=o();for(;;){const s=r();if(void 0===s||"op"!==s.t||!(s.v in O))break;const o=O[s.v];if(o<e)break;i++;const l=n("^"===s.v?o:o+1);t={k:"bin",op:s.v,a:t,b:l}}return t}const l=n(0),h=e[i];if(void 0!==h)throw new y(`unexpected "${h.v}"`,h.i);return l}function P(e,t){if("sym"!==e.k)if("neg"!==e.k){if("bin"===e.k)return P(e.a,t),void P(e.b,t);if("fn"===e.k)for(const i of e.args)P(i,t)}else P(e.a,t);else t.includes(e.name)||t.push(e.name)}function j(e){const t=function(e){const t=[];let i=0;for(;i<e.length;){const r=e[i];if(" "!==r&&"\t"!==r&&"\n"!==r&&"\r"!==r){if("'"===r||'"'===r){const s=e.indexOf(r,i+1);if(-1===s)throw new y(`unclosed ${r} in expression`,i);const o=e.slice(i+1,s);if(""===o)throw new y("empty quoted symbol",i);t.push({t:"sym",v:o,i:i}),i=s+1;continue}if(/[0-9]/.test(r)||"."===r&&/[0-9]/.test(e[i+1]??"")){let r=i;for(;r<e.length&&/[0-9.]/.test(e[r]);)r++;const s=e.slice(i,r),o=Number(s);if(!Number.isFinite(o))throw new y(`"${s}" is not a number`,i);t.push({t:"num",v:o,i:i}),i=r;continue}if(N.test(r)){let r=i;for(;r<e.length&&M.test(e[r]);)r++;let s=e.slice(i,r);for(;s.endsWith(":");)s=s.slice(0,-1),r--;t.push({t:"sym",v:s,i:i}),i=r;continue}if("+-*/^(),".includes(r))t.push({t:"op",v:r,i:i}),i++;else if("×"!==r)if("÷"!==r){if("−"!==r)throw new y(`unexpected "${r}" in expression`,i);t.push({t:"op",v:"-",i:i}),i++}else t.push({t:"op",v:"/",i:i}),i++;else t.push({t:"op",v:"*",i:i}),i++}else i++}return t}(e);if(0===t.length)throw new y("expression is empty",0);const i=k(t,e),r=[];if(P(i,r),0===r.length)throw new y("expression names no symbol",0);return{source:e,symbols:r,ast:i}}const S={lo:NaN,hi:NaN},T=e=>!Number.isFinite(e.lo)||!Number.isFinite(e.hi),z=e=>({lo:Math.min(...e),hi:Math.max(...e)});function C(e,t){if(t.lo!==t.hi)return S;const i=t.lo,r=[Math.pow(e.lo,i),Math.pow(e.hi,i)];return e.lo<0&&e.hi>0&&Number.isInteger(i)&&i%2==0&&r.push(0),z(r)}function $(e,t){return z([t(e.lo),t(e.hi)])}function A(e,t){switch(e.k){case"num":return{lo:e.v,hi:e.v};case"sym":return t(e.name)??S;case"neg":{const i=A(e.a,t);return T(i)?S:{lo:-i.hi,hi:-i.lo}}case"bin":{const i=A(e.a,t),r=A(e.b,t);if(T(i)||T(r))return S;switch(e.op){case"+":return{lo:i.lo+r.lo,hi:i.hi+r.hi};case"-":return{lo:i.lo-r.hi,hi:i.hi-r.lo};case"*":return function(e,t){return z([e.lo*t.lo,e.lo*t.hi,e.hi*t.lo,e.hi*t.hi])}(i,r);case"/":return function(e,t){return t.lo<=0&&t.hi>=0?S:z([e.lo/t.lo,e.lo/t.hi,e.hi/t.lo,e.hi/t.hi])}(i,r);case"^":return C(i,r)}return S}case"fn":{const i=e.args.map(e=>A(e,t));if(i.some(T))return S;const[r,s]=i;switch(e.name){case"abs":return function(e){return e.lo>=0?e:e.hi<=0?{lo:-e.hi,hi:-e.lo}:{lo:0,hi:Math.max(-e.lo,e.hi)}}(r);case"sqrt":return r.lo<0?S:$(r,Math.sqrt);case"ln":case"log":return r.lo<=0?S:$(r,Math.log);case"log10":return r.lo<=0?S:$(r,Math.log10);case"exp":return $(r,Math.exp);case"min":return{lo:Math.min(r.lo,s.lo),hi:Math.min(r.hi,s.hi)};case"max":return{lo:Math.max(r.lo,s.lo),hi:Math.max(r.hi,s.hi)};case"pow":return C(r,s)}return S}}}let B=!1;function E(){B||(B=!0,function(){v("heikin-ashi","Heikin Ashi","candlestick",[],()=>({}),()=>new n,!0),v("renko","Renko","candlestick",[g("boxSize","Box size")],(e,t)=>({boxSize:p(e.boxSize,()=>m(t))}),e=>new l({boxSize:x(e,"boxSize")})),v("range-bars","Range bars","candlestick",[g("range","Range")],(e,t)=>({range:p(e.range,()=>2*m(t))}),e=>new h({range:x(e,"range")})),v("line-break","Line break","candlestick",[{key:"lines",type:"number",label:"Lines to break",default:3,min:1,step:1}],e=>({lines:e.lines??3}),e=>new a({lines:x(e,"lines")}));const e={key:"mode",is:"atr"};v("point-figure","Point and figure","point-figure",[{key:"mode",type:"select",label:"Box size from",default:"fixed",options:[{label:"Fixed size",value:"fixed"},{label:"Percent of price",value:"percent"},{label:"ATR",value:"atr"}]},{...g("boxSize","Box size"),visibleWhen:{key:"mode",is:"fixed"}},{key:"percent",type:"number",label:"Box percent",default:1,min:0,visibleWhen:{key:"mode",is:"percent"}},{key:"atrPeriod",type:"number",label:"ATR length",default:14,min:1,step:1,visibleWhen:e},{key:"atrMultiplier",type:"number",label:"ATR multiplier",default:1,min:0,visibleWhen:e},{key:"reversal",type:"number",label:"Reversal boxes",default:3,min:1,step:1},{key:"method",type:"select",label:"Prices",default:"hl",options:[{label:"High and low",value:"hl"},{label:"Close",value:"close"}]}],(e,t)=>{const i=e.mode??"fixed";return{...e,mode:i,..."fixed"===i?{boxSize:p(e.boxSize,()=>m(t))}:{},..."percent"===i?{percent:p(e.percent,()=>1)}:{}}},e=>new c({mode:e.mode,boxSize:e.boxSize,percent:e.percent,atrPeriod:e.atrPeriod,atrMultiplier:e.atrMultiplier,reversal:e.reversal,method:e.method})),v("kagi","Kagi","kagi",[g("reversal","Reversal")],(e,t)=>({reversal:p(e.reversal,()=>2*m(t))}),e=>new _({reversal:x(e,"reversal")}))}(),t.registerChartType("point-figure",{defaultStyle:{},isPriceSeries:!0,draw:(e,t,i,s,o,n,l)=>r(e,t,i,s,o,n,l.plotHeight),extents:e=>({min:e.low,max:e.high})}),t.registerChartType("kagi",{defaultStyle:{thickColor:"#26a69a",thinColor:"#ef5350"},isPriceSeries:!0,connectsBars:!0,draw:(e,t,i,r,s,o)=>function(e,t,i,r,s){if(t.length<2)return;const o=s.thickColor??"#26a69a",n=s.thinColor??"#ef5350",l=Math.max(2,Math.round(2.5*r)),h=Math.max(1,Math.round(r)),a=t[0].edgeX,u=t[t.length-1].edgeX,c=void 0===a?-1/0:a-8,b=void 0===u?1/0:u+8;e.save();for(let s=1;s<t.length;s++){const a=t[s-1],u=t[s],_=(u.bar.volume??0)>=1;e.strokeStyle=_?o:n,e.lineWidth=_?l:h;const f=Math.max(a.x,c)*r,m=Math.min(u.x,b)*r,p=i(a.bar.close)*r,d=i(u.bar.close)*r;e.beginPath(),e.moveTo(f,p),e.lineTo(m,p),u.x<=b&&e.lineTo(m,d),e.stroke()}e.restore()}(e,t,i,s,o),extents:e=>({min:e.close,max:e.close})}))}return E(),e.ExpressionError=y,e.HeikinAshiTransform=n,e.KagiTransform=_,e.LineBreakTransform=a,e.PointFigureTransform=c,e.RangeBarsTransform=h,e.RenkoTransform=l,e.TRANSFORM_TIER="transform",e.ensureIncreasingTimes=o,e.evaluateExpression=function(e,t,i={}){const r="interval"===i.ohlc,s=i.primary??e.symbols[0],o=t[s];if(void 0===o||0===o.length)return[];const n=new Map;for(const i of e.symbols){if(i===s)continue;const e=t[i];if(void 0===e)return[];const r=new Map;for(const t of e)r.set(t.time,t);n.set(i,r)}const l=[],h=new Map;for(const t of o){h.clear(),h.set(s,t);let o=!0;for(const[e,i]of n){const r=i.get(t.time);if(void 0===r){o=!1;break}h.set(e,r)}if(!o)continue;const a=e=>t=>{const i=h.get(t);return void 0===i?null:{lo:i[e],hi:i[e]}},u=A(e.ast,a("open")),c=A(e.ast,a("close"));if(T(u)||T(c))continue;let b=Math.max(u.hi,c.hi),_=Math.min(u.lo,c.lo);if(r){const t=A(e.ast,e=>{const t=h.get(e);return void 0===t?null:{lo:t.low,hi:t.high}});if(T(t))continue;b=Math.max(b,t.hi),_=Math.min(_,t.lo)}const f={time:t.time,open:u.lo,high:b,low:_,close:c.lo};if("sum"===i.volume){let t=0;for(const i of e.symbols){const e=h.get(i)?.volume;if(void 0===e||!Number.isFinite(e)||e<0){t=NaN;break}t+=e}Number.isFinite(t)&&(f.volume=t)}l.push(f)}return l},e.isPlainSymbol=function(e){try{return"sym"===j(e).ast.k}catch{return!1}},e.parseExpression=j,e.registerTransformChartTypes=E,e.runTransform=function(e,t){e.reset();const i=[];for(const r of t)i.push(...e.push(r));return e.flush&&i.push(...e.flush()),o(i)},e}({},OpenAlgoCharts);