@pipsend/charts 2.0.1 → 2.2.0

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
@@ -18,6 +18,7 @@ Simple • Powerful • Framework-Agnostic • TypeScript • Production-Ready
18
18
  - [Installation](#-installation)
19
19
  - [Quick Start](#-quick-start)
20
20
  - [Demo & Examples](#-demo--examples)
21
+ - [Chart Types](#-chart-types)
21
22
  - [Available Technical Indicators](#-available-technical-indicators)
22
23
  - [Interactive Trading Lines API](#-interactive-trading-lines-api)
23
24
  - [Framework Integration Examples](#-framework-integration-examples)
@@ -228,6 +229,75 @@ document.getElementById('btnAlert').onclick = async () => {
228
229
 
229
230
  ---
230
231
 
232
+ ## 📈 Chart Types
233
+
234
+ Every series is added with `chart.addSeries(<Type>, options?, paneIndex?)`.
235
+
236
+ | Series | Import | Data shape |
237
+ |---|---|---|
238
+ | Candlestick | `CandlestickSeries` | `{ time, open, high, low, close }` |
239
+ | Bar (OHLC) | `BarSeries` | `{ time, open, high, low, close }` |
240
+ | Line | `LineSeries` | `{ time, value }` |
241
+ | Area | `AreaSeries` | `{ time, value }` |
242
+ | Baseline | `BaselineSeries` | `{ time, value }` |
243
+ | Histogram | `HistogramSeries` | `{ time, value, color? }` |
244
+ | Custom | `chart.addCustomSeries(paneView)` | your own |
245
+
246
+ ### Heikin Ashi
247
+
248
+ Heikin Ashi is a transform of the OHLC bars, not a separate series type, so it
249
+ is applied on top of an existing candlestick or bar series:
250
+
251
+ ```javascript
252
+ import { createChart, CandlestickSeries, applyHeikinAshi } from '@pipsend/charts';
253
+
254
+ const series = chart.addSeries(CandlestickSeries);
255
+ series.setData(bars);
256
+
257
+ const ha = applyHeikinAshi(series, chart);
258
+
259
+ // Back to regular candles
260
+ ha.remove();
261
+ ```
262
+
263
+ The source series keeps its real prices and is only painted transparent, not
264
+ hidden: indicators bound to it keep computing on the true OHLC, its price lines
265
+ and primitives (positions, alerts, drawings) stay on screen, and `remove()`
266
+ restores the chart exactly as it was — which makes this usable as a chart-type
267
+ toggle. New bars pushed to the source are transformed automatically.
268
+
269
+ The same trick is exported as `hideSeriesPaint(series)` for drawing any other
270
+ view over a series: it blanks the paint, leaves the series visible to the engine,
271
+ and returns a function that puts the paint back.
272
+
273
+ Colors can be changed on a running transform, and are the candlestick ones:
274
+
275
+ ```javascript
276
+ applyHeikinAshi(series, chart, {
277
+ upColor: '#26a69a',
278
+ downColor: '#ef5350',
279
+ borderVisible: true,
280
+ wickVisible: true,
281
+ hideSource: true, // set false to draw over the raw candles
282
+ paneIndex: 0
283
+ });
284
+ ```
285
+
286
+ If you only want the numbers — to feed a different series, or to compute on them
287
+ — use the transform on its own:
288
+
289
+ ```javascript
290
+ import { calculateHeikinAshi } from '@pipsend/charts';
291
+
292
+ const haBars = calculateHeikinAshi(bars);
293
+ ```
294
+
295
+ Each Heikin Ashi bar folds in the one before it, so the result depends on where
296
+ the data starts. Pass the whole series rather than a recent window when you can;
297
+ the difference decays over a few bars.
298
+
299
+ ---
300
+
231
301
  ## 📊 Available Technical Indicators
232
302
 
233
303
  ### Overlay Indicators (appear on main chart)
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @license
3
- * Pipsend Charts v2.0.1
3
+ * Pipsend Charts v2.2.0
4
4
  * Copyright (c) 2026 Pipsend
5
5
  * Licensed under MIT License
6
6
  * Built on TradingView Lightweight Charts™ (Apache 2.0)
@@ -15520,6 +15520,85 @@ function hasSeriesVolumes(series) {
15520
15520
  return volumes !== undefined && volumes.size > 0;
15521
15521
  }
15522
15522
 
15523
+ const TRANSPARENT = 'rgba(0, 0, 0, 0)';
15524
+ /**
15525
+ * Take a series off the screen without hiding it.
15526
+ *
15527
+ * `visible: false` takes down everything hung off the series as well: its
15528
+ * price lines, primitives and price-axis label stop rendering. A transform
15529
+ * that only wants the bars themselves out of the way — Heikin Ashi drawing
15530
+ * over its source — needs the series to stay visible to the engine, so its
15531
+ * paint is made transparent instead and the last-value label and price line
15532
+ * are switched off. Custom series have no known colours; those fall back to
15533
+ * `visible: false`.
15534
+ *
15535
+ * @param series - Series to blank out.
15536
+ * @returns Puts back the options the series had when it was blanked.
15537
+ */
15538
+ function hideSeriesPaint(series) {
15539
+ switch (series.seriesType()) {
15540
+ case 'Candlestick':
15541
+ return blank(series, {
15542
+ upColor: TRANSPARENT,
15543
+ downColor: TRANSPARENT,
15544
+ borderVisible: false,
15545
+ wickVisible: false,
15546
+ });
15547
+ case 'Bar':
15548
+ return blank(series, {
15549
+ upColor: TRANSPARENT,
15550
+ downColor: TRANSPARENT,
15551
+ });
15552
+ case 'Line':
15553
+ return blank(series, {
15554
+ color: TRANSPARENT,
15555
+ crosshairMarkerVisible: false,
15556
+ pointMarkersVisible: false,
15557
+ });
15558
+ case 'Area':
15559
+ return blank(series, {
15560
+ lineColor: TRANSPARENT,
15561
+ topColor: TRANSPARENT,
15562
+ bottomColor: TRANSPARENT,
15563
+ crosshairMarkerVisible: false,
15564
+ pointMarkersVisible: false,
15565
+ });
15566
+ case 'Baseline':
15567
+ return blank(series, {
15568
+ topLineColor: TRANSPARENT,
15569
+ topFillColor1: TRANSPARENT,
15570
+ topFillColor2: TRANSPARENT,
15571
+ bottomLineColor: TRANSPARENT,
15572
+ bottomFillColor1: TRANSPARENT,
15573
+ bottomFillColor2: TRANSPARENT,
15574
+ crosshairMarkerVisible: false,
15575
+ pointMarkersVisible: false,
15576
+ });
15577
+ case 'Histogram':
15578
+ return blank(series, {
15579
+ color: TRANSPARENT,
15580
+ });
15581
+ default:
15582
+ return blank(series, { visible: false });
15583
+ }
15584
+ }
15585
+ function blank(series, paint) {
15586
+ const patch = {
15587
+ ...paint,
15588
+ lastValueVisible: false,
15589
+ priceLineVisible: false,
15590
+ };
15591
+ const before = series.options();
15592
+ const snapshot = {};
15593
+ for (const key of Object.keys(patch)) {
15594
+ snapshot[key] = before[key];
15595
+ }
15596
+ series.applyOptions(patch);
15597
+ return () => {
15598
+ series.applyOptions(snapshot);
15599
+ };
15600
+ }
15601
+
15523
15602
  /**
15524
15603
  * Pins a bounded indicator (RSI, Stochastic…) to a fixed price range.
15525
15604
  *
@@ -17154,6 +17233,168 @@ function applyPivotPoints(series, chart, options = {}) {
17154
17233
  };
17155
17234
  }
17156
17235
 
17236
+ function isOhlc(bar) {
17237
+ return bar !== null
17238
+ && bar !== undefined
17239
+ && typeof bar.close === 'number';
17240
+ }
17241
+ /**
17242
+ * Turns raw OHLC bars into Heikin Ashi ones.
17243
+ *
17244
+ * Heikin Ashi is a price transform, not an overlay: each candle averages itself
17245
+ * with the one before it, which drops most of the single-bar noise and leaves
17246
+ * runs of same-coloured bodies while a trend holds.
17247
+ *
17248
+ * ```
17249
+ * close = (O + H + L + C) / 4
17250
+ * open = (previous open + previous close) / 2 // first bar: (O + C) / 2
17251
+ * high = max(H, open, close)
17252
+ * low = min(L, open, close)
17253
+ * ```
17254
+ *
17255
+ * Because every bar folds in the one before it, the result depends on where the
17256
+ * data starts: the same bar computed from a longer history differs slightly.
17257
+ * The difference decays over a few bars, so pass the whole series rather than a
17258
+ * recent window when you can.
17259
+ *
17260
+ * Whitespace items are passed through untouched, and do not advance the
17261
+ * running open/close — a gap in the data is not a bar.
17262
+ *
17263
+ * @param bars - Source bars, ordered oldest to newest.
17264
+ * @returns The transformed bars, one per input item.
17265
+ */
17266
+ function calculateHeikinAshi(bars) {
17267
+ const result = [];
17268
+ let previousOpen = null;
17269
+ let previousClose = null;
17270
+ for (const bar of bars) {
17271
+ if (!isOhlc(bar)) {
17272
+ if (bar !== null && bar !== undefined) {
17273
+ result.push({ time: bar.time, customValues: bar.customValues });
17274
+ }
17275
+ continue;
17276
+ }
17277
+ const haClose = (bar.open + bar.high + bar.low + bar.close) / 4;
17278
+ const haOpen = previousOpen === null || previousClose === null
17279
+ ? (bar.open + bar.close) / 2
17280
+ : (previousOpen + previousClose) / 2;
17281
+ result.push({
17282
+ time: bar.time,
17283
+ open: haOpen,
17284
+ high: Math.max(bar.high, haOpen, haClose),
17285
+ low: Math.min(bar.low, haOpen, haClose),
17286
+ close: haClose,
17287
+ customValues: bar.customValues,
17288
+ });
17289
+ previousOpen = haOpen;
17290
+ previousClose = haClose;
17291
+ }
17292
+ return result;
17293
+ }
17294
+ /**
17295
+ * Draw a source series as Heikin Ashi candles.
17296
+ *
17297
+ * The source series is left in place holding its real prices — it is only
17298
+ * painted transparent — so indicators bound to it keep computing on the true
17299
+ * OHLC, its price lines and primitives stay on screen, and `remove()` puts the
17300
+ * chart back exactly as it was. That makes this usable as a chart-type toggle:
17301
+ *
17302
+ * ```js
17303
+ * const ha = applyHeikinAshi(candleSeries, chart);
17304
+ * // …back to regular candles:
17305
+ * ha.remove();
17306
+ * ```
17307
+ *
17308
+ * @param series - Source OHLC series (a candlestick or bar series).
17309
+ * @param chart - Chart instance.
17310
+ * @param options - Heikin Ashi configuration options.
17311
+ * @returns The Heikin Ashi candlestick series, plus live control over its options.
17312
+ */
17313
+ function applyHeikinAshi(series, chart, options = {}) {
17314
+ const resolved = {
17315
+ paneIndex: options.paneIndex ?? 0,
17316
+ upColor: options.upColor ?? '#26a69a',
17317
+ downColor: options.downColor ?? '#ef5350',
17318
+ borderVisible: options.borderVisible ?? true,
17319
+ borderUpColor: options.borderUpColor ?? '#26a69a',
17320
+ borderDownColor: options.borderDownColor ?? '#ef5350',
17321
+ wickVisible: options.wickVisible ?? true,
17322
+ wickUpColor: options.wickUpColor ?? '#26a69a',
17323
+ wickDownColor: options.wickDownColor ?? '#ef5350',
17324
+ hideSource: options.hideSource ?? true,
17325
+ };
17326
+ const sourceOptions = series.options();
17327
+ // Same price scale and the same formatting as the source: the candles are a
17328
+ // restatement of that series, not a second instrument, so they must not
17329
+ // autoscale on their own axis or round to a different precision.
17330
+ const haSeries = chart.addSeries(candlestickSeries, {
17331
+ upColor: resolved.upColor,
17332
+ downColor: resolved.downColor,
17333
+ borderVisible: resolved.borderVisible,
17334
+ borderUpColor: resolved.borderUpColor,
17335
+ borderDownColor: resolved.borderDownColor,
17336
+ wickVisible: resolved.wickVisible,
17337
+ wickUpColor: resolved.wickUpColor,
17338
+ wickDownColor: resolved.wickDownColor,
17339
+ priceScaleId: sourceOptions.priceScaleId,
17340
+ priceFormat: sourceOptions.priceFormat,
17341
+ }, resolved.paneIndex);
17342
+ let restoreSourcePaint = null;
17343
+ const blankSource = (blank) => {
17344
+ if (blank && restoreSourcePaint === null) {
17345
+ restoreSourcePaint = hideSeriesPaint(series);
17346
+ }
17347
+ else if (!blank && restoreSourcePaint !== null) {
17348
+ restoreSourcePaint();
17349
+ restoreSourcePaint = null;
17350
+ }
17351
+ };
17352
+ const runtime = bindIndicator({
17353
+ _internal_source: series,
17354
+ _internal_chart: chart,
17355
+ _internal_outputs: [haSeries],
17356
+ _internal_label: 'Heikin Ashi',
17357
+ _internal_options: resolved,
17358
+ // Every option here is a colour or a toggle on the series itself, so a
17359
+ // change never needs the transform run again.
17360
+ _internal_recomputeOn: [],
17361
+ _internal_compute: (data) => [
17362
+ [haSeries, calculateHeikinAshi(data)],
17363
+ ],
17364
+ _internal_applyStyle: (current) => {
17365
+ haSeries.applyOptions({
17366
+ upColor: current.upColor,
17367
+ downColor: current.downColor,
17368
+ borderVisible: current.borderVisible,
17369
+ borderUpColor: current.borderUpColor,
17370
+ borderDownColor: current.borderDownColor,
17371
+ wickVisible: current.wickVisible,
17372
+ wickUpColor: current.wickUpColor,
17373
+ wickDownColor: current.wickDownColor,
17374
+ });
17375
+ blankSource(current.hideSource === true);
17376
+ },
17377
+ });
17378
+ const handle = {
17379
+ _internal_series: haSeries,
17380
+ options: runtime.options,
17381
+ applyOptions: runtime.applyOptions,
17382
+ recalculate: runtime.recalculate,
17383
+ remove: () => {
17384
+ runtime.remove();
17385
+ // The source outlives the indicator, so its paint is ours to put
17386
+ // back — otherwise removing a Heikin Ashi overlay leaves a blank chart.
17387
+ try {
17388
+ blankSource(false);
17389
+ }
17390
+ catch (error) {
17391
+ // The series may already be gone if the chart was disposed
17392
+ }
17393
+ },
17394
+ };
17395
+ return handle;
17396
+ }
17397
+
17157
17398
  /**
17158
17399
  * Apply RSI indicator to a series
17159
17400
  * @param series - Source series to calculate RSI from
@@ -29212,7 +29453,7 @@ const customSeriesDefaultOptions = {
29212
29453
  * Returns the current version as a string. For example `'1.0.0'`.
29213
29454
  */
29214
29455
  function version() {
29215
- return "2.0.1";
29456
+ return "2.2.0";
29216
29457
  }
29217
29458
 
29218
- export { areaSeries as AreaSeries, ArrowTool, barSeries as BarSeries, baselineSeries as BaselineSeries, BrushTool, candlestickSeries as CandlestickSeries, CircleTool, ColorType, CrossLineTool, CrosshairMode, DEFAULT_SESSIONS, DraggablePriceLine, DrawingToolsManager, EXTENDED_FIBONACCI_RATIOS, FibonacciCalculator, FibonacciExtensionTool, FibonacciFanTool, FibonacciTool, GanttTool, histogramSeries as HistogramSeries, HorizontalLineTool, InteractiveLineManager, LastPriceAnimationMode, lineSeries as LineSeries, LineStyle, LineType, MismatchDirection, ParallelChannelTool, PitchforkTool, PolygonTool, PositionCalculator, PositionMarkersManager, PositionTool, PriceLineSource, PriceScaleMode, RectangleTool, RulerCalculator, RulerTool, STANDARD_FIBONACCI_RATIOS, TextTool, TickMarkType, TrackingModeExitMode, TradingSessionsIndicator, TrendLineTool, VerticalLineTool, VolumeProfileIndicator, applyADX, applyATR, applyBollingerBands, applyCCI, applyDonchianChannels, applyEMA, applyIchimoku, applyKeltnerChannels, applyMACD, applyMFI, applyOBV, applyParabolicSAR, applyPivotPoints, applyRSI, applySMA, applyStochastic, applySuperTrend, applyVWAP, applyVolume, applyWMA, applyWilliamsR, calculatePipConfig, coordinateFromTime, createArrowTool, createBrushTool, createChart, createChartEx, createCircleTool, createCrossLineTool, createFibonacciExtensionTool, createFibonacciFanTool, createFibonacciTool, createGanttTool, createHorizontalLineTool, createImageWatermark, createInteractiveLineManager, createOptionsChart, createParallelChannelTool, createPitchforkTool, createPolygonTool, createPositionMarkers, createPositionTool, createRectangleTool, createRulerTool, createSeriesMarkers, createTextTool, createTextWatermark, createTradingLine, createTradingSessionsIndicator, createTrendLineTool, createUpDownMarkers, createVerticalLineTool, createVolumeProfileIndicator, createYieldCurveChart, customSeriesDefaultOptions, defaultHorzScaleBehavior, getPipConfig, isBusinessDay, isUTCTimestamp, setSeriesVolumes, setVolumeProfileData, timeFromCoordinate, version };
29459
+ export { areaSeries as AreaSeries, ArrowTool, barSeries as BarSeries, baselineSeries as BaselineSeries, BrushTool, candlestickSeries as CandlestickSeries, CircleTool, ColorType, CrossLineTool, CrosshairMode, DEFAULT_SESSIONS, DraggablePriceLine, DrawingToolsManager, EXTENDED_FIBONACCI_RATIOS, FibonacciCalculator, FibonacciExtensionTool, FibonacciFanTool, FibonacciTool, GanttTool, histogramSeries as HistogramSeries, HorizontalLineTool, InteractiveLineManager, LastPriceAnimationMode, lineSeries as LineSeries, LineStyle, LineType, MismatchDirection, ParallelChannelTool, PitchforkTool, PolygonTool, PositionCalculator, PositionMarkersManager, PositionTool, PriceLineSource, PriceScaleMode, RectangleTool, RulerCalculator, RulerTool, STANDARD_FIBONACCI_RATIOS, TextTool, TickMarkType, TrackingModeExitMode, TradingSessionsIndicator, TrendLineTool, VerticalLineTool, VolumeProfileIndicator, applyADX, applyATR, applyBollingerBands, applyCCI, applyDonchianChannels, applyEMA, applyHeikinAshi, applyIchimoku, applyKeltnerChannels, applyMACD, applyMFI, applyOBV, applyParabolicSAR, applyPivotPoints, applyRSI, applySMA, applyStochastic, applySuperTrend, applyVWAP, applyVolume, applyWMA, applyWilliamsR, calculateHeikinAshi, calculatePipConfig, coordinateFromTime, createArrowTool, createBrushTool, createChart, createChartEx, createCircleTool, createCrossLineTool, createFibonacciExtensionTool, createFibonacciFanTool, createFibonacciTool, createGanttTool, createHorizontalLineTool, createImageWatermark, createInteractiveLineManager, createOptionsChart, createParallelChannelTool, createPitchforkTool, createPolygonTool, createPositionMarkers, createPositionTool, createRectangleTool, createRulerTool, createSeriesMarkers, createTextTool, createTextWatermark, createTradingLine, createTradingSessionsIndicator, createTrendLineTool, createUpDownMarkers, createVerticalLineTool, createVolumeProfileIndicator, createYieldCurveChart, customSeriesDefaultOptions, defaultHorzScaleBehavior, getPipConfig, hideSeriesPaint, isBusinessDay, isUTCTimestamp, setSeriesVolumes, setVolumeProfileData, timeFromCoordinate, version };