@@ -205,6 +205,15 @@ describe("orderbook sampler", () => {
205205} ) ;
206206
207207describe ( "ohlcv bar tracker" , ( ) => {
208+ const snapshot = Array . from ( { length : 500 } , ( _ , index ) => [
209+ 1_700_000_000_000 + index * 60_000 ,
210+ 1 ,
211+ 2 ,
212+ 0.5 ,
213+ 1.5 ,
214+ 10 ,
215+ ] ) ;
216+
208217 test ( "parseOhlcvBar accepts CCXT tuple shape" , ( ) => {
209218 expect ( parseOhlcvBar ( [ 1_000 , 1 , 2 , 0.5 , 1.5 , 10 , 15 ] ) ) . toEqual ( {
210219 openTimeMs : 1_000 ,
@@ -280,6 +289,63 @@ describe("ohlcv bar tracker", () => {
280289 } ,
281290 ] ) ;
282291 } ) ;
292+
293+ test ( "preserves all bars in the first batch and leaves the newest open" , ( ) => {
294+ const tracker = new OhlcvBarTracker ( ) ;
295+
296+ const candidates = tracker . process ( snapshot , 100 ) ;
297+
298+ expect ( candidates ) . toHaveLength ( 500 ) ;
299+ expect (
300+ candidates . map ( ( { bar, isClosed } ) => ( {
301+ openTimeMs : bar . openTimeMs ,
302+ isClosed,
303+ } ) ) ,
304+ ) . toEqual (
305+ snapshot . map ( ( [ openTimeMs ] , index ) => ( {
306+ openTimeMs,
307+ isClosed : index < snapshot . length - 1 ,
308+ } ) ) ,
309+ ) ;
310+ } ) ;
311+
312+ test ( "repeated snapshot only re-emits the open bar update" , ( ) => {
313+ const tracker = new OhlcvBarTracker ( ) ;
314+ tracker . process ( snapshot , 100 ) ;
315+
316+ const candidates = tracker . process ( snapshot , 200 ) ;
317+
318+ expect ( candidates ) . toHaveLength ( 1 ) ;
319+ expect ( candidates [ 0 ] ) . toMatchObject ( {
320+ bar : { openTimeMs : snapshot . at ( - 1 ) ?. [ 0 ] } ,
321+ isClosed : false ,
322+ brokerVersion : 200 ,
323+ } ) ;
324+ } ) ;
325+
326+ test ( "overlapping snapshot closes the previous open bar and emits the new open bar" , ( ) => {
327+ const tracker = new OhlcvBarTracker ( ) ;
328+ tracker . process ( snapshot , 100 ) ;
329+ const previousOpenTimeMs = snapshot . at ( - 1 ) ?. [ 0 ] ?? 0 ;
330+ const nextOpenTimeMs = previousOpenTimeMs + 60_000 ;
331+ const overlappingSnapshot = [
332+ ...snapshot . slice ( 1 ) ,
333+ [ nextOpenTimeMs , 1.5 , 2.5 , 1 , 2 , 12 ] ,
334+ ] ;
335+
336+ const candidates = tracker . process ( overlappingSnapshot , 200 ) ;
337+
338+ expect (
339+ candidates . map ( ( { bar, isClosed, brokerVersion } ) => ( {
340+ openTimeMs : bar . openTimeMs ,
341+ isClosed,
342+ brokerVersion,
343+ } ) ) ,
344+ ) . toEqual ( [
345+ { openTimeMs : previousOpenTimeMs , isClosed : true , brokerVersion : 200 } ,
346+ { openTimeMs : nextOpenTimeMs , isClosed : false , brokerVersion : 200 } ,
347+ ] ) ;
348+ } ) ;
283349} ) ;
284350
285351describe ( "ohlcv bootstrap limit" , ( ) => {
0 commit comments