Skip to content

Commit 4e7bac1

Browse files
committed
add parsing for equity options
1 parent 6b53083 commit 4e7bac1

File tree

3 files changed

+500
-1
lines changed

3 files changed

+500
-1
lines changed

lib/utilities/parsers/SymbolParser.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ module.exports = (() => {
4949
types.futures.options.short = /^([A-Z][A-Z0-9\$\-!\.]?)([A-Z])([0-9]{1,4})([A-Z])$/i;
5050
types.futures.options.long = /^([A-Z][A-Z0-9\$\-!\.]{0,2})([A-Z])([0-9]{1,4})\|(\-?[0-9]{1,5})(C|P)$/i;
5151
types.futures.options.historical = /^([A-Z][A-Z0-9\$\-!\.]{0,2})([A-Z])([0-9]{2})([0-9]{1,5})(C|P)$/i;
52+
types.equities = { };
53+
types.equities.options = /^([A-Z\$][A-Z\.\-]{0,})([0-9]?)\|([[0-9]{4})([[0-9]{2})([[0-9]{2})\|([0-9]+\.[0-9]+)[P|W]?(C|P)/i;
5254
types.indicies = { };
5355
types.indicies.external = /^\$(.*)$/i;
5456
types.indicies.sector = /^\-(.*)$/i;
@@ -121,6 +123,31 @@ module.exports = (() => {
121123
return definition;
122124
});
123125

126+
parsers.push((symbol) => {
127+
let definition = null;
128+
129+
const match = symbol.match(types.equities.options);
130+
131+
if (match !== null) {
132+
definition = { };
133+
134+
definition.symbol = symbol;
135+
definition.type = 'equity_option';
136+
137+
definition.option_type = match[7] === 'C' ? 'call' : 'put';
138+
definition.strike = parseFloat(match[6]);
139+
140+
definition.root = match[1];
141+
definition.month = parseInt(match[4]);
142+
definition.day = parseInt(match[5]);
143+
definition.year = parseInt(match[3]);
144+
145+
definition.adjusted = match[2] !== '';
146+
}
147+
148+
return definition;
149+
});
150+
124151
parsers.push((symbol) => {
125152
let definition = null;
126153

@@ -195,7 +222,7 @@ module.exports = (() => {
195222
definition.symbol = symbol;
196223
definition.type = 'future_option';
197224

198-
definition.option_type = match[5] === 'C' ? 'call' : 'put';
225+
definition.option_type = match[5] === 'C' ? 'call' : 'put';
199226
definition.strike = parseInt(match[4]);
200227

201228
definition.root = match[1];
@@ -509,6 +536,19 @@ module.exports = (() => {
509536
return is.string(symbol) && predicates.bats.test(symbol);
510537
}
511538

539+
/**
540+
* Returns true if the symbol represents an option on an equity or index; false
541+
* otherwise.
542+
*
543+
* @public
544+
* @static
545+
* @param {String} symbol
546+
* @returns {Boolean}
547+
*/
548+
static getIsEquityOption(symbol) {
549+
return is.string(symbol) && types.equities.options.test(symbol);
550+
}
551+
512552
/**
513553
* Returns true if the symbol has an expiration and the symbol appears
514554
* to be expired (e.g. a future for a past year).

test/dist/barchart-marketdata-api-tests-4.0.js

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,8 @@ module.exports = (() => {
24492449
types.futures.options.short = /^([A-Z][A-Z0-9\$\-!\.]?)([A-Z])([0-9]{1,4})([A-Z])$/i;
24502450
types.futures.options.long = /^([A-Z][A-Z0-9\$\-!\.]{0,2})([A-Z])([0-9]{1,4})\|(\-?[0-9]{1,5})(C|P)$/i;
24512451
types.futures.options.historical = /^([A-Z][A-Z0-9\$\-!\.]{0,2})([A-Z])([0-9]{2})([0-9]{1,5})(C|P)$/i;
2452+
types.equities = {};
2453+
types.equities.options = /^([A-Z\$][A-Z\.\-]{0,})([0-9]?)\|([[0-9]{4})([[0-9]{2})([[0-9]{2})\|([0-9]+\.[0-9]+)[P|W]?(C|P)/i;
24522454
types.indicies = {};
24532455
types.indicies.external = /^\$(.*)$/i;
24542456
types.indicies.sector = /^\-(.*)$/i;
@@ -2507,6 +2509,25 @@ module.exports = (() => {
25072509

25082510
return definition;
25092511
});
2512+
parsers.push(symbol => {
2513+
let definition = null;
2514+
const match = symbol.match(types.equities.options);
2515+
2516+
if (match !== null) {
2517+
definition = {};
2518+
definition.symbol = symbol;
2519+
definition.type = 'equity_option';
2520+
definition.option_type = match[7] === 'C' ? 'call' : 'put';
2521+
definition.strike = parseFloat(match[6]);
2522+
definition.root = match[1];
2523+
definition.month = parseInt(match[4]);
2524+
definition.day = parseInt(match[5]);
2525+
definition.year = parseInt(match[3]);
2526+
definition.adjusted = match[2] !== '';
2527+
}
2528+
2529+
return definition;
2530+
});
25102531
parsers.push(symbol => {
25112532
let definition = null;
25122533

@@ -2877,6 +2898,20 @@ module.exports = (() => {
28772898
static getIsBats(symbol) {
28782899
return is.string(symbol) && predicates.bats.test(symbol);
28792900
}
2901+
/**
2902+
* Returns true if the symbol represents an option on an equity or index; false
2903+
* otherwise.
2904+
*
2905+
* @public
2906+
* @static
2907+
* @param {String} symbol
2908+
* @returns {Boolean}
2909+
*/
2910+
2911+
2912+
static getIsEquityOption(symbol) {
2913+
return is.string(symbol) && types.equities.options.test(symbol);
2914+
}
28802915
/**
28812916
* Returns true if the symbol has an expiration and the symbol appears
28822917
* to be expired (e.g. a future for a past year).
@@ -15548,6 +15583,78 @@ describe('When parsing a symbol for instrument type', () => {
1554815583
expect(instrumentType.type).toEqual('future_spread');
1554915584
});
1555015585
});
15586+
describe('and the symbol is AAPL1|20200515|250.00C', () => {
15587+
let instrumentType;
15588+
beforeEach(() => {
15589+
instrumentType = SymbolParser.parseInstrumentType('AAPL1|20200515|250.00C');
15590+
});
15591+
it('the result should not be null', () => {
15592+
expect(instrumentType).not.toBe(null);
15593+
});
15594+
it('the "symbol" should be "AAPL1|20200515|250.00C"', () => {
15595+
expect(instrumentType.symbol).toEqual('AAPL1|20200515|250.00C');
15596+
});
15597+
it('the "type" should be "equity_option"', () => {
15598+
expect(instrumentType.type).toEqual('equity_option');
15599+
});
15600+
it('the "root" should be "AAPL"', () => {
15601+
expect(instrumentType.root).toEqual('AAPL');
15602+
});
15603+
it('the "month" should be 5', () => {
15604+
expect(instrumentType.month).toEqual(5);
15605+
});
15606+
it('the "day" should be 15', () => {
15607+
expect(instrumentType.day).toEqual(15);
15608+
});
15609+
it('the "year" should be 2020', () => {
15610+
expect(instrumentType.year).toEqual(2020);
15611+
});
15612+
it('the "strike" should be 250', () => {
15613+
expect(instrumentType.strike).toEqual(250);
15614+
});
15615+
it('the "option_type" should be "call"', () => {
15616+
expect(instrumentType.option_type).toEqual('call');
15617+
});
15618+
it('the "adjusted" flag should be true', () => {
15619+
expect(instrumentType.adjusted).toEqual(true);
15620+
});
15621+
});
15622+
describe('and the symbol is $VIX|20200422|20.00WP', () => {
15623+
let instrumentType;
15624+
beforeEach(() => {
15625+
instrumentType = SymbolParser.parseInstrumentType('$VIX|20200422|20.00WP');
15626+
});
15627+
it('the result should not be null', () => {
15628+
expect(instrumentType).not.toBe(null);
15629+
});
15630+
it('the "symbol" should be "$VIX|20200422|20.00WP"', () => {
15631+
expect(instrumentType.symbol).toEqual('$VIX|20200422|20.00WP');
15632+
});
15633+
it('the "type" should be "equity_option"', () => {
15634+
expect(instrumentType.type).toEqual('equity_option');
15635+
});
15636+
it('the "root" should be "$VIX"', () => {
15637+
expect(instrumentType.root).toEqual('$VIX');
15638+
});
15639+
it('the "month" should be 4', () => {
15640+
expect(instrumentType.month).toEqual(4);
15641+
});
15642+
it('the "day" should be 22', () => {
15643+
expect(instrumentType.day).toEqual(22);
15644+
});
15645+
it('the "year" should be 2020', () => {
15646+
expect(instrumentType.year).toEqual(2020);
15647+
});
15648+
it('the "strike" should be 20', () => {
15649+
expect(instrumentType.strike).toEqual(20);
15650+
});
15651+
it('the "option_type" should be "put"', () => {
15652+
expect(instrumentType.option_type).toEqual('put');
15653+
});
15654+
it('the "adjusted" flag should be false', () => {
15655+
expect(instrumentType.adjusted).toEqual(false);
15656+
});
15657+
});
1555115658
});
1555215659
describe('When checking to see if a symbol is a future', () => {
1555315660
it('the symbol "ES*1" should return true', () => {
@@ -15610,6 +15717,12 @@ describe('When checking to see if a symbol is a future', () => {
1561015717
it('the symbol "ZCPAUS.CM" should return false', () => {
1561115718
expect(SymbolParser.getIsFuture('ZCPAUS.CM')).toEqual(false);
1561215719
});
15720+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
15721+
expect(SymbolParser.getIsFuture('AAPL|20200515|250.00C')).toEqual(false);
15722+
});
15723+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
15724+
expect(SymbolParser.getIsFuture('$VIX|20200422|20.00WP')).toEqual(false);
15725+
});
1561315726
});
1561415727
describe('When checking to see if a symbol is a "concrete" future', () => {
1561515728
it('the symbol "ESZ6" should return true', () => {
@@ -15715,6 +15828,12 @@ describe('When checking to see if a symbol is sector', () => {
1571515828
it('the symbol "ZCPAUS.CM" should return false', () => {
1571615829
expect(SymbolParser.getIsSector('ZCPAUS.CM')).toEqual(false);
1571715830
});
15831+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
15832+
expect(SymbolParser.getIsSector('AAPL|20200515|250.00C')).toEqual(false);
15833+
});
15834+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
15835+
expect(SymbolParser.getIsSector('$VIX|20200422|20.00WP')).toEqual(false);
15836+
});
1571815837
});
1571915838
describe('When checking to see if a symbol is forex', () => {
1572015839
it('the symbol "ES*1" should return false', () => {
@@ -15783,6 +15902,12 @@ describe('When checking to see if a symbol is forex', () => {
1578315902
it('the symbol "ZCPAUS.CM" should return false', () => {
1578415903
expect(SymbolParser.getIsForex('ZCPAUS.CM')).toEqual(false);
1578515904
});
15905+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
15906+
expect(SymbolParser.getIsForex('AAPL|20200515|250.00C')).toEqual(false);
15907+
});
15908+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
15909+
expect(SymbolParser.getIsForex('$VIX|20200422|20.00WP')).toEqual(false);
15910+
});
1578615911
});
1578715912
describe('When checking to see if a symbol is a future spread', () => {
1578815913
it('the symbol "ES*1" should return false', () => {
@@ -15851,6 +15976,12 @@ describe('When checking to see if a symbol is a future spread', () => {
1585115976
it('the symbol "ZCPAUS.CM" should return false', () => {
1585215977
expect(SymbolParser.getIsFutureSpread('ZCPAUS.CM')).toEqual(false);
1585315978
});
15979+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
15980+
expect(SymbolParser.getIsFutureSpread('AAPL|20200515|250.00C')).toEqual(false);
15981+
});
15982+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
15983+
expect(SymbolParser.getIsFutureSpread('$VIX|20200422|20.00WP')).toEqual(false);
15984+
});
1585415985
});
1585515986
describe('When checking to see if a symbol is a future option', () => {
1585615987
it('the symbol "ES*1" should return false', () => {
@@ -15919,6 +16050,12 @@ describe('When checking to see if a symbol is a future option', () => {
1591916050
it('the symbol "ZCPAUS.CM" should return false', () => {
1592016051
expect(SymbolParser.getIsFutureOption('ZCPAUS.CM')).toEqual(false);
1592116052
});
16053+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
16054+
expect(SymbolParser.getIsFutureOption('AAPL|20200515|250.00C')).toEqual(false);
16055+
});
16056+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
16057+
expect(SymbolParser.getIsFutureOption('$VIX|20200422|20.00WP')).toEqual(false);
16058+
});
1592216059
});
1592316060
describe('When checking to see if a symbol is a cmdty index option', () => {
1592416061
it('the symbol "ES*1" should return false', () => {
@@ -15987,6 +16124,86 @@ describe('When checking to see if a symbol is a cmdty index option', () => {
1598716124
it('the symbol "ZCPAUS.CM" should return true', () => {
1598816125
expect(SymbolParser.getIsCmdty('ZCPAUS.CM')).toEqual(true);
1598916126
});
16127+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
16128+
expect(SymbolParser.getIsCmdty('AAPL|20200515|250.00C')).toEqual(false);
16129+
});
16130+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
16131+
expect(SymbolParser.getIsCmdty('$VIX|20200422|20.00WP')).toEqual(false);
16132+
});
16133+
});
16134+
describe('When checking to see if a symbol is a equity option', () => {
16135+
it('the symbol "ES*1" should return false', () => {
16136+
expect(SymbolParser.getIsEquityOption('ES*1')).toEqual(false);
16137+
});
16138+
it('the symbol "NG*13" should return false', () => {
16139+
expect(SymbolParser.getIsEquityOption('NG*13')).toEqual(false);
16140+
});
16141+
it('the symbol "ESZ6" should return false', () => {
16142+
expect(SymbolParser.getIsEquityOption('ESZ6')).toEqual(false);
16143+
});
16144+
it('the symbol "ESZ16" should return false', () => {
16145+
expect(SymbolParser.getIsEquityOption('ESZ16')).toEqual(false);
16146+
});
16147+
it('the symbol "ESZ2016" should return false', () => {
16148+
expect(SymbolParser.getIsEquityOption('ESZ2016')).toEqual(false);
16149+
});
16150+
it('the symbol "ESZ016" should return false', () => {
16151+
expect(SymbolParser.getIsEquityOption('ESZ016')).toEqual(false);
16152+
});
16153+
it('the symbol "O!H7" should return false', () => {
16154+
expect(SymbolParser.getIsEquityOption('O!H7')).toEqual(false);
16155+
});
16156+
it('the symbol "O!H17" should return false', () => {
16157+
expect(SymbolParser.getIsEquityOption('O!H17')).toEqual(false);
16158+
});
16159+
it('the symbol "O!H2017" should return false', () => {
16160+
expect(SymbolParser.getIsEquityOption('O!H2017')).toEqual(false);
16161+
});
16162+
it('the symbol "IBM" should return false', () => {
16163+
expect(SymbolParser.getIsEquityOption('IBM')).toEqual(false);
16164+
});
16165+
it('the symbol "^EURUSD" should return false', () => {
16166+
expect(SymbolParser.getIsEquityOption('^EURUSD')).toEqual(false);
16167+
});
16168+
it('the symbol "-001A" should return false', () => {
16169+
expect(SymbolParser.getIsEquityOption('-001A')).toEqual(false);
16170+
});
16171+
it('the symbol "$DOWI" should return false', () => {
16172+
expect(SymbolParser.getIsEquityOption('$DOWI')).toEqual(false);
16173+
});
16174+
it('the symbol "$S1GE" should return false', () => {
16175+
expect(SymbolParser.getIsEquityOption('$S1GE')).toEqual(false);
16176+
});
16177+
it('the symbol "_S_SP_ZCH7_ZCK7" should return false', () => {
16178+
expect(SymbolParser.getIsEquityOption('_S_SP_ZCH7_ZCK7')).toEqual(false);
16179+
});
16180+
it('the symbol "ESZ2660Q" should return false', () => {
16181+
expect(SymbolParser.getIsEquityOption('ESZ2660Q')).toEqual(false);
16182+
});
16183+
it('the symbol "ZWH9|470C" should return false', () => {
16184+
expect(SymbolParser.getIsEquityOption('ZWH9|470C')).toEqual(false);
16185+
});
16186+
it('the symbol "BB1F8|12050C" should return false', () => {
16187+
expect(SymbolParser.getIsEquityOption('BB1F8|12050C')).toEqual(false);
16188+
});
16189+
it('the symbol "ZWK18465C" should return false', () => {
16190+
expect(SymbolParser.getIsEquityOption('ZWK18465C')).toEqual(false);
16191+
});
16192+
it('the symbol "PLATTS:AAVSV00C" should return false', () => {
16193+
expect(SymbolParser.getIsEquityOption('PLATTS:AAVSV00C')).toEqual(false);
16194+
});
16195+
it('the symbol "PLATTS:AAVSV00" should return false', () => {
16196+
expect(SymbolParser.getIsEquityOption('PLATTS:AAVSV00')).toEqual(false);
16197+
});
16198+
it('the symbol "ZCPAUS.CM" should return true', () => {
16199+
expect(SymbolParser.getIsEquityOption('ZCPAUS.CM')).toEqual(false);
16200+
});
16201+
it('the symbol "AAPL|20200515|250.00C" should return false', () => {
16202+
expect(SymbolParser.getIsEquityOption('AAPL|20200515|250.00C')).toEqual(true);
16203+
});
16204+
it('the symbol "$VIX|20200422|20.00WP" should return false', () => {
16205+
expect(SymbolParser.getIsEquityOption('$VIX|20200422|20.00WP')).toEqual(true);
16206+
});
1599016207
});
1599116208
describe('When checking to see if a symbol is a BATS listing', () => {
1599216209
it('the symbol "IBM" should return false', () => {

0 commit comments

Comments
 (0)