hyperprop-charting-library 0.1.80 → 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.
@@ -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;
@@ -2463,6 +2478,14 @@ function createChart(element, options = {}) {
2463
2478
  const stopDist = Math.abs(entry.price - stop.price);
2464
2479
  const rr = stopDist > 0 ? targetDist / stopDist : 0;
2465
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)}` : "";
2466
2489
  const drawPositionPill = (text, centerX, centerY, bg) => {
2467
2490
  const prevFont = ctx.font;
2468
2491
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
@@ -2480,9 +2503,14 @@ function createChart(element, options = {}) {
2480
2503
  ctx.fillText(text, centerX, pillY + pillH / 2);
2481
2504
  ctx.font = prevFont;
2482
2505
  };
2483
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2484
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2485
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
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
+ );
2486
2514
  if (drawing.label) {
2487
2515
  drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2488
2516
  }
@@ -3945,7 +3973,14 @@ function createChart(element, options = {}) {
3945
3973
  color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3946
3974
  colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3947
3975
  style: defaults.style ?? "solid",
3948
- 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 }
3949
3984
  })
3950
3985
  );
3951
3986
  emitDrawingsChange();
@@ -4515,6 +4550,20 @@ function createChart(element, options = {}) {
4515
4550
  if (region === "outside") {
4516
4551
  return;
4517
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
+ }
4518
4567
  if (doubleClickAction === "placeLimitOrder") {
4519
4568
  if (region !== "plot") {
4520
4569
  return;
@@ -4825,6 +4874,9 @@ function createChart(element, options = {}) {
4825
4874
  const onDrawingSelect = (handler) => {
4826
4875
  drawingSelectHandler = handler;
4827
4876
  };
4877
+ const onDrawingDoubleClick = (handler) => {
4878
+ drawingDoubleClickHandler = handler;
4879
+ };
4828
4880
  const onDrawingHover = (handler) => {
4829
4881
  drawingHoverHandler = handler;
4830
4882
  };
@@ -4882,6 +4934,7 @@ function createChart(element, options = {}) {
4882
4934
  clearDrawings,
4883
4935
  onDrawingsChange,
4884
4936
  onDrawingSelect,
4937
+ onDrawingDoubleClick,
4885
4938
  setSelectedDrawing,
4886
4939
  onDrawingHover,
4887
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;
@@ -2437,6 +2452,14 @@ function createChart(element, options = {}) {
2437
2452
  const stopDist = Math.abs(entry.price - stop.price);
2438
2453
  const rr = stopDist > 0 ? targetDist / stopDist : 0;
2439
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)}` : "";
2440
2463
  const drawPositionPill = (text, centerX, centerY, bg) => {
2441
2464
  const prevFont = ctx.font;
2442
2465
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
@@ -2454,9 +2477,14 @@ function createChart(element, options = {}) {
2454
2477
  ctx.fillText(text, centerX, pillY + pillH / 2);
2455
2478
  ctx.font = prevFont;
2456
2479
  };
2457
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2458
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2459
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
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
+ );
2460
2488
  if (drawing.label) {
2461
2489
  drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2462
2490
  }
@@ -3919,7 +3947,14 @@ function createChart(element, options = {}) {
3919
3947
  color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3920
3948
  colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3921
3949
  style: defaults.style ?? "solid",
3922
- 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 }
3923
3958
  })
3924
3959
  );
3925
3960
  emitDrawingsChange();
