openalgo-charts 1.8.9 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/draw/index.d.ts +141 -1
- package/dist/index.d.ts +15 -1
- package/dist/openalgo-charts.draw.mjs +1 -1
- package/dist/openalgo-charts.draw.mjs.map +1 -1
- package/dist/openalgo-charts.mjs +1 -1
- package/dist/openalgo-charts.mjs.map +1 -1
- package/dist/openalgo-charts.standalone.js +1 -1
- package/dist/openalgo-charts.standalone.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,13 +8,13 @@ Professional interactive charts, 102 built-in indicators plus your own custom on
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/openalgo-charts)
|
|
10
10
|
[](./LICENSE)
|
|
11
|
-
[](#size-budget)
|
|
12
|
+
[](#develop)
|
|
13
13
|
[](#principles)
|
|
14
14
|
|
|
15
15
|
[**Documentation**](https://marketcalls.github.io/openalgo-charts/) · [**Live examples**](https://marketcalls.github.io/openalgo-charts/examples) · [**Getting started**](./docs/getting-started.md) · [**Architecture**](./ARCHITECTURE.md)
|
|
16
16
|
|
|
17
|
-
<img src="docs/architecture-diagram.svg" alt="OpenAlgo Charts architecture: seven layers from the public API down to feeds and data, with 102 built-in plus custom indicators,
|
|
17
|
+
<img src="docs/architecture-diagram.svg" alt="OpenAlgo Charts architecture: seven layers from the public API down to feeds and data, with 102 built-in plus custom indicators, 51 drawing tools, and a six-tier bundle legend" width="920" />
|
|
18
18
|
|
|
19
19
|
</div>
|
|
20
20
|
|
|
@@ -62,7 +62,7 @@ in front of npm rather than being places you upload to. A chart is one HTML file
|
|
|
62
62
|
```html
|
|
63
63
|
<div id="chart" style="width:100vw;height:100vh"></div>
|
|
64
64
|
<script type="module">
|
|
65
|
-
import { createChart } from 'https://unpkg.com/openalgo-charts@1.
|
|
65
|
+
import { createChart } from 'https://unpkg.com/openalgo-charts@1.9.2/dist/openalgo-charts.mjs';
|
|
66
66
|
const chart = createChart(document.getElementById('chart'), { timezone: 'Asia/Kolkata' });
|
|
67
67
|
chart.addSeries('candlestick').setData(bars);
|
|
68
68
|
</script>
|
|
@@ -79,14 +79,14 @@ Import only what you use. Each tier is a separate bundle that registers into the
|
|
|
79
79
|
|
|
80
80
|
| Import | Contents | Brotli |
|
|
81
81
|
|---|---|---|
|
|
82
|
-
| `openalgo-charts` | Engine, 13 chart types, panes & scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, OpenAlgo feeds | 60.
|
|
82
|
+
| `openalgo-charts` | Engine, 13 chart types, panes & scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, OpenAlgo feeds | 60.9 KB |
|
|
83
83
|
| `openalgo-charts/indicators` | 102 built-in indicators, the `registerIndicator` contract for your own, and the Tier-2 (external-data) contract | 27.3 KB |
|
|
84
|
-
| `openalgo-charts/draw` | 43 drawing tools + a headless drawing controller and clipboard |
|
|
84
|
+
| `openalgo-charts/draw` | 43 drawing tools + a headless drawing controller and clipboard | 15.4 KB |
|
|
85
85
|
| `openalgo-charts/transform` | Heikin Ashi, Renko, Range bars, Line Break, Point & Figure, Kagi | 2.7 KB |
|
|
86
86
|
| `openalgo-charts/profile` | Volume Profile, Market Profile (TPO), Footprint, order flow | 10.7 KB |
|
|
87
87
|
| `openalgo-charts/trade` | Order / position / bracket tools + DOM ladder | 7.6 KB |
|
|
88
88
|
|
|
89
|
-
Everything together is **
|
|
89
|
+
Everything together is **124.47 KB Brotli**. Figures are the measured `size-limit` output. The trade tier is listed as its delta over the base, so loading base + trade costs 68.49 KB.
|
|
90
90
|
|
|
91
91
|
## What's built
|
|
92
92
|
|
|
@@ -118,7 +118,7 @@ const draw = new DrawingController(chart, { magnet: true });
|
|
|
118
118
|
draw.setTool('trend-line'); // the next two clicks place it
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
51 tools. Lines: trend line, ray, extended line, arrow, horizontal line/ray, vertical line, cross line. Shapes: rectangle, rotated rectangle, ellipse, circle, triangle. Paths: path, polyline, arc, curve, double curve. Channels: parallel channel, fib channel. Fibonacci: retracement, extension, time zone, speed fan. Gann: fan, box. Cycles: cyclic lines, time cycles, sine line. Forecasting: long/short position (1:1 from one click, with risk/reward and risk-based sizing), forecast. Measurers: price range, date range, measure. Arrows: mark up, down, left, right. Text and notes: text, price label, callout, flag mark. Annotations: note, balloon, comment, signpost, price note, table. Brushes: brush, highlighter (freehand).
|
|
122
122
|
|
|
123
123
|
Headless by design: no toolbar, no dialogs. Placement with live preview, selection, whole-shape and per-anchor dragging, magnet snap to O/H/L/C, undo/redo (a drag is one step), and persistence. Anchors are `{ time, price }`, never pixels, so they survive zoom and resolve inside collapsed session gaps and past the last bar.
|
|
124
124
|
|
|
@@ -227,13 +227,13 @@ Enforced in CI by [`size-limit`](./.size-limit.json). Nothing is excluded, becau
|
|
|
227
227
|
|
|
228
228
|
| Bundle | Limit | Actual |
|
|
229
229
|
|---|---|---|
|
|
230
|
-
| Base engine | 62 KB | 60.
|
|
231
|
-
| Base + trade | 70 KB | 68.
|
|
230
|
+
| Base engine | 62 KB | 60.88 KB |
|
|
231
|
+
| Base + trade | 70 KB | 68.49 KB |
|
|
232
232
|
| Indicators tier | 30 KB | 27.27 KB |
|
|
233
|
-
| Draw tier |
|
|
233
|
+
| Draw tier | 16 KB | 15.39 KB |
|
|
234
234
|
| Transform tier | 5 KB | 2.66 KB |
|
|
235
235
|
| Profile tier | 11 KB | 10.66 KB |
|
|
236
|
-
| **Everything** | **
|
|
236
|
+
| **Everything** | **126 KB** | **124.47 KB** |
|
|
237
237
|
|
|
238
238
|
## Documentation
|
|
239
239
|
|
|
@@ -273,7 +273,7 @@ cd examples/yfinance && pip install -r requirements.txt && python server.py
|
|
|
273
273
|
```bash
|
|
274
274
|
npm install # install dev toolchain
|
|
275
275
|
npm run typecheck # strict TypeScript check
|
|
276
|
-
npm test # unit tests (vitest) -
|
|
276
|
+
npm test # unit tests (vitest) - 2898 across 143 files
|
|
277
277
|
npm run build # Rollup -> dist/ (minified ESM per tier + types)
|
|
278
278
|
npm run size # size-limit (Brotli) against the budget
|
|
279
279
|
npm run e2e # Playwright Chromium smoke tests
|
|
@@ -290,7 +290,7 @@ npm run verify # typecheck + test + build + size
|
|
|
290
290
|
|
|
291
291
|
## Status & limitations
|
|
292
292
|
|
|
293
|
-
Version **1.
|
|
293
|
+
Version **1.9.2**. All engine build phases are implemented with 2898 unit tests across 143 files.
|
|
294
294
|
|
|
295
295
|
Known gaps, stated plainly:
|
|
296
296
|
|
package/dist/draw/index.d.ts
CHANGED
|
@@ -217,10 +217,150 @@ declare const TEXT: DrawingTool;
|
|
|
217
217
|
* The arrow is what separates it from `polyline`: a path points somewhere.
|
|
218
218
|
*/
|
|
219
219
|
declare const PATH: DrawingTool;
|
|
220
|
+
/**
|
|
221
|
+
* Price label — a pill of the anchored price with a tail pointing at the bar.
|
|
222
|
+
* Reads its value off the anchor, so dragging it re-reads rather than going
|
|
223
|
+
* stale the way a typed-in `text` would.
|
|
224
|
+
*/
|
|
225
|
+
declare const PRICE_LABEL: DrawingTool;
|
|
226
|
+
/**
|
|
227
|
+
* Callout — a text bubble on its own anchor with a tail back to the point it
|
|
228
|
+
* annotates, so the note can sit clear of the price action it refers to.
|
|
229
|
+
*/
|
|
230
|
+
declare const CALLOUT: DrawingTool;
|
|
231
|
+
/** Flag mark — a pennant on a pole at one anchor, for tagging a bar. */
|
|
232
|
+
declare const FLAG_MARK: DrawingTool;
|
|
233
|
+
/**
|
|
234
|
+
* Note — a pin at the bar with its text to the upper right.
|
|
235
|
+
*
|
|
236
|
+
* The pin is the point being annotated and the plate is the annotation, which
|
|
237
|
+
* is why the two are drawn as separate marks joined by a stem rather than as
|
|
238
|
+
* one bubble: the reader needs to see exactly which bar is meant, and a bubble
|
|
239
|
+
* wide enough to hold a sentence covers several.
|
|
240
|
+
*/
|
|
241
|
+
declare const NOTE: DrawingTool;
|
|
242
|
+
/**
|
|
243
|
+
* Balloon — a speech bubble sitting above its anchor, tail pointing down.
|
|
244
|
+
*
|
|
245
|
+
* One anchor rather than the callout's two: a balloon is for saying something
|
|
246
|
+
* *about this bar*, so letting the bubble be dragged away from what it labels
|
|
247
|
+
* would only invite it to drift.
|
|
248
|
+
*/
|
|
249
|
+
declare const BALLOON: DrawingTool;
|
|
250
|
+
/**
|
|
251
|
+
* Comment — a small square-cornered box with a tail off its bottom left.
|
|
252
|
+
*
|
|
253
|
+
* Deliberately plainer than the balloon: a chart that says something at every
|
|
254
|
+
* other bar needs one of these marks to be quiet, and the shape is the only
|
|
255
|
+
* thing distinguishing them once both are the user's own colour.
|
|
256
|
+
*/
|
|
257
|
+
declare const COMMENT: DrawingTool;
|
|
258
|
+
/**
|
|
259
|
+
* Signpost — a post standing on the bar with its plate at the top.
|
|
260
|
+
*
|
|
261
|
+
* The one annotation anchored to *time* rather than to a level: the post is
|
|
262
|
+
* vertical so the plate can clear the price action entirely while the foot
|
|
263
|
+
* still names an exact bar. Useful for events, which happen at a moment and
|
|
264
|
+
* not at a price.
|
|
265
|
+
*/
|
|
266
|
+
declare const SIGNPOST: DrawingTool;
|
|
267
|
+
/**
|
|
268
|
+
* Price note — the anchored price, with the user's text under it.
|
|
269
|
+
*
|
|
270
|
+
* The price is read off the anchor rather than typed, so dragging the note
|
|
271
|
+
* re-reads it. A typed price is a number that was true once, which on a chart
|
|
272
|
+
* is worse than no number at all.
|
|
273
|
+
*/
|
|
274
|
+
declare const PRICE_NOTE: DrawingTool;
|
|
275
|
+
/**
|
|
276
|
+
* Table — rows of text in a grid, anchored top-left.
|
|
277
|
+
*
|
|
278
|
+
* Cells come from `text`: a newline starts a row and a pipe separates columns,
|
|
279
|
+
* so a whole table is one editable string and survives `getState` with no new
|
|
280
|
+
* shape in the drawing model. The first row is drawn as a header because a
|
|
281
|
+
* table on a chart is nearly always labelled.
|
|
282
|
+
*/
|
|
283
|
+
declare const TABLE: DrawingTool;
|
|
284
|
+
declare const ARROW_UP: DrawingTool;
|
|
285
|
+
declare const ARROW_DOWN: DrawingTool;
|
|
286
|
+
declare const ARROW_LEFT: DrawingTool;
|
|
287
|
+
declare const ARROW_RIGHT: DrawingTool;
|
|
220
288
|
declare const BUILTIN_DRAWING_TOOLS: readonly DrawingTool[];
|
|
221
289
|
/** Register every built-in tool. Idempotent; called on tier import. */
|
|
222
290
|
declare function registerBuiltinDrawingTools(): void;
|
|
223
291
|
|
|
292
|
+
/**
|
|
293
|
+
* Glyphs for the drawing tools, as path data.
|
|
294
|
+
*
|
|
295
|
+
* The engine ships no DOM, and this does not change that: an icon here is a
|
|
296
|
+
* string of SVG path commands, not an element. The host still builds its own
|
|
297
|
+
* toolbar, flyouts and rail; what it no longer has to do is draw fifty-one
|
|
298
|
+
* glyphs before it can show them.
|
|
299
|
+
*
|
|
300
|
+
* That was the real cost of leaving them out. Every adopter drew their own set,
|
|
301
|
+
* each drifted on stroke weight, grid and visual density independently, and the
|
|
302
|
+
* result read as fifty-one icons rather than as one set, however carefully any
|
|
303
|
+
* single glyph was made. A shipped set is worth more than a better glyph.
|
|
304
|
+
*
|
|
305
|
+
* # The grid
|
|
306
|
+
*
|
|
307
|
+
* Every glyph is authored to the same constraints, and `tests/draw-icons.test.ts`
|
|
308
|
+
* enforces all of them mechanically, because a set of this size cannot be kept
|
|
309
|
+
* consistent by review:
|
|
310
|
+
*
|
|
311
|
+
* - **24 by 24 viewBox.** One box for every glyph, so a host sets the size once.
|
|
312
|
+
* - **Live area 2 to 22.** A two-unit margin on all sides. Without it, glyphs
|
|
313
|
+
* that happen to reach the edge look larger than their neighbours and the rail
|
|
314
|
+
* reads as ragged.
|
|
315
|
+
* - **Integer coordinates.** With `STROKE` of 2, an orthogonal edge centred on
|
|
316
|
+
* an integer covers exactly two device pixels at 1:1, which is what makes it
|
|
317
|
+
* crisp. Half-unit coordinates were the previous set's crispness bug: at a
|
|
318
|
+
* 1.5 stroke on integers, nothing landed on a pixel boundary at any size.
|
|
319
|
+
* - **One stroke weight.** Three different weights across identically sized
|
|
320
|
+
* boxes is the single most visible tell of a set assembled rather than drawn.
|
|
321
|
+
*
|
|
322
|
+
* # Rendering
|
|
323
|
+
*
|
|
324
|
+
* Crispest at 24px, and at any integer multiple of it. At 18px the 0.75 scale
|
|
325
|
+
* puts a 2-unit stroke on 1.5 device pixels and every edge is anti-aliased
|
|
326
|
+
* across two rows: that is a host sizing choice, not something the path data can
|
|
327
|
+
* fix. Prefer 24, or 12 with a heavier weight.
|
|
328
|
+
*/
|
|
329
|
+
/** The viewBox every glyph is authored in. */
|
|
330
|
+
declare const ICON_VIEWBOX = "0 0 24 24";
|
|
331
|
+
/**
|
|
332
|
+
* Stroke width in viewBox units. Paths carry no presentation attributes, so a
|
|
333
|
+
* host that wants a lighter set overrides this once rather than editing glyphs.
|
|
334
|
+
*/
|
|
335
|
+
declare const ICON_STROKE = 2;
|
|
336
|
+
/** Attributes a host should apply to the `<svg>`, so every set matches. */
|
|
337
|
+
declare const ICON_ATTRS: {
|
|
338
|
+
readonly viewBox: "0 0 24 24";
|
|
339
|
+
readonly fill: "none";
|
|
340
|
+
readonly stroke: "currentColor";
|
|
341
|
+
readonly strokeWidth: 2;
|
|
342
|
+
readonly strokeLinecap: "round";
|
|
343
|
+
readonly strokeLinejoin: "round";
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* Path data by tool id, plus a few keys a host toolbar needs that are not
|
|
347
|
+
* themselves tools (`cursor`, the group headers).
|
|
348
|
+
*
|
|
349
|
+
* Values are the `d` attribute of one `<path>`. Multiple subpaths are joined
|
|
350
|
+
* into the same string rather than split across elements, so a host renders one
|
|
351
|
+
* node per glyph.
|
|
352
|
+
*/
|
|
353
|
+
declare const DRAWING_TOOL_ICONS: Readonly<Record<string, string>>;
|
|
354
|
+
/**
|
|
355
|
+
* The glyph for a tool, or `undefined` when it has none.
|
|
356
|
+
*
|
|
357
|
+
* Undefined rather than a placeholder: a host that renders an empty box has a
|
|
358
|
+
* visible gap to fix, while one handed a question mark ships it.
|
|
359
|
+
*/
|
|
360
|
+
declare function drawingToolIcon(toolId: string): string | undefined;
|
|
361
|
+
/** Every id this set covers, for a host building a palette from it. */
|
|
362
|
+
declare function drawingToolIconIds(): string[];
|
|
363
|
+
|
|
224
364
|
/**
|
|
225
365
|
* One `DrawingLayer` per pane: renders every drawing on it and answers the
|
|
226
366
|
* chart's hit-test. Anchors live in `{ time, price }`, so the layer maps them
|
|
@@ -623,4 +763,4 @@ declare function extendSegment(a: ScreenPoint, b: ScreenPoint, width: number, le
|
|
|
623
763
|
|
|
624
764
|
declare const DRAW_TIER: "draw";
|
|
625
765
|
|
|
626
|
-
export { ARROW, BUILTIN_DRAWING_TOOLS, CROSS_LINE, type ClipboardPort, DRAWING_CLIPBOARD_KEY, DRAWING_CLIPBOARD_VERSION, DRAW_TIER, type DrawContext, type Drawing, type DrawingChartHost, DrawingClipboard, type DrawingClipboardOptions, DrawingController, type DrawingControllerOptions, DrawingLayer, type DrawingPoint, type DrawingStyle, type DrawingTool, ELLIPSE, EXTENDED_LINE, type ExpandContext, 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, clearMemoryClipboard, decodeClipboardPayload, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, drawingShortcuts, encodeClipboardPayload, extendSegment, getDrawingTool, hasDrawingTool, matchDrawingShortcut, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools, sanitizeDrawing, systemClipboard };
|
|
766
|
+
export { ARROW, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, BALLOON, BUILTIN_DRAWING_TOOLS, CALLOUT, COMMENT, CROSS_LINE, type ClipboardPort, DRAWING_CLIPBOARD_KEY, DRAWING_CLIPBOARD_VERSION, DRAWING_TOOL_ICONS, DRAW_TIER, type DrawContext, type Drawing, type DrawingChartHost, DrawingClipboard, type DrawingClipboardOptions, DrawingController, type DrawingControllerOptions, DrawingLayer, type DrawingPoint, type DrawingStyle, type DrawingTool, ELLIPSE, EXTENDED_LINE, type ExpandContext, FIB_EXTENSION, FIB_RETRACEMENT, FLAG_MARK, HORIZONTAL_LINE, HORIZONTAL_RAY, type HitContext, ICON_ATTRS, ICON_STROKE, ICON_VIEWBOX, LONG_POSITION, MEASURE, NOTE, PARALLEL_CHANNEL, PATH, PRICE_LABEL, PRICE_NOTE, RAY, RECTANGLE, SHORT_POSITION, SIGNPOST, type ScreenPoint, type ShortcutEvent, TABLE, TEXT, TREND_LINE, VERTICAL_LINE, clearMemoryClipboard, decodeClipboardPayload, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, drawingShortcuts, drawingToolIcon, drawingToolIconIds, encodeClipboardPayload, extendSegment, getDrawingTool, hasDrawingTool, matchDrawingShortcut, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools, sanitizeDrawing, systemClipboard };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Library version string. Matches package.json (published npm release). */
|
|
2
|
-
declare const VERSION = "1.
|
|
2
|
+
declare const VERSION = "1.9.2";
|
|
3
3
|
/** Returns the current library version. */
|
|
4
4
|
declare function version(): string;
|
|
5
5
|
|
|
@@ -2387,6 +2387,20 @@ interface IndicatorHost {
|
|
|
2387
2387
|
* one to ask for the instrument's own step.
|
|
2388
2388
|
*/
|
|
2389
2389
|
tickSize?(paneIndex: number): number | undefined;
|
|
2390
|
+
/**
|
|
2391
|
+
* Write a number the way the price axis of that pane writes it.
|
|
2392
|
+
*
|
|
2393
|
+
* The legend sits inches from the axis and names the same quantity, so the
|
|
2394
|
+
* two disagreeing is the reading a user has to reconcile themselves. Deriving
|
|
2395
|
+
* the format here from a tick got that wrong twice over: a study pane carries
|
|
2396
|
+
* no tick at all, so a percentage read `0.618` beside an axis saying `0.62`,
|
|
2397
|
+
* and a price pane's tick alone misses the precision floor and the host's own
|
|
2398
|
+
* formatter, so a volume study read seven digits where its axis said `1.20M`.
|
|
2399
|
+
*
|
|
2400
|
+
* Asking the scale removes the second opinion. Optional so a host driving
|
|
2401
|
+
* this module alone still works, falling back to the magnitude ladder.
|
|
2402
|
+
*/
|
|
2403
|
+
formatPrice?(paneIndex: number, value: number): string | undefined;
|
|
2390
2404
|
/** Pin a pane's price scale to a fixed range, or release it with `null`. */
|
|
2391
2405
|
setPaneRange(paneIndex: number, range: {
|
|
2392
2406
|
min: number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function t(t,e,i,n){const s=n.x-i.x,r=n.y-i.y,o=s*s+r*r;if(0===o)return Math.hypot(t-i.x,e-i.y);let l=((t-i.x)*s+(e-i.y)*r)/o;return l=l<0?0:l>1?1:l,Math.hypot(t-(i.x+l*s),e-(i.y+l*r))}function e(t,e,i,n){const s=n.x-i.x,r=n.y-i.y,o=Math.hypot(s,r);return 0===o?Math.hypot(t-i.x,e-i.y):Math.abs(r*(t-i.x)-s*(e-i.y))/o}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 r=1;r<n.length;r++){const o=t(e,i,n[r-1],n[r]);o<s&&(s=o)}return s}function r(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 o(e,i,n,s,o){const l=r(n,s);if(e>=l.x0&&e<=l.x1&&i>=l.y0&&i<=l.y1&&o)return 0;const a=[{x:l.x0,y:l.y0},{x:l.x1,y:l.y0},{x:l.x1,y:l.y1},{x:l.x0,y:l.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 l(t,e,i,n,s){const o=r(i,n),l=(o.x0+o.x1)/2,a=(o.y0+o.y1)/2,c=Math.max(1e-6,(o.x1-o.x0)/2),h=Math.max(1e-6,(o.y1-o.y0)/2),x=(t-l)/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 r=e.x-t.x;if(0===r)return[t,e];const o=(e.y-t.y)/r;return[n?{x:0,y:t.y+(0-t.x)*o}:t,s?{x:i,y:t.y+(i-t.x)*o}: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,r){const o=t.roundRect;"function"==typeof o?o.call(t,e,i,n,s,Math.max(0,Math.min(r,n/2,s/2))):t.rect(e,i,n,s)}const d=new Map;function p(t){d.set(t.id,t)}function u(t){const e=d.get(t);if(void 0===e)throw new Error(`openalgo-charts: unknown drawing tool "${t}"`);return e}function f(t){return d.has(t)}function y(){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 r=g(t.shortcut);if(r.key===e&&r.alt===i&&r.ctrl===n&&r.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:r,rc:o,style:l}=t,a=(l.fontSize??11)*o.dpr;r.save(),r.setLineDash([]),r.font=`${a}px ui-sans-serif, system-ui, sans-serif`,r.textBaseline="middle",r.textAlign="left";const c=r.measureText(e).width;r.globalAlpha=.85,r.fillStyle=o.theme.background,r.fillRect(i-2*o.dpr,n-.75*a,c+4*o.dpr,1.5*a),r.globalAlpha=1,r.fillStyle=s??l.color,r.fillText(e,i,n),r.restore()}function T(t,e,i,n,s,r={}){const{ctx:o,rc:l}=t,a=l.dpr,c=(t.style.fontSize??11)*a;o.save(),o.setLineDash([]),o.globalAlpha=1,o.font=`${c}px ui-sans-serif, system-ui, sans-serif`,o.textBaseline="middle",o.textAlign="left";const d=5*a,p=3*a,u=1.35*c;let f=0;for(const t of e)f=Math.max(f,o.measureText(t).width);const y=f+2*d,g=u*e.length+2*p,m=r.align??"left",b="center"===m?i-y/2:"right"===m?i-y:i,_=r.place??"above",w="above"===_?n-g-4*a:"below"===_?n+4*a:n-g/2;o.beginPath(),x(o,b,w,y,g,3*a),o.fillStyle=s,o.fill(),o.fillStyle=h(s);for(let t=0;t<e.length;t++)o.fillText(e[t],b+d,w+p+u*(t+.5));return o.restore(),g}function P(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 S(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 k(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 L(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 O="#26a69a",D="#ef5350",$=[0,.236,.382,.5,.618,.786,1];function F(i,n,s,r){return{id:i,name:n,points:2,defaultStyle:{extendLeft:s,extendRight:r},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??r);_(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,o)=>{const l=o.drawing.style.extendLeft??s,c=o.drawing.style.extendRight??r;if(l&&c)return e(i,n,o.pts[0],o.pts[1]);const[h,x]=a(o.pts[0],o.pts[1],o.rc.plotWidth,l,c);return t(i,n,h,x)}}}const A={...F("trend-line","Trend Line",!1,!1),shortcut:"Alt+T"},N=F("ray","Ray",!1,!0),I=F("extended-line","Extended Line",!0,!0),C={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])},W={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)},j={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)},z={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))},E={id:"rectangle",name:"Rectangle",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"left",textVAlign:"top",textPosition:"inside"},draw:t=>{const e=r(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)=>o(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},U={id:"ellipse",name:"Ellipse",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"center",textVAlign:"middle",textPosition:"inside"},draw:t=>{const e=r(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),o=Math.max(1,(e.y1-e.y0)/2),l=()=>{t.ctx.beginPath(),t.ctx.ellipse(i,n,s,o,0,0,2*Math.PI)};v(t,()=>{l(),t.ctx.fill()}),_(t),l(),t.ctx.stroke(),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:"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)),r={x:e.x,y:e.y+s},o={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(o.x,o.y),t.ctx.lineTo(r.x,r.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(r.x,r.y),t.ctx.lineTo(o.x,o.y),t.ctx.stroke(),t.ctx.setLineDash([]),it(t,Math.min(e.x,i.x),Math.min(e.y,i.y,r.y,o.y),Math.max(e.x,i.x),Math.max(e.y,i.y,r.y,o.y))},distance:(e,i,n)=>{const[s,r,o]=n.pts,l=o.y-(s.y+.5*(r.y-s.y)),a=t(e,i,s,r),c=t(e,i,{x:s.x,y:s.y+l},{x:r.x,y:r.y+l});return Math.min(a,c)}};function J(t,e,i){return{id:t,name:e,points:i,defaultStyle:{showLabels:!0,levels:[...$],fill:!0,fillOpacity:.06},draw:t=>{const e=t.style.levels??$,n=t.drawing.points,s=2===i?n[0].price:n[2].price,r=n[1].price-n[0].price,o=Math.min(t.pts[0].x,t.pts[i-1].x),l=Math.max(t.pts[0].x,t.pts[i-1].x),a=!0===t.style.extendRight?t.rc.plotWidth*t.rc.dpr:l;_(t);let c=null;for(const i of e){const e=s+r*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=w(t),t.ctx.fillRect(o,Math.min(c,n),a-o,Math.abs(n-c)),t.ctx.restore()),c=n,t.ctx.beginPath(),t.ctx.moveTo(o,n),t.ctx.lineTo(a,n),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,`${(100*i).toFixed(1)}% ${t.formatPrice(e)}`,o+4*t.rc.dpr,n-8*t.rc.dpr)}t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.drawing.style.levels??$,r=n.drawing.points,o=2===i?r[0].price:r[2].price,l=r[1].price-r[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(o+l*t));i<h&&(h=i)}return h}}}const H=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=r(t.pts[0],t.pts[1]),i=t.rc.dpr,n=t.drawing.points,s=n[1].price-n[0].price,o=0!==n[0].price?s/n[0].price*100:0,l=s>=0,a=l?O:D;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(),_(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(),L(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(),L(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),u=Math.abs(Math.round(p-d)),f=l?"+":"",y=[`${f}${t.formatPrice(s)} (${f}${o.toFixed(2)}%)`,`${P(u)} bars, ${k(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&&y.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`:P(t)}(i)}`)}T(t,y,c,Math.max(h,x)+6*i,a,{align:"center",place:"below"})},distance:(t,e,i)=>o(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,r=Math.max(5,Math.round(.08*e.visibleBars)),o=n.time+Math.max(1,e.barSeconds)*r;return i?[n,{time:o,price:n.price+s},{time:o,price:n.price-s}]:[n,{time:o,price:n.price-s},{time:o,price:n.price+s}]},draw:t=>{if(t.drawing.points.length<3||t.pts.length<3)return;const[e,n,s]=t.drawing.points,r=t.rc.dpr,o=Math.min(t.pts[0].x,t.pts[1].x,t.pts[2].x),l=Math.max(t.pts[0].x,t.pts[1].x,t.pts[2].x),a=t.rc.priceScale.priceToY(e.price)*r,c=t.rc.priceScale.priceToY(n.price)*r,h=t.rc.priceScale.priceToY(s.price)*r,x=(e,i,n)=>{t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.13,t.ctx.fillStyle=n,t.ctx.fillRect(o,Math.min(e,i),l-o,Math.abs(i-e)),t.ctx.restore()};x(a,c,O),x(a,h,D),_(t);for(const e of[a,c,h]){const i=Math.round(e)+.5;t.ctx.beginPath(),t.ctx.moveTo(o,i),t.ctx.lineTo(l,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),u=d>0?p/d:0,f=t.style.accountSize??0,y=t.style.risk??0,g=d>0&&f>0?Math.floor(f*y/100/d):0,m=t=>(0!==e.price?t/e.price*100:0).toFixed(3),b=t=>g>0?`, Amount: ${P(g*t)}`:"",w=(o+l)/2;T(t,[`Target: ${t.formatPrice(p)} (${m(p)}%)${b(p)}`],w,c,O,{align:"center",place:c<=a?"above":"below"}),T(t,[`Stop: ${t.formatPrice(d)} (${m(d)}%)${b(d)}`],w,h,D,{align:"center",place:h>=a?"below":"above"}),T(t,[`${i?"Long":"Short"} · Qty: ${g>0?P(g):"—"}`,`Risk/reward ratio: ${u.toFixed(2)}`],w,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 r=i.drawing.points.map(t=>i.rc.priceScale.priceToY(t.price)),o=Math.min(...r),l=Math.max(...r);return e>=o&&e<=l?0:Math.min(Math.abs(e-o),Math.abs(e-l))}}}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 r=n[0];for(let e=1;e<n.length;e++){const o=`${r} ${n[e]}`;t.measureText(o).width>i?(s.push(r),r=n[e]):r=o}s.push(r)}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 r=0;for(const e of s)r=Math.max(r,t.measureText(e).width);const o=n*Q;return{lines:s,width:r+10*i,height:s.length*o+10*i,lineHeight:o}}function it(t,e,i,n,s){const{ctx:r,rc:o,style:l}=t,a=l.text;if(void 0===a||""===a)return;const c=o.dpr,h=(l.fontSize??14)*c,x=6*c;r.save(),r.setLineDash([]),r.font=Z(l,h),r.fillStyle=l.fontColor??l.color,r.textBaseline="top";const d=!0===l.wrap?tt(r,l,Math.max(20*c,n-e-2*x)):a.split("\n"),p=h*Q,u=d.length*p,f=l.textAlign??"left";r.textAlign=f;const y="center"===f?(e+n)/2:"right"===f?n-x:e+x;let g;if("outside"===l.textPosition)g=i-u-x;else{const t=l.textVAlign??"top";g="middle"===t?(i+s-u)/2:"bottom"===t?s-u-x:i+x}for(const t of d)r.fillText(t,y,g),g+=p;r.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,r=et(e,n,s),o=t.pts[0].x,l=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(o,l,r.width,r.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(o,l,r.width,r.height,4*s),e.stroke()),e.font=Z(n,(n.fontSize??13)*s),e.fillStyle=n.color,e.textBaseline="top";const a=n.textAlign??"left";e.textAlign=a;const c="center"===a?o+r.width/2:"right"===a?o+r.width-5*s:o+5*s;let h=l+5*s;for(const t of r.lines)e.fillText(t,c,h),h+=r.lineHeight;e.restore()},distance:(t,e,i)=>{const n=i.drawing.style,s=n.fontSize??13,r=i.pts[0],o=function(){if(void 0!==st)return st;try{st="undefined"==typeof document?null:document.createElement("canvas").getContext("2d")}catch{st=null}return st}(),l=null===o?{width:(n.text??"").length*s*.6+10,height:s*Q+10}:et(o,n,1);return t>=r.x-3&&t<=r.x+l.width+3&&e>=r.y-3&&e<=r.y+l.height+3?0:null}};let st;const rt={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([]),L(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)},ot={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)},lt={id:"rotated-rectangle",name:"Rotated Rectangle",points:3,defaultStyle:{fill:!0,fillOpacity:.12},draw:t=>{if(t.pts.length<3)return;const e=at(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=at(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,r=i.length-1;s<i.length;r=s++){const o=i[s],l=i[r];o.y>e!=l.y>e&&t<(l.x-o.x)*(e-o.y)/(l.y-o.y)+o.x&&(n=!n)}return n}(e,i,s))return 0;let r=1/0;for(let n=0;n<4;n++)r=Math.min(r,t(e,i,s[n],s[(n+1)%4]));return r}};function at(t,e,i){const n=e.x-t.x,s=e.y-t.y,r=Math.hypot(n,s)||1,o=-s/r,l=n/r,a=(i.x-e.x)*o+(i.y-e.y)*l;return[t,e,{x:e.x+o*a,y:e.y+l*a},{x:t.x+o*a,y:t.y+l*a}]}const ct={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,r,o]=i.pts;return s(t,e,function(t,e,i,n,s){const r=[];for(let o=0;o<=s;o++){const l=o/s,a=1-l,c=a*a*a,h=3*a*a*l,x=3*a*l*l,d=l*l*l;r.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 r}(n,r,{x:n.x+o.x-r.x,y:n.y+o.y-r.y},o,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,r=t.rc.plotWidth*t.rc.dpr;_(t),t.ctx.beginPath();for(let i=0;i<=12;i++){const o=Math.round(e.x+n*i)+.5;o<0||o>r||(t.ctx.moveTo(o,0),t.ctx.lineTo(o,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 r=e.x+n*i+n/2;r+s<0||r-s>t.rc.plotWidth*t.rc.dpr||(t.ctx.moveTo(r+s,e.y),t.ctx.arc(r,e.y,s,0,Math.PI,!0))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,r=s.x-n.x;if(!Number.isFinite(r)||Math.abs(r)<1)return null;const o=Math.abs(r)/2;let l=1/0;for(let i=0;i<12;i++){const s=n.x+r*i+r/2;e>n.y+2||(l=Math.min(l,Math.abs(Math.hypot(t-s,e-n.y)-o)))}return Number.isFinite(l)?l: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 r=e/64;s.push({x:t.x+i*r,y:t.y+n*Math.sin(r*Math.PI*2)})}return s}const ut={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=yt(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,r=n.y-30-11;return t>=s&&t<=s+64&&e>=r&&e<=r+22||Math.hypot(t-n.x,e-n.y)<=10?0:null}},ft={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=yt(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,r]=n.pts;return Math.abs(e-r.x)<=60&&Math.abs(i-r.y)<=16?0:t(e,i,s,r)}};function yt(t,e,i,n){const s=t.rc.dpr,r=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.font=`${r}px ui-sans-serif, system-ui, sans-serif`;let o=0;for(const i of e)o=Math.max(o,t.ctx.measureText(i).width);t.ctx.restore();const l=o+14*s,a=1.4*r*e.length+8*s;return{x:i-l/2,y:n-a/2,w:l,h:a}}function gt(t,e,i,n){const s=t.rc.dpr,r=e.x+e.w/2,o=e.y+e.h/2,l=Math.atan2(i.y-o,i.x-r),a=5*s,c=r+Math.cos(l)*(e.w/2-a),h=o+Math.sin(l)*(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(l)*a,h+Math.cos(l)*a),t.ctx.lineTo(c+Math.sin(l)*a,h-Math.cos(l)*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 mt(t,e,i,n){const s=t.rc.dpr,r=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.setLineDash([]),t.ctx.font=`${r}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 o=1.4*r,l=e.y+e.h/2-o*(i.length-1)/2;for(let n=0;n<i.length;n++)t.ctx.fillText(i[n],e.x+e.w/2,l+o*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,r=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*r),t.ctx.lineTo(e.x+.72*s,e.y-n+.5*r),t.ctx.lineTo(e.x+s,e.y-n+.72*r),t.ctx.lineTo(e.x,e.y-n+r),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,r=n>=0,o=r?"#26a69a":"#ef5350",l=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=o,t.ctx.fillRect(l,Math.min(c,h),a-l,Math.abs(h-c)),t.ctx.restore(),_(t),t.ctx.strokeStyle=o,t.ctx.beginPath();for(const e of[c,h])t.ctx.moveTo(l,Math.round(e)+.5),t.ctx.lineTo(a,Math.round(e)+.5);const x=(l+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=r?"+":"";M(t,`${p}${t.formatPrice(n)} (${p}${s.toFixed(2)}%)`,x+6*e,(c+h)/2,o)},distance:(t,e,i)=>o(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,r=t.pts[1].x,o=Math.min(t.pts[0].y,t.pts[1].y),l=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,r),o,Math.abs(r-s),l-o),t.ctx.restore(),_(t),t.ctx.beginPath();for(const e of[s,r])t.ctx.moveTo(Math.round(e)+.5,o),t.ctx.lineTo(Math.round(e)+.5,l);const a=(o+l)/2;t.ctx.moveTo(s,a),t.ctx.lineTo(r,a);const c=r>s?1:-1;t.ctx.moveTo(r-5*e*c,a-4*e),t.ctx.lineTo(r,a),t.ctx.lineTo(r-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);M(t,`${Math.abs(Math.round(x-h))} bars`,(s+r)/2,o-10*e,n)},distance:(t,e,i)=>o(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,r=i[1].price-i[0].price,o=0!==i[0].price?r/i[0].price*100:0,l=r>=0,a=l?"#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(),_(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=l?"+":"";T(t,[t.formatPrice(i[0].price),S(i[0].time)],n.x,n.y,a,{align:"center"}),T(t,[`${h}${t.formatPrice(r)} (${h}${o.toFixed(2)}%) in ${k(i[1].time-i[0].time)}`,`${t.formatPrice(i[1].price)} · ${S(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(l?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,r=Math.hypot(s.x-n.x,s.y-n.y),o=Math.hypot(t-n.x,e-n.y);return!0===i.drawing.style.fill&&o<=r?0:Math.abs(o-r)}},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]])},Pt={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 St={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,r=[];for(let e=0;e<=16;e++){const o=e/16,l=1-o;r.push({x:l*l*t.x+2*l*o*n+o*o*i.x,y:l*l*t.y+2*l*o*s+o*o*i.y})}return r}(i.pts[0],i.pts[1],i.pts[2]))},kt={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,r,o]=i.pts,l=[];for(let t=0;t<=16;t++){const e=t/16,i=1-e;l.push({x:i*i*n.x+2*i*e*r.x+e*e*o.x,y:i*i*n.y+2*i*e*r.y+e*e*o.y})}return s(t,e,l)}};function Lt(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],r=16*e,o=6*e,l=i?1:-1,a=s+2*l*e;t.ctx.beginPath(),t.ctx.moveTo(n,a),t.ctx.lineTo(n-o,a+l*o),t.ctx.lineTo(n-o/2.4,a+l*o),t.ctx.lineTo(n-o/2.4,a+l*r),t.ctx.lineTo(n+o/2.4,a+l*r),t.ctx.lineTo(n+o/2.4,a+l*o),t.ctx.lineTo(n+o,a+l*o),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],r=i?e-s.y:s.y-e;return Math.abs(t-s.x)<=8&&r>=-4&&r<=20?0:null}}}const Ot=Lt("arrow-up","Arrow Up",!0),Dt=Lt("arrow-down","Arrow Down",!1),$t={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:[...$]},draw:t=>{const e=t.style.levels??$,[i,n,s]=t.pts,r=s.x-n.x,o=s.y-n.y;_(t);for(const s of e)t.ctx.beginPath(),t.ctx.moveTo(i.x+r*s,i.y+o*s),t.ctx.lineTo(n.x+r*s,n.y+o*s),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,`${(100*s).toFixed(1)}%`,n.x+r*s+4*t.rc.dpr,n.y+o*s);t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??$,[r,o,l]=n.pts;let a=1/0;for(const n of s){const s=t(e,i,{x:r.x+(l.x-o.x)*n,y:r.y+(l.y-o.y)*n},{x:o.x+(l.x-o.x)*n,y:o.y+(l.y-o.y)*n});s<a&&(a=s)}return a}},At=[0,1,2,3,5,8,13,21,34,55],Nt={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,r=t.rc.plotWidth*s;_(t);for(const i of At){const o=e.x+n*i;o<-10||o>r+10||(t.ctx.beginPath(),t.ctx.moveTo(Math.round(o)+.5,0),t.ctx.lineTo(Math.round(o)+.5,t.rc.plotHeight*s),t.ctx.stroke(),!1!==t.style.showLabels&&M(t,String(i),o+3*s,12*s))}t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,r=s.x-n.x;if(Math.abs(r)<.5)return null;let o=1/0;for(const e of At)o=Math.min(o,Math.abs(t-(n.x+r*e)));return o}},It=[.236,.382,.5,.618,.786,1],Ct={id:"fib-fan",name:"Fib Speed Fan",points:2,defaultStyle:{showLabels:!0,levels:[...It]},draw:t=>{const e=t.style.levels??It,[i,n]=t.pts,s=t.rc.dpr,r=t.rc.plotWidth*s;_(t);for(const o of e){const e=a(i,{x:n.x,y:i.y+(n.y-i.y)*o},r,!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*o).toFixed(1)}%`,n.x+4*s,i.y+(n.y-i.y)*o)}t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??It,[r,o]=n.pts;let l=1/0;for(const c of s)l=Math.min(l,t(e,i,r,a(r,{x:o.x,y:r.y+(o.y-r.y)*c},n.rc.plotWidth,!1,!0)[1]));return l}},Wt=[[1,.125],[1,.25],[1,.5],[1,1],[.5,1],[.25,1],[.125,1]],Rt=[A,N,I,C,W,R,j,z,E,U,B,H,Y,K,G,vt,V,_t,wt,Mt,Tt,Pt,St,kt,lt,ct,Ot,Dt,$t,ot,Ft,Nt,Ct,{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,r=i.x-e.x,o=i.y-e.y;if(!(Math.abs(r)<.5)){_(t);for(const[i,n]of Wt){const l=a(e,{x:e.x+r*i,y:e.y+o*n},s,!1,!0)[1];t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(l.x,l.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,r]=n.pts,o=r.x-s.x,l=r.y-s.y;let c=1/0;for(const[r,h]of Wt)c=Math.min(c,t(e,i,s,a(s,{x:s.x+o*r,y:s.y+l*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=r(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 r=Math.round(e.x0+i*s/8)+.5,o=Math.round(e.y0+n*s/8)+.5;t.ctx.moveTo(r,e.y0),t.ctx.lineTo(r,e.y1),t.ctx.moveTo(e.x0,o),t.ctx.lineTo(e.x1,o)}t.ctx.moveTo(e.x0,e.y1),t.ctx.lineTo(e.x1,e.y0),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>o(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},ht,xt,dt,nt,rt,ut,ft,bt];let jt=!1;function zt(){if(!jt){jt=!0;for(const t of Rt)p(t)}}function Et(t,e){return f(t)&&!0===u(t).freehand&&e>2?[0,e-1]:Array.from({length:e},(t,e)=>e)}class Ut{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||!f(n.tool))continue;const i=u(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 r={color:n.style.color??e.theme.lineColor,lineWidth:n.style.lineWidth??1.5,...n.style},o=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*o,y:t.y*o})),style:{...r,color:r.color,lineWidth:r.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 r of Et(n,i.length)){const n=i[r];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 Et(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 r=this._drawings[s];if(!1===r.visible||!0===r.locked||!f(r.tool))continue;const o=u(r.tool);if(r.points.length<Math.max(1,o.points))continue;const l=o.distance(t,e,{pts:this._points(i,r),drawing:r,rc:i});null===l||!Number.isFinite(l)||l>6||(null===n||l<n.distance)&&(n={id:r.id,distance:l})}return null===n?null:{externalId:`draw:${n.id}`,zOrder:"top",distance:n.distance,cursor:"move",draggable:!0}}}const Bt="openalgo-charts/drawings",Jt=1;let Ht=null;function Yt(){Ht=null}function Vt(){const t=globalThis.navigator,e=t?.clipboard;return void 0===e||"function"!=typeof e.writeText||"function"!=typeof e.readText?null:e}function qt(t){return JSON.stringify({[Bt]:{version:1,drawings:t.map(t=>({tool:t.tool,points:t.points.map(t=>({time:t.time,price:t.price})),style:t.style??{},paneIndex:t.paneIndex,...void 0===t.locked?{}:{locked:t.locked},...void 0===t.visible?{}:{visible:t.visible}}))}})}const Kt=t=>"object"==typeof t&&null!==t&&!Array.isArray(t),Gt=t=>"number"==typeof t&&Number.isFinite(t);function Qt(t){if(!Kt(t))return null;if("string"!=typeof t.tool||!f(t.tool))return null;const e=function(t){if(!Array.isArray(t)||0===t.length||t.length>2e4)return null;const e=[];for(const i of t){if(!Kt(i)||!Gt(i.time)||!Gt(i.price))return null;e.push({time:i.time,price:i.price})}return e}(t.points);if(null===e)return null;const i=function(t){if(void 0===t)return{};if(!Kt(t))return null;const e={};let i=0;for(const[n,s]of Object.entries(t))if("__proto__"!==n&&"constructor"!==n&&"prototype"!==n){if(++i>64)return null;if("string"==typeof s){if(s.length>4096)return null;e[n]=s}else if("boolean"==typeof s)e[n]=s;else if(Gt(s))e[n]=s;else if(Array.isArray(s)){if(s.length>64||!s.every(Gt))return null;e[n]=s.slice()}}return e}(t.style);if(null===i)return null;const n=void 0===t.paneIndex?0:t.paneIndex;return!Gt(n)||n<0||!Number.isInteger(n)||void 0!==t.locked&&"boolean"!=typeof t.locked||void 0!==t.visible&&"boolean"!=typeof t.visible?null:{tool:t.tool,points:e,style:i,paneIndex:n,...void 0===t.locked?{}:{locked:t.locked},...void 0===t.visible?{}:{visible:t.visible}}}function Xt(t){if("string"!=typeof t||0===t.length)return null;let e;try{e=JSON.parse(t)}catch{return null}if(!Kt(e))return null;const i=e[Bt];if(!Kt(i))return null;if(!Gt(i.version)||i.version<1||i.version>1)return null;const n=i.drawings;if(!Array.isArray(n)||0===n.length||n.length>512)return null;const s=[];for(const t of n){const e=Qt(t);if(null===e)return null;s.push(e)}return s}class Zt{constructor(t={}){Object.defineProperty(this,"_port",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_fallback",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_lastError",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._port=void 0===t.port?Vt():t.port,this._fallback=t.fallbackToMemory??!0}setPort(t){this._port=t}setFallbackToMemory(t){this._fallback=t}lastError(){return this._lastError}async write(t){if(0===t.length)return!1;let e;try{e=qt(t)}catch(t){return this._lastError=String(t),!1}this._lastError=null;let i=!1;if(null!==this._port)try{await this._port.writeText(e),i=!0}catch(t){this._lastError=String(t)}else this._lastError="openalgo-charts: no system clipboard available";return this._fallback?(Ht=e,!0):i}async read(){if(this._lastError=null,null!==this._port)try{const t=Xt(await this._port.readText());if(null!==t)return t}catch(t){this._lastError=String(t)}return this._fallback?Xt(Ht):null}}let te=1;class ee{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,"_clipboard",{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,pasteOffsetBars:e.pasteOffsetBars??2,pasteOffsetPixels:e.pasteOffsetPixels??16,defaultStyle:e.defaultStyle??{}},this._clipboard=new Zt({...void 0===e.clipboard?{}:{port:e.clipboard},...void 0===e.clipboardFallbackToMemory?{}:{fallbackToMemory:e.clipboardFallbackToMemory}}),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&&!f(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){const{clipboard:e,...i}=t;this._opts={...this._opts,...i,defaultStyle:t.defaultStyle??this._opts.defaultStyle},void 0!==e&&this._clipboard.setPort(e)}clipboard(){return this._clipboard}drawings(){return this._drawings}get(t){return this._drawings.find(e=>e.id===t)}add(t){this._pushUndo();const e=this._insert(t);return this._sync(),this._chart.emit("draw:add",{drawing:e}),e}_insert(t){const e=u(t.tool),i={...t,id:t.id??"d"+te++,style:{...this._opts.defaultStyle,...e.defaultStyle,...t.style}};return this._drawings.push(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}async copy(t){const e=this._targets(t);if(0===e.length)return!1;const i=await this._clipboard.write(e);return i&&this._chart.emit("draw:copy",{drawings:e.map(t=>({...t,points:t.points.map(t=>({...t})),style:{...t.style}}))}),i}async cut(t){const e=this._targets(t);if(0===e.length)return!1;if(!await this._clipboard.write(e))return!1;const i=new Set(e.map(t=>t.id)),n=this._drawings.filter(t=>i.has(t.id));if(0===n.length)return!1;this._pushUndo(),this._drawings=this._drawings.filter(t=>!i.has(t.id)),null!==this._selected&&i.has(this._selected)&&(this._selected=null),this._sync();for(const t of n)this._chart.emit("draw:remove",{drawing:t});return this._chart.emit("draw:cut",{drawings:n}),!0}async paste(){const t=await this._clipboard.read();if(null===t||0===t.length)return[];for(const e of t)if(!f(e.tool))return[];const e=t.map(t=>{const e=this._clampPane(t.paneIndex);return{...t,paneIndex:e,points:this._offsetPoints(t.points,e)}});this._pushUndo();const i=e.map(t=>this._insert(t));this._sync();for(const t of i)this._chart.emit("draw:add",{drawing:t});return this._chart.emit("draw:paste",{drawings:i}),this.select(i[i.length-1].id),i}_targets(t){if(null==t){const t=null===this._selected?void 0:this.get(this._selected);return void 0===t?[]:[t]}const e="string"==typeof t?[t]:t,i=[];for(const t of e){const e=this.get(t);void 0!==e&&i.push(e)}return i}_clampPane(t){const e=this._chart.panes;if(void 0===e)return t;const i=e.call(this._chart).length;return 0===i?0:Math.min(t,i-1)}_offsetPoints(t,e){const i=this._barSeconds()*this._opts.pasteOffsetBars,n=this._opts.pasteOffsetPixels;return t.map(t=>({time:t.time+i,price:this._offsetPrice(t.price,e,n)}))}_offsetPrice(t,e,i){if(0===i)return t;const n=this._chart.priceToCoordinate,s=this._chart.coordinateToPrice;if(void 0===n||void 0===s)return t;const r=n.call(this._chart,t,e);if(null===r||!Number.isFinite(r))return t;const o=s.call(this._chart,r+i,e);return null!==o&&Number.isFinite(o)?o:t}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.getVisibleLogicalRange(),n=null===i?60:Math.max(1,i.to-i.from);return t.expand(e,{barSeconds:this._barSeconds(),visibleBars:n})}_barSeconds(){const t=this._chart.dataLayer,e=t.baseIndex,i=e>0?t.indexToTime(e-1):void 0,n=e>=0?t.indexToTime(e):void 0;return void 0!==i&&void 0!==n&&n>i?n-i:60}_isFreehand(){return null!==this._tool&&!0===u(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=u(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=u(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=u(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 r=this._dragStart;if(null===s){const e=t.time-r.from.time,i=t.price-r.from.price;n.points=r.points.map(t=>({time:t.time+e,price:t.price+i}))}else s>=0&&s<n.points.length&&(n.points=r.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 Ut,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 ie="draw";zt();export{C as ARROW,Rt as BUILTIN_DRAWING_TOOLS,z as CROSS_LINE,Bt as DRAWING_CLIPBOARD_KEY,Jt as DRAWING_CLIPBOARD_VERSION,ie as DRAW_TIER,Zt as DrawingClipboard,ee as DrawingController,Ut as DrawingLayer,U as ELLIPSE,I as EXTENDED_LINE,Y as FIB_EXTENSION,H as FIB_RETRACEMENT,W as HORIZONTAL_LINE,R as HORIZONTAL_RAY,K as LONG_POSITION,V as MEASURE,B as PARALLEL_CHANNEL,rt as PATH,N as RAY,E as RECTANGLE,G as SHORT_POSITION,nt as TEXT,A as TREND_LINE,j as VERTICAL_LINE,Yt as clearMemoryClipboard,Xt as decodeClipboardPayload,l as distToEllipse,e as distToLine,s as distToPolyline,o as distToRect,t as distToSegment,b as drawingShortcuts,qt as encodeClipboardPayload,a as extendSegment,u as getDrawingTool,f as hasDrawingTool,m as matchDrawingShortcut,r as rectOf,zt as registerBuiltinDrawingTools,p as registerDrawingTool,y as registeredDrawingTools,Qt as sanitizeDrawing,Vt as systemClipboard};
|
|
1
|
+
function t(t,e,i,n){const s=n.x-i.x,l=n.y-i.y,o=s*s+l*l;if(0===o)return Math.hypot(t-i.x,e-i.y);let r=((t-i.x)*s+(e-i.y)*l)/o;return r=r<0?0:r>1?1:r,Math.hypot(t-(i.x+r*s),e-(i.y+r*l))}function e(t,e,i,n){const s=n.x-i.x,l=n.y-i.y,o=Math.hypot(s,l);return 0===o?Math.hypot(t-i.x,e-i.y):Math.abs(l*(t-i.x)-s*(e-i.y))/o}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 l=1;l<n.length;l++){const o=t(e,i,n[l-1],n[l]);o<s&&(s=o)}return s}function l(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 o(e,i,n,s,o){const r=l(n,s);if(e>=r.x0&&e<=r.x1&&i>=r.y0&&i<=r.y1&&o)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 o=l(i,n),r=(o.x0+o.x1)/2,c=(o.y0+o.y1)/2,a=Math.max(1e-6,(o.x1-o.x0)/2),h=Math.max(1e-6,(o.y1-o.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 l=e.x-t.x;if(0===l)return[t,e];const o=(e.y-t.y)/l;return[n?{x:0,y:t.y+(0-t.x)*o}:t,s?{x:i,y:t.y+(i-t.x)*o}: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,l){const o=t.roundRect;"function"==typeof o?o.call(t,e,i,n,s,Math.max(0,Math.min(l,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 l=g(t.shortcut);if(l.key===e&&l.alt===i&&l.ctrl===n&&l.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 M(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 _(t,e,i,n,s){const{ctx:l,rc:o,style:r}=t,c=(r.fontSize??11)*o.dpr;l.save(),l.setLineDash([]),l.font=`${c}px ui-sans-serif, system-ui, sans-serif`,l.textBaseline="middle",l.textAlign="left";const a=l.measureText(e).width;l.globalAlpha=.85,l.fillStyle=o.theme.background,l.fillRect(i-2*o.dpr,n-.75*c,a+4*o.dpr,1.5*c),l.globalAlpha=1,l.fillStyle=s??r.color,l.fillText(e,i,n),l.restore()}function T(t,e,i,n,s,l={}){const{ctx:o,rc:r}=t,c=r.dpr,a=(t.style.fontSize??11)*c;o.save(),o.setLineDash([]),o.globalAlpha=1,o.font=`${a}px ui-sans-serif, system-ui, sans-serif`,o.textBaseline="middle",o.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,o.measureText(t).width);const f=u+2*d,g=y*e.length+2*p,m=l.align??"left",b="center"===m?i-f/2:"right"===m?i-f:i,M=l.place??"above",w="above"===M?n-g-4*c:"below"===M?n+4*c:n-g/2;o.beginPath(),x(o,b,w,f,g,3*c),o.fillStyle=s,o.fill(),o.fillStyle=h(s);for(let t=0;t<e.length;t++)o.fillText(e[t],b+d,w+p+y*(t+.5));return o.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 k(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 L(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 O="#26a69a",A="#ef5350",D=[0,.236,.382,.5,.618,.786,1];function $(i,n,s,l){return{id:i,name:n,points:2,defaultStyle:{extendLeft:s,extendRight:l},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??l);M(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,o)=>{const r=o.drawing.style.extendLeft??s,a=o.drawing.style.extendRight??l;if(r&&a)return e(i,n,o.pts[0],o.pts[1]);const[h,x]=c(o.pts[0],o.pts[1],o.rc.plotWidth,r,a);return t(i,n,h,x)}}}const z={...$("trend-line","Trend Line",!1,!1),shortcut:"Alt+T"},F=$("ray","Ray",!1,!0),C=$("extended-line","Extended Line",!0,!0),N={id:"arrow",name:"Arrow",points:2,draw:t=>{const[e,i]=t.pts;M(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])},W={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;M(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)},I={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;M(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)},H={id:"vertical-line",name:"Vertical Line",points:1,shortcut:"Alt+V",draw:t=>{const e=Math.round(t.pts[0].x)+.5;M(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)},R={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;M(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))},j={id:"rectangle",name:"Rectangle",points:2,defaultStyle:{fill:!0,fontSize:14,textAlign:"left",textVAlign:"top",textPosition:"inside"},draw:t=>{const e=l(t.pts[0],t.pts[1]);v(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),M(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)=>o(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=l(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),o=Math.max(1,(e.y1-e.y0)/2),r=()=>{t.ctx.beginPath(),t.ctx.ellipse(i,n,s,o,0,0,2*Math.PI)};v(t,()=>{r(),t.ctx.fill()}),M(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)},E={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)),l={x:e.x,y:e.y+s},o={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(o.x,o.y),t.ctx.lineTo(l.x,l.y),t.ctx.closePath(),t.ctx.fill()}),M(t),t.ctx.beginPath(),t.ctx.moveTo(e.x,e.y),t.ctx.lineTo(i.x,i.y),t.ctx.moveTo(l.x,l.y),t.ctx.lineTo(o.x,o.y),t.ctx.stroke(),t.ctx.setLineDash([]),it(t,Math.min(e.x,i.x),Math.min(e.y,i.y,l.y,o.y),Math.max(e.x,i.x),Math.max(e.y,i.y,l.y,o.y))},distance:(e,i,n)=>{const[s,l,o]=n.pts,r=o.y-(s.y+.5*(l.y-s.y)),c=t(e,i,s,l),a=t(e,i,{x:s.x,y:s.y+r},{x:l.x,y:l.y+r});return Math.min(c,a)}};function U(t,e,i){return{id:t,name:e,points:i,defaultStyle:{showLabels:!0,levels:[...D],fill:!0,fillOpacity:.06},draw:t=>{const e=t.style.levels??D,n=t.drawing.points,s=2===i?n[0].price:n[2].price,l=n[1].price-n[0].price,o=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;M(t);let a=null;for(const i of e){const e=s+l*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(o,Math.min(a,n),c-o,Math.abs(n-a)),t.ctx.restore()),a=n,t.ctx.beginPath(),t.ctx.moveTo(o,n),t.ctx.lineTo(c,n),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,`${(100*i).toFixed(1)}% ${t.formatPrice(e)}`,o+4*t.rc.dpr,n-8*t.rc.dpr)}t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.drawing.style.levels??D,l=n.drawing.points,o=2===i?l[0].price:l[2].price,r=l[1].price-l[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(o+r*t));i<h&&(h=i)}return h}}}const J=U("fib-retracement","Fib Retracement",2),V=U("fib-extension","Fib Extension",3),Y={id:"measure",name:"Measure",points:2,defaultStyle:{fill:!0,showLabels:!0,fillOpacity:.14},draw:t=>{const e=l(t.pts[0],t.pts[1]),i=t.rc.dpr,n=t.drawing.points,s=n[1].price-n[0].price,o=0!==n[0].price?s/n[0].price*100:0,r=s>=0,c=r?O:A;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(),M(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(),L(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(),L(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}${o.toFixed(2)}%)`,`${S(y)} bars, ${k(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)=>o(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,l=Math.max(5,Math.round(.08*e.visibleBars)),o=n.time+Math.max(1,e.barSeconds)*l;return i?[n,{time:o,price:n.price+s},{time:o,price:n.price-s}]:[n,{time:o,price:n.price-s},{time:o,price:n.price+s}]},draw:t=>{if(t.drawing.points.length<3||t.pts.length<3)return;const[e,n,s]=t.drawing.points,l=t.rc.dpr,o=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)*l,a=t.rc.priceScale.priceToY(n.price)*l,h=t.rc.priceScale.priceToY(s.price)*l,x=(e,i,n)=>{t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.13,t.ctx.fillStyle=n,t.ctx.fillRect(o,Math.min(e,i),r-o,Math.abs(i-e)),t.ctx.restore()};x(c,a,O),x(c,h,A),M(t);for(const e of[c,a,h]){const i=Math.round(e)+.5;t.ctx.beginPath(),t.ctx.moveTo(o,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=(o+r)/2;T(t,[`Target: ${t.formatPrice(p)} (${m(p)}%)${b(p)}`],w,a,O,{align:"center",place:a<=c?"above":"below"}),T(t,[`Stop: ${t.formatPrice(d)} (${m(d)}%)${b(d)}`],w,h,A,{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 l=i.drawing.points.map(t=>i.rc.priceScale.priceToY(t.price)),o=Math.min(...l),r=Math.max(...l);return e>=o&&e<=r?0:Math.min(Math.abs(e-o),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 l=n[0];for(let e=1;e<n.length;e++){const o=`${l} ${n[e]}`;t.measureText(o).width>i?(s.push(l),l=n[e]):l=o}s.push(l)}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 l=0;for(const e of s)l=Math.max(l,t.measureText(e).width);const o=n*Q;return{lines:s,width:l+10*i,height:s.length*o+10*i,lineHeight:o}}function it(t,e,i,n,s){const{ctx:l,rc:o,style:r}=t,c=r.text;if(void 0===c||""===c)return;const a=o.dpr,h=(r.fontSize??14)*a,x=6*a;l.save(),l.setLineDash([]),l.font=Z(r,h),l.fillStyle=r.fontColor??r.color,l.textBaseline="top";const d=!0===r.wrap?tt(l,r,Math.max(20*a,n-e-2*x)):c.split("\n"),p=h*Q,y=d.length*p,u=r.textAlign??"left";l.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)l.fillText(t,f,g),g+=p;l.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,l=et(e,n,s),o=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(o,r,l.width,l.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(o,r,l.width,l.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?o+l.width/2:"right"===c?o+l.width-5*s:o+5*s;let h=r+5*s;for(const t of l.lines)e.fillText(t,a,h),h+=l.lineHeight;e.restore()},distance:(t,e,i)=>{const n=i.drawing.style,s=n.fontSize??13,l=i.pts[0],o=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===o?{width:(n.text??"").length*s*.6+10,height:s*Q+10}:et(o,n,1);return t>=l.x-3&&t<=l.x+r.width+3&&e>=l.y-3&&e<=l.y+r.height+3?0:null}};let st;const lt={id:"path",name:"Path",points:0,draw:t=>{if(!(t.pts.length<2)){M(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([]),L(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)},ot={id:"brush",name:"Brush",points:0,freehand:!0,defaultStyle:{lineWidth:2},draw:t=>{if(!(t.pts.length<2)){M(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()),M(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,l=i.length-1;s<i.length;l=s++){const o=i[s],r=i[l];o.y>e!=r.y>e&&t<(r.x-o.x)*(e-o.y)/(r.y-o.y)+o.x&&(n=!n)}return n}(e,i,s))return 0;let l=1/0;for(let n=0;n<4;n++)l=Math.min(l,t(e,i,s[n],s[(n+1)%4]));return l}};function ct(t,e,i){const n=e.x-t.x,s=e.y-t.y,l=Math.hypot(n,s)||1,o=-s/l,r=n/l,c=(i.x-e.x)*o+(i.y-e.y)*r;return[t,e,{x:e.x+o*c,y:e.y+r*c},{x:t.x+o*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;M(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,l,o]=i.pts;return s(t,e,function(t,e,i,n,s){const l=[];for(let o=0;o<=s;o++){const r=o/s,c=1-r,a=c*c*c,h=3*c*c*r,x=3*c*r*r,d=r*r*r;l.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 l}(n,l,{x:n.x+o.x-l.x,y:n.y+o.y-l.y},o,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,l=t.rc.plotWidth*t.rc.dpr;M(t),t.ctx.beginPath();for(let i=0;i<=12;i++){const o=Math.round(e.x+n*i)+.5;o<0||o>l||(t.ctx.moveTo(o,0),t.ctx.lineTo(o,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;M(t),t.ctx.beginPath();for(let i=0;i<12;i++){const l=e.x+n*i+n/2;l+s<0||l-s>t.rc.plotWidth*t.rc.dpr||(t.ctx.moveTo(l+s,e.y),t.ctx.arc(l,e.y,s,0,Math.PI,!0))}t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,l=s.x-n.x;if(!Number.isFinite(l)||Math.abs(l)<1)return null;const o=Math.abs(l)/2;let r=1/0;for(let i=0;i<12;i++){const s=n.x+l*i+l/2;e>n.y+2||(r=Math.min(r,Math.abs(Math.hypot(t-s,e-n.y)-o)))}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){M(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 l=e/64;s.push({x:t.x+i*l,y:t.y+n*Math.sin(l*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,l=n.y-30-11;return t>=s&&t<=s+64&&e>=l&&e<=l+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,l]=n.pts;return Math.abs(e-l.x)<=60&&Math.abs(i-l.y)<=16?0:t(e,i,s,l)}};function ft(t,e,i,n){const s=t.rc.dpr,l=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.font=`${l}px ui-sans-serif, system-ui, sans-serif`;let o=0;for(const i of e)o=Math.max(o,t.ctx.measureText(i).width);t.ctx.restore();const r=o+14*s,c=1.4*l*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,l=e.x+e.w/2,o=e.y+e.h/2,r=Math.atan2(i.y-o,i.x-l),c=5*s,a=l+Math.cos(r)*(e.w/2-c),h=o+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,l=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.setLineDash([]),t.ctx.font=`${l}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 o=1.4*l,r=e.y+e.h/2-o*(i.length-1)/2;for(let n=0;n<i.length;n++)t.ctx.fillText(i[n],e.x+e.w/2,r+o*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,l=11*i;M(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*l),t.ctx.lineTo(e.x+.72*s,e.y-n+.5*l),t.ctx.lineTo(e.x+s,e.y-n+.72*l),t.ctx.lineTo(e.x,e.y-n+l),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}};function Mt(t,e){const i=t.style.text;return(void 0===i||""===i?e:i).split("\n")}function wt(t,e,i,n){const s=t.rc.dpr,l=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.font=`${l}px ui-sans-serif, system-ui, sans-serif`;let o=0;for(const i of e)o=Math.max(o,t.ctx.measureText(i).width);return t.ctx.restore(),{x:i,y:n,w:o+16*s,h:1.45*l*e.length+10*s}}function vt(t,e,i,n=6){const s=t.rc.dpr,l=(t.style.fontSize??12)*s;t.ctx.save(),t.ctx.setLineDash([]),t.ctx.globalAlpha=t.style.fillOpacity??1,t.ctx.fillStyle=t.style.backgroundColor??t.style.color,t.ctx.beginPath(),x(t.ctx,e.x,e.y,e.w,e.h,n*s),t.ctx.fill(),t.ctx.globalAlpha=1,!0===t.style.border&&(t.ctx.strokeStyle=t.style.borderColor??t.style.color,t.ctx.lineWidth=Math.max(1,t.style.lineWidth*s),t.ctx.stroke()),t.ctx.font=`${l}px ui-sans-serif, system-ui, sans-serif`,t.ctx.textAlign="left",t.ctx.textBaseline="middle",t.ctx.fillStyle=t.style.fontColor??h(t.style.backgroundColor??t.style.color);const o=1.45*l,r=e.y+e.h/2-o*(i.length-1)/2;for(let n=0;n<i.length;n++)t.ctx.fillText(i[n],e.x+8*s,r+o*n);t.ctx.restore()}function _t(t,e,i,n,s,l){return t>=i&&t<=i+s&&e>=n&&e<=n+l?0:null}function Tt(t,e){return{w:120,h:1.45*(t.fontSize??12)*Math.max(1,e)+10}}const St=(t,e)=>(void 0===t.text||""===t.text?e:t.text).split("\n").length,Pt={id:"note",name:"Note",points:1,defaultStyle:{text:"Note",fontSize:12,fillOpacity:.95},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=Mt(t,"Note"),s=wt(t,n,i.x+16*e,i.y-34*e);t.ctx.save(),t.ctx.setLineDash([]),t.ctx.strokeStyle=t.style.color,t.ctx.lineWidth=Math.max(1,t.style.lineWidth*e),t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(s.x,s.y+s.h),t.ctx.stroke(),t.ctx.fillStyle=t.style.color,t.ctx.beginPath(),t.ctx.arc(i.x,i.y,3.5*e,0,2*Math.PI),t.ctx.fill(),t.ctx.restore(),vt(t,s,n)},distance:(t,e,i)=>{const n=i.pts[0],s=Tt(i.drawing.style,St(i.drawing.style,"Note")),l=_t(t,e,n.x+16,n.y-34,s.w,s.h);return null!==l?l:Math.hypot(t-n.x,e-n.y)<=8?0:null}},kt={id:"balloon",name:"Balloon",points:1,defaultStyle:{text:"Balloon",fontSize:12,fillOpacity:.95},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=Mt(t,"Balloon"),s=wt(t,n,0,0),l={x:i.x-s.w/2,y:i.y-s.h-12*e,w:s.w,h:s.h};t.ctx.save(),t.ctx.setLineDash([]),t.ctx.globalAlpha=t.style.fillOpacity??.95,t.ctx.fillStyle=t.style.backgroundColor??t.style.color,t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x-6*e,l.y+l.h),t.ctx.lineTo(i.x+6*e,l.y+l.h),t.ctx.closePath(),t.ctx.fill(),t.ctx.restore(),vt(t,l,n,8)},distance:(t,e,i)=>{const n=i.pts[0],s=Tt(i.drawing.style,St(i.drawing.style,"Balloon")),l=_t(t,e,n.x-s.w/2,n.y-s.h-12,s.w,s.h);return null!==l?l:Math.hypot(t-n.x,e-n.y)<=8?0:null}},Lt={id:"comment",name:"Comment",points:1,defaultStyle:{text:"Comment",fontSize:11,fillOpacity:.92},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=Mt(t,"Comment"),s=wt(t,n,0,0),l={x:i.x+8*e,y:i.y-s.h-10*e,w:s.w,h:s.h};t.ctx.save(),t.ctx.setLineDash([]),t.ctx.globalAlpha=t.style.fillOpacity??.92,t.ctx.fillStyle=t.style.backgroundColor??t.style.color,t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(l.x,l.y+l.h-5*e),t.ctx.lineTo(l.x+10*e,l.y+l.h),t.ctx.closePath(),t.ctx.fill(),t.ctx.restore(),vt(t,l,n,3)},distance:(t,e,i)=>{const n=i.pts[0],s=Tt(i.drawing.style,St(i.drawing.style,"Comment")),l=_t(t,e,n.x+8,n.y-s.h-10,s.w,s.h);return null!==l?l:Math.hypot(t-n.x,e-n.y)<=8?0:null}},Ot={id:"signpost",name:"Signpost",points:1,defaultStyle:{text:"Event",fontSize:11,fillOpacity:.95},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=34*e,s=Mt(t,"Event"),l=wt(t,s,0,0);t.ctx.save(),t.ctx.setLineDash([]),t.ctx.strokeStyle=t.style.color,t.ctx.lineWidth=Math.max(1,t.style.lineWidth*e),t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(i.x,i.y-n),t.ctx.stroke(),t.ctx.fillStyle=t.style.color,t.ctx.beginPath(),t.ctx.arc(i.x,i.y,3*e,0,2*Math.PI),t.ctx.fill(),t.ctx.restore(),vt(t,{x:i.x-l.w/2,y:i.y-n-l.h,w:l.w,h:l.h},s,4)},distance:(t,e,i)=>{const n=i.pts[0],s=Tt(i.drawing.style,St(i.drawing.style,"Event")),l=_t(t,e,n.x-s.w/2,n.y-34-s.h,s.w,s.h);return null!==l?l:Math.abs(t-n.x)<=5&&e>=n.y-34&&e<=n.y+4?0:null}},At={id:"price-note",name:"Price Note",points:1,defaultStyle:{text:"Note",fontSize:11,fillOpacity:.95},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=[t.formatPrice(t.drawing.points[0].price),...Mt(t,"Note")],s=wt(t,n,i.x+14*e,i.y-12*e);t.ctx.save(),t.ctx.setLineDash([]),t.ctx.strokeStyle=t.style.color,t.ctx.lineWidth=Math.max(1,t.style.lineWidth*e),t.ctx.beginPath(),t.ctx.moveTo(i.x,i.y),t.ctx.lineTo(s.x,i.y),t.ctx.stroke(),t.ctx.restore(),vt(t,s,n,4)},distance:(t,e,i)=>{const n=i.pts[0],s=Tt(i.drawing.style,St(i.drawing.style,"Note")+1),l=_t(t,e,n.x+14,n.y-12,s.w,s.h);return null!==l?l:Math.hypot(t-n.x,e-n.y)<=8?0:null}},Dt={id:"table",name:"Table",points:1,defaultStyle:{text:"Level|Price\nEntry|-\nStop|-",fontSize:11,fillOpacity:.92,border:!0},draw:t=>{const e=t.rc.dpr,i=t.pts[0],n=$t(t.style),s=(t.style.fontSize??11)*e,l=7*e,o=1.7*s;t.ctx.save(),t.ctx.font=`${s}px ui-sans-serif, system-ui, sans-serif`;const r=Math.max(...n.map(t=>t.length)),c=[];for(let e=0;e<r;e++){let i=0;for(const s of n)i=Math.max(i,t.ctx.measureText(s[e]??"").width);c.push(i+2*l)}const a=c.reduce((t,e)=>t+e,0),h=o*n.length;if(t.ctx.setLineDash([]),t.ctx.globalAlpha=t.style.fillOpacity??.92,t.ctx.fillStyle=t.style.backgroundColor??t.rc.theme.background,t.ctx.beginPath(),x(t.ctx,i.x,i.y,a,h,4*e),t.ctx.fill(),t.ctx.globalAlpha=1,!1!==t.style.border){t.ctx.strokeStyle=t.style.borderColor??t.style.color,t.ctx.lineWidth=Math.max(1,t.style.lineWidth*e),t.ctx.stroke(),t.ctx.globalAlpha=.45,t.ctx.beginPath();for(let e=1;e<n.length;e++)t.ctx.moveTo(i.x,i.y+o*e),t.ctx.lineTo(i.x+a,i.y+o*e);let s=i.x;for(let e=0;e<c.length-1;e++)s+=c[e],t.ctx.moveTo(s,i.y),t.ctx.lineTo(s,i.y+h);t.ctx.stroke(),t.ctx.globalAlpha=1}t.ctx.textBaseline="middle",t.ctx.textAlign="left";for(let e=0;e<n.length;e++){t.ctx.fillStyle=t.style.fontColor??t.style.color,t.ctx.font=0===e?`600 ${s}px ui-sans-serif, system-ui, sans-serif`:`${s}px ui-sans-serif, system-ui, sans-serif`;let r=i.x;for(let s=0;s<c.length;s++)t.ctx.fillText(n[e][s]??"",r+l,i.y+o*e+o/2),r+=c[s]}t.ctx.restore()},distance:(t,e,i)=>{const n=i.pts[0],s=$t(i.drawing.style),l=i.drawing.style.fontSize??11,o=Math.max(...s.map(t=>t.length));return _t(t,e,n.x,n.y,70*o,1.7*l*s.length)}};function $t(t){return(void 0===t.text||""===t.text?"Level|Price":t.text).split("\n").map(t=>t.split("|"))}const zt={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,l=n>=0,o=l?"#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=o,t.ctx.fillRect(r,Math.min(a,h),c-r,Math.abs(h-a)),t.ctx.restore(),M(t),t.ctx.strokeStyle=o,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=l?"+":"";_(t,`${p}${t.formatPrice(n)} (${p}${s.toFixed(2)}%)`,x+6*e,(a+h)/2,o)},distance:(t,e,i)=>o(t,e,i.pts[0],i.pts[1],!0)},Ft={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,l=t.pts[1].x,o=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,l),o,Math.abs(l-s),r-o),t.ctx.restore(),M(t),t.ctx.beginPath();for(const e of[s,l])t.ctx.moveTo(Math.round(e)+.5,o),t.ctx.lineTo(Math.round(e)+.5,r);const c=(o+r)/2;t.ctx.moveTo(s,c),t.ctx.lineTo(l,c);const a=l>s?1:-1;t.ctx.moveTo(l-5*e*a,c-4*e),t.ctx.lineTo(l,c),t.ctx.lineTo(l-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);_(t,`${Math.abs(Math.round(x-h))} bars`,(s+l)/2,o-10*e,n)},distance:(t,e,i)=>o(t,e,i.pts[0],i.pts[1],!0)},Ct={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,l=i[1].price-i[0].price,o=0!==i[0].price?l/i[0].price*100:0,r=l>=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(),M(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(l)} (${h}${o.toFixed(2)}%) in ${k(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])},Nt={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()),M(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,l=Math.hypot(s.x-n.x,s.y-n.y),o=Math.hypot(t-n.x,e-n.y);return!0===i.drawing.style.fill&&o<=l?0:Math.abs(o-l)}},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(),v(t,()=>t.ctx.fill()),M(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>s(t,e,[...i.pts,i.pts[0]])},It={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())),M(t),t.ctx.stroke(),t.ctx.setLineDash([])}},distance:(t,e,i)=>s(t,e,i.pts)};const Ht={id:"arc",name:"Arc",points:3,draw:t=>{const[e,i,n]=t.pts;M(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,l=[];for(let e=0;e<=16;e++){const o=e/16,r=1-o;l.push({x:r*r*t.x+2*r*o*n+o*o*i.x,y:r*r*t.y+2*r*o*s+o*o*i.y})}return l}(i.pts[0],i.pts[1],i.pts[2]))},Rt={id:"curve",name:"Curve",points:3,draw:t=>{const[e,i,n]=t.pts;M(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,l,o]=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*l.x+e*e*o.x,y:i*i*n.y+2*i*e*l.y+e*e*o.y})}return s(t,e,r)}};function jt(t,e,i,n="vertical"){return{id:t,name:e,points:1,defaultStyle:{fill:!0,fillOpacity:.9},draw:t=>{const e=t.rc.dpr,{x:s,y:l}=t.pts[0],o=16*e,r=6*e,c=i?1:-1,a=l+2*c*e;if(t.ctx.beginPath(),"vertical"!==n){const i="right"===n?-1:1,c=s+2*i*e;t.ctx.moveTo(c,l),t.ctx.lineTo(c+i*r,l-r),t.ctx.lineTo(c+i*r,l-r/2.4),t.ctx.lineTo(c+i*o,l-r/2.4),t.ctx.lineTo(c+i*o,l+r/2.4),t.ctx.lineTo(c+i*r,l+r/2.4),t.ctx.lineTo(c+i*r,l+r),t.ctx.closePath()}else t.ctx.moveTo(s,a),t.ctx.lineTo(s-r,a+c*r),t.ctx.lineTo(s-r/2.4,a+c*r),t.ctx.lineTo(s-r/2.4,a+c*o),t.ctx.lineTo(s+r/2.4,a+c*o),t.ctx.lineTo(s+r/2.4,a+c*r),t.ctx.lineTo(s+r,a+c*r),t.ctx.closePath();t.ctx.save(),t.ctx.globalAlpha=t.style.fillOpacity??.9,t.ctx.fillStyle=w(t),t.ctx.fill(),t.ctx.restore(),M(t),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,n)=>{const s=n.pts[0],l=i?e-s.y:s.y-e;return Math.abs(t-s.x)<=8&&l>=-4&&l<=20?0:null}}}const Bt=jt("arrow-up","Arrow Up",!0),Et=jt("arrow-down","Arrow Down",!1),Ut=jt("arrow-left","Arrow Left",!0,"left"),Jt=jt("arrow-right","Arrow Right",!0,"right"),Vt={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}},Yt={id:"fib-channel",name:"Fib Channel",points:3,defaultStyle:{showLabels:!0,levels:[...D]},draw:t=>{const e=t.style.levels??D,[i,n,s]=t.pts,l=s.x-n.x,o=s.y-n.y;M(t);for(const s of e)t.ctx.beginPath(),t.ctx.moveTo(i.x+l*s,i.y+o*s),t.ctx.lineTo(n.x+l*s,n.y+o*s),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,`${(100*s).toFixed(1)}%`,n.x+l*s+4*t.rc.dpr,n.y+o*s);t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??D,[l,o,r]=n.pts;let c=1/0;for(const n of s){const s=t(e,i,{x:l.x+(r.x-o.x)*n,y:l.y+(r.y-o.y)*n},{x:o.x+(r.x-o.x)*n,y:o.y+(r.y-o.y)*n});s<c&&(c=s)}return c}},qt=[0,1,2,3,5,8,13,21,34,55],Kt={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,l=t.rc.plotWidth*s;M(t);for(const i of qt){const o=e.x+n*i;o<-10||o>l+10||(t.ctx.beginPath(),t.ctx.moveTo(Math.round(o)+.5,0),t.ctx.lineTo(Math.round(o)+.5,t.rc.plotHeight*s),t.ctx.stroke(),!1!==t.style.showLabels&&_(t,String(i),o+3*s,12*s))}t.ctx.setLineDash([])},distance:(t,e,i)=>{const[n,s]=i.pts,l=s.x-n.x;if(Math.abs(l)<.5)return null;let o=1/0;for(const e of qt)o=Math.min(o,Math.abs(t-(n.x+l*e)));return o}},Gt=[.236,.382,.5,.618,.786,1],Qt={id:"fib-fan",name:"Fib Speed Fan",points:2,defaultStyle:{showLabels:!0,levels:[...Gt]},draw:t=>{const e=t.style.levels??Gt,[i,n]=t.pts,s=t.rc.dpr,l=t.rc.plotWidth*s;M(t);for(const o of e){const e=c(i,{x:n.x,y:i.y+(n.y-i.y)*o},l,!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*o).toFixed(1)}%`,n.x+4*s,i.y+(n.y-i.y)*o)}t.ctx.setLineDash([])},distance:(e,i,n)=>{const s=n.drawing.style.levels??Gt,[l,o]=n.pts;let r=1/0;for(const a of s)r=Math.min(r,t(e,i,l,c(l,{x:o.x,y:l.y+(o.y-l.y)*a},n.rc.plotWidth,!1,!0)[1]));return r}},Xt=[[1,.125],[1,.25],[1,.5],[1,1],[.5,1],[.25,1],[.125,1]],Zt=[z,F,C,N,W,I,H,R,j,B,E,J,V,K,G,Ct,Y,zt,Ft,Nt,Wt,It,Ht,Rt,rt,at,Bt,Et,Vt,ot,Yt,Kt,Qt,{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,l=i.x-e.x,o=i.y-e.y;if(!(Math.abs(l)<.5)){M(t);for(const[i,n]of Xt){const r=c(e,{x:e.x+l*i,y:e.y+o*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,l]=n.pts,o=l.x-s.x,r=l.y-s.y;let a=1/0;for(const[l,h]of Xt)a=Math.min(a,t(e,i,s,c(s,{x:s.x+o*l,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=l(t.pts[0],t.pts[1]);v(t,()=>t.ctx.fillRect(e.x0,e.y0,e.x1-e.x0,e.y1-e.y0)),M(t);const i=e.x1-e.x0,n=e.y1-e.y0;t.ctx.beginPath();for(let s=0;s<=8;s++){const l=Math.round(e.x0+i*s/8)+.5,o=Math.round(e.y0+n*s/8)+.5;t.ctx.moveTo(l,e.y0),t.ctx.lineTo(l,e.y1),t.ctx.moveTo(e.x0,o),t.ctx.lineTo(e.x1,o)}t.ctx.moveTo(e.x0,e.y1),t.ctx.lineTo(e.x1,e.y0),t.ctx.stroke(),t.ctx.setLineDash([])},distance:(t,e,i)=>o(t,e,i.pts[0],i.pts[1],!0===i.drawing.style.fill)},ht,xt,dt,nt,lt,yt,ut,bt,Pt,kt,Lt,Ot,At,Dt,Ut,Jt];let te=!1;function ee(){if(!te){te=!0;for(const t of Zt)p(t)}}const ie="0 0 24 24",ne=2,se={viewBox:ie,fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"},le={cursor:"M12 3v6M12 15v6M3 12h6M15 12h6",magnet:"M6 4v8a6 6 0 0 0 12 0V4M6 9h4M14 9h4","trend-line":"M4 20 20 4",ray:"M4 20 20 4M2 18 6 22","extended-line":"M2 22 22 2",arrow:"M4 20 18 6M18 6h-6M18 6v6","horizontal-line":"M2 12h20","horizontal-ray":"M6 12H22M4 10V14","vertical-line":"M12 2v20","cross-line":"M2 12h20M12 2v20","trend-angle":"M4 20 18 8M4 20h12M8 20a8 8 0 0 0 2-5","info-line":"M4 20 20 4M8 8h8",path:"M2 18 8 8l4 6 4-10",polyline:"M2 18 8 8l4 6 4-10 4 4","parallel-channel":"M2 16 14 4M8 22 20 10","disjoint-channel":"M2 16 14 6M8 22 22 14","flat-bottom":"M2 14 14 4M2 20h20","fib-channel":"M2 14 14 4M4 18 16 8M6 22 18 12","regression-trend":"M2 18 20 6M4 20 22 8M2 14 20 2",rectangle:"M3 5h18v14H3z","rotated-rectangle":"M2 14 10 4l12 6-8 10z",ellipse:"M12 5c5 0 9 3 9 7s-4 7-9 7-9-3-9-7 4-7 9-7z",circle:"M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18z",triangle:"M12 4 21 20H3z",arc:"M3 19a12 12 0 0 1 18 0",curve:"M3 18c4-12 14-12 18 0","double-curve":"M3 18c3-9 7-9 9 0 2 9 6 9 9 0",brush:"M3 19c4 0 4-8 8-8s4 8 9 4",highlighter:"M4 16 14 6l4 4-10 10H4z","fib-retracement":"M3 4h18M3 9h18M3 14h18M3 19h18","fib-extension":"M3 5h18M3 12h18M3 19h18M8 5v14","fib-fan":"M3 20 21 4M3 20 21 10M3 20 21 16M3 20h18","fib-time-zone":"M4 3v18M8 3v18M14 3v18M22 3v18","fib-circles":"M12 20A5 5 0 0 1 12 10M12 20A9 9 0 0 1 12 2M10 20h4","fib-spiral":"M12 13A3 3 0 1 1 15 10A7 7 0 1 1 8 3A9 9 0 1 1 21 12","fib-wedge":"M3 20 21 4M3 20 21 12M3 20a12 12 0 0 0 10-6","fib-speed-fan":"M3 20V4M3 20h18M3 20 21 4M3 20 13 4","gann-fan":"M3 20 21 2M3 20 21 9M3 20 21 15M3 20h18","gann-box":"M3 3h18v18H3zM3 3l18 18M3 21 21 3",measure:"M4 16h16M4 12v8M20 12v8M8 4h8M12 4v6","price-range":"M12 4v16M8 8l4-4 4 4M8 16l4 4 4-4","date-range":"M4 12h16M8 8l-4 4 4 4M16 8l4 4-4 4","date-price-range":"M4 6h16v12H4zM4 12h16M12 6v12","cyclic-lines":"M4 4v16M10 4v16M16 4v16M22 4v16","time-cycles":"M4 12a4 4 0 0 1 8 0 4 4 0 0 0 8 0M4 4v16","sine-line":"M2 12c3-9 6-9 9 0 3 9 6 9 9 0","long-position":"M3 15h18v5H3zM3 5h18v5H3zM12 10v5","short-position":"M3 5h18v5H3zM3 15h18v5H3zM12 10v5",forecast:"M3 18 9 10l4 4 8-10M13 4h8v8","risk-reward-long":"M3 14h18v6H3zM3 4h18v6H3zM12 10v4M6 7h4","risk-reward-short":"M3 4h18v6H3zM3 14h18v6H3zM12 10v4M6 17h4",text:"M4 5h16M12 5v14M8 19h8",note:"M4 20 9 15M9 5h13v10H9zM4 20v-4",callout:"M3 4h18v11H3zM8 15l-2 5 6-5",balloon:"M3 4h18v12H9l-4 4v-4H3z",comment:"M3 5h18v10H3zM6 15v4l4-4",signpost:"M12 21V9M5 3h14v6H5z","price-label":"M3 12 8 7h13v10H8z","price-note":"M2 12h5M7 6h15v12H7zM10 12h9",table:"M3 5h18v14H3zM3 10h18M9 10v9M15 10v9","flag-mark":"M6 21V3M6 3h12l-3 4 3 4H6","arrow-up":"M12 3v18M6 9l6-6 6 6","arrow-down":"M12 3v18M6 15l6 6 6-6","arrow-left":"M3 12h18M9 6l-6 6 6 6","arrow-right":"M3 12h18M15 6l6 6-6 6"};function oe(t){return le[t]}function re(){return Object.keys(le)}function ce(t,e){return u(t)&&!0===y(t).freehand&&e>2?[0,e-1]:Array.from({length:e},(t,e)=>e)}class ae{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 l={color:n.style.color??e.theme.lineColor,lineWidth:n.style.lineWidth??1.5,...n.style},o=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*o,y:t.y*o})),style:{...l,color:l.color,lineWidth:l.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 l of ce(n,i.length)){const n=i[l];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 ce(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 l=this._drawings[s];if(!1===l.visible||!0===l.locked||!u(l.tool))continue;const o=y(l.tool);if(l.points.length<Math.max(1,o.points))continue;const r=o.distance(t,e,{pts:this._points(i,l),drawing:l,rc:i});null===r||!Number.isFinite(r)||r>6||(null===n||r<n.distance)&&(n={id:l.id,distance:r})}return null===n?null:{externalId:`draw:${n.id}`,zOrder:"top",distance:n.distance,cursor:"move",draggable:!0}}}const he="openalgo-charts/drawings",xe=1;let de=null;function pe(){de=null}function ye(){const t=globalThis.navigator,e=t?.clipboard;return void 0===e||"function"!=typeof e.writeText||"function"!=typeof e.readText?null:e}function ue(t){return JSON.stringify({[he]:{version:1,drawings:t.map(t=>({tool:t.tool,points:t.points.map(t=>({time:t.time,price:t.price})),style:t.style??{},paneIndex:t.paneIndex,...void 0===t.locked?{}:{locked:t.locked},...void 0===t.visible?{}:{visible:t.visible}}))}})}const fe=t=>"object"==typeof t&&null!==t&&!Array.isArray(t),ge=t=>"number"==typeof t&&Number.isFinite(t);function me(t){if(!fe(t))return null;if("string"!=typeof t.tool||!u(t.tool))return null;const e=function(t){if(!Array.isArray(t)||0===t.length||t.length>2e4)return null;const e=[];for(const i of t){if(!fe(i)||!ge(i.time)||!ge(i.price))return null;e.push({time:i.time,price:i.price})}return e}(t.points);if(null===e)return null;const i=function(t){if(void 0===t)return{};if(!fe(t))return null;const e={};let i=0;for(const[n,s]of Object.entries(t))if("__proto__"!==n&&"constructor"!==n&&"prototype"!==n){if(++i>64)return null;if("string"==typeof s){if(s.length>4096)return null;e[n]=s}else if("boolean"==typeof s)e[n]=s;else if(ge(s))e[n]=s;else if(Array.isArray(s)){if(s.length>64||!s.every(ge))return null;e[n]=s.slice()}}return e}(t.style);if(null===i)return null;const n=void 0===t.paneIndex?0:t.paneIndex;return!ge(n)||n<0||!Number.isInteger(n)||void 0!==t.locked&&"boolean"!=typeof t.locked||void 0!==t.visible&&"boolean"!=typeof t.visible?null:{tool:t.tool,points:e,style:i,paneIndex:n,...void 0===t.locked?{}:{locked:t.locked},...void 0===t.visible?{}:{visible:t.visible}}}function be(t){if("string"!=typeof t||0===t.length)return null;let e;try{e=JSON.parse(t)}catch{return null}if(!fe(e))return null;const i=e[he];if(!fe(i))return null;if(!ge(i.version)||i.version<1||i.version>1)return null;const n=i.drawings;if(!Array.isArray(n)||0===n.length||n.length>512)return null;const s=[];for(const t of n){const e=me(t);if(null===e)return null;s.push(e)}return s}class Me{constructor(t={}){Object.defineProperty(this,"_port",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_fallback",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_lastError",{enumerable:!0,configurable:!0,writable:!0,value:null}),this._port=void 0===t.port?ye():t.port,this._fallback=t.fallbackToMemory??!0}setPort(t){this._port=t}setFallbackToMemory(t){this._fallback=t}lastError(){return this._lastError}async write(t){if(0===t.length)return!1;let e;try{e=ue(t)}catch(t){return this._lastError=String(t),!1}this._lastError=null;let i=!1;if(null!==this._port)try{await this._port.writeText(e),i=!0}catch(t){this._lastError=String(t)}else this._lastError="openalgo-charts: no system clipboard available";return this._fallback?(de=e,!0):i}async read(){if(this._lastError=null,null!==this._port)try{const t=be(await this._port.readText());if(null!==t)return t}catch(t){this._lastError=String(t)}return this._fallback?be(de):null}}let we=1;class ve{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,"_clipboard",{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,pasteOffsetBars:e.pasteOffsetBars??2,pasteOffsetPixels:e.pasteOffsetPixels??16,defaultStyle:e.defaultStyle??{}},this._clipboard=new Me({...void 0===e.clipboard?{}:{port:e.clipboard},...void 0===e.clipboardFallbackToMemory?{}:{fallbackToMemory:e.clipboardFallbackToMemory}}),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){const{clipboard:e,...i}=t;this._opts={...this._opts,...i,defaultStyle:t.defaultStyle??this._opts.defaultStyle},void 0!==e&&this._clipboard.setPort(e)}clipboard(){return this._clipboard}drawings(){return this._drawings}get(t){return this._drawings.find(e=>e.id===t)}add(t){this._pushUndo();const e=this._insert(t);return this._sync(),this._chart.emit("draw:add",{drawing:e}),e}_insert(t){const e=y(t.tool),i={...t,id:t.id??"d"+we++,style:{...this._opts.defaultStyle,...e.defaultStyle,...t.style}};return this._drawings.push(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}async copy(t){const e=this._targets(t);if(0===e.length)return!1;const i=await this._clipboard.write(e);return i&&this._chart.emit("draw:copy",{drawings:e.map(t=>({...t,points:t.points.map(t=>({...t})),style:{...t.style}}))}),i}async cut(t){const e=this._targets(t);if(0===e.length)return!1;if(!await this._clipboard.write(e))return!1;const i=new Set(e.map(t=>t.id)),n=this._drawings.filter(t=>i.has(t.id));if(0===n.length)return!1;this._pushUndo(),this._drawings=this._drawings.filter(t=>!i.has(t.id)),null!==this._selected&&i.has(this._selected)&&(this._selected=null),this._sync();for(const t of n)this._chart.emit("draw:remove",{drawing:t});return this._chart.emit("draw:cut",{drawings:n}),!0}async paste(){const t=await this._clipboard.read();if(null===t||0===t.length)return[];for(const e of t)if(!u(e.tool))return[];const e=t.map(t=>{const e=this._clampPane(t.paneIndex);return{...t,paneIndex:e,points:this._offsetPoints(t.points,e)}});this._pushUndo();const i=e.map(t=>this._insert(t));this._sync();for(const t of i)this._chart.emit("draw:add",{drawing:t});return this._chart.emit("draw:paste",{drawings:i}),this.select(i[i.length-1].id),i}_targets(t){if(null==t){const t=null===this._selected?void 0:this.get(this._selected);return void 0===t?[]:[t]}const e="string"==typeof t?[t]:t,i=[];for(const t of e){const e=this.get(t);void 0!==e&&i.push(e)}return i}_clampPane(t){const e=this._chart.panes;if(void 0===e)return t;const i=e.call(this._chart).length;return 0===i?0:Math.min(t,i-1)}_offsetPoints(t,e){const i=this._barSeconds()*this._opts.pasteOffsetBars,n=this._opts.pasteOffsetPixels;return t.map(t=>({time:t.time+i,price:this._offsetPrice(t.price,e,n)}))}_offsetPrice(t,e,i){if(0===i)return t;const n=this._chart.priceToCoordinate,s=this._chart.coordinateToPrice;if(void 0===n||void 0===s)return t;const l=n.call(this._chart,t,e);if(null===l||!Number.isFinite(l))return t;const o=s.call(this._chart,l+i,e);return null!==o&&Number.isFinite(o)?o:t}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.getVisibleLogicalRange(),n=null===i?60:Math.max(1,i.to-i.from);return t.expand(e,{barSeconds:this._barSeconds(),visibleBars:n})}_barSeconds(){const t=this._chart.dataLayer,e=t.baseIndex,i=e>0?t.indexToTime(e-1):void 0,n=e>=0?t.indexToTime(e):void 0;return void 0!==i&&void 0!==n&&n>i?n-i:60}_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 l=this._dragStart;if(null===s){const e=t.time-l.from.time,i=t.price-l.from.price;n.points=l.points.map(t=>({time:t.time+e,price:t.price+i}))}else s>=0&&s<n.points.length&&(n.points=l.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 ae,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 _e="draw";ee();export{N as ARROW,Et as ARROW_DOWN,Ut as ARROW_LEFT,Jt as ARROW_RIGHT,Bt as ARROW_UP,kt as BALLOON,Zt as BUILTIN_DRAWING_TOOLS,ut as CALLOUT,Lt as COMMENT,R as CROSS_LINE,he as DRAWING_CLIPBOARD_KEY,xe as DRAWING_CLIPBOARD_VERSION,le as DRAWING_TOOL_ICONS,_e as DRAW_TIER,Me as DrawingClipboard,ve as DrawingController,ae as DrawingLayer,B as ELLIPSE,C as EXTENDED_LINE,V as FIB_EXTENSION,J as FIB_RETRACEMENT,bt as FLAG_MARK,W as HORIZONTAL_LINE,I as HORIZONTAL_RAY,se as ICON_ATTRS,ne as ICON_STROKE,ie as ICON_VIEWBOX,K as LONG_POSITION,Y as MEASURE,Pt as NOTE,E as PARALLEL_CHANNEL,lt as PATH,yt as PRICE_LABEL,At as PRICE_NOTE,F as RAY,j as RECTANGLE,G as SHORT_POSITION,Ot as SIGNPOST,Dt as TABLE,nt as TEXT,z as TREND_LINE,H as VERTICAL_LINE,pe as clearMemoryClipboard,be as decodeClipboardPayload,r as distToEllipse,e as distToLine,s as distToPolyline,o as distToRect,t as distToSegment,b as drawingShortcuts,oe as drawingToolIcon,re as drawingToolIconIds,ue as encodeClipboardPayload,c as extendSegment,y as getDrawingTool,u as hasDrawingTool,m as matchDrawingShortcut,l as rectOf,ee as registerBuiltinDrawingTools,p as registerDrawingTool,f as registeredDrawingTools,me as sanitizeDrawing,ye as systemClipboard};
|
|
2
2
|
//# sourceMappingURL=openalgo-charts.draw.mjs.map
|