funhi-chart 1.3.4 → 1.3.6
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/dts/core/CandleManager.d.ts +0 -3
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -60,9 +60,6 @@ export declare class CandleManager {
|
|
|
60
60
|
getLastCandleTime(): number;
|
|
61
61
|
/**
|
|
62
62
|
* Loads candles from storage
|
|
63
|
-
* CRITICAL: Merges with existing candles instead of replacing them
|
|
64
|
-
* Preserves current candle if it's newer than loaded candles
|
|
65
|
-
* Also checks if currentCandle is stale and resets it if needed
|
|
66
63
|
*/
|
|
67
64
|
loadCandles(candles: CandleData[]): void;
|
|
68
65
|
/**
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import t,{useState as e,useEffect as i,useCallback as s,useMemo as n,useRef as r}from"react";class o{static validate(t){return t&&t.time>0&&t.open>0&&t.high>0&&t.low>0&&t.close>0&&isFinite(t.open)&&isFinite(t.high)&&isFinite(t.low)&&isFinite(t.close)&&t.high>=Math.max(t.open,t.close)&&t.low<=Math.min(t.open,t.close)}static ensureMinimumBodySize(t,e){const i=e||Math.max(t.open*this.MIN_BODY_PERCENTAGE,this.MIN_BODY_ABSOLUTE),s=Math.abs(t.open-t.close);if(Math.abs(t.close-t.open)>=i)return t;let n;n=s>1e-4?t.close>=t.open?1:-1:1;const r=t.open+n*i;return{...t,close:r,high:Math.max(t.high,r),low:Math.min(t.low,r)}}static validateOHLC(t){return{...t,high:Math.max(t.open,t.high,t.close),low:Math.min(t.open,t.low,t.close)}}static isCurrentBucket(t,e,i){const s=Math.floor(i/1e3),n=Math.floor(s/e)*e;return t.time===n}static validatePrice(t){return t>0&&isFinite(t)}static calculateMinBodySize(t){return Math.max(t*this.MIN_BODY_PERCENTAGE,this.MIN_BODY_ABSOLUTE)}}o.MIN_BODY_PERCENTAGE=1e-4,o.MIN_BODY_ABSOLUTE=.01;class h{constructor(t){this.candles=[],this.currentCandle=null,this.lastCandleTime=0,this.lastProcessedTimestamp=0,this.debounceMs=50,this.timeframeSeconds=t}createOrUpdate(t,e){const i=Date.now();if(this.lastProcessedTimestamp&&i-this.lastProcessedTimestamp<this.debounceMs)return null;if(this.lastProcessedTimestamp=i,!o.validatePrice(t))return console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Invalid price data: ${t}`),null;const s=Math.floor(e/1e3),n=this.calculateBucketStart(s);return n!==this.lastCandleTime?this.createNewCandle(t,e,n):this.currentCandle?this.updateCurrentCandle(t,e,n):null}createNewCandle(t,e,i){const s=this.getPreviousCandleClose(i),n=this.getPreviousCandleDirection();if(this.currentCandle&&this.isValidCandle(this.currentCandle)){const t=o.validateOHLC(this.currentCandle);this.addCandleToHistory(t)}const r=s??t;null===s&&console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] No previous candle close found, using current price: $${t.toFixed(2)}`);const h=this.buildNewCandle(i,r,t,n);return this.currentCandle=h,this.lastCandleTime=i,this.addCandleToHistory(h),console.log(`🆕 [CandleManager-${this.timeframeSeconds}s] New candle: time=${i}, open=$${r.toFixed(2)}, close=$${h.close.toFixed(2)}`),{candle:h,isNewCandle:!0,wasUpdated:!1}}updateCurrentCandle(t,e,i){if(this.currentCandle.time!==i)return console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Skipping update for historical candle (time: ${this.currentCandle.time}, current: ${i})`),null;if(!this.isValidCandle(this.currentCandle)){console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Invalid existing candle, recreating`);const e={time:this.currentCandle.time,open:t,high:t,low:t,close:t,volume:0};return this.currentCandle=e,this.updateCandleInHistory(e,i),{candle:e,isNewCandle:!1,wasUpdated:!0}}const s=this.updateCandlePrice(this.currentCandle,t),n=o.validateOHLC(s);return n.time!==i?(console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Prevented update of historical candle: time=${n.time}, currentBucket=${i}`),{candle:n,isNewCandle:!1,wasUpdated:!1}):(this.currentCandle=n,this.updateCandleInHistory(n,i),{candle:n,isNewCandle:!1,wasUpdated:!0})}updateCandlePrice(t,e){const i=o.calculateMinBodySize(t.open),s=Math.abs(t.open-e),n=Math.abs(t.close-t.open);let r=e;if(n>0&&n<=10*i&&t.open>0)if(s<100*i){const s=e>=t.open?1:-1;r=t.open+s*i}else{r=e;if(Math.abs(r-t.open)<i){const s=e>=t.open?1:-1;r=t.open+s*i}}else if(s<i&&t.open>0){const s=e>=t.open?1:-1;r=t.open+s*i}if(Math.abs(r-t.open)<i&&t.open>0){let s;s=e!==t.open&&Math.abs(e-t.open)>1e-4?e>=t.open?1:-1:t.close!==t.open&&Math.abs(t.close-t.open)>1e-4?t.close>=t.open?1:-1:1,r=t.open+s*i}return{...t,high:Math.max(t.high,e,r),low:Math.min(t.low,e,r),close:r}}buildNewCandle(t,e,i,s){const n=o.calculateMinBodySize(e),r=Math.abs(e-i);let h=i;if(r<n){let t;t=0===r||Math.abs(i-e)<1e-4?s??1:i>=e?1:-1,h=e+t*n}if(Math.abs(h-e)<n&&e>0){h=e+(i>=e||1===s?1:-1)*n}return{time:t,open:e,high:Math.max(e,h,i),low:Math.min(e,h,i),close:h,volume:0}}getPreviousCandleClose(t){if(this.currentCandle&&this.currentCandle.close>0&&isFinite(this.currentCandle.close)&&this.currentCandle.time<t)return this.currentCandle.close;if(this.candles.length>0){const e=[...this.candles].sort((t,e)=>e.time-t.time),i=e.find(e=>e.time<t&&e.close>0&&isFinite(e.close));if(i)return i.close}return this.currentCandle&&this.currentCandle.close>0&&isFinite(this.currentCandle.close)?this.currentCandle.close:null}getPreviousCandleDirection(){return this.currentCandle&&this.currentCandle.open>0?this.currentCandle.close>=this.currentCandle.open?1:-1:1}calculateBucketStart(t){return Math.floor(t/this.timeframeSeconds)*this.timeframeSeconds}isValidCandle(t){return t.open>0&&t.high>0&&t.low>0&&t.close>0}addCandleToHistory(t){const e=this.candles.findIndex(e=>e.time===t.time);e>=0?this.candles[e]=t:(this.candles.push(t),this.candles.sort((t,e)=>t.time-e.time))}updateCandleInHistory(t,e){if(t.time!==e)return;const i=this.candles.findIndex(t=>t.time===e);i>=0&&this.candles[i].time===e?this.candles[i]=t:t.time===e&&(this.candles.push(t),this.candles.sort((t,e)=>t.time-e.time))}getCandles(){return[...this.candles]}getCurrentCandle(){return this.currentCandle}getLastCandleTime(){return this.lastCandleTime}loadCandles(t){if(0===t.length)return;const e=t.map(t=>{const e=o.ensureMinimumBodySize(t);return o.validateOHLC(e)});e.forEach(t=>{const e=this.candles.findIndex(e=>e.time===t.time);e>=0?this.candles[e]=t:this.candles.push(t)}),this.candles.sort((t,e)=>t.time-e.time);const i=Math.floor(Date.now()/1e3),s=this.calculateBucketStart(i),n=this.currentCandle&&this.currentCandle.time!==s&&this.currentCandle.time<s;if(this.candles.length>0){const t=e.reduce((t,e)=>e.time>t.time?e:t),i=t.time;if(n&&this.currentCandle){const t=this.currentCandle.time,e=o.validateOHLC(this.currentCandle),i=this.candles.findIndex(t=>t.time===e.time);i>=0?this.candles[i]=e:(this.candles.push(e),this.candles.sort((t,e)=>t.time-e.time)),this.currentCandle=null,this.lastCandleTime=0,console.log(`🔄 [CandleManager-${this.timeframeSeconds}s] Reset stale currentCandle (was: ${t}, current bucket: ${s})`)}if(this.currentCandle){if(i>this.lastCandleTime&&i===s)this.currentCandle=t,this.lastCandleTime=i;else if(this.currentCandle){const t=this.candles.findIndex(t=>t.time===this.currentCandle.time);t>=0?this.candles[t]=this.currentCandle:(this.candles.push(this.currentCandle),this.candles.sort((t,e)=>t.time-e.time))}}else i===s&&(this.currentCandle=t,this.lastCandleTime=i)}}updateFromExternal(t,e){if(t.time!==e)return void console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Skipping external update for historical candle`);const i=o.ensureMinimumBodySize(t),s=o.validateOHLC(i);this.currentCandle=s,this.lastCandleTime=s.time,this.updateCandleInHistory(s,e)}reset(){this.candles=[],this.currentCandle=null,this.lastCandleTime=0,this.lastProcessedTimestamp=0}}class l{constructor(t){this.timeframes=t,this.managers=new Map,t.forEach(t=>{this.managers.set(t.seconds,new h(t.seconds))})}getManager(t){return this.managers.get(t)}updateAll(t,e){this.managers.forEach(i=>{i.createOrUpdate(t,e)})}getCandles(t){const e=this.managers.get(t);return e?e.getCandles():[]}getCurrentCandle(t){const e=this.managers.get(t);return e?e.getCurrentCandle():null}loadCandles(t,e){const i=this.managers.get(t);i&&i.loadCandles(e)}updateFromExternal(t,e,i){const s=this.managers.get(t);s&&s.updateFromExternal(e,i)}getTimeframes(){return[...this.timeframes]}reset(){this.managers.forEach(t=>t.reset())}}function a(t){var e=t.width,i=t.height;if(e<0)throw new Error("Negative width is not allowed for Size");if(i<0)throw new Error("Negative height is not allowed for Size");return{width:e,height:i}}function c(t,e){return t.width===e.width&&t.height===e.height}var u=function(){function t(t){var e=this;this._resolutionListener=function(){return e._onResolutionChanged()},this._resolutionMediaQueryList=null,this._observers=[],this._window=t,this._installResolutionListener()}return t.prototype.dispose=function(){this._uninstallResolutionListener(),this._window=null},Object.defineProperty(t.prototype,"value",{get:function(){return this._window.devicePixelRatio},enumerable:!1,configurable:!0}),t.prototype.subscribe=function(t){var e=this,i={next:t};return this._observers.push(i),{unsubscribe:function(){e._observers=e._observers.filter(function(t){return t!==i})}}},t.prototype._installResolutionListener=function(){if(null!==this._resolutionMediaQueryList)throw new Error("Resolution listener is already installed");var t=this._window.devicePixelRatio;this._resolutionMediaQueryList=this._window.matchMedia("all and (resolution: ".concat(t,"dppx)")),this._resolutionMediaQueryList.addListener(this._resolutionListener)},t.prototype._uninstallResolutionListener=function(){null!==this._resolutionMediaQueryList&&(this._resolutionMediaQueryList.removeListener(this._resolutionListener),this._resolutionMediaQueryList=null)},t.prototype._reinstallResolutionListener=function(){this._uninstallResolutionListener(),this._installResolutionListener()},t.prototype._onResolutionChanged=function(){var t=this;this._observers.forEach(function(e){return e.next(t._window.devicePixelRatio)}),this._reinstallResolutionListener()},t}();var d=function(){function t(t,e,i){var s;this._canvasElement=null,this._bitmapSizeChangedListeners=[],this._suggestedBitmapSize=null,this._suggestedBitmapSizeChangedListeners=[],this._devicePixelRatioObservable=null,this._canvasElementResizeObserver=null,this._canvasElement=t,this._canvasElementClientSize=a({width:this._canvasElement.clientWidth,height:this._canvasElement.clientHeight}),this._transformBitmapSize=null!=e?e:function(t){return t},this._allowResizeObserver=null===(s=null==i?void 0:i.allowResizeObserver)||void 0===s||s,this._chooseAndInitObserver()}return t.prototype.dispose=function(){var t,e;if(null===this._canvasElement)throw new Error("Object is disposed");null===(t=this._canvasElementResizeObserver)||void 0===t||t.disconnect(),this._canvasElementResizeObserver=null,null===(e=this._devicePixelRatioObservable)||void 0===e||e.dispose(),this._devicePixelRatioObservable=null,this._suggestedBitmapSizeChangedListeners.length=0,this._bitmapSizeChangedListeners.length=0,this._canvasElement=null},Object.defineProperty(t.prototype,"canvasElement",{get:function(){if(null===this._canvasElement)throw new Error("Object is disposed");return this._canvasElement},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"canvasElementClientSize",{get:function(){return this._canvasElementClientSize},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"bitmapSize",{get:function(){return a({width:this.canvasElement.width,height:this.canvasElement.height})},enumerable:!1,configurable:!0}),t.prototype.resizeCanvasElement=function(t){this._canvasElementClientSize=a(t),this.canvasElement.style.width="".concat(this._canvasElementClientSize.width,"px"),this.canvasElement.style.height="".concat(this._canvasElementClientSize.height,"px"),this._invalidateBitmapSize()},t.prototype.subscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners=this._bitmapSizeChangedListeners.filter(function(e){return e!==t})},Object.defineProperty(t.prototype,"suggestedBitmapSize",{get:function(){return this._suggestedBitmapSize},enumerable:!1,configurable:!0}),t.prototype.subscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners=this._suggestedBitmapSizeChangedListeners.filter(function(e){return e!==t})},t.prototype.applySuggestedBitmapSize=function(){if(null!==this._suggestedBitmapSize){var t=this._suggestedBitmapSize;this._suggestedBitmapSize=null,this._resizeBitmap(t),this._emitSuggestedBitmapSizeChanged(t,this._suggestedBitmapSize)}},t.prototype._resizeBitmap=function(t){var e=this.bitmapSize;c(e,t)||(this.canvasElement.width=t.width,this.canvasElement.height=t.height,this._emitBitmapSizeChanged(e,t))},t.prototype._emitBitmapSizeChanged=function(t,e){var i=this;this._bitmapSizeChangedListeners.forEach(function(s){return s.call(i,t,e)})},t.prototype._suggestNewBitmapSize=function(t){var e=this._suggestedBitmapSize,i=a(this._transformBitmapSize(t,this._canvasElementClientSize)),s=c(this.bitmapSize,i)?null:i;null===e&&null===s||null!==e&&null!==s&&c(e,s)||(this._suggestedBitmapSize=s,this._emitSuggestedBitmapSizeChanged(e,s))},t.prototype._emitSuggestedBitmapSizeChanged=function(t,e){var i=this;this._suggestedBitmapSizeChangedListeners.forEach(function(s){return s.call(i,t,e)})},t.prototype._chooseAndInitObserver=function(){var t=this;this._allowResizeObserver?new Promise(function(t){var e=new ResizeObserver(function(i){t(i.every(function(t){return"devicePixelContentBoxSize"in t})),e.disconnect()});e.observe(document.body,{box:"device-pixel-content-box"})}).catch(function(){return!1}).then(function(e){return e?t._initResizeObserver():t._initDevicePixelRatioObservable()}):this._initDevicePixelRatioObservable()},t.prototype._initDevicePixelRatioObservable=function(){var t=this;if(null!==this._canvasElement){var e=f(this._canvasElement);if(null===e)throw new Error("No window is associated with the canvas");this._devicePixelRatioObservable=function(t){return new u(t)}(e),this._devicePixelRatioObservable.subscribe(function(){return t._invalidateBitmapSize()}),this._invalidateBitmapSize()}},t.prototype._invalidateBitmapSize=function(){var t,e;if(null!==this._canvasElement){var i=f(this._canvasElement);if(null!==i){var s=null!==(e=null===(t=this._devicePixelRatioObservable)||void 0===t?void 0:t.value)&&void 0!==e?e:i.devicePixelRatio,n=this._canvasElement.getClientRects(),r=void 0!==n[0]?function(t,e){return a({width:Math.round(t.left*e+t.width*e)-Math.round(t.left*e),height:Math.round(t.top*e+t.height*e)-Math.round(t.top*e)})}(n[0],s):a({width:this._canvasElementClientSize.width*s,height:this._canvasElementClientSize.height*s});this._suggestNewBitmapSize(r)}}},t.prototype._initResizeObserver=function(){var t=this;null!==this._canvasElement&&(this._canvasElementResizeObserver=new ResizeObserver(function(e){var i=e.find(function(e){return e.target===t._canvasElement});if(i&&i.devicePixelContentBoxSize&&i.devicePixelContentBoxSize[0]){var s=i.devicePixelContentBoxSize[0],n=a({width:s.inlineSize,height:s.blockSize});t._suggestNewBitmapSize(n)}}),this._canvasElementResizeObserver.observe(this._canvasElement,{box:"device-pixel-content-box"}))},t}();function f(t){return t.ownerDocument.defaultView}var m=function(){function t(t,e,i){if(0===e.width||0===e.height)throw new TypeError("Rendering target could only be created on a media with positive width and height");if(this._mediaSize=e,0===i.width||0===i.height)throw new TypeError("Rendering target could only be created using a bitmap with positive integer width and height");this._bitmapSize=i,this._context=t}return t.prototype.useMediaCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),this._context.scale(this._horizontalPixelRatio,this._verticalPixelRatio),t({context:this._context,mediaSize:this._mediaSize})}finally{this._context.restore()}},t.prototype.useBitmapCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),t({context:this._context,mediaSize:this._mediaSize,bitmapSize:this._bitmapSize,horizontalPixelRatio:this._horizontalPixelRatio,verticalPixelRatio:this._verticalPixelRatio})}finally{this._context.restore()}},Object.defineProperty(t.prototype,"_horizontalPixelRatio",{get:function(){return this._bitmapSize.width/this._mediaSize.width},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"_verticalPixelRatio",{get:function(){return this._bitmapSize.height/this._mediaSize.height},enumerable:!1,configurable:!0}),t}();function p(t,e){var i=t.canvasElementClientSize;if(0===i.width||0===i.height)return null;var s=t.bitmapSize;if(0===s.width||0===s.height)return null;var n=t.canvasElement.getContext("2d",e);return null===n?null:new m(n,i,s)}
|
|
1
|
+
import t,{useState as e,useEffect as i,useCallback as s,useMemo as n,useRef as r}from"react";class o{static validate(t){return t&&t.time>0&&t.open>0&&t.high>0&&t.low>0&&t.close>0&&isFinite(t.open)&&isFinite(t.high)&&isFinite(t.low)&&isFinite(t.close)&&t.high>=Math.max(t.open,t.close)&&t.low<=Math.min(t.open,t.close)}static ensureMinimumBodySize(t,e){const i=e||Math.max(t.open*this.MIN_BODY_PERCENTAGE,this.MIN_BODY_ABSOLUTE),s=Math.abs(t.open-t.close);if(Math.abs(t.close-t.open)>=i)return t;let n;n=s>1e-4?t.close>=t.open?1:-1:1;const r=t.open+n*i;return{...t,close:r,high:Math.max(t.high,r),low:Math.min(t.low,r)}}static validateOHLC(t){return{...t,high:Math.max(t.open,t.high,t.close),low:Math.min(t.open,t.low,t.close)}}static isCurrentBucket(t,e,i){const s=Math.floor(i/1e3),n=Math.floor(s/e)*e;return t.time===n}static validatePrice(t){return t>0&&isFinite(t)}static calculateMinBodySize(t){return Math.max(t*this.MIN_BODY_PERCENTAGE,this.MIN_BODY_ABSOLUTE)}}o.MIN_BODY_PERCENTAGE=1e-4,o.MIN_BODY_ABSOLUTE=.01;class h{constructor(t){this.candles=[],this.currentCandle=null,this.lastCandleTime=0,this.lastProcessedTimestamp=0,this.debounceMs=50,this.timeframeSeconds=t}createOrUpdate(t,e){const i=Date.now();if(this.lastProcessedTimestamp&&i-this.lastProcessedTimestamp<this.debounceMs)return null;if(this.lastProcessedTimestamp=i,!o.validatePrice(t))return console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Invalid price data: ${t}`),null;const s=Math.floor(e/1e3),n=this.calculateBucketStart(s);return n!==this.lastCandleTime?this.createNewCandle(t,e,n):this.currentCandle?this.updateCurrentCandle(t,e,n):null}createNewCandle(t,e,i){const s=this.getPreviousCandleClose(i),n=this.getPreviousCandleDirection();if(this.currentCandle&&this.isValidCandle(this.currentCandle)){const t=o.validateOHLC(this.currentCandle);this.addCandleToHistory(t)}const r=s??t;null===s&&console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] No previous candle close found, using current price: $${t.toFixed(2)}`);const h=this.buildNewCandle(i,r,t,n);return this.currentCandle=h,this.lastCandleTime=i,this.addCandleToHistory(h),console.log(`🆕 [CandleManager-${this.timeframeSeconds}s] New candle: time=${i}, open=$${r.toFixed(2)}, close=$${h.close.toFixed(2)}`),{candle:h,isNewCandle:!0,wasUpdated:!1}}updateCurrentCandle(t,e,i){if(this.currentCandle.time!==i)return console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Skipping update for historical candle (time: ${this.currentCandle.time}, current: ${i})`),null;if(!this.isValidCandle(this.currentCandle)){console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Invalid existing candle, recreating`);const e={time:this.currentCandle.time,open:t,high:t,low:t,close:t,volume:0};return this.currentCandle=e,this.updateCandleInHistory(e,i),{candle:e,isNewCandle:!1,wasUpdated:!0}}const s=this.updateCandlePrice(this.currentCandle,t),n=o.validateOHLC(s);return n.time!==i?(console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Prevented update of historical candle: time=${n.time}, currentBucket=${i}`),{candle:n,isNewCandle:!1,wasUpdated:!1}):(this.currentCandle=n,this.updateCandleInHistory(n,i),{candle:n,isNewCandle:!1,wasUpdated:!0})}updateCandlePrice(t,e){const i=o.calculateMinBodySize(t.open),s=Math.abs(t.open-e),n=Math.abs(t.close-t.open);let r=e;if(n>0&&n<=10*i&&t.open>0)if(s<100*i){const s=e>=t.open?1:-1;r=t.open+s*i}else{r=e;if(Math.abs(r-t.open)<i){const s=e>=t.open?1:-1;r=t.open+s*i}}else if(s<i&&t.open>0){const s=e>=t.open?1:-1;r=t.open+s*i}if(Math.abs(r-t.open)<i&&t.open>0){let s;s=e!==t.open&&Math.abs(e-t.open)>1e-4?e>=t.open?1:-1:t.close!==t.open&&Math.abs(t.close-t.open)>1e-4?t.close>=t.open?1:-1:1,r=t.open+s*i}return{...t,high:Math.max(t.high,e,r),low:Math.min(t.low,e,r),close:r}}buildNewCandle(t,e,i,s){const n=o.calculateMinBodySize(e),r=Math.abs(e-i);let h=i;if(r<n){let t;t=0===r||Math.abs(i-e)<1e-4?s??1:i>=e?1:-1,h=e+t*n}if(Math.abs(h-e)<n&&e>0){h=e+(i>=e||1===s?1:-1)*n}return{time:t,open:e,high:Math.max(e,h,i),low:Math.min(e,h,i),close:h,volume:0}}getPreviousCandleClose(t){if(this.currentCandle&&this.currentCandle.close>0&&isFinite(this.currentCandle.close)&&this.currentCandle.time<t)return this.currentCandle.close;if(this.candles.length>0){const e=[...this.candles].sort((t,e)=>e.time-t.time),i=e.find(e=>e.time<t&&e.close>0&&isFinite(e.close));if(i)return i.close}return this.currentCandle&&this.currentCandle.close>0&&isFinite(this.currentCandle.close)?this.currentCandle.close:null}getPreviousCandleDirection(){return this.currentCandle&&this.currentCandle.open>0?this.currentCandle.close>=this.currentCandle.open?1:-1:1}calculateBucketStart(t){return Math.floor(t/this.timeframeSeconds)*this.timeframeSeconds}isValidCandle(t){return t.open>0&&t.high>0&&t.low>0&&t.close>0}addCandleToHistory(t){const e=this.candles.findIndex(e=>e.time===t.time);e>=0?this.candles[e]=t:(this.candles.push(t),this.candles.sort((t,e)=>t.time-e.time))}updateCandleInHistory(t,e){if(t.time!==e)return;const i=this.candles.findIndex(t=>t.time===e);i>=0&&this.candles[i].time===e?this.candles[i]=t:t.time===e&&(this.candles.push(t),this.candles.sort((t,e)=>t.time-e.time))}getCandles(){return[...this.candles]}getCurrentCandle(){return this.currentCandle}getLastCandleTime(){return this.lastCandleTime}loadCandles(t){if(0===t.length)return;const e=t.reduce((t,e)=>{const i=o.ensureMinimumBodySize(e),s=o.validateOHLC(i),n=t.findIndex(t=>t.time===s.time);return n>=0?t[n]=s:t.push(s),t},[]);if(this.candles=e.sort((t,e)=>t.time-e.time),this.candles.length>0){const t=this.candles[this.candles.length-1];this.currentCandle=t,this.lastCandleTime=t.time}}updateFromExternal(t,e){if(t.time!==e)return void console.warn(`⚠️ [CandleManager-${this.timeframeSeconds}s] Skipping external update for historical candle`);const i=o.ensureMinimumBodySize(t),s=o.validateOHLC(i);this.currentCandle=s,this.lastCandleTime=s.time,this.updateCandleInHistory(s,e)}reset(){this.candles=[],this.currentCandle=null,this.lastCandleTime=0,this.lastProcessedTimestamp=0}}class l{constructor(t){this.timeframes=t,this.managers=new Map,t.forEach(t=>{this.managers.set(t.seconds,new h(t.seconds))})}getManager(t){return this.managers.get(t)}updateAll(t,e){this.managers.forEach(i=>{i.createOrUpdate(t,e)})}getCandles(t){const e=this.managers.get(t);return e?e.getCandles():[]}getCurrentCandle(t){const e=this.managers.get(t);return e?e.getCurrentCandle():null}loadCandles(t,e){const i=this.managers.get(t);i&&i.loadCandles(e)}updateFromExternal(t,e,i){const s=this.managers.get(t);s&&s.updateFromExternal(e,i)}getTimeframes(){return[...this.timeframes]}reset(){this.managers.forEach(t=>t.reset())}}function a(t){var e=t.width,i=t.height;if(e<0)throw new Error("Negative width is not allowed for Size");if(i<0)throw new Error("Negative height is not allowed for Size");return{width:e,height:i}}function c(t,e){return t.width===e.width&&t.height===e.height}var u=function(){function t(t){var e=this;this._resolutionListener=function(){return e._onResolutionChanged()},this._resolutionMediaQueryList=null,this._observers=[],this._window=t,this._installResolutionListener()}return t.prototype.dispose=function(){this._uninstallResolutionListener(),this._window=null},Object.defineProperty(t.prototype,"value",{get:function(){return this._window.devicePixelRatio},enumerable:!1,configurable:!0}),t.prototype.subscribe=function(t){var e=this,i={next:t};return this._observers.push(i),{unsubscribe:function(){e._observers=e._observers.filter(function(t){return t!==i})}}},t.prototype._installResolutionListener=function(){if(null!==this._resolutionMediaQueryList)throw new Error("Resolution listener is already installed");var t=this._window.devicePixelRatio;this._resolutionMediaQueryList=this._window.matchMedia("all and (resolution: ".concat(t,"dppx)")),this._resolutionMediaQueryList.addListener(this._resolutionListener)},t.prototype._uninstallResolutionListener=function(){null!==this._resolutionMediaQueryList&&(this._resolutionMediaQueryList.removeListener(this._resolutionListener),this._resolutionMediaQueryList=null)},t.prototype._reinstallResolutionListener=function(){this._uninstallResolutionListener(),this._installResolutionListener()},t.prototype._onResolutionChanged=function(){var t=this;this._observers.forEach(function(e){return e.next(t._window.devicePixelRatio)}),this._reinstallResolutionListener()},t}();var d=function(){function t(t,e,i){var s;this._canvasElement=null,this._bitmapSizeChangedListeners=[],this._suggestedBitmapSize=null,this._suggestedBitmapSizeChangedListeners=[],this._devicePixelRatioObservable=null,this._canvasElementResizeObserver=null,this._canvasElement=t,this._canvasElementClientSize=a({width:this._canvasElement.clientWidth,height:this._canvasElement.clientHeight}),this._transformBitmapSize=null!=e?e:function(t){return t},this._allowResizeObserver=null===(s=null==i?void 0:i.allowResizeObserver)||void 0===s||s,this._chooseAndInitObserver()}return t.prototype.dispose=function(){var t,e;if(null===this._canvasElement)throw new Error("Object is disposed");null===(t=this._canvasElementResizeObserver)||void 0===t||t.disconnect(),this._canvasElementResizeObserver=null,null===(e=this._devicePixelRatioObservable)||void 0===e||e.dispose(),this._devicePixelRatioObservable=null,this._suggestedBitmapSizeChangedListeners.length=0,this._bitmapSizeChangedListeners.length=0,this._canvasElement=null},Object.defineProperty(t.prototype,"canvasElement",{get:function(){if(null===this._canvasElement)throw new Error("Object is disposed");return this._canvasElement},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"canvasElementClientSize",{get:function(){return this._canvasElementClientSize},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"bitmapSize",{get:function(){return a({width:this.canvasElement.width,height:this.canvasElement.height})},enumerable:!1,configurable:!0}),t.prototype.resizeCanvasElement=function(t){this._canvasElementClientSize=a(t),this.canvasElement.style.width="".concat(this._canvasElementClientSize.width,"px"),this.canvasElement.style.height="".concat(this._canvasElementClientSize.height,"px"),this._invalidateBitmapSize()},t.prototype.subscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners=this._bitmapSizeChangedListeners.filter(function(e){return e!==t})},Object.defineProperty(t.prototype,"suggestedBitmapSize",{get:function(){return this._suggestedBitmapSize},enumerable:!1,configurable:!0}),t.prototype.subscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners=this._suggestedBitmapSizeChangedListeners.filter(function(e){return e!==t})},t.prototype.applySuggestedBitmapSize=function(){if(null!==this._suggestedBitmapSize){var t=this._suggestedBitmapSize;this._suggestedBitmapSize=null,this._resizeBitmap(t),this._emitSuggestedBitmapSizeChanged(t,this._suggestedBitmapSize)}},t.prototype._resizeBitmap=function(t){var e=this.bitmapSize;c(e,t)||(this.canvasElement.width=t.width,this.canvasElement.height=t.height,this._emitBitmapSizeChanged(e,t))},t.prototype._emitBitmapSizeChanged=function(t,e){var i=this;this._bitmapSizeChangedListeners.forEach(function(s){return s.call(i,t,e)})},t.prototype._suggestNewBitmapSize=function(t){var e=this._suggestedBitmapSize,i=a(this._transformBitmapSize(t,this._canvasElementClientSize)),s=c(this.bitmapSize,i)?null:i;null===e&&null===s||null!==e&&null!==s&&c(e,s)||(this._suggestedBitmapSize=s,this._emitSuggestedBitmapSizeChanged(e,s))},t.prototype._emitSuggestedBitmapSizeChanged=function(t,e){var i=this;this._suggestedBitmapSizeChangedListeners.forEach(function(s){return s.call(i,t,e)})},t.prototype._chooseAndInitObserver=function(){var t=this;this._allowResizeObserver?new Promise(function(t){var e=new ResizeObserver(function(i){t(i.every(function(t){return"devicePixelContentBoxSize"in t})),e.disconnect()});e.observe(document.body,{box:"device-pixel-content-box"})}).catch(function(){return!1}).then(function(e){return e?t._initResizeObserver():t._initDevicePixelRatioObservable()}):this._initDevicePixelRatioObservable()},t.prototype._initDevicePixelRatioObservable=function(){var t=this;if(null!==this._canvasElement){var e=f(this._canvasElement);if(null===e)throw new Error("No window is associated with the canvas");this._devicePixelRatioObservable=function(t){return new u(t)}(e),this._devicePixelRatioObservable.subscribe(function(){return t._invalidateBitmapSize()}),this._invalidateBitmapSize()}},t.prototype._invalidateBitmapSize=function(){var t,e;if(null!==this._canvasElement){var i=f(this._canvasElement);if(null!==i){var s=null!==(e=null===(t=this._devicePixelRatioObservable)||void 0===t?void 0:t.value)&&void 0!==e?e:i.devicePixelRatio,n=this._canvasElement.getClientRects(),r=void 0!==n[0]?function(t,e){return a({width:Math.round(t.left*e+t.width*e)-Math.round(t.left*e),height:Math.round(t.top*e+t.height*e)-Math.round(t.top*e)})}(n[0],s):a({width:this._canvasElementClientSize.width*s,height:this._canvasElementClientSize.height*s});this._suggestNewBitmapSize(r)}}},t.prototype._initResizeObserver=function(){var t=this;null!==this._canvasElement&&(this._canvasElementResizeObserver=new ResizeObserver(function(e){var i=e.find(function(e){return e.target===t._canvasElement});if(i&&i.devicePixelContentBoxSize&&i.devicePixelContentBoxSize[0]){var s=i.devicePixelContentBoxSize[0],n=a({width:s.inlineSize,height:s.blockSize});t._suggestNewBitmapSize(n)}}),this._canvasElementResizeObserver.observe(this._canvasElement,{box:"device-pixel-content-box"}))},t}();function f(t){return t.ownerDocument.defaultView}var m=function(){function t(t,e,i){if(0===e.width||0===e.height)throw new TypeError("Rendering target could only be created on a media with positive width and height");if(this._mediaSize=e,0===i.width||0===i.height)throw new TypeError("Rendering target could only be created using a bitmap with positive integer width and height");this._bitmapSize=i,this._context=t}return t.prototype.useMediaCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),this._context.scale(this._horizontalPixelRatio,this._verticalPixelRatio),t({context:this._context,mediaSize:this._mediaSize})}finally{this._context.restore()}},t.prototype.useBitmapCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),t({context:this._context,mediaSize:this._mediaSize,bitmapSize:this._bitmapSize,horizontalPixelRatio:this._horizontalPixelRatio,verticalPixelRatio:this._verticalPixelRatio})}finally{this._context.restore()}},Object.defineProperty(t.prototype,"_horizontalPixelRatio",{get:function(){return this._bitmapSize.width/this._mediaSize.width},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"_verticalPixelRatio",{get:function(){return this._bitmapSize.height/this._mediaSize.height},enumerable:!1,configurable:!0}),t}();function p(t,e){var i=t.canvasElementClientSize;if(0===i.width||0===i.height)return null;var s=t.bitmapSize;if(0===s.width||0===s.height)return null;var n=t.canvasElement.getContext("2d",e);return null===n?null:new m(n,i,s)}
|
|
2
2
|
/*!
|
|
3
3
|
* @license
|
|
4
4
|
* TradingView Lightweight Charts™ v4.2.3
|