@tradecanvas/core 0.4.0 โ†’ 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -16,6 +16,6 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require
16
16
  cursor: pointer;
17
17
  color: ${n?`#26A69A`:`#EF5350`};
18
18
  transition: background 0.1s;
19
- `,t.addEventListener(`mouseenter`,()=>{t.style.background=`#2a2e39`}),t.addEventListener(`mouseleave`,()=>{t.style.background=`transparent`}),t.addEventListener(`click`,()=>{this.onItemSelect?.(e.intent),this.hide()}),o.appendChild(t)}n.appendChild(o),this.menuElement=o;let c=e=>{(e instanceof KeyboardEvent&&e.key===`Escape`||e instanceof MouseEvent&&!o.contains(e.target))&&this.hide()};document.addEventListener(`mousedown`,c),document.addEventListener(`keydown`,c),this.removeHandler=()=>{document.removeEventListener(`mousedown`,c),document.removeEventListener(`keydown`,c)}}hide(){this.menuElement?.remove(),this.menuElement=null,this.removeHandler?.(),this.removeHandler=null}destroy(){this.hide(),this.onItemSelect=null}},gt=class{orders=[];positions=[];depthData=null;currentPrice=null;config;orderRenderer=new dt;positionRenderer=new ft;depthOverlay=new pt;dragHandler;contextMenu=new ht;requestRender=null;eventCallback=null;container=null;constructor(t){this.config={...e.DEFAULT_TRADING_CONFIG,...t},this.dragHandler=new mt(this.config.dragThreshold),this.contextMenu.onItemSelect=e=>{this.eventCallback?.(`orderPlace`,e)}}setContainer(e){this.container=e}setRequestRender(e){this.requestRender=e}setEventCallback(e){this.eventCallback=e}setOrders(e){this.orders=e,this.requestRender?.()}setPositions(e){this.positions=e,this.requestRender?.()}setDepthData(e){this.depthData=e,this.requestRender?.()}setCurrentPrice(e){this.currentPrice=e,this.requestRender?.()}setConfig(e){Object.assign(this.config,e),this.requestRender?.()}onPointerDown(e,t){return this.config.enabled?this.dragHandler.onPointerDown(e,this.orders,this.positions,t,8):!1}onPointerMove(e,t){if(!this.dragHandler.isActive())return!1;let n=this.dragHandler.onPointerMove(e,t);return n&&this.requestRender?.(),n}onPointerUp(){let e=this.dragHandler.onPointerUp();return e?(e.sourceType===`order`?this.eventCallback?.(`orderModify`,{orderId:e.id,newPrice:e.newPrice,previousPrice:e.previousPrice}):this.eventCallback?.(`positionModify`,{positionId:e.id,[e.sourceType]:e.newPrice}),this.requestRender?.(),!0):!1}onContextMenu(e,t){if(!this.config.enabled||!this.config.contextMenu?.enabled||!this.container)return!1;let n=c(e.y,t);return this.contextMenu.show(e,n,this.container,this.config),!0}render(e,t,n){this.config.enabled&&(this.depthData&&this.depthOverlay.render(e,this.depthData,t,this.config),this.positions.length>0&&this.positionRenderer.render(e,this.positions,this.currentPrice,t,n,this.config),this.orders.length>0&&this.orderRenderer.render(e,this.orders,t,n,this.config,this.dragHandler.getDragState()))}renderAxisBadges(e,t,n){this.config.enabled&&(this.positions.length>0&&this.positionRenderer.renderAxisBadges(e,this.positions,t,n,this.config),this.orders.length>0&&this.orderRenderer.renderAxisBadges(e,this.orders,t,n,this.config,this.dragHandler.getDragState()))}destroy(){this.contextMenu.destroy()}},_t=class{constructor(e){this.manager=e}render(e,t,n){this.manager.render(e,t,n)}renderAxisBadges(e,t,n){this.manager.renderAxisBadges(e,t,n)}},G=class{listeners=new Map;on(e,t){let n=this.listeners.get(e);return n||(n=new Set,this.listeners.set(e,n)),n.add(t),()=>n.delete(t)}once(e,t){let n=this.on(e,e=>{n(),t(e)});return n}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){let n=this.listeners.get(e);if(n)for(let e of n)e(t)}removeAllListeners(){this.listeners.clear()}},vt=class extends G{currentBar=null;timeframeMs;tickRing;ringHead=0;ringCount=0;ringCapacity;constructor(t,n=1e3){super(),this.timeframeMs=(0,e.timeframeToMs)(t),this.ringCapacity=n,this.tickRing=Array(n)}setTimeframe(t){this.timeframeMs=(0,e.timeframeToMs)(t),this.currentBar=null,this.ringHead=0,this.ringCount=0}processTick(e){let t=(this.ringHead+this.ringCount)%this.ringCapacity;this.tickRing[t]=e,this.ringCount<this.ringCapacity?this.ringCount++:this.ringHead=(this.ringHead+1)%this.ringCapacity;let n=this.alignToTimeframe(e.time);!this.currentBar||this.currentBar.time!==n?(this.currentBar&&(this.currentBar.closed=!0,this.emit(`barClose`,this.currentBar)),this.currentBar={time:n,open:e.price,high:e.price,low:e.price,close:e.price,volume:e.volume,closed:!1,tickCount:1}):(this.currentBar.high=Math.max(this.currentBar.high,e.price),this.currentBar.low=Math.min(this.currentBar.low,e.price),this.currentBar.close=e.price,this.currentBar.volume+=e.volume,this.currentBar.tickCount++),this.emit(`bar`,this.currentBar)}processBar(e,t){if(t&&this.currentBar&&this.currentBar.time===e.time)this.currentBar={...e,closed:!0,tickCount:this.currentBar.tickCount+1},this.emit(`barClose`,this.currentBar),this.currentBar=null;else if(!t)this.currentBar={...e,closed:!1,tickCount:(this.currentBar?.tickCount??0)+1},this.emit(`bar`,this.currentBar);else{let t={...e,closed:!0,tickCount:1};this.emit(`barClose`,t),this.currentBar=null}}getCurrentBar(){return this.currentBar?{...this.currentBar}:null}getTickBuffer(){let e=Array(this.ringCount);for(let t=0;t<this.ringCount;t++)e[t]=this.tickRing[(this.ringHead+t)%this.ringCapacity];return e}reset(){this.currentBar=null,this.ringHead=0,this.ringCount=0}alignToTimeframe(e){return Math.floor(e/this.timeframeMs)*this.timeframeMs}},K=class extends G{config;attempt=0;timer=null;active=!1;constructor(t){super(),this.config={...e.DEFAULT_RECONNECT,...t}}schedule(e){if(!this.config.enabled||!this.active)return;if(this.attempt++,this.attempt>this.config.maxRetries){this.emit(`giveUp`,{attempts:this.attempt-1}),this.active=!1;return}let t=this.computeDelay();this.emit(`attempt`,{attempt:this.attempt,delay:t}),this.timer=setTimeout(()=>{this.timer=null,this.active&&e()},t)}onConnected(){this.attempt=0,this.cancel(),this.emit(`success`,void 0)}start(){this.active=!0}stop(){this.active=!1,this.cancel(),this.attempt=0}cancel(){this.timer&&=(clearTimeout(this.timer),null)}getAttempt(){return this.attempt}isActive(){return this.active}computeDelay(){let e=this.config.baseDelay,t=this.config.backoffMultiplier**(this.attempt-1),n=Math.min(e*t,this.config.maxDelay),r=n*.25*(Math.random()*2-1);return Math.max(0,Math.round(n+r))}},yt=class{price=null;previousClose=null;visible=!0;flashUntil=0;pricePrecision=2;setPrice(e,t){this.price!==null&&e!==this.price&&(this.flashUntil=Date.now()+300),this.previousClose=t??this.price??e,this.price=e}setVisible(e){this.visible=e}setPricePrecision(e){this.pricePrecision=e}getPrice(){return this.price}render(t,n,r){if(!this.visible||this.price===null)return;let i=o(this.price,n),{chartRect:a}=n;if(i<a.y||i>a.y+a.height)return;let s=this.previousClose===null||this.price>=this.previousClose?r.candleUp??`#26A69A`:r.candleDown??`#EF5350`,c=Date.now()<this.flashUntil;t.setLineDash([4,3]),t.strokeStyle=s,t.lineWidth=1,t.globalAlpha=c?1:.7,t.beginPath(),t.moveTo(a.x,Math.round(i)+.5),t.lineTo(a.x+a.width,Math.round(i)+.5),t.stroke(),t.setLineDash([]),t.globalAlpha=1;let l=a.x+a.width+1,u=this.price.toFixed(this.pricePrecision);t.font=`bold 11px ${r.font.family}`;let d=t.measureText(u).width,f=Math.min(d+12,e.PRICE_AXIS_WIDTH-2);t.fillStyle=s,t.fillRect(l,i-10,f,20);let p=l-5;t.beginPath(),t.moveTo(p,i),t.lineTo(p+5,i-5),t.lineTo(p+5,i+5),t.closePath(),t.fill(),t.fillStyle=`#FFFFFF`,t.textBaseline=`middle`,t.textAlign=`left`,t.fillText(u,l+5,i)}},bt=class extends G{config=null;adapter=null;aggregator=null;reconnector;priceLine=new yt;state=`disconnected`;lastPrice=null;previousClose=null;unsubscribers=[];heartbeatTimer=null;lastMessageTime=0;constructor(){super(),this.reconnector=new K,this.wireReconnector()}async connect(t){this.disconnect(),this.config={...e.DEFAULT_STREAM_CONFIG,...t},this.adapter=t.adapter,this.aggregator=new vt(t.timeframe),this.reconnector.removeAllListeners(),this.reconnector.stop(),this.reconnector=new K(t.reconnect??e.DEFAULT_RECONNECT),this.wireReconnector(),this.aggregator.on(`bar`,e=>{this.emit(`barUpdate`,e),this.updatePrice(e.close)}),this.aggregator.on(`barClose`,e=>{this.previousClose=e.close,this.emit(`barClose`,e)}),this.wireAdapter(),this.reconnector.start(),await this.doConnect()}disconnect(){this.reconnector.stop(),this.stopHeartbeat();for(let e of this.unsubscribers)e();this.unsubscribers=[],this.adapter&&=(this.adapter.disconnect(),null),this.aggregator?.reset(),this.aggregator?.removeAllListeners(),this.aggregator=null,this.config=null,this.lastPrice=null,this.previousClose=null,this.setState(`disconnected`)}async switchTo(e,t){!this.config||!this.adapter||(this.adapter.disconnect(),this.aggregator?.reset(),this.aggregator?.setTimeframe(t),this.lastPrice=null,this.previousClose=null,this.config.symbol=e,this.config.timeframe=t,await this.doConnect())}getConnectionState(){return this.state}getConnectionInfo(){return{state:this.state,reconnectAttempt:this.reconnector.getAttempt(),lastMessageTime:this.lastMessageTime}}getLastPrice(){return this.lastPrice}async doConnect(){if(!(!this.config||!this.adapter)){this.setState(`connecting`);try{let e=await this.adapter.fetchHistory(this.config.symbol,this.config.timeframe,this.config.historyLimit??500);e.length>0&&(this.previousClose=e[e.length-1].close,this.updatePrice(e[e.length-1].close)),this.emit(`snapshot`,e),this.adapter.connect({symbol:this.config.symbol,timeframe:this.config.timeframe}),this.startHeartbeat()}catch(e){let t=e instanceof Error?e.message:String(e);this.emit(`error`,{message:t,code:`CONNECT_FAILED`}),this.setState(`error`),this.reconnector.schedule(()=>this.doConnect())}}}wireReconnector(){this.reconnector.on(`attempt`,({attempt:e,delay:t})=>{this.setState(`reconnecting`),this.emit(`connectionChange`,{state:`reconnecting`,reconnectAttempt:e,lastMessageTime:this.lastMessageTime})}),this.reconnector.on(`giveUp`,({attempts:e})=>{this.setState(`error`),this.emit(`error`,{message:`Reconnection failed after ${e} attempts`,code:`RECONNECT_EXHAUSTED`})})}wireAdapter(){if(!this.adapter)return;let e=this.adapter,t=e=>{let t=e.data;this.lastMessageTime=Date.now(),t===`connected`?(this.reconnector.onConnected(),this.setState(`connected`)):(t===`disconnected`||t===`error`)&&this.reconnector.schedule(()=>this.doConnect())};e.on(`connectionChange`,t),this.unsubscribers.push(()=>e.off(`connectionChange`,t));let n=e=>{this.lastMessageTime=Date.now();let t=e.data;this.emit(`tick`,t),this.config?.aggregateTicks&&this.aggregator?this.aggregator.processTick(t):this.updatePrice(t.price)};e.on(`tick`,n),this.unsubscribers.push(()=>e.off(`tick`,n));let r=e=>{this.lastMessageTime=Date.now();let{bar:t,closed:n}=e.data;this.aggregator&&this.aggregator.processBar(t,n)};e.on(`bar`,r),this.unsubscribers.push(()=>e.off(`bar`,r));let i=e=>{this.emit(`error`,{message:e.data?.message??`Adapter error`})};e.on(`error`,i),this.unsubscribers.push(()=>e.off(`error`,i))}updatePrice(e){e!==this.lastPrice&&(this.lastPrice=e,this.priceLine.setPrice(e,this.previousClose??void 0),this.emit(`priceChange`,{price:e,previousClose:this.previousClose}))}setState(e){this.state!==e&&(this.state=e,this.emit(`connectionChange`,{state:e,reconnectAttempt:this.reconnector.getAttempt(),lastMessageTime:this.lastMessageTime}))}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{Date.now()-this.lastMessageTime>6e4&&this.state===`connected`&&(this.emit(`error`,{message:`Heartbeat timeout`,code:`HEARTBEAT_TIMEOUT`}),this.adapter?.disconnect(),this.reconnector.schedule(()=>this.doConnect()))},3e4)}stopHeartbeat(){this.heartbeatTimer&&=(clearInterval(this.heartbeatTimer),null)}dispose(){this.disconnect(),this.removeAllListeners()}},xt={"1s":`1s`,"1m":`1m`,"3m":`3m`,"5m":`5m`,"15m":`15m`,"30m":`30m`,"1h":`1h`,"2h":`2h`,"4h":`4h`,"6h":`6h`,"8h":`8h`,"12h":`12h`,"1d":`1d`,"3d":`3d`,"1w":`1w`,"1M":`1M`},St=class{name=`binance`;ws=null;state=`disconnected`;listeners=new Map;config=null;restBase;wsBase;constructor(e){this.restBase=e?.restBase??`https://api.binance.com/api/v3`,this.wsBase=e?.wsBase??`wss://stream.binance.com:9443/ws`}connect(e){this.config=e,this.connectWs()}disconnect(){this.ws&&=(this.ws.onclose=null,this.ws.close(),null),this.setState(`disconnected`)}getConnectionState(){return this.state}async fetchHistory(e,t,n=500){let r=xt[t]??`15m`,i=`${this.restBase}/klines?symbol=${e}&interval=${r}&limit=${n}`,a=await fetch(i);if(!a.ok)throw Error(`Binance REST error: ${a.status}`);return(await a.json()).map(e=>({time:e[0],open:parseFloat(e[1]),high:parseFloat(e[2]),low:parseFloat(e[3]),close:parseFloat(e[4]),volume:parseFloat(e[5])}))}on(e,t){let n=this.listeners.get(e);n||(n=new Set,this.listeners.set(e,n)),n.add(t)}off(e,t){this.listeners.get(e)?.delete(t)}dispose(){this.disconnect(),this.listeners.clear()}connectWs(){if(!this.config)return;let e=`${this.config.symbol.toLowerCase()}@kline_${xt[this.config.timeframe]??`15m`}`,t=`${this.wsBase}/${e}`;this.setState(`connecting`);try{this.ws=new WebSocket(t)}catch{this.setState(`error`),this.emitEvent(`error`,{message:`WebSocket creation failed`}),this.emitEvent(`connectionChange`,`error`);return}this.ws.onopen=()=>{this.setState(`connected`),this.emitEvent(`connectionChange`,`connected`)},this.ws.onmessage=e=>{try{let t=JSON.parse(e.data);t.e===`kline`&&this.handleKline(t.k)}catch{}},this.ws.onerror=()=>{this.setState(`error`),this.emitEvent(`error`,{message:`WebSocket error`})},this.ws.onclose=()=>{this.setState(`disconnected`),this.emitEvent(`connectionChange`,`disconnected`)}}handleKline(e){let t={time:e.t,open:parseFloat(e.o),high:parseFloat(e.h),low:parseFloat(e.l),close:parseFloat(e.c),volume:parseFloat(e.v)},n=e.x;this.emitEvent(`bar`,{bar:t,closed:n}),this.emitEvent(`tick`,{time:Date.now(),price:t.close,volume:t.volume})}setState(e){this.state=e}emitEvent(e,t){let n=this.listeners.get(e);if(n){let r={type:e,data:t,timestamp:Date.now()};for(let e of n)e(r)}}},Ct=class{name=`mock`;state=`disconnected`;listeners=new Map;config=null;options;tickTimer=null;currentPrice;constructor(e){this.options={basePrice:100,volatility:1.5,tickInterval:2e3,historySize:500,...e},this.currentPrice=this.options.basePrice}connect(e){this.config=e,this.state=`connected`,this.emitEvent(`connectionChange`,`connected`),this.startTicking()}disconnect(){this.stopTicking(),this.state=`disconnected`,this.emitEvent(`connectionChange`,`disconnected`)}getConnectionState(){return this.state}async fetchHistory(e,t,n){return this.options.historyGenerator?this.options.historyGenerator(e,t,n??this.options.historySize):this.generateHistory(t,n??this.options.historySize)}on(e,t){let n=this.listeners.get(e);n||(n=new Set,this.listeners.set(e,n)),n.add(t)}off(e,t){this.listeners.get(e)?.delete(t)}dispose(){this.disconnect(),this.listeners.clear()}generateHistory(t,n){let r=[],i=Date.now(),a=(0,e.timeframeToMs)(t),o=this.options.basePrice,s=this.options.volatility/100;for(let e=n-1;e>=0;e--){let t=i-e*a,n=(Math.random()-.48)*o*s,c=o;o+=n;let l=Math.max(c,o)+Math.random()*o*s*.3,u=Math.min(c,o)-Math.random()*o*s*.3,d=Math.floor(1e4+Math.random()*1e5);r.push({time:t,open:c,high:l,low:u,close:o,volume:d})}return this.currentPrice=o,r}startTicking(){this.stopTicking();let t=this.options.tickInterval??2e3;this.tickTimer=setInterval(()=>{if(this.state!==`connected`||!this.config)return;let t=this.options.volatility/100,n=(Math.random()-.48)*this.currentPrice*t*.3;this.currentPrice+=n;let r=Date.now(),i=(0,e.timeframeToMs)(this.config.timeframe),a={time:Math.floor(r/i)*i,open:this.currentPrice-n,high:Math.max(this.currentPrice,this.currentPrice-n)+Math.abs(n)*.2,low:Math.min(this.currentPrice,this.currentPrice-n)-Math.abs(n)*.2,close:this.currentPrice,volume:Math.floor(100+Math.random()*5e3)};this.emitEvent(`bar`,{bar:a,closed:!1}),this.emitEvent(`tick`,{time:r,price:this.currentPrice,volume:a.volume})},t)}stopTicking(){this.tickTimer&&=(clearInterval(this.tickTimer),null)}emitEvent(e,t){let n=this.listeners.get(e);if(n){let r={type:e,data:t,timestamp:Date.now()};for(let e of n)e(r)}}},wt={visible:!0,showSymbol:!0,showOHLC:!0,showChange:!0,showVolume:!0,position:`top-left`,fontSize:12},Tt=class{config={...wt};symbol=``;timeframe=``;hoverBar=null;indicators=[];setConfig(e){Object.assign(this.config,e)}setSymbol(e){this.symbol=e}setTimeframe(e){this.timeframe=e}setChartType(e){}setHoverBar(e){this.hoverBar=e}setIndicatorValues(e){this.indicators=e}render(e,t,n,r){if(!this.config.visible||r.length===0)return;let i=this.hoverBar??r[r.length-1],a=r.length>1?r[r.length-2]:i,{chartRect:o}=t,s=this.config.fontSize,c=this.config.position===`top-left`,l=c?o.x+8:o.x+o.width-8,u=o.y+6;if(e.textAlign=c?`left`:`right`,e.textBaseline=`top`,this.config.showSymbol){e.font=`bold ${s+2}px ${n.font.family}`,e.fillStyle=n.text;let t=[this.symbol,this.timeframe].filter(Boolean).join(` ยท `);e.fillText(t,l,u),u+=s+6}if(this.config.showOHLC){e.font=`${s}px ${n.font.family}`;let t=i.close>=i.open,r=e=>e.toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2}),o=[{label:`O`,value:r(i.open),color:n.text},{label:`H`,value:r(i.high),color:n.text},{label:`L`,value:r(i.low),color:n.text},{label:`C`,value:r(i.close),color:t?n.candleUp:n.candleDown}];if(this.config.showChange){let e=i.close-a.close,t=a.close===0?0:e/a.close*100,s=e>=0?`+`:``;o.push({label:``,value:`${s}${r(e)} (${s}${t.toFixed(2)}%)`,color:e>=0?n.candleUp:n.candleDown})}let d=l;if(c)for(let t of o)t.label&&(e.fillStyle=n.textSecondary,e.fillText(t.label,d,u),d+=e.measureText(t.label+` `).width),e.fillStyle=t.color,e.fillText(t.value,d,u),d+=e.measureText(t.value+` `).width;else{let t=o.map(e=>`${e.label} ${e.value}`).join(` `);e.fillStyle=n.text,e.fillText(t,l,u)}u+=s+3}if(this.config.showVolume){e.font=`${s-1}px ${n.font.family}`,e.fillStyle=n.textSecondary;let t=i.volume>=1e6?`${(i.volume/1e6).toFixed(2)}M`:i.volume>=1e3?`${(i.volume/1e3).toFixed(2)}K`:i.volume.toFixed(0);e.fillText(`Vol ${t}`,l,u),u+=s+2}if(this.indicators.length>0){e.font=`${s-1}px ${n.font.family}`;let t=l;for(let n of this.indicators){e.fillStyle=n.color;let r=`${n.name} ${n.value}`;e.fillText(r,t,u),t+=e.measureText(r+` `).width}}}},Et=class{static toDataURL(e,t){let n=e.querySelectorAll(`canvas`);if(n.length===0)return``;let r=n[0],i=r.width,a=r.height,o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);t&&(s.fillStyle=t,s.fillRect(0,0,i,a));let c=Array.from(n).sort((e,t)=>(parseInt(e.style.zIndex)||0)-(parseInt(t.style.zIndex)||0));for(let e of c)s.drawImage(e,0,0);return o.toDataURL(`image/png`)}static async toBlob(e,t){let n=this.toDataURL(e,t);return n?(await fetch(n)).blob():null}static download(e,t=`chart.png`,n){let r=this.toDataURL(e,n);if(!r)return;let i=document.createElement(`a`);i.href=r,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}},Dt=class{config=null;setConfig(e){this.config=e}render(e,t,n){if(!this.config?.text)return;let{chartRect:r}=t,i=this.config.fontSize??48,a=this.config.color??n.textSecondary;e.save(),e.globalAlpha=.07,e.font=`bold ${i}px ${n.font.family}`,e.fillStyle=a,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(this.config.text,r.x+r.width/2,r.y+r.height/2),e.restore()}},Ot=class{visible=!0;timeframeMs=0;setVisible(e){this.visible=e}isVisible(){return this.visible}setTimeframeMs(e){this.timeframeMs=e}render(e,t,n,r){if(!this.visible||this.timeframeMs<=0||r.length===0)return;let i=r[r.length-1],o=(i.time>0xe8d4a51000?i.time:i.time*1e3)+this.timeframeMs-Date.now();if(o<=0)return;let s=this.formatRemaining(o),c=a(r.length-1,t),l=t.chartRect.y+t.chartRect.height-4;c<t.chartRect.x||c>t.chartRect.x+t.chartRect.width||(e.font=`${n.font.sizeSmall}px ${n.font.family}`,e.textBaseline=`bottom`,e.textAlign=`center`,e.fillStyle=n.textSecondary,e.fillText(s,c,l))}formatRemaining(e){let t=Math.ceil(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}:${String(r).padStart(2,`0`)}:${String(i).padStart(2,`0`)}`:`${r}:${String(i).padStart(2,`0`)}`}},kt=class{config={visible:!1};cachedBreaks=[];lastDataLength=0;setConfig(e){Object.assign(this.config,e)}isVisible(){return this.config.visible}setVisible(e){this.config.visible=e}computeBreaks(e){if(e.length<2)return[];if(e.length===this.lastDataLength&&this.cachedBreaks.length>0)return this.cachedBreaks;let t=[],n=this.getDayKey(e[0].time);for(let r=1;r<e.length;r++){let i=this.getDayKey(e[r].time);i!==n&&(t.push(r),n=i)}return this.lastDataLength=e.length,this.cachedBreaks=t,t}getDayKey(e){let t=e>0xe8d4a51000?e:e*1e3,n=new Date(t);return`${n.getFullYear()}-${n.getMonth()}-${n.getDate()}`}render(e,t,n,r){if(!this.config.visible||r.length<2)return;let i=this.computeBreaks(r);if(i.length===0)return;let{chartRect:o}=t,s=this.config.color??n.axisLine,c=this.config.lineWidth??1,l=this.config.lineStyle??`dashed`;e.save(),e.strokeStyle=s,e.lineWidth=c,e.globalAlpha=.4,l===`dashed`?e.setLineDash([6,4]):l===`dotted`&&e.setLineDash([2,3]),e.beginPath();for(let n of i){let r=a(n,t)-(t.barWidth+t.barSpacing)/2;if(r<o.x-1||r>o.x+o.width+1)continue;let i=Math.round(r)+.5;e.moveTo(i,o.y),e.lineTo(i,o.y+o.height)}e.stroke(),e.restore()}invalidateCache(){this.lastDataLength=0,this.cachedBreaks=[]}},At=1,jt=class extends G{alerts=[];lastPrice=null;requestRender=null;pricePrecision=2;setRequestRender(e){this.requestRender=e}setPricePrecision(e){this.pricePrecision=e}addAlert(e,t=`crossing`,n,r=!1){let i=`tc_alert_${At++}`,a={id:i,price:e,condition:t,message:n,triggered:!1,repeating:r};return this.alerts.push(a),this.emit(`added`,a),this.requestRender?.(),i}removeAlert(e){this.alerts=this.alerts.filter(t=>t.id!==e),this.emit(`removed`,e),this.requestRender?.()}getAlerts(){return[...this.alerts]}clearAlerts(){this.alerts=[],this.requestRender?.()}checkPrice(e){if(this.lastPrice===null){this.lastPrice=e;return}for(let t of this.alerts){if(t.triggered&&!t.repeating)continue;let n=!1;switch(t.condition){case`crossingUp`:n=this.lastPrice<t.price&&e>=t.price;break;case`crossingDown`:n=this.lastPrice>t.price&&e<=t.price;break;case`crossing`:n=this.lastPrice<t.price&&e>=t.price||this.lastPrice>t.price&&e<=t.price;break;case`greaterThan`:n=e>t.price;break;case`lessThan`:n=e<t.price;break}n&&(t.triggered=!0,this.emit(`triggered`,{...t}))}this.lastPrice=e}saveToStorage(e){try{let t=this.alerts.map(e=>({id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered}));localStorage.setItem(e,JSON.stringify(t))}catch{}}loadFromStorage(e){try{let t=localStorage.getItem(e);if(!t)return;let n=JSON.parse(t);if(!Array.isArray(n))return;for(let e of n)e.price&&e.condition&&!e.triggered&&this.addAlert(e.price,e.condition,e.message)}catch{}}render(e,t,n){let{chartRect:r}=t;for(let i of this.alerts){let a=o(i.price,t);if(a<r.y||a>r.y+r.height)continue;let s=i.triggered?`#FF9800`:`#FFD700`;e.setLineDash([2,6]),e.strokeStyle=s,e.lineWidth=1,e.beginPath(),e.moveTo(r.x,Math.round(a)+.5),e.lineTo(r.x+r.width,Math.round(a)+.5),e.stroke(),e.setLineDash([]),e.font=`10px ${n.font.family}`,e.fillStyle=s,e.textBaseline=`bottom`,e.textAlign=`right`;let c=`๐Ÿ”” ${i.price.toFixed(this.pricePrecision)}${i.message?` - ${i.message}`:``}`;e.fillText(c,r.x+r.width-4,a-2)}}},Mt=class extends G{data=[];currentIndex=0;timer=null;state=`stopped`;config={speed:1,interval:500};load(e){this.stop(),this.data=e,this.currentIndex=0}play(e){this.data.length!==0&&(e&&Object.assign(this.config,e),e?.startIndex!==void 0&&(this.currentIndex=e.startIndex),this.state=`playing`,this.emit(`stateChange`,`playing`),this.timer=setInterval(()=>{if(this.currentIndex>=this.data.length){this.stop(),this.emit(`complete`,void 0);return}let e=this.data[this.currentIndex];this.emit(`bar`,{bar:e,index:this.currentIndex,total:this.data.length}),this.currentIndex++},this.config.interval/this.config.speed))}pause(){this.timer&&=(clearInterval(this.timer),null),this.state=`paused`,this.emit(`stateChange`,`paused`)}resume(){this.state===`paused`&&this.play()}stop(){this.timer&&=(clearInterval(this.timer),null),this.state=`stopped`,this.currentIndex=0,this.emit(`stateChange`,`stopped`)}seekTo(e){this.currentIndex=Math.max(0,Math.min(e,this.data.length-1))}setSpeed(e){this.config.speed=e,this.state===`playing`&&(this.pause(),this.play())}getState(){return this.state}getProgress(){return{current:this.currentIndex,total:this.data.length,percent:this.data.length>0?this.currentIndex/this.data.length*100:0}}dispose(){this.stop(),this.removeAllListeners(),this.data=[]}},q=1,Nt=class{static capture(e,t){return{version:q,timestamp:Date.now(),chartType:t?.chartType??`candlestick`,symbol:t?.symbol,timeframe:t?.timeframe,viewport:{barWidth:8,barSpacing:2,offset:0},theme:e.getTheme().name,indicators:e.getIndicators?.()??[],drawings:e.getDrawings(),orders:e.getOrders?.()??[],positions:e.getPositions?.()??[],alerts:e.getAlerts?.()??[]}}static serialize(e){return JSON.stringify(e)}static deserialize(e){let t=JSON.parse(e);return t.version!==q&&console.warn(`Chart state version mismatch: ${t.version} vs ${q}`),t}static saveToStorage(e,t){localStorage.setItem(e,this.serialize(t))}static loadFromStorage(e){let t=localStorage.getItem(e);return t?this.deserialize(t):null}static downloadFile(e,t=`tc-chart-state.json`){let n=new Blob([this.serialize(e)],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)}static loadFromFile(){return new Promise((e,t)=>{let n=document.createElement(`input`);n.type=`file`,n.accept=`.json`,n.onchange=async()=>{let r=n.files?.[0];if(!r){t(Error(`No file selected`));return}let i=await r.text();e(this.deserialize(i))},n.click()})}},Pt=class{undoStack=[];redoStack=[];maxHistory=50;onChange=null;setOnChange(e){this.onChange=e}push(e){this.undoStack.push(e),this.undoStack.length>this.maxHistory&&this.undoStack.shift(),this.redoStack.length=0,this.onChange?.()}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}undo(){let e=this.undoStack.pop();return e?(this.redoStack.push(e),this.onChange?.(),e):null}redo(){let e=this.redoStack.pop();return e?(this.undoStack.push(e),this.onChange?.(),e):null}clear(){this.undoStack.length=0,this.redoStack.length=0}getState(){return{canUndo:this.undoStack.length>0,canRedo:this.redoStack.length>0,undoCount:this.undoStack.length,redoCount:this.redoStack.length}}},Ft=class{static toCSV(e){return[`Time,Open,High,Low,Close,Volume`,...e.map(e=>`${new Date(e.time).toISOString()},${e.open},${e.high},${e.low},${e.close},${e.volume}`)].join(`
19
+ `,t.addEventListener(`mouseenter`,()=>{t.style.background=`#2a2e39`}),t.addEventListener(`mouseleave`,()=>{t.style.background=`transparent`}),t.addEventListener(`click`,()=>{this.onItemSelect?.(e.intent),this.hide()}),o.appendChild(t)}n.appendChild(o),this.menuElement=o;let c=e=>{(e instanceof KeyboardEvent&&e.key===`Escape`||e instanceof MouseEvent&&!o.contains(e.target))&&this.hide()};document.addEventListener(`mousedown`,c),document.addEventListener(`keydown`,c),this.removeHandler=()=>{document.removeEventListener(`mousedown`,c),document.removeEventListener(`keydown`,c)}}hide(){this.menuElement?.remove(),this.menuElement=null,this.removeHandler?.(),this.removeHandler=null}destroy(){this.hide(),this.onItemSelect=null}},gt=class{orders=[];positions=[];depthData=null;currentPrice=null;config;orderRenderer=new dt;positionRenderer=new ft;depthOverlay=new pt;dragHandler;contextMenu=new ht;requestRender=null;eventCallback=null;container=null;constructor(t){this.config={...e.DEFAULT_TRADING_CONFIG,...t},this.dragHandler=new mt(this.config.dragThreshold),this.contextMenu.onItemSelect=e=>{this.eventCallback?.(`orderPlace`,e)}}setContainer(e){this.container=e}setRequestRender(e){this.requestRender=e}setEventCallback(e){this.eventCallback=e}setOrders(e){this.orders=e,this.requestRender?.()}setPositions(e){this.positions=e,this.requestRender?.()}setDepthData(e){this.depthData=e,this.requestRender?.()}setCurrentPrice(e){this.currentPrice=e,this.requestRender?.()}setConfig(e){Object.assign(this.config,e),this.requestRender?.()}onPointerDown(e,t){return this.config.enabled?this.dragHandler.onPointerDown(e,this.orders,this.positions,t,8):!1}onPointerMove(e,t){if(!this.dragHandler.isActive())return!1;let n=this.dragHandler.onPointerMove(e,t);return n&&this.requestRender?.(),n}onPointerUp(){let e=this.dragHandler.onPointerUp();return e?(e.sourceType===`order`?this.eventCallback?.(`orderModify`,{orderId:e.id,newPrice:e.newPrice,previousPrice:e.previousPrice}):this.eventCallback?.(`positionModify`,{positionId:e.id,[e.sourceType]:e.newPrice}),this.requestRender?.(),!0):!1}onContextMenu(e,t){if(!this.config.enabled||!this.config.contextMenu?.enabled||!this.container)return!1;let n=c(e.y,t);return this.contextMenu.show(e,n,this.container,this.config),!0}render(e,t,n){this.config.enabled&&(this.depthData&&this.depthOverlay.render(e,this.depthData,t,this.config),this.positions.length>0&&this.positionRenderer.render(e,this.positions,this.currentPrice,t,n,this.config),this.orders.length>0&&this.orderRenderer.render(e,this.orders,t,n,this.config,this.dragHandler.getDragState()))}renderAxisBadges(e,t,n){this.config.enabled&&(this.positions.length>0&&this.positionRenderer.renderAxisBadges(e,this.positions,t,n,this.config),this.orders.length>0&&this.orderRenderer.renderAxisBadges(e,this.orders,t,n,this.config,this.dragHandler.getDragState()))}destroy(){this.contextMenu.destroy()}},_t=class{constructor(e){this.manager=e}render(e,t,n){this.manager.render(e,t,n)}renderAxisBadges(e,t,n){this.manager.renderAxisBadges(e,t,n)}},G=class{listeners=new Map;on(e,t){let n=this.listeners.get(e);return n||(n=new Set,this.listeners.set(e,n)),n.add(t),()=>n.delete(t)}once(e,t){let n=this.on(e,e=>{n(),t(e)});return n}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){let n=this.listeners.get(e);if(n)for(let e of n)e(t)}removeAllListeners(){this.listeners.clear()}},vt=class extends G{currentBar=null;timeframeMs;tickRing;ringHead=0;ringCount=0;ringCapacity;constructor(t,n=1e3){super(),this.timeframeMs=(0,e.timeframeToMs)(t),this.ringCapacity=n,this.tickRing=Array(n)}setTimeframe(t){this.timeframeMs=(0,e.timeframeToMs)(t),this.currentBar=null,this.ringHead=0,this.ringCount=0}processTick(e){let t=(this.ringHead+this.ringCount)%this.ringCapacity;this.tickRing[t]=e,this.ringCount<this.ringCapacity?this.ringCount++:this.ringHead=(this.ringHead+1)%this.ringCapacity;let n=this.alignToTimeframe(e.time);!this.currentBar||this.currentBar.time!==n?(this.currentBar&&(this.currentBar.closed=!0,this.emit(`barClose`,this.currentBar)),this.currentBar={time:n,open:e.price,high:e.price,low:e.price,close:e.price,volume:e.volume,closed:!1,tickCount:1}):(this.currentBar.high=Math.max(this.currentBar.high,e.price),this.currentBar.low=Math.min(this.currentBar.low,e.price),this.currentBar.close=e.price,this.currentBar.volume+=e.volume,this.currentBar.tickCount++),this.emit(`bar`,this.currentBar)}processBar(e,t){if(t&&this.currentBar&&this.currentBar.time===e.time)this.currentBar={...e,closed:!0,tickCount:this.currentBar.tickCount+1},this.emit(`barClose`,this.currentBar),this.currentBar=null;else if(!t)this.currentBar={...e,closed:!1,tickCount:(this.currentBar?.tickCount??0)+1},this.emit(`bar`,this.currentBar);else{let t={...e,closed:!0,tickCount:1};this.emit(`barClose`,t),this.currentBar=null}}getCurrentBar(){return this.currentBar?{...this.currentBar}:null}getTickBuffer(){let e=Array(this.ringCount);for(let t=0;t<this.ringCount;t++)e[t]=this.tickRing[(this.ringHead+t)%this.ringCapacity];return e}reset(){this.currentBar=null,this.ringHead=0,this.ringCount=0}alignToTimeframe(e){return Math.floor(e/this.timeframeMs)*this.timeframeMs}},K=class extends G{config;attempt=0;timer=null;active=!1;constructor(t){super(),this.config={...e.DEFAULT_RECONNECT,...t}}schedule(e){if(!this.config.enabled||!this.active)return;if(this.attempt++,this.attempt>this.config.maxRetries){this.emit(`giveUp`,{attempts:this.attempt-1}),this.active=!1;return}let t=this.computeDelay();this.emit(`attempt`,{attempt:this.attempt,delay:t}),this.timer=setTimeout(()=>{this.timer=null,this.active&&e()},t)}onConnected(){this.attempt=0,this.cancel(),this.emit(`success`,void 0)}start(){this.active=!0}stop(){this.active=!1,this.cancel(),this.attempt=0}cancel(){this.timer&&=(clearTimeout(this.timer),null)}getAttempt(){return this.attempt}isActive(){return this.active}computeDelay(){let e=this.config.baseDelay,t=this.config.backoffMultiplier**(this.attempt-1),n=Math.min(e*t,this.config.maxDelay),r=n*.25*(Math.random()*2-1);return Math.max(0,Math.round(n+r))}},yt=class{price=null;previousClose=null;visible=!0;flashUntil=0;pricePrecision=2;setPrice(e,t){this.price!==null&&e!==this.price&&(this.flashUntil=Date.now()+300),this.previousClose=t??this.price??e,this.price=e}setVisible(e){this.visible=e}setPricePrecision(e){this.pricePrecision=e}getPrice(){return this.price}render(t,n,r){if(!this.visible||this.price===null)return;let i=o(this.price,n),{chartRect:a}=n;if(i<a.y||i>a.y+a.height)return;let s=this.previousClose===null||this.price>=this.previousClose?r.candleUp??`#26A69A`:r.candleDown??`#EF5350`,c=Date.now()<this.flashUntil;t.setLineDash([4,3]),t.strokeStyle=s,t.lineWidth=1,t.globalAlpha=c?1:.7,t.beginPath(),t.moveTo(a.x,Math.round(i)+.5),t.lineTo(a.x+a.width,Math.round(i)+.5),t.stroke(),t.setLineDash([]),t.globalAlpha=1;let l=a.x+a.width+1,u=this.price.toFixed(this.pricePrecision);t.font=`bold 11px ${r.font.family}`;let d=t.measureText(u).width,f=Math.min(d+12,e.PRICE_AXIS_WIDTH-2);t.fillStyle=s,t.fillRect(l,i-10,f,20);let p=l-5;t.beginPath(),t.moveTo(p,i),t.lineTo(p+5,i-5),t.lineTo(p+5,i+5),t.closePath(),t.fill(),t.fillStyle=`#FFFFFF`,t.textBaseline=`middle`,t.textAlign=`left`,t.fillText(u,l+5,i)}},bt=class extends G{config=null;adapter=null;aggregator=null;reconnector;priceLine=new yt;state=`disconnected`;lastPrice=null;previousClose=null;unsubscribers=[];heartbeatTimer=null;lastMessageTime=0;constructor(){super(),this.reconnector=new K,this.wireReconnector()}async connect(t){this.disconnect(),this.config={...e.DEFAULT_STREAM_CONFIG,...t},this.adapter=t.adapter,this.aggregator=new vt(t.timeframe),this.reconnector.removeAllListeners(),this.reconnector.stop(),this.reconnector=new K(t.reconnect??e.DEFAULT_RECONNECT),this.wireReconnector(),this.aggregator.on(`bar`,e=>{this.emit(`barUpdate`,e),this.updatePrice(e.close)}),this.aggregator.on(`barClose`,e=>{this.previousClose=e.close,this.emit(`barClose`,e)}),this.wireAdapter(),this.reconnector.start(),await this.doConnect()}disconnect(){this.reconnector.stop(),this.stopHeartbeat();for(let e of this.unsubscribers)e();this.unsubscribers=[],this.adapter&&=(this.adapter.disconnect(),null),this.aggregator?.reset(),this.aggregator?.removeAllListeners(),this.aggregator=null,this.config=null,this.lastPrice=null,this.previousClose=null,this.setState(`disconnected`)}async switchTo(e,t){!this.config||!this.adapter||(this.adapter.disconnect(),this.aggregator?.reset(),this.aggregator?.setTimeframe(t),this.lastPrice=null,this.previousClose=null,this.config.symbol=e,this.config.timeframe=t,await this.doConnect())}getConnectionState(){return this.state}getConnectionInfo(){return{state:this.state,reconnectAttempt:this.reconnector.getAttempt(),lastMessageTime:this.lastMessageTime}}getLastPrice(){return this.lastPrice}async doConnect(){if(!(!this.config||!this.adapter)){this.setState(`connecting`);try{let e=await this.adapter.fetchHistory(this.config.symbol,this.config.timeframe,this.config.historyLimit??500);e.length>0&&(this.previousClose=e[e.length-1].close,this.updatePrice(e[e.length-1].close)),this.emit(`snapshot`,e),this.adapter.connect({symbol:this.config.symbol,timeframe:this.config.timeframe}),this.startHeartbeat()}catch(e){let t=e instanceof Error?e.message:String(e);this.emit(`error`,{message:t,code:`CONNECT_FAILED`}),this.setState(`error`),this.reconnector.schedule(()=>this.doConnect())}}}wireReconnector(){this.reconnector.on(`attempt`,({attempt:e,delay:t})=>{this.setState(`reconnecting`),this.emit(`connectionChange`,{state:`reconnecting`,reconnectAttempt:e,lastMessageTime:this.lastMessageTime})}),this.reconnector.on(`giveUp`,({attempts:e})=>{this.setState(`error`),this.emit(`error`,{message:`Reconnection failed after ${e} attempts`,code:`RECONNECT_EXHAUSTED`})})}wireAdapter(){if(!this.adapter)return;let e=this.adapter,t=e=>{let t=e.data;this.lastMessageTime=Date.now(),t===`connected`?(this.reconnector.onConnected(),this.setState(`connected`)):(t===`disconnected`||t===`error`)&&this.reconnector.schedule(()=>this.doConnect())};e.on(`connectionChange`,t),this.unsubscribers.push(()=>e.off(`connectionChange`,t));let n=e=>{this.lastMessageTime=Date.now();let t=e.data;this.emit(`tick`,t),this.config?.aggregateTicks&&this.aggregator?this.aggregator.processTick(t):this.updatePrice(t.price)};e.on(`tick`,n),this.unsubscribers.push(()=>e.off(`tick`,n));let r=e=>{this.lastMessageTime=Date.now();let{bar:t,closed:n}=e.data;this.aggregator&&this.aggregator.processBar(t,n)};e.on(`bar`,r),this.unsubscribers.push(()=>e.off(`bar`,r));let i=e=>{this.emit(`error`,{message:e.data?.message??`Adapter error`})};e.on(`error`,i),this.unsubscribers.push(()=>e.off(`error`,i))}updatePrice(e){e!==this.lastPrice&&(this.lastPrice=e,this.priceLine.setPrice(e,this.previousClose??void 0),this.emit(`priceChange`,{price:e,previousClose:this.previousClose}))}setState(e){this.state!==e&&(this.state=e,this.emit(`connectionChange`,{state:e,reconnectAttempt:this.reconnector.getAttempt(),lastMessageTime:this.lastMessageTime}))}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{Date.now()-this.lastMessageTime>6e4&&this.state===`connected`&&(this.emit(`error`,{message:`Heartbeat timeout`,code:`HEARTBEAT_TIMEOUT`}),this.adapter?.disconnect(),this.reconnector.schedule(()=>this.doConnect()))},3e4)}stopHeartbeat(){this.heartbeatTimer&&=(clearInterval(this.heartbeatTimer),null)}dispose(){this.disconnect(),this.removeAllListeners()}},xt={"1s":`1s`,"1m":`1m`,"3m":`3m`,"5m":`5m`,"15m":`15m`,"30m":`30m`,"1h":`1h`,"2h":`2h`,"4h":`4h`,"6h":`6h`,"8h":`8h`,"12h":`12h`,"1d":`1d`,"3d":`3d`,"1w":`1w`,"1M":`1M`},St=class{name=`binance`;ws=null;state=`disconnected`;listeners=new Map;config=null;restBase;wsBase;constructor(e){this.restBase=e?.restBase??`https://api.binance.com/api/v3`,this.wsBase=e?.wsBase??`wss://stream.binance.com:9443/ws`}connect(e){this.config=e,this.connectWs()}disconnect(){this.ws&&=(this.ws.onclose=null,this.ws.close(),null),this.setState(`disconnected`)}getConnectionState(){return this.state}async fetchHistory(e,t,n=500){let r=xt[t]??`15m`,i=`${this.restBase}/klines?symbol=${e}&interval=${r}&limit=${n}`,a=await fetch(i);if(!a.ok)throw Error(`Binance REST error: ${a.status}`);return(await a.json()).map(e=>({time:e[0],open:parseFloat(e[1]),high:parseFloat(e[2]),low:parseFloat(e[3]),close:parseFloat(e[4]),volume:parseFloat(e[5])}))}on(e,t){let n=this.listeners.get(e);n||(n=new Set,this.listeners.set(e,n)),n.add(t)}off(e,t){this.listeners.get(e)?.delete(t)}dispose(){this.disconnect(),this.listeners.clear()}connectWs(){if(!this.config)return;let e=`${this.config.symbol.toLowerCase()}@kline_${xt[this.config.timeframe]??`15m`}`,t=`${this.wsBase}/${e}`;this.setState(`connecting`);try{this.ws=new WebSocket(t)}catch{this.setState(`error`),this.emitEvent(`error`,{message:`WebSocket creation failed`}),this.emitEvent(`connectionChange`,`error`);return}this.ws.onopen=()=>{this.setState(`connected`),this.emitEvent(`connectionChange`,`connected`)},this.ws.onmessage=e=>{try{let t=JSON.parse(e.data);t.e===`kline`&&this.handleKline(t.k)}catch{}},this.ws.onerror=()=>{this.setState(`error`),this.emitEvent(`error`,{message:`WebSocket error`})},this.ws.onclose=()=>{this.setState(`disconnected`),this.emitEvent(`connectionChange`,`disconnected`)}}handleKline(e){let t={time:e.t,open:parseFloat(e.o),high:parseFloat(e.h),low:parseFloat(e.l),close:parseFloat(e.c),volume:parseFloat(e.v)},n=e.x;this.emitEvent(`bar`,{bar:t,closed:n}),this.emitEvent(`tick`,{time:Date.now(),price:t.close,volume:t.volume})}setState(e){this.state=e}emitEvent(e,t){let n=this.listeners.get(e);if(n){let r={type:e,data:t,timestamp:Date.now()};for(let e of n)e(r)}}},Ct=class{name=`mock`;state=`disconnected`;listeners=new Map;config=null;options;tickTimer=null;currentPrice;constructor(e){this.options={basePrice:100,volatility:1.5,tickInterval:2e3,historySize:500,...e},this.currentPrice=this.options.basePrice}connect(e){this.config=e,this.state=`connected`,this.emitEvent(`connectionChange`,`connected`),this.startTicking()}disconnect(){this.stopTicking(),this.state=`disconnected`,this.emitEvent(`connectionChange`,`disconnected`)}getConnectionState(){return this.state}async fetchHistory(e,t,n){return this.options.historyGenerator?this.options.historyGenerator(e,t,n??this.options.historySize):this.generateHistory(t,n??this.options.historySize)}on(e,t){let n=this.listeners.get(e);n||(n=new Set,this.listeners.set(e,n)),n.add(t)}off(e,t){this.listeners.get(e)?.delete(t)}dispose(){this.disconnect(),this.listeners.clear()}generateHistory(t,n){let r=[],i=Date.now(),a=(0,e.timeframeToMs)(t),o=this.options.basePrice,s=this.options.volatility/100;for(let e=n-1;e>=0;e--){let t=i-e*a,n=(Math.random()-.48)*o*s,c=o;o+=n;let l=Math.max(c,o)+Math.random()*o*s*.3,u=Math.min(c,o)-Math.random()*o*s*.3,d=Math.floor(1e4+Math.random()*1e5);r.push({time:t,open:c,high:l,low:u,close:o,volume:d})}return this.currentPrice=o,r}startTicking(){this.stopTicking();let t=this.options.tickInterval??2e3;this.tickTimer=setInterval(()=>{if(this.state!==`connected`||!this.config)return;let t=this.options.volatility/100,n=(Math.random()-.48)*this.currentPrice*t*.3;this.currentPrice+=n;let r=Date.now(),i=(0,e.timeframeToMs)(this.config.timeframe),a={time:Math.floor(r/i)*i,open:this.currentPrice-n,high:Math.max(this.currentPrice,this.currentPrice-n)+Math.abs(n)*.2,low:Math.min(this.currentPrice,this.currentPrice-n)-Math.abs(n)*.2,close:this.currentPrice,volume:Math.floor(100+Math.random()*5e3)};this.emitEvent(`bar`,{bar:a,closed:!1}),this.emitEvent(`tick`,{time:r,price:this.currentPrice,volume:a.volume})},t)}stopTicking(){this.tickTimer&&=(clearInterval(this.tickTimer),null)}emitEvent(e,t){let n=this.listeners.get(e);if(n){let r={type:e,data:t,timestamp:Date.now()};for(let e of n)e(r)}}},wt={visible:!0,showSymbol:!0,showOHLC:!0,showChange:!0,showVolume:!0,position:`top-left`,fontSize:12},Tt=class{config={...wt};symbol=``;timeframe=``;hoverBar=null;indicators=[];statusText=null;setConfig(e){Object.assign(this.config,e)}setSymbol(e){this.symbol=e}setTimeframe(e){this.timeframe=e}setChartType(e){}setHoverBar(e){this.hoverBar=e}setIndicatorValues(e){this.indicators=e}setStatusText(e){this.statusText=e}render(e,t,n,r){if(!this.config.visible||r.length===0)return;let i=this.hoverBar??r[r.length-1],a=r.length>1?r[r.length-2]:i,{chartRect:o}=t,s=this.config.fontSize,c=this.config.position===`top-left`,l=c?o.x+8:o.x+o.width-8,u=o.y+6;if(e.textAlign=c?`left`:`right`,e.textBaseline=`top`,this.config.showSymbol){e.font=`bold ${s+2}px ${n.font.family}`,e.fillStyle=n.text;let t=[this.symbol,this.timeframe].filter(Boolean).join(` ยท `),r=this.statusText?`${t} ${this.statusText}`:t;e.fillText(r,l,u),u+=s+6}else this.statusText&&(e.font=`${s}px ${n.font.family}`,e.fillStyle=n.textSecondary,e.fillText(this.statusText,l,u),u+=s+4);if(this.config.showOHLC){e.font=`${s}px ${n.font.family}`;let t=i.close>=i.open,r=e=>e.toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2}),o=[{label:`O`,value:r(i.open),color:n.text},{label:`H`,value:r(i.high),color:n.text},{label:`L`,value:r(i.low),color:n.text},{label:`C`,value:r(i.close),color:t?n.candleUp:n.candleDown}];if(this.config.showChange){let e=i.close-a.close,t=a.close===0?0:e/a.close*100,s=e>=0?`+`:``;o.push({label:``,value:`${s}${r(e)} (${s}${t.toFixed(2)}%)`,color:e>=0?n.candleUp:n.candleDown})}let d=l;if(c)for(let t of o)t.label&&(e.fillStyle=n.textSecondary,e.fillText(t.label,d,u),d+=e.measureText(t.label+` `).width),e.fillStyle=t.color,e.fillText(t.value,d,u),d+=e.measureText(t.value+` `).width;else{let t=o.map(e=>`${e.label} ${e.value}`).join(` `);e.fillStyle=n.text,e.fillText(t,l,u)}u+=s+3}if(this.config.showVolume){e.font=`${s-1}px ${n.font.family}`,e.fillStyle=n.textSecondary;let t=i.volume>=1e6?`${(i.volume/1e6).toFixed(2)}M`:i.volume>=1e3?`${(i.volume/1e3).toFixed(2)}K`:i.volume.toFixed(0);e.fillText(`Vol ${t}`,l,u),u+=s+2}if(this.indicators.length>0){e.font=`${s-1}px ${n.font.family}`;let t=l;for(let n of this.indicators){e.fillStyle=n.color;let r=`${n.name} ${n.value}`;e.fillText(r,t,u),t+=e.measureText(r+` `).width}}}},Et=class{static toDataURL(e,t){let n=e.querySelectorAll(`canvas`);if(n.length===0)return``;let r=n[0],i=r.width,a=r.height,o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);t&&(s.fillStyle=t,s.fillRect(0,0,i,a));let c=Array.from(n).sort((e,t)=>(parseInt(e.style.zIndex)||0)-(parseInt(t.style.zIndex)||0));for(let e of c)s.drawImage(e,0,0);return o.toDataURL(`image/png`)}static async toBlob(e,t){let n=this.toDataURL(e,t);return n?(await fetch(n)).blob():null}static download(e,t=`chart.png`,n){let r=this.toDataURL(e,n);if(!r)return;let i=document.createElement(`a`);i.href=r,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i)}},Dt=class{config=null;setConfig(e){this.config=e}render(e,t,n){if(!this.config?.text)return;let{chartRect:r}=t,i=this.config.fontSize??48,a=this.config.color??n.textSecondary;e.save(),e.globalAlpha=.07,e.font=`bold ${i}px ${n.font.family}`,e.fillStyle=a,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(this.config.text,r.x+r.width/2,r.y+r.height/2),e.restore()}},Ot=class{visible=!0;timeframeMs=0;setVisible(e){this.visible=e}isVisible(){return this.visible}setTimeframeMs(e){this.timeframeMs=e}render(e,t,n,r){if(!this.visible||this.timeframeMs<=0||r.length===0)return;let i=r[r.length-1],o=(i.time>0xe8d4a51000?i.time:i.time*1e3)+this.timeframeMs-Date.now();if(o<=0)return;let s=this.formatRemaining(o),c=a(r.length-1,t),l=t.chartRect.y+t.chartRect.height-4;c<t.chartRect.x||c>t.chartRect.x+t.chartRect.width||(e.font=`${n.font.sizeSmall}px ${n.font.family}`,e.textBaseline=`bottom`,e.textAlign=`center`,e.fillStyle=n.textSecondary,e.fillText(s,c,l))}formatRemaining(e){let t=Math.ceil(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}:${String(r).padStart(2,`0`)}:${String(i).padStart(2,`0`)}`:`${r}:${String(i).padStart(2,`0`)}`}},kt=class{config={visible:!1};cachedBreaks=[];lastDataLength=0;setConfig(e){Object.assign(this.config,e)}isVisible(){return this.config.visible}setVisible(e){this.config.visible=e}computeBreaks(e){if(e.length<2)return[];if(e.length===this.lastDataLength&&this.cachedBreaks.length>0)return this.cachedBreaks;let t=[],n=this.getDayKey(e[0].time);for(let r=1;r<e.length;r++){let i=this.getDayKey(e[r].time);i!==n&&(t.push(r),n=i)}return this.lastDataLength=e.length,this.cachedBreaks=t,t}getDayKey(e){let t=e>0xe8d4a51000?e:e*1e3,n=new Date(t);return`${n.getFullYear()}-${n.getMonth()}-${n.getDate()}`}render(e,t,n,r){if(!this.config.visible||r.length<2)return;let i=this.computeBreaks(r);if(i.length===0)return;let{chartRect:o}=t,s=this.config.color??n.axisLine,c=this.config.lineWidth??1,l=this.config.lineStyle??`dashed`;e.save(),e.strokeStyle=s,e.lineWidth=c,e.globalAlpha=.4,l===`dashed`?e.setLineDash([6,4]):l===`dotted`&&e.setLineDash([2,3]),e.beginPath();for(let n of i){let r=a(n,t)-(t.barWidth+t.barSpacing)/2;if(r<o.x-1||r>o.x+o.width+1)continue;let i=Math.round(r)+.5;e.moveTo(i,o.y),e.lineTo(i,o.y+o.height)}e.stroke(),e.restore()}invalidateCache(){this.lastDataLength=0,this.cachedBreaks=[]}},At=1,jt=class extends G{alerts=[];lastPrice=null;requestRender=null;pricePrecision=2;setRequestRender(e){this.requestRender=e}setPricePrecision(e){this.pricePrecision=e}addAlert(e,t=`crossing`,n,r=!1){let i=`tc_alert_${At++}`,a={id:i,price:e,condition:t,message:n,triggered:!1,repeating:r};return this.alerts.push(a),this.emit(`added`,a),this.requestRender?.(),i}removeAlert(e){this.alerts=this.alerts.filter(t=>t.id!==e),this.emit(`removed`,e),this.requestRender?.()}getAlerts(){return[...this.alerts]}clearAlerts(){this.alerts=[],this.requestRender?.()}checkPrice(e){if(this.lastPrice===null){this.lastPrice=e;return}for(let t of this.alerts){if(t.triggered&&!t.repeating)continue;let n=!1;switch(t.condition){case`crossingUp`:n=this.lastPrice<t.price&&e>=t.price;break;case`crossingDown`:n=this.lastPrice>t.price&&e<=t.price;break;case`crossing`:n=this.lastPrice<t.price&&e>=t.price||this.lastPrice>t.price&&e<=t.price;break;case`greaterThan`:n=e>t.price;break;case`lessThan`:n=e<t.price;break}n&&(t.triggered=!0,this.emit(`triggered`,{...t}))}this.lastPrice=e}saveToStorage(e){try{let t=this.alerts.map(e=>({id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered}));localStorage.setItem(e,JSON.stringify(t))}catch{}}loadFromStorage(e){try{let t=localStorage.getItem(e);if(!t)return;let n=JSON.parse(t);if(!Array.isArray(n))return;for(let e of n)e.price&&e.condition&&!e.triggered&&this.addAlert(e.price,e.condition,e.message)}catch{}}render(e,t,n){let{chartRect:r}=t;for(let i of this.alerts){let a=o(i.price,t);if(a<r.y||a>r.y+r.height)continue;let s=i.triggered?`#FF9800`:`#FFD700`;e.setLineDash([2,6]),e.strokeStyle=s,e.lineWidth=1,e.beginPath(),e.moveTo(r.x,Math.round(a)+.5),e.lineTo(r.x+r.width,Math.round(a)+.5),e.stroke(),e.setLineDash([]),e.font=`10px ${n.font.family}`,e.fillStyle=s,e.textBaseline=`bottom`,e.textAlign=`right`;let c=`๐Ÿ”” ${i.price.toFixed(this.pricePrecision)}${i.message?` - ${i.message}`:``}`;e.fillText(c,r.x+r.width-4,a-2)}}},Mt=class extends G{data=[];currentIndex=0;timer=null;state=`stopped`;config={speed:1,interval:500};load(e){this.stop(),this.data=e,this.currentIndex=0}play(e){this.data.length!==0&&(e&&Object.assign(this.config,e),e?.startIndex!==void 0&&(this.currentIndex=e.startIndex),this.state=`playing`,this.emit(`stateChange`,`playing`),this.timer=setInterval(()=>{if(this.currentIndex>=this.data.length){this.stop(),this.emit(`complete`,void 0);return}let e=this.data[this.currentIndex];this.emit(`bar`,{bar:e,index:this.currentIndex,total:this.data.length}),this.currentIndex++},this.config.interval/this.config.speed))}pause(){this.timer&&=(clearInterval(this.timer),null),this.state=`paused`,this.emit(`stateChange`,`paused`)}resume(){this.state===`paused`&&this.play()}stop(){this.timer&&=(clearInterval(this.timer),null),this.state=`stopped`,this.currentIndex=0,this.emit(`stateChange`,`stopped`)}seekTo(e){this.currentIndex=Math.max(0,Math.min(e,this.data.length-1))}setSpeed(e){this.config.speed=e,this.state===`playing`&&(this.pause(),this.play())}getState(){return this.state}getProgress(){return{current:this.currentIndex,total:this.data.length,percent:this.data.length>0?this.currentIndex/this.data.length*100:0}}dispose(){this.stop(),this.removeAllListeners(),this.data=[]}},q=1,Nt=class{static capture(e,t){return{version:q,timestamp:Date.now(),chartType:t?.chartType??`candlestick`,symbol:t?.symbol,timeframe:t?.timeframe,viewport:{barWidth:8,barSpacing:2,offset:0},theme:e.getTheme().name,indicators:e.getIndicators?.()??[],drawings:e.getDrawings(),orders:e.getOrders?.()??[],positions:e.getPositions?.()??[],alerts:e.getAlerts?.()??[]}}static serialize(e){return JSON.stringify(e)}static deserialize(e){let t=JSON.parse(e);return t.version!==q&&console.warn(`Chart state version mismatch: ${t.version} vs ${q}`),t}static saveToStorage(e,t){localStorage.setItem(e,this.serialize(t))}static loadFromStorage(e){let t=localStorage.getItem(e);return t?this.deserialize(t):null}static downloadFile(e,t=`tc-chart-state.json`){let n=new Blob([this.serialize(e)],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)}static loadFromFile(){return new Promise((e,t)=>{let n=document.createElement(`input`);n.type=`file`,n.accept=`.json`,n.onchange=async()=>{let r=n.files?.[0];if(!r){t(Error(`No file selected`));return}let i=await r.text();e(this.deserialize(i))},n.click()})}},Pt=class{undoStack=[];redoStack=[];maxHistory=50;onChange=null;setOnChange(e){this.onChange=e}push(e){this.undoStack.push(e),this.undoStack.length>this.maxHistory&&this.undoStack.shift(),this.redoStack.length=0,this.onChange?.()}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}undo(){let e=this.undoStack.pop();return e?(this.redoStack.push(e),this.onChange?.(),e):null}redo(){let e=this.redoStack.pop();return e?(this.undoStack.push(e),this.onChange?.(),e):null}clear(){this.undoStack.length=0,this.redoStack.length=0}getState(){return{canUndo:this.undoStack.length>0,canRedo:this.redoStack.length>0,undoCount:this.undoStack.length,redoCount:this.redoStack.length}}},Ft=class{static toCSV(e){return[`Time,Open,High,Low,Close,Volume`,...e.map(e=>`${new Date(e.time).toISOString()},${e.open},${e.high},${e.low},${e.close},${e.volume}`)].join(`
20
20
  `)}static toJSON(e){return JSON.stringify(e.map(e=>({time:new Date(e.time).toISOString(),open:e.open,high:e.high,low:e.low,close:e.close,volume:e.volume})),null,2)}static download(e,t,n){let r=new Blob([e],{type:n}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i)}},It={linear:e=>e,easeOutCubic:e=>1-(1-e)**3,easeOutQuart:e=>1-(1-e)**4,easeInOutCubic:e=>e<.5?4*e*e*e:1-(-2*e+2)**3/2,easeOutExpo:e=>e===1?1:1-2**(-10*e),easeOutElastic:e=>e===0||e===1?e:2**(-10*e)*Math.sin((e*10-.75)*(2*Math.PI/3))+1,spring:e=>1-Math.E**(-6*e)*Math.cos(8*e)},Lt=class{animations=new Map;frameId=0;running=!1;animate(e,t){this.animations.set(e,{startTime:-1,duration:t.duration,easing:t.easing??It.easeOutCubic,onUpdate:t.onUpdate,onComplete:t.onComplete}),this.running||(this.running=!0,this.tick())}cancel(e){this.animations.delete(e),this.animations.size===0&&this.stop()}cancelAll(){this.animations.clear(),this.stop()}isAnimating(e){return e?this.animations.has(e):this.animations.size>0}tick(){this.frameId=requestAnimationFrame(e=>{let t=[];for(let[n,r]of this.animations){r.startTime<0&&(r.startTime=e);let i=e-r.startTime,a=Math.min(1,i/r.duration),o=r.easing(a);r.onUpdate(o),a>=1&&(r.onComplete?.(),t.push(n))}for(let e of t)this.animations.delete(e);this.animations.size>0?this.tick():this.running=!1})}stop(){this.frameId&&=(cancelAnimationFrame(this.frameId),0),this.running=!1}dispose(){this.cancelAll()}};function Rt(t){return!t||t===`dark`?e.DARK_THEME:t===`light`?e.LIGHT_THEME:t}var zt=class{canvas;ctx;container;theme;width=0;height=0;dpr=1;frameId=null;resizeObserver;constructor(e,t){this.container=e,this.theme=Rt(t),this.canvas=document.createElement(`canvas`),this.canvas.style.width=`100%`,this.canvas.style.height=`100%`,this.canvas.style.display=`block`,e.appendChild(this.canvas),this.ctx=this.canvas.getContext(`2d`),this.dpr=window.devicePixelRatio||1,this.updateSize(),this.resizeObserver=new ResizeObserver(()=>{this.updateSize(),this.requestRender()}),this.resizeObserver.observe(e)}updateSize(){this.dpr=window.devicePixelRatio||1;let e=this.container.getBoundingClientRect();this.width=e.width||this.container.clientWidth,this.height=e.height||this.container.clientHeight,this.canvas.width=Math.max(1,Math.floor(this.width*this.dpr)),this.canvas.height=Math.max(1,Math.floor(this.height*this.dpr))}requestRender(){this.frameId===null&&(this.frameId=requestAnimationFrame(()=>{this.frameId=null,(this.width===0||this.height===0)&&this.updateSize(),!(this.width===0||this.height===0)&&(this.ctx.save(),this.ctx.scale(this.dpr,this.dpr),this.ctx.clearRect(0,0,this.width,this.height),this.renderChart(this.ctx,this.width,this.height,this.theme),this.ctx.restore())}))}setTheme(e){this.theme=Rt(e),this.requestRender()}destroy(){this.frameId!==null&&cancelAnimationFrame(this.frameId),this.resizeObserver.disconnect(),this.canvas.remove()}},Bt=class{pos=null;canvas;onUpdate;handleMove;handleLeave;constructor(e,t){this.canvas=e,this.onUpdate=t,this.handleMove=t=>{let n=e.getBoundingClientRect();this.pos={x:t.clientX-n.left,y:t.clientY-n.top},this.onUpdate()},this.handleLeave=()=>{this.pos=null,this.onUpdate()},e.addEventListener(`pointermove`,this.handleMove),e.addEventListener(`pointerleave`,this.handleLeave)}getPosition(){return this.pos}isActive(){return this.pos!==null}drawCrosshair(e,t,n,r){this.pos&&(e.save(),e.strokeStyle=r,e.lineWidth=.5,e.setLineDash([4,4]),e.beginPath(),e.moveTo(this.pos.x,0),e.lineTo(this.pos.x,n),e.stroke(),e.beginPath(),e.moveTo(0,this.pos.y),e.lineTo(t,this.pos.y),e.stroke(),e.restore())}destroy(){this.canvas.removeEventListener(`pointermove`,this.handleMove),this.canvas.removeEventListener(`pointerleave`,this.handleLeave)}};function Vt(e,t,n,r,i){let{data:a,mode:o=`area`,lineWidth:s=1.5,showLastPoint:c=!1,showMinMax:l=!1}=r;if(a.length<2||t<=0||n<=0)return;let u=r.color??i.lineColor,d=r.fillColor??u,f=t-4,p=n-4,m=1/0,h=-1/0,g=0,_=0;for(let e=0;e<a.length;e++)a[e]<m&&(m=a[e],g=e),a[e]>h&&(h=a[e],_=e);let v=h-m||1,y=e=>2+e/(a.length-1)*f,b=e=>2+p-(e-m)/v*p;if(o===`area`){let t=e.createLinearGradient(0,2,0,n-2);t.addColorStop(0,d+(d.startsWith(`#`)?`40`:``)),t.addColorStop(1,`transparent`),e.beginPath(),e.moveTo(y(0),b(a[0]));for(let t=1;t<a.length;t++)e.lineTo(y(t),b(a[t]));e.lineTo(y(a.length-1),n-2),e.lineTo(y(0),n-2),e.closePath(),e.fillStyle=t,e.fill()}e.beginPath(),e.moveTo(y(0),b(a[0]));for(let t=1;t<a.length;t++)e.lineTo(y(t),b(a[t]));if(e.strokeStyle=u,e.lineWidth=s,e.lineJoin=`round`,e.stroke(),c){let t=r.lastPointColor??u,n=y(a.length-1),i=b(a[a.length-1]);e.beginPath(),e.arc(n,i,3,0,Math.PI*2),e.fillStyle=t,e.fill()}if(l){let t=r.minPointColor??i.candleDown,n=r.maxPointColor??i.candleUp;e.beginPath(),e.arc(y(g),b(m),2.5,0,Math.PI*2),e.fillStyle=t,e.fill(),e.beginPath(),e.arc(y(_),b(h),2.5,0,Math.PI*2),e.fillStyle=n,e.fill()}}var Ht=50,Ut=60,J=20,Wt=.2;function Gt(e){let t=[...e].sort((e,t)=>t.price-e.price),n=[],r=0;for(let e of t)r+=e.volume,n.push({price:e.price,cumulativeVolume:r});return n}function Kt(e){let t=[...e].sort((e,t)=>e.price-t.price),n=[],r=0;for(let e of t)r+=e.volume,n.push({price:e.price,cumulativeVolume:r});return n}function qt(e,t){return{left:Ht,right:e-Ut,top:J,bottom:t-J,plotWidth:e-Ht-Ut,plotHeight:t-J*2}}function Jt(e,t,n,r){e.fillStyle=r,e.fillRect(0,0,t,n)}function Yt(t,n,r,i,a,o,s,c){let{left:l,right:u,top:d,bottom:f,plotWidth:p,plotHeight:m}=n;t.save(),t.strokeStyle=o.grid,t.lineWidth=.5,t.fillStyle=o.axisLabel,t.font=`${o.font.sizeSmall}px ${o.font.family}`;let h=(0,e.computeTickStep)(0,a,5);for(let e=0;e<=a;e+=h){let n=f-e/a*m;t.beginPath(),t.moveTo(l,n),t.lineTo(u,n),t.stroke(),t.textAlign=`right`,t.textBaseline=`middle`,t.fillText(c(e),l-4,n)}let g=i-r,_=(0,e.computeTickStep)(r,i,6),v=Math.ceil(r/_)*_;for(let e=v;e<=i;e+=_){let n=l+(e-r)/g*p;t.beginPath(),t.moveTo(n,d),t.lineTo(n,f),t.stroke(),t.textAlign=`center`,t.textBaseline=`top`,t.fillText(s(e),n,f+4)}t.restore()}function Xt(e,t,n,r,i,a,o,s,c){if(t.length===0)return;let{left:l,bottom:u,plotWidth:d,plotHeight:f}=n,p=e=>l+(e-r)/i*d,m=e=>u-e/a*f;if(e.beginPath(),c===`bid`){e.moveTo(p(t[0].price),u);for(let n=0;n<t.length;n++){let r=p(t[n].price),i=m(t[n].cumulativeVolume);e.lineTo(r,i),n<t.length-1&&e.lineTo(p(t[n+1].price),i)}e.lineTo(p(t[t.length-1].price),u)}else{e.moveTo(p(t[0].price),u);for(let n=0;n<t.length;n++){let r=p(t[n].price),i=m(t[n].cumulativeVolume);e.lineTo(r,i),n<t.length-1&&e.lineTo(p(t[n+1].price),i)}e.lineTo(p(t[t.length-1].price),u)}if(e.closePath(),e.fillStyle=o,e.fill(),e.beginPath(),c===`bid`){e.moveTo(p(t[0].price),m(t[0].cumulativeVolume));for(let n=0;n<t.length;n++){let r=p(t[n].price),i=m(t[n].cumulativeVolume);n>0&&e.lineTo(r,m(t[n-1].cumulativeVolume)),e.lineTo(r,i)}}else{e.moveTo(p(t[0].price),m(t[0].cumulativeVolume));for(let n=1;n<t.length;n++){let r=m(t[n-1].cumulativeVolume),i=p(t[n].price),a=m(t[n].cumulativeVolume);e.lineTo(i,r),e.lineTo(i,a)}}e.strokeStyle=s,e.lineWidth=1.5,e.stroke()}function Zt(e,t,n,r,i,a,o,s,c){let{left:l,top:u,bottom:d,plotWidth:f}=r,p=l+(t-i)/a*f;if(e.save(),e.strokeStyle=o.textSecondary,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(p,u),e.lineTo(p,d),e.stroke(),e.restore(),s){let t=`Spread: ${c(n)}`;e.save(),e.font=`${o.font.sizeSmall}px ${o.font.family}`,e.fillStyle=o.textSecondary,e.textAlign=`center`,e.textBaseline=`bottom`,e.fillText(t,p,u-2),e.restore()}}function Qt(e,t,n,r,i,a,o,s,c,l,u){let{left:d,top:f,bottom:p,plotWidth:m,plotHeight:h}=i,g=t.x;if(g<d||g>i.right)return;let _=a+(g-d)/m*o,v=0,y=``;if(n.length>0&&_<=n[0].price){y=`Bid`;for(let e of n)if(_<=e.price)v=e.cumulativeVolume;else break}if(r.length>0&&_>=r[0].price){y=`Ask`;for(let e of r)if(_>=e.price)v=e.cumulativeVolume;else break}if(e.save(),e.strokeStyle=c.crosshair,e.lineWidth=.5,e.setLineDash([4,4]),e.beginPath(),e.moveTo(g,f),e.lineTo(g,p),e.stroke(),v>0){let t=p-v/s*h;e.beginPath(),e.moveTo(d,t),e.lineTo(i.right,t),e.stroke()}e.restore();let b=[`Price: ${l(_)}`,y?`${y} Vol: ${u(v)}`:``].filter(Boolean);e.save(),e.font=`${c.font.sizeSmall}px ${c.font.family}`;let x=Math.max(...b.map(t=>e.measureText(t).width))+16,S=b.length*(c.font.sizeSmall+4)+12,C=g+10,w=t.y-S/2;C+x>i.right&&(C=g-x-10),w<f&&(w=f),w+S>p&&(w=p-S),e.fillStyle=c.axisLabelBackground,e.globalAlpha=.9,e.fillRect(C,w,x,S),e.globalAlpha=1,e.fillStyle=c.text,e.textBaseline=`top`,e.textAlign=`left`;for(let t=0;t<b.length;t++)e.fillText(b[t],C+8,w+6+t*(c.font.sizeSmall+4));e.restore()}function $t(e){return e.toFixed(2)}function en(e){return e>=1e6?(e/1e6).toFixed(2)+`M`:e>=1e3?(e/1e3).toFixed(1)+`K`:e.toFixed(0)}function tn(e,t,n,r,i,a){let{data:o}=r;if(o.bids.length===0&&o.asks.length===0||t<=0||n<=0)return;let s=r.bidColor??i.candleUp,c=r.askColor??i.candleDown,l=r.bidFillColor??s+`40`,u=r.askFillColor??c+`40`,d=r.midPriceLine!==!1,f=r.spreadLabel!==!1,p=r.priceFormat??$t,m=r.volumeFormat??en,h=Gt(o.bids),g=Kt(o.asks),_=h.length>0?h[0].price:0,v=g.length>0?g[0].price:0,y=h.length>0&&g.length>0?(_+v)/2:_||v,b=g.length>0&&h.length>0?v-_:0,x=h.length>0?h[h.length-1].price:y,S=g.length>0?g[g.length-1].price:y,C=Math.max(y-x,S-y)*(1+Wt),w=y-C,T=y+C,E=T-w,D=h.length>0?h[h.length-1].cumulativeVolume:0,O=g.length>0?g[g.length-1].cumulativeVolume:0,k=Math.max(D,O)||1,A=qt(t,n);Jt(e,t,n,i.background),Yt(e,A,w,T,k,i,p,m),Xt(e,h,A,w,E,k,l,s,`bid`),Xt(e,g,A,w,E,k,u,c,`ask`),d&&Zt(e,y,b,A,w,E,i,f,p),a&&Qt(e,a,h,g,A,w,E,k,i,p,m)}var Y=70,nn=30,rn=20,an=20,on=.05;function sn(e,t){return{left:Y,right:e-rn,top:an,bottom:t-nn,plotWidth:e-Y-rn,plotHeight:t-an-nn}}function cn(e,t){let n=1/0,r=-1/0;for(let t of e)t.value<n&&(n=t.value),t.value>r&&(r=t.value);if(t)for(let e of t)e.value<n&&(n=e.value),e.value>r&&(r=e.value);let i=(r-n)*on;return{valMin:n-i,valMax:r+i}}function ln(e){let t=[],n=-1/0;for(let r of e)r.value>n&&(n=r.value),t.push(n);return t}function un(e){let t=864e5;if(365.25*t,e<7*t){let e=new Intl.DateTimeFormat(void 0,{hour:`2-digit`,minute:`2-digit`});return t=>e.format(new Date(t))}if(e<315576e5){let e=new Intl.DateTimeFormat(void 0,{month:`short`,day:`numeric`});return t=>e.format(new Date(t))}let n=new Intl.DateTimeFormat(void 0,{month:`short`,year:`numeric`});return e=>n.format(new Date(e))}function dn(e){return Math.abs(e)>=1e6?(e/1e6).toFixed(2)+`M`:Math.abs(e)>=1e3?(e/1e3).toFixed(1)+`K`:e.toFixed(2)}function fn(e,t,n,r){e.fillStyle=r,e.fillRect(0,0,t,n)}function pn(t,n,r,i,a,o,s,c,l){let{left:u,right:d,top:f,bottom:p,plotWidth:m,plotHeight:h}=n;t.save(),t.strokeStyle=s.grid,t.lineWidth=.5,t.fillStyle=s.axisLabel,t.font=`${s.font.sizeSmall}px ${s.font.family}`;let g=(0,e.computeTickStep)(r,i,6),_=Math.ceil(r/g)*g;for(let e=_;e<=i;e+=g){let n=p-(e-r)/(i-r)*h;t.beginPath(),t.moveTo(u,n),t.lineTo(d,n),t.stroke(),t.textAlign=`right`,t.textBaseline=`middle`,t.fillText(c(e),u-6,n)}let v=o-a,y=(0,e.computeTickStep)(a,o,6),b=Math.ceil(a/y)*y;for(let e=b;e<=o;e+=y){let n=u+(e-a)/v*m;t.beginPath(),t.moveTo(n,f),t.lineTo(n,p),t.stroke(),t.textAlign=`center`,t.textBaseline=`top`,t.fillText(l(e),n,p+4)}t.restore()}function mn(e,t,n,r,i,a,o,s,c){if(t.length<2)return;let{left:l,bottom:u,plotWidth:d,plotHeight:f}=n,p=e=>l+(e-r)/i*d,m=e=>u-(e-a)/o*f;e.save(),e.beginPath(),e.moveTo(p(t[0].time),m(t[0].value));for(let n=1;n<t.length;n++)e.lineTo(p(t[n].time),m(t[n].value));e.strokeStyle=s,e.lineWidth=c,e.lineJoin=`round`,e.stroke(),e.restore()}function hn(e,t,n,r,i,a,o,s){if(t.length<2)return;let{left:c,bottom:l,plotWidth:u,plotHeight:d}=n,f=e=>c+(e-r)/i*u,p=e=>l-(e-a)/o*d,m=e.createLinearGradient(0,n.top,0,l);m.addColorStop(0,s+`40`),m.addColorStop(1,`transparent`),e.save(),e.beginPath(),e.moveTo(f(t[0].time),p(t[0].value));for(let n=1;n<t.length;n++)e.lineTo(f(t[n].time),p(t[n].value));e.lineTo(f(t[t.length-1].time),l),e.lineTo(f(t[0].time),l),e.closePath(),e.fillStyle=m,e.fill(),e.restore()}function gn(e,t,n,r,i,a,o,s,c){if(t.length<2)return;let{left:l,bottom:u,plotWidth:d,plotHeight:f}=r,p=e=>l+(e-i)/a*d,m=e=>u-(e-o)/s*f;e.save(),e.fillStyle=c,e.beginPath(),e.moveTo(p(t[0].time),m(n[0]));for(let r=1;r<t.length;r++)e.lineTo(p(t[r].time),m(n[r]));for(let n=t.length-1;n>=0;n--)e.lineTo(p(t[n].time),m(t[n].value));e.closePath(),e.fill(),e.restore()}function _n(e,t,n,r,i,a,o,s,c,l){if(t.length===0)return;let{left:u,bottom:d,plotWidth:f,plotHeight:p}=n,m=t[t.length-1],h=u+(m.time-r)/i*f,g=d-(m.value-a)/o*p;e.save(),e.font=`${l.font.sizeSmall}px ${l.font.family}`,e.fillStyle=c,e.textAlign=`left`,e.textBaseline=`middle`,e.fillText(s,h+4,g),e.restore()}function vn(e,t,n,r,i,a,o,s,c,l,u,d){let{left:f,top:p,bottom:m,plotWidth:h,plotHeight:g}=i,_=t.x;if(_<f||_>i.right)return;e.save(),e.strokeStyle=l.crosshair,e.lineWidth=.5,e.setLineDash([4,4]),e.beginPath(),e.moveTo(_,p),e.lineTo(_,m),e.stroke(),e.restore();let v=a+(_-f)/h*o,y=0,b=1/0;for(let e=0;e<n.length;e++){let t=Math.abs(n[e].time-v);t<b&&(b=t,y=e)}let x=n[y],S=[u(x.time),`Value: ${d(x.value)}`];r&&r.length>y&&S.push(`Benchmark: ${d(r[y].value)}`);let C=f+(x.time-a)/o*h,w=m-(x.value-s)/c*g;e.beginPath(),e.arc(C,w,3,0,Math.PI*2),e.fillStyle=l.lineColor,e.fill(),e.save(),e.font=`${l.font.sizeSmall}px ${l.font.family}`;let T=Math.max(...S.map(t=>e.measureText(t).width))+16,E=S.length*(l.font.sizeSmall+4)+12,D=_+10,O=t.y-E/2;D+T>i.right&&(D=_-T-10),O<p&&(O=p),O+E>m&&(O=m-E),e.fillStyle=l.axisLabelBackground,e.globalAlpha=.9,e.fillRect(D,O,T,E),e.globalAlpha=1,e.fillStyle=l.text,e.textBaseline=`top`,e.textAlign=`left`;for(let t=0;t<S.length;t++)e.fillText(S[t],D+8,O+6+t*(l.font.sizeSmall+4));e.restore()}function yn(e,t,n,r,i,a){let{data:o}=r;if(o.length<2||t<=0||n<=0)return;let s=r.lineColor??i.lineColor,c=r.lineWidth??1.5,l=r.drawdown===!0,u=r.drawdownColor??i.candleDown+`30`,d=r.fillArea===!0,f=r.benchmark,p=r.benchmarkColor??i.textSecondary,m=r.benchmarkLabel??`Benchmark`,h=r.valueFormat??dn,{valMin:g,valMax:_}=cn(o,f),v=_-g||1,y=o[0].time,b=o[o.length-1].time,x=b-y||1,S=r.timeFormat??un(x),C=sn(t,n);fn(e,t,n,i.background),pn(e,C,g,_,y,b,i,h,S),l&&gn(e,o,ln(o),C,y,x,g,v,u),d&&hn(e,o,C,y,x,g,v,s),mn(e,o,C,y,x,g,v,s,c),f&&f.length>=2&&(mn(e,f,C,y,x,g,v,p,1),_n(e,f,C,y,x,g,v,m,p,i)),a&&vn(e,a,o,f,C,y,x,g,v,i,S,h)}function bn(e,t,n){if(e.length===0)return[];let r=e.length,i=Math.ceil(Math.sqrt(r)),a=Math.ceil(r/i),o=t.width/i,s=t.height/a,c=[];for(let a=0;a<r;a++){let r=a%i,l=Math.floor(a/i);c.push({id:e[a].id,rect:{x:t.x+r*o+n,y:t.y+l*s+n,width:Math.max(0,o-n*2),height:Math.max(0,s-n*2)}})}return c}function xn(e,t){let n=e.reduce((e,t)=>e+t,0);if(n===0||t===0)return 1/0;let r=0;for(let i of e){let e=n/t,a=i/e,o=e>a?e/a:a/e;o>r&&(r=o)}return r}function X(e,t,n,r,i,a){let o=r?n.height:n.width,s=e.reduce((e,t)=>e+t,0),c=o>0?s/o:0,l=0;for(let o=0;o<e.length;o++){let s=c>0?e[o]/c:0,u;u=r?{x:n.x+i,y:n.y+l+i,width:Math.max(0,c-i*2),height:Math.max(0,s-i*2)}:{x:n.x+l+i,y:n.y+i,width:Math.max(0,s-i*2),height:Math.max(0,c-i*2)},a.push({id:t[o],rect:u}),l+=s}}function Sn(e,t,n,r,i){if(e.length===0)return;let a=n.width>=n.height,o=a?n.height:n.width;if(e.length===1){X(e,t,n,a,r,i);return}let s=[],c=[],l=0;for(;l<e.length;){let u=[...s,e[l]];if(s.length===0||xn(u,o)<=xn(s,o))s.push(e[l]),c.push(t[l]),l++;else{X(s,c,n,a,r,i);let u=s.reduce((e,t)=>e+t,0),d=o>0?u/o:0;n=a?{x:n.x+d,y:n.y,width:n.width-d,height:n.height}:{x:n.x,y:n.y+d,width:n.width,height:n.height-d},Sn(e.slice(l),t.slice(l),n,r,i);return}}s.length>0&&X(s,c,n,a,r,i)}function Cn(e,t,n){if(e.length===0)return[];let r=[...e].sort((e,t)=>t.weight-e.weight),i=r.reduce((e,t)=>e+Math.max(0,t.weight),0);if(i===0)return[];let a=t.width*t.height,o=r.map(e=>Math.max(0,e.weight)/i*a),s=r.map(e=>e.id),c=[];return Sn(o,s,{...t},n,c),c}function wn(e){return(e>=0?`+`:``)+e.toFixed(2)+`%`}function Tn(e){return e.label}function En(t,n){let r=n.min??-5,i=n.max??5;if(t<=r)return n.negative;if(t>=i)return n.positive;if(t<0){let i=1-t/r;return(0,e.lerpColor)(n.negative,n.zero,i)}let a=t/i;return(0,e.lerpColor)(n.zero,n.positive,a)}function Z(e,t,n,r,i,a){let o=Math.min(a,r/2,i/2);e.beginPath(),e.moveTo(t+o,n),e.lineTo(t+r-o,n),e.arcTo(t+r,n,t+r,n+o,o),e.lineTo(t+r,n+i-o),e.arcTo(t+r,n+i,t+r-o,n+i,o),e.lineTo(t+o,n+i),e.arcTo(t,n+i,t,n+i-o,o),e.lineTo(t,n+o),e.arcTo(t,n,t+o,n,o),e.closePath()}function Dn(e,t,n,r,i,a,o,s,c,l,u){if(i<40||a<30)return;let d=n+i/2,f=r+a/2;if(e.save(),e.shadowColor=`rgba(0,0,0,0.6)`,e.shadowBlur=2,e.fillStyle=`#FFFFFF`,e.textAlign=`center`,s){let n=l(t),r=Math.min(o.font.sizeMedium,i/n.length*1.5,a/4);e.font=`bold `+Math.max(8,r)+`px `+o.font.family,e.textBaseline=c?`bottom`:`middle`,e.fillText(n,d,c?f-1:f,i-8)}if(c){let n=u(t.value),r=Math.min(o.font.sizeSmall,i/n.length*1.5,a/4);e.font=Math.max(7,r)+`px `+o.font.family,e.textBaseline=s?`top`:`middle`,e.fillText(n,d,s?f+1:f,i-8)}e.restore()}function On(e,t,n,r,i,a,o,s){let c=[o(t),s(t.value)];if(t.meta)for(let[e,n]of Object.entries(t.meta))c.push(e+`: `+String(n));e.save(),e.font=a.font.sizeSmall+`px `+a.font.family;let l=Math.max(...c.map(t=>e.measureText(t).width))+16,u=a.font.sizeSmall+4,d=c.length*u+12,f=n.x+14,p=n.y-d/2;f+l>r&&(f=n.x-l-14),p<0&&(p=0),p+d>i&&(p=i-d),e.fillStyle=a.axisLabelBackground,e.globalAlpha=.92,Z(e,f,p,l,d,4),e.fill(),e.globalAlpha=1,e.fillStyle=a.text,e.textBaseline=`top`,e.textAlign=`left`;for(let t=0;t<c.length;t++)e.fillText(c[t],f+8,p+6+t*u);e.restore()}function kn(e,t,n,r,i,a,o,s){if(r.length===0||i.length===0||t<=0||n<=0)return null;let c=a.colorScale??{negative:`#EF5350`,zero:`#424242`,positive:`#26A69A`},l=a.cellRadius??4,u=a.showLabels!==!1,d=a.showValues!==!1,f=a.valueFormat??wn,p=a.labelFormat??Tn,m=new Map;for(let e of r)m.set(e.id,e);let h=null,g=null;if(s)for(let e of i){let{x:t,y:n,width:r,height:i}=e.rect;if(s.x>=t&&s.x<=t+r&&s.y>=n&&s.y<=n+i){h=e.id;let t=m.get(e.id);t&&(g={cell:t,rect:e});break}}e.fillStyle=o.background,e.fillRect(0,0,t,n);for(let t of i){let n=m.get(t.id);if(!n)continue;let{x:r,y:i,width:a,height:s}=t.rect;if(a<=0||s<=0)continue;let g=En(n.value,c);Z(e,r,i,a,s,l),e.fillStyle=g,e.fill(),Dn(e,n,r,i,a,s,o,u,d,p,f),t.id===h&&(Z(e,r,i,a,s,l),e.strokeStyle=`#FFFFFF`,e.lineWidth=1.5,e.stroke())}return g&&s&&On(e,g.cell,s,t,n,o,p,f),g}var An=60,jn=12,Mn=24,Nn=40,Pn=.7,Fn=1;function In(e){return e.type?e.type:e.value>0?`positive`:e.value<0?`negative`:`subtotal`}function Ln(e){let t=Math.abs(e);return t>=1e6?(e/1e6).toFixed(2)+`M`:t>=1e3?(e/1e3).toFixed(1)+`K`:e.toFixed(2)}function Rn(e,t){return{left:An,right:e-jn,top:Mn,bottom:t-Nn,plotWidth:e-An-jn,plotHeight:t-Mn-Nn}}function zn(e,t,n,r,i){let a=Array(e.length),o=Array(e.length),s=t.plotWidth/e.length,c=s*n,l=(s-c)/2,{left:u,bottom:d,plotHeight:f}=t,p=0;for(let t=0;t<e.length;t++){let n=e[t],m=In(n),h,g;m===`total`||m===`subtotal`?(h=0,g=n.value,p=n.value):(h=p,g=p+n.value,p=g);let _=Math.min(h,g),v=Math.max(h,g),y=d-(_-r)/i*f,b=d-(v-r)/i*f,x=Math.min(y,b),S=Math.max(Math.abs(b-y),Fn),C=u+t*s,w=C+l;a[t]={label:n.label,value:n.value,start:h,end:g,type:m,rectX:w,rectY:x,rectW:c,rectH:S,slotX:C,slotW:s},o[t]=p}return{bars:a,cumulatives:o}}function Bn(e){if(e.length===0)return{valMin:0,valMax:1};let t=0,n=0,r=0;for(let i=0;i<e.length;i++){let a=e[i],o=In(a),s,c;o===`total`||o===`subtotal`?(s=0,c=a.value,r=a.value):(s=r,c=r+a.value,r=c),s<t&&(t=s),c<t&&(t=c),s>n&&(n=s),c>n&&(n=c)}let i=(n-t||1)*.1;return{valMin:t-i,valMax:n+i}}function Vn(e,t,n,r){e.fillStyle=r,e.fillRect(0,0,t,n)}function Hn(t,n,r,i,a,o){let{left:s,right:c,top:l,bottom:u,plotHeight:d}=n,f=i-r||1;t.strokeStyle=a.grid,t.lineWidth=.5,t.fillStyle=a.axisLabel,t.font=`${a.font.sizeSmall}px ${a.font.family}`,t.textAlign=`right`,t.textBaseline=`middle`;let p=(0,e.computeTickStep)(r,i,5),m=Math.ceil(r/p)*p;t.beginPath();for(let e=m;e<=i;e+=p){let n=Math.round(u-(e-r)/f*d)+.5;n<l||n>u||(t.moveTo(s,n),t.lineTo(c,n))}t.stroke();for(let e=m;e<=i;e+=p){let n=u-(e-r)/f*d;n<l-1||n>u+1||t.fillText(o(e),s-6,n)}if(r<0&&i>0){let e=Math.round(u-(0-r)/f*d)+.5;t.strokeStyle=a.axisLine,t.lineWidth=1,t.beginPath(),t.moveTo(s,e),t.lineTo(c,e),t.stroke()}}function Un(e,t,n){let r=[`positive`,`negative`,`total`,`subtotal`];for(let i=0;i<r.length;i++){let a=r[i],o=n[a],s=!1;e.beginPath();for(let n=0;n<t.length;n++){let r=t[n];if(r.type!==a)continue;let i=Math.round(r.rectX),o=Math.round(r.rectY),c=Math.round(r.rectW),l=Math.round(r.rectH);e.rect(i,o,c,l),s=!0}s&&(e.fillStyle=o,e.fill())}}function Wn(e,t,n,r,i,a,o){if(o===`none`||t.length<2)return;let{bottom:s,plotHeight:c}=n;e.strokeStyle=a,e.lineWidth=1,o===`dashed`?e.setLineDash([4,4]):e.setLineDash([]),e.beginPath();for(let n=0;n<t.length-1;n++){let a=t[n],o=t[n+1],l=a.end,u=Math.round(s-(l-r)/i*c)+.5,d=Math.round(a.rectX+a.rectW),f=Math.round(o.rectX);f<=d||(e.moveTo(d,u),e.lineTo(f,u))}e.stroke(),e.setLineDash([])}function Gn(e,t,n,r,i,a){e.fillStyle=r.text,e.font=`${r.font.sizeSmall}px ${r.font.family}`,e.textAlign=`center`;for(let r=0;r<t.length;r++){let o=t[r],s;s=o.type===`total`||o.type===`subtotal`?i(o.value):a?`${o.value>=0?`+`:``}${i(o.value)}`:i(n[r]);let c=o.rectX+o.rectW/2;o.end<o.start?(e.textBaseline=`top`,e.fillText(s,c,o.rectY+o.rectH+4)):(e.textBaseline=`bottom`,e.fillText(s,c,o.rectY-4))}}function Kn(e,t,n,r,i){e.fillStyle=r.axisLabel,e.font=`${r.font.sizeSmall}px ${r.font.family}`,e.textAlign=`center`,e.textBaseline=`top`;let a=n.bottom+6,o=t.length>0?t[0].slotW-4:0,s=!1;for(let n=0;n<t.length;n++)if(e.measureText(i(t[n].label)).width>o){s=!0;break}if(!s){for(let n=0;n<t.length;n++){let r=t[n],o=r.slotX+r.slotW/2;e.fillText(i(r.label),o,a)}return}e.save(),e.textAlign=`right`,e.textBaseline=`middle`;for(let n=0;n<t.length;n++){let r=t[n],o=r.slotX+r.slotW/2;e.setTransform(1,0,0,1,o,a+4),e.rotate(-Math.PI/4),e.fillText(i(r.label),0,0)}e.setTransform(1,0,0,1,0,0),e.restore()}function qn(e,t,n){if(t<n.left||t>n.right)return null;for(let n=0;n<e.length;n++){let r=e[n];if(t>=r.slotX&&t<=r.slotX+r.slotW)return n}return null}function Jn(e,t,n,r,i,a,o,s){let c=t[r],l=n[r],u=Math.round(c.slotX+c.slotW/2)+.5;e.strokeStyle=o.crosshair,e.lineWidth=.5,e.setLineDash([4,4]),e.beginPath(),e.moveTo(u,a.top),e.lineTo(u,a.bottom),e.stroke(),e.setLineDash([]);let d=[c.label,`Value: ${c.value>=0&&(c.type===`positive`||c.type===`negative`)?`+`:``}${s(c.value)}`,`Total: ${s(l)}`];e.font=`${o.font.sizeSmall}px ${o.font.family}`;let f=0;for(let t=0;t<d.length;t++){let n=e.measureText(d[t]).width;n>f&&(f=n)}let p=f+16,m=d.length*(o.font.sizeSmall+4)+12,h=i.x+10,g=i.y-m/2;h+p>a.right&&(h=i.x-p-10),g<a.top&&(g=a.top),g+m>a.bottom&&(g=a.bottom-m),e.fillStyle=o.axisLabelBackground,e.globalAlpha=.9,e.fillRect(h,g,p,m),e.globalAlpha=1,e.fillStyle=o.text,e.textAlign=`left`,e.textBaseline=`top`;let _=o.font.sizeSmall+4;for(let t=0;t<d.length;t++)e.fillText(d[t],h+8,g+6+t*_)}function Yn(e,t,n,r,i,a){let{data:o}=r;if(!o||o.length===0||t<=0||n<=0)return{hitBar:null};let s=r.positiveColor??i.candleUp,c=r.negativeColor??i.candleDown,l=r.totalColor??i.lineColor,u=r.subtotalColor??i.textSecondary,d=r.connectorColor??i.textSecondary,f=r.connectorStyle??`dashed`,p=r.barWidth??Pn,m=r.showValues!==!1,h=r.showDelta!==!1,g=r.valueFormat??Ln,_=r.labelFormat??(e=>e),{valMin:v,valMax:y}=Bn(o),b=y-v||1,x=Rn(t,n),{bars:S,cumulatives:C}=zn(o,x,p,v,b);Vn(e,t,n,i.background),Hn(e,x,v,y,i,g),Wn(e,S,x,v,b,d,f),Un(e,S,{positive:s,negative:c,total:l,subtotal:u}),m&&Gn(e,S,C,i,g,h),Kn(e,S,x,i,_);let w=a?qn(S,a.x,x):null;return a&&w!==null&&Jn(e,S,C,w,a,x,i,g),{hitBar:w}}var Xn=Math.PI/180,Zn=135,Qn=405,$n=.25;function er(e){let t=Math.abs(e);return t>=1e6?(e/1e6).toFixed(2)+`M`:t>=1e3?(e/1e3).toFixed(1)+`K`:Number.isInteger(e)?e.toFixed(0):e.toFixed(1)}function Q(e,t,n){return e<t?t:e>n?n:e}function tr(e,t,n){let r=n.min??0,i=n.max??100,a=i-r||1,o=(n.startAngle??Zn)*Xn,s=(n.endAngle??Qn)*Xn,c=n.thickness??$n,l=e/2,u=t/2+t*.05,d=Math.max(10,Math.min(e,t)/2-24);return{cx:l,cy:u,radius:d,innerRadius:Math.max(2,d*(1-c)),startAngle:o,endAngle:s,angleRange:s-o,min:r,max:i,range:a}}function $(e,t){let n=Q((e-t.min)/t.range,0,1);return t.startAngle+t.angleRange*n}function nr(e,t,n,r){e.fillStyle=r,e.fillRect(0,0,t,n)}function rr(e,t,n){e.beginPath(),e.arc(t.cx,t.cy,t.radius,t.startAngle,t.endAngle,!1),e.arc(t.cx,t.cy,t.innerRadius,t.endAngle,t.startAngle,!0),e.closePath(),e.fillStyle=n,e.fill()}function ir(e,t,n){let r=Q(n.from,t.min,t.max),i=Q(n.to,t.min,t.max);if(i<=r)return;let a=$(r,t),o=$(i,t);e.beginPath(),e.arc(t.cx,t.cy,t.radius,a,o,!1),e.arc(t.cx,t.cy,t.innerRadius,o,a,!0),e.closePath(),e.fillStyle=n.color,e.fill()}function ar(e,t,n,r,i){let a=$(n,t);a<=t.startAngle||(e.globalAlpha=i,e.beginPath(),e.arc(t.cx,t.cy,t.radius,t.startAngle,a,!1),e.arc(t.cx,t.cy,t.innerRadius,a,t.startAngle,!0),e.closePath(),e.fillStyle=r,e.fill(),e.globalAlpha=1)}function or(e,t,n,r){let i=$(n,t),a=Math.cos(i),o=Math.sin(i),s=t.radius-2,c=t.innerRadius*.25,l=-o,u=a,d=t.cx+a*s,f=t.cy+o*s,p=t.cx+l*4-a*c,m=t.cy+u*4-o*c,h=t.cx-l*4-a*c,g=t.cy-u*4-o*c;e.beginPath(),e.moveTo(d,f),e.lineTo(p,m),e.lineTo(h,g),e.closePath(),e.fillStyle=r,e.fill(),e.beginPath(),e.arc(t.cx,t.cy,Math.max(4,t.innerRadius*.12),0,Math.PI*2),e.fill()}function sr(e,t,n,r,i){let a=Math.round(t.innerRadius*.55),o=Math.round(i.font.sizeMedium);e.fillStyle=i.text,e.textAlign=`center`,e.textBaseline=`middle`,e.font=`600 ${a}px ${i.font.family}`;let s=!!r,c=s?t.cy-o*.6:t.cy-a*.1;e.fillText(n,t.cx,c),s&&(e.fillStyle=i.textSecondary,e.font=`${o}px ${i.font.family}`,e.fillText(r,t.cx,t.cy+a*.55))}function cr(e,t,n,r){e.fillStyle=r.textSecondary,e.font=`${r.font.sizeSmall}px ${r.font.family}`;let i=t.radius+10,a=Math.cos(t.startAngle),o=Math.sin(t.startAngle),s=Math.cos(t.endAngle),c=Math.sin(t.endAngle),l=t.cx+a*i,u=t.cy+o*i,d=t.cx+s*i,f=t.cy+c*i;e.textBaseline=`middle`,e.textAlign=a<-.2?`right`:a>.2?`left`:`center`,e.fillText(n(t.min),l,u),e.textAlign=s<-.2?`right`:s>.2?`left`:`center`,e.fillText(n(t.max),d,f)}function lr(e,t,n,r){e.fillStyle=r.textSecondary,e.font=`${r.font.sizeSmall}px ${r.font.family}`,e.textAlign=`center`,e.textBaseline=`middle`;let i=(t.radius+t.innerRadius)/2;for(let r=0;r<n.length;r++){let a=n[r];if(!a.label)continue;let o=$((Q(a.from,t.min,t.max)+Q(a.to,t.min,t.max))/2,t),s=t.cx+Math.cos(o)*i,c=t.cy+Math.sin(o)*i;e.fillText(a.label,s,c)}}function ur(e,t,n,r,i,a){if(t<=0||n<=0)return;let o=tr(t,n,r),s=r.trackColor??i.grid,c=r.needleColor??i.text,l=r.showValue!==!1,u=r.showZoneLabels===!0,d=r.valueFormat??er,f=Q(a,o.min,o.max);nr(e,t,n,i.background),rr(e,o,s);let p=r.zones;if(p&&p.length>0)for(let t=0;t<p.length;t++)ir(e,o,p[t]);ar(e,o,f,c,.12),or(e,o,f,c),l&&sr(e,o,d(f),r.label,i),cr(e,o,d,i),u&&p&&p.length>0&&lr(e,o,p,i)}exports.ADXIndicator=he,exports.ATRIndicator=me,exports.AccumulationDistributionIndicator=z,exports.AlertManager=jt,exports.AnchoredVWAPTool=ct,exports.Animator=Lt,exports.AreaRenderer=h,exports.AroonIndicator=N,exports.ArrowTool=it,exports.BarCountdown=Ot,exports.BarRenderer=g,exports.BaseFinanceChart=zt,exports.BaselineRenderer=v,exports.BinanceAdapter=St,exports.BollingerBandsIndicator=ie,exports.CCIIndicator=j,exports.CMFIndicator=I,exports.CandlestickRenderer=p,exports.CanvasLayer=t,exports.ChartLegend=Tt,exports.ChartStateManager=Nt,exports.CompareRenderer=C,exports.CrosshairHandler=ke,exports.CrosshairTooltip=je,exports.CurrentPriceLine=yt,exports.DEFAULT_LEGEND_CONFIG=wt,exports.DPRManager=i,exports.DataExporter=Ft,exports.DateRangeTool=tt,exports.DepthOverlay=pt,exports.DonchianChannelIndicator=ue,exports.DrawingBase=V,exports.DrawingManager=Ie,exports.DrawingRenderer=Le,exports.EMAIndicator=re,exports.Easing=It,exports.ElliottWaveTool=$e,exports.EllipseTool=Ye,exports.Emitter=G,exports.EventBus=Pe,exports.ExtendedLineTool=He,exports.FibExtensionTool=qe,exports.FibRetracementTool=Ge,exports.FinanceCrosshair=Bt,exports.GannBoxTool=st,exports.GannFanTool=ot,exports.GridRenderer=be,exports.HollowCandleRenderer=_,exports.HorizontalLineTool=ze,exports.IchimokuIndicator=oe,exports.IndicatorBase=A,exports.IndicatorEngine=te,exports.InteractionManager=Ee,exports.KagiRenderer=b,exports.KeltnerChannelIndicator=le,exports.KeyboardHandler=Ae,exports.LayerManager=n,exports.LineRenderer=m,exports.MACDIndicator=fe,exports.MFIIndicator=M,exports.MeasureTool=nt,exports.MockAdapter=Ct,exports.OBVIndicator=ge,exports.OrderRenderer=dt,exports.PanHandler=De,exports.ParabolicSARIndicator=se,exports.ParallelChannelTool=Ue,exports.PitchforkTool=Ze,exports.PointAndFigureRenderer=x,exports.PositionRenderer=ft,exports.PriceAxis=xe,exports.PriceRangeTool=et,exports.ROCIndicator=P,exports.RSIIndicator=de,exports.RayTool=Ve,exports.ReconnectManager=K,exports.RectangleTool=Je,exports.RegressionChannelTool=We,exports.RenderEngine=u,exports.RenderLoop=r,exports.RenkoRenderer=y,exports.ReplayManager=Mt,exports.SMAIndicator=ne,exports.Screenshot=Et,exports.SessionBreaks=kt,exports.StdDevIndicator=L,exports.StochasticIndicator=pe,exports.StreamManager=bt,exports.SupertrendIndicator=ce,exports.TSIIndicator=F,exports.TextAnnotationTool=rt,exports.TickAggregator=vt,exports.TimeAxis=Te,exports.TradingContextMenu=ht,exports.TradingDragHandler=mt,exports.TradingManager=gt,exports.TradingRenderer=_t,exports.TrendLineTool=Re,exports.TriangleTool=Xe,exports.UndoRedoManager=Pt,exports.VROCIndicator=ve,exports.VWAPIndicator=ae,exports.VerticalLineTool=Be,exports.Viewport=d,exports.VolumeProfileIndicator=R,exports.VolumeProfileRangeTool=lt,exports.VolumeRenderer=S,exports.Watermark=Dt,exports.WilliamsRIndicator=_e,exports.ZoomHandler=Oe,exports.barIndexToX=a,exports.getVisibleData=f,exports.layoutSquarifiedTreemap=Cn,exports.layoutUniformGrid=bn,exports.priceToY=o,exports.registerBuiltInDrawingTools=ut,exports.registerBuiltInIndicators=ye,exports.renderDepthChart=tn,exports.renderEquityCurve=yn,exports.renderGauge=ur,exports.renderHeatmap=kn,exports.renderSparkline=Vt,exports.renderWaterfall=Yn,exports.timestampToBarIndex=l,exports.toHeikinAshi=w,exports.toKagi=O,exports.toLineBreak=D,exports.toPointAndFigure=k,exports.toRenko=T,exports.xToBarIndex=s,exports.yToPrice=c;
21
21
  //# sourceMappingURL=index.cjs.map