velo-plot 1.15.0 → 2.0.0
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/{ChartCore-BimVvUEg.js → ChartCore-BhQ4j7f5.js} +2213 -1489
- package/dist/ChartCore-BhQ4j7f5.js.map +1 -0
- package/dist/SciPlot-GJvw7GJo.js +463 -0
- package/dist/SciPlot-GJvw7GJo.js.map +1 -0
- package/dist/assets/downsample.worker-C70QJ04y.js +2 -0
- package/dist/assets/downsample.worker-C70QJ04y.js.map +1 -0
- package/dist/assets/indicator.worker-bv0zC4EX.js +2 -0
- package/dist/assets/indicator.worker-bv0zC4EX.js.map +1 -0
- package/dist/axisFormat-SPX-CD5s.js +200 -0
- package/dist/axisFormat-SPX-CD5s.js.map +1 -0
- package/dist/core/InteractionManager.d.ts +1 -0
- package/dist/core/OverlayRenderer.d.ts +13 -0
- package/dist/core/chart/ChartAlerts.d.ts +42 -0
- package/dist/core/chart/ChartCore.d.ts +24 -1
- package/dist/core/chart/ChartRenderLoop.d.ts +9 -2
- package/dist/core/chart/ChartRenderer.d.ts +8 -2
- package/dist/core/chart/candlestickMarkers.d.ts +23 -0
- package/dist/core/chart/heikinAshi.d.ts +10 -0
- package/dist/core/chart/positionLines.d.ts +12 -0
- package/dist/core/chart/series/types.d.ts +2 -2
- package/dist/core/chart/types.d.ts +9 -0
- package/dist/core/format/axisFormat.d.ts +2 -1
- package/dist/core/indicator/addIndicator.d.ts +36 -0
- package/dist/core/indicator/index.d.ts +2 -0
- package/dist/core/indicator/indicatorPresets.d.ts +45 -0
- package/dist/core/series/Series.d.ts +3 -0
- package/dist/core/stacked/types.d.ts +8 -0
- package/dist/core/time/TimeScale.d.ts +31 -0
- package/dist/core/time/applyTimeScale.d.ts +10 -0
- package/dist/createStackedChart-DJSmqerD.js +706 -0
- package/dist/createStackedChart-DJSmqerD.js.map +1 -0
- package/dist/gpu/adapter/gpuRenderer.d.ts +21 -0
- package/dist/gpu/backends/webgpu/WebGPUBackend.d.ts +2 -1
- package/dist/gpuRenderer-BpaMYz-k.js +1848 -0
- package/dist/gpuRenderer-BpaMYz-k.js.map +1 -0
- package/dist/{index-DjeWClO9.js → index-CWipqOLP.js} +2 -2
- package/dist/{index-DjeWClO9.js.map → index-CWipqOLP.js.map} +1 -1
- package/dist/index-D7dTq6VB.js +503 -0
- package/dist/index-D7dTq6VB.js.map +1 -0
- package/dist/{index-Ce2JgkH_.js → index-DoYxf1cV.js} +86 -43
- package/dist/{index-Ce2JgkH_.js.map → index-DoYxf1cV.js.map} +1 -1
- package/dist/{index.core-C_-CFftD.js → index.core-fpZ1dYN0.js} +3 -3
- package/dist/{index.core-C_-CFftD.js.map → index.core-fpZ1dYN0.js.map} +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/indicators--eJGmVox.js +302 -0
- package/dist/indicators--eJGmVox.js.map +1 -0
- package/dist/mockDatafeed-Cdg5hKEo.js +511 -0
- package/dist/mockDatafeed-Cdg5hKEo.js.map +1 -0
- package/dist/plugins/analysis.js +530 -807
- package/dist/plugins/analysis.js.map +1 -1
- package/dist/plugins/caching.js +26 -21
- package/dist/plugins/caching.js.map +1 -1
- package/dist/plugins/drawing-tools/index.d.ts +29 -0
- package/dist/plugins/drawing-tools/measure.d.ts +21 -0
- package/dist/plugins/drawing-tools/snapToCandle.d.ts +21 -0
- package/dist/plugins/gpu.js +202 -1895
- package/dist/plugins/gpu.js.map +1 -1
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/keyboard/index.d.ts +1 -7
- package/dist/plugins/keyboard.js +1 -1
- package/dist/plugins/lazy-load/types.d.ts +7 -0
- package/dist/plugins/lazy-load.js +131 -108
- package/dist/plugins/lazy-load.js.map +1 -1
- package/dist/plugins/replay/index.d.ts +19 -0
- package/dist/plugins/tools.js +1 -1
- package/dist/plugins/virtualization/types.d.ts +12 -0
- package/dist/plugins/virtualization.js +1 -1
- package/dist/pool-15HMCNv8.js +88 -0
- package/dist/pool-15HMCNv8.js.map +1 -0
- package/dist/react.js +5 -5
- package/dist/renderer/CandlestickRenderer.d.ts +1 -1
- package/dist/renderer/ChartSeriesRenderer.d.ts +6 -0
- package/dist/renderer/GpuChartRenderer.d.ts +23 -0
- package/dist/renderer/index.d.ts +3 -0
- package/dist/renderer/spike/WebGLGridSpike.d.ts +40 -0
- package/dist/testing/baselines/v1.15.0.json.d.ts +51 -0
- package/dist/testing/gridSpikeBenchmark.d.ts +49 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/rendererBenchmark.d.ts +13 -0
- package/dist/testing/stage1BrowserBench.d.ts +42 -0
- package/dist/trading/datafeed.d.ts +48 -0
- package/dist/trading/index.d.ts +29 -0
- package/dist/trading/mockDatafeed.d.ts +9 -0
- package/dist/trading/ohlcvGenerator.d.ts +25 -0
- package/dist/trading.d.ts +1 -0
- package/dist/trading.js +95 -0
- package/dist/trading.js.map +1 -0
- package/dist/types.d.ts +22 -2
- package/dist/velo-plot.full.js +1088 -776
- package/dist/velo-plot.full.js.map +1 -1
- package/dist/velo-plot.js +15 -15
- package/dist/workers/downsample.d.ts +38 -0
- package/dist/workers/downsampleAsync.d.ts +6 -0
- package/dist/workers/indicator.worker.d.ts +32 -0
- package/dist/workers/indicatorsAsync.d.ts +26 -0
- package/dist/workers/pool.d.ts +36 -0
- package/package.json +23 -1
- package/dist/ChartCore-BimVvUEg.js.map +0 -1
- package/dist/axisFormat-B7o_uIEA.js +0 -127
- package/dist/axisFormat-B7o_uIEA.js.map +0 -1
- package/dist/createStackedChart-CjsKcOvX.js +0 -1088
- package/dist/createStackedChart-CjsKcOvX.js.map +0 -1
- package/dist/index-ChgIdk3N.js +0 -229
- package/dist/index-ChgIdk3N.js.map +0 -1
package/dist/plugins/caching.js
CHANGED
|
@@ -21,8 +21,8 @@ const x = {
|
|
|
21
21
|
},
|
|
22
22
|
debug: !1
|
|
23
23
|
};
|
|
24
|
-
function k(
|
|
25
|
-
const s = { ...$, ...
|
|
24
|
+
function k(p = {}) {
|
|
25
|
+
const s = { ...$, ...p };
|
|
26
26
|
let f = null;
|
|
27
27
|
const o = /* @__PURE__ */ new Map(), r = {
|
|
28
28
|
hits: 0,
|
|
@@ -38,7 +38,7 @@ function k(y = {}) {
|
|
|
38
38
|
0
|
|
39
39
|
) : 100;
|
|
40
40
|
}
|
|
41
|
-
function
|
|
41
|
+
function z(e) {
|
|
42
42
|
if (o.size === 0) return;
|
|
43
43
|
const t = Array.from(o.entries());
|
|
44
44
|
s.strategy === "lru" ? t.sort((a, l) => a[1].lastAccess - l[1].lastAccess) : s.strategy === "lfu" && t.sort((a, l) => a[1].hits - l[1].hits);
|
|
@@ -60,7 +60,7 @@ function k(y = {}) {
|
|
|
60
60
|
o.delete(i);
|
|
61
61
|
return s.debug && t.length > 0 && console.log(`[Cache] Pruned ${t.length} expired entries`), t.length;
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function b(e) {
|
|
64
64
|
if (!s.enabled) return;
|
|
65
65
|
const t = o.get(e);
|
|
66
66
|
if (!t) {
|
|
@@ -73,12 +73,12 @@ function k(y = {}) {
|
|
|
73
73
|
}
|
|
74
74
|
return t.lastAccess = Date.now(), t.hits++, r.hits++, s.debug && console.log(`[Cache] HIT: ${e}`), t.value;
|
|
75
75
|
}
|
|
76
|
-
function
|
|
76
|
+
function v(e, t, i = {}) {
|
|
77
77
|
if (!s.enabled) return;
|
|
78
78
|
const n = i.size ?? u(t);
|
|
79
79
|
if (c + n > s.maxSize) {
|
|
80
|
-
const
|
|
81
|
-
|
|
80
|
+
const A = c + n - s.maxSize;
|
|
81
|
+
z(A);
|
|
82
82
|
}
|
|
83
83
|
if (n > s.maxSize) {
|
|
84
84
|
console.warn(`[Cache] Value too large to cache: ${e} (${n} bytes)`);
|
|
@@ -97,7 +97,7 @@ function k(y = {}) {
|
|
|
97
97
|
};
|
|
98
98
|
o.set(e, l), c += n, s.debug && console.log(`[Cache] SET: ${e} (${n} bytes)`);
|
|
99
99
|
}
|
|
100
|
-
function
|
|
100
|
+
function T(e) {
|
|
101
101
|
return o.has(e);
|
|
102
102
|
}
|
|
103
103
|
function I(e) {
|
|
@@ -112,7 +112,7 @@ function k(y = {}) {
|
|
|
112
112
|
timestamp: Date.now()
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
-
function
|
|
115
|
+
function y(e) {
|
|
116
116
|
const t = [];
|
|
117
117
|
for (const [i, n] of o.entries())
|
|
118
118
|
n.tags && n.tags.some((a) => e.includes(a)) && (t.push(i), c -= n.size);
|
|
@@ -124,7 +124,7 @@ function k(y = {}) {
|
|
|
124
124
|
timestamp: Date.now()
|
|
125
125
|
}), t.length;
|
|
126
126
|
}
|
|
127
|
-
function
|
|
127
|
+
function C() {
|
|
128
128
|
const e = r.hits + r.misses;
|
|
129
129
|
return {
|
|
130
130
|
hits: r.hits,
|
|
@@ -136,26 +136,26 @@ function k(y = {}) {
|
|
|
136
136
|
evictions: r.evictions
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
|
-
function
|
|
139
|
+
function D() {
|
|
140
140
|
r.hits = 0, r.misses = 0, r.evictions = 0;
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function S() {
|
|
143
143
|
return Array.from(o.keys());
|
|
144
144
|
}
|
|
145
|
-
function
|
|
145
|
+
function w() {
|
|
146
146
|
return o.size;
|
|
147
147
|
}
|
|
148
148
|
const m = {
|
|
149
|
-
get:
|
|
150
|
-
set:
|
|
151
|
-
has:
|
|
149
|
+
get: b,
|
|
150
|
+
set: v,
|
|
151
|
+
has: T,
|
|
152
152
|
delete: I,
|
|
153
153
|
clear: h,
|
|
154
|
-
invalidateByTags:
|
|
155
|
-
getStats:
|
|
156
|
-
resetStats:
|
|
157
|
-
keys:
|
|
158
|
-
size:
|
|
154
|
+
invalidateByTags: y,
|
|
155
|
+
getStats: C,
|
|
156
|
+
resetStats: D,
|
|
157
|
+
keys: S,
|
|
158
|
+
size: w,
|
|
159
159
|
prune: g,
|
|
160
160
|
updateConfig(e) {
|
|
161
161
|
Object.assign(s, e);
|
|
@@ -169,6 +169,11 @@ function k(y = {}) {
|
|
|
169
169
|
g();
|
|
170
170
|
}, 6e4);
|
|
171
171
|
},
|
|
172
|
+
onDataUpdate(e) {
|
|
173
|
+
if (!s.autoInvalidate) return;
|
|
174
|
+
const t = [];
|
|
175
|
+
s.cacheTypes.transforms && t.push("transform"), s.cacheTypes.analysis && t.push("analysis"), s.cacheTypes.bounds && t.push("bounds"), t.length > 0 && y(t);
|
|
176
|
+
},
|
|
172
177
|
onDestroy(e) {
|
|
173
178
|
d !== null && clearInterval(d), h(), delete e.chart.caching, f = null;
|
|
174
179
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caching.js","sources":["../../src/plugins/caching/index.ts"],"sourcesContent":["/**\n * @fileoverview Advanced caching plugin for performance optimization\n * @module plugins/caching\n */\n\nimport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-caching',\n version: '1.0.0',\n description: 'Advanced caching system for performance optimization',\n provides: ['caching', 'performance'],\n tags: ['optimization', 'cache', 'memory'],\n};\n\nconst DEFAULT_CONFIG: Required<PluginCachingConfig> = {\n enabled: true,\n maxSize: 50 * 1024 * 1024, // 50MB\n strategy: 'lru',\n defaultTTL: undefined as any,\n autoInvalidate: true,\n cacheTypes: {\n transforms: true,\n analysis: true,\n frames: false,\n bounds: true,\n },\n onInvalidate: () => {},\n debug: false,\n};\n\nexport function PluginCaching(\n userConfig: Partial<PluginCachingConfig> = {}\n): ChartPlugin<PluginCachingConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n\n // Cache storage\n const cache = new Map<string, CacheEntry>();\n \n // Statistics\n const stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n \n let currentSize = 0;\n\n /**\n * Estimate size of value in bytes\n */\n function estimateSize(value: any): number {\n if (value === null || value === undefined) return 0;\n \n const type = typeof value;\n \n if (type === 'boolean') return 4;\n if (type === 'number') return 8;\n if (type === 'string') return value.length * 2;\n \n if (value instanceof Float32Array || value instanceof Float64Array) {\n return value.byteLength;\n }\n \n if (Array.isArray(value)) {\n return value.reduce((sum, item) => sum + estimateSize(item), 0);\n }\n \n if (type === 'object') {\n return Object.keys(value).reduce(\n (sum, key) => sum + key.length * 2 + estimateSize(value[key]),\n 0\n );\n }\n \n return 100; // Default estimate\n }\n\n /**\n * Evict entries based on strategy\n */\n function evict(requiredSpace: number): void {\n if (cache.size === 0) return;\n\n const entries = Array.from(cache.entries());\n \n // Sort based on strategy\n if (config.strategy === 'lru') {\n // Least recently used\n entries.sort((a, b) => a[1].lastAccess - b[1].lastAccess);\n } else if (config.strategy === 'lfu') {\n // Least frequently used\n entries.sort((a, b) => a[1].hits - b[1].hits);\n }\n // FIFO is already in insertion order (Map preserves order)\n \n let freedSpace = 0;\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of entries) {\n if (freedSpace >= requiredSpace) break;\n \n keysToDelete.push(key);\n freedSpace += entry.size;\n currentSize -= entry.size;\n stats.evictions++;\n }\n \n // Delete entries\n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Evicted ${keysToDelete.length} entries, freed ${freedSpace} bytes`);\n }\n }\n\n /**\n * Prune expired entries\n */\n function pruneExpired(): number {\n const now = Date.now();\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.ttl && now - entry.timestamp > entry.ttl) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Pruned ${keysToDelete.length} expired entries`);\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | undefined {\n if (!config.enabled) return undefined;\n \n const entry = cache.get(key);\n \n if (!entry) {\n stats.misses++;\n return undefined;\n }\n \n // Check TTL\n if (entry.ttl) {\n const age = Date.now() - entry.timestamp;\n if (age > entry.ttl) {\n cache.delete(key);\n currentSize -= entry.size;\n stats.misses++;\n return undefined;\n }\n }\n \n // Update access metadata\n entry.lastAccess = Date.now();\n entry.hits++;\n stats.hits++;\n \n if (config.debug) {\n console.log(`[Cache] HIT: ${key}`);\n }\n \n return entry.value as T;\n }\n\n /**\n * Set value in cache\n */\n function set<T>(\n key: string,\n value: T,\n options: { ttl?: number; tags?: string[]; size?: number } = {}\n ): void {\n if (!config.enabled) return;\n \n // Estimate size\n const size = options.size ?? estimateSize(value);\n \n // Check if we need to evict\n if (currentSize + size > config.maxSize) {\n const requiredSpace = currentSize + size - config.maxSize;\n evict(requiredSpace);\n }\n \n // Still too large after eviction?\n if (size > config.maxSize) {\n console.warn(`[Cache] Value too large to cache: ${key} (${size} bytes)`);\n return;\n }\n \n // Remove old entry if exists\n const oldEntry = cache.get(key);\n if (oldEntry) {\n currentSize -= oldEntry.size;\n }\n \n // Create entry\n const entry: CacheEntry<T> = {\n value,\n timestamp: Date.now(),\n lastAccess: Date.now(),\n hits: 0,\n size,\n ttl: options.ttl ?? config.defaultTTL,\n tags: options.tags,\n };\n \n cache.set(key, entry);\n currentSize += size;\n \n if (config.debug) {\n console.log(`[Cache] SET: ${key} (${size} bytes)`);\n }\n }\n\n /**\n * Check if key exists\n */\n function has(key: string): boolean {\n return cache.has(key);\n }\n\n /**\n * Delete specific key\n */\n function deleteKey(key: string): boolean {\n const entry = cache.get(key);\n if (entry) {\n currentSize -= entry.size;\n return cache.delete(key);\n }\n return false;\n }\n\n /**\n * Clear all cache\n */\n function clear(): void {\n const count = cache.size;\n cache.clear();\n currentSize = 0;\n \n if (config.debug) {\n console.log(`[Cache] Cleared ${count} entries`);\n }\n \n if (config.onInvalidate) {\n config.onInvalidate({\n keys: [],\n reason: 'manual',\n timestamp: Date.now(),\n });\n }\n }\n\n /**\n * Invalidate by tags\n */\n function invalidateByTags(tags: string[]): number {\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.tags && entry.tags.some(tag => tags.includes(tag))) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Invalidated ${keysToDelete.length} entries by tags:`, tags);\n }\n \n if (config.onInvalidate && keysToDelete.length > 0) {\n config.onInvalidate({\n keys: keysToDelete,\n reason: 'tag',\n timestamp: Date.now(),\n });\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get cache statistics\n */\n function getStats(): CacheStats {\n const total = stats.hits + stats.misses;\n \n return {\n hits: stats.hits,\n misses: stats.misses,\n hitRatio: total > 0 ? stats.hits / total : 0,\n currentSize,\n maxSize: config.maxSize,\n entryCount: cache.size,\n evictions: stats.evictions,\n };\n }\n\n /**\n * Reset statistics\n */\n function resetStats(): void {\n stats.hits = 0;\n stats.misses = 0;\n stats.evictions = 0;\n }\n\n /**\n * Get all keys\n */\n function keys(): string[] {\n return Array.from(cache.keys());\n }\n\n /**\n * Get cache size\n */\n function size(): number {\n return cache.size;\n }\n\n // API implementation\n const api: CachingAPI & Record<string, unknown> = {\n get,\n set,\n has,\n delete: deleteKey,\n clear,\n invalidateByTags,\n getStats,\n resetStats,\n keys,\n size,\n prune: pruneExpired,\n updateConfig(newConfig: Partial<PluginCachingConfig>) {\n Object.assign(config, newConfig);\n },\n };\n\n // Periodic cleanup\n let cleanupInterval: number | null = null;\n\n return {\n manifest,\n\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n\n // Attach to chart API\n (ctx.chart as any).caching = api;\n\n // Setup periodic cleanup (every 60 seconds)\n cleanupInterval = window.setInterval(() => {\n pruneExpired();\n }, 60000);\n\n // TODO: Auto-invalidate on data changes if enabled\n // Requires 'dataUpdate' event to be added to ChartEventMap\n // if (config.autoInvalidate) {\n // ctx.chart.on?.('dataUpdate', () => {\n // if (config.cacheTypes.transforms) invalidateByTags(['transform']);\n // if (config.cacheTypes.analysis) invalidateByTags(['analysis']);\n // if (config.cacheTypes.bounds) invalidateByTags(['bounds']);\n // });\n // }\n },\n\n onDestroy(pluginCtx: PluginContext) {\n // Clear cleanup interval\n if (cleanupInterval !== null) {\n clearInterval(cleanupInterval);\n }\n\n // Clear cache\n clear();\n\n // Remove from chart API\n delete (pluginCtx.chart as any).caching;\n\n ctx = null;\n },\n\n api,\n };\n}\n\nexport default PluginCaching;\n\n// Type exports\nexport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n CacheStrategy,\n CacheInvalidationEvent,\n} from './types';\n"],"names":["manifest","DEFAULT_CONFIG","PluginCaching","userConfig","config","ctx","cache","stats","currentSize","estimateSize","value","type","sum","item","key","evict","requiredSpace","entries","b","freedSpace","keysToDelete","entry","pruneExpired","now","get","set","options","size","oldEntry","has","deleteKey","clear","count","invalidateByTags","tags","tag","getStats","total","resetStats","keys","api","newConfig","cleanupInterval","pluginCtx"],"mappings":"AAiBA,MAAMA,IAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,WAAW,aAAa;AAAA,EACnC,MAAM,CAAC,gBAAgB,SAAS,QAAQ;AAC1C,GAEMC,IAAgD;AAAA,EACpD,SAAS;AAAA,EACT,SAAS,KAAK,OAAO;AAAA;AAAA,EACrB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAAA,EAEV,cAAc,MAAM;AAAA,EAAC;AAAA,EACrB,OAAO;AACT;AAEO,SAASC,EACdC,IAA2C,IACT;AAClC,QAAMC,IAAS,EAAE,GAAGH,GAAgB,GAAGE,EAAA;AACvC,MAAIE,IAA4B;AAGhC,QAAMC,wBAAY,IAAA,GAGZC,IAAQ;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA;AAGb,MAAIC,IAAc;AAKlB,WAASC,EAAaC,GAAoB;AACxC,QAAIA,KAAU,KAA6B,QAAO;AAElD,UAAMC,IAAO,OAAOD;AAEpB,WAAIC,MAAS,YAAkB,IAC3BA,MAAS,WAAiB,IAC1BA,MAAS,WAAiBD,EAAM,SAAS,IAEzCA,aAAiB,gBAAgBA,aAAiB,eAC7CA,EAAM,aAGX,MAAM,QAAQA,CAAK,IACdA,EAAM,OAAO,CAACE,GAAKC,MAASD,IAAMH,EAAaI,CAAI,GAAG,CAAC,IAG5DF,MAAS,WACJ,OAAO,KAAKD,CAAK,EAAE;AAAA,MACxB,CAACE,GAAKE,MAAQF,IAAME,EAAI,SAAS,IAAIL,EAAaC,EAAMI,CAAG,CAAC;AAAA,MAC5D;AAAA,IAAA,IAIG;AAAA,EACT;AAKA,WAASC,EAAMC,GAA6B;AAC1C,QAAIV,EAAM,SAAS,EAAG;AAEtB,UAAMW,IAAU,MAAM,KAAKX,EAAM,SAAS;AAG1C,IAAIF,EAAO,aAAa,QAEtBa,EAAQ,KAAK,CAAC,GAAGC,MAAM,EAAE,CAAC,EAAE,aAAaA,EAAE,CAAC,EAAE,UAAU,IAC/Cd,EAAO,aAAa,SAE7Ba,EAAQ,KAAK,CAAC,GAAGC,MAAM,EAAE,CAAC,EAAE,OAAOA,EAAE,CAAC,EAAE,IAAI;AAI9C,QAAIC,IAAa;AACjB,UAAMC,IAAyB,CAAA;AAE/B,eAAW,CAACN,GAAKO,CAAK,KAAKJ,GAAS;AAClC,UAAIE,KAAcH,EAAe;AAEjC,MAAAI,EAAa,KAAKN,CAAG,GACrBK,KAAcE,EAAM,MACpBb,KAAea,EAAM,MACrBd,EAAM;AAAA,IACR;AAGA,eAAWO,KAAOM;AAChB,MAAAd,EAAM,OAAOQ,CAAG;AAGlB,IAAIV,EAAO,SAASgB,EAAa,SAAS,KACxC,QAAQ,IAAI,mBAAmBA,EAAa,MAAM,mBAAmBD,CAAU,QAAQ;AAAA,EAE3F;AAKA,WAASG,IAAuB;AAC9B,UAAMC,IAAM,KAAK,IAAA,GACXH,IAAyB,CAAA;AAE/B,eAAW,CAACN,GAAKO,CAAK,KAAKf,EAAM;AAC/B,MAAIe,EAAM,OAAOE,IAAMF,EAAM,YAAYA,EAAM,QAC7CD,EAAa,KAAKN,CAAG,GACrBN,KAAea,EAAM;AAIzB,eAAWP,KAAOM;AAChB,MAAAd,EAAM,OAAOQ,CAAG;AAGlB,WAAIV,EAAO,SAASgB,EAAa,SAAS,KACxC,QAAQ,IAAI,kBAAkBA,EAAa,MAAM,kBAAkB,GAG9DA,EAAa;AAAA,EACtB;AAKA,WAASI,EAAOV,GAA4B;AAC1C,QAAI,CAACV,EAAO,QAAS;AAErB,UAAMiB,IAAQf,EAAM,IAAIQ,CAAG;AAE3B,QAAI,CAACO,GAAO;AACV,MAAAd,EAAM;AACN;AAAA,IACF;AAGA,QAAIc,EAAM,OACI,KAAK,IAAA,IAAQA,EAAM,YACrBA,EAAM,KAAK;AACnB,MAAAf,EAAM,OAAOQ,CAAG,GAChBN,KAAea,EAAM,MACrBd,EAAM;AACN;AAAA,IACF;AAIF,WAAAc,EAAM,aAAa,KAAK,IAAA,GACxBA,EAAM,QACNd,EAAM,QAEFH,EAAO,SACT,QAAQ,IAAI,gBAAgBU,CAAG,EAAE,GAG5BO,EAAM;AAAA,EACf;AAKA,WAASI,EACPX,GACAJ,GACAgB,IAA4D,CAAA,GACtD;AACN,QAAI,CAACtB,EAAO,QAAS;AAGrB,UAAMuB,IAAOD,EAAQ,QAAQjB,EAAaC,CAAK;AAG/C,QAAIF,IAAcmB,IAAOvB,EAAO,SAAS;AACvC,YAAMY,IAAgBR,IAAcmB,IAAOvB,EAAO;AAClD,MAAAW,EAAMC,CAAa;AAAA,IACrB;AAGA,QAAIW,IAAOvB,EAAO,SAAS;AACzB,cAAQ,KAAK,qCAAqCU,CAAG,KAAKa,CAAI,SAAS;AACvE;AAAA,IACF;AAGA,UAAMC,IAAWtB,EAAM,IAAIQ,CAAG;AAC9B,IAAIc,MACFpB,KAAeoB,EAAS;AAI1B,UAAMP,IAAuB;AAAA,MAC3B,OAAAX;AAAA,MACA,WAAW,KAAK,IAAA;AAAA,MAChB,YAAY,KAAK,IAAA;AAAA,MACjB,MAAM;AAAA,MACN,MAAAiB;AAAAA,MACA,KAAKD,EAAQ,OAAOtB,EAAO;AAAA,MAC3B,MAAMsB,EAAQ;AAAA,IAAA;AAGhB,IAAApB,EAAM,IAAIQ,GAAKO,CAAK,GACpBb,KAAemB,GAEXvB,EAAO,SACT,QAAQ,IAAI,gBAAgBU,CAAG,KAAKa,CAAI,SAAS;AAAA,EAErD;AAKA,WAASE,EAAIf,GAAsB;AACjC,WAAOR,EAAM,IAAIQ,CAAG;AAAA,EACtB;AAKA,WAASgB,EAAUhB,GAAsB;AACvC,UAAMO,IAAQf,EAAM,IAAIQ,CAAG;AAC3B,WAAIO,KACFb,KAAea,EAAM,MACdf,EAAM,OAAOQ,CAAG,KAElB;AAAA,EACT;AAKA,WAASiB,IAAc;AACrB,UAAMC,IAAQ1B,EAAM;AACpB,IAAAA,EAAM,MAAA,GACNE,IAAc,GAEVJ,EAAO,SACT,QAAQ,IAAI,mBAAmB4B,CAAK,UAAU,GAG5C5B,EAAO,gBACTA,EAAO,aAAa;AAAA,MAClB,MAAM,CAAA;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,KAAK,IAAA;AAAA,IAAI,CACrB;AAAA,EAEL;AAKA,WAAS6B,EAAiBC,GAAwB;AAChD,UAAMd,IAAyB,CAAA;AAE/B,eAAW,CAACN,GAAKO,CAAK,KAAKf,EAAM;AAC/B,MAAIe,EAAM,QAAQA,EAAM,KAAK,KAAK,OAAOa,EAAK,SAASC,CAAG,CAAC,MACzDf,EAAa,KAAKN,CAAG,GACrBN,KAAea,EAAM;AAIzB,eAAWP,KAAOM;AAChB,MAAAd,EAAM,OAAOQ,CAAG;AAGlB,WAAIV,EAAO,SAASgB,EAAa,SAAS,KACxC,QAAQ,IAAI,uBAAuBA,EAAa,MAAM,qBAAqBc,CAAI,GAG7E9B,EAAO,gBAAgBgB,EAAa,SAAS,KAC/ChB,EAAO,aAAa;AAAA,MAClB,MAAMgB;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,KAAK,IAAA;AAAA,IAAI,CACrB,GAGIA,EAAa;AAAA,EACtB;AAKA,WAASgB,IAAuB;AAC9B,UAAMC,IAAQ9B,EAAM,OAAOA,EAAM;AAEjC,WAAO;AAAA,MACL,MAAMA,EAAM;AAAA,MACZ,QAAQA,EAAM;AAAA,MACd,UAAU8B,IAAQ,IAAI9B,EAAM,OAAO8B,IAAQ;AAAA,MAC3C,aAAA7B;AAAA,MACA,SAASJ,EAAO;AAAA,MAChB,YAAYE,EAAM;AAAA,MAClB,WAAWC,EAAM;AAAA,IAAA;AAAA,EAErB;AAKA,WAAS+B,IAAmB;AAC1B,IAAA/B,EAAM,OAAO,GACbA,EAAM,SAAS,GACfA,EAAM,YAAY;AAAA,EACpB;AAKA,WAASgC,IAAiB;AACxB,WAAO,MAAM,KAAKjC,EAAM,KAAA,CAAM;AAAA,EAChC;AAKA,WAASqB,IAAe;AACtB,WAAOrB,EAAM;AAAA,EACf;AAGA,QAAMkC,IAA4C;AAAA,IAChD,KAAAhB;AAAA,IACA,KAAAC;AAAA,IACA,KAAAI;AAAA,IACA,QAAQC;AAAA,IACR,OAAAC;AAAA,IACA,kBAAAE;AAAA,IACA,UAAAG;AAAA,IACA,YAAAE;AAAA,IACA,MAAAC;AAAA,IACA,MAAAZ;AAAA,IACA,OAAOL;AAAA,IACP,aAAamB,GAAyC;AACpD,aAAO,OAAOrC,GAAQqC,CAAS;AAAA,IACjC;AAAA,EAAA;AAIF,MAAIC,IAAiC;AAErC,SAAO;AAAA,IACL,UAAA1C;AAAA,IAEA,OAAO2C,GAA0B;AAC/B,MAAAtC,IAAMsC,GAGLtC,EAAI,MAAc,UAAUmC,GAG7BE,IAAkB,OAAO,YAAY,MAAM;AACzC,QAAApB,EAAA;AAAA,MACF,GAAG,GAAK;AAAA,IAWV;AAAA,IAEA,UAAUqB,GAA0B;AAElC,MAAID,MAAoB,QACtB,cAAcA,CAAe,GAI/BX,EAAA,GAGA,OAAQY,EAAU,MAAc,SAEhCtC,IAAM;AAAA,IACR;AAAA,IAEA,KAAAmC;AAAA,EAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"caching.js","sources":["../../src/plugins/caching/index.ts"],"sourcesContent":["/**\n * @fileoverview Advanced caching plugin for performance optimization\n * @module plugins/caching\n */\n\nimport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-caching',\n version: '1.0.0',\n description: 'Advanced caching system for performance optimization',\n provides: ['caching', 'performance'],\n tags: ['optimization', 'cache', 'memory'],\n};\n\nconst DEFAULT_CONFIG: Required<PluginCachingConfig> = {\n enabled: true,\n maxSize: 50 * 1024 * 1024, // 50MB\n strategy: 'lru',\n defaultTTL: undefined as any,\n autoInvalidate: true,\n cacheTypes: {\n transforms: true,\n analysis: true,\n frames: false,\n bounds: true,\n },\n onInvalidate: () => {},\n debug: false,\n};\n\nexport function PluginCaching(\n userConfig: Partial<PluginCachingConfig> = {}\n): ChartPlugin<PluginCachingConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n\n // Cache storage\n const cache = new Map<string, CacheEntry>();\n \n // Statistics\n const stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n \n let currentSize = 0;\n\n /**\n * Estimate size of value in bytes\n */\n function estimateSize(value: any): number {\n if (value === null || value === undefined) return 0;\n \n const type = typeof value;\n \n if (type === 'boolean') return 4;\n if (type === 'number') return 8;\n if (type === 'string') return value.length * 2;\n \n if (value instanceof Float32Array || value instanceof Float64Array) {\n return value.byteLength;\n }\n \n if (Array.isArray(value)) {\n return value.reduce((sum, item) => sum + estimateSize(item), 0);\n }\n \n if (type === 'object') {\n return Object.keys(value).reduce(\n (sum, key) => sum + key.length * 2 + estimateSize(value[key]),\n 0\n );\n }\n \n return 100; // Default estimate\n }\n\n /**\n * Evict entries based on strategy\n */\n function evict(requiredSpace: number): void {\n if (cache.size === 0) return;\n\n const entries = Array.from(cache.entries());\n \n // Sort based on strategy\n if (config.strategy === 'lru') {\n // Least recently used\n entries.sort((a, b) => a[1].lastAccess - b[1].lastAccess);\n } else if (config.strategy === 'lfu') {\n // Least frequently used\n entries.sort((a, b) => a[1].hits - b[1].hits);\n }\n // FIFO is already in insertion order (Map preserves order)\n \n let freedSpace = 0;\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of entries) {\n if (freedSpace >= requiredSpace) break;\n \n keysToDelete.push(key);\n freedSpace += entry.size;\n currentSize -= entry.size;\n stats.evictions++;\n }\n \n // Delete entries\n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Evicted ${keysToDelete.length} entries, freed ${freedSpace} bytes`);\n }\n }\n\n /**\n * Prune expired entries\n */\n function pruneExpired(): number {\n const now = Date.now();\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.ttl && now - entry.timestamp > entry.ttl) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Pruned ${keysToDelete.length} expired entries`);\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | undefined {\n if (!config.enabled) return undefined;\n \n const entry = cache.get(key);\n \n if (!entry) {\n stats.misses++;\n return undefined;\n }\n \n // Check TTL\n if (entry.ttl) {\n const age = Date.now() - entry.timestamp;\n if (age > entry.ttl) {\n cache.delete(key);\n currentSize -= entry.size;\n stats.misses++;\n return undefined;\n }\n }\n \n // Update access metadata\n entry.lastAccess = Date.now();\n entry.hits++;\n stats.hits++;\n \n if (config.debug) {\n console.log(`[Cache] HIT: ${key}`);\n }\n \n return entry.value as T;\n }\n\n /**\n * Set value in cache\n */\n function set<T>(\n key: string,\n value: T,\n options: { ttl?: number; tags?: string[]; size?: number } = {}\n ): void {\n if (!config.enabled) return;\n \n // Estimate size\n const size = options.size ?? estimateSize(value);\n \n // Check if we need to evict\n if (currentSize + size > config.maxSize) {\n const requiredSpace = currentSize + size - config.maxSize;\n evict(requiredSpace);\n }\n \n // Still too large after eviction?\n if (size > config.maxSize) {\n console.warn(`[Cache] Value too large to cache: ${key} (${size} bytes)`);\n return;\n }\n \n // Remove old entry if exists\n const oldEntry = cache.get(key);\n if (oldEntry) {\n currentSize -= oldEntry.size;\n }\n \n // Create entry\n const entry: CacheEntry<T> = {\n value,\n timestamp: Date.now(),\n lastAccess: Date.now(),\n hits: 0,\n size,\n ttl: options.ttl ?? config.defaultTTL,\n tags: options.tags,\n };\n \n cache.set(key, entry);\n currentSize += size;\n \n if (config.debug) {\n console.log(`[Cache] SET: ${key} (${size} bytes)`);\n }\n }\n\n /**\n * Check if key exists\n */\n function has(key: string): boolean {\n return cache.has(key);\n }\n\n /**\n * Delete specific key\n */\n function deleteKey(key: string): boolean {\n const entry = cache.get(key);\n if (entry) {\n currentSize -= entry.size;\n return cache.delete(key);\n }\n return false;\n }\n\n /**\n * Clear all cache\n */\n function clear(): void {\n const count = cache.size;\n cache.clear();\n currentSize = 0;\n \n if (config.debug) {\n console.log(`[Cache] Cleared ${count} entries`);\n }\n \n if (config.onInvalidate) {\n config.onInvalidate({\n keys: [],\n reason: 'manual',\n timestamp: Date.now(),\n });\n }\n }\n\n /**\n * Invalidate by tags\n */\n function invalidateByTags(tags: string[]): number {\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.tags && entry.tags.some(tag => tags.includes(tag))) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Invalidated ${keysToDelete.length} entries by tags:`, tags);\n }\n \n if (config.onInvalidate && keysToDelete.length > 0) {\n config.onInvalidate({\n keys: keysToDelete,\n reason: 'tag',\n timestamp: Date.now(),\n });\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get cache statistics\n */\n function getStats(): CacheStats {\n const total = stats.hits + stats.misses;\n \n return {\n hits: stats.hits,\n misses: stats.misses,\n hitRatio: total > 0 ? stats.hits / total : 0,\n currentSize,\n maxSize: config.maxSize,\n entryCount: cache.size,\n evictions: stats.evictions,\n };\n }\n\n /**\n * Reset statistics\n */\n function resetStats(): void {\n stats.hits = 0;\n stats.misses = 0;\n stats.evictions = 0;\n }\n\n /**\n * Get all keys\n */\n function keys(): string[] {\n return Array.from(cache.keys());\n }\n\n /**\n * Get cache size\n */\n function size(): number {\n return cache.size;\n }\n\n // API implementation\n const api: CachingAPI & Record<string, unknown> = {\n get,\n set,\n has,\n delete: deleteKey,\n clear,\n invalidateByTags,\n getStats,\n resetStats,\n keys,\n size,\n prune: pruneExpired,\n updateConfig(newConfig: Partial<PluginCachingConfig>) {\n Object.assign(config, newConfig);\n },\n };\n\n // Periodic cleanup\n let cleanupInterval: number | null = null;\n\n return {\n manifest,\n\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n\n // Attach to chart API\n (ctx.chart as any).caching = api;\n\n // Setup periodic cleanup (every 60 seconds)\n cleanupInterval = window.setInterval(() => {\n pruneExpired();\n }, 60000);\n },\n\n onDataUpdate(_pluginCtx: PluginContext) {\n if (!config.autoInvalidate) return;\n\n const tags: string[] = [];\n if (config.cacheTypes.transforms) tags.push(\"transform\");\n if (config.cacheTypes.analysis) tags.push(\"analysis\");\n if (config.cacheTypes.bounds) tags.push(\"bounds\");\n\n if (tags.length > 0) {\n invalidateByTags(tags);\n }\n },\n\n onDestroy(pluginCtx: PluginContext) {\n // Clear cleanup interval\n if (cleanupInterval !== null) {\n clearInterval(cleanupInterval);\n }\n\n // Clear cache\n clear();\n\n // Remove from chart API\n delete (pluginCtx.chart as any).caching;\n\n ctx = null;\n },\n\n api,\n };\n}\n\nexport default PluginCaching;\n\n// Type exports\nexport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n CacheStrategy,\n CacheInvalidationEvent,\n} from './types';\n"],"names":["manifest","DEFAULT_CONFIG","PluginCaching","userConfig","config","ctx","cache","stats","currentSize","estimateSize","value","type","sum","item","key","evict","requiredSpace","entries","b","freedSpace","keysToDelete","entry","pruneExpired","now","get","set","options","size","oldEntry","has","deleteKey","clear","count","invalidateByTags","tags","tag","getStats","total","resetStats","keys","api","newConfig","cleanupInterval","pluginCtx","_pluginCtx"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ChartPlugin } from '../types';
|
|
2
|
+
|
|
3
|
+
export type DrawingMode = "none" | "pan" | "trendline" | "horizontal" | "vertical" | "rectangle" | "fibonacci" | "measure";
|
|
4
|
+
export interface PluginDrawingToolsConfig {
|
|
5
|
+
/** Default stroke color */
|
|
6
|
+
color?: string;
|
|
7
|
+
/** Enable candle magnet by default */
|
|
8
|
+
magnet?: boolean;
|
|
9
|
+
/** Return to pan mode after each completed stroke (default true) */
|
|
10
|
+
autoDeselect?: boolean;
|
|
11
|
+
/** Notified when drawing mode changes (including auto-deselect to none) */
|
|
12
|
+
onModeChange?: (mode: DrawingMode) => void;
|
|
13
|
+
/** Color for upward measurements (default green) */
|
|
14
|
+
measureUpColor?: string;
|
|
15
|
+
/** Color for downward measurements (default red) */
|
|
16
|
+
measureDownColor?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DrawingToolsAPI {
|
|
19
|
+
setMode(mode: DrawingMode): void;
|
|
20
|
+
getMode(): DrawingMode;
|
|
21
|
+
setMagnet(enabled: boolean): void;
|
|
22
|
+
isMagnet(): boolean;
|
|
23
|
+
undo(): boolean;
|
|
24
|
+
redo(): boolean;
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare function PluginDrawingTools(config?: PluginDrawingToolsConfig): ChartPlugin<PluginDrawingToolsConfig>;
|
|
28
|
+
export { snapToCandle, findNearestBarIndex } from './snapToCandle';
|
|
29
|
+
export default PluginDrawingTools;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Measurement helper for the price-range / measure tool (TradingView-style).
|
|
3
|
+
*/
|
|
4
|
+
export interface MeasurePoint {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Measurement {
|
|
9
|
+
/** Absolute price change (end - start) */
|
|
10
|
+
change: number;
|
|
11
|
+
/** Percentage change relative to the start price */
|
|
12
|
+
percent: number;
|
|
13
|
+
/** Number of bars spanned (rounded X distance) */
|
|
14
|
+
bars: number;
|
|
15
|
+
/** True when the range moves up (change >= 0) */
|
|
16
|
+
up: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function computeMeasurement(a: MeasurePoint, b: MeasurePoint): Measurement;
|
|
19
|
+
export declare function formatMeasurement(m: Measurement): string;
|
|
20
|
+
/** Compact price formatting used for level labels. */
|
|
21
|
+
export declare function formatPrice(value: number): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snap drawing points to nearest candlestick O/H/L/C (TradingView-style magnet).
|
|
3
|
+
*/
|
|
4
|
+
export interface CandleSnapInput {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
barX: Float32Array | Float64Array;
|
|
8
|
+
open: Float32Array | Float64Array;
|
|
9
|
+
high: Float32Array | Float64Array;
|
|
10
|
+
low: Float32Array | Float64Array;
|
|
11
|
+
close: Float32Array | Float64Array;
|
|
12
|
+
dataToPixelX: (x: number) => number;
|
|
13
|
+
dataToPixelY: (y: number) => number;
|
|
14
|
+
pixelThreshold?: number;
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function findNearestBarIndex(barX: Float32Array | Float64Array, x: number): number;
|
|
18
|
+
export declare function snapToCandle(input: CandleSnapInput): {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
};
|