hyperprop-charting-library 0.1.79 → 0.1.81
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 +57 -18
- package/dist/hyperprop-charting-library.d.ts +9 -1
- package/dist/hyperprop-charting-library.js +57 -18
- package/dist/index.cjs +57 -18
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +57 -18
- package/docs/API.md +2 -1
- package/package.json +1 -1
|
@@ -961,6 +961,13 @@ function createChart(element, options = {}) {
|
|
|
961
961
|
style: drawing.style ?? "dotted",
|
|
962
962
|
width: Math.max(1, Number(drawing.width) || 1),
|
|
963
963
|
locked: drawing.locked ?? false,
|
|
964
|
+
accountSize: Number(drawing.accountSize) || 0,
|
|
965
|
+
lotSize: Number(drawing.lotSize) || 1,
|
|
966
|
+
risk: Number(drawing.risk) || 0,
|
|
967
|
+
riskMode: drawing.riskMode === "amount" ? "amount" : "percent",
|
|
968
|
+
leverage: Number(drawing.leverage) || 1,
|
|
969
|
+
pointValue: Number(drawing.pointValue) || 1,
|
|
970
|
+
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
964
971
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
965
972
|
});
|
|
966
973
|
const serializeDrawing = (drawing) => ({
|
|
@@ -973,6 +980,13 @@ function createChart(element, options = {}) {
|
|
|
973
980
|
style: drawing.style,
|
|
974
981
|
width: drawing.width,
|
|
975
982
|
locked: drawing.locked,
|
|
983
|
+
accountSize: drawing.accountSize,
|
|
984
|
+
lotSize: drawing.lotSize,
|
|
985
|
+
risk: drawing.risk,
|
|
986
|
+
riskMode: drawing.riskMode,
|
|
987
|
+
leverage: drawing.leverage,
|
|
988
|
+
pointValue: drawing.pointValue,
|
|
989
|
+
qtyPrecision: drawing.qtyPrecision,
|
|
976
990
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
977
991
|
});
|
|
978
992
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -982,6 +996,7 @@ function createChart(element, options = {}) {
|
|
|
982
996
|
let drawingDragState = null;
|
|
983
997
|
let drawingsChangeHandler = null;
|
|
984
998
|
let drawingSelectHandler = null;
|
|
999
|
+
let drawingDoubleClickHandler = null;
|
|
985
1000
|
let drawingHoverHandler = null;
|
|
986
1001
|
let lastHoveredDrawingId = null;
|
|
987
1002
|
let selectedDrawingId = null;
|
|
@@ -2429,20 +2444,6 @@ function createChart(element, options = {}) {
|
|
|
2429
2444
|
ctx.fillStyle = lossFill;
|
|
2430
2445
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2431
2446
|
ctx.restore();
|
|
2432
|
-
if (data.length > 0) {
|
|
2433
|
-
const nowX = xFromDrawingPoint({ index: data.length - 1, price: 0 });
|
|
2434
|
-
const darkRight = clamp(nowX, boxX0, boxX1);
|
|
2435
|
-
if (darkRight - boxX0 > 0.5) {
|
|
2436
|
-
const darkW = darkRight - boxX0;
|
|
2437
|
-
ctx.save();
|
|
2438
|
-
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
2439
|
-
ctx.fillStyle = hexToRgba(profitColor, 0.18);
|
|
2440
|
-
ctx.fillRect(boxX0, Math.min(entryY, targetY), darkW, Math.abs(targetY - entryY));
|
|
2441
|
-
ctx.fillStyle = hexToRgba(lossColor, 0.18);
|
|
2442
|
-
ctx.fillRect(boxX0, Math.min(entryY, stopY), darkW, Math.abs(stopY - entryY));
|
|
2443
|
-
ctx.restore();
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
2447
|
if (isSelected) {
|
|
2447
2448
|
ctx.save();
|
|
2448
2449
|
ctx.setLineDash([]);
|
|
@@ -2477,6 +2478,14 @@ function createChart(element, options = {}) {
|
|
|
2477
2478
|
const stopDist = Math.abs(entry.price - stop.price);
|
|
2478
2479
|
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2479
2480
|
const cx = (boxX0 + boxX1) / 2;
|
|
2481
|
+
const effectivePointValue = (drawing.pointValue > 0 ? drawing.pointValue : 1) * (drawing.lotSize > 0 ? drawing.lotSize : 1);
|
|
2482
|
+
const riskAmount = drawing.riskMode === "amount" ? drawing.risk : drawing.accountSize * (drawing.risk / 100);
|
|
2483
|
+
const qtyRaw = riskAmount > 0 && stopDist > 0 ? riskAmount / (stopDist * effectivePointValue) : 0;
|
|
2484
|
+
const hasMoney = qtyRaw > 0 && Number.isFinite(qtyRaw);
|
|
2485
|
+
const qtyText = hasMoney ? qtyRaw.toFixed(Math.max(0, drawing.qtyPrecision)) : "";
|
|
2486
|
+
const formatAmount = (value) => Math.abs(value) >= 1e3 ? value.toFixed(0) : value.toFixed(2);
|
|
2487
|
+
const targetAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * targetDist * effectivePointValue)}` : "";
|
|
2488
|
+
const stopAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * stopDist * effectivePointValue)}` : "";
|
|
2480
2489
|
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2481
2490
|
const prevFont = ctx.font;
|
|
2482
2491
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
@@ -2494,9 +2503,14 @@ function createChart(element, options = {}) {
|
|
|
2494
2503
|
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2495
2504
|
ctx.font = prevFont;
|
|
2496
2505
|
};
|
|
2497
|
-
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2498
|
-
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2499
|
-
drawPositionPill(
|
|
2506
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}${targetAmountText}`, cx, targetY, profitLine);
|
|
2507
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}${stopAmountText}`, cx, stopY, lossLine);
|
|
2508
|
+
drawPositionPill(
|
|
2509
|
+
hasMoney ? `Entry ${formatPrice(entry.price)} Qty ${qtyText} RR ${rr.toFixed(2)}` : `Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`,
|
|
2510
|
+
cx,
|
|
2511
|
+
entryY,
|
|
2512
|
+
hexToRgba(drawing.color, 0.92)
|
|
2513
|
+
);
|
|
2500
2514
|
if (drawing.label) {
|
|
2501
2515
|
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2502
2516
|
}
|
|
@@ -3959,7 +3973,14 @@ function createChart(element, options = {}) {
|
|
|
3959
3973
|
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3960
3974
|
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3961
3975
|
style: defaults.style ?? "solid",
|
|
3962
|
-
width: defaults.width ?? 1
|
|
3976
|
+
width: defaults.width ?? 1,
|
|
3977
|
+
...defaults.accountSize === void 0 ? {} : { accountSize: defaults.accountSize },
|
|
3978
|
+
...defaults.lotSize === void 0 ? {} : { lotSize: defaults.lotSize },
|
|
3979
|
+
...defaults.risk === void 0 ? {} : { risk: defaults.risk },
|
|
3980
|
+
...defaults.riskMode === void 0 ? {} : { riskMode: defaults.riskMode },
|
|
3981
|
+
...defaults.leverage === void 0 ? {} : { leverage: defaults.leverage },
|
|
3982
|
+
...defaults.pointValue === void 0 ? {} : { pointValue: defaults.pointValue },
|
|
3983
|
+
...defaults.qtyPrecision === void 0 ? {} : { qtyPrecision: defaults.qtyPrecision }
|
|
3963
3984
|
})
|
|
3964
3985
|
);
|
|
3965
3986
|
emitDrawingsChange();
|
|
@@ -4529,6 +4550,20 @@ function createChart(element, options = {}) {
|
|
|
4529
4550
|
if (region === "outside") {
|
|
4530
4551
|
return;
|
|
4531
4552
|
}
|
|
4553
|
+
if (region === "plot" && !activeDrawingTool) {
|
|
4554
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4555
|
+
if (drawingHit) {
|
|
4556
|
+
selectedDrawingId = drawingHit.drawing.id;
|
|
4557
|
+
drawingDoubleClickHandler?.({
|
|
4558
|
+
drawing: serializeDrawing(drawingHit.drawing),
|
|
4559
|
+
target: drawingHit.target,
|
|
4560
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4561
|
+
x: point.x,
|
|
4562
|
+
y: point.y
|
|
4563
|
+
});
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4532
4567
|
if (doubleClickAction === "placeLimitOrder") {
|
|
4533
4568
|
if (region !== "plot") {
|
|
4534
4569
|
return;
|
|
@@ -4839,6 +4874,9 @@ function createChart(element, options = {}) {
|
|
|
4839
4874
|
const onDrawingSelect = (handler) => {
|
|
4840
4875
|
drawingSelectHandler = handler;
|
|
4841
4876
|
};
|
|
4877
|
+
const onDrawingDoubleClick = (handler) => {
|
|
4878
|
+
drawingDoubleClickHandler = handler;
|
|
4879
|
+
};
|
|
4842
4880
|
const onDrawingHover = (handler) => {
|
|
4843
4881
|
drawingHoverHandler = handler;
|
|
4844
4882
|
};
|
|
@@ -4896,6 +4934,7 @@ function createChart(element, options = {}) {
|
|
|
4896
4934
|
clearDrawings,
|
|
4897
4935
|
onDrawingsChange,
|
|
4898
4936
|
onDrawingSelect,
|
|
4937
|
+
onDrawingDoubleClick,
|
|
4899
4938
|
setSelectedDrawing,
|
|
4900
4939
|
onDrawingHover,
|
|
4901
4940
|
setDrawingDefaults,
|
|
@@ -66,6 +66,13 @@ interface DrawingObjectOptions {
|
|
|
66
66
|
width?: number;
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
|
+
accountSize?: number;
|
|
70
|
+
lotSize?: number;
|
|
71
|
+
risk?: number;
|
|
72
|
+
riskMode?: "percent" | "amount";
|
|
73
|
+
leverage?: number;
|
|
74
|
+
pointValue?: number;
|
|
75
|
+
qtyPrecision?: number;
|
|
69
76
|
}
|
|
70
77
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
78
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -84,7 +91,7 @@ interface DrawingHoverEvent {
|
|
|
84
91
|
x: number;
|
|
85
92
|
y: number;
|
|
86
93
|
}
|
|
87
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width">>;
|
|
94
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
88
95
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
89
96
|
id?: string;
|
|
90
97
|
type: string;
|
|
@@ -420,6 +427,7 @@ interface ChartInstance {
|
|
|
420
427
|
clearDrawings: () => void;
|
|
421
428
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
422
429
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
|
+
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
423
431
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
424
432
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
433
|
setSelectedDrawing: (id: string | null) => void;
|
|
@@ -935,6 +935,13 @@ function createChart(element, options = {}) {
|
|
|
935
935
|
style: drawing.style ?? "dotted",
|
|
936
936
|
width: Math.max(1, Number(drawing.width) || 1),
|
|
937
937
|
locked: drawing.locked ?? false,
|
|
938
|
+
accountSize: Number(drawing.accountSize) || 0,
|
|
939
|
+
lotSize: Number(drawing.lotSize) || 1,
|
|
940
|
+
risk: Number(drawing.risk) || 0,
|
|
941
|
+
riskMode: drawing.riskMode === "amount" ? "amount" : "percent",
|
|
942
|
+
leverage: Number(drawing.leverage) || 1,
|
|
943
|
+
pointValue: Number(drawing.pointValue) || 1,
|
|
944
|
+
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
938
945
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
939
946
|
});
|
|
940
947
|
const serializeDrawing = (drawing) => ({
|
|
@@ -947,6 +954,13 @@ function createChart(element, options = {}) {
|
|
|
947
954
|
style: drawing.style,
|
|
948
955
|
width: drawing.width,
|
|
949
956
|
locked: drawing.locked,
|
|
957
|
+
accountSize: drawing.accountSize,
|
|
958
|
+
lotSize: drawing.lotSize,
|
|
959
|
+
risk: drawing.risk,
|
|
960
|
+
riskMode: drawing.riskMode,
|
|
961
|
+
leverage: drawing.leverage,
|
|
962
|
+
pointValue: drawing.pointValue,
|
|
963
|
+
qtyPrecision: drawing.qtyPrecision,
|
|
950
964
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
951
965
|
});
|
|
952
966
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -956,6 +970,7 @@ function createChart(element, options = {}) {
|
|
|
956
970
|
let drawingDragState = null;
|
|
957
971
|
let drawingsChangeHandler = null;
|
|
958
972
|
let drawingSelectHandler = null;
|
|
973
|
+
let drawingDoubleClickHandler = null;
|
|
959
974
|
let drawingHoverHandler = null;
|
|
960
975
|
let lastHoveredDrawingId = null;
|
|
961
976
|
let selectedDrawingId = null;
|
|
@@ -2403,20 +2418,6 @@ function createChart(element, options = {}) {
|
|
|
2403
2418
|
ctx.fillStyle = lossFill;
|
|
2404
2419
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2405
2420
|
ctx.restore();
|
|
2406
|
-
if (data.length > 0) {
|
|
2407
|
-
const nowX = xFromDrawingPoint({ index: data.length - 1, price: 0 });
|
|
2408
|
-
const darkRight = clamp(nowX, boxX0, boxX1);
|
|
2409
|
-
if (darkRight - boxX0 > 0.5) {
|
|
2410
|
-
const darkW = darkRight - boxX0;
|
|
2411
|
-
ctx.save();
|
|
2412
|
-
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
2413
|
-
ctx.fillStyle = hexToRgba(profitColor, 0.18);
|
|
2414
|
-
ctx.fillRect(boxX0, Math.min(entryY, targetY), darkW, Math.abs(targetY - entryY));
|
|
2415
|
-
ctx.fillStyle = hexToRgba(lossColor, 0.18);
|
|
2416
|
-
ctx.fillRect(boxX0, Math.min(entryY, stopY), darkW, Math.abs(stopY - entryY));
|
|
2417
|
-
ctx.restore();
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
2421
|
if (isSelected) {
|
|
2421
2422
|
ctx.save();
|
|
2422
2423
|
ctx.setLineDash([]);
|
|
@@ -2451,6 +2452,14 @@ function createChart(element, options = {}) {
|
|
|
2451
2452
|
const stopDist = Math.abs(entry.price - stop.price);
|
|
2452
2453
|
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2453
2454
|
const cx = (boxX0 + boxX1) / 2;
|
|
2455
|
+
const effectivePointValue = (drawing.pointValue > 0 ? drawing.pointValue : 1) * (drawing.lotSize > 0 ? drawing.lotSize : 1);
|
|
2456
|
+
const riskAmount = drawing.riskMode === "amount" ? drawing.risk : drawing.accountSize * (drawing.risk / 100);
|
|
2457
|
+
const qtyRaw = riskAmount > 0 && stopDist > 0 ? riskAmount / (stopDist * effectivePointValue) : 0;
|
|
2458
|
+
const hasMoney = qtyRaw > 0 && Number.isFinite(qtyRaw);
|
|
2459
|
+
const qtyText = hasMoney ? qtyRaw.toFixed(Math.max(0, drawing.qtyPrecision)) : "";
|
|
2460
|
+
const formatAmount = (value) => Math.abs(value) >= 1e3 ? value.toFixed(0) : value.toFixed(2);
|
|
2461
|
+
const targetAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * targetDist * effectivePointValue)}` : "";
|
|
2462
|
+
const stopAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * stopDist * effectivePointValue)}` : "";
|
|
2454
2463
|
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2455
2464
|
const prevFont = ctx.font;
|
|
2456
2465
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
@@ -2468,9 +2477,14 @@ function createChart(element, options = {}) {
|
|
|
2468
2477
|
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2469
2478
|
ctx.font = prevFont;
|
|
2470
2479
|
};
|
|
2471
|
-
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2472
|
-
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2473
|
-
drawPositionPill(
|
|
2480
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}${targetAmountText}`, cx, targetY, profitLine);
|
|
2481
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}${stopAmountText}`, cx, stopY, lossLine);
|
|
2482
|
+
drawPositionPill(
|
|
2483
|
+
hasMoney ? `Entry ${formatPrice(entry.price)} Qty ${qtyText} RR ${rr.toFixed(2)}` : `Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`,
|
|
2484
|
+
cx,
|
|
2485
|
+
entryY,
|
|
2486
|
+
hexToRgba(drawing.color, 0.92)
|
|
2487
|
+
);
|
|
2474
2488
|
if (drawing.label) {
|
|
2475
2489
|
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2476
2490
|
}
|
|
@@ -3933,7 +3947,14 @@ function createChart(element, options = {}) {
|
|
|
3933
3947
|
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3934
3948
|
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3935
3949
|
style: defaults.style ?? "solid",
|
|
3936
|
-
width: defaults.width ?? 1
|
|
3950
|
+
width: defaults.width ?? 1,
|
|
3951
|
+
...defaults.accountSize === void 0 ? {} : { accountSize: defaults.accountSize },
|
|
3952
|
+
...defaults.lotSize === void 0 ? {} : { lotSize: defaults.lotSize },
|
|
3953
|
+
...defaults.risk === void 0 ? {} : { risk: defaults.risk },
|
|
3954
|
+
...defaults.riskMode === void 0 ? {} : { riskMode: defaults.riskMode },
|
|
3955
|
+
...defaults.leverage === void 0 ? {} : { leverage: defaults.leverage },
|
|
3956
|
+
...defaults.pointValue === void 0 ? {} : { pointValue: defaults.pointValue },
|
|
3957
|
+
...defaults.qtyPrecision === void 0 ? {} : { qtyPrecision: defaults.qtyPrecision }
|
|
3937
3958
|
})
|
|
3938
3959
|
);
|
|
3939
3960
|
emitDrawingsChange();
|
|
@@ -4503,6 +4524,20 @@ function createChart(element, options = {}) {
|
|
|
4503
4524
|
if (region === "outside") {
|
|
4504
4525
|
return;
|
|
4505
4526
|
}
|
|
4527
|
+
if (region === "plot" && !activeDrawingTool) {
|
|
4528
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4529
|
+
if (drawingHit) {
|
|
4530
|
+
selectedDrawingId = drawingHit.drawing.id;
|
|
4531
|
+
drawingDoubleClickHandler?.({
|
|
4532
|
+
drawing: serializeDrawing(drawingHit.drawing),
|
|
4533
|
+
target: drawingHit.target,
|
|
4534
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4535
|
+
x: point.x,
|
|
4536
|
+
y: point.y
|
|
4537
|
+
});
|
|
4538
|
+
return;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4506
4541
|
if (doubleClickAction === "placeLimitOrder") {
|
|
4507
4542
|
if (region !== "plot") {
|
|
4508
4543
|
return;
|
|
@@ -4813,6 +4848,9 @@ function createChart(element, options = {}) {
|
|
|
4813
4848
|
const onDrawingSelect = (handler) => {
|
|
4814
4849
|
drawingSelectHandler = handler;
|
|
4815
4850
|
};
|
|
4851
|
+
const onDrawingDoubleClick = (handler) => {
|
|
4852
|
+
drawingDoubleClickHandler = handler;
|
|
4853
|
+
};
|
|
4816
4854
|
const onDrawingHover = (handler) => {
|
|
4817
4855
|
drawingHoverHandler = handler;
|
|
4818
4856
|
};
|
|
@@ -4870,6 +4908,7 @@ function createChart(element, options = {}) {
|
|
|
4870
4908
|
clearDrawings,
|
|
4871
4909
|
onDrawingsChange,
|
|
4872
4910
|
onDrawingSelect,
|
|
4911
|
+
onDrawingDoubleClick,
|
|
4873
4912
|
setSelectedDrawing,
|
|
4874
4913
|
onDrawingHover,
|
|
4875
4914
|
setDrawingDefaults,
|
package/dist/index.cjs
CHANGED
|
@@ -961,6 +961,13 @@ function createChart(element, options = {}) {
|
|
|
961
961
|
style: drawing.style ?? "dotted",
|
|
962
962
|
width: Math.max(1, Number(drawing.width) || 1),
|
|
963
963
|
locked: drawing.locked ?? false,
|
|
964
|
+
accountSize: Number(drawing.accountSize) || 0,
|
|
965
|
+
lotSize: Number(drawing.lotSize) || 1,
|
|
966
|
+
risk: Number(drawing.risk) || 0,
|
|
967
|
+
riskMode: drawing.riskMode === "amount" ? "amount" : "percent",
|
|
968
|
+
leverage: Number(drawing.leverage) || 1,
|
|
969
|
+
pointValue: Number(drawing.pointValue) || 1,
|
|
970
|
+
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
964
971
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
965
972
|
});
|
|
966
973
|
const serializeDrawing = (drawing) => ({
|
|
@@ -973,6 +980,13 @@ function createChart(element, options = {}) {
|
|
|
973
980
|
style: drawing.style,
|
|
974
981
|
width: drawing.width,
|
|
975
982
|
locked: drawing.locked,
|
|
983
|
+
accountSize: drawing.accountSize,
|
|
984
|
+
lotSize: drawing.lotSize,
|
|
985
|
+
risk: drawing.risk,
|
|
986
|
+
riskMode: drawing.riskMode,
|
|
987
|
+
leverage: drawing.leverage,
|
|
988
|
+
pointValue: drawing.pointValue,
|
|
989
|
+
qtyPrecision: drawing.qtyPrecision,
|
|
976
990
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
977
991
|
});
|
|
978
992
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -982,6 +996,7 @@ function createChart(element, options = {}) {
|
|
|
982
996
|
let drawingDragState = null;
|
|
983
997
|
let drawingsChangeHandler = null;
|
|
984
998
|
let drawingSelectHandler = null;
|
|
999
|
+
let drawingDoubleClickHandler = null;
|
|
985
1000
|
let drawingHoverHandler = null;
|
|
986
1001
|
let lastHoveredDrawingId = null;
|
|
987
1002
|
let selectedDrawingId = null;
|
|
@@ -2429,20 +2444,6 @@ function createChart(element, options = {}) {
|
|
|
2429
2444
|
ctx.fillStyle = lossFill;
|
|
2430
2445
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2431
2446
|
ctx.restore();
|
|
2432
|
-
if (data.length > 0) {
|
|
2433
|
-
const nowX = xFromDrawingPoint({ index: data.length - 1, price: 0 });
|
|
2434
|
-
const darkRight = clamp(nowX, boxX0, boxX1);
|
|
2435
|
-
if (darkRight - boxX0 > 0.5) {
|
|
2436
|
-
const darkW = darkRight - boxX0;
|
|
2437
|
-
ctx.save();
|
|
2438
|
-
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
2439
|
-
ctx.fillStyle = hexToRgba(profitColor, 0.18);
|
|
2440
|
-
ctx.fillRect(boxX0, Math.min(entryY, targetY), darkW, Math.abs(targetY - entryY));
|
|
2441
|
-
ctx.fillStyle = hexToRgba(lossColor, 0.18);
|
|
2442
|
-
ctx.fillRect(boxX0, Math.min(entryY, stopY), darkW, Math.abs(stopY - entryY));
|
|
2443
|
-
ctx.restore();
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
2447
|
if (isSelected) {
|
|
2447
2448
|
ctx.save();
|
|
2448
2449
|
ctx.setLineDash([]);
|
|
@@ -2477,6 +2478,14 @@ function createChart(element, options = {}) {
|
|
|
2477
2478
|
const stopDist = Math.abs(entry.price - stop.price);
|
|
2478
2479
|
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2479
2480
|
const cx = (boxX0 + boxX1) / 2;
|
|
2481
|
+
const effectivePointValue = (drawing.pointValue > 0 ? drawing.pointValue : 1) * (drawing.lotSize > 0 ? drawing.lotSize : 1);
|
|
2482
|
+
const riskAmount = drawing.riskMode === "amount" ? drawing.risk : drawing.accountSize * (drawing.risk / 100);
|
|
2483
|
+
const qtyRaw = riskAmount > 0 && stopDist > 0 ? riskAmount / (stopDist * effectivePointValue) : 0;
|
|
2484
|
+
const hasMoney = qtyRaw > 0 && Number.isFinite(qtyRaw);
|
|
2485
|
+
const qtyText = hasMoney ? qtyRaw.toFixed(Math.max(0, drawing.qtyPrecision)) : "";
|
|
2486
|
+
const formatAmount = (value) => Math.abs(value) >= 1e3 ? value.toFixed(0) : value.toFixed(2);
|
|
2487
|
+
const targetAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * targetDist * effectivePointValue)}` : "";
|
|
2488
|
+
const stopAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * stopDist * effectivePointValue)}` : "";
|
|
2480
2489
|
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2481
2490
|
const prevFont = ctx.font;
|
|
2482
2491
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
@@ -2494,9 +2503,14 @@ function createChart(element, options = {}) {
|
|
|
2494
2503
|
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2495
2504
|
ctx.font = prevFont;
|
|
2496
2505
|
};
|
|
2497
|
-
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2498
|
-
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2499
|
-
drawPositionPill(
|
|
2506
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}${targetAmountText}`, cx, targetY, profitLine);
|
|
2507
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}${stopAmountText}`, cx, stopY, lossLine);
|
|
2508
|
+
drawPositionPill(
|
|
2509
|
+
hasMoney ? `Entry ${formatPrice(entry.price)} Qty ${qtyText} RR ${rr.toFixed(2)}` : `Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`,
|
|
2510
|
+
cx,
|
|
2511
|
+
entryY,
|
|
2512
|
+
hexToRgba(drawing.color, 0.92)
|
|
2513
|
+
);
|
|
2500
2514
|
if (drawing.label) {
|
|
2501
2515
|
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2502
2516
|
}
|
|
@@ -3959,7 +3973,14 @@ function createChart(element, options = {}) {
|
|
|
3959
3973
|
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3960
3974
|
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3961
3975
|
style: defaults.style ?? "solid",
|
|
3962
|
-
width: defaults.width ?? 1
|
|
3976
|
+
width: defaults.width ?? 1,
|
|
3977
|
+
...defaults.accountSize === void 0 ? {} : { accountSize: defaults.accountSize },
|
|
3978
|
+
...defaults.lotSize === void 0 ? {} : { lotSize: defaults.lotSize },
|
|
3979
|
+
...defaults.risk === void 0 ? {} : { risk: defaults.risk },
|
|
3980
|
+
...defaults.riskMode === void 0 ? {} : { riskMode: defaults.riskMode },
|
|
3981
|
+
...defaults.leverage === void 0 ? {} : { leverage: defaults.leverage },
|
|
3982
|
+
...defaults.pointValue === void 0 ? {} : { pointValue: defaults.pointValue },
|
|
3983
|
+
...defaults.qtyPrecision === void 0 ? {} : { qtyPrecision: defaults.qtyPrecision }
|
|
3963
3984
|
})
|
|
3964
3985
|
);
|
|
3965
3986
|
emitDrawingsChange();
|
|
@@ -4529,6 +4550,20 @@ function createChart(element, options = {}) {
|
|
|
4529
4550
|
if (region === "outside") {
|
|
4530
4551
|
return;
|
|
4531
4552
|
}
|
|
4553
|
+
if (region === "plot" && !activeDrawingTool) {
|
|
4554
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4555
|
+
if (drawingHit) {
|
|
4556
|
+
selectedDrawingId = drawingHit.drawing.id;
|
|
4557
|
+
drawingDoubleClickHandler?.({
|
|
4558
|
+
drawing: serializeDrawing(drawingHit.drawing),
|
|
4559
|
+
target: drawingHit.target,
|
|
4560
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4561
|
+
x: point.x,
|
|
4562
|
+
y: point.y
|
|
4563
|
+
});
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4532
4567
|
if (doubleClickAction === "placeLimitOrder") {
|
|
4533
4568
|
if (region !== "plot") {
|
|
4534
4569
|
return;
|
|
@@ -4839,6 +4874,9 @@ function createChart(element, options = {}) {
|
|
|
4839
4874
|
const onDrawingSelect = (handler) => {
|
|
4840
4875
|
drawingSelectHandler = handler;
|
|
4841
4876
|
};
|
|
4877
|
+
const onDrawingDoubleClick = (handler) => {
|
|
4878
|
+
drawingDoubleClickHandler = handler;
|
|
4879
|
+
};
|
|
4842
4880
|
const onDrawingHover = (handler) => {
|
|
4843
4881
|
drawingHoverHandler = handler;
|
|
4844
4882
|
};
|
|
@@ -4896,6 +4934,7 @@ function createChart(element, options = {}) {
|
|
|
4896
4934
|
clearDrawings,
|
|
4897
4935
|
onDrawingsChange,
|
|
4898
4936
|
onDrawingSelect,
|
|
4937
|
+
onDrawingDoubleClick,
|
|
4899
4938
|
setSelectedDrawing,
|
|
4900
4939
|
onDrawingHover,
|
|
4901
4940
|
setDrawingDefaults,
|
package/dist/index.d.cts
CHANGED
|
@@ -66,6 +66,13 @@ interface DrawingObjectOptions {
|
|
|
66
66
|
width?: number;
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
|
+
accountSize?: number;
|
|
70
|
+
lotSize?: number;
|
|
71
|
+
risk?: number;
|
|
72
|
+
riskMode?: "percent" | "amount";
|
|
73
|
+
leverage?: number;
|
|
74
|
+
pointValue?: number;
|
|
75
|
+
qtyPrecision?: number;
|
|
69
76
|
}
|
|
70
77
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
78
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -84,7 +91,7 @@ interface DrawingHoverEvent {
|
|
|
84
91
|
x: number;
|
|
85
92
|
y: number;
|
|
86
93
|
}
|
|
87
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width">>;
|
|
94
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
88
95
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
89
96
|
id?: string;
|
|
90
97
|
type: string;
|
|
@@ -420,6 +427,7 @@ interface ChartInstance {
|
|
|
420
427
|
clearDrawings: () => void;
|
|
421
428
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
422
429
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
|
+
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
423
431
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
424
432
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
433
|
setSelectedDrawing: (id: string | null) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,13 @@ interface DrawingObjectOptions {
|
|
|
66
66
|
width?: number;
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
|
+
accountSize?: number;
|
|
70
|
+
lotSize?: number;
|
|
71
|
+
risk?: number;
|
|
72
|
+
riskMode?: "percent" | "amount";
|
|
73
|
+
leverage?: number;
|
|
74
|
+
pointValue?: number;
|
|
75
|
+
qtyPrecision?: number;
|
|
69
76
|
}
|
|
70
77
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
78
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -84,7 +91,7 @@ interface DrawingHoverEvent {
|
|
|
84
91
|
x: number;
|
|
85
92
|
y: number;
|
|
86
93
|
}
|
|
87
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width">>;
|
|
94
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
88
95
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
89
96
|
id?: string;
|
|
90
97
|
type: string;
|
|
@@ -420,6 +427,7 @@ interface ChartInstance {
|
|
|
420
427
|
clearDrawings: () => void;
|
|
421
428
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
422
429
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
|
+
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
423
431
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
424
432
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
433
|
setSelectedDrawing: (id: string | null) => void;
|
package/dist/index.js
CHANGED
|
@@ -935,6 +935,13 @@ function createChart(element, options = {}) {
|
|
|
935
935
|
style: drawing.style ?? "dotted",
|
|
936
936
|
width: Math.max(1, Number(drawing.width) || 1),
|
|
937
937
|
locked: drawing.locked ?? false,
|
|
938
|
+
accountSize: Number(drawing.accountSize) || 0,
|
|
939
|
+
lotSize: Number(drawing.lotSize) || 1,
|
|
940
|
+
risk: Number(drawing.risk) || 0,
|
|
941
|
+
riskMode: drawing.riskMode === "amount" ? "amount" : "percent",
|
|
942
|
+
leverage: Number(drawing.leverage) || 1,
|
|
943
|
+
pointValue: Number(drawing.pointValue) || 1,
|
|
944
|
+
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
938
945
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
939
946
|
});
|
|
940
947
|
const serializeDrawing = (drawing) => ({
|
|
@@ -947,6 +954,13 @@ function createChart(element, options = {}) {
|
|
|
947
954
|
style: drawing.style,
|
|
948
955
|
width: drawing.width,
|
|
949
956
|
locked: drawing.locked,
|
|
957
|
+
accountSize: drawing.accountSize,
|
|
958
|
+
lotSize: drawing.lotSize,
|
|
959
|
+
risk: drawing.risk,
|
|
960
|
+
riskMode: drawing.riskMode,
|
|
961
|
+
leverage: drawing.leverage,
|
|
962
|
+
pointValue: drawing.pointValue,
|
|
963
|
+
qtyPrecision: drawing.qtyPrecision,
|
|
950
964
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
951
965
|
});
|
|
952
966
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -956,6 +970,7 @@ function createChart(element, options = {}) {
|
|
|
956
970
|
let drawingDragState = null;
|
|
957
971
|
let drawingsChangeHandler = null;
|
|
958
972
|
let drawingSelectHandler = null;
|
|
973
|
+
let drawingDoubleClickHandler = null;
|
|
959
974
|
let drawingHoverHandler = null;
|
|
960
975
|
let lastHoveredDrawingId = null;
|
|
961
976
|
let selectedDrawingId = null;
|
|
@@ -2403,20 +2418,6 @@ function createChart(element, options = {}) {
|
|
|
2403
2418
|
ctx.fillStyle = lossFill;
|
|
2404
2419
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2405
2420
|
ctx.restore();
|
|
2406
|
-
if (data.length > 0) {
|
|
2407
|
-
const nowX = xFromDrawingPoint({ index: data.length - 1, price: 0 });
|
|
2408
|
-
const darkRight = clamp(nowX, boxX0, boxX1);
|
|
2409
|
-
if (darkRight - boxX0 > 0.5) {
|
|
2410
|
-
const darkW = darkRight - boxX0;
|
|
2411
|
-
ctx.save();
|
|
2412
|
-
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
2413
|
-
ctx.fillStyle = hexToRgba(profitColor, 0.18);
|
|
2414
|
-
ctx.fillRect(boxX0, Math.min(entryY, targetY), darkW, Math.abs(targetY - entryY));
|
|
2415
|
-
ctx.fillStyle = hexToRgba(lossColor, 0.18);
|
|
2416
|
-
ctx.fillRect(boxX0, Math.min(entryY, stopY), darkW, Math.abs(stopY - entryY));
|
|
2417
|
-
ctx.restore();
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
2421
|
if (isSelected) {
|
|
2421
2422
|
ctx.save();
|
|
2422
2423
|
ctx.setLineDash([]);
|
|
@@ -2451,6 +2452,14 @@ function createChart(element, options = {}) {
|
|
|
2451
2452
|
const stopDist = Math.abs(entry.price - stop.price);
|
|
2452
2453
|
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2453
2454
|
const cx = (boxX0 + boxX1) / 2;
|
|
2455
|
+
const effectivePointValue = (drawing.pointValue > 0 ? drawing.pointValue : 1) * (drawing.lotSize > 0 ? drawing.lotSize : 1);
|
|
2456
|
+
const riskAmount = drawing.riskMode === "amount" ? drawing.risk : drawing.accountSize * (drawing.risk / 100);
|
|
2457
|
+
const qtyRaw = riskAmount > 0 && stopDist > 0 ? riskAmount / (stopDist * effectivePointValue) : 0;
|
|
2458
|
+
const hasMoney = qtyRaw > 0 && Number.isFinite(qtyRaw);
|
|
2459
|
+
const qtyText = hasMoney ? qtyRaw.toFixed(Math.max(0, drawing.qtyPrecision)) : "";
|
|
2460
|
+
const formatAmount = (value) => Math.abs(value) >= 1e3 ? value.toFixed(0) : value.toFixed(2);
|
|
2461
|
+
const targetAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * targetDist * effectivePointValue)}` : "";
|
|
2462
|
+
const stopAmountText = hasMoney ? `, Amount: ${formatAmount(qtyRaw * stopDist * effectivePointValue)}` : "";
|
|
2454
2463
|
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2455
2464
|
const prevFont = ctx.font;
|
|
2456
2465
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
@@ -2468,9 +2477,14 @@ function createChart(element, options = {}) {
|
|
|
2468
2477
|
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2469
2478
|
ctx.font = prevFont;
|
|
2470
2479
|
};
|
|
2471
|
-
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2472
|
-
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2473
|
-
drawPositionPill(
|
|
2480
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}${targetAmountText}`, cx, targetY, profitLine);
|
|
2481
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}${stopAmountText}`, cx, stopY, lossLine);
|
|
2482
|
+
drawPositionPill(
|
|
2483
|
+
hasMoney ? `Entry ${formatPrice(entry.price)} Qty ${qtyText} RR ${rr.toFixed(2)}` : `Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`,
|
|
2484
|
+
cx,
|
|
2485
|
+
entryY,
|
|
2486
|
+
hexToRgba(drawing.color, 0.92)
|
|
2487
|
+
);
|
|
2474
2488
|
if (drawing.label) {
|
|
2475
2489
|
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2476
2490
|
}
|
|
@@ -3933,7 +3947,14 @@ function createChart(element, options = {}) {
|
|
|
3933
3947
|
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3934
3948
|
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3935
3949
|
style: defaults.style ?? "solid",
|
|
3936
|
-
width: defaults.width ?? 1
|
|
3950
|
+
width: defaults.width ?? 1,
|
|
3951
|
+
...defaults.accountSize === void 0 ? {} : { accountSize: defaults.accountSize },
|
|
3952
|
+
...defaults.lotSize === void 0 ? {} : { lotSize: defaults.lotSize },
|
|
3953
|
+
...defaults.risk === void 0 ? {} : { risk: defaults.risk },
|
|
3954
|
+
...defaults.riskMode === void 0 ? {} : { riskMode: defaults.riskMode },
|
|
3955
|
+
...defaults.leverage === void 0 ? {} : { leverage: defaults.leverage },
|
|
3956
|
+
...defaults.pointValue === void 0 ? {} : { pointValue: defaults.pointValue },
|
|
3957
|
+
...defaults.qtyPrecision === void 0 ? {} : { qtyPrecision: defaults.qtyPrecision }
|
|
3937
3958
|
})
|
|
3938
3959
|
);
|
|
3939
3960
|
emitDrawingsChange();
|
|
@@ -4503,6 +4524,20 @@ function createChart(element, options = {}) {
|
|
|
4503
4524
|
if (region === "outside") {
|
|
4504
4525
|
return;
|
|
4505
4526
|
}
|
|
4527
|
+
if (region === "plot" && !activeDrawingTool) {
|
|
4528
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4529
|
+
if (drawingHit) {
|
|
4530
|
+
selectedDrawingId = drawingHit.drawing.id;
|
|
4531
|
+
drawingDoubleClickHandler?.({
|
|
4532
|
+
drawing: serializeDrawing(drawingHit.drawing),
|
|
4533
|
+
target: drawingHit.target,
|
|
4534
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4535
|
+
x: point.x,
|
|
4536
|
+
y: point.y
|
|
4537
|
+
});
|
|
4538
|
+
return;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4506
4541
|
if (doubleClickAction === "placeLimitOrder") {
|
|
4507
4542
|
if (region !== "plot") {
|
|
4508
4543
|
return;
|
|
@@ -4813,6 +4848,9 @@ function createChart(element, options = {}) {
|
|
|
4813
4848
|
const onDrawingSelect = (handler) => {
|
|
4814
4849
|
drawingSelectHandler = handler;
|
|
4815
4850
|
};
|
|
4851
|
+
const onDrawingDoubleClick = (handler) => {
|
|
4852
|
+
drawingDoubleClickHandler = handler;
|
|
4853
|
+
};
|
|
4816
4854
|
const onDrawingHover = (handler) => {
|
|
4817
4855
|
drawingHoverHandler = handler;
|
|
4818
4856
|
};
|
|
@@ -4870,6 +4908,7 @@ function createChart(element, options = {}) {
|
|
|
4870
4908
|
clearDrawings,
|
|
4871
4909
|
onDrawingsChange,
|
|
4872
4910
|
onDrawingSelect,
|
|
4911
|
+
onDrawingDoubleClick,
|
|
4873
4912
|
setSelectedDrawing,
|
|
4874
4913
|
onDrawingHover,
|
|
4875
4914
|
setDrawingDefaults,
|
package/docs/API.md
CHANGED
|
@@ -422,7 +422,7 @@ Drawings are user-created chart tools, separate from indicators. They are intera
|
|
|
422
422
|
- `ray`: two-point line that extends infinitely past the second point
|
|
423
423
|
- `fib-retracement`: two-point retracement with levels/bands
|
|
424
424
|
- `fib-extension`: trend-based three-point extension (click trend start, trend end, then the projection origin); levels project from the third point by the first→second move
|
|
425
|
-
- `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio. `color` sets the entry line; `colors` is `[profitColor, lossColor, labelTextColor]` (defaults `POSITION_DEFAULT_COLORS`).
|
|
425
|
+
- `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio. `color` sets the entry line; `colors` is `[profitColor, lossColor, labelTextColor]` (defaults `POSITION_DEFAULT_COLORS`). Sizing inputs `accountSize`, `lotSize`, `risk`, `riskMode` (`"percent"|"amount"`), `leverage`, `pointValue`, `qtyPrecision` drive the Qty/Amount labels — set `pointValue` (contract $/point) from your app for real money values.
|
|
426
426
|
- `points: DrawingPoint[]`
|
|
427
427
|
- `visible?: boolean`
|
|
428
428
|
- `color?: string`
|
|
@@ -482,6 +482,7 @@ Use `getDrawings()` / `setDrawings()` for persistence.
|
|
|
482
482
|
- `fitContent(): void` (x-only fit, keeps y zoom)
|
|
483
483
|
- `resetViewport(): void` (fit x + reset y auto-scale)
|
|
484
484
|
- `setSelectedDrawing(id: string | null): void` (marks a drawing selected; only the selected/drafted drawing renders its handles, and position tools render their lines/labels only while selected)
|
|
485
|
+
- `onDrawingDoubleClick(handler): void` (fires when a drawing is double-clicked; use it to open a settings dialog, e.g. for position tools)
|
|
485
486
|
- `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`)
|
|
486
487
|
- `getActiveDrawingTool(): DrawingToolType | null`
|
|
487
488
|
- `setDrawings(drawings: DrawingObjectOptions[]): void`
|