@363045841yyt/klinechart-core 0.8.1 → 0.8.3

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.
Files changed (138) hide show
  1. package/dist/controllers/createChartController.d.ts.map +1 -1
  2. package/dist/controllers/createChartController.js +31 -0
  3. package/dist/controllers/createChartController.js.map +1 -1
  4. package/dist/controllers/types.d.ts +16 -0
  5. package/dist/controllers/types.d.ts.map +1 -1
  6. package/dist/data-fetchers/baostock.d.ts +9 -2
  7. package/dist/data-fetchers/baostock.d.ts.map +1 -1
  8. package/dist/data-fetchers/baostock.js +78 -9
  9. package/dist/data-fetchers/baostock.js.map +1 -1
  10. package/dist/data-fetchers/dataBuffer.d.ts.map +1 -1
  11. package/dist/data-fetchers/dataBuffer.js +3 -0
  12. package/dist/data-fetchers/dataBuffer.js.map +1 -1
  13. package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts +13 -0
  14. package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -0
  15. package/dist/data-fetchers/fetcherDefinitionRegistry.js +36 -0
  16. package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -0
  17. package/dist/data-fetchers/gotdx.d.ts +10 -0
  18. package/dist/data-fetchers/gotdx.d.ts.map +1 -0
  19. package/dist/data-fetchers/gotdx.js +168 -0
  20. package/dist/data-fetchers/gotdx.js.map +1 -0
  21. package/dist/data-fetchers/hundred-mock.d.ts +9 -2
  22. package/dist/data-fetchers/hundred-mock.d.ts.map +1 -1
  23. package/dist/data-fetchers/hundred-mock.js +92 -7
  24. package/dist/data-fetchers/hundred-mock.js.map +1 -1
  25. package/dist/data-fetchers/index.d.ts +7 -4
  26. package/dist/data-fetchers/index.d.ts.map +1 -1
  27. package/dist/data-fetchers/index.js +6 -4
  28. package/dist/data-fetchers/index.js.map +1 -1
  29. package/dist/data-fetchers/router.d.ts.map +1 -1
  30. package/dist/data-fetchers/router.js +14 -15
  31. package/dist/data-fetchers/router.js.map +1 -1
  32. package/dist/data-fetchers/thousand-mock.d.ts +9 -2
  33. package/dist/data-fetchers/thousand-mock.d.ts.map +1 -1
  34. package/dist/data-fetchers/thousand-mock.js +88 -16
  35. package/dist/data-fetchers/thousand-mock.js.map +1 -1
  36. package/dist/data-fetchers/tradingview.d.ts +9 -2
  37. package/dist/data-fetchers/tradingview.d.ts.map +1 -1
  38. package/dist/data-fetchers/tradingview.js +75 -4
  39. package/dist/data-fetchers/tradingview.js.map +1 -1
  40. package/dist/data-fetchers/types.d.ts +21 -0
  41. package/dist/data-fetchers/types.d.ts.map +1 -0
  42. package/dist/data-fetchers/types.js +2 -0
  43. package/dist/data-fetchers/types.js.map +1 -0
  44. package/dist/engine/data/chartDataManager.d.ts +1 -0
  45. package/dist/engine/data/chartDataManager.d.ts.map +1 -1
  46. package/dist/engine/data/chartDataManager.js +3 -0
  47. package/dist/engine/data/chartDataManager.js.map +1 -1
  48. package/dist/engine/render/chartRenderer.d.ts.map +1 -1
  49. package/dist/engine/render/chartRenderer.js +2 -0
  50. package/dist/engine/render/chartRenderer.js.map +1 -1
  51. package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
  52. package/dist/engine/renderers/Indicator/ichimoku.js +8 -5
  53. package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
  54. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +1 -1
  55. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
  56. package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
  57. package/dist/engine/renderers/Indicator/sar.js +3 -3
  58. package/dist/engine/renderers/Indicator/sar.js.map +1 -1
  59. package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
  60. package/dist/engine/renderers/Indicator/supertrend.js +3 -3
  61. package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
  62. package/dist/engine/renderers/timeAxis.d.ts.map +1 -1
  63. package/dist/engine/renderers/timeAxis.js +1 -0
  64. package/dist/engine/renderers/timeAxis.js.map +1 -1
  65. package/dist/index.d.ts +2 -0
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +2 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/mcp/chartBridge.d.ts +47 -0
  70. package/dist/mcp/chartBridge.d.ts.map +1 -0
  71. package/dist/mcp/chartBridge.js +167 -0
  72. package/dist/mcp/chartBridge.js.map +1 -0
  73. package/dist/mcp/index.d.ts +3 -0
  74. package/dist/mcp/index.d.ts.map +1 -0
  75. package/dist/mcp/index.js +2 -0
  76. package/dist/mcp/index.js.map +1 -0
  77. package/dist/mcp/types.d.ts +17 -0
  78. package/dist/mcp/types.d.ts.map +1 -0
  79. package/dist/mcp/types.js +2 -0
  80. package/dist/mcp/types.js.map +1 -0
  81. package/dist/plugin/types.d.ts +2 -0
  82. package/dist/plugin/types.d.ts.map +1 -1
  83. package/dist/plugin/types.js.map +1 -1
  84. package/dist/semantic/index.d.ts +1 -1
  85. package/dist/semantic/index.d.ts.map +1 -1
  86. package/dist/semantic/index.js.map +1 -1
  87. package/dist/semantic/schema.json +1 -1
  88. package/dist/semantic/types.d.ts +2 -1
  89. package/dist/semantic/types.d.ts.map +1 -1
  90. package/dist/utils/dateFormat.d.ts +25 -0
  91. package/dist/utils/dateFormat.d.ts.map +1 -1
  92. package/dist/utils/dateFormat.js +78 -0
  93. package/dist/utils/dateFormat.js.map +1 -1
  94. package/dist/utils/kLineDraw/axis.d.ts +2 -0
  95. package/dist/utils/kLineDraw/axis.d.ts.map +1 -1
  96. package/dist/utils/kLineDraw/axis.js +11 -6
  97. package/dist/utils/kLineDraw/axis.js.map +1 -1
  98. package/dist/version.d.ts +1 -1
  99. package/dist/version.js +1 -1
  100. package/package.json +1 -1
  101. package/src/controllers/createChartController.ts +34 -0
  102. package/src/controllers/types.ts +9 -0
  103. package/src/data-fetchers/__tests__/dataBuffer.test.ts +5 -2
  104. package/src/data-fetchers/__tests__/fetcherRegistry.test.ts +192 -0
  105. package/src/data-fetchers/baostock.ts +54 -22
  106. package/src/data-fetchers/dataBuffer.ts +6 -0
  107. package/src/data-fetchers/fetcherDefinitionRegistry.ts +50 -0
  108. package/src/data-fetchers/gotdx.ts +160 -0
  109. package/src/data-fetchers/hundred-mock.ts +54 -7
  110. package/src/data-fetchers/index.ts +19 -4
  111. package/src/data-fetchers/router.ts +27 -15
  112. package/src/data-fetchers/thousand-mock.ts +49 -16
  113. package/src/data-fetchers/tradingview.ts +32 -6
  114. package/src/data-fetchers/types.ts +27 -0
  115. package/src/engine/data/chartDataManager.ts +4 -0
  116. package/src/engine/render/chartRenderer.ts +2 -0
  117. package/src/engine/renderers/Indicator/ichimoku.ts +10 -4
  118. package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +1 -1
  119. package/src/engine/renderers/Indicator/sar.ts +3 -3
  120. package/src/engine/renderers/Indicator/supertrend.ts +3 -4
  121. package/src/engine/renderers/__tests__/boll.renderer.test.ts +1 -0
  122. package/src/engine/renderers/__tests__/ene.renderer.test.ts +1 -0
  123. package/src/engine/renderers/__tests__/expma.renderer.test.ts +1 -0
  124. package/src/engine/renderers/__tests__/ma.renderer.test.ts +1 -0
  125. package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +1 -0
  126. package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +1 -0
  127. package/src/engine/renderers/timeAxis.ts +1 -0
  128. package/src/index.ts +2 -0
  129. package/src/mcp/chartBridge.ts +220 -0
  130. package/src/mcp/index.ts +2 -0
  131. package/src/mcp/types.ts +19 -0
  132. package/src/plugin/types.ts +2 -0
  133. package/src/semantic/index.ts +1 -0
  134. package/src/semantic/schema.json +1 -1
  135. package/src/semantic/types.ts +3 -1
  136. package/src/utils/dateFormat.ts +85 -0
  137. package/src/utils/kLineDraw/axis.ts +13 -6
  138. package/src/version.ts +1 -1
