acttrader-charts 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -164,9 +164,11 @@ chart.setLevels([], 'label', 'price', 'pending'); // clear all of one type
164
164
 
165
165
  ```ts
166
166
  // Confirmed drag of a pending order entry
167
- chart.on('tradeLevelEdit', ({ label, type, changes, isFullscreen }) => {
167
+ chart.on('tradeLevelEdit', ({ label, type, data, changes, newLots, isFullscreen }) => {
168
168
  for (const c of changes) {
169
- if (c.field === 'MAIN') myApi.modifyOrder(label, { price: c.newPrice });
169
+ // `c.newLots` is present on the MAIN change when qty was edited this session.
170
+ // `data.lots` is also overridden with the new qty for convenience.
171
+ if (c.field === 'MAIN') myApi.modifyOrder(label, { price: c.newPrice, qty: c.newLots ?? (data as any).lots });
170
172
  if (c.field === 'SL') myApi.modifyOrder(label, { stopLoss: c.newPrice });
171
173
  if (c.field === 'TP') myApi.modifyOrder(label, { takeProfit: c.newPrice });
172
174
  }
@@ -224,6 +226,7 @@ When `enableTrading` is on and live BID/ASK data is streaming, hovering / activa
224
226
  | `showVolume` | | `true` | Show volume overlay |
225
227
  | `showUI` | | `true` | Render top / bottom / left bars. When `false`, the loading overlay is also suppressed (mobile wrappers provide their own) |
226
228
  | `showDrawingTools` | | `true` | Show drawing toolbar and pencil button |
229
+ | `showFullscreenButton` | | `true` | Show the fullscreen toggle button in the top bar. Set to `false` to hide it entirely. Mobile wrappers (Android / iOS) default this to `false` |
227
230
  | `timeframe` | | `"1D"` | Initial timeframe |
228
231
  | `duration` | | — | Initial active duration button |
229
232
  | `symbol` | | — | Symbol name shown in the top bar |
@@ -235,6 +238,10 @@ When `enableTrading` is on and live BID/ASK data is streaming, hovering / activa
235
238
  | `maxCandles` | | `200` | Max bars fetched per data-load request |
236
239
  | `prefetchThreshold` | | `80` | Bars from start of data at which historical fetch triggers (min 20) |
237
240
  | `mobileBarDivisor` | | `2` | Divide desktop visible bar count on touch devices (`2`, `3`, or `4`) |
241
+ | `momentumScrollEnabled` | | `true` | Enable momentum (kinetic) scrolling — chart coasts after a fast flick |
242
+ | `momentumDecay` | | `0.95` | Per-frame velocity decay, normalised to 60 fps. Clamped `[0.80, 0.99]`. Lower = stops faster |
243
+ | `momentumThreshold` | | `0.3` | Min release velocity (px/ms) to launch momentum. Raise to require a faster flick |
244
+ | `momentumMaxVelocity` | | `6.0` | Max launch velocity (px/ms) — caps hard-flick speed |
238
245
  | `targetCandleWidth` | | `10` | Target px width per candle for auto-calculating initial bar count |
239
246
  | `durationTimeframeMap` | | *(see below)* | Override duration → timeframe pairings |
240
247
  | `dataLoader` | | — | `(params) => Promise<OHLCVBar[]>` auto-called on load / change |
@@ -256,7 +263,10 @@ When `enableTrading` is on and live BID/ASK data is streaming, hovering / activa
256
263
  | `hideSymbolAndTick` | | `false` | Hide the symbol name, OHLC strip, and tick-activity dot overlay |
257
264
  | `showBottomBar` | | `false` | Show the bottom duration-selector bar |
258
265
  | `hideQtyButton` | | `false` | Hide the floating Qty input overlay on draft orders |
266
+ | `showQuantityField` | | `false` | Render an editable QTY pill at the left of the draft order info box. Clicking the pill opens a flyout input to edit the quantity before submitting |
267
+ | `quantityFieldConfig` | | — | Constraints for the draft order QTY field (only relevant when `showQuantityField` is `true`). Object: `{ minLots?: number, maxLots?: number }`. `minLots` also sets the initial quantity and the step value for the flyout input (default: `1`). `maxLots` caps the input (default: `100`) |
259
268
  | `tradesThresholdForHorizontalLine` | | `2` | Level count above which render auto-switches to `"dot"` mode |
269
+ | `timezone` | | `"UTC"` | IANA timezone string for time-axis and crosshair labels. `"UTC"` (default), `"local"` (browser/device timezone), or any IANA string (`"America/New_York"`, `"Europe/London"`, etc.) |
260
270
  | `canvasColors` | | — | Per-theme canvas background color overrides (persisted from Settings dialog) |
261
271
  | `aggregateFrom` | | — | Fetch finer-grained data and aggregate client-side per timeframe |
262
272
  | `onOrderSubmit` | | — | Called when user submits a trade via the floating button |
@@ -479,6 +489,20 @@ chart.loadData(bars: OHLCVBar[]): this
479
489
  chart.prependData(bars: OHLCVBar[]): this // prepend historical bars (infinite scroll back)
480
490
  chart.correctBar(barTime: number, bar: OHLCVBar): void // replace a bar with authoritative data after close
481
491
  chart.setLoading(loading: boolean): this
492
+
493
+ // Reset — clears all bars, the live price line, any in-flight fetch,
494
+ // all user drawings, and all trade/position levels (including pending drafts).
495
+ // Call before switching to a new symbol so no previous symbol state bleeds in.
496
+ // If you only want to clear bars (e.g. refreshing the same symbol), call
497
+ // chart.loadData([]) directly to preserve drawings.
498
+ chart.resetData(): this
499
+ ```
500
+
501
+ **Symbol switch pattern:**
502
+ ```ts
503
+ chart.setSymbol('GBPUSD').resetData();
504
+ // … fetch new bars …
505
+ chart.loadData(newBars);
482
506
  ```
