@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.
- package/dist/controllers/createChartController.d.ts.map +1 -1
- package/dist/controllers/createChartController.js +31 -0
- package/dist/controllers/createChartController.js.map +1 -1
- package/dist/controllers/types.d.ts +16 -0
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.d.ts +9 -2
- package/dist/data-fetchers/baostock.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.js +78 -9
- package/dist/data-fetchers/baostock.js.map +1 -1
- package/dist/data-fetchers/dataBuffer.d.ts.map +1 -1
- package/dist/data-fetchers/dataBuffer.js +3 -0
- package/dist/data-fetchers/dataBuffer.js.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts +13 -0
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -0
- package/dist/data-fetchers/fetcherDefinitionRegistry.js +36 -0
- package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -0
- package/dist/data-fetchers/gotdx.d.ts +10 -0
- package/dist/data-fetchers/gotdx.d.ts.map +1 -0
- package/dist/data-fetchers/gotdx.js +168 -0
- package/dist/data-fetchers/gotdx.js.map +1 -0
- package/dist/data-fetchers/hundred-mock.d.ts +9 -2
- package/dist/data-fetchers/hundred-mock.d.ts.map +1 -1
- package/dist/data-fetchers/hundred-mock.js +92 -7
- package/dist/data-fetchers/hundred-mock.js.map +1 -1
- package/dist/data-fetchers/index.d.ts +7 -4
- package/dist/data-fetchers/index.d.ts.map +1 -1
- package/dist/data-fetchers/index.js +6 -4
- package/dist/data-fetchers/index.js.map +1 -1
- package/dist/data-fetchers/router.d.ts.map +1 -1
- package/dist/data-fetchers/router.js +14 -15
- package/dist/data-fetchers/router.js.map +1 -1
- package/dist/data-fetchers/thousand-mock.d.ts +9 -2
- package/dist/data-fetchers/thousand-mock.d.ts.map +1 -1
- package/dist/data-fetchers/thousand-mock.js +88 -16
- package/dist/data-fetchers/thousand-mock.js.map +1 -1
- package/dist/data-fetchers/tradingview.d.ts +9 -2
- package/dist/data-fetchers/tradingview.d.ts.map +1 -1
- package/dist/data-fetchers/tradingview.js +75 -4
- package/dist/data-fetchers/tradingview.js.map +1 -1
- package/dist/data-fetchers/types.d.ts +21 -0
- package/dist/data-fetchers/types.d.ts.map +1 -0
- package/dist/data-fetchers/types.js +2 -0
- package/dist/data-fetchers/types.js.map +1 -0
- package/dist/engine/data/chartDataManager.d.ts +1 -0
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +3 -0
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/render/chartRenderer.d.ts.map +1 -1
- package/dist/engine/render/chartRenderer.js +2 -0
- package/dist/engine/render/chartRenderer.js.map +1 -1
- package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/ichimoku.js +8 -5
- package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
- package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/sar.js +3 -3
- package/dist/engine/renderers/Indicator/sar.js.map +1 -1
- package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/supertrend.js +3 -3
- package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
- package/dist/engine/renderers/timeAxis.d.ts.map +1 -1
- package/dist/engine/renderers/timeAxis.js +1 -0
- package/dist/engine/renderers/timeAxis.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/chartBridge.d.ts +47 -0
- package/dist/mcp/chartBridge.d.ts.map +1 -0
- package/dist/mcp/chartBridge.js +167 -0
- package/dist/mcp/chartBridge.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/types.d.ts +17 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/plugin/types.d.ts +2 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/types.js.map +1 -1
- package/dist/semantic/index.d.ts +1 -1
- package/dist/semantic/index.d.ts.map +1 -1
- package/dist/semantic/index.js.map +1 -1
- package/dist/semantic/schema.json +1 -1
- package/dist/semantic/types.d.ts +2 -1
- package/dist/semantic/types.d.ts.map +1 -1
- package/dist/utils/dateFormat.d.ts +25 -0
- package/dist/utils/dateFormat.d.ts.map +1 -1
- package/dist/utils/dateFormat.js +78 -0
- package/dist/utils/dateFormat.js.map +1 -1
- package/dist/utils/kLineDraw/axis.d.ts +2 -0
- package/dist/utils/kLineDraw/axis.d.ts.map +1 -1
- package/dist/utils/kLineDraw/axis.js +11 -6
- package/dist/utils/kLineDraw/axis.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/controllers/createChartController.ts +34 -0
- package/src/controllers/types.ts +9 -0
- package/src/data-fetchers/__tests__/dataBuffer.test.ts +5 -2
- package/src/data-fetchers/__tests__/fetcherRegistry.test.ts +192 -0
- package/src/data-fetchers/baostock.ts +54 -22
- package/src/data-fetchers/dataBuffer.ts +6 -0
- package/src/data-fetchers/fetcherDefinitionRegistry.ts +50 -0
- package/src/data-fetchers/gotdx.ts +160 -0
- package/src/data-fetchers/hundred-mock.ts +54 -7
- package/src/data-fetchers/index.ts +19 -4
- package/src/data-fetchers/router.ts +27 -15
- package/src/data-fetchers/thousand-mock.ts +49 -16
- package/src/data-fetchers/tradingview.ts +32 -6
- package/src/data-fetchers/types.ts +27 -0
- package/src/engine/data/chartDataManager.ts +4 -0
- package/src/engine/render/chartRenderer.ts +2 -0
- package/src/engine/renderers/Indicator/ichimoku.ts +10 -4
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +1 -1
- package/src/engine/renderers/Indicator/sar.ts +3 -3
- package/src/engine/renderers/Indicator/supertrend.ts +3 -4
- package/src/engine/renderers/__tests__/boll.renderer.test.ts +1 -0
- package/src/engine/renderers/__tests__/ene.renderer.test.ts +1 -0
- package/src/engine/renderers/__tests__/expma.renderer.test.ts +1 -0
- package/src/engine/renderers/__tests__/ma.renderer.test.ts +1 -0
- package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +1 -0
- package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +1 -0
- package/src/engine/renderers/timeAxis.ts +1 -0
- package/src/index.ts +2 -0
- package/src/mcp/chartBridge.ts +220 -0
- package/src/mcp/index.ts +2 -0
- package/src/mcp/types.ts +19 -0
- package/src/plugin/types.ts +2 -0
- package/src/semantic/index.ts +1 -0
- package/src/semantic/schema.json +1 -1
- package/src/semantic/types.ts +3 -1
- package/src/utils/dateFormat.ts +85 -0
- package/src/utils/kLineDraw/axis.ts +13 -6
- package/src/version.ts +1 -1
package/src/semantic/schema.json
CHANGED
|
@@ -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": {
|
package/src/semantic/types.ts
CHANGED
|
@@ -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:
|
|
35
|
+
adjust: AdjustType
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
// ============ 指标配置 ============
|
package/src/utils/dateFormat.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
427
|
-
if (lastWasYear !== isYear) {
|
|
434
|
+
if (lastBold !== isYear) {
|
|
428
435
|
setCanvasFont(ctx, isYear ? boldFont : regularFont)
|
|
429
|
-
|
|
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
|
+
export const VERSION = "0.8.3"
|