UNPKG

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 • 52 kB
if("undefined"==typeof OpenAlgoCharts)throw new Error("openalgo-charts.profile.standalone.js needs openalgo-charts.standalone.js loaded before it");this.OpenAlgoCharts=this.OpenAlgoCharts||{},this.OpenAlgoCharts.profile=function(e){"use strict";function t(e){let t=1/0,o=-1/0;for(const i of e)0!==i.levels.length&&(o=Math.max(o,i.levels[0].price),t=Math.min(t,i.levels[i.levels.length-1].price));return Number.isFinite(t)?{min:t,max:o}:null}function o(e,t){return Math.round(Math.round(e/t)*t*1e8)/1e8}function i(e,t,i){if(!(i>0)||i===1/0)return[];const r=o(e,i),n=o(t,i),l=Math.round((n-r)/i)+1;if(!Number.isFinite(l)||r+i===r||n+i===n)return[];const s=[];for(let e=0,t=r;e<l;e++,t+=i)s.push(o(t,i));return s}function r(e,t){let o=0;for(let t=1;t<e.length;t++)e[t]>e[o]&&(o=t);let i=o,r=o,n=e[o]??0;for(;n<t&&(i>0||r<e.length-1);){n+=(i>0?e[i-1]:-1)>=(r<e.length-1?e[r+1]:-1)?e[--i]:e[++r]}return{poc:o,upper:i,lower:r}}const n=19800;const l="Asia/Kolkata",s=new Map,a={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};function c(e,t){const o=function(e){let t=s.get(e);if(void 0===t){let o;try{o=new Intl.DateTimeFormat("en-US",{timeZone:e,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",weekday:"short"})}catch{throw new Error(`openalgo-charts: unknown IANA time zone "${e}"`)}t={format:o,parts:new Map,lastSecond:Number.NaN,lastParts:null},s.set(e,t)}return t}(t);if(e===o.lastSecond&&null!==o.lastParts)return o.lastParts;let i=o.parts.get(e);return void 0===i&&(i=function(e,t){let o=1970,i=1,r=1,n=0,l=0,s=0,c=4;for(const h of e.formatToParts(new Date(1e3*t)))switch(h.type){case"year":o=Number(h.value);break;case"month":i=Number(h.value);break;case"day":r=Number(h.value);break;case"hour":n=Number(h.value)%24;break;case"minute":l=Number(h.value);break;case"second":s=Number(h.value);break;case"weekday":c=a[h.value]??0}return{year:o,month:i,day:r,hour:n,minute:l,second:s,weekday:c,dayIndex:Math.floor(Date.UTC(o,i-1,r)/864e5)}}(o.format,e),o.parts.size>=4096&&o.parts.clear(),o.parts.set(e,i)),o.lastSecond=e,o.lastParts=i,i}function h(e,t=l){const o=c(e,t);return{year:o.year,month:o.month,day:o.day,hour:o.hour,minute:o.minute,second:o.second,weekday:o.weekday}}function u(e,t=l){const o=c(e,t);return Math.floor(Date.UTC(o.year,o.month-1,o.day,o.hour,o.minute,o.second)/1e3)-e}const p=86400;function d(e,t){return t===l?function(e){const t=new Date(1e3*(e+n));return{year:t.getUTCFullYear(),month:t.getUTCMonth()+1,day:t.getUTCDate(),hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds(),weekday:t.getUTCDay()}}(e):h(e,t)}function m(e,t){if(t===l){const t=((e+n)%p+p)%p;return Math.floor(t/60)}const o=h(e,t);return 60*o.hour+o.minute}function f(e,t){return t===l?Math.floor((e+n)/p):function(e,t=l){return c(e,t).dayIndex}(e,t)}function b(e,t,o,i){if("composite"===t)return 0;if("month"===t){const t=d(e,o);return 12*t.year+(t.month-1)}let r=f(e,o);return void 0!==i&&i.startMinute>i.endMinute&&m(e,o)<i.endMinute&&(r-=1),"day"===t?r:Math.floor((r+3)/7)}const g={tickSize:.05,session:"composite",valueAreaPercent:.7,deltaFromBarDirection:!0,timezone:l};const w={displayMode:"total",side:"right",width:90,opacity:.85,barColor:"#3b5168",buyColor:"#26a69a",sellColor:"#ef5350",showPoc:!0,pocColor:"#f0a020",showPocLabel:!0,showValueArea:!0,vahColor:"#8892a6",valColor:"#8892a6",showValueAreaLabels:!0,highlightValueArea:!0,valueAreaFillColor:"#4a6fa5",valueAreaFillOpacity:.08,valueAreaOpacityDim:.4,labelSide:"right",zOrder:"bottom"};const v={tickSize:.05,rowTicks:1,session:"day",blockMinutes:30,valueAreaPercent:.7,initialBalancePeriods:2,compositeSessions:1,tailEdges:0,timezone:l};function M(e){const t=(e%52+52)%52;return t<26?String.fromCharCode(65+t):String.fromCharCode(t-26+97)}function _(e,t){return e?.zone??t}function x(e,t,o=l){if(t.startMinute===t.endMinute)return!0;const i=m(e,_(t,o));return t.startMinute<t.endMinute?i>=t.startMinute&&i<t.endMinute:i>=t.startMinute||i<t.endMinute}function y(e,t,o,i){const r=d(e,o),n=new Date(Date.UTC(r.year,r.month-1,r.day+i));return function(e,t,o,i=0,r=0,n=0,s=l){const a=Math.floor(Date.UTC(e,t-1,o,i,r,n)/1e3),c=a-u(a,s);return a-u(c,s)}(n.getUTCFullYear(),n.getUTCMonth()+1,n.getUTCDate(),Math.floor(t.startMinute/60),t.startMinute%60,0,o)}function T(e,t){const o=e.map(e=>e.count),i=r(o,o.reduce((e,t)=>e+t,0)*t);return{poc:e[i.poc].price,vah:e[i.upper].price,val:e[i.lower].price}}function S(e,t,o){let i=0;for(let r=t;r>=0&&r<e.length&&1===e[r].count;r+=o)i++;return i}function k(e,t,o,i,r,n){const l=e.high-e.low,s=t-o;if(s<=0||l<=0)return"normal";if(i.up>0&&i.down>0)return"neutral";const a=r.findIndex(e=>e.price===n);if(a>=0&&r.length>=5){const e=r[a].count;let t=1/0,o=0;for(let e=0;e<r.length;e++){const i=Math.abs(e-a);i>1&&(o=Math.max(o,r[e].count)),i>0&&i<=Math.max(2,Math.floor(r.length/4))&&(t=Math.min(t,r[e].count))}if(o>=.7*e&&t<=.35*e)return"double-distribution"}const c=s/l;return c>=2.5?"trend":c>=1.4?"normal-variation":"normal"}function P(e,t,o,i,r){if(void 0===t)return"auction";const n=i-r;if(n<=0)return"auction";const l=t.high-t.low,s=(e-r)/n;if((s>.7||s<.3)&&l<=.35*n)return"drive";if(void 0!==o){const i=t.low<e-.25*l,r=t.high>e+.25*l;if(i&&o.high>t.high||r&&o.low<t.low)return"test-drive";if(r&&o.low<e||i&&o.high>e)return"rejection-reverse"}return"auction"}function C(e,t){if(0===e.length)return null;const o=e[0].time;let r=o;const n=t.win;if(void 0!==n&&n.startMinute!==n.endMinute){const e=y(o,n,t.cal,0);r=e<=o?e:y(o,n,t.cal,-1)}const l=new Map,s=new Map;let a=0,c=-1/0,h=1/0,u=0,p=-1/0,d=1/0;for(const o of e){const e=Math.max(0,Math.floor((o.time-r)/t.blockSec));e>a&&(a=e),e<t.ibPeriods&&(c=Math.max(c,o.high),h=Math.min(h,o.low)),p=Math.max(p,o.high),d=Math.min(d,o.low);const n=o.volume??0;u+=n;let m=s.get(e);void 0===m&&(m={index:e,letter:M(e),startTime:o.time,endTime:o.time,high:o.high,low:o.low,volume:0},s.set(e,m)),m.endTime=o.time,m.high=Math.max(m.high,o.high),m.low=Math.min(m.low,o.low),m.volume+=n;const f=i(o.low,o.high,t.row),b=n/Math.max(1,f.length);for(const t of f){let o=l.get(t);void 0===o&&(o={periods:new Set,volume:0},l.set(t,o)),o.periods.add(e),o.volume+=b}}const m=Array.from(s.values()).sort((e,t)=>e.index-t.index),f=Array.from(l.entries()).map(([e,t])=>{const o=Array.from(t.periods).sort((e,t)=>e-t);return{price:e,count:o.length,periods:o,volume:t.volume,letters:o.map(M).join("")}}).sort((e,t)=>t.price-e.price);if(0===f.length)return null;const b=T(f,t.vaPct),g=[];for(let e=1;e<f.length-1;e++)1===f[e].count&&g.push(f[e].price);const w={high:Number.isFinite(c)?c:f[0].price,low:Number.isFinite(h)?h:f[f.length-1].price},v={up:Math.max(0,p-w.high),down:Math.max(0,w.low-d)};let _=f[0].price,x=-1;for(const e of f)e.volume>x&&(x=e.volume,_=e.price);return{startTime:o,endTime:e[e.length-1].time,label:n?.name,levels:f,poc:b.poc,vah:b.vah,val:b.val,high:p,low:d,open:e[0].open,close:e[e.length-1].close,periods:a+1,periodDetail:m,initialBalance:w,rangeExtension:v,singlePrints:g,...V(f,t.tailEdges),poorHigh:f[0].count>1,poorLow:f[f.length-1].count>1,developing:A(f,m,t.vaPct),dayType:k(w,p,d,v,f,b.poc),openType:P(e[0].open,m[0],m[1],p,d),volumePoc:_,totalVolume:u}}function A(e,t,o){const i=[];for(const r of t){const t=[];for(const o of e){let e=0;for(const t of o.periods)t<=r.index&&e++;e>0&&t.push({price:o.price,count:e})}0!==t.length&&i.push({periodIndex:r.index,time:r.endTime,...T(t,o)})}return i}function V(e,t){let o=null,i=null;if(t>0){const r=S(e,0,1);r>=t&&(i={high:e[0].price,low:e[r-1].price});const n=S(e,e.length-1,-1);n>=t&&(o={high:e[e.length-n].price,low:e[e.length-1].price})}return{buyingTail:o,sellingTail:i}}function O(e){const t=[],o=e.sessions,i=["poc","vah","val"];for(let e=0;e<o.length;e++)for(const r of i){const i=o[e][r];let n=!1;for(let t=e+1;t<o.length&&!n;t++)i<=o[t].high&&i>=o[t].low&&(n=!0);n||t.push({time:o[e].startTime,price:i,kind:r})}return t}function R(e,t){return o(e,t.tickSize*Math.max(1,Math.floor(t.rowTicks)))}const F=["25755","65656","34443","65556","74747","74744","34553","55755","72227","11152","55655","44447","57755","57555","25552","65644","25573","65655","34216","72222","55557","55552","55775","55255","55222","71247","03137","44656","03443","11353","02743","32722","03531","44655","20223","10152","44565","62223","07755","06555","02552","06564","03511","03444","03216","27223","05553","05552","05577","05225","05531","07127","75557","26227","61247","61216","55711","74616","34752","71222","25252","25716","57575"],D=new Map(Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#",(e,t)=>{const o=[];for(let e=0;e<5;e++){const i=Number(F[t][e]);for(let t=0;t<3;t++){if(!(i&4>>t))continue;const r=t;for(;t+1<3&&i&4>>t+1;)t++;o.push([r,e,t-r+1])}}return[e,o]}));function N(e,t,o,i,r,n,l="center"){if(0===t.length||!Number.isFinite(r)||!Number.isFinite(n))return!1;const s=4*t.length-1,a=Math.floor(Math.min(r/5,n/s)+1e-7);if(a<1)return!1;const c=s*a,h=Math.round(o-("center"===l?c/2:"right"===l?c:0)),u=Math.round(i-5*a/2);for(let o=0;o<t.length;o++){const i=D.get(t[o]);if(void 0!==i)for(const[t,r,n]of i)e.fillRect(h+(4*o+t)*a,u+r*a,n*a,a)}return!0}const I=["#e05555","#e08a3c","#d9c341","#8cc44a","#3fb96b","#38b2a3","#3b9fd1","#5a7fe0","#8a68d9","#c05fc4","#d1508f","#9b7b5a"],z={blockDisplay:"auto",minLetterHeight:7,letterFade:4,letterWidth:8,font:10,colorMode:"period",periodColors:I,color:"#5a6b8c",vaColor:"#4a8f7a",opacity:.92,outsideVaOpacity:.45,zOrder:"top",split:!1,showSessionOpen:!1,sessionOpenColor:"#5ca8ff",showLastPrice:!1,lastPriceColor:"#ff6b5e",profileSpacing:4,showPoc:!0,pocColor:"#f0a020",pocThickness:2,showPocLabel:!0,showValueArea:!0,vahColor:"#8892a6",valColor:"#8892a6",showValueAreaLabels:!0,fillValueArea:!0,valueAreaFillColor:"#4a8f7a",valueAreaFillOpacity:.07,showInitialBalance:!0,ibColor:"#c8853a",showSinglePrints:!0,singlePrintColor:"#e0556b",showTails:!0,buyTailColor:"#3fb96b",sellTailColor:"#e05555",showPoorHighLow:!1,poorColor:"#ffd966",showNakedLevels:!1,nakedColor:"#b0b0b0",showDevelopingPoc:!1,developingPocColor:"#ffffff",showDevelopingVa:!1,developingVaColor:"#888888",showTpoCounts:!1,countColor:"#8892a6",showSessionLabel:!0,showDayType:!1,showOpenType:!1,labelColor:"#cccccc",showVolumeProfile:!1,volumeProfileWidth:60,volumeProfileSide:"right",volumeColor:"#3b5168",showVolumeValues:!1},L={normal:"Normal","normal-variation":"Normal Var",trend:"Trend","double-distribution":"Double Dist",neutral:"Neutral"},E={drive:"Open-Drive","test-drive":"Open-Test-Drive","rejection-reverse":"Open-Rej-Rev",auction:"Open-Auction"};function j(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError("Footprint tickSize must be positive and finite");if(!Number.isSafeInteger(t)||t<1)throw new RangeError("Footprint rowTicks must be a positive integer");const o=e*t;if(!Number.isFinite(o))throw new RangeError("Footprint tickSize * rowTicks must be finite");return o}function H(e){if(!Number.isFinite(e.price))throw new RangeError("Footprint trade price must be finite");if(!Number.isFinite(e.qty)||e.qty<0)throw new RangeError("Footprint trade qty must be nonnegative and finite");if("bid"!==e.side&&"ask"!==e.side)throw new TypeError("Footprint trade side must be bid or ask")}function W(e){let t=1/0;for(let o=1;o<e.length;o++){const i=e[o-1].price-e[o].price;i>0&&(t=Math.min(t,i))}return t}function U(e,t,o){const i=Math.max(1e-7*o,Math.max(Math.abs(e),Math.abs(t))*Number.EPSILON*8);return Number.isFinite(o)&&e>t&&Math.abs(e-t-o)<=i}function B(e,t=3,o,i=0){if(!Number.isFinite(t)||t<=0)throw new RangeError("Imbalance ratio must be positive and finite");if(void 0!==o&&(!Number.isFinite(o)||o<=0))throw new RangeError("Imbalance rowSize must be positive and finite");if(!Number.isFinite(i)||i<0)throw new RangeError("Imbalance threshold must be nonnegative and finite");const r=[...e].sort((e,t)=>t.price-e.price),n=o??W(r),l=(e,o)=>e>0&&e>=i&&e>=t*o,s=[];for(let e=0;e<r.length;e++){const t=r[e],o=r[e+1],i=r[e-1];o&&U(t.price,o.price,n)&&l(t.askVol,o.bidVol)&&s.push({price:t.price,side:"buy"}),i&&U(i.price,t.price,n)&&l(t.bidVol,i.askVol)&&s.push({price:t.price,side:"sell"})}return s}function Y(e,t=3,o=3,i,r=0){if(!Number.isSafeInteger(o)||o<1)throw new RangeError("Imbalance minStack must be a positive integer");const n=[...e].sort((e,t)=>t.price-e.price),l=B(n,t,i,r),s=i??W(n),a=[];for(const e of["buy","sell"]){const t=new Set(l.filter(t=>t.side===e).map(e=>e.price));let i;const r=()=>{i&&i.count>=o&&a.push(i),i=void 0};for(const o of n)t.has(o.price)?(i&&!U(i.endPrice,o.price,s)&&r(),i?(i.endPrice=o.price,i.count++):i={startPrice:o.price,endPrice:o.price,side:e,count:1}):r();r()}return a.sort((e,t)=>t.startPrice-e.startPrice)}function $(e){const t=e.trim();if(t.startsWith("#")){const e=t.slice(1);if(3===e.length||4===e.length){const[t,o,i,r]=[...e].map(e=>parseInt(e+e,16));return[t,o,i].some(Number.isNaN)?null:{r:t,g:o,b:i,a:4===e.length?r/255:1}}if(6===e.length||8===e.length){const t=parseInt(e.slice(0,6),16);if(Number.isNaN(t))return null;const o=8===e.length?parseInt(e.slice(6,8),16)/255:1;return{r:t>>16&255,g:t>>8&255,b:255&t,a:Number.isNaN(o)?1:o}}return null}const o=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i.exec(t);return null===o?null:{r:Number(o[1]),g:Number(o[2]),b:Number(o[3]),a:void 0===o[4]?1:Number(o[4])}}const q=e=>{const t=e/255;return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)};function K(e,t,o){return e<t?t:e>o?o:e}function X(e){return`rgb(${Math.round(e.r)},${Math.round(e.g)},${Math.round(e.b)})`}function G(e,t,o){return{r:e.r+(t.r-e.r)*o,g:e.g+(t.g-e.g)*o,b:e.b+(t.b-e.b)*o,a:1}}function Z(e){return function(e){return.2126*q(e.r)+.7152*q(e.g)+.0722*q(e.b)}({r:K(e.r,0,255),g:K(e.g,0,255),b:K(e.b,0,255),a:e.a})}function J(e,t){const o=$(t);if(!o)return e;const i=Z(o),r=e=>{const t=Z(e);return(Math.max(t,i)+.05)/(Math.min(t,i)+.05)},n=(i+.05)/.05>=1.05/(i+.05)?0:255,l={r:n,g:n,b:n},s=$(e);if(!s)return X(l);const a=G(o,s,Math.max(0,Math.min(1,s.a)));if(r(a)>=4.5)return e;let c=0,h=1,u=l;for(let e=0;e<10;e++){const e=(c+h)/2,t=G(a,l,e),o={r:Math.round(t.r),g:Math.round(t.g),b:Math.round(t.b),a:1};r(o)>=4.5?(h=e,u=o):c=e}return X(u)}const Q={widthFactor:.9,font:10,minTextHeight:11,textFade:4,displayMode:"bidask",volumeDivisor:1,cellStyle:"heatmap",textColorMode:"contrast",imbalanceRatio:3,imbalanceThreshold:0,stackedImbalances:3,statsRows:[],tableRows:[],tableLabelWidth:150,statsRowHeight:15,statsPosition:"bottom",cvdOffset:0,showCandle:!0,showPoc:!0,pocStyle:"marker",pocColor:"#f0a020",showValueArea:!1,valueAreaPercent:.7,radius:2};function ee(e){if(!Number.isFinite(e))return"-";const t=Number(e.toPrecision(3)),o=Math.abs(t),[i,r]=o>=1e9?["B",1e9]:o>=1e6?["M",1e6]:o>=1e3?["K",1e3]:["",1];return String(Number((t/r).toPrecision(3)))+i}function te(e,t,o){const i=$(e),r=$(t);if(null===i||null===r)return t;const n=Math.max(0,Math.min(1,o));return`rgb(${Math.round(i.r+(r.r-i.r)*n)},${Math.round(i.g+(r.g-i.g)*n)},${Math.round(i.b+(r.b-i.b)*n)})`}const oe={volume:"Volume",bidVolume:"Bid Volume",askVolume:"Ask Volume",delta:"Delta",minDelta:"Min Delta",maxDelta:"Max Delta",deltaPct:"Delta %",cvd:"CVD",trades:"Trades"},ie={...oe,volume:"Total Volume",bidVolume:"Total Bid Volume",askVolume:"Total Ask Volume",cvd:"Cumulative Delta"};return e.DEFAULT_FOOTPRINT_OPTIONS=Q,e.DEFAULT_MARKET_PROFILE_OPTIONS=v,e.DEFAULT_MARKET_PROFILE_PRIMITIVE_OPTIONS=z,e.DEFAULT_VOLUME_PROFILE_FAMILY_OPTIONS=g,e.DEFAULT_VOLUME_PROFILE_PRIMITIVE_OPTIONS=w,e.Footprint=class{constructor(e={}){Object.defineProperty(this,"_bars",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_opts",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_stats",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_cols",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_rc",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_inferredStep",{enumerable:!0,configurable:!0,writable:!0,value:0}),this._opts={...Q,...e,statsRows:[...e.statsRows??Q.statsRows],tableRows:[...e.tableRows??[]]},this._validateOptions(this._opts)}attached(e){this._host=e}detached(){this._host=null,this._rc=null,this._cols=[]}zOrder(){return"normal"}_validateOptions(e){for(const t of[e.widthFactor,e.font,e.statsRowHeight,e.tableLabelWidth,e.imbalanceRatio,e.volumeDivisor])if(!Number.isFinite(t)||t<=0)throw new RangeError("Footprint dimensions and ratio must be positive and finite");for(const t of[e.radius,e.minTextHeight,e.textFade,e.imbalanceThreshold])if(!Number.isFinite(t)||t<0)throw new RangeError("Footprint thresholds and radius must be nonnegative and finite");for(const t of[e.cellWidth,e.tickSize])if(void 0!==t&&(!Number.isFinite(t)||t<=0))throw new RangeError("Footprint width and row step must be positive and finite");if(!Number.isSafeInteger(e.stackedImbalances)||e.stackedImbalances<0)throw new RangeError("Footprint stack length must be a nonnegative integer");if(!Number.isFinite(e.cvdOffset))throw new RangeError("Footprint CVD offset must be finite");if(!Number.isFinite(e.valueAreaPercent)||e.valueAreaPercent<=0||e.valueAreaPercent>1)throw new RangeError("Footprint value area must be in (0, 1]");for(const t of[e.statsRows,e.tableRows])if(t.some(e=>!Object.prototype.hasOwnProperty.call(oe,e))||new Set(t).size!==t.length)throw new RangeError("Footprint statistics rows must be known and unique")}setBars(e){this._bars=e.map(e=>({...e,cells:e.cells.map(e=>({...e})).sort((e,t)=>t.price-e.price)}));let t=1/0;for(const e of this._bars){void 0!==e.rowSize&&e.rowSize>0&&(t=Math.min(t,e.rowSize));for(let o=1;o<e.cells.length;o++){const i=e.cells[o-1].price-e.cells[o].price;i>0&&(t=Math.min(t,i))}}this._inferredStep=Number.isFinite(t)?t:0,this._cols=[],this._recomputeStats(),this._host?.requestUpdate()}setOptions(e){const t={...this._opts,...e};this._validateOptions(t),this._opts={...t,statsRows:[...t.statsRows],tableRows:[...t.tableRows]},this._cols=[],void 0===e.cvdOffset&&void 0===e.valueAreaPercent||this._recomputeStats(),this._host?.requestUpdate()}options(){return{...this._opts,statsRows:[...this._opts.statsRows],tableRows:[...this._opts.tableRows]}}stats(){return this._stats}_step(e){return this._opts.tickSize??e.rowSize??this._inferredStep}autoscaleInfo(){let e=1/0,t=-1/0;for(const o of this._bars){const i=this._step(o)/2;for(const r of o.cells)e=Math.min(e,r.price-i),t=Math.max(t,r.price+i);this._opts.showCandle&&(void 0!==o.low&&(e=Math.min(e,o.low)),void 0!==o.high&&(t=Math.max(t,o.high)))}return Number.isFinite(e)?{min:e,max:t}:null}_recomputeStats(){let e=this._opts.cvdOffset;this._stats=this._bars.map(t=>{const o=t.cells.map(e=>e.bidVol+e.askVol),i=o.reduce((e,t)=>e+t,0),n=t.cells.reduce((e,t)=>e+t.bidVol,0),l=t.cells.reduce((e,t)=>e+t.askVol,0),s=r(o,i*this._opts.valueAreaPercent);return e+=t.delta,{time:t.time,volume:i,bidVolume:n,askVolume:l,delta:t.delta,minDelta:t.minDelta??null,maxDelta:t.maxDelta??null,deltaPct:i>0?t.delta/i*100:0,cvd:e,trades:t.tradeCount??null,poc:t.cells[s.poc]?.price??0,vah:t.cells[s.upper]?.price??0,val:t.cells[s.lower]?.price??0}})}_bounds(e,t,o){const i=o.priceScale.priceToY(e);if(!(t>0))return{top:i-8,bottom:i+8};const r=o.priceScale.priceToY(e-t/2),n=o.priceScale.priceToY(e+t/2);return{top:Math.min(r,n),bottom:Math.max(r,n)}}draw(e,t){if(this._rc=t,this._cols=[],0===this._bars.length||t.plotHeight<=0||t.plotWidth<=0)return;const o=this._opts,i=t.dpr,r=o.buyColor??t.theme.upColor,n=o.sellColor??t.theme.downColor,l=t.theme.background,s=t.timeScale.barSpacing,a=Math.max(.1,Math.min(o.cellWidth??s*o.widthFactor,.96*s)),c=o.showCandle&&a>=20?Math.min(9,.15*a):0,h=Math.max(.1,a-c),u=o.tableRows.length?o.tableRows:"bottom"===o.statsPosition?o.statsRows:[],p=Math.min(t.plotHeight,u.length*o.statsRowHeight),d=t.plotHeight-p,m=t.timeScale.visibleRange();for(let e=0;e<this._bars.length;e++){const o=this._bars[e];if(!o.cells.length)continue;const i=t.dataLayer.timeToIndex(o.time);if(void 0===i||i<m.from-1||i>m.to+1)continue;const r=t.timeScale.indexToX(i)-a/2+c;r+h<0||r>t.plotWidth||this._cols.push({bar:o,stats:this._stats[e],x:r+h/2,x0:r,width:h,rowSize:this._step(o),rows:[]})}e.save(),e.beginPath(),e.rect(0,0,t.plotWidth*i,t.plotHeight*i),e.clip(),e.textBaseline="middle",e.save(),e.beginPath(),e.rect(0,0,t.plotWidth*i,d*i),e.clip();for(const o of this._cols)this._drawColumn(e,t,o,c,r,n,l,d);if(e.restore(),o.statsRows.length&&"bar"===o.statsPosition)for(const o of this._cols)this._drawCard(e,t,o,r,n,l,d);u.length&&this._drawFooter(e,t,r,n,l,p,u),e.restore()}_drawColumn(e,t,o,i,r,n,l,s){const a=this._opts,c=t.dpr,{bar:h,stats:u}=o,p=o.width*c,d=p/2,m=o.x0*c,f=o.x*c,b=B(h.cells,a.imbalanceRatio,o.rowSize||void 0,a.imbalanceThreshold),g=new Set(b.filter(e=>"buy"===e.side).map(e=>e.price)),w=new Set(b.filter(e=>"sell"===e.side).map(e=>e.price));let v=0,M=0;for(const e of h.cells)v=Math.max(v,"volume"===a.displayMode?e.bidVol+e.askVol:"delta"===a.displayMode?Math.abs(e.askVol-e.bidVol):Math.max(e.bidVol,e.askVol)),M=Math.max(M,"bidask"===a.displayMode?Math.max(e.bidVol,e.askVol):e.bidVol+e.askVol);i>0&&this._drawCandle(e,t,o,i,r,n);for(const i of h.cells){const h=this._bounds(i.price,o.rowSize,t);if(h.bottom<=0||h.top>=s)continue;o.rows.push({cell:i,top:Math.max(0,h.top),bottom:Math.min(s,h.bottom)});const b=h.top*c,_=(h.bottom-h.top)*c,x=Math.max(0,_-Math.min(c,.1*_)),y=Math.max(0,Math.min(1,(h.bottom-h.top-a.minTextHeight)/Math.max(1,a.textFade)+1));if(e.font=a.font*c+"px ui-monospace, SFMono-Regular, Menlo, monospace","bidask"===a.displayMode){const o=Math.min(c,.08*d),s=d-o;this._cell(e,t,i,m,b,s,x,i.bidVol,v,M,n,r,n,l,w.has(i.price),y,"bid"),this._cell(e,t,i,f+o,b,s,x,i.askVol,v,M,r,r,n,l,g.has(i.price),y,"ask")}else{const o="delta"===a.displayMode?i.askVol-i.bidVol:i.bidVol+i.askVol,s=i.askVol-i.bidVol;this._cell(e,t,i,m,b,p,x,o,v,M,s>0?r:s<0?n:te(r,n,.5),r,n,l,s>0?g.has(i.price):s<0&&w.has(i.price),y,"single")}a.showPoc&&i.price===u.poc&&("outline"===a.pocStyle?(e.strokeStyle=a.pocColor,e.lineWidth=Math.max(1,c),e.strokeRect(m,b+c/2,p,Math.max(0,x-c))):(e.fillStyle=a.pocColor,e.fillRect(m-2*c,b,2*c,x)))}if(a.showValueArea&&u.volume>0){const i=this._bounds(u.vah,o.rowSize,t),r=this._bounds(u.val,o.rowSize,t);e.strokeStyle=a.valueAreaColor??t.theme.axisText,e.lineWidth=c,e.beginPath();for(const t of[Math.min(i.top,r.top),Math.max(i.bottom,r.bottom)])e.moveTo(m,t*c),e.lineTo(m+p,t*c);e.stroke()}if(a.stackedImbalances>0&&o.width>=16){const i=Y(h.cells,a.imbalanceRatio,a.stackedImbalances,o.rowSize||void 0,a.imbalanceThreshold);for(const l of i){const i=this._bounds(l.startPrice,o.rowSize,t),s=this._bounds(l.endPrice,o.rowSize,t),a=Math.min(i.top,s.top)*c,h=Math.max(i.bottom,s.bottom)*c,u=("buy"===l.side?o.x0+o.width-1:o.x0+1)*c,p=("buy"===l.side?-3:3)*c;e.strokeStyle="buy"===l.side?r:n,e.lineWidth=c,e.beginPath(),e.moveTo(u+p,a),e.lineTo(u,a),e.lineTo(u,h),e.lineTo(u+p,h),e.stroke()}}}_drawCandle(e,t,o,i,r,n){const l=o.bar,s=t.dpr,a=(o.x0-i/2)*s,c=Math.min(4,.45*i)*s,h=l.high??l.cells[0].price,u=l.low??l.cells[l.cells.length-1].price,p=t.priceScale.priceToY(h)*s,d=t.priceScale.priceToY(u)*s,m=void 0!==l.open&&void 0!==l.close,f=m?l.close>=l.open?r:n:t.theme.axisText;if(e.fillStyle=f,e.fillRect(a,Math.min(p,d),s,Math.max(s,Math.abs(d-p))),m){const o=t.priceScale.priceToY(l.open)*s,i=t.priceScale.priceToY(l.close)*s;e.fillRect(a-c/2,Math.min(o,i),c,Math.max(s,Math.abs(i-o)))}}_cell(e,t,o,i,r,n,l,s,a,c,h,u,p,d,m,f,b){if(n<=0||l<=0)return;const g=this._opts,w=t.dpr,v="profile"===g.cellStyle,M=Math.max(0,Math.min(1,a>0?Math.abs(s)/a:0)),_=m?h:te(d,h,"ladder"===g.cellStyle?.18+.82*Math.sqrt(M):.08+.62*Math.sqrt(M)),x=v?n*M:n,y=v&&"bid"===b?i+n-x:i;if(x>0&&(e.fillStyle=_,e.beginPath(),e.roundRect(y,r,x,l,"ladder"===g.cellStyle||v?0:Math.min(g.radius*w,l/2,x/2)),e.fill()),f<=0||l<g.font*w*.6)return;const T=ee(s/g.volumeDivisor),S=e.measureText(T).width;if(S+4*w>n)return;e.textAlign=v&&"single"!==b?"bid"===b?"right":"left":"center";const k=v&&"single"!==b?"bid"===b?i+n-2*w:i+2*w:i+n/2,P="right"===e.textAlign?k-S:"left"===e.textAlign?k:k-S/2,C=P+S;let A=_;v&&(0===x||C<=y||P>=y+x?A=d:(P<y||C>y+x)&&(A=d,e.fillStyle=d,e.fillRect(P-w,r,S+2*w,l)));const V=g.textColor??J(t.theme.axisText,d),O=function(e){const{mode:t,side:o,bidVol:i,askVol:r,neutral:n,buy:l,sell:s}=e,a=r>i?l:i>r?s:n,c="ask"===o?l:"bid"===o?s:a;let h=n;switch(t){case"contrast":break;case"side":h=c;break;case"delta":h=a;break;case"dominant":("single"===o||"ask"===o&&r>i||"bid"===o&&i>r)&&(h=a);break;case"imbalance":e.hot&&(h=c);break;case"volume":{const t="ask"===o?r:"bid"===o?i:r+i,l=e.peak>0?Math.max(0,Math.min(1,t/e.peak)):0;if(l>=1)h=c;else if(l>0&&c!==n){const e=$(n),t=$(c);e&&t&&(h=X(G(e,t,l)))}break}}return J($(h)?h:n,e.background)}({mode:g.textColorMode,side:b,bidVol:o.bidVol,askVol:o.askVol,peak:c,hot:m,neutral:V,buy:g.buyTextColor??u,sell:g.sellTextColor??p,background:A});e.fillStyle=function(e,t){const o=$(e);return null===o?e:`rgba(${o.r},${o.g},${o.b},${t})`}(O,f),e.fillText(T,k,r+l/2)}_drawCard(e,t,o,i,r,n,l){const s=this._opts,a=t.dpr;if(o.width<68||0===o.rows.length)return;let c=-1/0;for(const e of o.bar.cells)c=Math.max(c,this._bounds(e.price,o.rowSize,t).bottom);if(s.showCandle)for(const e of[o.bar.high,o.bar.low])void 0!==e&&(c=Math.max(c,t.priceScale.priceToY(e)));const h=c+8,u=s.statsRows.length*s.statsRowHeight+8;if(h<0||h+u>l)return;o.card={top:h,bottom:h+u};const p=te(n,t.theme.axisText,.13);e.fillStyle=p,e.beginPath(),e.roundRect(o.x0*a,h*a,o.width*a,u*a,2*a),e.fill(),e.font=Math.max(8,s.font-1)*a+"px ui-monospace, SFMono-Regular, Menlo, monospace",s.statsRows.forEach((n,l)=>{const c=this._metric(o.stats,n),u=this._statText(c,n),d=(h+4+(l+.5)*s.statsRowHeight)*a,m=oe[n];e.measureText(m).width+e.measureText(u).width+12*a>o.width*a||(e.textAlign="left",e.fillStyle=J(s.textColor??t.theme.axisText,p),e.fillText(m,(o.x0+4)*a,d),e.textAlign="right",e.fillStyle=J(this._statColor(n,c,s.textColor??t.theme.axisText,s.buyTextColor??i,s.sellTextColor??r),p),e.fillText(u,(o.x0+o.width-4)*a,d))})}_drawFooter(e,t,o,i,r,n,l){const s=this._opts,a=t.dpr,c=t.plotHeight-n,h=Math.min(s.tableLabelWidth,t.plotWidth);e.fillStyle=r,e.fillRect(0,c*a,t.plotWidth*a,n*a),e.font=Math.max(8,s.font-.5)*a+"px ui-monospace, SFMono-Regular, Menlo, monospace",e.textAlign="center";const u=t.timeScale.barSpacing;for(const e of this._cols){const o=t.timeScale.indexToX(t.dataLayer.timeToIndex(e.bar.time)),i=Math.max(h,o-u/2),r=Math.min(t.plotWidth,o+u/2);i<r&&(e.table={left:i,right:r,top:c,bottom:t.plotHeight})}e.save(),e.beginPath(),e.rect(h*a,c*a,(t.plotWidth-h)*a,n*a),e.clip(),l.forEach((n,l)=>{let h=1;for(const e of this._cols)e.table&&(h=Math.max(h,Math.abs(this._metric(e.stats,n)??0)));for(const p of this._cols){if(!p.table)continue;const d=this._metric(p.stats,n),m=d??0,f=te(r,this._statColor(n,d,t.theme.axisText,o,i),.1+.4*Math.abs(m)/h),b=t.timeScale.indexToX(t.dataLayer.timeToIndex(p.bar.time)),g=(c+l*s.statsRowHeight)*a;e.fillStyle=f,e.fillRect((b-u/2)*a,g+a,Math.max(0,u*a-a),Math.max(0,s.statsRowHeight*a-a));const w=this._statText(d,n),v=e.measureText(w).width/(2*a)+2;b-v<p.table.left||b+v>p.table.right||(e.fillStyle=J(s.textColor??t.theme.axisText,f),e.fillText(w,b*a,g+s.statsRowHeight*a/2))}}),e.restore(),e.save(),e.beginPath(),e.rect(0,c*a,h*a,n*a),e.clip();const p=te(r,t.theme.axisText,.09);e.fillStyle=p,e.fillRect(0,c*a,h*a,n*a),e.fillStyle=J(s.textColor??t.theme.axisText,p),e.textAlign="left",l.forEach((t,o)=>e.fillText(ie[t],6*a,(c+(o+.5)*s.statsRowHeight)*a)),e.restore(),e.strokeStyle=te(r,t.theme.axisText,.25),e.lineWidth=a,e.beginPath();for(let o=0;o<=l.length;o++){const i=(c+o*s.statsRowHeight)*a;e.moveTo(0,i),e.lineTo(t.plotWidth*a,i)}e.moveTo(h*a,c*a),e.lineTo(h*a,t.plotHeight*a),e.stroke()}_statColor(e,t,o,i,r){return null===t||0===t||"volume"===e||"trades"===e?o:"askVolume"===e?i:"bidVolume"===e?r:t>0?i:r}_metric(e,t){return"deltaPct"===t?e.deltaPct:e[t]}_statText(e,t){if(null===e)return"-";if("deltaPct"===t)return`${e>=0?"+":""}${e.toFixed(1)}%`;const o="trades"===t?e:e/this._opts.volumeDivisor;return(e=>"volume"===e||"trades"===e||"bidVolume"===e||"askVolume"===e)(t)?ee(o):((i=o)>=0?"+":"")+ee(i);var i}hitTest(e,t){const o=this.hoverAt(e,t);return o?{externalId:`footprint:${o.time}`,zOrder:"normal",distance:0,cursor:"crosshair"}:null}hoverAt(e,t,o){const i=o??this._rc;if(!i||e<0||e>i.plotWidth||t<0||t>i.plotHeight)return null;const r=this._cols.find(o=>o.table&&e>=o.table.left&&e<o.table.right&&t>=o.table.top&&t<=o.table.bottom);if(r)return{time:r.bar.time,price:null,cell:null,stats:r.stats};const n=this._cols.find(t=>e>=t.x0&&e<=t.x0+t.width);if(!n)return null;const l=n.rows.find(e=>t>=e.top&&t<e.bottom);return l?{time:n.bar.time,price:l.cell.price,cell:l.cell,stats:n.stats}:n.card&&t>=n.card.top&&t<=n.card.bottom?{time:n.bar.time,price:null,cell:null,stats:n.stats}:null}},e.FootprintAggregator=class{constructor(e,t,o=1){if(Object.defineProperty(this,"_tf",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_tickSize",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_time",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_cells",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"_delta",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_minDelta",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_maxDelta",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_count",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_volume",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_open",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_lastTickTime",{enumerable:!0,configurable:!0,writable:!0,value:-1/0}),Object.defineProperty(this,"_openPrice",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_high",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_low",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_close",{enumerable:!0,configurable:!0,writable:!0,value:0}),this._tickSize=j(t,o),"interval"===e.mode){if(!Number.isFinite(e.seconds)||e.seconds<=0)throw new RangeError("Footprint interval seconds must be positive and finite");if(void 0!==e.anchorSec&&!Number.isFinite(e.anchorSec))throw new RangeError("Footprint anchorSec must be finite")}else if("ticks"===e.mode){if(!Number.isSafeInteger(e.count)||e.count<1)throw new RangeError("Footprint tick count must be a positive integer")}else{if("volume"!==e.mode)throw new TypeError("Unknown footprint timeframe mode");if(!Number.isFinite(e.perBar)||e.perBar<=0)throw new RangeError("Footprint volume perBar must be positive and finite")}this._tf={...e}}_snapshot(){const e=Array.from(this._cells.values(),e=>({...e})).sort((e,t)=>t.price-e.price);return{time:this._time,cells:e,delta:this._delta,minDelta:this._minDelta,maxDelta:this._maxDelta,rowSize:this._tickSize,open:this._openPrice,high:this._high,low:this._low,close:this._close,tradeCount:this._count}}current(){return this._open?this._snapshot():null}_intervalKey(e){if("interval"!==this._tf.mode)return 0;const t=this._tf.anchorSec??0;return t+Math.floor((e-t)/this._tf.seconds)*this._tf.seconds}onTick(e){if(H(e),!Number.isFinite(e.time))throw new RangeError("Footprint tick time must be finite");if(e.time<this._lastTickTime)throw new RangeError("Footprint tick timestamp is out of order");let t=!this._open;this._open&&(t="interval"===this._tf.mode?this._intervalKey(e.time)!==this._time:"ticks"===this._tf.mode?this._count>=this._tf.count&&e.time>this._time:this._volume>=this._tf.perBar&&e.time>this._time),t&&(this._cells=new Map,this._delta=0,this._minDelta=0,this._maxDelta=0,this._count=0,this._volume=0,this._open=!0,this._openPrice=this._high=this._low=e.price,this._time="interval"===this._tf.mode?this._intervalKey(e.time):e.time);const i=o(e.price,this._tickSize);let r=this._cells.get(i);return void 0===r&&(r={price:i,bidVol:0,askVol:0},this._cells.set(i,r)),"bid"===e.side?(r.bidVol+=e.qty,this._delta-=e.qty):(r.askVol+=e.qty,this._delta+=e.qty),this._minDelta=Math.min(this._minDelta,this._delta),this._maxDelta=Math.max(this._maxDelta,this._delta),this._count+=1,this._volume+=e.qty,this._high=Math.max(this._high,e.price),this._low=Math.min(this._low,e.price),this._close=e.price,this._lastTickTime=e.time,{bar:this._snapshot(),isNew:t}}},e.HorizontalProfile=class{constructor(e){Object.defineProperty(this,"_opts",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._opts=e}attached(e){this._host=e}detached(){this._host=null}zOrder(){return"bottom"}autoscaleInfo(){return null}setData(e){this._opts=e,this._host?.requestUpdate()}draw(e,t){const o=this._opts;if(0===o.buckets.length)return;const i=t.dpr,r=o.buckets.reduce((e,t)=>Math.max(e,t.value),0)||1,n=o.width*i,l="left"===o.side?0:t.plotWidth*i,s=Math.max(2*i,t.plotHeight*i/Math.max(1,o.buckets.length)-i);e.save();for(const a of o.buckets){const c=t.priceScale.priceToY(a.price)*i,h=n*(a.value/r),u=a.price<=o.vah&&a.price>=o.val;e.fillStyle=a.price===o.poc?"#f0a020":u?o.vaColor:o.barColor;const p="left"===o.side?l:l-h;e.fillRect(p,c-s/2,h,s)}for(const[r,n]of[[o.poc,"#f0a020"],[o.vah,"#5a6b8c"],[o.val,"#5a6b8c"]]){const o=Math.round(t.priceScale.priceToY(r)*i)+.5;e.strokeStyle=n,e.lineWidth=Math.max(1,Math.round(i)),e.beginPath(),e.moveTo(0,o),e.lineTo(t.plotWidth*i,o),e.stroke()}e.restore()}},e.MarketProfile=class{constructor(e=null,t={}){Object.defineProperty(this,"_result",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_opts",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_boxes",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_rowH",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_rc",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_sessionSplits",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),this._result=e,this._opts={...z,...t}}attached(e){this._host=e}detached(){this._host=null}zOrder(){return this._opts.zOrder}options(){return this._opts}autoscaleInfo(){return null===this._result?null:t(this._result.sessions)}setData(e){this._result=e,this._boxes=[],this._host?.requestUpdate()}setOptions(e){this._opts={...this._opts,...e},void 0!==e.split&&this._sessionSplits.clear(),this._host?.requestUpdate()}isSessionSplit(e){const t=this._sessionKey(e);return null!==t&&(this._sessionSplits.get(t)??this._opts.split)}setSessionSplit(e,t){const o=this._sessionKey(e);return null!==o&&(null===t?this._sessionSplits.delete(o):this._sessionSplits.set(o,t),this._host?.requestUpdate(),!0)}_sessionKey(e){if(!Number.isInteger(e)||e<0||null===this._result)return null;const t=this._result.sessions[e];return void 0===t?null:function(e,t){const o=_(t.window,t.timezone??l);return[t.session,t.compositeSessions,o,t.window?.startMinute??"",t.window?.endMinute??"",b(e,t.session,o,t.window)].join("|")}(t.startTime,this._result.options)}hitTest(e,t){const o=this._boxes.find(t=>e>=t.x0&&e<=t.x1);return void 0===o?null:{externalId:`mp:${o.index}`,zOrder:"normal",distance:0,cursor:"crosshair"}}hoverAt(e,t,o){const i=o??this._rc;if(null===i||null===this._result)return null;const r=this._boxes.find(t=>e>=t.x0&&e<=t.x1);if(void 0===r)return null;const n=this._result.sessions[r.index];if(void 0===n)return null;let l=null,s=1/0;for(const e of n.levels){const o=Math.abs(i.priceScale.priceToY(e.price)-t);o<s&&o<=Math.max(4,this._rowH)&&(s=o,l=e)}return null===l?null:{sessionIndex:r.index,price:l.price,level:l,session:n,isPoc:l.price===n.poc,inValueArea:l.price<=n.vah&&l.price>=n.val,isSinglePrint:n.singlePrints.includes(l.price)}}draw(e,t){if(this._rc=t,this._boxes=[],null===this._result||0===this._result.sessions.length)return;const o=this._result.options,i=o.tickSize*Math.max(1,Math.floor(o.rowTicks)),r="compact"===this._opts.blockDisplay;r&&(e.save(),e.beginPath(),e.rect(0,0,Math.floor(t.plotWidth*t.dpr),Math.floor(t.plotHeight*t.dpr)),e.clip());for(let o=0;o<this._result.sessions.length;o++)this._drawSession(e,t,this._result.sessions[o],i,o);this._opts.showNakedLevels&&this._drawNaked(e,t),r&&e.restore()}_letterAlpha(e){const t=this._opts;if("compact"===t.blockDisplay||"letters"===t.blockDisplay||"blocks+letters"===t.blockDisplay)return 1;if("blocks"===t.blockDisplay)return 0;const o=Math.max(1,t.letterFade);return Math.max(0,Math.min(1,(e-t.minLetterHeight)/o))}_blockColor(e,t,o){const i=this._opts;return"period"===i.colorMode?i.periodColors[t%i.periodColors.length]??i.color:"valueArea"===i.colorMode&&e.price<=o.vah&&e.price>=o.val?i.vaColor:i.color}_drawSession(e,t,o,i,r){const n=this._opts,l=t.dpr,s="compact"===n.blockDisplay,a=this.isSessionSplit(r),c=t.dataLayer.timeToIndex(o.startTime),h=t.dataLayer.timeToIndex(o.endTime);if(void 0===c||void 0===h)return;const u=n.profileSpacing*l;let p=Math.round(t.timeScale.indexToX(c)*l)+u/2;const d=Math.max(p+1,Math.round(t.timeScale.indexToX(h)*l)-u/2),m=p<=t.plotWidth*l&&d>=0;this._boxes.push({index:r,x0:p/l,x1:d/l});const f=e=>t.priceScale.priceToY(e)*l,b=Math.max(1,Math.abs(t.priceScale.priceToY(o.poc)-t.priceScale.priceToY(o.poc+i))*l);this._rowH=b/l;const g=s&&b<12*l,w=Math.floor(Math.min(b,n.font*l)+1e-7),v=g?Math.max(1,Math.min(Math.round(n.letterWidth*l),4*Math.max(1,Math.floor(w/5)))):n.letterWidth*l;n.showSessionOpen&&(p+=v+3*l);const M=n.showLastPrice&&r===this._result.sessions.length-1,_=this._letterAlpha(b/l),x=!s&&("letters"!==n.blockDisplay||_<1);if(e.save(),n.fillValueArea&&d>p){const t=f(o.vah)-b/2,i=f(o.val)+b/2;e.globalAlpha=n.valueAreaFillOpacity,e.fillStyle=n.valueAreaFillColor,e.fillRect(p,t,d-p,i-t),e.globalAlpha=1}let y=1,T=0;for(const e of o.levels)e.count>y&&(y=e.count),e.volume>T&&(T=e.volume);n.showVolumeProfile&&T>0&&this._drawVolume(e,t,o,p,d,b,T);const S=Math.min(n.font*l,.95*b);_>0&&(e.font=`${S}px ui-monospace, SFMono-Regular, Menlo, monospace`,e.textBaseline="middle",e.textAlign="center");const k=Math.max(1,b-Math.min(1.5*l,.15*b)),P="count"===n.colorMode||"volume"===n.colorMode;for(const i of o.levels){const r=f(i.price);if(s&&(r+b/2<0||r-b/2>t.plotHeight*l))continue;const c=i.price<=o.vah&&i.price>=o.val?1:n.outsideVaOpacity,h="count"===n.colorMode?i.count/y:"volume"===n.colorMode&&T>0?i.volume/T:1,u=n.opacity*c*(P?.3+.7*h:1);for(let c=0;c<i.periods.length;c++){const m=a?i.periods[c]:c,f=p+m*v;if(f>d)break;if(s&&(f+v>d||f+v<0||f>t.plotWidth*l))continue;const b=this._blockColor(i,i.periods[c],o);x&&(e.globalAlpha=u,e.fillStyle=b,e.fillRect(f,r-k/2,Math.max(1,v-Math.min(1,.12*v)),k)),_>0&&(e.globalAlpha=s?n.opacity*(P?.3+.7*h:1):_*(x?.95:u),e.fillStyle=x?"#12151c":b,g?N(e,i.letters[c]??"",f+v/2,r,w,v-1)||e.fillRect(Math.round(f),Math.round(r),Math.max(1,Math.floor(v-1)),1):e.fillText(i.letters[c]??"",s?Math.round(f+v/2):f+v/2,s?Math.round(r):r))}}if(e.globalAlpha=1,n.showTpoCounts){e.font=`${Math.min((n.font-1)*l,b)}px ui-monospace, monospace`,e.textAlign="left",e.textBaseline="middle",e.fillStyle=n.countColor;const i=p+((a?o.periods:y)+(M?1:0))*v+3*l;for(const r of o.levels){const o=f(r.price);if(g){if(o+b/2<0||o-b/2>t.plotHeight*l)continue;N(e,String(r.count),i,o,w,Math.max(0,d-i),"left")}else e.fillText(String(r.count),i,o)}}if(n.showSinglePrints&&o.singlePrints.length>0){e.strokeStyle=n.singlePrintColor,e.lineWidth=Math.max(1,Math.round(l));for(const t of o.singlePrints){const o=Math.round(f(t))+.5;e.beginPath(),e.moveTo(p,o),e.lineTo(p+6*l,o),e.stroke()}}if(n.showTails){const t=(t,o)=>{if(null===t)return;e.fillStyle=o,e.globalAlpha=.75;const i=f(t.high)-b/2,r=f(t.low)+b/2;e.fillRect(p-4*l,i,3*l,r-i),e.globalAlpha=1};t(o.sellingTail,n.sellTailColor),t(o.buyingTail,n.buyTailColor)}if(n.showInitialBalance&&Number.isFinite(o.initialBalance.high)){const t=f(o.initialBalance.high),i=f(o.initialBalance.low),r=p-2*l;e.strokeStyle=n.ibColor,e.lineWidth=Math.max(1,Math.round(1.5*l)),e.beginPath(),e.moveTo(r,t),e.lineTo(r,i),e.moveTo(r,t),e.lineTo(r+5*l,t),e.moveTo(r,i),e.lineTo(r+5*l,i),e.stroke()}const C=(t,o,i,r=1)=>{const s=Math.round(f(t))+.5;e.strokeStyle=o,e.lineWidth=Math.max(1,Math.round(r*l)),e.beginPath(),e.moveTo(p,s),e.lineTo(d,s),e.stroke(),""!==i&&(e.font=(n.font-1)*l+"px ui-sans-serif, system-ui, sans-serif",e.textBaseline="middle",e.textAlign="left",e.fillStyle=o,e.fillText(i,d+3*l,s))};n.showValueArea&&(C(o.vah,n.vahColor,n.showValueAreaLabels?`VAH ${t.priceScale.format(o.vah)}`:""),C(o.val,n.valColor,n.showValueAreaLabels?`VAL ${t.priceScale.format(o.val)}`:"")),n.showPoc&&C(o.poc,n.pocColor,n.showPocLabel?`POC ${t.priceScale.format(o.poc)}`:"",n.pocThickness),n.showPoorHighLow&&(o.poorHigh&&C(o.high,n.poorColor,"Poor High"),o.poorLow&&C(o.low,n.poorColor,"Poor Low")),n.showDevelopingPoc&&this._drawDeveloping(e,t,o,"poc",n.developingPocColor),n.showDevelopingVa&&(this._drawDeveloping(e,t,o,"vah",n.developingVaColor),this._drawDeveloping(e,t,o,"val",n.developingVaColor));const A=this._result;if(n.showSessionOpen&&this._drawPriceMarker(e,t,"o",p-v/2-3*l,f(R(o.open,A.options)),b,n.sessionOpenColor),M&&m){const i=R(o.close,A.options),r=o.levels.find(e=>e.price===i);if(void 0!==r){const o=a?(r.periods[r.periods.length-1]??0)+1:r.count,s=Math.max(2,v/2),c=Math.max(s,Math.min(p+(o+.5)*v,t.plotWidth*l-s));this._drawPriceMarker(e,t,"#",c,f(i),b,n.lastPriceColor)}}const V=[];n.showSessionLabel&&void 0!==o.label&&V.push(o.label),n.showDayType&&V.push(L[o.dayType]??o.dayType),n.showOpenType&&V.push(E[o.openType]??o.openType),V.length>0&&(e.font=(n.font-1)*l+"px ui-sans-serif, system-ui, sans-serif",e.textAlign="left",e.textBaseline="bottom",e.fillStyle=n.labelColor,e.fillText(V.join("  ·  "),p,f(o.high)-b)),e.restore()}_drawPriceMarker(e,t,o,i,r,n,l){const s=Math.max(5,Math.min(n,this._opts.font*t.dpr));e.save(),e.globalAlpha=this._opts.opacity,e.fillStyle=l,n<12*t.dpr?N(e,o,i,r,s,Math.max(3,s)):(e.font=`${s}px ui-monospace, SFMono-Regular, Menlo, monospace`,e.textAlign="center",e.textBaseline="middle",e.fillText(o,Math.round(i),r)),e.restore()}_drawVolume(e,t,o,i,r,n,l){const s=this._opts,a=t.dpr,c=s.volumeProfileWidth*a,h="right"===s.volumeProfileSide,u="compact"===s.blockDisplay,p=e=>!u||e+n/2>=0&&e-n/2<=t.plotHeight*a;e.globalAlpha=.55,e.fillStyle=s.volumeColor;for(const s of o.levels){if(!p(t.priceScale.priceToY(s.price)*a))continue;const o=c*(s.volume/l),u=t.priceScale.priceToY(s.price)*a-n/2;e.fillRect(h?r-o:i,u,o,Math.max(1,n-1))}if(e.globalAlpha=1,s.showVolumeValues&&n>=(u?5-1e-7:7*a)){e.font=`${Math.min(9*a,.9*n)}px ui-monospace, monospace`,e.textBaseline="middle",e.textAlign=h?"right":"left",e.fillStyle=s.countColor;for(const l of o.levels){const o=t.priceScale.priceToY(l.price)*a;if(!p(o))continue;const s=Math.round(l.volume).toString(),d=h?r-2*a:i+2*a;u&&n<12*a?N(e,s,d,o,Math.min(n,9*a),Math.max(0,c-4*a),h?"right":"left"):e.fillText(s,d,o)}}}_drawDeveloping(e,t,o,i,r){if(0===o.developing.length)return;const n=t.dpr;e.save(),e.strokeStyle=r,e.lineWidth=Math.max(1,Math.round(n)),e.beginPath();let l=!1;for(const r of o.developing){const o=t.dataLayer.timeToIndex(r.time);if(void 0===o)continue;const s=t.timeScale.indexToX(o)*n,a=Math.round(t.priceScale.priceToY(r[i])*n)+.5;l?e.lineTo(s,a):(e.moveTo(s,a),l=!0)}l&&e.stroke(),e.restore()}_drawNaked(e,t){const o=this._opts,i=t.dpr,r=O(this._result);if(0===r.length)return;e.save(),e.strokeStyle=o.nakedColor,e.lineWidth=Math.max(1,Math.round(i)),e.setLineDash([4*i,3*i]);const n=t.plotWidth*i;for(const o of r){const r=t.dataLayer.timeToIndex(o.time);if(void 0===r)continue;const l=Math.round(t.priceScale.priceToY(o.price)*i)+.5;e.beginPath(),e.moveTo(t.timeScale.indexToX(r)*i,l),e.lineTo(n,l),e.stroke()}e.setLineDash([]),e.restore()}},e.PROFILE_TIER="profile",e.TPO_PERIOD_COLORS=I,e.TRADING_HOURS={"all-hours":{startMinute:0,endMinute:0,name:"All Hours"},india:{startMinute:555,endMinute:930,zone:"Asia/Kolkata",name:"India"},asia:{startMinute:540,endMinute:900,zone:"Asia/Tokyo",name:"Asia"},london:{startMinute:420,endMinute:780,zone:"Europe/London",name:"London"},"new-york":{startMinute:480,endMinute:930,zone:"America/New_York",name:"New York"},"us-regular":{startMinute:570,endMinute:960,zone:"America/New_York",name:"US Regular"}},e.VolumeProfile=class{constructor(e=null,t={}){Object.defineProperty(this,"_result",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_opts",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._result=e,this._opts={...w,...t}}attached(e){this._host=e}detached(){this._host=null}zOrder(){return this._opts.zOrder}autoscaleInfo(){return null===this._result?null:t(this._result.sessions)}setData(e){this._result=e,this._host?.requestUpdate()}setOptions(e){this._opts={...this._opts,...e},this._host?.requestUpdate()}draw(e,t){if(null===this._result||0===this._result.sessions.length)return;const o=this._result.options.tickSize;for(const i of this._result.sessions)this._drawSession(e,t,i,o)}_segments(e,t,o){const i=this._opts;if("delta"===i.displayMode){const r=Math.abs(e.delta)/t*o;return[{color:e.delta>=0?i.buyColor:i.sellColor,len:r}]}const r=e.volume/t*o;if("buySell"===i.displayMode&&e.volume>0){const t=r*(e.buyVolume/e.volume);return[{color:i.buyColor,len:t},{color:i.sellColor,len:r-t}]}return[{color:i.barColor,len:r}]}_drawSession(e,t,o,i){const r=this._opts,n=t.dpr,l=t.dataLayer.timeToIndex(o.startTime),s=t.dataLayer.timeToIndex(o.endTime);if(void 0===l||void 0===s)return;const a=Math.round(t.timeScale.indexToX(l)*n),c=Math.max(a+1,Math.round(t.timeScale.indexToX(s)*n)),h=e=>t.priceScale.priceToY(e)*n,u=Math.max(1,Math.abs(t.priceScale.priceToY(o.poc)-t.priceScale.priceToY(o.poc+i))*n),p=r.width*n,d="right"===r.side?c:a;let m=0;for(const e of o.levels){const t="delta"===r.displayMode?Math.abs(e.delta):e.volume;t>m&&(m=t)}if(m<=0&&(m=1),e.save(),r.highlightValueArea){const t=h(o.vah)-u/2,i=h(o.val)+u/2,n="right"===r.side?c-p:a;e.globalAlpha=r.valueAreaFillOpacity,e.fillStyle=r.valueAreaFillColor,e.fillRect(n,t,p,i-t),e.globalAlpha=1}for(const t of o.levels){const i=t.price<=o.vah&&t.price>=o.val,n=r.opacity*(i?1:r.valueAreaOpacityDim),l=h(t.price)-u/2,s=Math.max(1,u-1);let a=d;e.globalAlpha=n;for(const o of this._segments(t,m,p)){if(o.len<=0)continue;const t="right"===r.side?a-o.len:a;e.fillStyle=o.color,e.fillRect(t,l,o.len,s),a="right"===r.side?a-o.len:a+o.len}}e.globalAlpha=1;const f=(t,o,i)=>{const l=Math.round(h(t))+.5;e.strokeStyle=o,e.lineWidth=Math.max(1,Math.round(n)),e.beginPath(),e.moveTo(a,l),e.lineTo(c,l),e.stroke(),""!==i&&(e.font=9*n+"px ui-sans-serif, system-ui, sans-serif",e.textBaseline="middle",e.fillStyle=o,"right"===r.labelSide?(e.textAlign="left",e.fillText(i,c+3*n,l)):(e.textAlign="right",e.fillText(i,a-3*n,l)))};r.showValueArea&&(f(o.vah,r.vahColor,r.showValueAreaLabels?`VAH ${t.priceScale.format(o.vah)}`:""),f(o.val,r.valColor,r.showValueAreaLabels?`VAL ${t.priceScale.format(o.val)}`:"")),r.showPoc&&f(o.poc,r.pocColor,r.showPocLabel?`POC ${t.priceScale.format(o.poc)}`:""),e.restore()}},e.bucketPrice=o,e.compactVol=ee,e.computeFootprint=function(e,t,i,r=1){const n=j(i,r);if(!Number.isFinite(e))throw new RangeError("Footprint time must be finite");for(const e of t)H(e);const l=new Map;let s=0,a=0,c=0;for(const e of t){const t=o(e.price,n);let i=l.get(t);void 0===i&&(i={price:t,bidVol:0,askVol:0},l.set(t,i)),"bid"===e.side?(i.bidVol+=e.qty,s-=e.qty):(i.askVol+=e.qty,s+=e.qty),a=Math.min(a,s),c=Math.max(c,s)}const h={time:e,cells:Array.from(l.values()).sort((e,t)=>t.price-e.price),delta:s,minDelta:a,maxDelta:c,rowSize:n,tradeCount:t.length};if(t.length>0){h.open=t[0].price,h.close=t[t.length-1].price,h.high=h.low=t[0].price;for(const e of t)h.high=Math.max(h.high,e.price),h.low=Math.min(h.low,e.price)}return h},e.computeMarketProfile=function(e,t={}){const o={...v,...t},i=o.tickSize>0?o.tickSize:v.tickSize,r=Math.max(1,Math.floor(o.rowTicks)),n=o.timezone??l,s={row:i*r,blockSec:Math.max(1,Math.round(60*o.blockMinutes)),vaPct:Math.min(1,Math.max(0,o.valueAreaPercent)),ibPeriods:Math.max(1,Math.floor(o.initialBalancePeriods)),tailEdges:o.tailEdges,win:o.window,cal:_(o.window,n)},a=[];for(const t of function(e,t,o,i){const r=t.window,n=Math.max(1,Math.floor(t.compositeSessions)),l=new Map,s=[];for(const n of e){if(void 0!==r&&!x(n.time,r,o))continue;const e=b(n.time,t.session,i,r);let a=l.get(e);void 0===a&&(a=[],l.set(e,a),s.push(e)),a.push(n)}const a=[];if(n>1&&"composite"!==t.session)for(let e=0;e<s.length;e+=n){const t=[];for(let o=e;o<Math.min(e+n,s.length);o++)t.push(...l.get(s[o]));a.push(t)}else for(const e of s)a.push(l.get(e));return a}(e,o,n,s.cal)){const e=C(t,s);null!==e&&a.push(e)}return{sessions:a,options:{...o,rowTicks:r,timezone:n}}},e.computeTpo=function(e,t,o,n=.7,l=2){const s=Math.max(1,t),a=new Map;let c=-1/0,h=1/0;const u=Math.ceil(e.length/s);for(let t=0;t<u;t++){const r=e.slice(t*s,(t+1)*s);if(0===r.length)continue;let n=-1/0,u=1/0;for(const e of r)n=Math.max(n,e.high),u=Math.min(u,e.low);t<l&&(c=Math.max(c,n),h=Math.min(h,u));for(const e of i(u,n,o))a.set(e,(a.get(e)??0)+1)}const p=Array.from(a.entries()).map(([e,t])=>({price:e,count:t})).sort((e,t)=>t.price-e.price);if(0===p.length)return{buckets:p,poc:0,vah:0,val:0,ib:{high:0,low:0}};const d=p.reduce((e,t)=>e+t.count,0),m=r(p.map(e=>e.count),d*n);return{buckets:p,poc:p[m.poc].price,vah:p[m.upper].price,val:p[m.lower].price,ib:{high:c,low:h}}},e.computeVolumeProfile=function(e,t,o=.7){const n=new Map;for(const o of e){const e=i(o.low,o.high,t),r=(o.volume??0)/e.length;for(const t of e)n.set(t,(n.get(t)??0)+r)}const l=Array.from(n.entries()).map(([e,t])=>({price:e,volume:t})).sort((e,t)=>t.price-e.price);if(0===l.length)return{buckets:l,poc:0,vah:0,val:0,totalVolume:0};const s=l.reduce((e,t)=>e+t.volume,0),a=r(l.map(e=>e.volume),s*o);return{buckets:l,poc:l[a.poc].price,vah:l[a.upper].price,val:l[a.lower].price,totalVolume:s}},e.computeVolumeProfileSessions=function(e,t={}){const o={...g,...t},n=o.tickSize>0?o.tickSize:g.tickSize,s=Math.min(1,Math.max(0,o.valueAreaPercent)),a=o.timezone??l,c=new Map,h=[];for(const t of e){const e=b(t.time,o.session,a);let i=c.get(e);void 0===i&&(i=[],c.set(e,i),h.push(e)),i.push(t)}const u=[];for(const e of h){const t=c.get(e);if(0===t.length)continue;const l=new Map;let a=0,h=0,p=0;for(const e of t){const t=e.volume??0;a+=t;const r=e.close>=e.open,s=o.deltaFromBarDirection&&r?t:0,c=o.deltaFromBarDirection?r?0:t:0;h+=s,p+=c;const u=i(e.low,e.high,n),d=Math.max(1,u.length),m=t/d,f=s/d,b=c/d;for(const e of u){let t=l.get(e);void 0===t&&(t={volume:0,buy:0,sell:0},l.set(e,t)),t.volume+=m,t.buy+=f,t.sell+=b}}const d=Array.from(l.entries()).map(([e,t])=>({price:e,volume:t.volume,buyVolume:t.buy,sellVolume:t.sell,delta:t.buy-t.sell})).sort((e,t)=>t.price-e.price);if(0===d.length)continue;const m=r(d.map(e=>e.volume),a*s);u.push({startTime:t[0].time,endTime:t[t.length-1].time,levels:d,poc:d[m.poc].price,vah:d[m.upper].price,val:d[m.lower].price,totalVolume:a,buyVolume:h,sellVolume:p,delta:h-p})}return{sessions:u,options:{...o,timezone:a}}},e.cumulativeDelta=function(e){const t=[];let o=0;for(const i of e)o+=i.delta,t.push(o);return t},e.diagonalImbalances=B,e.inWindow=x,e.nakedLevels=O,e.priceBuckets=i,e.rowOf=R,e.rowTicksFor=function(e,t){return e>0&&t>0?Math.max(1,Math.round(e/t)):1},e.stackedImbalances=Y,e.tpoLetter=M,e}({});