@@ -33,7 +33,7 @@
33
33
  "type": "string",
34
34
  "enum": ["daily", "weekly", "monthly", "5min", "15min", "30min", "60min"]
35
35
  },
36
- "adjust": { "type": "string", "enum": ["qfq", "hfq", "none"] }
36
+ "adjust": { "type": "string", "enum": ["qfq", "hfq", "splits", "none"] }
37
37
  }
38
38
  },
39
39
  "IndicatorsConfig": {
@@ -19,6 +19,8 @@ export interface SemanticChartConfig {
19
19
  // ============ 数据配置 ============
20
20
 
21
21
  /** 数据配置 */
22
+ export type AdjustType = 'qfq' | 'hfq' | 'splits' | 'none'
23
+
22
24
  export interface DataConfig {
23
25
  source: 'baostock' | 'dongcai'
24
26
  /** 股票代码(6位数字,不含前缀) */
@@ -30,7 +32,7 @@ export interface DataConfig {
30
32
  /** 结束日期 YYYY-MM-DD */
31
33
  endDate: string
32
34
  period: 'daily' | 'weekly' | 'monthly' | '5min' | '15min' | '30min' | '60min'
33
- adjust: 'qfq' | 'hfq' | 'none'
35
+ adjust: AdjustType
34
36
  }
35
37
 
36
38
  // ============ 指标配置 ============
@@ -137,6 +137,39 @@ export function monthKey(timestamp: number): number {
137
137
 
138
138
  // ========== 便捷别名 ==========
139
139
 
140
+ /**
141
+ * 格式化时间戳为日期/日期时间字符串,支持可配置时区
142
+ * @param timestamp - 时间戳(毫秒)
143
+ * @param options - 配置项
144
+ * @param options.timeZone - 时区,默认 'Asia/Shanghai'
145
+ * @param options.showTime - 是否显示时间,默认 false
146
+ * @returns 格式化后的字符串,如 "2026-05-15" 或 "2026-05-15 09:35"
147
+ */
148
+ export function formatTimestamp(
149
+ timestamp: number,
150
+ options?: { timeZone?: string; showTime?: boolean }
151
+ ): string {
152
+ const timeZone = options?.timeZone ?? 'Asia/Shanghai'
153
+ const showTime = options?.showTime ?? false
154
+ const formatter = new Intl.DateTimeFormat('zh-CN', {
155
+ timeZone,
156
+ year: 'numeric',
157
+ month: '2-digit',
158
+ day: '2-digit',
159
+ ...(showTime ? { hour: '2-digit', minute: '2-digit', hour12: false } : {}),
160
+ })
161
+ const parts = formatter.formatToParts(new Date(timestamp))
162
+ let y = '', m = '', d = '', h = '', min = ''
163
+ for (const p of parts) {
164
+ if (p.type === 'year') y = p.value
165
+ else if (p.type === 'month') m = p.value
166
+ else if (p.type === 'day') d = p.value
167
+ else if (p.type === 'hour') h = p.value
168
+ else if (p.type === 'minute') min = p.value
169
+ }
170
+ return showTime ? `${y}-${m}-${d} ${h}:${min}` : `${y}-${m}-${d}`
171
+ }
172
+
140
173
  /**
141
174
  * formatDateToYYYYMMDD 的别名,保持与历史代码的兼容性
142
175
  * timestamp 是"上海时区当天 00:00:00"映射到 UTC 的值;显示时强制按上海时区格式化
@@ -206,3 +239,55 @@ export function findMonthBoundaries(data: Array<{ timestamp: number } | undefine
206
239
  _cacheResult = boundaries
207
240
  return boundaries
208
241
  }
242
+
243
+ // ========== 日边界查找 + 日标签格式化 ==========
244
+
245
+ /**
246
+ * 查找每天第一个K线的索引
247
+ */
248
+ export function findDayBoundaries(data: Array<{ timestamp: number } | undefined>): number[] {
249
+ if (data.length === 0) return []
250
+
251
+ const boundaries: number[] = [0]
252
+ let lastKey = dayKey(data[0]!.timestamp)
253
+
254
+ for (let i = 1; i < data.length; i++) {
255
+ const cur = data[i]
256
+ if (!cur) continue
257
+ const curKey = dayKey(cur.timestamp)
258
+ if (curKey !== lastKey) {
259
+ boundaries.push(i)
260
+ lastKey = curKey
261
+ }
262
+ }
263
+
264
+ return boundaries
265
+ }
266
+
267
+ function dayKey(timestamp: number): number {
268
+ const d = new Date(timestamp)
269
+ return d.getFullYear() * 366 + getDayOfYear(d)
270
+ }
271
+
272
+ /**
273
+ * 格式化日期为 "MM-DD" 或年初显示 "YYYY-MM-DD"
274
+ */
275
+ export function formatDay(timestamp: number): { text: string; isYear: boolean } {
276
+ const d = new Date(timestamp)
277
+ const month = String(d.getMonth() + 1).padStart(2, '0')
278
+ const day = String(d.getDate()).padStart(2, '0')
279
+ const isYear = d.getMonth() === 0 && d.getDate() === 1
280
+ if (isYear) {
281
+ return { text: `${d.getFullYear()}-${month}-${day}`, isYear }
282
+ }
283
+ return { text: `${month}-${day}`, isYear }
284
+ }
285
+
286
+ // 兼容 getDayOfYear — fallback when not on Date prototype
287
+ function getDayOfYear(date: Date): number {
288
+ const start = new Date(date.getFullYear(), 0, 0)
289
+ const diff = date.getTime() - start.getTime()
290
+ return Math.floor(diff / 86400000)
291
+ }
292
+
293
+
@@ -1,7 +1,7 @@
1
1
  import type { KLineData } from '../../types/price'
2
2
  import { priceToY, yToPrice } from '../priceToY'
3
3
  import { alignToPhysicalPixelCenter, roundToPhysicalPixel } from '../../engine/draw/pixelAlign'
4
- import { formatYMDShanghai, formatMonthOrYear, findMonthBoundaries } from '../../utils/dateFormat'
4
+ import { formatYMDShanghai, formatMonthOrYear, formatDay, findMonthBoundaries, findDayBoundaries } from '../../utils/dateFormat'
5
5
  import { resolveThemeColors } from '../../tokens'
6
6
  import type { ColorPresetSettings } from '../../tokens'
7
7
  import { getFont, setCanvasFont } from '../../engine/theme/fonts'
@@ -133,6 +133,8 @@ export interface TimeAxisOptions {
133
133
  drawTopBorder?: boolean
134
134
  /** 是否绘制底部边界线(默认 true,如果副图已有下边框则设为 false 避免重复) */
135
135
  drawBottomBorder?: boolean
136
+ /** K线级别,如 'daily'、'5min'、'15min' */
137
+ period: string
136
138
  }
137
139
 
138
140
  export interface LastPriceLineOptions {
@@ -406,15 +408,21 @@ export function drawTimeAxis(ctx: CanvasRenderingContext2D, opts: TimeAxisOption
406
408
  const regularFont = getFont(fontSize)
407
409
  const boldFont = getFont(fontSize, { bold: true })
408
410
 
409
- const boundaries = findMonthBoundaries(data)
411
+ const isMinuteData = opts.period.includes('min')
412
+ const showOnlyYear = !isMinuteData && opts.period !== 'daily'
413
+ const boundaries = isMinuteData ? findDayBoundaries(data) : findMonthBoundaries(data)
410
414
  const visibleBoundaries = boundaries.filter((idx: number) => idx >= startIndex && idx < endIndex)
411
415
 
412
- let lastWasYear: boolean | null = null
416
+ let lastBold: boolean | null = null
417
+ const labelFn = isMinuteData ? formatDay : formatMonthOrYear
413
418
 
414
419
  for (const idx of visibleBoundaries) {
415
420
  const k = data[idx]
416
421
  if (!k) continue
417
422
 
423
+ const { text, isYear } = labelFn(k.timestamp)
424
+ if (showOnlyYear && !isYear) continue
425
+
418
426
  const worldX = startX + idx * unit + alignedKWidth / 2
419
427
  const screenX = worldX - scrollLeft
420
428
 
@@ -423,10 +431,9 @@ export function drawTimeAxis(ctx: CanvasRenderingContext2D, opts: TimeAxisOption
423
431
 
424
432
  if (screenX >= minX && screenX <= maxX) {
425
433
  const drawX = Math.min(Math.max(screenX, minX), maxX)
426
- const { text, isYear } = formatMonthOrYear(k.timestamp)
427
- if (lastWasYear !== isYear) {
434
+ if (lastBold !== isYear) {
428
435
  setCanvasFont(ctx, isYear ? boldFont : regularFont)
429
- lastWasYear = isYear
436
+ lastBold = isYear
430
437
  }
431
438
  ctx.fillText(text, roundToPhysicalPixel(drawX, dpr), alignToPhysicalPixelCenter(textY, dpr))
432
439
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.8.1"
1
+ export const VERSION = "0.8.3"