483
507
 
484
508
  ### Series & Appearance
@@ -488,6 +512,7 @@ chart.setSeries(series: SeriesType): this
488
512
  chart.setTheme('dark' | 'light'): this
489
513
  chart.setTimeframe(tf: Timeframe): this // change timeframe and reload data
490
514
  chart.setThemeOverrides(overrides: ThemeOverrides): this // update per-theme color overrides at runtime
515
+ chart.setTimezone(tz: string): this // change display timezone at runtime
491
516
  chart.setVolume(show: boolean): this
492
517
  ```
493
518
 
@@ -511,12 +536,17 @@ chart.setDrawingTool(tool: DrawingToolType | null): this
511
536
  ```ts
512
537
  chart.setLevels(levels, labelField, priceField, type): this
513
538
  chart.removeLevelByLabel(label: string): this
514
- chart.cancelCurrentEdit(): this // cancel the active draft order or in-progress level edit; no-op when nothing is active
539
+ chart.updateLevelMainPrice(label: string, price: number): this // move an existing level's entry price; stages the edit so it survives subsequent setLevels refreshes until the server echoes the new price or cancelLevelEdit/cancelCurrentEdit is called
540
+ chart.updateLevelBracket(label: string, bracketType: 'sl' | 'tp', price: number | null): this // update or remove a SL/TP bracket on an existing level; same staging semantics as updateLevelMainPrice — pass null to remove
541
+ chart.cancelLevelEdit(label: string): this // drop any staged edit for this level and revert to last confirmed server state
542
+ chart.cancelCurrentEdit(): this // cancel the active draft order or any in-progress level edit; no-op when nothing is active
515
543
  chart.addLevelBracket(label: string, bracketType: 'sl' | 'tp'): this // auto-place a SL or TP bracket at a default offset; emits tradeLevelBracketActivated with the computed price
516
- chart.setDraftBracketPnl(bracketType: 'sl' | 'tp', pnlText: string | null): this // set estimated P&L text on a draft order bracket line; pass null to clear
544
+ chart.setDraftBracketPnl(bracketType: 'sl' | 'tp', pnlText: string | null): this // set estimated P&L text on the active bracket host — the draft order while drafting, or the currently selected existing pending order / position while modifying; pass null to clear
517
545
  chart.setTfcActive(enabled: boolean): this // toggle TFC on/off at runtime; hides/shows all trade levels, draft orders, and floating trade button; fires tfcToggle event
518
546
  ```
519
547
 
548
+ > **Staging semantics for `updateLevelMainPrice` / `updateLevelBracket`.** Calls to these methods register the change in the chart's pending-edit buffer (the same buffer chart-initiated drags use), so the edit stays visible even when the host app keeps pushing fresh server state via `setLevels` (e.g. per-tick PnL refreshes). When the server echoes back the new price in a later `setLevels` call, the staged edit is auto-released (mobile, i.e. `hideLevelConfirmCancel: true`). If a panel closes without submitting, call `cancelLevelEdit(label)` or `cancelCurrentEdit()` to drop the staged edit — otherwise it will keep overriding server state on the chart.
549
+
520
550
  ### Trade Button
521
551
 
522
552
  ```ts
