@@ -20,12 +20,12 @@ import type VisibleRange from '../common/VisibleRange'
2020import type BarSpace from '../common/BarSpace'
2121import type Crosshair from '../common/Crosshair'
2222import { type IndicatorStyle , type IndicatorPolygonStyle , type SmoothLineStyle , type RectStyle , type TextStyle , type TooltipIconStyle , type LineStyle , type LineType , type PolygonType , type TooltipLegend } from '../common/Styles'
23+ import { isNumber , isValid , merge , clone , isArray , isBoolean } from '../common/utils/typeChecks'
2324
2425import { type XAxis } from './XAxis'
2526import { type YAxis } from './YAxis'
2627
2728import { formatValue } from '../common/utils/format'
28- import { isValid , merge , clone } from '../common/utils/typeChecks'
2929
3030import { type ArcAttrs } from '../extension/figure/arc'
3131import { type RectAttrs } from '../extension/figure/rect'
@@ -79,6 +79,8 @@ export interface IndicatorFigure<D = any> {
7979 styles ?: IndicatorFigureStylesCallback < D >
8080}
8181
82+ export type IndicatorShouldUpdateReturn = boolean | { calc : boolean , draw : boolean }
83+
8284export type IndicatorRegenerateFiguresCallback < D = any > = ( calcParams : any [ ] ) => Array < IndicatorFigure < D > >
8385
8486export interface IndicatorTooltipData {
@@ -187,6 +189,11 @@ export interface Indicator<D = any> {
187189 */
188190 styles : Nullable < Partial < IndicatorStyle > >
189191
192+ /**
193+ * Should update, should calc or draw
194+ */
195+ shouldUpdate : ( prev : Indicator < D > , current : Indicator < D > ) => IndicatorShouldUpdateReturn
196+
190197 /**
191198 * Indicator calculation
192199 */
@@ -211,6 +218,11 @@ export interface Indicator<D = any> {
211218 * Calculation result
212219 */
213220 result : D [ ]
221+
222+ /**
223+ * Others
224+ */
225+ [ key : string ] : any
214226}
215227
216228export type IndicatorTemplate < D = any > = ExcludePickPartial < Omit < Indicator < D > , 'result' > , 'name' | 'calc' >
@@ -284,204 +296,103 @@ export function eachFigures<D> (
284296 } )
285297}
286298
287- export default abstract class IndicatorImp < D = any > implements Indicator < D > {
288- name : string
289- shortName : string
290- precision : number
291- calcParams : any [ ]
292- shouldOhlc : boolean
293- shouldFormatBigNumber : boolean
294- visible : boolean
295- zLevel : number
296- extendData : any
297- series : IndicatorSeries
298- figures : Array < IndicatorFigure < D > >
299- minValue : Nullable < number >
300- maxValue : Nullable < number >
301- styles : Nullable < Partial < IndicatorStyle > >
302- regenerateFigures : Nullable < IndicatorRegenerateFiguresCallback < D > >
303- createTooltipDataSource : Nullable < IndicatorCreateTooltipDataSourceCallback >
304- draw : Nullable < IndicatorDrawCallback < D > >
305-
306- result : D [ ] = [ ]
307-
308- private _precisionFlag : boolean = false
309-
310- constructor ( indicator : IndicatorTemplate ) {
311- const {
312- name, shortName, series, calcParams, figures, precision,
313- shouldOhlc, shouldFormatBigNumber, visible, zLevel,
314- minValue, maxValue, styles, extendData,
315- regenerateFigures, createTooltipDataSource, draw
316- } = indicator
317- this . name = name
318- this . shortName = shortName ?? name
319- this . series = series ?? IndicatorSeries . Normal
320- this . precision = precision ?? 4
321- this . calcParams = calcParams ?? [ ]
322- this . figures = figures ?? [ ]
323- this . shouldOhlc = shouldOhlc ?? false
324- this . shouldFormatBigNumber = shouldFormatBigNumber ?? false
325- this . visible = visible ?? true
326- this . zLevel = zLevel ?? 0
327- this . minValue = minValue ?? null
328- this . maxValue = maxValue ?? null
329- this . styles = clone ( styles ?? { } )
330- this . extendData = extendData
331- this . regenerateFigures = regenerateFigures ?? null
332- this . createTooltipDataSource = createTooltipDataSource ?? null
333- this . draw = draw ?? null
334- }
335-
336- setShortName ( shortName : string ) : boolean {
337- if ( this . shortName !== shortName ) {
338- this . shortName = shortName
339- return true
340- }
341- return false
342- }
343-
344- setSeries ( series : IndicatorSeries ) : boolean {
345- if ( this . series !== series ) {
346- this . series = series
347- return true
348- }
349- return false
350- }
351-
352- setPrecision ( precision : number , flag ?: boolean ) : boolean {
353- const f = flag ?? false
354- const optimalPrecision = Math . floor ( precision )
355- if ( optimalPrecision !== this . precision && precision >= 0 && ( ! f || ( f && ! this . _precisionFlag ) ) ) {
356- this . precision = optimalPrecision
357- if ( ! f ) {
358- this . _precisionFlag = true
359- }
360- return true
361- }
362- return false
363- }
364-
365- setCalcParams ( params : any [ ] ) : boolean {
366- this . calcParams = params
367- this . figures = this . regenerateFigures ?.( params ) ?? this . figures
368- return true
299+ export default class IndicatorImp < D = any > {
300+ private _prevIndicator : Indicator < D >
301+ private readonly _indicator : Indicator < D > = {
302+ name : '' ,
303+ shortName : '' ,
304+ precision : 4 ,
305+ calcParams : [ ] ,
306+ shouldOhlc : false ,
307+ shouldFormatBigNumber : false ,
308+ visible : true ,
309+ zLevel : 0 ,
310+ extendData : null ,
311+ series : IndicatorSeries . Normal ,
312+ figures : [ ] ,
313+ minValue : null ,
314+ maxValue : null ,
315+ styles : { } ,
316+ regenerateFigures : null ,
317+ createTooltipDataSource : null ,
318+ shouldUpdate : ( prev , current ) => {
319+ const calc = JSON . stringify ( prev . calcParams ) !== JSON . stringify ( current . calcParams ) ||
320+ prev . figures !== current . figures ||
321+ prev . calc !== current . calc
322+ const draw = calc ||
323+ prev . shortName !== current . shortName ||
324+ prev . series !== current . series ||
325+ prev . minValue !== current . minValue ||
326+ prev . maxValue !== current . maxValue ||
327+ prev . precision !== current . precision ||
328+ prev . shouldOhlc !== current . shouldOhlc ||
329+ prev . shouldFormatBigNumber !== current . shouldFormatBigNumber ||
330+ prev . visible !== current . visible ||
331+ prev . zLevel !== current . zLevel ||
332+ prev . extendData !== current . extendData ||
333+ prev . regenerateFigures !== current . regenerateFigures ||
334+ prev . createTooltipDataSource !== current . createTooltipDataSource ||
335+ prev . draw !== current . draw
336+
337+ return { calc, draw }
338+ } ,
339+ calc : ( ) => [ ] ,
340+ draw : null ,
341+ result : [ ]
369342 }
370343
371- setShouldOhlc ( shouldOhlc : boolean ) : boolean {
372- if ( this . shouldOhlc !== shouldOhlc ) {
373- this . shouldOhlc = shouldOhlc
374- return true
375- }
376- return false
377- }
344+ private _lockSeriesPrecision : boolean = false
378345
379- setShouldFormatBigNumber ( shouldFormatBigNumber : boolean ) : boolean {
380- if ( this . shouldFormatBigNumber !== shouldFormatBigNumber ) {
381- this . shouldFormatBigNumber = shouldFormatBigNumber
382- return true
346+ constructor ( indicator : IndicatorTemplate < D > ) {
347+ this . override ( indicator )
348+ this . _indicator . shortName ??= this . _indicator . name
349+ if ( isArray ( indicator . figures ) ) {
350+ this . _indicator . figures = indicator . figures
383351 }
384- return false
385352 }
386353
387- setVisible ( visible : boolean ) : boolean {
388- if ( this . visible !== visible ) {
389- this . visible = visible
390- return true
391- }
392- return false
354+ getIndicator ( ) : Indicator < D > {
355+ return this . _indicator
393356 }
394357
395- setZLevel ( zLevel : number ) : boolean {
396- if ( this . zLevel !== zLevel ) {
397- this . zLevel = zLevel
398- return true
358+ override ( indicator : IndicatorCreate < D > ) : void {
359+ this . _prevIndicator = clone ( this . _indicator )
360+ merge ( this . _indicator , indicator )
361+ if ( isNumber ( indicator . precision ) ) {
362+ this . _lockSeriesPrecision = true
399363 }
400- return false
401364 }
402365
403- setStyles ( styles : Partial < IndicatorStyle > ) : boolean {
404- merge ( this . styles , styles )
405- return true
406- }
407-
408- setExtendData ( extendData : any ) : boolean {
409- if ( this . extendData !== extendData ) {
410- this . extendData = extendData
411- return true
366+ setSeriesPrecision ( precision : number ) : void {
367+ if ( ! this . _lockSeriesPrecision ) {
368+ this . _indicator . precision = precision
412369 }
413- return false
414370 }
415371
416- setFigures ( figures : IndicatorFigure [ ] ) : boolean {
417- if ( this . figures !== figures ) {
418- this . figures = figures
419- return true
372+ shouldUpdate ( ) : ( { calc : boolean , draw : boolean , sort : boolean } ) {
373+ const sort = this . _prevIndicator . zLevel !== this . _indicator . zLevel
374+ const result = this . _indicator . shouldUpdate ( this . _prevIndicator , this . _indicator )
375+ if ( isBoolean ( result ) ) {
376+ return { calc : result , draw : result , sort }
420377 }
421- return false
378+ return { ... result , sort }
422379 }
423380
424- setMinValue ( value : Nullable < number > ) : boolean {
425- if ( this . minValue !== value ) {
426- this . minValue = value
427- return true
428- }
429- return false
430- }
431-
432- setMaxValue ( value : Nullable < number > ) : boolean {
433- if ( this . maxValue !== value ) {
434- this . maxValue = value
435- return true
436- }
437- return false
438- }
439-
440- setRegenerateFigures ( callback : Nullable < IndicatorRegenerateFiguresCallback > ) : boolean {
441- if ( this . regenerateFigures !== callback ) {
442- this . regenerateFigures = callback
443- return true
444- }
445- return false
446- }
447-
448- setCreateTooltipDataSource ( callback : Nullable < IndicatorCreateTooltipDataSourceCallback > ) : boolean {
449- if ( this . createTooltipDataSource !== callback ) {
450- this . createTooltipDataSource = callback
451- return true
452- }
453- return false
454- }
455-
456- setDraw ( callback : Nullable < IndicatorDrawCallback > ) : boolean {
457- if ( this . draw !== callback ) {
458- this . draw = callback
459- return true
460- }
461- return false
462- }
463-
464- async calcIndicator ( dataList : KLineData [ ] ) : Promise < boolean > {
381+ async calc ( dataList : KLineData [ ] ) : Promise < boolean > {
465382 try {
466- const result = await this . calc ( dataList , this )
467- this . result = result
383+ const result = await this . _indicator . calc ( dataList , this . _indicator )
384+ this . _indicator . result = result
468385 return true
469386 } catch ( e ) {
470387 return false
471388 }
472389 }
473390
474- abstract calc ( dataList : KLineData [ ] , indicator : Indicator < D > ) : D [ ] | Promise < D [ ] >
475-
476- static extend < D > ( template : IndicatorTemplate ) : IndicatorConstructor < D > {
391+ static extend < D > ( template : IndicatorTemplate < D > ) : IndicatorConstructor < D > {
477392 class Custom extends IndicatorImp < D > {
478393 constructor ( ) {
479394 super ( template )
480395 }
481-
482- calc ( dataList : KLineData [ ] , indicator : Indicator < D > ) : D [ ] | Promise < D [ ] > {
483- return template . calc ( dataList , indicator )
484- }
485396 }
486397 return Custom
487398 }
0 commit comments