@@ -4489,6 +4524,20 @@ function createChart(element, options = {}) {
4489
4524
  if (region === "outside") {
4490
4525
  return;
4491
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
+ }
4492
4541
  if (doubleClickAction === "placeLimitOrder") {
4493
4542
  if (region !== "plot") {
4494
4543
  return;
@@ -4799,6 +4848,9 @@ function createChart(element, options = {}) {
4799
4848
  const onDrawingSelect = (handler) => {
4800
4849
  drawingSelectHandler = handler;
4801
4850
  };
4851
+ const onDrawingDoubleClick = (handler) => {
4852
+ drawingDoubleClickHandler = handler;
4853
+ };
4802
4854
  const onDrawingHover = (handler) => {
4803
4855
  drawingHoverHandler = handler;
4804
4856
  };
@@ -4856,6 +4908,7 @@ function createChart(element, options = {}) {
4856
4908
  clearDrawings,
4857
4909
  onDrawingsChange,
4858
4910
  onDrawingSelect,
4911
+ onDrawingDoubleClick,
4859
4912
  setSelectedDrawing,
4860
4913
  onDrawingHover,
4861
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;
@@ -2463,6 +2478,14 @@ function createChart(element, options = {}) {
2463
2478
  const stopDist = Math.abs(entry.price - stop.price);
2464
2479
  const rr = stopDist > 0 ? targetDist / stopDist : 0;
2465
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)}` : "";
2466
2489
  const drawPositionPill = (text, centerX, centerY, bg) => {
2467
2490
  const prevFont = ctx.font;
2468
2491
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
@@ -2480,9 +2503,14 @@ function createChart(element, options = {}) {
2480
2503
  ctx.fillText(text, centerX, pillY + pillH / 2);
2481
2504
  ctx.font = prevFont;
2482
2505
  };
2483
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2484
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2485
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
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
+ );
2486
2514
  if (drawing.label) {
2487
2515
  drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2488
2516
  }
@@ -3945,7 +3973,14 @@ function createChart(element, options = {}) {
3945
3973
  color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3946
3974
  colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3947
3975
  style: defaults.style ?? "solid",
3948
- 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 }
3949
3984
  })
3950
3985
  );
3951
3986
  emitDrawingsChange();
@@ -4515,6 +4550,20 @@ function createChart(element, options = {}) {
4515
4550
  if (region === "outside") {
4516
4551
  return;
4517
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
+ }
4518
4567
  if (doubleClickAction === "placeLimitOrder") {
4519
4568
  if (region !== "plot") {
4520
4569
  return;
@@ -4825,6 +4874,9 @@ function createChart(element, options = {}) {
4825
4874
  const onDrawingSelect = (handler) => {
4826
4875
  drawingSelectHandler = handler;
4827
4876
  };
4877
+ const onDrawingDoubleClick = (handler) => {
4878
+ drawingDoubleClickHandler = handler;
4879
+ };
4828
4880
  const onDrawingHover = (handler) => {
4829
4881
  drawingHoverHandler = handler;
4830
4882
  };
@@ -4882,6 +4934,7 @@ function createChart(element, options = {}) {
4882
4934
  clearDrawings,
4883
4935
  onDrawingsChange,
4884
4936
  onDrawingSelect,
4937
+ onDrawingDoubleClick,
4885
4938
  setSelectedDrawing,
4886
4939
  onDrawingHover,
4887
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;
@@ -2437,6 +2452,14 @@ function createChart(element, options = {}) {
2437
2452
  const stopDist = Math.abs(entry.price - stop.price);
2438
2453
  const rr = stopDist > 0 ? targetDist / stopDist : 0;
2439
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)}` : "";
2440
2463
  const drawPositionPill = (text, centerX, centerY, bg) => {
2441
2464
  const prevFont = ctx.font;
2442
2465
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
@@ -2454,9 +2477,14 @@ function createChart(element, options = {}) {
2454
2477
  ctx.fillText(text, centerX, pillY + pillH / 2);
2455
2478
  ctx.font = prevFont;
2456
2479
  };
2457
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2458
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2459
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
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
+ );
2460
2488
  if (drawing.label) {
2461
2489
  drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2462
2490
  }
@@ -3919,7 +3947,14 @@ function createChart(element, options = {}) {
3919
3947
  color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3920
3948
  colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3921
3949
  style: defaults.style ?? "solid",
3922
- 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 }
3923
3958
  })
3924
3959
  );
3925
3960
  emitDrawingsChange();
@@ -4489,6 +4524,20 @@ function createChart(element, options = {}) {
4489
4524
  if (region === "outside") {
4490
4525
  return;
4491
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
+ }
4492
4541
  if (doubleClickAction === "placeLimitOrder") {
4493
4542
  if (region !== "plot") {
4494
4543
  return;
@@ -4799,6 +4848,9 @@ function createChart(element, options = {}) {
4799
4848
  const onDrawingSelect = (handler) => {
4800
4849
  drawingSelectHandler = handler;
4801
4850
  };
4851
+ const onDrawingDoubleClick = (handler) => {
4852
+ drawingDoubleClickHandler = handler;
4853
+ };
4802
4854
  const onDrawingHover = (handler) => {
4803
4855
  drawingHoverHandler = handler;
4804
4856
  };
@@ -4856,6 +4908,7 @@ function createChart(element, options = {}) {
4856
4908
  clearDrawings,
4857
4909
  onDrawingsChange,
4858
4910
  onDrawingSelect,
4911
+ onDrawingDoubleClick,
4859
4912
  setSelectedDrawing,
4860
4913
  onDrawingHover,
4861
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`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.80",
3
+ "version": "0.1.81",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",