Skip to content

Commit 9c78383

Browse files
committed
fix: fix the problem that asynchronous calculation of indicators may cause incorrect display
1 parent f80972a commit 9c78383

34 files changed

+306
-261
lines changed

src/Chart.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -505,28 +505,6 @@ export default class ChartImp implements Chart {
505505
}
506506
}
507507

508-
crosshairChange (crosshair: Crosshair): void {
509-
if (this._chartStore.hasAction('onCrosshairChange')) {
510-
const indicatorData = {}
511-
this._drawPanes.forEach(pane => {
512-
const id = pane.getId()
513-
const paneIndicatorData = {}
514-
const indicators = this._chartStore.getIndicatorsByPaneId(id)
515-
indicators.forEach(indicator => {
516-
const result = indicator.result
517-
paneIndicatorData[indicator.name] = result[crosshair.dataIndex ?? result.length - 1]
518-
})
519-
indicatorData[id] = paneIndicatorData
520-
})
521-
if (isString(crosshair.paneId)) {
522-
this._chartStore.executeAction('onCrosshairChange', {
523-
crosshair,
524-
indicatorData
525-
})
526-
}
527-
}
528-
}
529-
530508
getDom (paneId?: string, position?: DomPosition): Nullable<HTMLElement> {
531509
if (isValid(paneId)) {
532510
const pane = this.getDrawPaneById(paneId)

src/Store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,8 +1063,8 @@ export default class StoreImp implements Store {
10631063
prevCrosshair.paneId !== cr.paneId ||
10641064
(forceInvalidate ?? false)
10651065
) {
1066-
if (isValid(kLineData) && !(notExecuteAction ?? false)) {
1067-
this._chart.crosshairChange(this._crosshair)
1066+
if (isValid(kLineData) && !(notExecuteAction ?? false) && this.hasAction('onCrosshairChange') && isString(this._crosshair.paneId)) {
1067+
this.executeAction('onCrosshairChange', crosshair)
10681068
}
10691069
if (!(notInvalidate ?? false)) {
10701070
this._chart.updatePane(UpdateLevel.Overlay)

src/component/Indicator.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export interface IndicatorDrawParams<D, C, E> {
9999

100100
export type IndicatorDrawCallback<D, C, E> = (params: IndicatorDrawParams<D, C, E>) => boolean
101101

102-
export type IndicatorCalcCallback<D, C, E> = (dataList: KLineData[], indicator: Indicator<D, C, E>) => Promise<D[]> | D[]
102+
export type IndicatorCalcCallback<D, C, E> = (dataList: KLineData[], indicator: Indicator<D, C, E>) => Promise<Record<number, D>> | Record<number, D>
103103

104104
export type IndicatorShouldUpdateCallback<D, C, E> = (prev: Indicator<D, C, E>, current: Indicator<D, C, E>) => (boolean | { calc: boolean, draw: boolean })
105105

@@ -227,7 +227,7 @@ export interface Indicator<D = unknown, C = unknown, E = unknown> {
227227
/**
228228
* Calculation result
229229
*/
230-
result: D[]
230+
result: Record<number, D>
231231
}
232232

233233
export type IndicatorTemplate<D = unknown, C = unknown, E = unknown> = ExcludePickPartial<Omit<Indicator<D, C, E>, 'result' | 'paneId'>, 'name' | 'calc'>
@@ -244,7 +244,7 @@ export type EachFigureCallback<D> = (figure: IndicatorFigure<D>, figureStyles: I
244244

245245
export function eachFigures<D = unknown> (
246246
indicator: Indicator,
247-
dataIndex: number,
247+
timestamps: NeighborData<Nullable<number>>,
248248
defaultStyles: IndicatorStyle,
249249
eachFigureCallback: EachFigureCallback<D>
250250
): void {
@@ -295,9 +295,9 @@ export function eachFigures<D = unknown> (
295295
if (isValid(figure.type)) {
296296
const ss = figure.styles?.({
297297
data: {
298-
prev: result[dataIndex - 1],
299-
current: result[dataIndex],
300-
next: result[dataIndex + 1]
298+
prev: result[timestamps.prev ?? ''],
299+
current: result[timestamps.current ?? ''],
300+
next: result[timestamps.next ?? '']
301301
},
302302
indicator,
303303
defaultStyles
@@ -347,14 +347,14 @@ export default class IndicatorImp<D = unknown, C = unknown, E = unknown> impleme
347347
return { calc, draw }
348348
}
349349

350-
calc: IndicatorCalcCallback<D, C, E> = () => []
350+
calc: IndicatorCalcCallback<D, C, E> = () => ({})
351351
regenerateFigures: Nullable<IndicatorRegenerateFiguresCallback<D, C>> = null
352352
createTooltipDataSource: Nullable<IndicatorCreateTooltipDataSourceCallback<D>> = null
353353
draw: Nullable<IndicatorDrawCallback<D, C, E>> = null
354354

355355
onDataStateChange: Nullable<IndicatorOnDataStateChangeCallback<D>> = null
356356

357-
result: D[] = []
357+
result: Record<number, D> = {}
358358

359359
private _prevIndicator: Indicator<D, C, E>
360360
private _lockSeriesPrecision = false

src/component/YAxis.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,32 +119,31 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
119119
const areaValueKey = candleStyles.area.value
120120
const shouldCompareHighLow = (inCandle && !isArea) || (!inCandle && shouldOhlc)
121121
visibleRangeDataList.forEach((visibleData) => {
122-
const dataIndex = visibleData.dataIndex
123-
const data = visibleData.data.current
124-
if (isValid(data)) {
122+
const kLineData = visibleData.data.current
123+
if (isValid(kLineData)) {
125124
if (shouldCompareHighLow) {
126-
min = Math.min(min, data.low)
127-
max = Math.max(max, data.high)
125+
min = Math.min(min, kLineData.low)
126+
max = Math.max(max, kLineData.high)
128127
}
129128
if (inCandle && isArea) {
130-
const value = data[areaValueKey]
129+
const value = kLineData[areaValueKey]
131130
if (isNumber(value)) {
132131
min = Math.min(min, value)
133132
max = Math.max(max, value)
134133
}
135134
}
136-
}
137-
indicators.forEach(({ result, figures }) => {
138-
const data = result[dataIndex] ?? {}
139-
figures.forEach(figure => {
135+
indicators.forEach(({ result, figures }) => {
136+
const data = result[kLineData.timestamp] ?? {}
137+
figures.forEach(figure => {
140138
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- ignore
141-
const value = data[figure.key]
142-
if (isNumber(value)) {
143-
min = Math.min(min, value)
144-
max = Math.max(max, value)
145-
}
139+
const value = data[figure.key]
140+
if (isNumber(value)) {
141+
min = Math.min(min, value)
142+
max = Math.max(max, value)
143+
}
144+
})
146145
})
147-
})
146+
}
148147
})
149148

150149
if (min !== Number.MAX_SAFE_INTEGER && max !== Number.MIN_SAFE_INTEGER) {

src/extension/indicator/averagePrice.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const averagePrice: IndicatorTemplate<Avp> = {
3232
calc: (dataList) => {
3333
let totalTurnover = 0
3434
let totalVolume = 0
35-
return dataList.map((kLineData) => {
35+
return dataList.reduce((prev, kLineData) => {
3636
const avp: Avp = {}
3737
const turnover = kLineData.turnover ?? 0
3838
const volume = kLineData.volume ?? 0
@@ -41,8 +41,9 @@ const averagePrice: IndicatorTemplate<Avp> = {
4141
if (totalVolume !== 0) {
4242
avp.avp = totalTurnover / totalVolume
4343
}
44-
return avp
45-
})
44+
prev[kLineData.timestamp] = avp
45+
return prev
46+
}, {})
4647
}
4748
}
4849

src/extension/indicator/awesomeOscillator.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const awesomeOscillator: IndicatorTemplate<Ao, number> = {
5050
let longSum = 0
5151
let short = 0
5252
let long = 0
53-
return dataList.map((kLineData, i) => {
53+
return dataList.reduce((prev, kLineData, i) => {
5454
const ao: Ao = {}
5555
const middle = (kLineData.low + kLineData.high) / 2
5656
shortSum += middle
@@ -68,8 +68,9 @@ const awesomeOscillator: IndicatorTemplate<Ao, number> = {
6868
if (i >= maxPeriod - 1) {
6969
ao.ao = short - long
7070
}
71-
return ao
72-
})
71+
prev[kLineData.timestamp] = ao
72+
return prev
73+
}, {})
7374
}
7475
}
7576

src/extension/indicator/bias.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const bias: IndicatorTemplate<Bias, number> = {
3737
calc: (dataList, indicator) => {
3838
const { calcParams: params, figures } = indicator
3939
const closeSums: number[] = []
40-
return dataList.map((kLineData, i) => {
40+
return dataList.reduce((prev, kLineData, i) => {
4141
const bias: Bias = {}
4242
const close = kLineData.close
4343
params.forEach((p, index) => {
@@ -49,8 +49,9 @@ const bias: IndicatorTemplate<Bias, number> = {
4949
closeSums[index] -= dataList[i - (p - 1)].close
5050
}
5151
})
52-
return bias
53-
})
52+
prev[kLineData.timestamp] = bias
53+
return prev
54+
}, {})
5455
}
5556
}
5657

src/extension/indicator/bollingerBands.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const bollingerBands: IndicatorTemplate<Boll, number> = {
5757
const params = indicator.calcParams
5858
const p = params[0] - 1
5959
let closeSum = 0
60-
return dataList.map((kLineData, i) => {
60+
return dataList.reduce((prev, kLineData, i) => {
6161
const close = kLineData.close
6262
const boll: Boll = {}
6363
closeSum += close
@@ -68,8 +68,9 @@ const bollingerBands: IndicatorTemplate<Boll, number> = {
6868
boll.dn = boll.mid - params[1] * md
6969
closeSum -= dataList[i - p].close
7070
}
71-
return boll
72-
})
71+
prev[kLineData.timestamp] = boll
72+
return prev
73+
}, {})
7374
}
7475
}
7576

src/extension/indicator/brar.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const brar: IndicatorTemplate<Brar, number> = {
4242
let cyl = 0
4343
let ho = 0
4444
let ol = 0
45-
return dataList.map((kLineData, i) => {
45+
return dataList.reduce((prev, kLineData, i) => {
4646
const brar: Brar = {}
4747
const high = kLineData.high
4848
const low = kLineData.low
@@ -73,8 +73,9 @@ const brar: IndicatorTemplate<Brar, number> = {
7373
ho -= (agoHigh - agoOpen)
7474
ol -= (agoOpen - agoLow)
7575
}
76-
return brar
77-
})
76+
prev[kLineData.timestamp] = brar
77+
return prev
78+
}, {})
7879
}
7980
}
8081

src/extension/indicator/bullAndBearIndex.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const bullAndBearIndex: IndicatorTemplate<Bbi, number> = {
3737
const maxPeriod = Math.max(...params)
3838
const closeSums: number[] = []
3939
const mas: number[] = []
40-
return dataList.map((kLineData, i) => {
40+
return dataList.reduce((prev, kLineData, i) => {
4141
const bbi: Bbi = {}
4242
const close = kLineData.close
4343
params.forEach((p, index) => {
@@ -54,8 +54,9 @@ const bullAndBearIndex: IndicatorTemplate<Bbi, number> = {
5454
})
5555
bbi.bbi = maSum / 4
5656
}
57-
return bbi
58-
})
57+
prev[kLineData.timestamp] = bbi
58+
return prev
59+
}, {})
5960
}
6061
}
6162

0 commit comments

Comments
 (0)