@@ -548,6 +548,8 @@ interface ChartConfig {
548
548
  showDrawingTools?: boolean;
549
549
  /** If false, the settings gear button in the top bar is hidden entirely. Default: true */
550
550
  showSettings?: boolean;
551
+ /** If false, the fullscreen toggle button in the top bar is hidden entirely. Default: true */
552
+ showFullscreenButton?: boolean;
551
553
  timeframe?: Timeframe;
552
554
  duration?: Duration;
553
555
  symbol?: string;
@@ -568,6 +570,22 @@ interface ChartConfig {
568
570
  * Minimum (and default) lot size for draft order submission. Default: `1`.
569
571
  */
570
572
  minLots?: number;
573
+ /**
574
+ * When true, renders an editable QTY pill at the left of the draft order
575
+ * info box. Clicking the pill opens a flyout to edit the quantity. Default: `false`.
576
+ */
577
+ showQuantityField?: boolean;
578
+ /**
579
+ * Constraints for the draft order QTY field. Only relevant when
580
+ * `showQuantityField` is true. `minLots` also sets the initial quantity
581
+ * and the step value for the flyout input.
582
+ */
583
+ quantityFieldConfig?: {
584
+ /** Minimum lot size, step size, and initial quantity (e.g. `0.01`). Default: `1` */
585
+ minLots?: number;
586
+ /** Maximum lot size (e.g. `100`). Default: `100` */
587
+ maxLots?: number;
588
+ };
571
589
  /** Called when user submits an order via the floating trade button */
572
590
  onOrderSubmit?: (order: OrderSubmit) => void;
573
591
  /**
@@ -588,10 +606,12 @@ interface ChartConfig {
588
606
  label: string;
589
607
  type: TradeLevelType;
590
608
  data: unknown;
609
+ newLots?: number;
591
610
  changes: Array<{
592
611
  field: 'MAIN' | 'SL' | 'TP' | 'ADD_SL' | 'ADD_TP' | 'REMOVE_SL' | 'REMOVE_TP';
593
612
  newPrice: number;
594
613
  data: unknown;
614
+ newLots?: number;
595
615
  bracketOrderLabel?: string;
596
616
  }>;
597
617
  }) => void;
@@ -621,6 +641,13 @@ interface ChartConfig {
621
641
  * }
622
642
  */
623
643
  themeOverrides?: ThemeOverrides;
644
+ /**
645
+ * IANA timezone string for all time-axis and crosshair labels.
646
+ * `"UTC"` (default) preserves existing behavior.
647
+ * `"local"` uses the browser/device timezone automatically.
648
+ * Any IANA string is accepted: `"America/New_York"`, `"Europe/London"`, etc.
649
+ */
650
+ timezone?: string;
624
651
  /**
625
652
  * Optional per-component UI configuration overrides (font sizes, icon
626
653
  * sizes, spacing). Only the keys you provide are overridden; all others
@@ -664,6 +691,33 @@ interface ChartConfig {
664
691
  * Default: `2`.
665
692
  */
666
693
  mobileBarDivisor?: 2 | 3 | 4;
694
+ /**
695
+ * Enable momentum (kinetic) scrolling on drag release. When `true`, releasing
696
+ * a fast pan gesture lets the chart continue scrolling with gradually
697
+ * decelerating speed — matching the feel of native iOS/Android scroll views.
698
+ * Default: `true`.
699
+ */
700
+ momentumScrollEnabled?: boolean;
701
+ /**
702
+ * Per-frame velocity decay factor for momentum scrolling, normalised to 60 fps.
703
+ * A value of `0.95` means the viewport retains 95% of its speed each 16.67 ms
704
+ * frame. Lower values stop faster; higher values coast longer.
705
+ * Clamped to `[0.80, 0.99]`. Default: `0.95`.
706
+ */
707
+ momentumDecay?: number;
708
+ /**
709
+ * Minimum release velocity (px/ms) required to trigger a momentum scroll.
710
+ * Swipes slower than this threshold stop immediately on finger-up.
711
+ * Raising this value suppresses momentum for slow drags while still triggering
712
+ * on fast flicks. Default: `0.3`.
713
+ */
714
+ momentumThreshold?: number;
715
+ /**
716
+ * Maximum initial launch velocity (px/ms) for momentum scrolling.
717
+ * Caps runaway fast-flick launches that would scroll hundreds of bars in one
718
+ * gesture. Default: `6.0`.
719
+ */
720
+ momentumMaxVelocity?: number;
667
721
  /**
668
722
  * Initial number of candles visible when the chart first loads (desktop).
669
723
  * On mobile this value is further divided by `mobileBarDivisor` unless
@@ -1089,16 +1143,29 @@ type ChartEventMap = {
1089
1143
  tradeLevelEdit: {
1090
1144
  label: string;
1091
1145
  type: TradeLevelType;
1092
- /** Parent level's data. */
1146
+ /**
1147
+ * Parent level's data. When the user edited the lot size during this session,
1148
+ * the `lots` field of this object is overridden with the new value for convenience
1149
+ * (so `data.lots` always reflects the effective qty being submitted). The original
1150
+ * server fields (e.g. `Quantity`) are left untouched — use `newLots` when you need
1151
+ * to distinguish "edited" from "unchanged".
1152
+ */
1093
1153
  data: unknown;
1094
1154
  /** True when the chart is in fullscreen mode (native or CSS) at the time of the action. */
1095
1155
  isFullscreen: boolean;
1156
+ /** Present when the user changed the lot size via the QTY pill flyout during this edit session. */
1157
+ newLots?: number;
1096
1158
  changes: Array<{
1097
1159
  /** MAIN = entry price edit; SL/TP = bracket edit; ADD_SL/ADD_TP = new bracket placed; REMOVE_SL/REMOVE_TP = bracket removed. */
1098
1160
  field: 'MAIN' | 'SL' | 'TP' | 'ADD_SL' | 'ADD_TP' | 'REMOVE_SL' | 'REMOVE_TP';
1099
1161
  newPrice: number;
1100
- /** Bracket order's data when the bracket is a ToClose order; parent's data for inline brackets. */
1162
+ /**
1163
+ * Bracket order's data when the bracket is a ToClose order; parent's data for inline brackets.
1164
+ * On the MAIN change, `lots` is overridden with the new qty when the user edited it (same rule as the top-level `data`).
1165
+ */
1101
1166
  data: unknown;
1167
+ /** Present on the MAIN change when the user edited the lot size during this session. */
1168
+ newLots?: number;
1102
1169
  bracketOrderLabel?: string;
1103
1170
  }>;
1104
1171
  };
@@ -548,6 +548,8 @@ interface ChartConfig {
548
548
  showDrawingTools?: boolean;
549
549
  /** If false, the settings gear button in the top bar is hidden entirely. Default: true */
550
550
  showSettings?: boolean;
551
+ /** If false, the fullscreen toggle button in the top bar is hidden entirely. Default: true */
552
+ showFullscreenButton?: boolean;
551
553
  timeframe?: Timeframe;
552
554
  duration?: Duration;
553
555
  symbol?: string;
@@ -568,6 +570,22 @@ interface ChartConfig {
568
570
  * Minimum (and default) lot size for draft order submission. Default: `1`.
569
571
  */
570
572
  minLots?: number;
573
+ /**
574
+ * When true, renders an editable QTY pill at the left of the draft order
575
+ * info box. Clicking the pill opens a flyout to edit the quantity. Default: `false`.
576
+ */
577
+ showQuantityField?: boolean;
578
+ /**
579
+ * Constraints for the draft order QTY field. Only relevant when
580
+ * `showQuantityField` is true. `minLots` also sets the initial quantity
581
+ * and the step value for the flyout input.
582
+ */
583
+ quantityFieldConfig?: {
584
+ /** Minimum lot size, step size, and initial quantity (e.g. `0.01`). Default: `1` */
585
+ minLots?: number;
586
+ /** Maximum lot size (e.g. `100`). Default: `100` */
587
+ maxLots?: number;
588
+ };
571
589
  /** Called when user submits an order via the floating trade button */
572
590
  onOrderSubmit?: (order: OrderSubmit) => void;
573
591
  /**
@@ -588,10 +606,12 @@ interface ChartConfig {
588
606
  label: string;
589
607
  type: TradeLevelType;
590
608
  data: unknown;
609
+ newLots?: number;
591
610
  changes: Array<{
592
611
  field: 'MAIN' | 'SL' | 'TP' | 'ADD_SL' | 'ADD_TP' | 'REMOVE_SL' | 'REMOVE_TP';
593
612
  newPrice: number;
594
613
  data: unknown;
614
+ newLots?: number;
595
615
  bracketOrderLabel?: string;
596
616
  }>;
597
617
  }) => void;
@@ -621,6 +641,13 @@ interface ChartConfig {
621
641
  * }
622
642
  */
623
643
  themeOverrides?: ThemeOverrides;
644
+ /**
645
+ * IANA timezone string for all time-axis and crosshair labels.
646
+ * `"UTC"` (default) preserves existing behavior.
647
+ * `"local"` uses the browser/device timezone automatically.
648
+ * Any IANA string is accepted: `"America/New_York"`, `"Europe/London"`, etc.
649
+ */
650
+ timezone?: string;
624
651
  /**
625
652
  * Optional per-component UI configuration overrides (font sizes, icon
626
653
  * sizes, spacing). Only the keys you provide are overridden; all others
@@ -664,6 +691,33 @@ interface ChartConfig {
664
691
  * Default: `2`.
665
692
  */
666
693
  mobileBarDivisor?: 2 | 3 | 4;
694
+ /**
695
+ * Enable momentum (kinetic) scrolling on drag release. When `true`, releasing
696
+ * a fast pan gesture lets the chart continue scrolling with gradually
697
+ * decelerating speed — matching the feel of native iOS/Android scroll views.
698
+ * Default: `true`.
699
+ */
700
+ momentumScrollEnabled?: boolean;
701
+ /**
702
+ * Per-frame velocity decay factor for momentum scrolling, normalised to 60 fps.
703
+ * A value of `0.95` means the viewport retains 95% of its speed each 16.67 ms
704
+ * frame. Lower values stop faster; higher values coast longer.
705
+ * Clamped to `[0.80, 0.99]`. Default: `0.95`.
706
+ */
707
+ momentumDecay?: number;
708
+ /**
709
+ * Minimum release velocity (px/ms) required to trigger a momentum scroll.
710
+ * Swipes slower than this threshold stop immediately on finger-up.
711
+ * Raising this value suppresses momentum for slow drags while still triggering
712
+ * on fast flicks. Default: `0.3`.
713
+ */
714
+ momentumThreshold?: number;
715
+ /**
716
+ * Maximum initial launch velocity (px/ms) for momentum scrolling.
717
+ * Caps runaway fast-flick launches that would scroll hundreds of bars in one
718
+ * gesture. Default: `6.0`.
719
+ */
720
+ momentumMaxVelocity?: number;
667
721
  /**
668
722
  * Initial number of candles visible when the chart first loads (desktop).
669
723
  * On mobile this value is further divided by `mobileBarDivisor` unless
@@ -1089,16 +1143,29 @@ type ChartEventMap = {
1089
1143
  tradeLevelEdit: {
1090
1144
  label: string;
1091
1145
  type: TradeLevelType;
1092
- /** Parent level's data. */
1146
+ /**
1147
+ * Parent level's data. When the user edited the lot size during this session,
1148
+ * the `lots` field of this object is overridden with the new value for convenience
1149
+ * (so `data.lots` always reflects the effective qty being submitted). The original
1150
+ * server fields (e.g. `Quantity`) are left untouched — use `newLots` when you need
1151
+ * to distinguish "edited" from "unchanged".
1152
+ */
1093
1153
  data: unknown;
1094
1154
  /** True when the chart is in fullscreen mode (native or CSS) at the time of the action. */
1095
1155
  isFullscreen: boolean;
1156
+ /** Present when the user changed the lot size via the QTY pill flyout during this edit session. */
1157
+ newLots?: number;
1096
1158
  changes: Array<{
1097
1159
  /** MAIN = entry price edit; SL/TP = bracket edit; ADD_SL/ADD_TP = new bracket placed; REMOVE_SL/REMOVE_TP = bracket removed. */
1098
1160
  field: 'MAIN' | 'SL' | 'TP' | 'ADD_SL' | 'ADD_TP' | 'REMOVE_SL' | 'REMOVE_TP';
1099
1161
  newPrice: number;
1100
- /** Bracket order's data when the bracket is a ToClose order; parent's data for inline brackets. */
1162
+ /**
1163
+ * Bracket order's data when the bracket is a ToClose order; parent's data for inline brackets.
1164
+ * On the MAIN change, `lots` is overridden with the new qty when the user edited it (same rule as the top-level `data`).
1165
+ */
1101
1166
  data: unknown;
1167
+ /** Present on the MAIN change when the user edited the lot size during this session. */
1168
+ newLots?: number;
1102
1169
  bracketOrderLabel?: string;
1103
1170
  }>;
1104
1171
  };