openalgo-charts 1.0.26 → 1.0.28

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.
@@ -142,6 +142,14 @@ interface DrawingTool {
142
142
  * draggable handle.
143
143
  */
144
144
  expand?(clicked: readonly DrawingPoint[], ctx: ExpandContext): DrawingPoint[];
145
+ /**
146
+ * Keyboard shortcut that arms this tool, as `'Alt+T'` / `'Shift+Alt+F'` —
147
+ * modifiers in `Ctrl`, `Alt`, `Shift` order, then a single key. Hosts render
148
+ * it beside the tool's name in a palette and bind it with
149
+ * `matchDrawingShortcut`; the library itself installs no listener, since only
150
+ * the host knows whether the chart has focus or a dialog is open.
151
+ */
152
+ shortcut?: string;
145
153
  /** Merged under the caller's style when a drawing is created. */
146
154
  defaultStyle?: DrawingStyle;
147
155
  draw(c: DrawContext): void;
@@ -165,6 +173,28 @@ declare function registerDrawingTool(tool: DrawingTool): void;
165
173
  declare function getDrawingTool(id: string): DrawingTool;
166
174
  declare function hasDrawingTool(id: string): boolean;
167
175
  declare function registeredDrawingTools(): DrawingTool[];
176
+ /** Keyboard event fields a shortcut is matched against. */
177
+ interface ShortcutEvent {
178
+ key: string;
179
+ altKey?: boolean;
180
+ ctrlKey?: boolean;
181
+ metaKey?: boolean;
182
+ shiftKey?: boolean;
183
+ }
184
+ /**
185
+ * The id of the tool whose `shortcut` matches this key event, or `null`.
186
+ *
187
+ * Pure, so a host can bind one `keydown` listener and decide for itself when
188
+ * shortcuts apply — the library installs no listener, because only the host
189
+ * knows whether the chart has focus, a dialog is open, or the user is typing.
190
+ *
191
+ * Modifiers must match exactly: `Alt+T` will not fire for `Ctrl+Alt+T`, so a
192
+ * tool shortcut cannot shadow a browser or host chord. `metaKey` (Cmd) is
193
+ * treated as Ctrl, which is what a Mac user expects.
194
+ */
195
+ declare function matchDrawingShortcut(e: ShortcutEvent): string | null;
196
+ /** Every registered tool that has a shortcut, as `id -> shortcut`. */
197
+ declare function drawingShortcuts(): Record<string, string>;
168
198
  declare const TREND_LINE: DrawingTool;
169
199
  declare const RAY: DrawingTool;
170
200
  declare const EXTENDED_LINE: DrawingTool;
@@ -396,4 +426,4 @@ declare function extendSegment(a: ScreenPoint, b: ScreenPoint, width: number, le
396
426
 
397
427
  declare const DRAW_TIER: "draw";
398
428
 
399
- export { ARROW, BUILTIN_DRAWING_TOOLS, CROSS_LINE, DRAW_TIER, type DrawContext, type Drawing, DrawingController, type DrawingControllerOptions, DrawingLayer, type DrawingPoint, type DrawingStyle, type DrawingTool, ELLIPSE, EXTENDED_LINE, FIB_EXTENSION, FIB_RETRACEMENT, HORIZONTAL_LINE, HORIZONTAL_RAY, type HitContext, LONG_POSITION, MEASURE, PARALLEL_CHANNEL, PATH, RAY, RECTANGLE, SHORT_POSITION, type ScreenPoint, TEXT, TREND_LINE, VERTICAL_LINE, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, extendSegment, getDrawingTool, hasDrawingTool, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools };
429
+ export { ARROW, BUILTIN_DRAWING_TOOLS, CROSS_LINE, DRAW_TIER, type DrawContext, type Drawing, DrawingController, type DrawingControllerOptions, DrawingLayer, type DrawingPoint, type DrawingStyle, type DrawingTool, ELLIPSE, EXTENDED_LINE, FIB_EXTENSION, FIB_RETRACEMENT, HORIZONTAL_LINE, HORIZONTAL_RAY, type HitContext, LONG_POSITION, MEASURE, PARALLEL_CHANNEL, PATH, RAY, RECTANGLE, SHORT_POSITION, type ScreenPoint, type ShortcutEvent, TEXT, TREND_LINE, VERTICAL_LINE, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, drawingShortcuts, extendSegment, getDrawingTool, hasDrawingTool, matchDrawingShortcut, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools };
package/dist/index.d.ts CHANGED
@@ -1053,6 +1053,16 @@ declare class PriceLine implements IPrimitive {
1053
1053
  setPrice(price: number): void;
1054
1054
  /** Update the info segment text (e.g. live position P&L); repaints. */
1055
1055
  setLeftLabel(text: string): void;
1056
+ /**
1057
+ * Restyle in place; repaints. `id` is the hit-test handle the chart routes
1058
+ * clicks and drags through, so it is not patchable — swapping it under a
1059
+ * live drag would strand the gesture.
1060
+ *
1061
+ * A last-price line is the case this exists for: it has to follow the tick
1062
+ * direction, and only `setPrice` was updatable, so the colour was stuck at
1063
+ * whatever it was constructed with.
1064
+ */
1065
+ setOptions(patch: Partial<Omit<PriceLineOptions, 'id'>>): void;
1056
1066
  /**
1057
1067
  * Show a dimmed reference line at the pre-drag price while the user drags
1058
1068
  * (pass the original price on drag start, null on drag end to clear).
@@ -1,2 +1,2 @@
1
- function t(t,e,i,n){const s=n.x-i.x,o=n.y-i.y,l=s*s+o*o;if(0===l)return Math.hypot(t-i.x,e-i.y);let r=((t-i.x)*s+(e-i.y)*o)/l;return r=r<0?0:r>1?1:r,Math.hypot(t-(i.x+r*s),e-(i.y+r*o))}function e(t,e,i,n){const s=n.x-i.x,o=n.y-i.y,l=Math.hypot(s,o);return 0===l?Math.hypot(t-i.x,e-i.y):Math.abs(o*(t-i.x)-s*(e-i.y))/l}function i(t,e){return Math.abs(t-e)}function n(t,e){return Math.abs(t-e)}function s(e,i,n){let s=1/0;for(let o=1;o<n.length;o++){const l=t(e,i,n[o-1],n[o]);l<s&&(s=l)}return s}function o(t,e){return{x0:Math.min(t.x,e.x),y0:Math.min(t.y,e.y),x1:Math.max(t.x,e.x),y1:Math.max(t.y,e.y)}}function l(e,i,n,s,l){const r=o(n,s);if(e>=r.x0&&e<=r.x1&&i>=r.y0&&i<=r.y1&&l)return 0;const a=[{x:r.x0,y:r.y0},{x:r.x1,y:r.y0},{x:r.x1,y:r.y1},{x:r.x0,y:r.y1}];let c=1/0;for(let n=0;n<4;n++){const s=t(e,i,a[n],a[(n+1)%4]);s<c&&(c=s)}return c}function r(t,e,i,n,s){const l=o(i,n),r=(l.x0+l.x1)/2,a=(l.y0+l.y1)/2,c=Math.max(1e-6,(l.x1-l.x0)/2),h=Math.max(1e-6,(l.y1-l.y0)/2),x=(t-r)/c,d=(e-a)/h,p=Math.hypot(x,d);return s&&p<=1?0:Math.abs(p-1)*Math.min(c,h)}function a(t,e,i,n,s){const o=e.x-t.x;if(0===o)return[t,e];const l=(e.y-t.y)/o;return[n?{x:0,y:t.y+(0-t.x)*l}:t,s?{x:i,y:t.y+(i-t.x)*l}:e]}function c(t){const e=function(t){const e=t.trim();if(e.startsWith("#")){const t=e.slice(1);if(3===t.length||4===t.length){const[e,i,n,s]=[...t].map(t=>parseInt(t+t,16));return[e,i,n].some(Number.isNaN)?null:{r:e,g:i,b:n,a:4===t.length?s/255:1}}if(6===t.length||8===t.length){const e=parseInt(t.slice(0,6),16);if(Number.isNaN(e))return null;const i=8===t.length?parseInt(t.slice(6,8),16)/255:1;return{r:e>>16&255,g:e>>8&255,b:255&e,a:Number.isNaN(i)?1:i}}return null}const i=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i.exec(e);return null===i?null:{r:Number(i[1]),g:Number(i[2]),b:Number(i[3]),a:void 0===i[4]?1:Number(i[4])}}(t);if(null===e)return.5;const i=t=>{const e=t/255;return e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4)};return.2126*i(e.r)+.7152*i(e.g)+.0722*i(e.b)}function h(t){return c(t)>.45?"#10131a":"#ffffff"}function x(t,e,i,n,s,o){const l=t.roundRect;"function"==typeof l?l.call(t,e,i,n,s,Math.max(0,Math.min(o,n/2,s/2))):t.rect(e,i,n,s)}const d=new Map;function p(t){d.set(t.id,t)}function y(t){const e=d.get(t);if(void 0===e)throw new Error(`openalgo-charts: unknown drawing tool "${t}"`);return e}function u(t){return d.has(t)}function f(){return Array.from(d.values())}function g(t){const{ctx:e,rc:i,style:n}=t,s=i.dpr;e.strokeStyle=n.color,e.lineWidth=Math.max(1,Math.round(n.lineWidth*s)),e.lineJoin="round",e.lineCap="round",e.setLineDash("dashed"===n.lineStyle?[6*s,4*s]:"dotted"===n.lineStyle?[1*s,3*s]:[])}function m(t){return t.style.fillColor??t.style.color}function b(t,e){if(!0!==t.style.fill)return;const{ctx:i}=t;i.save(),i.globalAlpha=t.style.fillOpacity??.12,i.fillStyle=m(t),e(),i.restore()}function _(t,e,i,n,s){const{ctx:o,rc:l,style:r}=t,a=(r.fontSize??11)*l.dpr;o.save(),o.setLineDash([]),o.font=`${a}px ui-sans-serif, system-ui, sans-serif`,o.textBaseline="middle",o.textAlign="left";const c=o.measureText(e).width;o.globalAlpha=.85,o.fillStyle=l.theme.background,o.fillRect(i-2*l.dpr,n-.75*a,c+4*l.dpr,1.5*a),o.globalAlpha=1,o.fillStyle=s??r.color,o.fillText(e,i,n),o.restore()}function w(t,e,i,n,s,o={}){const{ctx:l,rc:r}=t,a=r.dpr,c=(t.style.fontSize??11)*a;l.save(),l.setLineDash([]),l.globalAlpha=1,l.font=`${c}px ui-sans-serif, system-ui, sans-serif`,l.textBaseline="middle",l.textAlign="left";const d=5*a,p=3*a,y=1.35*c;let u=0;for(const t of e)u=Math.max(u,l.measureText(t).width);const f=u+2*d,g=y*e.length+2*p,m=o.align??"left",b="center"===m?i-f/2:"right"===m?i-f:i,_=o.place??"above",w="above"===_?n-g-4*a:"below"===_?n+4*a:n-g/2;l.beginPath(),x(l,b,w,f,g,3*a),l.fillStyle=s,l.fill(),l.fillStyle=h(s);for(let t=0;t<e.length;t++)l.fillText(e[t],b+d,w+p+y*(t+.5));return l.restore(),g}function M(t,e=0){const[i,n]=Math.abs(t).toFixed(e).split(".");return(t<0?"-":"")+i.replace(/\B(?=(\d{3})+(?!\d))/g,",")+(void 0===n?"":"."+n)}function v(t){const e=new Date(1e3*t),i=t=>String(t).padStart(2,"0");return`${e.getUTCFullYear()}-${i(e.getUTCMonth()+1)}-${i(e.getUTCDate())}`}function T(t){const e=Math.max(0,Math.round(Math.abs(t))),i=Math.floor(e/86400),n=Math.floor(e%86400/3600),s=Math.floor(e%3600/60);return i>0?`${i}d ${n}h`:n>0?`${n}h ${s}m`:`${s}m`}function S(t,e,i){const n=Math.max(8,5*t.style.lineWidth)*t.rc.dpr,s=Math.atan2(i.y-e.y,i.x-e.x);t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x-n*Math.cos(s-.4),i.y-n*Math.sin(s-.4)),t.ctx.lineTo(i.x-n*Math.cos(s+.4),i.y-n*Math.sin(s+.4)),t.ctx.closePath(),t.ctx.fillStyle=t.style.color,t.ctx.fill()}const P="#26a69a",L="#ef5350",k=[0,.236,.382,.5,.618,.786,1];function D(i,n,s,o){return{id:i,name:n,points:2,defaultStyle:{extendLeft:s,extendRight:o},draw:t=>{const[e,i]=a(t.pts[0],t.pts[1],t.rc.plotWidth*t.rc.dpr,t.style.extendLeft??s,t.style.extendRight??o);g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(i,n,l)=>{const r=l.drawing.style.extendLeft??s,c=l.drawing.style.extendRight??o;if(r&&c)return e(i,n,l.pts[0],l.pts[1]);const[h,x]=a(l.pts[0],l.pts[1],l.rc.plotWidth,r,c);return t(i,n,h,x)}}}const $=D("trend-line","Trend Line",!1,!1),O=D("ray","Ray",!1,!0),F=D("extended-line","Extended Line",!0,!0),A={id:"arrow",name:"Arrow",points:2,draw:t=>{const[e,i]=t.pts;g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.stroke();const n=Math.max(8,5*t.style.lineWidth)*t.rc.dpr,s=Math.atan2(i.y-e.y,i.x-e.x);t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x-n*Math.cos(s-.4),i.y-n*Math.sin(s-.4)),t.ctx.lineTo(i.x-n*Math.cos(s+.4),i.y-n*Math.sin(s+.4)),t.ctx.closePath(),t.ctx.fillStyle=t.style.color,t.ctx.fill(),t.ctx.setLineDash([])},distance:(e,i,n)=>t(e,i,n.pts[0],n.pts[1])},N={id:"horizontal-line",name:"Horizontal Line",points:1,defaultStyle:{showLabels:!0},draw:t=>{const e=Math.round(t.pts[0].y)+.5;g(t),t.ctx.beginPath(),t.ctx.moveTo(0,e),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,e),t.ctx.stroke(),t.ctx.setLineDash([]),!1!==t.style.showLabels&&_(t,t.formatPrice(t.drawing.points[0].price),4*t.rc.dpr,e-8*t.rc.dpr)},distance:(t,e,n)=>i(e,n.pts[0].y)},W={id:"horizontal-ray",name:"Horizontal Ray",points:1,defaultStyle:{showLabels:!0},draw:t=>{const e=Math.round(t.pts[0].y)+.5;g(t),t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,e),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,e),t.ctx.stroke(),t.ctx.setLineDash([]),!1!==t.style.showLabels&&_(t,t.formatPrice(t.drawing.points[0].price),t.pts[0].x+4*t.rc.dpr,e-8*t.rc.dpr)},distance:(t,e,n)=>t<n.pts[0].x?null:i(e,n.pts[0].y)},C={id:"vertical-line",name:"Vertical Line",points:1,draw:t=>{const e=Math.round(t.pts[0].x)+.5;g(t),t.ctx.beginPath(),t.ctx.moveTo(e,0),t.ctx.lineTo(e,t.rc.plotHeight*t.rc.dpr),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>n(t,i.pts[0].x)},I={id:"cross-line",name:"Cross Line",points:1,draw:t=>{const e=Math.round(t.pts[0].x)+.5,i=Math.round(t.pts[0].y)+.5;g(t),t.ctx.beginPath(),t.ctx.moveTo(e,0),t.ctx.lineTo(e,t.rc.plotHeight*t.rc.dpr),t.ctx.moveTo(0,i),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,i),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,s)=>Math.min(n(t,s.pts[0].x),i(e,s.pts[0].y))},R={id:"rectangle",name:"Rectangle",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"left",textVAlign:"top",textPosition:"inside"},draw:t=>{const e=o(t.pts[0],t.pts[1]);b(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),g(t),t.ctx.strokeRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.setLineDash([]),Z(t,e.x0,e.y0,e.x1,e.y1)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},z={id:"ellipse",name:"Ellipse",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"center",textVAlign:"middle",textPosition:"inside"},draw:t=>{const e=o(t.pts[0],t.pts[1]),i=(e.x0+e.x1)/2,n=(e.y0+e.y1)/2,s=Math.max(1,(e.x1-e.x0)/2),l=Math.max(1,(e.y1-e.y0)/2),r=()=>{t.ctx.beginPath(),t.ctx.ellipse(i,n,s,l,0,0,2*Math.PI)};b(t,()=>{r(),t.ctx.fill()}),g(t),r(),t.ctx.stroke(),t.ctx.setLineDash([]),Z(t,e.x0,e.y0,e.x1,e.y1)},distance:(t,e,i)=>r(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},j={id:"parallel-channel",name:"Parallel Channel",points:3,defaultStyle:{fill:!0},draw:t=>{const[e,i,n]=t.pts,s=n.y-(e.y+.5*(i.y-e.y)),o={x:e.x,y:e.y+s},l={x:i.x,y:i.y+s};b(t,()=>{t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.lineTo(l.x,l.y),t.ctx.lineTo(o.x,o.y),t.ctx.closePath(),t.ctx.fill()}),g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.moveTo(o.x,o.y),t.ctx.lineTo(l.x,l.y),t.ctx.stroke(),t.ctx.setLineDash([]),Z(t,Math.min(e.x,i.x),Math.min(e.y,i.y,o.y,l.y),Math.max(e.x,i.x),Math.max(e.y,i.y,o.y,l.y))},distance:(e,i,n)=>{const[s,o,l]=n.pts,r=l.y-(s.y+.5*(o.y-s.y)),a=t(e,i,s,o),c=t(e,i,{x:s.x,y:s.y+r},{x:o.x,y:o.y+r});return Math.min(a,c)}};function U(t,e,i){return{id:t,name:e,points:i,defaultStyle:{showLabels:!0,levels:[...k],fill:!0,fillOpacity:.06},draw:t=>{const e=t.style.levels??k,n=t.drawing.points,s=2===i?n[0].price:n[2].price,o=n[1].price-n[0].price,l=Math.min(t.pts[0].x,t.pts[i-1].x),r=Math.max(t.pts[0].x,t.pts[i-1].x),a=!0===t.style.extendRight?t.rc.plotWidth*t.rc.dpr:r;g(t);let c=null;for(const i of e){const e=s+o*i,n=Math.round(t.rc.priceScale.priceToY(e)*t.rc.dpr)+.5;!0===t.style.fill&&null!==c&&(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.06,t.ctx.fillStyle=m(t),t.ctx.fillRect(l,Math.min(c,n),a-l,Math.abs(n-c)),t.ctx.restore()),c=n,t.ctx.beginPath(),t.ctx.moveTo(l,n),t.ctx.lineTo(a,n),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,`${(100*i).toFixed(1)}% ${t.formatPrice(e)}`,l+4*t.rc.dpr,n-8*t.rc.dpr)}t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.drawing.style.levels??k,o=n.drawing.points,l=2===i?o[0].price:o[2].price,r=o[1].price-o[0].price,a=Math.min(n.pts[0].x,n.pts[i-1].x),c=!0===n.drawing.style.extendRight?n.rc.plotWidth:Math.max(n.pts[0].x,n.pts[i-1].x);if(t<a-4||t>c+4)return null;let h=1/0;for(const t of s){const i=Math.abs(e-n.rc.priceScale.priceToY(l+r*t));i<h&&(h=i)}return h}}}const B=U("fib-retracement","Fib Retracement",2),H=U("fib-extension","Fib Extension",3),J={id:"measure",name:"Measure",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.14},draw:t=>{const e=o(t.pts[0],t.pts[1]),i=t.rc.dpr,n=t.drawing.points,s=n[1].price-n[0].price,l=0!==n[0].price?s/n[0].price*100:0,r=s>=0,a=r?P:L;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.14,t.ctx.fillStyle=a,t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.restore(),g(t),t.ctx.strokeStyle=a,t.ctx.strokeRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.setLineDash([]);const c=(e.x0+e.x1)/2,h=t.pts[0].y,x=t.pts[1].y;if(t.ctx.strokeStyle=a,t.ctx.beginPath(),t.ctx.moveTo(e.x0,h),t.ctx.lineTo(e.x1,h),t.ctx.stroke(),S(t,{x:e.x0,y:h},{x:e.x1,y:h}),t.ctx.beginPath(),t.ctx.moveTo(c,h),t.ctx.lineTo(c,x),t.ctx.stroke(),S(t,{x:c,y:h},{x:c,y:x}),!1===t.style.showLabels)return;const d=t.rc.dataLayer.timeToIndexFloat(n[0].time),p=t.rc.dataLayer.timeToIndexFloat(n[1].time),y=Math.abs(Math.round(p-d)),u=r?"+":"",f=[`${u}${t.formatPrice(s)} (${u}${l.toFixed(2)}%)`,`${M(y)} bars, ${T(n[1].time-n[0].time)}`],m=t.rc.bars?.();if(void 0!==m&&m.length>0){const t=Math.min(n[0].time,n[1].time),e=Math.max(n[0].time,n[1].time);let i=0,s=!1;for(const n of m)if(!(n.time<t)){if(n.time>e)break;void 0!==n.volume&&(i+=n.volume,s=!0)}s&&f.push(`Vol ${function(t){const e=Math.abs(t);return e>=1e9?`${(t/1e9).toFixed(2)}B`:e>=1e6?`${(t/1e6).toFixed(2)}M`:e>=1e3?`${(t/1e3).toFixed(2)}K`:M(t)}(i)}`)}w(t,f,c,Math.max(h,x)+6*i,a,{align:"center",place:"below"})},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)};function E(t,e,i){return{id:t,name:e,points:1,defaultStyle:{showLabels:!0,fillOpacity:.13,accountSize:1e5,risk:1},expand:(t,e)=>{const n=t[0],s=.01*Math.abs(n.price)||1,o=Math.max(5,Math.round(.08*e.visibleBars)),l=n.time+Math.max(1,e.barSeconds)*o;return i?[n,{time:l,price:n.price+s},{time:l,price:n.price-s}]:[n,{time:l,price:n.price-s},{time:l,price:n.price+s}]},draw:t=>{if(t.drawing.points.length<3||t.pts.length<3)return;const[e,n,s]=t.drawing.points,o=t.rc.dpr,l=Math.min(t.pts[0].x,t.pts[1].x,t.pts[2].x),r=Math.max(t.pts[0].x,t.pts[1].x,t.pts[2].x),a=t.rc.priceScale.priceToY(e.price)*o,c=t.rc.priceScale.priceToY(n.price)*o,h=t.rc.priceScale.priceToY(s.price)*o,x=(e,i,n)=>{t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.13,t.ctx.fillStyle=n,t.ctx.fillRect(l,Math.min(e,i),r-l,Math.abs(i-e)),t.ctx.restore()};x(a,c,P),x(a,h,L),g(t);for(const e of[a,c,h]){const i=Math.round(e)+.5;t.ctx.beginPath(),t.ctx.moveTo(l,i),t.ctx.lineTo(r,i),t.ctx.stroke()}if(t.ctx.setLineDash([]),!1===t.style.showLabels)return;const d=Math.abs(e.price-s.price),p=Math.abs(n.price-e.price),y=d>0?p/d:0,u=t.style.accountSize??0,f=t.style.risk??0,m=d>0&&u>0?Math.floor(u*f/100/d):0,b=t=>(0!==e.price?t/e.price*100:0).toFixed(3),_=t=>m>0?`, Amount: ${M(m*t)}`:"",v=(l+r)/2;w(t,[`Target: ${t.formatPrice(p)} (${b(p)}%)${_(p)}`],v,c,P,{align:"center",place:c<=a?"above":"below"}),w(t,[`Stop: ${t.formatPrice(d)} (${b(d)}%)${_(d)}`],v,h,L,{align:"center",place:h>=a?"below":"above"}),w(t,[`${i?"Long":"Short"} · Qty: ${m>0?M(m):"—"}`,`Risk/reward ratio: ${y.toFixed(2)}`],v,a,t.rc.theme.background,{align:"center",place:"middle"})},distance:(t,e,i)=>{if(i.pts.length<3)return null;const n=Math.min(i.pts[0].x,i.pts[1].x,i.pts[2].x),s=Math.max(i.pts[0].x,i.pts[1].x,i.pts[2].x);if(t<n-4||t>s+4)return null;const o=i.drawing.points.map(t=>i.rc.priceScale.priceToY(t.price)),l=Math.min(...o),r=Math.max(...o);return e>=l&&e<=r?0:Math.min(Math.abs(e-l),Math.abs(e-r))}}}const Y=E("long-position","Long Position",!0),V=E("short-position","Short Position",!1),q=1.35,G="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";function K(t,e){const i="bold"===t.fontWeight?"700 ":"";return`${"italic"===t.fontStyle?"italic ":""}${i}${e}px ${t.fontFamily??G}`}function Q(t,e,i){const n=(e.text??"").split("\n");if(!0!==e.wrap)return n;const s=[];for(const e of n){const n=e.split(/\s+/).filter(t=>""!==t);if(0===n.length){s.push("");continue}let o=n[0];for(let e=1;e<n.length;e++){const l=`${o} ${n[e]}`;t.measureText(l).width>i?(s.push(o),o=n[e]):o=l}s.push(o)}return s}function X(t,e,i){const n=(e.fontSize??13)*i;t.font=K(e,n);const s=Q(t,e,(e.wrapWidth??220)*i);let o=0;for(const e of s)o=Math.max(o,t.measureText(e).width);const l=n*q;return{lines:s,width:o+10*i,height:s.length*l+10*i,lineHeight:l}}function Z(t,e,i,n,s){const{ctx:o,rc:l,style:r}=t,a=r.text;if(void 0===a||""===a)return;const c=l.dpr,h=(r.fontSize??14)*c,x=6*c;o.save(),o.setLineDash([]),o.font=K(r,h),o.fillStyle=r.fontColor??r.color,o.textBaseline="top";const d=!0===r.wrap?Q(o,r,Math.max(20*c,n-e-2*x)):a.split("\n"),p=h*q,y=d.length*p,u=r.textAlign??"left";o.textAlign=u;const f="center"===u?(e+n)/2:"right"===u?n-x:e+x;let g;if("outside"===r.textPosition)g=i-y-x;else{const t=r.textVAlign??"top";g="middle"===t?(i+s-y)/2:"bottom"===t?s-y-x:i+x}for(const t of d)o.fillText(t,f,g),g+=p;o.restore()}const tt={id:"text",name:"Text",points:1,defaultStyle:{text:"Text",fontSize:14,fontWeight:"normal",fontStyle:"normal",background:!1,backgroundOpacity:1,border:!1,wrap:!1,wrapWidth:220,textAlign:"left"},draw:t=>{const{ctx:e,rc:i,style:n}=t,s=i.dpr,o=X(e,n,s),l=t.pts[0].x,r=t.pts[0].y;e.save(),e.setLineDash([]),!0===n.background&&(e.globalAlpha=n.backgroundOpacity??1,e.fillStyle=n.backgroundColor??i.theme.background,e.beginPath(),e.roundRect(l,r,o.width,o.height,4*s),e.fill(),e.globalAlpha=1),!0===n.border&&(e.strokeStyle=n.borderColor??n.color,e.lineWidth=Math.max(1,n.lineWidth*s),e.beginPath(),e.roundRect(l,r,o.width,o.height,4*s),e.stroke()),e.font=K(n,(n.fontSize??13)*s),e.fillStyle=n.color,e.textBaseline="top";const a=n.textAlign??"left";e.textAlign=a;const c="center"===a?l+o.width/2:"right"===a?l+o.width-5*s:l+5*s;let h=r+5*s;for(const t of o.lines)e.fillText(t,c,h),h+=o.lineHeight;e.restore()},distance:(t,e,i)=>{const n=i.drawing.style,s=n.fontSize??13,o=i.pts[0],l=function(){if(void 0!==et)return et;try{et="undefined"==typeof document?null:document.createElement("canvas").getContext("2d")}catch{et=null}return et}(),r=null===l?{width:(n.text??"").length*s*.6+10,height:s*q+10}:X(l,n,1);return t>=o.x-3&&t<=o.x+r.width+3&&e>=o.y-3&&e<=o.y+r.height+3?0:null}};let et;const it={id:"path",name:"Path",points:0,draw:t=>{if(!(t.pts.length<2)){g(t),t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.setLineDash([]),S(t,t.pts[t.pts.length-2],t.pts[t.pts.length-1])}},distance:(t,e,i)=>i.pts.length<2?null:s(t,e,i.pts)},nt={id:"brush",name:"Brush",points:0,freehand:!0,defaultStyle:{lineWidth:2},draw:t=>{if(!(t.pts.length<2)){g(t),t.ctx.lineCap="round",t.ctx.lineJoin="round",t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>i.pts.length<2?null:s(t,e,i.pts)},st={id:"rotated-rectangle",name:"Rotated Rectangle",points:3,defaultStyle:{fill:!0,fillOpacity:.12},draw:t=>{if(t.pts.length<3)return;const e=ot(t.pts[0],t.pts[1],t.pts[2]);t.ctx.beginPath(),t.ctx.moveTo(e[0].x,e[0].y);for(let i=1;i<4;i++)t.ctx.lineTo(e[i].x,e[i].y);t.ctx.closePath(),!0===t.style.fill&&(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.12,t.ctx.fillStyle=m(t),t.ctx.fill(),t.ctx.restore()),g(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(e,i,n)=>{if(n.pts.length<3)return null;const s=ot(n.pts[0],n.pts[1],n.pts[2]);if(!0===n.drawing.style.fill&&function(t,e,i){let n=!1;for(let s=0,o=i.length-1;s<i.length;o=s++){const l=i[s],r=i[o];l.y>e!=r.y>e&&t<(r.x-l.x)*(e-l.y)/(r.y-l.y)+l.x&&(n=!n)}return n}(e,i,s))return 0;let o=1/0;for(let n=0;n<4;n++)o=Math.min(o,t(e,i,s[n],s[(n+1)%4]));return o}};function ot(t,e,i){const n=e.x-t.x,s=e.y-t.y,o=Math.hypot(n,s)||1,l=-s/o,r=n/o,a=(i.x-e.x)*l+(i.y-e.y)*r;return[t,e,{x:e.x+l*a,y:e.y+r*a},{x:t.x+l*a,y:t.y+r*a}]}const lt={id:"double-curve",name:"Double Curve",points:3,draw:t=>{if(t.pts.length<3)return;const[e,i,n]=t.pts;g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.bezierCurveTo(i.x,i.y,e.x+n.x-i.x,e.y+n.y-i.y,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{if(i.pts.length<3)return null;const[n,o,l]=i.pts;return s(t,e,function(t,e,i,n,s){const o=[];for(let l=0;l<=s;l++){const r=l/s,a=1-r,c=a*a*a,h=3*a*a*r,x=3*a*r*r,d=r*r*r;o.push({x:c*t.x+h*e.x+x*i.x+d*n.x,y:c*t.y+h*e.y+x*i.y+d*n.y})}return o}(n,o,{x:n.x+l.x-o.x,y:n.y+l.y-o.y},l,24))}};const rt={id:"cyclic-lines",name:"Cyclic Lines",points:2,defaultStyle:{lineStyle:"dashed"},draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(!Number.isFinite(n)||Math.abs(n)<.5)return;const s=t.rc.plotHeight*t.rc.dpr,o=t.rc.plotWidth*t.rc.dpr;g(t),t.ctx.beginPath();for(let i=0;i<=12;i++){const l=Math.round(e.x+n*i)+.5;l<0||l>o||(t.ctx.moveTo(l,0),t.ctx.lineTo(l,s))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const n=i.pts[1].x-i.pts[0].x;if(!Number.isFinite(n)||Math.abs(n)<.5)return null;const s=Math.round((t-i.pts[0].x)/n);return s<0||s>12?null:Math.abs(t-(i.pts[0].x+n*s))}},at={id:"time-cycles",name:"Time Cycles",points:2,draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(!Number.isFinite(n)||Math.abs(n)<1)return;const s=Math.abs(n)/2;g(t),t.ctx.beginPath();for(let i=0;i<12;i++){const o=e.x+n*i+n/2;o+s<0||o-s>t.rc.plotWidth*t.rc.dpr||(t.ctx.moveTo(o+s,e.y),t.ctx.arc(o,e.y,s,0,Math.PI,!0))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=s.x-n.x;if(!Number.isFinite(o)||Math.abs(o)<1)return null;const l=Math.abs(o)/2;let r=1/0;for(let i=0;i<12;i++){const s=n.x+o*i+o/2;e>n.y+2||(r=Math.min(r,Math.abs(Math.hypot(t-s,e-n.y)-l)))}return Number.isFinite(r)?r:null}},ct={id:"sine-line",name:"Sine Line",points:2,draw:t=>{const e=ht(t.pts[0],t.pts[1]);if(null!==e){g(t),t.ctx.beginPath(),t.ctx.moveTo(e[0].x,e[0].y);for(let i=1;i<e.length;i++)t.ctx.lineTo(e[i].x,e[i].y);t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>{const n=ht(i.pts[0],i.pts[1]);return null===n?null:s(t,e,n)}};function ht(t,e){const i=e.x-t.x,n=e.y-t.y;if(!Number.isFinite(i)||Math.abs(i)<1)return null;const s=[];for(let e=0;e<=64;e++){const o=e/64;s.push({x:t.x+i*o,y:t.y+n*Math.sin(o*Math.PI*2)})}return s}const xt={id:"price-label",name:"Price Label",points:1,defaultStyle:{fontSize:12},draw:t=>{const e=t.pts[0],i=t.rc.dpr,n=void 0!==t.style.text&&""!==t.style.text?t.style.text:t.formatPrice(t.drawing.points[0].price),s=pt(t,[n],e.x+18*i,e.y-30*i);yt(t,s,e,t.style.color),ut(t,s,[n],t.style.color)},distance:(t,e,i)=>{const n=i.pts[0],s=n.x+18,o=n.y-30-11;return t>=s&&t<=s+64&&e>=o&&e<=o+22||Math.hypot(t-n.x,e-n.y)<=10?0:null}},dt={id:"callout",name:"Callout",points:2,defaultStyle:{fontSize:12,text:"Note"},draw:t=>{if(t.pts.length<2)return;const[e,i]=t.pts,n=(t.style.text??"Note").split("\n"),s=pt(t,n,i.x,i.y);yt(t,s,e,t.style.color),ut(t,s,n,t.style.color)},distance:(e,i,n)=>{if(n.pts.length<2)return null;const[s,o]=n.pts;return Math.abs(e-o.x)<=60&&Math.abs(i-o.y)<=16?0:t(e,i,s,o)}};function pt(t,e,i,n){const s=t.rc.dpr,o=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.font=`${o}px ui-sans-serif, system-ui, sans-serif`;let l=0;for(const i of e)l=Math.max(l,t.ctx.measureText(i).width);t.ctx.restore();const r=l+14*s,a=1.4*o*e.length+8*s;return{x:i-r/2,y:n-a/2,w:r,h:a}}function yt(t,e,i,n){const s=t.rc.dpr,o=e.x+e.w/2,l=e.y+e.h/2,r=Math.atan2(i.y-l,i.x-o),a=5*s,c=o+Math.cos(r)*(e.w/2-a),h=l+Math.sin(r)*(e.h/2-a);t.ctx.save(),t.ctx.setLineDash([]),t.ctx.fillStyle=n,t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(c-Math.sin(r)*a,h+Math.cos(r)*a),t.ctx.lineTo(c+Math.sin(r)*a,h-Math.cos(r)*a),t.ctx.closePath(),t.ctx.fill(),t.ctx.beginPath(),x(t.ctx,e.x,e.y,e.w,e.h,5*s),t.ctx.fill(),t.ctx.beginPath(),t.ctx.arc(i.x,i.y,2.5*s,0,2*Math.PI),t.ctx.fill(),t.ctx.restore()}function ut(t,e,i,n){const s=t.rc.dpr,o=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.setLineDash([]),t.ctx.font=`${o}px ui-sans-serif, system-ui, sans-serif`,t.ctx.textAlign="center",t.ctx.textBaseline="middle",t.ctx.fillStyle=t.style.fontColor??h(n);const l=1.4*o,r=e.y+e.h/2-l*(i.length-1)/2;for(let n=0;n<i.length;n++)t.ctx.fillText(i[n],e.x+e.w/2,r+l*n);t.ctx.restore()}const ft={id:"flag-mark",name:"Flag Mark",points:1,defaultStyle:{fill:!0,fillOpacity:.95},draw:t=>{const e=t.pts[0],i=t.rc.dpr,n=22*i,s=15*i,o=11*i;g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(e.x,e.y-n),t.ctx.stroke(),t.ctx.setLineDash([]),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y-n),t.ctx.lineTo(e.x+s,e.y-n+.28*o),t.ctx.lineTo(e.x+.72*s,e.y-n+.5*o),t.ctx.lineTo(e.x+s,e.y-n+.72*o),t.ctx.lineTo(e.x,e.y-n+o),t.ctx.closePath(),t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.95,t.ctx.fillStyle=m(t),t.ctx.fill(),t.ctx.restore()},distance:(t,e,i)=>{const n=i.pts[0];return t>=n.x-4&&t<=n.x+16&&e>=n.y-24&&e<=n.y+2||Math.hypot(t-n.x,e-n.y)<=8?0:null}},gt={id:"price-range",name:"Price Range",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.1},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,n=i[1].price-i[0].price,s=0!==i[0].price?n/i[0].price*100:0,o=n>=0,l=o?"#26a69a":"#ef5350",r=Math.min(t.pts[0].x,t.pts[1].x),a=Math.max(t.pts[0].x,t.pts[1].x)+(t.pts[0].x===t.pts[1].x?60*e:0),c=t.pts[0].y,h=t.pts[1].y;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.1,t.ctx.fillStyle=l,t.ctx.fillRect(r,Math.min(c,h),a-r,Math.abs(h-c)),t.ctx.restore(),g(t),t.ctx.strokeStyle=l,t.ctx.beginPath();for(const e of[c,h])t.ctx.moveTo(r,Math.round(e)+.5),t.ctx.lineTo(a,Math.round(e)+.5);const x=(r+a)/2;t.ctx.moveTo(x,c),t.ctx.lineTo(x,h);const d=h>c?1:-1;t.ctx.moveTo(x-4*e,h-5*e*d),t.ctx.lineTo(x,h),t.ctx.lineTo(x+4*e,h-5*e*d),t.ctx.moveTo(x-4*e,c+5*e*d),t.ctx.lineTo(x,c),t.ctx.lineTo(x+4*e,c+5*e*d),t.ctx.stroke(),t.ctx.setLineDash([]);const p=o?"+":"";_(t,`${p}${t.formatPrice(n)} (${p}${s.toFixed(2)}%)`,x+6*e,(c+h)/2,l)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)},mt={id:"date-range",name:"Date Range",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.1},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,n=t.style.color,s=t.pts[0].x,o=t.pts[1].x,l=Math.min(t.pts[0].y,t.pts[1].y),r=Math.max(t.pts[0].y,t.pts[1].y)+(t.pts[0].y===t.pts[1].y?40*e:0);t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.1,t.ctx.fillStyle=n,t.ctx.fillRect(Math.min(s,o),l,Math.abs(o-s),r-l),t.ctx.restore(),g(t),t.ctx.beginPath();for(const e of[s,o])t.ctx.moveTo(Math.round(e)+.5,l),t.ctx.lineTo(Math.round(e)+.5,r);const a=(l+r)/2;t.ctx.moveTo(s,a),t.ctx.lineTo(o,a);const c=o>s?1:-1;t.ctx.moveTo(o-5*e*c,a-4*e),t.ctx.lineTo(o,a),t.ctx.lineTo(o-5*e*c,a+4*e),t.ctx.moveTo(s+5*e*c,a-4*e),t.ctx.lineTo(s,a),t.ctx.lineTo(s+5*e*c,a+4*e),t.ctx.stroke(),t.ctx.setLineDash([]);const h=t.rc.dataLayer.timeToIndexFloat(i[0].time),x=t.rc.dataLayer.timeToIndexFloat(i[1].time);_(t,`${Math.abs(Math.round(x-h))} bars`,(s+o)/2,l-10*e,n)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)},bt={id:"forecast",name:"Forecast",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.12,lineStyle:"dashed"},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,[n,s]=t.pts,o=i[1].price-i[0].price,l=0!==i[0].price?o/i[0].price*100:0,r=o>=0,a=r?"#26a69a":"#ef5350",c=.35*Math.abs(s.y-n.y)+6*e;if(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.12,t.ctx.fillStyle=a,t.ctx.beginPath(),t.ctx.moveTo(n.x,n.y),t.ctx.lineTo(s.x,s.y-c),t.ctx.lineTo(s.x,s.y+c),t.ctx.closePath(),t.ctx.fill(),t.ctx.restore(),g(t),t.ctx.strokeStyle=a,t.ctx.beginPath(),t.ctx.moveTo(n.x,n.y),t.ctx.lineTo(s.x,s.y),t.ctx.stroke(),t.ctx.setLineDash([]),t.ctx.beginPath(),t.ctx.arc(n.x,n.y,3*e,0,2*Math.PI),t.ctx.fillStyle=a,t.ctx.fill(),!1===t.style.showLabels)return;const h=r?"+":"";w(t,[t.formatPrice(i[0].price),v(i[0].time)],n.x,n.y,a,{align:"center"}),w(t,[`${h}${t.formatPrice(o)} (${h}${l.toFixed(2)}%) in ${T(i[1].time-i[0].time)}`,`${t.formatPrice(i[1].price)} · ${v(i[1].time)}`],s.x,s.y,a,{align:"center",place:"below"});const x=t.rc.bars?.();if(void 0!==x&&x.length>0&&x[x.length-1].time>=i[1].time){let n=!1;for(const t of x)if(!(t.time<i[0].time)){if(t.time>i[1].time)break;if(r?t.high>=i[1].price:t.low<=i[1].price){n=!0;break}}w(t,[n?"SUCCESS":"MISSED"],s.x,s.y+36*e,n?"#4a934a":"#8a4a4a",{align:"center",place:"below"})}},distance:(e,i,n)=>t(e,i,n.pts[0],n.pts[1])},_t={id:"circle",name:"Circle",points:2,defaultStyle:{fill:!0},draw:t=>{const[e,i]=t.pts,n=Math.hypot(i.x-e.x,i.y-e.y);t.ctx.beginPath(),t.ctx.arc(e.x,e.y,n,0,2*Math.PI),b(t,()=>t.ctx.fill()),g(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=Math.hypot(s.x-n.x,s.y-n.y),l=Math.hypot(t-n.x,e-n.y);return!0===i.drawing.style.fill&&l<=o?0:Math.abs(l-o)}},wt={id:"triangle",name:"Triangle",points:3,defaultStyle:{fill:!0},draw:t=>{t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y),t.ctx.lineTo(t.pts[1].x,t.pts[1].y),t.ctx.lineTo(t.pts[2].x,t.pts[2].y),t.ctx.closePath(),b(t,()=>t.ctx.fill()),g(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>s(t,e,[...i.pts,i.pts[0]])},Mt={id:"polyline",name:"Polyline",points:0,defaultStyle:{fill:!1},draw:t=>{if(!(t.pts.length<2)){t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);!0===t.style.fill&&(t.ctx.closePath(),b(t,()=>t.ctx.fill())),g(t),t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>s(t,e,i.pts)};const vt={id:"arc",name:"Arc",points:3,draw:t=>{const[e,i,n]=t.pts;g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.quadraticCurveTo(2*i.x-(e.x+n.x)/2,2*i.y-(e.y+n.y)/2,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>s(t,e,function(t,e,i){const n=2*e.x-(t.x+i.x)/2,s=2*e.y-(t.y+i.y)/2,o=[];for(let e=0;e<=16;e++){const l=e/16,r=1-l;o.push({x:r*r*t.x+2*r*l*n+l*l*i.x,y:r*r*t.y+2*r*l*s+l*l*i.y})}return o}(i.pts[0],i.pts[1],i.pts[2]))},Tt={id:"curve",name:"Curve",points:3,draw:t=>{const[e,i,n]=t.pts;g(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.quadraticCurveTo(i.x,i.y,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,o,l]=i.pts,r=[];for(let t=0;t<=16;t++){const e=t/16,i=1-e;r.push({x:i*i*n.x+2*i*e*o.x+e*e*l.x,y:i*i*n.y+2*i*e*o.y+e*e*l.y})}return s(t,e,r)}};function St(t,e,i){return{id:t,name:e,points:1,defaultStyle:{fill:!0,fillOpacity:.9},draw:t=>{const e=t.rc.dpr,{x:n,y:s}=t.pts[0],o=16*e,l=6*e,r=i?1:-1,a=s+2*r*e;t.ctx.beginPath(),t.ctx.moveTo(n,a),t.ctx.lineTo(n-l,a+r*l),t.ctx.lineTo(n-l/2.4,a+r*l),t.ctx.lineTo(n-l/2.4,a+r*o),t.ctx.lineTo(n+l/2.4,a+r*o),t.ctx.lineTo(n+l/2.4,a+r*l),t.ctx.lineTo(n+l,a+r*l),t.ctx.closePath(),t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.9,t.ctx.fillStyle=m(t),t.ctx.fill(),t.ctx.restore(),g(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.pts[0],o=i?e-s.y:s.y-e;return Math.abs(t-s.x)<=8&&o>=-4&&o<=20?0:null}}}const Pt=St("arrow-up","Arrow Up",!0),Lt=St("arrow-down","Arrow Down",!1),kt={id:"highlighter",name:"Highlighter",points:0,freehand:!0,defaultStyle:{lineWidth:12,fillOpacity:.28},draw:t=>{if(t.pts.length<2)return;const e=t.rc.dpr;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.28,t.ctx.strokeStyle=t.style.color,t.ctx.lineWidth=Math.max(2,(t.style.lineWidth||12)*e),t.ctx.lineCap="round",t.ctx.lineJoin="round",t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.restore()},distance:(t,e,i)=>{const n=s(t,e,i.pts);return n<=Math.max(6,(i.drawing.style.lineWidth??12)/2)?0:n}},Dt={id:"fib-channel",name:"Fib Channel",points:3,defaultStyle:{showLabels:!0,levels:[...k]},draw:t=>{const e=t.style.levels??k,[i,n,s]=t.pts,o=s.x-n.x,l=s.y-n.y;g(t);for(const s of e)t.ctx.beginPath(),t.ctx.moveTo(i.x+o*s,i.y+l*s),t.ctx.lineTo(n.x+o*s,n.y+l*s),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,`${(100*s).toFixed(1)}%`,n.x+o*s+4*t.rc.dpr,n.y+l*s);t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??k,[o,l,r]=n.pts;let a=1/0;for(const n of s){const s=t(e,i,{x:o.x+(r.x-l.x)*n,y:o.y+(r.y-l.y)*n},{x:l.x+(r.x-l.x)*n,y:l.y+(r.y-l.y)*n});s<a&&(a=s)}return a}},$t=[0,1,2,3,5,8,13,21,34,55],Ot={id:"fib-time-zone",name:"Fib Time Zone",points:2,defaultStyle:{showLabels:!0},draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(Math.abs(n)<.5)return;const s=t.rc.dpr,o=t.rc.plotWidth*s;g(t);for(const i of $t){const l=e.x+n*i;l<-10||l>o+10||(t.ctx.beginPath(),t.ctx.moveTo(Math.round(l)+.5,0),t.ctx.lineTo(Math.round(l)+.5,t.rc.plotHeight*s),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,String(i),l+3*s,12*s))}t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=s.x-n.x;if(Math.abs(o)<.5)return null;let l=1/0;for(const e of $t)l=Math.min(l,Math.abs(t-(n.x+o*e)));return l}},Ft=[.236,.382,.5,.618,.786,1],At={id:"fib-fan",name:"Fib Speed Fan",points:2,defaultStyle:{showLabels:!0,levels:[...Ft]},draw:t=>{const e=t.style.levels??Ft,[i,n]=t.pts,s=t.rc.dpr,o=t.rc.plotWidth*s;g(t);for(const l of e){const e=a(i,{x:n.x,y:i.y+(n.y-i.y)*l},o,!1,!0)[1];t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(e.x,e.y),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,`${(100*l).toFixed(1)}%`,n.x+4*s,i.y+(n.y-i.y)*l)}t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??Ft,[o,l]=n.pts;let r=1/0;for(const c of s)r=Math.min(r,t(e,i,o,a(o,{x:l.x,y:o.y+(l.y-o.y)*c},n.rc.plotWidth,!1,!0)[1]));return r}},Nt=[[1,.125],[1,.25],[1,.5],[1,1],[.5,1],[.25,1],[.125,1]],Wt=[$,O,F,A,N,W,C,I,R,z,j,B,H,Y,V,bt,J,gt,mt,_t,wt,Mt,vt,Tt,st,lt,Pt,Lt,kt,nt,Dt,Ot,At,{id:"gann-fan",name:"Gann Fan",points:2,defaultStyle:{showLabels:!0},draw:t=>{const[e,i]=t.pts,n=t.rc.dpr,s=t.rc.plotWidth*n,o=i.x-e.x,l=i.y-e.y;if(!(Math.abs(o)<.5)){g(t);for(const[i,n]of Nt){const r=a(e,{x:e.x+o*i,y:e.y+l*n},s,!1,!0)[1];t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(r.x,r.y),t.ctx.stroke()}!1!==t.style.showLabels&&_(t,"1x1",i.x+4*n,i.y),t.ctx.setLineDash([])}},distance:(e,i,n)=>{const[s,o]=n.pts,l=o.x-s.x,r=o.y-s.y;let c=1/0;for(const[o,h]of Nt)c=Math.min(c,t(e,i,s,a(s,{x:s.x+l*o,y:s.y+r*h},n.rc.plotWidth,!1,!0)[1]));return c}},{id:"gann-box",name:"Gann Box",points:2,defaultStyle:{fill:!0,fillOpacity:.05},draw:t=>{const e=o(t.pts[0],t.pts[1]);b(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),g(t);const i=e.x1-e.x0,n=e.y1-e.y0;t.ctx.beginPath();for(let s=0;s<=8;s++){const o=Math.round(e.x0+i*s/8)+.5,l=Math.round(e.y0+n*s/8)+.5;t.ctx.moveTo(o,e.y0),t.ctx.lineTo(o,e.y1),t.ctx.moveTo(e.x0,l),t.ctx.lineTo(e.x1,l)}t.ctx.moveTo(e.x0,e.y1),t.ctx.lineTo(e.x1,e.y0),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},rt,at,ct,tt,it,xt,dt,ft];let Ct=!1;function It(){if(!Ct){Ct=!0;for(const t of Wt)p(t)}}function Rt(t,e){return u(t)&&!0===y(t).freehand&&e>2?[0,e-1]:Array.from({length:e},(t,e)=>e)}class zt{constructor(){Object.defineProperty(this,"_drawings",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_selected",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_preview",{enumerable:!0,configurable:!0,writable:!0,value:null})}attached(t){this._host=t}detached(){this._host=null}zOrder(){return"top"}autoscaleInfo(){return null}setDrawings(t){this._drawings=t.slice(),this._host?.requestUpdate()}setSelected(t){t!==this._selected&&(this._selected=t,this._host?.requestUpdate())}setPreview(t){this._preview=t,this._host?.requestUpdate()}_project(t,e,i){return{x:t.timeScale.indexToX(t.dataLayer.timeToIndexFloat(e)),y:t.priceScale.priceToY(i)}}_points(t,e){return e.points.map(e=>this._project(t,e.time,e.price))}draw(t,e){const i=null===this._preview?this._drawings:[...this._drawings,this._preview];for(const n of i){if(!1===n.visible||!u(n.tool))continue;const i=y(n.tool);if(n.points.length<Math.max(1,i.points))continue;const s=this._points(e,n);if(!s.some(t=>Number.isFinite(t.x)&&Number.isFinite(t.y)))continue;const o={color:n.style.color??e.theme.lineColor,lineWidth:n.style.lineWidth??1.5,...n.style},l=e.dpr;t.save(),n===this._preview&&(t.globalAlpha=.7),i.draw({ctx:t,rc:e,drawing:n,selected:n.id===this._selected,pts:s.map(t=>({x:t.x*l,y:t.y*l})),style:{...o,color:o.color,lineWidth:o.lineWidth},formatPrice:t=>e.priceScale.format(t)}),t.restore(),n.id===this._selected&&!0!==n.locked&&this._drawHandles(t,e,s,n.tool)}}_drawHandles(t,e,i,n){const s=e.dpr;t.save(),t.setLineDash([]),t.lineWidth=Math.max(1,Math.round(1.5*s));for(const o of Rt(n,i.length)){const n=i[o];t.beginPath(),t.arc(n.x*s,n.y*s,5*s,0,2*Math.PI),t.fillStyle=e.theme.background,t.fill(),t.strokeStyle=e.theme.lineColor,t.stroke()}t.restore()}hitTest(t,e,i){if(null!==this._selected){const n=this._drawings.find(t=>t.id===this._selected);if(void 0!==n&&!0!==n.locked){const s=this._points(i,n);for(const i of Rt(n.tool,s.length))if(Math.hypot(t-s[i].x,e-s[i].y)<=7)return{externalId:`draw:${n.id}#${i}`,zOrder:"top",distance:0,cursor:"grabbing",draggable:!0}}}let n=null;for(let s=this._drawings.length-1;s>=0;s--){const o=this._drawings[s];if(!1===o.visible||!0===o.locked||!u(o.tool))continue;const l=y(o.tool);if(o.points.length<Math.max(1,l.points))continue;const r=l.distance(t,e,{pts:this._points(i,o),drawing:o,rc:i});null===r||!Number.isFinite(r)||r>6||(null===n||r<n.distance)&&(n={id:o.id,distance:r})}return null===n?null:{externalId:`draw:${n.id}`,zOrder:"top",distance:n.distance,cursor:"move",draggable:!0}}}let jt=1;class Ut{constructor(t,e={}){Object.defineProperty(this,"_chart",{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,"_layers",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"_drawings",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_tool",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_pending",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_pendingPane",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_selected",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_undo",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_redo",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_dragStart",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_off",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_lastCursor",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_lastBar",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._chart=t,this._opts={magnet:e.magnet??!1,stayInDrawingMode:e.stayInDrawingMode??!1,historyLimit:e.historyLimit??50,defaultStyle:e.defaultStyle??{}},this._off.push(t.on("click",t=>this._onClick(t))),this._off.push(t.on("crosshair:move",t=>this._onCrosshair(t))),this._off.push(t.on("drag",t=>this._onDrag(t))),this._off.push(t.on("drag:end",()=>this._onDragEnd())),this._off.push(t.on("dblclick",()=>{this.finish()}));const i=t.drawingState();Array.isArray(i)&&(this._drawings=i.map(t=>({...t}))),this._sync()}setTool(t){if(null!==t&&!u(t))throw new Error(`openalgo-charts: unknown drawing tool "${t}"`);this._tool=t,this._pending=[],this._setPlacementMode(null!==t),this._syncPreview(),this._chart.emit("draw:tool",{tool:t})}_setPlacementMode(t){const e=this._chart;e.setPlacementMode?.(t)}activeTool(){return this._tool}setOptions(t){this._opts={...this._opts,...t,defaultStyle:t.defaultStyle??this._opts.defaultStyle}}drawings(){return this._drawings}get(t){return this._drawings.find(e=>e.id===t)}add(t){this._pushUndo();const e=y(t.tool),i={...t,id:t.id??"d"+jt++,style:{...this._opts.defaultStyle,...e.defaultStyle,...t.style}};return this._drawings.push(i),this._sync(),this._chart.emit("draw:add",{drawing:i}),i}update(t,e){const i=this.get(t);return void 0!==i&&(this._pushUndo(),void 0!==e.points&&(i.points=e.points.map(t=>({...t}))),void 0!==e.style&&(i.style={...i.style,...e.style}),void 0!==e.locked&&(i.locked=e.locked),void 0!==e.visible&&(i.visible=e.visible),this._sync(),this._chart.emit("draw:update",{drawing:i}),!0)}remove(t){const e=this._drawings.findIndex(e=>e.id===t);if(e<0)return!1;this._pushUndo();const[i]=this._drawings.splice(e,1);return this._selected===t&&(this._selected=null),this._sync(),this._chart.emit("draw:remove",{drawing:i}),!0}clear(){0!==this._drawings.length&&(this._pushUndo(),this._drawings=[],this._selected=null,this._sync())}select(t){this._selected=t;for(const e of this._layers.values())e.setSelected(t);this._chart.emit("draw:select",{id:t})}selected(){return this._selected}undo(){const t=this._undo.pop();return void 0!==t&&(this._redo.push(JSON.stringify(this._drawings)),this._drawings=JSON.parse(t),this._drawings.some(t=>t.id===this._selected)||(this._selected=null),this._sync(),!0)}redo(){const t=this._redo.pop();return void 0!==t&&(this._undo.push(JSON.stringify(this._drawings)),this._drawings=JSON.parse(t),this._sync(),!0)}canUndo(){return this._undo.length>0}canRedo(){return this._redo.length>0}toJSON(){return this._drawings.map(t=>({...t,points:t.points.map(t=>({...t})),style:{...t.style}}))}fromJSON(t){this._drawings=Array.isArray(t)?t.map(t=>({...t})):[],this._selected=null,this._undo=[],this._redo=[],this._sync()}destroy(){this._setPlacementMode(!1);for(const t of this._off)t();this._off.length=0;for(const[t,e]of this._layers)this._chart.removePrimitive(e);this._layers.clear()}_onCrosshair(t){const e=t.time,i=t.price,n=t.paneIndex??null;this._lastCursor=null===e||null===i||null===n?null:{time:e,price:i,paneIndex:n},this._lastBar=t.bar??null,null!==this._tool&&!0===t.pressed&&this._isFreehand()&&null!==e&&null!==i&&null!==n&&Number.isFinite(e)&&Number.isFinite(i)?this._inkPoint({time:e,price:i},n):null!==this._tool&&this._pending.length>0&&this._syncPreview()}_expand(t,e){if(void 0===t.expand)return e;const i=this._chart.dataLayer,n=i.baseIndex,s=n>0?i.indexToTime(n-1):void 0,o=n>=0?i.indexToTime(n):void 0,l=void 0!==s&&void 0!==o&&o>s?o-s:60,r=this._chart.getVisibleLogicalRange(),a=null===r?60:Math.max(1,r.to-r.from);return t.expand(e,{barSeconds:l,visibleBars:a})}_isFreehand(){return null!==this._tool&&!0===y(this._tool).freehand}_inkPoint(t,e){if(0===this._pending.length)this._pendingPane=e;else{if(e!==this._pendingPane)return;{const e=this._pending[this._pending.length-1];if(e.time===t.time&&e.price===t.price)return}}this._pending.push(t),this._syncPreview()}_commit(t){const e=y(this._tool),i=this.add({tool:e.id,points:t,style:{},paneIndex:this._pendingPane});this._pending=[],this._opts.stayInDrawingMode||(this._tool=null,this._setPlacementMode(!1)),this._syncPreview(),this.select(i.id),this._chart.emit("draw:tool",{tool:this._tool})}_finishFreehand(){const t=this._pending;this._pending=[],t.length<2?this._syncPreview():this._commit(t)}finish(){if(null===this._tool||0===this._pending.length)return!1;const t=y(this._tool);if(0!==t.points||!0===t.freehand)return!1;const e=this._pending;return e.length<2?(this._pending=[],this._syncPreview(),!1):(this._commit(e),!0)}_onClick(t){if(null===this._tool)null!==t.id&&t.id.startsWith("draw:")?this.select(t.id.slice(5).split("#")[0]):null===t.id&&this.select(null);else{if(this._isFreehand())return void(!0===t.viaDrag&&this._finishFreehand());if(!0===t.viaDrag&&0===this._pending.length)return;if(null===t.price||!Number.isFinite(t.price)||!Number.isFinite(t.time))return;this._placePoint({time:t.time,price:this._snap(t.price,t.paneIndex)},t.paneIndex)}}_placePoint(t,e){0===this._pending.length&&(this._pendingPane=e),this._pending.push(t);const i=y(this._tool);i.points>0&&this._pending.length>=i.points?this._commit(this._expand(i,this._pending)):this._syncPreview()}_snap(t,e){if(!this._opts.magnet||0!==e)return t;const i=this._lastBar;if(null===i)return t;let n=t,s=1/0;for(const e of[i.open,i.high,i.low,i.close]){const i=Math.abs(e-t);i<s&&(s=i,n=e)}return n}_onDrag(t){if(!t.id.startsWith("draw:"))return;const[e,i]=t.id.slice(5).split("#"),n=this.get(e);if(void 0===n||!0===n.locked)return;const s=void 0===i?null:Number(i);null!==this._dragStart&&this._dragStart.id===e&&this._dragStart.handle===s||(this._pushUndo(),this._dragStart={id:e,handle:s,points:n.points.map(t=>({...t})),from:{time:t.fromTime??t.time,price:t.fromPrice??t.price}});const o=this._dragStart;if(null===s){const e=t.time-o.from.time,i=t.price-o.from.price;n.points=o.points.map(t=>({time:t.time+e,price:t.price+i}))}else s>=0&&s<n.points.length&&(n.points=o.points.map((e,i)=>i===s?{time:t.time,price:t.price}:{...e}));this._sync()}_onDragEnd(){if(null===this._dragStart)return;const t=this.get(this._dragStart.id);this._dragStart=null,void 0!==t&&this._chart.emit("draw:update",{drawing:t})}_layerFor(t){let e=this._layers.get(t);return void 0===e&&(e=new zt,this._chart.addPrimitive(e,t),this._layers.set(t,e)),e}_sync(){const t=new Map;for(const e of this._drawings){const i=t.get(e.paneIndex)??[];i.push(e),t.set(e.paneIndex,i)}for(const[e,i]of t)this._layerFor(e).setDrawings(i);for(const[e,i]of this._layers)t.has(e)||i.setDrawings([]),i.setSelected(this._selected);this._chart.setDrawingState(this.toJSON())}_syncPreview(){for(const t of this._layers.values())t.setPreview(null);if(null===this._tool||0===this._pending.length)return;const t=this._lastCursor,e=null===t?this._pending:[...this._pending,{time:t.time,price:t.price}];this._layerFor(this._pendingPane).setPreview({id:"__preview",tool:this._tool,points:e,style:this._opts.defaultStyle,paneIndex:this._pendingPane})}_pushUndo(){this._undo.push(JSON.stringify(this._drawings)),this._undo.length>this._opts.historyLimit&&this._undo.shift(),this._redo=[]}}const Bt="draw";It();export{A as ARROW,Wt as BUILTIN_DRAWING_TOOLS,I as CROSS_LINE,Bt as DRAW_TIER,Ut as DrawingController,zt as DrawingLayer,z as ELLIPSE,F as EXTENDED_LINE,H as FIB_EXTENSION,B as FIB_RETRACEMENT,N as HORIZONTAL_LINE,W as HORIZONTAL_RAY,Y as LONG_POSITION,J as MEASURE,j as PARALLEL_CHANNEL,it as PATH,O as RAY,R as RECTANGLE,V as SHORT_POSITION,tt as TEXT,$ as TREND_LINE,C as VERTICAL_LINE,r as distToEllipse,e as distToLine,s as distToPolyline,l as distToRect,t as distToSegment,a as extendSegment,y as getDrawingTool,u as hasDrawingTool,o as rectOf,It as registerBuiltinDrawingTools,p as registerDrawingTool,f as registeredDrawingTools};
1
+ function t(t,e,i,n){const s=n.x-i.x,o=n.y-i.y,l=s*s+o*o;if(0===l)return Math.hypot(t-i.x,e-i.y);let r=((t-i.x)*s+(e-i.y)*o)/l;return r=r<0?0:r>1?1:r,Math.hypot(t-(i.x+r*s),e-(i.y+r*o))}function e(t,e,i,n){const s=n.x-i.x,o=n.y-i.y,l=Math.hypot(s,o);return 0===l?Math.hypot(t-i.x,e-i.y):Math.abs(o*(t-i.x)-s*(e-i.y))/l}function i(t,e){return Math.abs(t-e)}function n(t,e){return Math.abs(t-e)}function s(e,i,n){let s=1/0;for(let o=1;o<n.length;o++){const l=t(e,i,n[o-1],n[o]);l<s&&(s=l)}return s}function o(t,e){return{x0:Math.min(t.x,e.x),y0:Math.min(t.y,e.y),x1:Math.max(t.x,e.x),y1:Math.max(t.y,e.y)}}function l(e,i,n,s,l){const r=o(n,s);if(e>=r.x0&&e<=r.x1&&i>=r.y0&&i<=r.y1&&l)return 0;const c=[{x:r.x0,y:r.y0},{x:r.x1,y:r.y0},{x:r.x1,y:r.y1},{x:r.x0,y:r.y1}];let a=1/0;for(let n=0;n<4;n++){const s=t(e,i,c[n],c[(n+1)%4]);s<a&&(a=s)}return a}function r(t,e,i,n,s){const l=o(i,n),r=(l.x0+l.x1)/2,c=(l.y0+l.y1)/2,a=Math.max(1e-6,(l.x1-l.x0)/2),h=Math.max(1e-6,(l.y1-l.y0)/2),x=(t-r)/a,d=(e-c)/h,p=Math.hypot(x,d);return s&&p<=1?0:Math.abs(p-1)*Math.min(a,h)}function c(t,e,i,n,s){const o=e.x-t.x;if(0===o)return[t,e];const l=(e.y-t.y)/o;return[n?{x:0,y:t.y+(0-t.x)*l}:t,s?{x:i,y:t.y+(i-t.x)*l}:e]}function a(t){const e=function(t){const e=t.trim();if(e.startsWith("#")){const t=e.slice(1);if(3===t.length||4===t.length){const[e,i,n,s]=[...t].map(t=>parseInt(t+t,16));return[e,i,n].some(Number.isNaN)?null:{r:e,g:i,b:n,a:4===t.length?s/255:1}}if(6===t.length||8===t.length){const e=parseInt(t.slice(0,6),16);if(Number.isNaN(e))return null;const i=8===t.length?parseInt(t.slice(6,8),16)/255:1;return{r:e>>16&255,g:e>>8&255,b:255&e,a:Number.isNaN(i)?1:i}}return null}const i=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i.exec(e);return null===i?null:{r:Number(i[1]),g:Number(i[2]),b:Number(i[3]),a:void 0===i[4]?1:Number(i[4])}}(t);if(null===e)return.5;const i=t=>{const e=t/255;return e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4)};return.2126*i(e.r)+.7152*i(e.g)+.0722*i(e.b)}function h(t){return a(t)>.45?"#10131a":"#ffffff"}function x(t,e,i,n,s,o){const l=t.roundRect;"function"==typeof l?l.call(t,e,i,n,s,Math.max(0,Math.min(o,n/2,s/2))):t.rect(e,i,n,s)}const d=new Map;function p(t){d.set(t.id,t)}function y(t){const e=d.get(t);if(void 0===e)throw new Error(`openalgo-charts: unknown drawing tool "${t}"`);return e}function u(t){return d.has(t)}function f(){return Array.from(d.values())}function g(t){const e=t.split("+").map(t=>t.trim().toLowerCase());return{key:e[e.length-1]??"",alt:e.includes("alt"),ctrl:e.includes("ctrl")||e.includes("control"),shift:e.includes("shift")}}function m(t){const e=(t.key??"").toLowerCase();if(""===e)return null;const i=!0===t.altKey,n=!0===t.ctrlKey||!0===t.metaKey,s=!0===t.shiftKey;if(!i&&!n)return null;for(const t of d.values()){if(void 0===t.shortcut)continue;const o=g(t.shortcut);if(o.key===e&&o.alt===i&&o.ctrl===n&&o.shift===s)return t.id}return null}function b(){const t={};for(const e of d.values())void 0!==e.shortcut&&(t[e.id]=e.shortcut);return t}function _(t){const{ctx:e,rc:i,style:n}=t,s=i.dpr;e.strokeStyle=n.color,e.lineWidth=Math.max(1,Math.round(n.lineWidth*s)),e.lineJoin="round",e.lineCap="round",e.setLineDash("dashed"===n.lineStyle?[6*s,4*s]:"dotted"===n.lineStyle?[1*s,3*s]:[])}function w(t){return t.style.fillColor??t.style.color}function v(t,e){if(!0!==t.style.fill)return;const{ctx:i}=t;i.save(),i.globalAlpha=t.style.fillOpacity??.12,i.fillStyle=w(t),e(),i.restore()}function M(t,e,i,n,s){const{ctx:o,rc:l,style:r}=t,c=(r.fontSize??11)*l.dpr;o.save(),o.setLineDash([]),o.font=`${c}px ui-sans-serif, system-ui, sans-serif`,o.textBaseline="middle",o.textAlign="left";const a=o.measureText(e).width;o.globalAlpha=.85,o.fillStyle=l.theme.background,o.fillRect(i-2*l.dpr,n-.75*c,a+4*l.dpr,1.5*c),o.globalAlpha=1,o.fillStyle=s??r.color,o.fillText(e,i,n),o.restore()}function T(t,e,i,n,s,o={}){const{ctx:l,rc:r}=t,c=r.dpr,a=(t.style.fontSize??11)*c;l.save(),l.setLineDash([]),l.globalAlpha=1,l.font=`${a}px ui-sans-serif, system-ui, sans-serif`,l.textBaseline="middle",l.textAlign="left";const d=5*c,p=3*c,y=1.35*a;let u=0;for(const t of e)u=Math.max(u,l.measureText(t).width);const f=u+2*d,g=y*e.length+2*p,m=o.align??"left",b="center"===m?i-f/2:"right"===m?i-f:i,_=o.place??"above",w="above"===_?n-g-4*c:"below"===_?n+4*c:n-g/2;l.beginPath(),x(l,b,w,f,g,3*c),l.fillStyle=s,l.fill(),l.fillStyle=h(s);for(let t=0;t<e.length;t++)l.fillText(e[t],b+d,w+p+y*(t+.5));return l.restore(),g}function S(t,e=0){const[i,n]=Math.abs(t).toFixed(e).split(".");return(t<0?"-":"")+i.replace(/\B(?=(\d{3})+(?!\d))/g,",")+(void 0===n?"":"."+n)}function P(t){const e=new Date(1e3*t),i=t=>String(t).padStart(2,"0");return`${e.getUTCFullYear()}-${i(e.getUTCMonth()+1)}-${i(e.getUTCDate())}`}function L(t){const e=Math.max(0,Math.round(Math.abs(t))),i=Math.floor(e/86400),n=Math.floor(e%86400/3600),s=Math.floor(e%3600/60);return i>0?`${i}d ${n}h`:n>0?`${n}h ${s}m`:`${s}m`}function k(t,e,i){const n=Math.max(8,5*t.style.lineWidth)*t.rc.dpr,s=Math.atan2(i.y-e.y,i.x-e.x);t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x-n*Math.cos(s-.4),i.y-n*Math.sin(s-.4)),t.ctx.lineTo(i.x-n*Math.cos(s+.4),i.y-n*Math.sin(s+.4)),t.ctx.closePath(),t.ctx.fillStyle=t.style.color,t.ctx.fill()}const D="#26a69a",$="#ef5350",O=[0,.236,.382,.5,.618,.786,1];function F(i,n,s,o){return{id:i,name:n,points:2,defaultStyle:{extendLeft:s,extendRight:o},draw:t=>{const[e,i]=c(t.pts[0],t.pts[1],t.rc.plotWidth*t.rc.dpr,t.style.extendLeft??s,t.style.extendRight??o);_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(i,n,l)=>{const r=l.drawing.style.extendLeft??s,a=l.drawing.style.extendRight??o;if(r&&a)return e(i,n,l.pts[0],l.pts[1]);const[h,x]=c(l.pts[0],l.pts[1],l.rc.plotWidth,r,a);return t(i,n,h,x)}}}const A={...F("trend-line","Trend Line",!1,!1),shortcut:"Alt+T"},C=F("ray","Ray",!1,!0),N=F("extended-line","Extended Line",!0,!0),W={id:"arrow",name:"Arrow",points:2,draw:t=>{const[e,i]=t.pts;_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.stroke();const n=Math.max(8,5*t.style.lineWidth)*t.rc.dpr,s=Math.atan2(i.y-e.y,i.x-e.x);t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x-n*Math.cos(s-.4),i.y-n*Math.sin(s-.4)),t.ctx.lineTo(i.x-n*Math.cos(s+.4),i.y-n*Math.sin(s+.4)),t.ctx.closePath(),t.ctx.fillStyle=t.style.color,t.ctx.fill(),t.ctx.setLineDash([])},distance:(e,i,n)=>t(e,i,n.pts[0],n.pts[1])},I={id:"horizontal-line",name:"Horizontal Line",points:1,shortcut:"Alt+H",defaultStyle:{showLabels:!0},draw:t=>{const e=Math.round(t.pts[0].y)+.5;_(t),t.ctx.beginPath(),t.ctx.moveTo(0,e),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,e),t.ctx.stroke(),t.ctx.setLineDash([]),!1!==t.style.showLabels&&M(t,t.formatPrice(t.drawing.points[0].price),4*t.rc.dpr,e-8*t.rc.dpr)},distance:(t,e,n)=>i(e,n.pts[0].y)},R={id:"horizontal-ray",name:"Horizontal Ray",points:1,shortcut:"Alt+J",defaultStyle:{showLabels:!0},draw:t=>{const e=Math.round(t.pts[0].y)+.5;_(t),t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,e),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,e),t.ctx.stroke(),t.ctx.setLineDash([]),!1!==t.style.showLabels&&M(t,t.formatPrice(t.drawing.points[0].price),t.pts[0].x+4*t.rc.dpr,e-8*t.rc.dpr)},distance:(t,e,n)=>t<n.pts[0].x?null:i(e,n.pts[0].y)},z={id:"vertical-line",name:"Vertical Line",points:1,shortcut:"Alt+V",draw:t=>{const e=Math.round(t.pts[0].x)+.5;_(t),t.ctx.beginPath(),t.ctx.moveTo(e,0),t.ctx.lineTo(e,t.rc.plotHeight*t.rc.dpr),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>n(t,i.pts[0].x)},j={id:"cross-line",name:"Cross Line",points:1,shortcut:"Alt+C",draw:t=>{const e=Math.round(t.pts[0].x)+.5,i=Math.round(t.pts[0].y)+.5;_(t),t.ctx.beginPath(),t.ctx.moveTo(e,0),t.ctx.lineTo(e,t.rc.plotHeight*t.rc.dpr),t.ctx.moveTo(0,i),t.ctx.lineTo(t.rc.plotWidth*t.rc.dpr,i),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,s)=>Math.min(n(t,s.pts[0].x),i(e,s.pts[0].y))},U={id:"rectangle",name:"Rectangle",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"left",textVAlign:"top",textPosition:"inside"},draw:t=>{const e=o(t.pts[0],t.pts[1]);v(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),_(t),t.ctx.strokeRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.setLineDash([]),it(t,e.x0,e.y0,e.x1,e.y1)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},B={id:"ellipse",name:"Ellipse",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"center",textVAlign:"middle",textPosition:"inside"},draw:t=>{const e=o(t.pts[0],t.pts[1]),i=(e.x0+e.x1)/2,n=(e.y0+e.y1)/2,s=Math.max(1,(e.x1-e.x0)/2),l=Math.max(1,(e.y1-e.y0)/2),r=()=>{t.ctx.beginPath(),t.ctx.ellipse(i,n,s,l,0,0,2*Math.PI)};v(t,()=>{r(),t.ctx.fill()}),_(t),r(),t.ctx.stroke(),t.ctx.setLineDash([]),it(t,e.x0,e.y0,e.x1,e.y1)},distance:(t,e,i)=>r(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},H={id:"parallel-channel",name:"Parallel Channel",points:3,defaultStyle:{fill:!0},draw:t=>{const[e,i,n]=t.pts,s=n.y-(e.y+.5*(i.y-e.y)),o={x:e.x,y:e.y+s},l={x:i.x,y:i.y+s};v(t,()=>{t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.lineTo(l.x,l.y),t.ctx.lineTo(o.x,o.y),t.ctx.closePath(),t.ctx.fill()}),_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.moveTo(o.x,o.y),t.ctx.lineTo(l.x,l.y),t.ctx.stroke(),t.ctx.setLineDash([]),it(t,Math.min(e.x,i.x),Math.min(e.y,i.y,o.y,l.y),Math.max(e.x,i.x),Math.max(e.y,i.y,o.y,l.y))},distance:(e,i,n)=>{const[s,o,l]=n.pts,r=l.y-(s.y+.5*(o.y-s.y)),c=t(e,i,s,o),a=t(e,i,{x:s.x,y:s.y+r},{x:o.x,y:o.y+r});return Math.min(c,a)}};function J(t,e,i){return{id:t,name:e,points:i,defaultStyle:{showLabels:!0,levels:[...O],fill:!0,fillOpacity:.06},draw:t=>{const e=t.style.levels??O,n=t.drawing.points,s=2===i?n[0].price:n[2].price,o=n[1].price-n[0].price,l=Math.min(t.pts[0].x,t.pts[i-1].x),r=Math.max(t.pts[0].x,t.pts[i-1].x),c=!0===t.style.extendRight?t.rc.plotWidth*t.rc.dpr:r;_(t);let a=null;for(const i of e){const e=s+o*i,n=Math.round(t.rc.priceScale.priceToY(e)*t.rc.dpr)+.5;!0===t.style.fill&&null!==a&&(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.06,t.ctx.fillStyle=w(t),t.ctx.fillRect(l,Math.min(a,n),c-l,Math.abs(n-a)),t.ctx.restore()),a=n,t.ctx.beginPath(),t.ctx.moveTo(l,n),t.ctx.lineTo(c,n),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,`${(100*i).toFixed(1)}% ${t.formatPrice(e)}`,l+4*t.rc.dpr,n-8*t.rc.dpr)}t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.drawing.style.levels??O,o=n.drawing.points,l=2===i?o[0].price:o[2].price,r=o[1].price-o[0].price,c=Math.min(n.pts[0].x,n.pts[i-1].x),a=!0===n.drawing.style.extendRight?n.rc.plotWidth:Math.max(n.pts[0].x,n.pts[i-1].x);if(t<c-4||t>a+4)return null;let h=1/0;for(const t of s){const i=Math.abs(e-n.rc.priceScale.priceToY(l+r*t));i<h&&(h=i)}return h}}}const E=J("fib-retracement","Fib Retracement",2),Y=J("fib-extension","Fib Extension",3),V={id:"measure",name:"Measure",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.14},draw:t=>{const e=o(t.pts[0],t.pts[1]),i=t.rc.dpr,n=t.drawing.points,s=n[1].price-n[0].price,l=0!==n[0].price?s/n[0].price*100:0,r=s>=0,c=r?D:$;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.14,t.ctx.fillStyle=c,t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.restore(),_(t),t.ctx.strokeStyle=c,t.ctx.strokeRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0),t.ctx.setLineDash([]);const a=(e.x0+e.x1)/2,h=t.pts[0].y,x=t.pts[1].y;if(t.ctx.strokeStyle=c,t.ctx.beginPath(),t.ctx.moveTo(e.x0,h),t.ctx.lineTo(e.x1,h),t.ctx.stroke(),k(t,{x:e.x0,y:h},{x:e.x1,y:h}),t.ctx.beginPath(),t.ctx.moveTo(a,h),t.ctx.lineTo(a,x),t.ctx.stroke(),k(t,{x:a,y:h},{x:a,y:x}),!1===t.style.showLabels)return;const d=t.rc.dataLayer.timeToIndexFloat(n[0].time),p=t.rc.dataLayer.timeToIndexFloat(n[1].time),y=Math.abs(Math.round(p-d)),u=r?"+":"",f=[`${u}${t.formatPrice(s)} (${u}${l.toFixed(2)}%)`,`${S(y)} bars, ${L(n[1].time-n[0].time)}`],g=t.rc.bars?.();if(void 0!==g&&g.length>0){const t=Math.min(n[0].time,n[1].time),e=Math.max(n[0].time,n[1].time);let i=0,s=!1;for(const n of g)if(!(n.time<t)){if(n.time>e)break;void 0!==n.volume&&(i+=n.volume,s=!0)}s&&f.push(`Vol ${function(t){const e=Math.abs(t);return e>=1e9?`${(t/1e9).toFixed(2)}B`:e>=1e6?`${(t/1e6).toFixed(2)}M`:e>=1e3?`${(t/1e3).toFixed(2)}K`:S(t)}(i)}`)}T(t,f,a,Math.max(h,x)+6*i,c,{align:"center",place:"below"})},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)};function q(t,e,i){return{id:t,name:e,points:1,defaultStyle:{showLabels:!0,fillOpacity:.13,accountSize:1e5,risk:1},expand:(t,e)=>{const n=t[0],s=.01*Math.abs(n.price)||1,o=Math.max(5,Math.round(.08*e.visibleBars)),l=n.time+Math.max(1,e.barSeconds)*o;return i?[n,{time:l,price:n.price+s},{time:l,price:n.price-s}]:[n,{time:l,price:n.price-s},{time:l,price:n.price+s}]},draw:t=>{if(t.drawing.points.length<3||t.pts.length<3)return;const[e,n,s]=t.drawing.points,o=t.rc.dpr,l=Math.min(t.pts[0].x,t.pts[1].x,t.pts[2].x),r=Math.max(t.pts[0].x,t.pts[1].x,t.pts[2].x),c=t.rc.priceScale.priceToY(e.price)*o,a=t.rc.priceScale.priceToY(n.price)*o,h=t.rc.priceScale.priceToY(s.price)*o,x=(e,i,n)=>{t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.13,t.ctx.fillStyle=n,t.ctx.fillRect(l,Math.min(e,i),r-l,Math.abs(i-e)),t.ctx.restore()};x(c,a,D),x(c,h,$),_(t);for(const e of[c,a,h]){const i=Math.round(e)+.5;t.ctx.beginPath(),t.ctx.moveTo(l,i),t.ctx.lineTo(r,i),t.ctx.stroke()}if(t.ctx.setLineDash([]),!1===t.style.showLabels)return;const d=Math.abs(e.price-s.price),p=Math.abs(n.price-e.price),y=d>0?p/d:0,u=t.style.accountSize??0,f=t.style.risk??0,g=d>0&&u>0?Math.floor(u*f/100/d):0,m=t=>(0!==e.price?t/e.price*100:0).toFixed(3),b=t=>g>0?`, Amount: ${S(g*t)}`:"",w=(l+r)/2;T(t,[`Target: ${t.formatPrice(p)} (${m(p)}%)${b(p)}`],w,a,D,{align:"center",place:a<=c?"above":"below"}),T(t,[`Stop: ${t.formatPrice(d)} (${m(d)}%)${b(d)}`],w,h,$,{align:"center",place:h>=c?"below":"above"}),T(t,[`${i?"Long":"Short"} · Qty: ${g>0?S(g):"—"}`,`Risk/reward ratio: ${y.toFixed(2)}`],w,c,t.rc.theme.background,{align:"center",place:"middle"})},distance:(t,e,i)=>{if(i.pts.length<3)return null;const n=Math.min(i.pts[0].x,i.pts[1].x,i.pts[2].x),s=Math.max(i.pts[0].x,i.pts[1].x,i.pts[2].x);if(t<n-4||t>s+4)return null;const o=i.drawing.points.map(t=>i.rc.priceScale.priceToY(t.price)),l=Math.min(...o),r=Math.max(...o);return e>=l&&e<=r?0:Math.min(Math.abs(e-l),Math.abs(e-r))}}}const K=q("long-position","Long Position",!0),G=q("short-position","Short Position",!1),Q=1.35,X="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";function Z(t,e){const i="bold"===t.fontWeight?"700 ":"";return`${"italic"===t.fontStyle?"italic ":""}${i}${e}px ${t.fontFamily??X}`}function tt(t,e,i){const n=(e.text??"").split("\n");if(!0!==e.wrap)return n;const s=[];for(const e of n){const n=e.split(/\s+/).filter(t=>""!==t);if(0===n.length){s.push("");continue}let o=n[0];for(let e=1;e<n.length;e++){const l=`${o} ${n[e]}`;t.measureText(l).width>i?(s.push(o),o=n[e]):o=l}s.push(o)}return s}function et(t,e,i){const n=(e.fontSize??13)*i;t.font=Z(e,n);const s=tt(t,e,(e.wrapWidth??220)*i);let o=0;for(const e of s)o=Math.max(o,t.measureText(e).width);const l=n*Q;return{lines:s,width:o+10*i,height:s.length*l+10*i,lineHeight:l}}function it(t,e,i,n,s){const{ctx:o,rc:l,style:r}=t,c=r.text;if(void 0===c||""===c)return;const a=l.dpr,h=(r.fontSize??14)*a,x=6*a;o.save(),o.setLineDash([]),o.font=Z(r,h),o.fillStyle=r.fontColor??r.color,o.textBaseline="top";const d=!0===r.wrap?tt(o,r,Math.max(20*a,n-e-2*x)):c.split("\n"),p=h*Q,y=d.length*p,u=r.textAlign??"left";o.textAlign=u;const f="center"===u?(e+n)/2:"right"===u?n-x:e+x;let g;if("outside"===r.textPosition)g=i-y-x;else{const t=r.textVAlign??"top";g="middle"===t?(i+s-y)/2:"bottom"===t?s-y-x:i+x}for(const t of d)o.fillText(t,f,g),g+=p;o.restore()}const nt={id:"text",name:"Text",points:1,defaultStyle:{text:"Text",fontSize:14,fontWeight:"normal",fontStyle:"normal",background:!1,backgroundOpacity:1,border:!1,wrap:!1,wrapWidth:220,textAlign:"left"},draw:t=>{const{ctx:e,rc:i,style:n}=t,s=i.dpr,o=et(e,n,s),l=t.pts[0].x,r=t.pts[0].y;e.save(),e.setLineDash([]),!0===n.background&&(e.globalAlpha=n.backgroundOpacity??1,e.fillStyle=n.backgroundColor??i.theme.background,e.beginPath(),e.roundRect(l,r,o.width,o.height,4*s),e.fill(),e.globalAlpha=1),!0===n.border&&(e.strokeStyle=n.borderColor??n.color,e.lineWidth=Math.max(1,n.lineWidth*s),e.beginPath(),e.roundRect(l,r,o.width,o.height,4*s),e.stroke()),e.font=Z(n,(n.fontSize??13)*s),e.fillStyle=n.color,e.textBaseline="top";const c=n.textAlign??"left";e.textAlign=c;const a="center"===c?l+o.width/2:"right"===c?l+o.width-5*s:l+5*s;let h=r+5*s;for(const t of o.lines)e.fillText(t,a,h),h+=o.lineHeight;e.restore()},distance:(t,e,i)=>{const n=i.drawing.style,s=n.fontSize??13,o=i.pts[0],l=function(){if(void 0!==st)return st;try{st="undefined"==typeof document?null:document.createElement("canvas").getContext("2d")}catch{st=null}return st}(),r=null===l?{width:(n.text??"").length*s*.6+10,height:s*Q+10}:et(l,n,1);return t>=o.x-3&&t<=o.x+r.width+3&&e>=o.y-3&&e<=o.y+r.height+3?0:null}};let st;const ot={id:"path",name:"Path",points:0,draw:t=>{if(!(t.pts.length<2)){_(t),t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.setLineDash([]),k(t,t.pts[t.pts.length-2],t.pts[t.pts.length-1])}},distance:(t,e,i)=>i.pts.length<2?null:s(t,e,i.pts)},lt={id:"brush",name:"Brush",points:0,freehand:!0,defaultStyle:{lineWidth:2},draw:t=>{if(!(t.pts.length<2)){_(t),t.ctx.lineCap="round",t.ctx.lineJoin="round",t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>i.pts.length<2?null:s(t,e,i.pts)},rt={id:"rotated-rectangle",name:"Rotated Rectangle",points:3,defaultStyle:{fill:!0,fillOpacity:.12},draw:t=>{if(t.pts.length<3)return;const e=ct(t.pts[0],t.pts[1],t.pts[2]);t.ctx.beginPath(),t.ctx.moveTo(e[0].x,e[0].y);for(let i=1;i<4;i++)t.ctx.lineTo(e[i].x,e[i].y);t.ctx.closePath(),!0===t.style.fill&&(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.12,t.ctx.fillStyle=w(t),t.ctx.fill(),t.ctx.restore()),_(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(e,i,n)=>{if(n.pts.length<3)return null;const s=ct(n.pts[0],n.pts[1],n.pts[2]);if(!0===n.drawing.style.fill&&function(t,e,i){let n=!1;for(let s=0,o=i.length-1;s<i.length;o=s++){const l=i[s],r=i[o];l.y>e!=r.y>e&&t<(r.x-l.x)*(e-l.y)/(r.y-l.y)+l.x&&(n=!n)}return n}(e,i,s))return 0;let o=1/0;for(let n=0;n<4;n++)o=Math.min(o,t(e,i,s[n],s[(n+1)%4]));return o}};function ct(t,e,i){const n=e.x-t.x,s=e.y-t.y,o=Math.hypot(n,s)||1,l=-s/o,r=n/o,c=(i.x-e.x)*l+(i.y-e.y)*r;return[t,e,{x:e.x+l*c,y:e.y+r*c},{x:t.x+l*c,y:t.y+r*c}]}const at={id:"double-curve",name:"Double Curve",points:3,draw:t=>{if(t.pts.length<3)return;const[e,i,n]=t.pts;_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.bezierCurveTo(i.x,i.y,e.x+n.x-i.x,e.y+n.y-i.y,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{if(i.pts.length<3)return null;const[n,o,l]=i.pts;return s(t,e,function(t,e,i,n,s){const o=[];for(let l=0;l<=s;l++){const r=l/s,c=1-r,a=c*c*c,h=3*c*c*r,x=3*c*r*r,d=r*r*r;o.push({x:a*t.x+h*e.x+x*i.x+d*n.x,y:a*t.y+h*e.y+x*i.y+d*n.y})}return o}(n,o,{x:n.x+l.x-o.x,y:n.y+l.y-o.y},l,24))}};const ht={id:"cyclic-lines",name:"Cyclic Lines",points:2,defaultStyle:{lineStyle:"dashed"},draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(!Number.isFinite(n)||Math.abs(n)<.5)return;const s=t.rc.plotHeight*t.rc.dpr,o=t.rc.plotWidth*t.rc.dpr;_(t),t.ctx.beginPath();for(let i=0;i<=12;i++){const l=Math.round(e.x+n*i)+.5;l<0||l>o||(t.ctx.moveTo(l,0),t.ctx.lineTo(l,s))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const n=i.pts[1].x-i.pts[0].x;if(!Number.isFinite(n)||Math.abs(n)<.5)return null;const s=Math.round((t-i.pts[0].x)/n);return s<0||s>12?null:Math.abs(t-(i.pts[0].x+n*s))}},xt={id:"time-cycles",name:"Time Cycles",points:2,draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(!Number.isFinite(n)||Math.abs(n)<1)return;const s=Math.abs(n)/2;_(t),t.ctx.beginPath();for(let i=0;i<12;i++){const o=e.x+n*i+n/2;o+s<0||o-s>t.rc.plotWidth*t.rc.dpr||(t.ctx.moveTo(o+s,e.y),t.ctx.arc(o,e.y,s,0,Math.PI,!0))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=s.x-n.x;if(!Number.isFinite(o)||Math.abs(o)<1)return null;const l=Math.abs(o)/2;let r=1/0;for(let i=0;i<12;i++){const s=n.x+o*i+o/2;e>n.y+2||(r=Math.min(r,Math.abs(Math.hypot(t-s,e-n.y)-l)))}return Number.isFinite(r)?r:null}},dt={id:"sine-line",name:"Sine Line",points:2,draw:t=>{const e=pt(t.pts[0],t.pts[1]);if(null!==e){_(t),t.ctx.beginPath(),t.ctx.moveTo(e[0].x,e[0].y);for(let i=1;i<e.length;i++)t.ctx.lineTo(e[i].x,e[i].y);t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>{const n=pt(i.pts[0],i.pts[1]);return null===n?null:s(t,e,n)}};function pt(t,e){const i=e.x-t.x,n=e.y-t.y;if(!Number.isFinite(i)||Math.abs(i)<1)return null;const s=[];for(let e=0;e<=64;e++){const o=e/64;s.push({x:t.x+i*o,y:t.y+n*Math.sin(o*Math.PI*2)})}return s}const yt={id:"price-label",name:"Price Label",points:1,defaultStyle:{fontSize:12},draw:t=>{const e=t.pts[0],i=t.rc.dpr,n=void 0!==t.style.text&&""!==t.style.text?t.style.text:t.formatPrice(t.drawing.points[0].price),s=ft(t,[n],e.x+18*i,e.y-30*i);gt(t,s,e,t.style.color),mt(t,s,[n],t.style.color)},distance:(t,e,i)=>{const n=i.pts[0],s=n.x+18,o=n.y-30-11;return t>=s&&t<=s+64&&e>=o&&e<=o+22||Math.hypot(t-n.x,e-n.y)<=10?0:null}},ut={id:"callout",name:"Callout",points:2,defaultStyle:{fontSize:12,text:"Note"},draw:t=>{if(t.pts.length<2)return;const[e,i]=t.pts,n=(t.style.text??"Note").split("\n"),s=ft(t,n,i.x,i.y);gt(t,s,e,t.style.color),mt(t,s,n,t.style.color)},distance:(e,i,n)=>{if(n.pts.length<2)return null;const[s,o]=n.pts;return Math.abs(e-o.x)<=60&&Math.abs(i-o.y)<=16?0:t(e,i,s,o)}};function ft(t,e,i,n){const s=t.rc.dpr,o=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.font=`${o}px ui-sans-serif, system-ui, sans-serif`;let l=0;for(const i of e)l=Math.max(l,t.ctx.measureText(i).width);t.ctx.restore();const r=l+14*s,c=1.4*o*e.length+8*s;return{x:i-r/2,y:n-c/2,w:r,h:c}}function gt(t,e,i,n){const s=t.rc.dpr,o=e.x+e.w/2,l=e.y+e.h/2,r=Math.atan2(i.y-l,i.x-o),c=5*s,a=o+Math.cos(r)*(e.w/2-c),h=l+Math.sin(r)*(e.h/2-c);t.ctx.save(),t.ctx.setLineDash([]),t.ctx.fillStyle=n,t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(a-Math.sin(r)*c,h+Math.cos(r)*c),t.ctx.lineTo(a+Math.sin(r)*c,h-Math.cos(r)*c),t.ctx.closePath(),t.ctx.fill(),t.ctx.beginPath(),x(t.ctx,e.x,e.y,e.w,e.h,5*s),t.ctx.fill(),t.ctx.beginPath(),t.ctx.arc(i.x,i.y,2.5*s,0,2*Math.PI),t.ctx.fill(),t.ctx.restore()}function mt(t,e,i,n){const s=t.rc.dpr,o=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.setLineDash([]),t.ctx.font=`${o}px ui-sans-serif, system-ui, sans-serif`,t.ctx.textAlign="center",t.ctx.textBaseline="middle",t.ctx.fillStyle=t.style.fontColor??h(n);const l=1.4*o,r=e.y+e.h/2-l*(i.length-1)/2;for(let n=0;n<i.length;n++)t.ctx.fillText(i[n],e.x+e.w/2,r+l*n);t.ctx.restore()}const bt={id:"flag-mark",name:"Flag Mark",points:1,defaultStyle:{fill:!0,fillOpacity:.95},draw:t=>{const e=t.pts[0],i=t.rc.dpr,n=22*i,s=15*i,o=11*i;_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(e.x,e.y-n),t.ctx.stroke(),t.ctx.setLineDash([]),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y-n),t.ctx.lineTo(e.x+s,e.y-n+.28*o),t.ctx.lineTo(e.x+.72*s,e.y-n+.5*o),t.ctx.lineTo(e.x+s,e.y-n+.72*o),t.ctx.lineTo(e.x,e.y-n+o),t.ctx.closePath(),t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.95,t.ctx.fillStyle=w(t),t.ctx.fill(),t.ctx.restore()},distance:(t,e,i)=>{const n=i.pts[0];return t>=n.x-4&&t<=n.x+16&&e>=n.y-24&&e<=n.y+2||Math.hypot(t-n.x,e-n.y)<=8?0:null}},_t={id:"price-range",name:"Price Range",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.1},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,n=i[1].price-i[0].price,s=0!==i[0].price?n/i[0].price*100:0,o=n>=0,l=o?"#26a69a":"#ef5350",r=Math.min(t.pts[0].x,t.pts[1].x),c=Math.max(t.pts[0].x,t.pts[1].x)+(t.pts[0].x===t.pts[1].x?60*e:0),a=t.pts[0].y,h=t.pts[1].y;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.1,t.ctx.fillStyle=l,t.ctx.fillRect(r,Math.min(a,h),c-r,Math.abs(h-a)),t.ctx.restore(),_(t),t.ctx.strokeStyle=l,t.ctx.beginPath();for(const e of[a,h])t.ctx.moveTo(r,Math.round(e)+.5),t.ctx.lineTo(c,Math.round(e)+.5);const x=(r+c)/2;t.ctx.moveTo(x,a),t.ctx.lineTo(x,h);const d=h>a?1:-1;t.ctx.moveTo(x-4*e,h-5*e*d),t.ctx.lineTo(x,h),t.ctx.lineTo(x+4*e,h-5*e*d),t.ctx.moveTo(x-4*e,a+5*e*d),t.ctx.lineTo(x,a),t.ctx.lineTo(x+4*e,a+5*e*d),t.ctx.stroke(),t.ctx.setLineDash([]);const p=o?"+":"";M(t,`${p}${t.formatPrice(n)} (${p}${s.toFixed(2)}%)`,x+6*e,(a+h)/2,l)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)},wt={id:"date-range",name:"Date Range",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.1},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,n=t.style.color,s=t.pts[0].x,o=t.pts[1].x,l=Math.min(t.pts[0].y,t.pts[1].y),r=Math.max(t.pts[0].y,t.pts[1].y)+(t.pts[0].y===t.pts[1].y?40*e:0);t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.1,t.ctx.fillStyle=n,t.ctx.fillRect(Math.min(s,o),l,Math.abs(o-s),r-l),t.ctx.restore(),_(t),t.ctx.beginPath();for(const e of[s,o])t.ctx.moveTo(Math.round(e)+.5,l),t.ctx.lineTo(Math.round(e)+.5,r);const c=(l+r)/2;t.ctx.moveTo(s,c),t.ctx.lineTo(o,c);const a=o>s?1:-1;t.ctx.moveTo(o-5*e*a,c-4*e),t.ctx.lineTo(o,c),t.ctx.lineTo(o-5*e*a,c+4*e),t.ctx.moveTo(s+5*e*a,c-4*e),t.ctx.lineTo(s,c),t.ctx.lineTo(s+5*e*a,c+4*e),t.ctx.stroke(),t.ctx.setLineDash([]);const h=t.rc.dataLayer.timeToIndexFloat(i[0].time),x=t.rc.dataLayer.timeToIndexFloat(i[1].time);M(t,`${Math.abs(Math.round(x-h))} bars`,(s+o)/2,l-10*e,n)},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0)},vt={id:"forecast",name:"Forecast",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.12,lineStyle:"dashed"},draw:t=>{const e=t.rc.dpr,i=t.drawing.points,[n,s]=t.pts,o=i[1].price-i[0].price,l=0!==i[0].price?o/i[0].price*100:0,r=o>=0,c=r?"#26a69a":"#ef5350",a=.35*Math.abs(s.y-n.y)+6*e;if(t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.12,t.ctx.fillStyle=c,t.ctx.beginPath(),t.ctx.moveTo(n.x,n.y),t.ctx.lineTo(s.x,s.y-a),t.ctx.lineTo(s.x,s.y+a),t.ctx.closePath(),t.ctx.fill(),t.ctx.restore(),_(t),t.ctx.strokeStyle=c,t.ctx.beginPath(),t.ctx.moveTo(n.x,n.y),t.ctx.lineTo(s.x,s.y),t.ctx.stroke(),t.ctx.setLineDash([]),t.ctx.beginPath(),t.ctx.arc(n.x,n.y,3*e,0,2*Math.PI),t.ctx.fillStyle=c,t.ctx.fill(),!1===t.style.showLabels)return;const h=r?"+":"";T(t,[t.formatPrice(i[0].price),P(i[0].time)],n.x,n.y,c,{align:"center"}),T(t,[`${h}${t.formatPrice(o)} (${h}${l.toFixed(2)}%) in ${L(i[1].time-i[0].time)}`,`${t.formatPrice(i[1].price)} · ${P(i[1].time)}`],s.x,s.y,c,{align:"center",place:"below"});const x=t.rc.bars?.();if(void 0!==x&&x.length>0&&x[x.length-1].time>=i[1].time){let n=!1;for(const t of x)if(!(t.time<i[0].time)){if(t.time>i[1].time)break;if(r?t.high>=i[1].price:t.low<=i[1].price){n=!0;break}}T(t,[n?"SUCCESS":"MISSED"],s.x,s.y+36*e,n?"#4a934a":"#8a4a4a",{align:"center",place:"below"})}},distance:(e,i,n)=>t(e,i,n.pts[0],n.pts[1])},Mt={id:"circle",name:"Circle",points:2,defaultStyle:{fill:!0},draw:t=>{const[e,i]=t.pts,n=Math.hypot(i.x-e.x,i.y-e.y);t.ctx.beginPath(),t.ctx.arc(e.x,e.y,n,0,2*Math.PI),v(t,()=>t.ctx.fill()),_(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=Math.hypot(s.x-n.x,s.y-n.y),l=Math.hypot(t-n.x,e-n.y);return!0===i.drawing.style.fill&&l<=o?0:Math.abs(l-o)}},Tt={id:"triangle",name:"Triangle",points:3,defaultStyle:{fill:!0},draw:t=>{t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y),t.ctx.lineTo(t.pts[1].x,t.pts[1].y),t.ctx.lineTo(t.pts[2].x,t.pts[2].y),t.ctx.closePath(),v(t,()=>t.ctx.fill()),_(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>s(t,e,[...i.pts,i.pts[0]])},St={id:"polyline",name:"Polyline",points:0,defaultStyle:{fill:!1},draw:t=>{if(!(t.pts.length<2)){t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);!0===t.style.fill&&(t.ctx.closePath(),v(t,()=>t.ctx.fill())),_(t),t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>s(t,e,i.pts)};const Pt={id:"arc",name:"Arc",points:3,draw:t=>{const[e,i,n]=t.pts;_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.quadraticCurveTo(2*i.x-(e.x+n.x)/2,2*i.y-(e.y+n.y)/2,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>s(t,e,function(t,e,i){const n=2*e.x-(t.x+i.x)/2,s=2*e.y-(t.y+i.y)/2,o=[];for(let e=0;e<=16;e++){const l=e/16,r=1-l;o.push({x:r*r*t.x+2*r*l*n+l*l*i.x,y:r*r*t.y+2*r*l*s+l*l*i.y})}return o}(i.pts[0],i.pts[1],i.pts[2]))},Lt={id:"curve",name:"Curve",points:3,draw:t=>{const[e,i,n]=t.pts;_(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.quadraticCurveTo(i.x,i.y,n.x,n.y),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,o,l]=i.pts,r=[];for(let t=0;t<=16;t++){const e=t/16,i=1-e;r.push({x:i*i*n.x+2*i*e*o.x+e*e*l.x,y:i*i*n.y+2*i*e*o.y+e*e*l.y})}return s(t,e,r)}};function kt(t,e,i){return{id:t,name:e,points:1,defaultStyle:{fill:!0,fillOpacity:.9},draw:t=>{const e=t.rc.dpr,{x:n,y:s}=t.pts[0],o=16*e,l=6*e,r=i?1:-1,c=s+2*r*e;t.ctx.beginPath(),t.ctx.moveTo(n,c),t.ctx.lineTo(n-l,c+r*l),t.ctx.lineTo(n-l/2.4,c+r*l),t.ctx.lineTo(n-l/2.4,c+r*o),t.ctx.lineTo(n+l/2.4,c+r*o),t.ctx.lineTo(n+l/2.4,c+r*l),t.ctx.lineTo(n+l,c+r*l),t.ctx.closePath(),t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.9,t.ctx.fillStyle=w(t),t.ctx.fill(),t.ctx.restore(),_(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.pts[0],o=i?e-s.y:s.y-e;return Math.abs(t-s.x)<=8&&o>=-4&&o<=20?0:null}}}const Dt=kt("arrow-up","Arrow Up",!0),$t=kt("arrow-down","Arrow Down",!1),Ot={id:"highlighter",name:"Highlighter",points:0,freehand:!0,defaultStyle:{lineWidth:12,fillOpacity:.28},draw:t=>{if(t.pts.length<2)return;const e=t.rc.dpr;t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.28,t.ctx.strokeStyle=t.style.color,t.ctx.lineWidth=Math.max(2,(t.style.lineWidth||12)*e),t.ctx.lineCap="round",t.ctx.lineJoin="round",t.ctx.beginPath(),t.ctx.moveTo(t.pts[0].x,t.pts[0].y);for(let e=1;e<t.pts.length;e++)t.ctx.lineTo(t.pts[e].x,t.pts[e].y);t.ctx.stroke(),t.ctx.restore()},distance:(t,e,i)=>{const n=s(t,e,i.pts);return n<=Math.max(6,(i.drawing.style.lineWidth??12)/2)?0:n}},Ft={id:"fib-channel",name:"Fib Channel",points:3,defaultStyle:{showLabels:!0,levels:[...O]},draw:t=>{const e=t.style.levels??O,[i,n,s]=t.pts,o=s.x-n.x,l=s.y-n.y;_(t);for(const s of e)t.ctx.beginPath(),t.ctx.moveTo(i.x+o*s,i.y+l*s),t.ctx.lineTo(n.x+o*s,n.y+l*s),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,`${(100*s).toFixed(1)}%`,n.x+o*s+4*t.rc.dpr,n.y+l*s);t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??O,[o,l,r]=n.pts;let c=1/0;for(const n of s){const s=t(e,i,{x:o.x+(r.x-l.x)*n,y:o.y+(r.y-l.y)*n},{x:l.x+(r.x-l.x)*n,y:l.y+(r.y-l.y)*n});s<c&&(c=s)}return c}},At=[0,1,2,3,5,8,13,21,34,55],Ct={id:"fib-time-zone",name:"Fib Time Zone",points:2,defaultStyle:{showLabels:!0},draw:t=>{const[e,i]=t.pts,n=i.x-e.x;if(Math.abs(n)<.5)return;const s=t.rc.dpr,o=t.rc.plotWidth*s;_(t);for(const i of At){const l=e.x+n*i;l<-10||l>o+10||(t.ctx.beginPath(),t.ctx.moveTo(Math.round(l)+.5,0),t.ctx.lineTo(Math.round(l)+.5,t.rc.plotHeight*s),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,String(i),l+3*s,12*s))}t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,o=s.x-n.x;if(Math.abs(o)<.5)return null;let l=1/0;for(const e of At)l=Math.min(l,Math.abs(t-(n.x+o*e)));return l}},Nt=[.236,.382,.5,.618,.786,1],Wt={id:"fib-fan",name:"Fib Speed Fan",points:2,defaultStyle:{showLabels:!0,levels:[...Nt]},draw:t=>{const e=t.style.levels??Nt,[i,n]=t.pts,s=t.rc.dpr,o=t.rc.plotWidth*s;_(t);for(const l of e){const e=c(i,{x:n.x,y:i.y+(n.y-i.y)*l},o,!1,!0)[1];t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(e.x,e.y),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,`${(100*l).toFixed(1)}%`,n.x+4*s,i.y+(n.y-i.y)*l)}t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??Nt,[o,l]=n.pts;let r=1/0;for(const a of s)r=Math.min(r,t(e,i,o,c(o,{x:l.x,y:o.y+(l.y-o.y)*a},n.rc.plotWidth,!1,!0)[1]));return r}},It=[[1,.125],[1,.25],[1,.5],[1,1],[.5,1],[.25,1],[.125,1]],Rt=[A,C,N,W,I,R,z,j,U,B,H,E,Y,K,G,vt,V,_t,wt,Mt,Tt,St,Pt,Lt,rt,at,Dt,$t,Ot,lt,Ft,Ct,Wt,{id:"gann-fan",name:"Gann Fan",points:2,defaultStyle:{showLabels:!0},draw:t=>{const[e,i]=t.pts,n=t.rc.dpr,s=t.rc.plotWidth*n,o=i.x-e.x,l=i.y-e.y;if(!(Math.abs(o)<.5)){_(t);for(const[i,n]of It){const r=c(e,{x:e.x+o*i,y:e.y+l*n},s,!1,!0)[1];t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(r.x,r.y),t.ctx.stroke()}!1!==t.style.showLabels&&M(t,"1x1",i.x+4*n,i.y),t.ctx.setLineDash([])}},distance:(e,i,n)=>{const[s,o]=n.pts,l=o.x-s.x,r=o.y-s.y;let a=1/0;for(const[o,h]of It)a=Math.min(a,t(e,i,s,c(s,{x:s.x+l*o,y:s.y+r*h},n.rc.plotWidth,!1,!0)[1]));return a}},{id:"gann-box",name:"Gann Box",points:2,defaultStyle:{fill:!0,fillOpacity:.05},draw:t=>{const e=o(t.pts[0],t.pts[1]);v(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),_(t);const i=e.x1-e.x0,n=e.y1-e.y0;t.ctx.beginPath();for(let s=0;s<=8;s++){const o=Math.round(e.x0+i*s/8)+.5,l=Math.round(e.y0+n*s/8)+.5;t.ctx.moveTo(o,e.y0),t.ctx.lineTo(o,e.y1),t.ctx.moveTo(e.x0,l),t.ctx.lineTo(e.x1,l)}t.ctx.moveTo(e.x0,e.y1),t.ctx.lineTo(e.x1,e.y0),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>l(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},ht,xt,dt,nt,ot,yt,ut,bt];let zt=!1;function jt(){if(!zt){zt=!0;for(const t of Rt)p(t)}}function Ut(t,e){return u(t)&&!0===y(t).freehand&&e>2?[0,e-1]:Array.from({length:e},(t,e)=>e)}class Bt{constructor(){Object.defineProperty(this,"_drawings",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_host",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_selected",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_preview",{enumerable:!0,configurable:!0,writable:!0,value:null})}attached(t){this._host=t}detached(){this._host=null}zOrder(){return"top"}autoscaleInfo(){return null}setDrawings(t){this._drawings=t.slice(),this._host?.requestUpdate()}setSelected(t){t!==this._selected&&(this._selected=t,this._host?.requestUpdate())}setPreview(t){this._preview=t,this._host?.requestUpdate()}_project(t,e,i){return{x:t.timeScale.indexToX(t.dataLayer.timeToIndexFloat(e)),y:t.priceScale.priceToY(i)}}_points(t,e){return e.points.map(e=>this._project(t,e.time,e.price))}draw(t,e){const i=null===this._preview?this._drawings:[...this._drawings,this._preview];for(const n of i){if(!1===n.visible||!u(n.tool))continue;const i=y(n.tool);if(n.points.length<Math.max(1,i.points))continue;const s=this._points(e,n);if(!s.some(t=>Number.isFinite(t.x)&&Number.isFinite(t.y)))continue;const o={color:n.style.color??e.theme.lineColor,lineWidth:n.style.lineWidth??1.5,...n.style},l=e.dpr;t.save(),n===this._preview&&(t.globalAlpha=.7),i.draw({ctx:t,rc:e,drawing:n,selected:n.id===this._selected,pts:s.map(t=>({x:t.x*l,y:t.y*l})),style:{...o,color:o.color,lineWidth:o.lineWidth},formatPrice:t=>e.priceScale.format(t)}),t.restore(),n.id===this._selected&&!0!==n.locked&&this._drawHandles(t,e,s,n.tool)}}_drawHandles(t,e,i,n){const s=e.dpr;t.save(),t.setLineDash([]),t.lineWidth=Math.max(1,Math.round(1.5*s));for(const o of Ut(n,i.length)){const n=i[o];t.beginPath(),t.arc(n.x*s,n.y*s,5*s,0,2*Math.PI),t.fillStyle=e.theme.background,t.fill(),t.strokeStyle=e.theme.lineColor,t.stroke()}t.restore()}hitTest(t,e,i){if(null!==this._selected){const n=this._drawings.find(t=>t.id===this._selected);if(void 0!==n&&!0!==n.locked){const s=this._points(i,n);for(const i of Ut(n.tool,s.length))if(Math.hypot(t-s[i].x,e-s[i].y)<=7)return{externalId:`draw:${n.id}#${i}`,zOrder:"top",distance:0,cursor:"grabbing",draggable:!0}}}let n=null;for(let s=this._drawings.length-1;s>=0;s--){const o=this._drawings[s];if(!1===o.visible||!0===o.locked||!u(o.tool))continue;const l=y(o.tool);if(o.points.length<Math.max(1,l.points))continue;const r=l.distance(t,e,{pts:this._points(i,o),drawing:o,rc:i});null===r||!Number.isFinite(r)||r>6||(null===n||r<n.distance)&&(n={id:o.id,distance:r})}return null===n?null:{externalId:`draw:${n.id}`,zOrder:"top",distance:n.distance,cursor:"move",draggable:!0}}}let Ht=1;class Jt{constructor(t,e={}){Object.defineProperty(this,"_chart",{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,"_layers",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"_drawings",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_tool",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_pending",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_pendingPane",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_selected",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_undo",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_redo",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_dragStart",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_off",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_lastCursor",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_lastBar",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._chart=t,this._opts={magnet:e.magnet??!1,stayInDrawingMode:e.stayInDrawingMode??!1,historyLimit:e.historyLimit??50,defaultStyle:e.defaultStyle??{}},this._off.push(t.on("click",t=>this._onClick(t))),this._off.push(t.on("crosshair:move",t=>this._onCrosshair(t))),this._off.push(t.on("drag",t=>this._onDrag(t))),this._off.push(t.on("drag:end",()=>this._onDragEnd())),this._off.push(t.on("dblclick",()=>{this.finish()}));const i=t.drawingState();Array.isArray(i)&&(this._drawings=i.map(t=>({...t}))),this._sync()}setTool(t){if(null!==t&&!u(t))throw new Error(`openalgo-charts: unknown drawing tool "${t}"`);this._tool=t,this._pending=[],this._setPlacementMode(null!==t),this._syncPreview(),this._chart.emit("draw:tool",{tool:t})}_setPlacementMode(t){const e=this._chart;e.setPlacementMode?.(t)}activeTool(){return this._tool}setOptions(t){this._opts={...this._opts,...t,defaultStyle:t.defaultStyle??this._opts.defaultStyle}}drawings(){return this._drawings}get(t){return this._drawings.find(e=>e.id===t)}add(t){this._pushUndo();const e=y(t.tool),i={...t,id:t.id??"d"+Ht++,style:{...this._opts.defaultStyle,...e.defaultStyle,...t.style}};return this._drawings.push(i),this._sync(),this._chart.emit("draw:add",{drawing:i}),i}update(t,e){const i=this.get(t);return void 0!==i&&(this._pushUndo(),void 0!==e.points&&(i.points=e.points.map(t=>({...t}))),void 0!==e.style&&(i.style={...i.style,...e.style}),void 0!==e.locked&&(i.locked=e.locked),void 0!==e.visible&&(i.visible=e.visible),this._sync(),this._chart.emit("draw:update",{drawing:i}),!0)}remove(t){const e=this._drawings.findIndex(e=>e.id===t);if(e<0)return!1;this._pushUndo();const[i]=this._drawings.splice(e,1);return this._selected===t&&(this._selected=null),this._sync(),this._chart.emit("draw:remove",{drawing:i}),!0}clear(){0!==this._drawings.length&&(this._pushUndo(),this._drawings=[],this._selected=null,this._sync())}select(t){this._selected=t;for(const e of this._layers.values())e.setSelected(t);this._chart.emit("draw:select",{id:t})}selected(){return this._selected}undo(){const t=this._undo.pop();return void 0!==t&&(this._redo.push(JSON.stringify(this._drawings)),this._drawings=JSON.parse(t),this._drawings.some(t=>t.id===this._selected)||(this._selected=null),this._sync(),!0)}redo(){const t=this._redo.pop();return void 0!==t&&(this._undo.push(JSON.stringify(this._drawings)),this._drawings=JSON.parse(t),this._sync(),!0)}canUndo(){return this._undo.length>0}canRedo(){return this._redo.length>0}toJSON(){return this._drawings.map(t=>({...t,points:t.points.map(t=>({...t})),style:{...t.style}}))}fromJSON(t){this._drawings=Array.isArray(t)?t.map(t=>({...t})):[],this._selected=null,this._undo=[],this._redo=[],this._sync()}destroy(){this._setPlacementMode(!1);for(const t of this._off)t();this._off.length=0;for(const[t,e]of this._layers)this._chart.removePrimitive(e);this._layers.clear()}_onCrosshair(t){const e=t.time,i=t.price,n=t.paneIndex??null;this._lastCursor=null===e||null===i||null===n?null:{time:e,price:i,paneIndex:n},this._lastBar=t.bar??null,null!==this._tool&&!0===t.pressed&&this._isFreehand()&&null!==e&&null!==i&&null!==n&&Number.isFinite(e)&&Number.isFinite(i)?this._inkPoint({time:e,price:i},n):null!==this._tool&&this._pending.length>0&&this._syncPreview()}_expand(t,e){if(void 0===t.expand)return e;const i=this._chart.dataLayer,n=i.baseIndex,s=n>0?i.indexToTime(n-1):void 0,o=n>=0?i.indexToTime(n):void 0,l=void 0!==s&&void 0!==o&&o>s?o-s:60,r=this._chart.getVisibleLogicalRange(),c=null===r?60:Math.max(1,r.to-r.from);return t.expand(e,{barSeconds:l,visibleBars:c})}_isFreehand(){return null!==this._tool&&!0===y(this._tool).freehand}_inkPoint(t,e){if(0===this._pending.length)this._pendingPane=e;else{if(e!==this._pendingPane)return;{const e=this._pending[this._pending.length-1];if(e.time===t.time&&e.price===t.price)return}}this._pending.push(t),this._syncPreview()}_commit(t){const e=y(this._tool),i=this.add({tool:e.id,points:t,style:{},paneIndex:this._pendingPane});this._pending=[],this._opts.stayInDrawingMode||(this._tool=null,this._setPlacementMode(!1)),this._syncPreview(),this.select(i.id),this._chart.emit("draw:tool",{tool:this._tool})}_finishFreehand(){const t=this._pending;this._pending=[],t.length<2?this._syncPreview():this._commit(t)}finish(){if(null===this._tool||0===this._pending.length)return!1;const t=y(this._tool);if(0!==t.points||!0===t.freehand)return!1;const e=this._pending;return e.length<2?(this._pending=[],this._syncPreview(),!1):(this._commit(e),!0)}_onClick(t){if(null===this._tool)null!==t.id&&t.id.startsWith("draw:")?this.select(t.id.slice(5).split("#")[0]):null===t.id&&this.select(null);else{if(this._isFreehand())return void(!0===t.viaDrag&&this._finishFreehand());if(!0===t.viaDrag&&0===this._pending.length)return;if(null===t.price||!Number.isFinite(t.price)||!Number.isFinite(t.time))return;this._placePoint({time:t.time,price:this._snap(t.price,t.paneIndex)},t.paneIndex)}}_placePoint(t,e){0===this._pending.length&&(this._pendingPane=e),this._pending.push(t);const i=y(this._tool);i.points>0&&this._pending.length>=i.points?this._commit(this._expand(i,this._pending)):this._syncPreview()}_snap(t,e){if(!this._opts.magnet||0!==e)return t;const i=this._lastBar;if(null===i)return t;let n=t,s=1/0;for(const e of[i.open,i.high,i.low,i.close]){const i=Math.abs(e-t);i<s&&(s=i,n=e)}return n}_onDrag(t){if(!t.id.startsWith("draw:"))return;const[e,i]=t.id.slice(5).split("#"),n=this.get(e);if(void 0===n||!0===n.locked)return;const s=void 0===i?null:Number(i);null!==this._dragStart&&this._dragStart.id===e&&this._dragStart.handle===s||(this._pushUndo(),this._dragStart={id:e,handle:s,points:n.points.map(t=>({...t})),from:{time:t.fromTime??t.time,price:t.fromPrice??t.price}});const o=this._dragStart;if(null===s){const e=t.time-o.from.time,i=t.price-o.from.price;n.points=o.points.map(t=>({time:t.time+e,price:t.price+i}))}else s>=0&&s<n.points.length&&(n.points=o.points.map((e,i)=>i===s?{time:t.time,price:t.price}:{...e}));this._sync()}_onDragEnd(){if(null===this._dragStart)return;const t=this.get(this._dragStart.id);this._dragStart=null,void 0!==t&&this._chart.emit("draw:update",{drawing:t})}_layerFor(t){let e=this._layers.get(t);return void 0===e&&(e=new Bt,this._chart.addPrimitive(e,t),this._layers.set(t,e)),e}_sync(){const t=new Map;for(const e of this._drawings){const i=t.get(e.paneIndex)??[];i.push(e),t.set(e.paneIndex,i)}for(const[e,i]of t)this._layerFor(e).setDrawings(i);for(const[e,i]of this._layers)t.has(e)||i.setDrawings([]),i.setSelected(this._selected);this._chart.setDrawingState(this.toJSON())}_syncPreview(){for(const t of this._layers.values())t.setPreview(null);if(null===this._tool||0===this._pending.length)return;const t=this._lastCursor,e=null===t?this._pending:[...this._pending,{time:t.time,price:t.price}];this._layerFor(this._pendingPane).setPreview({id:"__preview",tool:this._tool,points:e,style:this._opts.defaultStyle,paneIndex:this._pendingPane})}_pushUndo(){this._undo.push(JSON.stringify(this._drawings)),this._undo.length>this._opts.historyLimit&&this._undo.shift(),this._redo=[]}}const Et="draw";jt();export{W as ARROW,Rt as BUILTIN_DRAWING_TOOLS,j as CROSS_LINE,Et as DRAW_TIER,Jt as DrawingController,Bt as DrawingLayer,B as ELLIPSE,N as EXTENDED_LINE,Y as FIB_EXTENSION,E as FIB_RETRACEMENT,I as HORIZONTAL_LINE,R as HORIZONTAL_RAY,K as LONG_POSITION,V as MEASURE,H as PARALLEL_CHANNEL,ot as PATH,C as RAY,U as RECTANGLE,G as SHORT_POSITION,nt as TEXT,A as TREND_LINE,z as VERTICAL_LINE,r as distToEllipse,e as distToLine,s as distToPolyline,l as distToRect,t as distToSegment,b as drawingShortcuts,c as extendSegment,y as getDrawingTool,u as hasDrawingTool,m as matchDrawingShortcut,o as rectOf,jt as registerBuiltinDrawingTools,p as registerDrawingTool,f as registeredDrawingTools};
2
2
  //# sourceMappingURL=openalgo-charts.draw.mjs.map