@qfo/qfchart 0.5.0 → 0.5.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qfo/qfchart",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Professional financial charting library built on Apache ECharts with candlestick charts, technical indicators, and interactive drawing tools",
5
5
  "keywords": [
6
6
  "chart",
@@ -69,12 +69,29 @@ export class SeriesBuilder {
69
69
  plot.data.forEach((point) => {
70
70
  const index = timeToIndex.get(point.time);
71
71
  if (index !== undefined) {
72
- const offsetIndex = index + dataIndexOffset;
73
- dataArray[offsetIndex] = point.value;
74
- colorArray[offsetIndex] = point.options?.color || plot.options.color;
72
+ const plotOffset = point.options?.offset ?? plot.options.offset ?? 0;
73
+ const offsetIndex = index + dataIndexOffset + plotOffset;
74
+
75
+ if (offsetIndex >= 0 && offsetIndex < totalDataLength) {
76
+ let value = point.value;
77
+ const pointColor = point.options?.color;
78
+
79
+ // TradingView compatibility: if color is 'na' (NaN, null, or "na"), break the line
80
+ const isNaColor =
81
+ pointColor === null ||
82
+ pointColor === 'na' ||
83
+ pointColor === 'NaN' ||
84
+ (typeof pointColor === 'number' && isNaN(pointColor));
85
+
86
+ if (isNaColor) {
87
+ value = null;
88
+ }
89
+
90
+ dataArray[offsetIndex] = value;
91
+ colorArray[offsetIndex] = pointColor || plot.options.color;
92
+ }
75
93
  }
76
94
  });
77
-
78
95
  switch (plot.options.style) {
79
96
  case 'histogram':
80
97
  case 'columns':
@@ -163,24 +180,75 @@ export class SeriesBuilder {
163
180
  });
164
181
  break;
165
182
 
183
+ case 'step':
184
+ series.push({
185
+ name: seriesName,
186
+ type: 'custom',
187
+ xAxisIndex: xAxisIndex,
188
+ yAxisIndex: yAxisIndex,
189
+ renderItem: (params: any, api: any) => {
190
+ const x = api.value(0);
191
+ const y = api.value(1);
192
+ if (isNaN(y) || y === null) return;
193
+
194
+ const coords = api.coord([x, y]);
195
+ const width = api.size([1, 0])[0];
196
+
197
+ return {
198
+ type: 'line',
199
+ shape: {
200
+ x1: coords[0] - width / 2,
201
+ y1: coords[1],
202
+ x2: coords[0] + width / 2,
203
+ y2: coords[1],
204
+ },
205
+ style: {
206
+ stroke: colorArray[params.dataIndex] || plot.options.color,
207
+ lineWidth: plot.options.linewidth || 1,
208
+ },
209
+ silent: true,
210
+ };
211
+ },
212
+ data: dataArray.map((val, i) => [i, val]),
213
+ });
214
+ break;
215
+
166
216
  case 'line':
167
217
  default:
168
218
  series.push({
169
219
  name: seriesName,
170
- type: 'line',
220
+ type: 'custom',
171
221
  xAxisIndex: xAxisIndex,
172
222
  yAxisIndex: yAxisIndex,
173
- smooth: true,
174
- showSymbol: false,
175
- data: dataArray.map((val, i) => ({
176
- value: val,
177
- itemStyle: colorArray[i] ? { color: colorArray[i] } : undefined,
178
- })),
179
- itemStyle: { color: plot.options.color },
180
- lineStyle: {
181
- width: plot.options.linewidth || 1,
182
- color: plot.options.color,
223
+ renderItem: (params: any, api: any) => {
224
+ const index = params.dataIndex;
225
+ if (index === 0) return; // Need at least two points for a line segment
226
+
227
+ const y2 = api.value(1);
228
+ const y1 = api.value(2); // We'll store prevValue in the data
229
+
230
+ if (y2 === null || isNaN(y2) || y1 === null || isNaN(y1)) return;
231
+
232
+ const p1 = api.coord([index - 1, y1]);
233
+ const p2 = api.coord([index, y2]);
234
+
235
+ return {
236
+ type: 'line',
237
+ shape: {
238
+ x1: p1[0],
239
+ y1: p1[1],
240
+ x2: p2[0],
241
+ y2: p2[1],
242
+ },
243
+ style: {
244
+ stroke: colorArray[index] || plot.options.color,
245
+ lineWidth: plot.options.linewidth || 1,
246
+ },
247
+ silent: true,
248
+ };
183
249
  },
250
+ // Data format: [index, value, prevValue]
251
+ data: dataArray.map((val, i) => [i, val, i > 0 ? dataArray[i - 1] : null]),
184
252
  });
185
253
  break;
186
254
  }
package/src/types.ts CHANGED
@@ -14,15 +14,18 @@ export interface IndicatorPoint {
14
14
  value: number | null;
15
15
  options?: {
16
16
  color?: string;
17
+ offset?: number;
17
18
  };
18
19
  }
19
20
 
20
- export type IndicatorStyle = 'line' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background';
21
+ export type IndicatorStyle = 'line' | 'step' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background';
21
22
 
22
23
  export interface IndicatorOptions {
23
24
  style: IndicatorStyle;
24
25
  color: string;
26
+ offset?: number;
25
27
  linewidth?: number;
28
+ smooth?: boolean;
26
29
  }
27
30
 
28
31
  export interface IndicatorPlot {