From 9ec8b9a8e3dd85e816f8acfc01a7d27c1ed8f08b Mon Sep 17 00:00:00 2001 From: Bryan Ingle Date: Tue, 13 Feb 2024 09:59:36 -0700 Subject: [PATCH] Update `SymbolParser.getProducerSymbol` to correctly translate futures symbols expiring in 10 or more years --- docs/content/releases/6.2.5.md | 3 ++ lib/utilities/parsers/SymbolParser.js | 39 +++++++++++++++ .../utilities/parsers/SymbolParserSpec.js | 50 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 docs/content/releases/6.2.5.md diff --git a/docs/content/releases/6.2.5.md b/docs/content/releases/6.2.5.md new file mode 100644 index 0000000..7f56be7 --- /dev/null +++ b/docs/content/releases/6.2.5.md @@ -0,0 +1,3 @@ +**Bug Fixes** + +* Updated `SymbolParser.getProducerSymbol` function, addressing failure to properly translate symbols for futures which expire in 10 or more years (e.g. `CLG34` now correctly translates to `GLB4`). \ No newline at end of file diff --git a/lib/utilities/parsers/SymbolParser.js b/lib/utilities/parsers/SymbolParser.js index 9229605..aeacb85 100644 --- a/lib/utilities/parsers/SymbolParser.js +++ b/lib/utilities/parsers/SymbolParser.js @@ -419,6 +419,21 @@ module.exports = (() => { } } + const distantFuturesMonths = { + F: 'A', + G: 'B', + H: 'C', + J: 'D', + K: 'E', + M: 'I', + N: 'L', + Q: 'O', + U: 'P', + V: 'R', + X: 'S', + Z: 'T' + }; + const alternateFuturesMonths = { A: 'F', B: 'G', @@ -707,6 +722,30 @@ module.exports = (() => { const converters = []; + converters.push((symbol) => { + let converted = null; + + if (SymbolParser.getIsFuture(symbol) && SymbolParser.getIsConcrete(symbol)) { + const matches = symbol.match(types.futures.concrete); + + if (matches !== null) { + const root = matches[1]; + const month = matches[2]; + const year = getFuturesYear(matches[3], month); + + if (year > (getCurrentYear() + 9)) { + const distant = distantFuturesMonths[month]; + + if (distant) { + converted = `${root}${distant}${getYearDigits(year, 1)}`; + } + } + } + } + + return converted; + }); + converters.push((symbol) => { let converted = null; diff --git a/test/specs/utilities/parsers/SymbolParserSpec.js b/test/specs/utilities/parsers/SymbolParserSpec.js index f6a97b5..c633f25 100644 --- a/test/specs/utilities/parsers/SymbolParserSpec.js +++ b/test/specs/utilities/parsers/SymbolParserSpec.js @@ -2797,6 +2797,56 @@ describe('When checking the display format for the symbol', () => { }); describe('When getting a producer symbol', () => { + describe('When the year distant (futures expiration in 10 or more years)', () => { + it('CLG2034 should map to CLB4', () => { + expect(SymbolParser.getProducerSymbol('CLG2034')).toEqual('CLB4'); + }); + + it('CLG34 should map to CLB4', () => { + expect(SymbolParser.getProducerSymbol('CLG34')).toEqual('CLB4'); + }); + + it('CLH35 should map to CLC5', () => { + expect(SymbolParser.getProducerSymbol('CLH35')).toEqual('CLC5'); + }); + + it('CLJ36 should map to CLD6', () => { + expect(SymbolParser.getProducerSymbol('CLJ36')).toEqual('CLD6'); + }); + + it('CLK37 should map to CLE7', () => { + expect(SymbolParser.getProducerSymbol('CLK37')).toEqual('CLE7'); + }); + + it('CLM38 should map to CLI8', () => { + expect(SymbolParser.getProducerSymbol('CLM38')).toEqual('CLI8'); + }); + + it('CLN39 should map to CLL9', () => { + expect(SymbolParser.getProducerSymbol('CLN39')).toEqual('CLL9'); + }); + + it('CLQ40 should map to CLO0', () => { + expect(SymbolParser.getProducerSymbol('CLQ40')).toEqual('CLO0'); + }); + + it('CLU41 should map to CLP1', () => { + expect(SymbolParser.getProducerSymbol('CLU41')).toEqual('CLP1'); + }); + + it('CLV42 should map to CLR2', () => { + expect(SymbolParser.getProducerSymbol('CLV42')).toEqual('CLR2'); + }); + + it('CLX43 should map to CLS3', () => { + expect(SymbolParser.getProducerSymbol('CLX43')).toEqual('CLS3'); + }); + + it('CLZ44 should map to CLT4', () => { + expect(SymbolParser.getProducerSymbol('CLZ44')).toEqual('CLT4'); + }); + }); + describe('When the year is unimportant', () => { it('TSLA should map to TSLA', () => { expect(SymbolParser.getProducerSymbol('TSLA')).toEqual('TSLA');