hyperprop-charting-library 0.1.156 → 0.1.158
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hyperprop-charting-library.cjs +74 -34
- package/dist/hyperprop-charting-library.d.ts +18 -1
- package/dist/hyperprop-charting-library.js +74 -34
- package/dist/index.cjs +74 -34
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +74 -34
- package/package.json +1 -1
|
@@ -5439,6 +5439,32 @@ function createChart(element, options = {}) {
|
|
|
5439
5439
|
ctx.fill();
|
|
5440
5440
|
ctx.restore();
|
|
5441
5441
|
};
|
|
5442
|
+
const drawTrashGlyph = (x, y, size, color) => {
|
|
5443
|
+
const w = size * 0.8;
|
|
5444
|
+
const h = size * 0.9;
|
|
5445
|
+
ctx.save();
|
|
5446
|
+
ctx.strokeStyle = color;
|
|
5447
|
+
ctx.lineWidth = 1.2;
|
|
5448
|
+
ctx.lineCap = "round";
|
|
5449
|
+
ctx.lineJoin = "round";
|
|
5450
|
+
ctx.beginPath();
|
|
5451
|
+
ctx.moveTo(x - w / 2, y - h * 0.28);
|
|
5452
|
+
ctx.lineTo(x + w / 2, y - h * 0.28);
|
|
5453
|
+
ctx.moveTo(x - w * 0.22, y - h * 0.28);
|
|
5454
|
+
ctx.lineTo(x - w * 0.22, y - h * 0.46);
|
|
5455
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.46);
|
|
5456
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.28);
|
|
5457
|
+
ctx.moveTo(x - w * 0.36, y - h * 0.28);
|
|
5458
|
+
ctx.lineTo(x - w * 0.28, y + h * 0.48);
|
|
5459
|
+
ctx.lineTo(x + w * 0.28, y + h * 0.48);
|
|
5460
|
+
ctx.lineTo(x + w * 0.36, y - h * 0.28);
|
|
5461
|
+
ctx.moveTo(x - w * 0.1, y - h * 0.08);
|
|
5462
|
+
ctx.lineTo(x - w * 0.1, y + h * 0.3);
|
|
5463
|
+
ctx.moveTo(x + w * 0.1, y - h * 0.08);
|
|
5464
|
+
ctx.lineTo(x + w * 0.1, y + h * 0.3);
|
|
5465
|
+
ctx.stroke();
|
|
5466
|
+
ctx.restore();
|
|
5467
|
+
};
|
|
5442
5468
|
const drawAlertLine = (alert, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
5443
5469
|
const lineY = getLineY(alert.price, yFromPrice, chartTop, chartBottom, false);
|
|
5444
5470
|
if (lineY === null) return;
|
|
@@ -5457,13 +5483,11 @@ function createChart(element, options = {}) {
|
|
|
5457
5483
|
ctx.restore();
|
|
5458
5484
|
const fontSize = Math.max(8, axis.fontSize);
|
|
5459
5485
|
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
5460
|
-
const text = alert.label ? `${formatPrice(alert.price)} ${alert.label}` : formatPrice(alert.price);
|
|
5461
5486
|
const paddingX = 6;
|
|
5462
5487
|
const bellWidth = fontSize + 2;
|
|
5463
5488
|
const labelHeight = 20;
|
|
5464
5489
|
const hovered = hoveredAlertId === alert.id;
|
|
5465
|
-
const
|
|
5466
|
-
const contentWidth = Math.ceil(measureTextWidth(text)) + bellWidth + paddingX * 3 + removeWidth;
|
|
5490
|
+
const contentWidth = bellWidth + paddingX * 2;
|
|
5467
5491
|
const labelWidth = getRightAxisLabelWidth(chartRight, contentWidth);
|
|
5468
5492
|
const labelX = getRightAxisLabelX(chartRight);
|
|
5469
5493
|
const labelY = placeRightAxisLabel(lineY - labelHeight / 2, labelHeight, chartTop, chartBottom - labelHeight);
|
|
@@ -5473,29 +5497,26 @@ function createChart(element, options = {}) {
|
|
|
5473
5497
|
fillRoundedRect(Math.round(labelX), Math.round(labelY), labelWidth, labelHeight, 3);
|
|
5474
5498
|
const inkColor = labelTextColorOn(color, "#101114");
|
|
5475
5499
|
drawBellGlyph(labelX + paddingX + bellWidth / 2, labelY + labelHeight / 2, fontSize, inkColor);
|
|
5476
|
-
|
|
5500
|
+
ctx.restore();
|
|
5477
5501
|
if (hovered) {
|
|
5478
|
-
const
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
ctx.
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
ctx.
|
|
5486
|
-
ctx.lineTo(removeX + inset, labelY + labelHeight - inset);
|
|
5487
|
-
ctx.stroke();
|
|
5502
|
+
const buttonSize = labelHeight;
|
|
5503
|
+
const buttonX = chartLeft + 10;
|
|
5504
|
+
const buttonY = lineY - buttonSize / 2;
|
|
5505
|
+
ctx.save();
|
|
5506
|
+
ctx.fillStyle = color;
|
|
5507
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, 3);
|
|
5508
|
+
drawTrashGlyph(buttonX + buttonSize / 2, lineY, fontSize, inkColor);
|
|
5509
|
+
ctx.restore();
|
|
5488
5510
|
alertRegions.push({
|
|
5489
5511
|
id: alert.id,
|
|
5490
|
-
x:
|
|
5491
|
-
y:
|
|
5492
|
-
width:
|
|
5493
|
-
height:
|
|
5512
|
+
x: buttonX,
|
|
5513
|
+
y: buttonY,
|
|
5514
|
+
width: buttonSize,
|
|
5515
|
+
height: buttonSize,
|
|
5494
5516
|
part: "remove"
|
|
5495
5517
|
});
|
|
5496
5518
|
}
|
|
5497
|
-
|
|
5498
|
-
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth - removeWidth, height: labelHeight, part: "line" });
|
|
5519
|
+
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth, height: labelHeight, part: "line" });
|
|
5499
5520
|
alertRegions.push({ id: alert.id, x: chartLeft, y: lineY - 5, width: chartRight - chartLeft, height: 10, part: "line" });
|
|
5500
5521
|
};
|
|
5501
5522
|
const drawOrderLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
@@ -8480,30 +8501,42 @@ function createChart(element, options = {}) {
|
|
|
8480
8501
|
ctx.fill();
|
|
8481
8502
|
cursorX += dotRadius * 2 + 6;
|
|
8482
8503
|
}
|
|
8483
|
-
const headline = [
|
|
8504
|
+
const headline = [
|
|
8505
|
+
dataLine.symbol,
|
|
8506
|
+
dataLine.description,
|
|
8507
|
+
dataLine.interval,
|
|
8508
|
+
dataLine.exchange,
|
|
8509
|
+
dataLine.chartTypeLabel
|
|
8510
|
+
].filter((part) => part && part.length > 0).join(" \xB7 ");
|
|
8484
8511
|
if (headline) {
|
|
8485
8512
|
ctx.fillStyle = symbolColor;
|
|
8486
8513
|
ctx.fillText(headline, cursorX, rowY);
|
|
8487
|
-
cursorX += measureTextWidth(headline) +
|
|
8514
|
+
cursorX += measureTextWidth(headline) + 12;
|
|
8488
8515
|
}
|
|
8489
8516
|
if (dataLine.showOhlc !== false) {
|
|
8490
|
-
const
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8517
|
+
const ohlcLabelColor = dataLine.ohlcLabelColor || textColor;
|
|
8518
|
+
const pairs = [
|
|
8519
|
+
["O", formatPrice(bar.o)],
|
|
8520
|
+
["H", formatPrice(bar.h)],
|
|
8521
|
+
["L", formatPrice(bar.l)],
|
|
8522
|
+
["C", formatPrice(bar.c)]
|
|
8523
|
+
];
|
|
8524
|
+
for (const [label, value] of pairs) {
|
|
8525
|
+
ctx.fillStyle = ohlcLabelColor;
|
|
8526
|
+
ctx.fillText(label, cursorX, rowY);
|
|
8527
|
+
cursorX += measureTextWidth(label) + 2;
|
|
8528
|
+
ctx.fillStyle = changeColor;
|
|
8529
|
+
ctx.fillText(value, cursorX, rowY);
|
|
8530
|
+
cursorX += measureTextWidth(value) + 9;
|
|
8531
|
+
}
|
|
8532
|
+
cursorX += 3;
|
|
8494
8533
|
}
|
|
8495
8534
|
if (dataLine.showChange !== false) {
|
|
8496
8535
|
const pct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
8497
8536
|
const changeText = `${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${pct.toFixed(2)}%)`;
|
|
8498
8537
|
ctx.fillStyle = changeColor;
|
|
8499
8538
|
ctx.fillText(changeText, cursorX, rowY);
|
|
8500
|
-
cursorX += measureTextWidth(changeText) +
|
|
8501
|
-
}
|
|
8502
|
-
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8503
|
-
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8504
|
-
ctx.fillStyle = textColor;
|
|
8505
|
-
ctx.fillText(volumeText, cursorX, rowY);
|
|
8506
|
-
cursorX += measureTextWidth(volumeText) + 10;
|
|
8539
|
+
cursorX += measureTextWidth(changeText) + 12;
|
|
8507
8540
|
}
|
|
8508
8541
|
for (const detail of dataLine.details ?? []) {
|
|
8509
8542
|
const text = detail.label ? `${detail.label} ${detail.value}` : detail.value;
|
|
@@ -8517,7 +8550,14 @@ function createChart(element, options = {}) {
|
|
|
8517
8550
|
ctx.fillText(text, cursorX, rowY);
|
|
8518
8551
|
cursorX += width2 + 12;
|
|
8519
8552
|
}
|
|
8520
|
-
|
|
8553
|
+
let lastRowY = rowY;
|
|
8554
|
+
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8555
|
+
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8556
|
+
lastRowY = rowY + fontSize + 4;
|
|
8557
|
+
ctx.fillStyle = textColor;
|
|
8558
|
+
ctx.fillText(volumeText, chartLeft + legendInsetX, lastRowY);
|
|
8559
|
+
}
|
|
8560
|
+
dataLineBottom = lastRowY + fontSize + 6;
|
|
8521
8561
|
ctx.font = prevFont;
|
|
8522
8562
|
}
|
|
8523
8563
|
}
|
|
@@ -697,15 +697,26 @@ interface DataLineOptions {
|
|
|
697
697
|
visible?: boolean;
|
|
698
698
|
/** e.g. "NQU6" — drawn first, in the emphasis color. */
|
|
699
699
|
symbol?: string;
|
|
700
|
+
/**
|
|
701
|
+
* Long instrument name, e.g. "NASDAQ 100 E-mini Futures". Drawn after the
|
|
702
|
+
* symbol in the emphasis color, the way other charting platforms label a
|
|
703
|
+
* pane. Omit to keep the headline to the code alone.
|
|
704
|
+
*/
|
|
705
|
+
description?: string;
|
|
700
706
|
/** e.g. "1h". */
|
|
701
707
|
interval?: string;
|
|
702
708
|
/** e.g. "CME". */
|
|
703
709
|
exchange?: string;
|
|
710
|
+
/**
|
|
711
|
+
* Chart style, e.g. "Candles" or "Renko [ATR(14), 1000]" — the last part of
|
|
712
|
+
* the headline, so a non-default style is never a surprise.
|
|
713
|
+
*/
|
|
714
|
+
chartTypeLabel?: string;
|
|
704
715
|
/** O/H/L/C values for the hovered (or latest) bar. Default true. */
|
|
705
716
|
showOhlc?: boolean;
|
|
706
717
|
/** Absolute and percent change of that bar, colored by direction. Default true. */
|
|
707
718
|
showChange?: boolean;
|
|
708
|
-
/** Bar volume. Default false. */
|
|
719
|
+
/** Bar volume. Drawn on its own row beneath the values. Default false. */
|
|
709
720
|
showVolume?: boolean;
|
|
710
721
|
/**
|
|
711
722
|
* Extra chips after the values — session, currency, a "Closed" badge. Each
|
|
@@ -724,6 +735,12 @@ interface DataLineOptions {
|
|
|
724
735
|
symbolColor?: string;
|
|
725
736
|
/** Everything after the symbol. Defaults to the indicator legend color. */
|
|
726
737
|
textColor?: string;
|
|
738
|
+
/**
|
|
739
|
+
* Color of the O/H/L/C letters. Values stay colored by direction, so dimming
|
|
740
|
+
* the letters is what makes the numbers readable at a glance rather than one
|
|
741
|
+
* run of same-colored text. Defaults to `textColor`.
|
|
742
|
+
*/
|
|
743
|
+
ohlcLabelColor?: string;
|
|
727
744
|
}
|
|
728
745
|
interface IndicatorUpdateOptions {
|
|
729
746
|
/**
|
|
@@ -5400,6 +5400,32 @@ function createChart(element, options = {}) {
|
|
|
5400
5400
|
ctx.fill();
|
|
5401
5401
|
ctx.restore();
|
|
5402
5402
|
};
|
|
5403
|
+
const drawTrashGlyph = (x, y, size, color) => {
|
|
5404
|
+
const w = size * 0.8;
|
|
5405
|
+
const h = size * 0.9;
|
|
5406
|
+
ctx.save();
|
|
5407
|
+
ctx.strokeStyle = color;
|
|
5408
|
+
ctx.lineWidth = 1.2;
|
|
5409
|
+
ctx.lineCap = "round";
|
|
5410
|
+
ctx.lineJoin = "round";
|
|
5411
|
+
ctx.beginPath();
|
|
5412
|
+
ctx.moveTo(x - w / 2, y - h * 0.28);
|
|
5413
|
+
ctx.lineTo(x + w / 2, y - h * 0.28);
|
|
5414
|
+
ctx.moveTo(x - w * 0.22, y - h * 0.28);
|
|
5415
|
+
ctx.lineTo(x - w * 0.22, y - h * 0.46);
|
|
5416
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.46);
|
|
5417
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.28);
|
|
5418
|
+
ctx.moveTo(x - w * 0.36, y - h * 0.28);
|
|
5419
|
+
ctx.lineTo(x - w * 0.28, y + h * 0.48);
|
|
5420
|
+
ctx.lineTo(x + w * 0.28, y + h * 0.48);
|
|
5421
|
+
ctx.lineTo(x + w * 0.36, y - h * 0.28);
|
|
5422
|
+
ctx.moveTo(x - w * 0.1, y - h * 0.08);
|
|
5423
|
+
ctx.lineTo(x - w * 0.1, y + h * 0.3);
|
|
5424
|
+
ctx.moveTo(x + w * 0.1, y - h * 0.08);
|
|
5425
|
+
ctx.lineTo(x + w * 0.1, y + h * 0.3);
|
|
5426
|
+
ctx.stroke();
|
|
5427
|
+
ctx.restore();
|
|
5428
|
+
};
|
|
5403
5429
|
const drawAlertLine = (alert, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
5404
5430
|
const lineY = getLineY(alert.price, yFromPrice, chartTop, chartBottom, false);
|
|
5405
5431
|
if (lineY === null) return;
|
|
@@ -5418,13 +5444,11 @@ function createChart(element, options = {}) {
|
|
|
5418
5444
|
ctx.restore();
|
|
5419
5445
|
const fontSize = Math.max(8, axis.fontSize);
|
|
5420
5446
|
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
5421
|
-
const text = alert.label ? `${formatPrice(alert.price)} ${alert.label}` : formatPrice(alert.price);
|
|
5422
5447
|
const paddingX = 6;
|
|
5423
5448
|
const bellWidth = fontSize + 2;
|
|
5424
5449
|
const labelHeight = 20;
|
|
5425
5450
|
const hovered = hoveredAlertId === alert.id;
|
|
5426
|
-
const
|
|
5427
|
-
const contentWidth = Math.ceil(measureTextWidth(text)) + bellWidth + paddingX * 3 + removeWidth;
|
|
5451
|
+
const contentWidth = bellWidth + paddingX * 2;
|
|
5428
5452
|
const labelWidth = getRightAxisLabelWidth(chartRight, contentWidth);
|
|
5429
5453
|
const labelX = getRightAxisLabelX(chartRight);
|
|
5430
5454
|
const labelY = placeRightAxisLabel(lineY - labelHeight / 2, labelHeight, chartTop, chartBottom - labelHeight);
|
|
@@ -5434,29 +5458,26 @@ function createChart(element, options = {}) {
|
|
|
5434
5458
|
fillRoundedRect(Math.round(labelX), Math.round(labelY), labelWidth, labelHeight, 3);
|
|
5435
5459
|
const inkColor = labelTextColorOn(color, "#101114");
|
|
5436
5460
|
drawBellGlyph(labelX + paddingX + bellWidth / 2, labelY + labelHeight / 2, fontSize, inkColor);
|
|
5437
|
-
|
|
5461
|
+
ctx.restore();
|
|
5438
5462
|
if (hovered) {
|
|
5439
|
-
const
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
ctx.
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
ctx.
|
|
5447
|
-
ctx.lineTo(removeX + inset, labelY + labelHeight - inset);
|
|
5448
|
-
ctx.stroke();
|
|
5463
|
+
const buttonSize = labelHeight;
|
|
5464
|
+
const buttonX = chartLeft + 10;
|
|
5465
|
+
const buttonY = lineY - buttonSize / 2;
|
|
5466
|
+
ctx.save();
|
|
5467
|
+
ctx.fillStyle = color;
|
|
5468
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, 3);
|
|
5469
|
+
drawTrashGlyph(buttonX + buttonSize / 2, lineY, fontSize, inkColor);
|
|
5470
|
+
ctx.restore();
|
|
5449
5471
|
alertRegions.push({
|
|
5450
5472
|
id: alert.id,
|
|
5451
|
-
x:
|
|
5452
|
-
y:
|
|
5453
|
-
width:
|
|
5454
|
-
height:
|
|
5473
|
+
x: buttonX,
|
|
5474
|
+
y: buttonY,
|
|
5475
|
+
width: buttonSize,
|
|
5476
|
+
height: buttonSize,
|
|
5455
5477
|
part: "remove"
|
|
5456
5478
|
});
|
|
5457
5479
|
}
|
|
5458
|
-
|
|
5459
|
-
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth - removeWidth, height: labelHeight, part: "line" });
|
|
5480
|
+
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth, height: labelHeight, part: "line" });
|
|
5460
5481
|
alertRegions.push({ id: alert.id, x: chartLeft, y: lineY - 5, width: chartRight - chartLeft, height: 10, part: "line" });
|
|
5461
5482
|
};
|
|
5462
5483
|
const drawOrderLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
@@ -8441,30 +8462,42 @@ function createChart(element, options = {}) {
|
|
|
8441
8462
|
ctx.fill();
|
|
8442
8463
|
cursorX += dotRadius * 2 + 6;
|
|
8443
8464
|
}
|
|
8444
|
-
const headline = [
|
|
8465
|
+
const headline = [
|
|
8466
|
+
dataLine.symbol,
|
|
8467
|
+
dataLine.description,
|
|
8468
|
+
dataLine.interval,
|
|
8469
|
+
dataLine.exchange,
|
|
8470
|
+
dataLine.chartTypeLabel
|
|
8471
|
+
].filter((part) => part && part.length > 0).join(" \xB7 ");
|
|
8445
8472
|
if (headline) {
|
|
8446
8473
|
ctx.fillStyle = symbolColor;
|
|
8447
8474
|
ctx.fillText(headline, cursorX, rowY);
|
|
8448
|
-
cursorX += measureTextWidth(headline) +
|
|
8475
|
+
cursorX += measureTextWidth(headline) + 12;
|
|
8449
8476
|
}
|
|
8450
8477
|
if (dataLine.showOhlc !== false) {
|
|
8451
|
-
const
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8478
|
+
const ohlcLabelColor = dataLine.ohlcLabelColor || textColor;
|
|
8479
|
+
const pairs = [
|
|
8480
|
+
["O", formatPrice(bar.o)],
|
|
8481
|
+
["H", formatPrice(bar.h)],
|
|
8482
|
+
["L", formatPrice(bar.l)],
|
|
8483
|
+
["C", formatPrice(bar.c)]
|
|
8484
|
+
];
|
|
8485
|
+
for (const [label, value] of pairs) {
|
|
8486
|
+
ctx.fillStyle = ohlcLabelColor;
|
|
8487
|
+
ctx.fillText(label, cursorX, rowY);
|
|
8488
|
+
cursorX += measureTextWidth(label) + 2;
|
|
8489
|
+
ctx.fillStyle = changeColor;
|
|
8490
|
+
ctx.fillText(value, cursorX, rowY);
|
|
8491
|
+
cursorX += measureTextWidth(value) + 9;
|
|
8492
|
+
}
|
|
8493
|
+
cursorX += 3;
|
|
8455
8494
|
}
|
|
8456
8495
|
if (dataLine.showChange !== false) {
|
|
8457
8496
|
const pct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
8458
8497
|
const changeText = `${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${pct.toFixed(2)}%)`;
|
|
8459
8498
|
ctx.fillStyle = changeColor;
|
|
8460
8499
|
ctx.fillText(changeText, cursorX, rowY);
|
|
8461
|
-
cursorX += measureTextWidth(changeText) +
|
|
8462
|
-
}
|
|
8463
|
-
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8464
|
-
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8465
|
-
ctx.fillStyle = textColor;
|
|
8466
|
-
ctx.fillText(volumeText, cursorX, rowY);
|
|
8467
|
-
cursorX += measureTextWidth(volumeText) + 10;
|
|
8500
|
+
cursorX += measureTextWidth(changeText) + 12;
|
|
8468
8501
|
}
|
|
8469
8502
|
for (const detail of dataLine.details ?? []) {
|
|
8470
8503
|
const text = detail.label ? `${detail.label} ${detail.value}` : detail.value;
|
|
@@ -8478,7 +8511,14 @@ function createChart(element, options = {}) {
|
|
|
8478
8511
|
ctx.fillText(text, cursorX, rowY);
|
|
8479
8512
|
cursorX += width2 + 12;
|
|
8480
8513
|
}
|
|
8481
|
-
|
|
8514
|
+
let lastRowY = rowY;
|
|
8515
|
+
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8516
|
+
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8517
|
+
lastRowY = rowY + fontSize + 4;
|
|
8518
|
+
ctx.fillStyle = textColor;
|
|
8519
|
+
ctx.fillText(volumeText, chartLeft + legendInsetX, lastRowY);
|
|
8520
|
+
}
|
|
8521
|
+
dataLineBottom = lastRowY + fontSize + 6;
|
|
8482
8522
|
ctx.font = prevFont;
|
|
8483
8523
|
}
|
|
8484
8524
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -5439,6 +5439,32 @@ function createChart(element, options = {}) {
|
|
|
5439
5439
|
ctx.fill();
|
|
5440
5440
|
ctx.restore();
|
|
5441
5441
|
};
|
|
5442
|
+
const drawTrashGlyph = (x, y, size, color) => {
|
|
5443
|
+
const w = size * 0.8;
|
|
5444
|
+
const h = size * 0.9;
|
|
5445
|
+
ctx.save();
|
|
5446
|
+
ctx.strokeStyle = color;
|
|
5447
|
+
ctx.lineWidth = 1.2;
|
|
5448
|
+
ctx.lineCap = "round";
|
|
5449
|
+
ctx.lineJoin = "round";
|
|
5450
|
+
ctx.beginPath();
|
|
5451
|
+
ctx.moveTo(x - w / 2, y - h * 0.28);
|
|
5452
|
+
ctx.lineTo(x + w / 2, y - h * 0.28);
|
|
5453
|
+
ctx.moveTo(x - w * 0.22, y - h * 0.28);
|
|
5454
|
+
ctx.lineTo(x - w * 0.22, y - h * 0.46);
|
|
5455
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.46);
|
|
5456
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.28);
|
|
5457
|
+
ctx.moveTo(x - w * 0.36, y - h * 0.28);
|
|
5458
|
+
ctx.lineTo(x - w * 0.28, y + h * 0.48);
|
|
5459
|
+
ctx.lineTo(x + w * 0.28, y + h * 0.48);
|
|
5460
|
+
ctx.lineTo(x + w * 0.36, y - h * 0.28);
|
|
5461
|
+
ctx.moveTo(x - w * 0.1, y - h * 0.08);
|
|
5462
|
+
ctx.lineTo(x - w * 0.1, y + h * 0.3);
|
|
5463
|
+
ctx.moveTo(x + w * 0.1, y - h * 0.08);
|
|
5464
|
+
ctx.lineTo(x + w * 0.1, y + h * 0.3);
|
|
5465
|
+
ctx.stroke();
|
|
5466
|
+
ctx.restore();
|
|
5467
|
+
};
|
|
5442
5468
|
const drawAlertLine = (alert, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
5443
5469
|
const lineY = getLineY(alert.price, yFromPrice, chartTop, chartBottom, false);
|
|
5444
5470
|
if (lineY === null) return;
|
|
@@ -5457,13 +5483,11 @@ function createChart(element, options = {}) {
|
|
|
5457
5483
|
ctx.restore();
|
|
5458
5484
|
const fontSize = Math.max(8, axis.fontSize);
|
|
5459
5485
|
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
5460
|
-
const text = alert.label ? `${formatPrice(alert.price)} ${alert.label}` : formatPrice(alert.price);
|
|
5461
5486
|
const paddingX = 6;
|
|
5462
5487
|
const bellWidth = fontSize + 2;
|
|
5463
5488
|
const labelHeight = 20;
|
|
5464
5489
|
const hovered = hoveredAlertId === alert.id;
|
|
5465
|
-
const
|
|
5466
|
-
const contentWidth = Math.ceil(measureTextWidth(text)) + bellWidth + paddingX * 3 + removeWidth;
|
|
5490
|
+
const contentWidth = bellWidth + paddingX * 2;
|
|
5467
5491
|
const labelWidth = getRightAxisLabelWidth(chartRight, contentWidth);
|
|
5468
5492
|
const labelX = getRightAxisLabelX(chartRight);
|
|
5469
5493
|
const labelY = placeRightAxisLabel(lineY - labelHeight / 2, labelHeight, chartTop, chartBottom - labelHeight);
|
|
@@ -5473,29 +5497,26 @@ function createChart(element, options = {}) {
|
|
|
5473
5497
|
fillRoundedRect(Math.round(labelX), Math.round(labelY), labelWidth, labelHeight, 3);
|
|
5474
5498
|
const inkColor = labelTextColorOn(color, "#101114");
|
|
5475
5499
|
drawBellGlyph(labelX + paddingX + bellWidth / 2, labelY + labelHeight / 2, fontSize, inkColor);
|
|
5476
|
-
|
|
5500
|
+
ctx.restore();
|
|
5477
5501
|
if (hovered) {
|
|
5478
|
-
const
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
ctx.
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
ctx.
|
|
5486
|
-
ctx.lineTo(removeX + inset, labelY + labelHeight - inset);
|
|
5487
|
-
ctx.stroke();
|
|
5502
|
+
const buttonSize = labelHeight;
|
|
5503
|
+
const buttonX = chartLeft + 10;
|
|
5504
|
+
const buttonY = lineY - buttonSize / 2;
|
|
5505
|
+
ctx.save();
|
|
5506
|
+
ctx.fillStyle = color;
|
|
5507
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, 3);
|
|
5508
|
+
drawTrashGlyph(buttonX + buttonSize / 2, lineY, fontSize, inkColor);
|
|
5509
|
+
ctx.restore();
|
|
5488
5510
|
alertRegions.push({
|
|
5489
5511
|
id: alert.id,
|
|
5490
|
-
x:
|
|
5491
|
-
y:
|
|
5492
|
-
width:
|
|
5493
|
-
height:
|
|
5512
|
+
x: buttonX,
|
|
5513
|
+
y: buttonY,
|
|
5514
|
+
width: buttonSize,
|
|
5515
|
+
height: buttonSize,
|
|
5494
5516
|
part: "remove"
|
|
5495
5517
|
});
|
|
5496
5518
|
}
|
|
5497
|
-
|
|
5498
|
-
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth - removeWidth, height: labelHeight, part: "line" });
|
|
5519
|
+
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth, height: labelHeight, part: "line" });
|
|
5499
5520
|
alertRegions.push({ id: alert.id, x: chartLeft, y: lineY - 5, width: chartRight - chartLeft, height: 10, part: "line" });
|
|
5500
5521
|
};
|
|
5501
5522
|
const drawOrderLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
@@ -8480,30 +8501,42 @@ function createChart(element, options = {}) {
|
|
|
8480
8501
|
ctx.fill();
|
|
8481
8502
|
cursorX += dotRadius * 2 + 6;
|
|
8482
8503
|
}
|
|
8483
|
-
const headline = [
|
|
8504
|
+
const headline = [
|
|
8505
|
+
dataLine.symbol,
|
|
8506
|
+
dataLine.description,
|
|
8507
|
+
dataLine.interval,
|
|
8508
|
+
dataLine.exchange,
|
|
8509
|
+
dataLine.chartTypeLabel
|
|
8510
|
+
].filter((part) => part && part.length > 0).join(" \xB7 ");
|
|
8484
8511
|
if (headline) {
|
|
8485
8512
|
ctx.fillStyle = symbolColor;
|
|
8486
8513
|
ctx.fillText(headline, cursorX, rowY);
|
|
8487
|
-
cursorX += measureTextWidth(headline) +
|
|
8514
|
+
cursorX += measureTextWidth(headline) + 12;
|
|
8488
8515
|
}
|
|
8489
8516
|
if (dataLine.showOhlc !== false) {
|
|
8490
|
-
const
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8517
|
+
const ohlcLabelColor = dataLine.ohlcLabelColor || textColor;
|
|
8518
|
+
const pairs = [
|
|
8519
|
+
["O", formatPrice(bar.o)],
|
|
8520
|
+
["H", formatPrice(bar.h)],
|
|
8521
|
+
["L", formatPrice(bar.l)],
|
|
8522
|
+
["C", formatPrice(bar.c)]
|
|
8523
|
+
];
|
|
8524
|
+
for (const [label, value] of pairs) {
|
|
8525
|
+
ctx.fillStyle = ohlcLabelColor;
|
|
8526
|
+
ctx.fillText(label, cursorX, rowY);
|
|
8527
|
+
cursorX += measureTextWidth(label) + 2;
|
|
8528
|
+
ctx.fillStyle = changeColor;
|
|
8529
|
+
ctx.fillText(value, cursorX, rowY);
|
|
8530
|
+
cursorX += measureTextWidth(value) + 9;
|
|
8531
|
+
}
|
|
8532
|
+
cursorX += 3;
|
|
8494
8533
|
}
|
|
8495
8534
|
if (dataLine.showChange !== false) {
|
|
8496
8535
|
const pct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
8497
8536
|
const changeText = `${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${pct.toFixed(2)}%)`;
|
|
8498
8537
|
ctx.fillStyle = changeColor;
|
|
8499
8538
|
ctx.fillText(changeText, cursorX, rowY);
|
|
8500
|
-
cursorX += measureTextWidth(changeText) +
|
|
8501
|
-
}
|
|
8502
|
-
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8503
|
-
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8504
|
-
ctx.fillStyle = textColor;
|
|
8505
|
-
ctx.fillText(volumeText, cursorX, rowY);
|
|
8506
|
-
cursorX += measureTextWidth(volumeText) + 10;
|
|
8539
|
+
cursorX += measureTextWidth(changeText) + 12;
|
|
8507
8540
|
}
|
|
8508
8541
|
for (const detail of dataLine.details ?? []) {
|
|
8509
8542
|
const text = detail.label ? `${detail.label} ${detail.value}` : detail.value;
|
|
@@ -8517,7 +8550,14 @@ function createChart(element, options = {}) {
|
|
|
8517
8550
|
ctx.fillText(text, cursorX, rowY);
|
|
8518
8551
|
cursorX += width2 + 12;
|
|
8519
8552
|
}
|
|
8520
|
-
|
|
8553
|
+
let lastRowY = rowY;
|
|
8554
|
+
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8555
|
+
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8556
|
+
lastRowY = rowY + fontSize + 4;
|
|
8557
|
+
ctx.fillStyle = textColor;
|
|
8558
|
+
ctx.fillText(volumeText, chartLeft + legendInsetX, lastRowY);
|
|
8559
|
+
}
|
|
8560
|
+
dataLineBottom = lastRowY + fontSize + 6;
|
|
8521
8561
|
ctx.font = prevFont;
|
|
8522
8562
|
}
|
|
8523
8563
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -697,15 +697,26 @@ interface DataLineOptions {
|
|
|
697
697
|
visible?: boolean;
|
|
698
698
|
/** e.g. "NQU6" — drawn first, in the emphasis color. */
|
|
699
699
|
symbol?: string;
|
|
700
|
+
/**
|
|
701
|
+
* Long instrument name, e.g. "NASDAQ 100 E-mini Futures". Drawn after the
|
|
702
|
+
* symbol in the emphasis color, the way other charting platforms label a
|
|
703
|
+
* pane. Omit to keep the headline to the code alone.
|
|
704
|
+
*/
|
|
705
|
+
description?: string;
|
|
700
706
|
/** e.g. "1h". */
|
|
701
707
|
interval?: string;
|
|
702
708
|
/** e.g. "CME". */
|
|
703
709
|
exchange?: string;
|
|
710
|
+
/**
|
|
711
|
+
* Chart style, e.g. "Candles" or "Renko [ATR(14), 1000]" — the last part of
|
|
712
|
+
* the headline, so a non-default style is never a surprise.
|
|
713
|
+
*/
|
|
714
|
+
chartTypeLabel?: string;
|
|
704
715
|
/** O/H/L/C values for the hovered (or latest) bar. Default true. */
|
|
705
716
|
showOhlc?: boolean;
|
|
706
717
|
/** Absolute and percent change of that bar, colored by direction. Default true. */
|
|
707
718
|
showChange?: boolean;
|
|
708
|
-
/** Bar volume. Default false. */
|
|
719
|
+
/** Bar volume. Drawn on its own row beneath the values. Default false. */
|
|
709
720
|
showVolume?: boolean;
|
|
710
721
|
/**
|
|
711
722
|
* Extra chips after the values — session, currency, a "Closed" badge. Each
|
|
@@ -724,6 +735,12 @@ interface DataLineOptions {
|
|
|
724
735
|
symbolColor?: string;
|
|
725
736
|
/** Everything after the symbol. Defaults to the indicator legend color. */
|
|
726
737
|
textColor?: string;
|
|
738
|
+
/**
|
|
739
|
+
* Color of the O/H/L/C letters. Values stay colored by direction, so dimming
|
|
740
|
+
* the letters is what makes the numbers readable at a glance rather than one
|
|
741
|
+
* run of same-colored text. Defaults to `textColor`.
|
|
742
|
+
*/
|
|
743
|
+
ohlcLabelColor?: string;
|
|
727
744
|
}
|
|
728
745
|
interface IndicatorUpdateOptions {
|
|
729
746
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -697,15 +697,26 @@ interface DataLineOptions {
|
|
|
697
697
|
visible?: boolean;
|
|
698
698
|
/** e.g. "NQU6" — drawn first, in the emphasis color. */
|
|
699
699
|
symbol?: string;
|
|
700
|
+
/**
|
|
701
|
+
* Long instrument name, e.g. "NASDAQ 100 E-mini Futures". Drawn after the
|
|
702
|
+
* symbol in the emphasis color, the way other charting platforms label a
|
|
703
|
+
* pane. Omit to keep the headline to the code alone.
|
|
704
|
+
*/
|
|
705
|
+
description?: string;
|
|
700
706
|
/** e.g. "1h". */
|
|
701
707
|
interval?: string;
|
|
702
708
|
/** e.g. "CME". */
|
|
703
709
|
exchange?: string;
|
|
710
|
+
/**
|
|
711
|
+
* Chart style, e.g. "Candles" or "Renko [ATR(14), 1000]" — the last part of
|
|
712
|
+
* the headline, so a non-default style is never a surprise.
|
|
713
|
+
*/
|
|
714
|
+
chartTypeLabel?: string;
|
|
704
715
|
/** O/H/L/C values for the hovered (or latest) bar. Default true. */
|
|
705
716
|
showOhlc?: boolean;
|
|
706
717
|
/** Absolute and percent change of that bar, colored by direction. Default true. */
|
|
707
718
|
showChange?: boolean;
|
|
708
|
-
/** Bar volume. Default false. */
|
|
719
|
+
/** Bar volume. Drawn on its own row beneath the values. Default false. */
|
|
709
720
|
showVolume?: boolean;
|
|
710
721
|
/**
|
|
711
722
|
* Extra chips after the values — session, currency, a "Closed" badge. Each
|
|
@@ -724,6 +735,12 @@ interface DataLineOptions {
|
|
|
724
735
|
symbolColor?: string;
|
|
725
736
|
/** Everything after the symbol. Defaults to the indicator legend color. */
|
|
726
737
|
textColor?: string;
|
|
738
|
+
/**
|
|
739
|
+
* Color of the O/H/L/C letters. Values stay colored by direction, so dimming
|
|
740
|
+
* the letters is what makes the numbers readable at a glance rather than one
|
|
741
|
+
* run of same-colored text. Defaults to `textColor`.
|
|
742
|
+
*/
|
|
743
|
+
ohlcLabelColor?: string;
|
|
727
744
|
}
|
|
728
745
|
interface IndicatorUpdateOptions {
|
|
729
746
|
/**
|
package/dist/index.js
CHANGED
|
@@ -5400,6 +5400,32 @@ function createChart(element, options = {}) {
|
|
|
5400
5400
|
ctx.fill();
|
|
5401
5401
|
ctx.restore();
|
|
5402
5402
|
};
|
|
5403
|
+
const drawTrashGlyph = (x, y, size, color) => {
|
|
5404
|
+
const w = size * 0.8;
|
|
5405
|
+
const h = size * 0.9;
|
|
5406
|
+
ctx.save();
|
|
5407
|
+
ctx.strokeStyle = color;
|
|
5408
|
+
ctx.lineWidth = 1.2;
|
|
5409
|
+
ctx.lineCap = "round";
|
|
5410
|
+
ctx.lineJoin = "round";
|
|
5411
|
+
ctx.beginPath();
|
|
5412
|
+
ctx.moveTo(x - w / 2, y - h * 0.28);
|
|
5413
|
+
ctx.lineTo(x + w / 2, y - h * 0.28);
|
|
5414
|
+
ctx.moveTo(x - w * 0.22, y - h * 0.28);
|
|
5415
|
+
ctx.lineTo(x - w * 0.22, y - h * 0.46);
|
|
5416
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.46);
|
|
5417
|
+
ctx.lineTo(x + w * 0.22, y - h * 0.28);
|
|
5418
|
+
ctx.moveTo(x - w * 0.36, y - h * 0.28);
|
|
5419
|
+
ctx.lineTo(x - w * 0.28, y + h * 0.48);
|
|
5420
|
+
ctx.lineTo(x + w * 0.28, y + h * 0.48);
|
|
5421
|
+
ctx.lineTo(x + w * 0.36, y - h * 0.28);
|
|
5422
|
+
ctx.moveTo(x - w * 0.1, y - h * 0.08);
|
|
5423
|
+
ctx.lineTo(x - w * 0.1, y + h * 0.3);
|
|
5424
|
+
ctx.moveTo(x + w * 0.1, y - h * 0.08);
|
|
5425
|
+
ctx.lineTo(x + w * 0.1, y + h * 0.3);
|
|
5426
|
+
ctx.stroke();
|
|
5427
|
+
ctx.restore();
|
|
5428
|
+
};
|
|
5403
5429
|
const drawAlertLine = (alert, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
5404
5430
|
const lineY = getLineY(alert.price, yFromPrice, chartTop, chartBottom, false);
|
|
5405
5431
|
if (lineY === null) return;
|
|
@@ -5418,13 +5444,11 @@ function createChart(element, options = {}) {
|
|
|
5418
5444
|
ctx.restore();
|
|
5419
5445
|
const fontSize = Math.max(8, axis.fontSize);
|
|
5420
5446
|
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
5421
|
-
const text = alert.label ? `${formatPrice(alert.price)} ${alert.label}` : formatPrice(alert.price);
|
|
5422
5447
|
const paddingX = 6;
|
|
5423
5448
|
const bellWidth = fontSize + 2;
|
|
5424
5449
|
const labelHeight = 20;
|
|
5425
5450
|
const hovered = hoveredAlertId === alert.id;
|
|
5426
|
-
const
|
|
5427
|
-
const contentWidth = Math.ceil(measureTextWidth(text)) + bellWidth + paddingX * 3 + removeWidth;
|
|
5451
|
+
const contentWidth = bellWidth + paddingX * 2;
|
|
5428
5452
|
const labelWidth = getRightAxisLabelWidth(chartRight, contentWidth);
|
|
5429
5453
|
const labelX = getRightAxisLabelX(chartRight);
|
|
5430
5454
|
const labelY = placeRightAxisLabel(lineY - labelHeight / 2, labelHeight, chartTop, chartBottom - labelHeight);
|
|
@@ -5434,29 +5458,26 @@ function createChart(element, options = {}) {
|
|
|
5434
5458
|
fillRoundedRect(Math.round(labelX), Math.round(labelY), labelWidth, labelHeight, 3);
|
|
5435
5459
|
const inkColor = labelTextColorOn(color, "#101114");
|
|
5436
5460
|
drawBellGlyph(labelX + paddingX + bellWidth / 2, labelY + labelHeight / 2, fontSize, inkColor);
|
|
5437
|
-
|
|
5461
|
+
ctx.restore();
|
|
5438
5462
|
if (hovered) {
|
|
5439
|
-
const
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
ctx.
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
ctx.
|
|
5447
|
-
ctx.lineTo(removeX + inset, labelY + labelHeight - inset);
|
|
5448
|
-
ctx.stroke();
|
|
5463
|
+
const buttonSize = labelHeight;
|
|
5464
|
+
const buttonX = chartLeft + 10;
|
|
5465
|
+
const buttonY = lineY - buttonSize / 2;
|
|
5466
|
+
ctx.save();
|
|
5467
|
+
ctx.fillStyle = color;
|
|
5468
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, 3);
|
|
5469
|
+
drawTrashGlyph(buttonX + buttonSize / 2, lineY, fontSize, inkColor);
|
|
5470
|
+
ctx.restore();
|
|
5449
5471
|
alertRegions.push({
|
|
5450
5472
|
id: alert.id,
|
|
5451
|
-
x:
|
|
5452
|
-
y:
|
|
5453
|
-
width:
|
|
5454
|
-
height:
|
|
5473
|
+
x: buttonX,
|
|
5474
|
+
y: buttonY,
|
|
5475
|
+
width: buttonSize,
|
|
5476
|
+
height: buttonSize,
|
|
5455
5477
|
part: "remove"
|
|
5456
5478
|
});
|
|
5457
5479
|
}
|
|
5458
|
-
|
|
5459
|
-
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth - removeWidth, height: labelHeight, part: "line" });
|
|
5480
|
+
alertRegions.push({ id: alert.id, x: labelX, y: labelY, width: labelWidth, height: labelHeight, part: "line" });
|
|
5460
5481
|
alertRegions.push({ id: alert.id, x: chartLeft, y: lineY - 5, width: chartRight - chartLeft, height: 10, part: "line" });
|
|
5461
5482
|
};
|
|
5462
5483
|
const drawOrderLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
@@ -8441,30 +8462,42 @@ function createChart(element, options = {}) {
|
|
|
8441
8462
|
ctx.fill();
|
|
8442
8463
|
cursorX += dotRadius * 2 + 6;
|
|
8443
8464
|
}
|
|
8444
|
-
const headline = [
|
|
8465
|
+
const headline = [
|
|
8466
|
+
dataLine.symbol,
|
|
8467
|
+
dataLine.description,
|
|
8468
|
+
dataLine.interval,
|
|
8469
|
+
dataLine.exchange,
|
|
8470
|
+
dataLine.chartTypeLabel
|
|
8471
|
+
].filter((part) => part && part.length > 0).join(" \xB7 ");
|
|
8445
8472
|
if (headline) {
|
|
8446
8473
|
ctx.fillStyle = symbolColor;
|
|
8447
8474
|
ctx.fillText(headline, cursorX, rowY);
|
|
8448
|
-
cursorX += measureTextWidth(headline) +
|
|
8475
|
+
cursorX += measureTextWidth(headline) + 12;
|
|
8449
8476
|
}
|
|
8450
8477
|
if (dataLine.showOhlc !== false) {
|
|
8451
|
-
const
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8478
|
+
const ohlcLabelColor = dataLine.ohlcLabelColor || textColor;
|
|
8479
|
+
const pairs = [
|
|
8480
|
+
["O", formatPrice(bar.o)],
|
|
8481
|
+
["H", formatPrice(bar.h)],
|
|
8482
|
+
["L", formatPrice(bar.l)],
|
|
8483
|
+
["C", formatPrice(bar.c)]
|
|
8484
|
+
];
|
|
8485
|
+
for (const [label, value] of pairs) {
|
|
8486
|
+
ctx.fillStyle = ohlcLabelColor;
|
|
8487
|
+
ctx.fillText(label, cursorX, rowY);
|
|
8488
|
+
cursorX += measureTextWidth(label) + 2;
|
|
8489
|
+
ctx.fillStyle = changeColor;
|
|
8490
|
+
ctx.fillText(value, cursorX, rowY);
|
|
8491
|
+
cursorX += measureTextWidth(value) + 9;
|
|
8492
|
+
}
|
|
8493
|
+
cursorX += 3;
|
|
8455
8494
|
}
|
|
8456
8495
|
if (dataLine.showChange !== false) {
|
|
8457
8496
|
const pct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
8458
8497
|
const changeText = `${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${pct.toFixed(2)}%)`;
|
|
8459
8498
|
ctx.fillStyle = changeColor;
|
|
8460
8499
|
ctx.fillText(changeText, cursorX, rowY);
|
|
8461
|
-
cursorX += measureTextWidth(changeText) +
|
|
8462
|
-
}
|
|
8463
|
-
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8464
|
-
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8465
|
-
ctx.fillStyle = textColor;
|
|
8466
|
-
ctx.fillText(volumeText, cursorX, rowY);
|
|
8467
|
-
cursorX += measureTextWidth(volumeText) + 10;
|
|
8500
|
+
cursorX += measureTextWidth(changeText) + 12;
|
|
8468
8501
|
}
|
|
8469
8502
|
for (const detail of dataLine.details ?? []) {
|
|
8470
8503
|
const text = detail.label ? `${detail.label} ${detail.value}` : detail.value;
|
|
@@ -8478,7 +8511,14 @@ function createChart(element, options = {}) {
|
|
|
8478
8511
|
ctx.fillText(text, cursorX, rowY);
|
|
8479
8512
|
cursorX += width2 + 12;
|
|
8480
8513
|
}
|
|
8481
|
-
|
|
8514
|
+
let lastRowY = rowY;
|
|
8515
|
+
if (dataLine.showVolume && bar.v !== void 0) {
|
|
8516
|
+
const volumeText = `Vol ${bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v))}`;
|
|
8517
|
+
lastRowY = rowY + fontSize + 4;
|
|
8518
|
+
ctx.fillStyle = textColor;
|
|
8519
|
+
ctx.fillText(volumeText, chartLeft + legendInsetX, lastRowY);
|
|
8520
|
+
}
|
|
8521
|
+
dataLineBottom = lastRowY + fontSize + 6;
|
|
8482
8522
|
ctx.font = prevFont;
|
|
8483
8523
|
}
|
|
8484
8524
|
}
|