overtime-live-trading-utils 3.0.1 → 3.0.2-rc.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overtime-live-trading-utils",
3
- "version": "3.0.1",
3
+ "version": "3.0.2-rc.0",
4
4
  "description": "",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -10,9 +10,14 @@ import {
10
10
  MockOnlyMoneylineWithDifferentSportsbook,
11
11
  } from '../mock/MockOpticSoccer';
12
12
  import { mockSoccer } from '../mock/MockSoccerRedis';
13
- import { getLastPolledDataForBookmakers, MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST } from '../utils/helper';
13
+ import {
14
+ getLastPolledDataForBookmakers,
15
+ getPlayersMap,
16
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
17
+ } from '../utils/helper';
14
18
 
15
19
  const lastPolledData = getLastPolledDataForBookmakers();
20
+ const playersMap = getPlayersMap();
16
21
 
17
22
  describe('Bookmakers', () => {
18
23
  it('Should return zero odds for moneyline when one of the bookmakers has no odds', () => {
@@ -28,7 +33,8 @@ describe('Bookmakers', () => {
28
33
  MAX_IMPLIED_PERCENTAGE_DIFF,
29
34
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
30
35
  lastPolledData,
31
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
36
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
37
+ playersMap
32
38
  );
33
39
 
34
40
  const hasOdds = market.odds.some(
@@ -53,7 +59,8 @@ describe('Bookmakers', () => {
53
59
  5,
54
60
  LeagueMocks.leagueInfoOnlyParent,
55
61
  lastPolledData,
56
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
62
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
63
+ playersMap
57
64
  );
58
65
 
59
66
  const hasOdds = market.odds.some(
@@ -78,7 +85,8 @@ describe('Bookmakers', () => {
78
85
  MAX_IMPLIED_PERCENTAGE_DIFF,
79
86
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
80
87
  lastPolledData,
81
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
88
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
89
+ playersMap
82
90
  );
83
91
 
84
92
  const hasOdds = market.odds.some(
@@ -103,7 +111,8 @@ describe('Bookmakers', () => {
103
111
  MAX_IMPLIED_PERCENTAGE_DIFF,
104
112
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
105
113
  lastPolledData,
106
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
114
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
115
+ playersMap
107
116
  );
108
117
 
109
118
  expect(market.childMarkets.length).toBe(2);
@@ -122,7 +131,8 @@ describe('Bookmakers', () => {
122
131
  MAX_IMPLIED_PERCENTAGE_DIFF,
123
132
  LeagueMocks.leaguInfoDifferentPrimaryBookmaker,
124
133
  lastPolledData,
125
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
134
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
135
+ playersMap
126
136
  );
127
137
 
128
138
  expect(market.childMarkets.length).toBe(3);
@@ -141,7 +151,8 @@ describe('Bookmakers', () => {
141
151
  MAX_IMPLIED_PERCENTAGE_DIFF,
142
152
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
143
153
  lastPolledData,
144
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
154
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
155
+ playersMap
145
156
  );
146
157
 
147
158
  expect(market.childMarkets.length).toBe(1);
@@ -5,9 +5,16 @@ import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
5
5
  import { LeagueMocks } from '../mock/MockLeagueMap';
6
6
  import { MockOnlyMoneyline, MockOpticSoccer } from '../mock/MockOpticSoccer';
7
7
  import { mockSoccer } from '../mock/MockSoccerRedis';
8
- import { getLastPolledDataForBookmakers, MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST } from '../utils/helper';
8
+ import { MockNbaData } from '../mock/OpticOddsMock/MockNBA';
9
+ import { MockRedisNba } from '../mock/OpticOddsMock/MockRedisNba';
10
+ import {
11
+ getLastPolledDataForBookmakers,
12
+ getPlayersMap,
13
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
14
+ } from '../utils/helper';
9
15
 
10
16
  const lastPolledData = getLastPolledDataForBookmakers();
17
+ const playersMap = getPlayersMap();
11
18
 
12
19
  describe('Markets', () => {
13
20
  describe('LeagueMap configuration', () => {
@@ -25,7 +32,8 @@ describe('Markets', () => {
25
32
  MAX_IMPLIED_PERCENTAGE_DIFF,
26
33
  LeagueMocks.leagueInfoOnlyParent,
27
34
  lastPolledData,
28
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
35
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
36
+ playersMap
29
37
  );
30
38
 
31
39
  expect(market.childMarkets).toHaveLength(0);
@@ -44,7 +52,8 @@ describe('Markets', () => {
44
52
  MAX_IMPLIED_PERCENTAGE_DIFF,
45
53
  LeagueMocks.leagueInfoMockDisabledChilds,
46
54
  lastPolledData,
47
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
55
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
56
+ playersMap
48
57
  );
49
58
 
50
59
  expect(market.childMarkets).toHaveLength(0);
@@ -63,7 +72,8 @@ describe('Markets', () => {
63
72
  MAX_IMPLIED_PERCENTAGE_DIFF,
64
73
  LeagueMocks.leagueInfoEnabledSpreadDisabledTotals,
65
74
  lastPolledData,
66
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
75
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
76
+ playersMap
67
77
  );
68
78
 
69
79
  const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
@@ -86,7 +96,8 @@ describe('Markets', () => {
86
96
  MAX_IMPLIED_PERCENTAGE_DIFF,
87
97
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
88
98
  lastPolledData,
89
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
99
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
100
+ playersMap
90
101
  );
91
102
 
92
103
  const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
@@ -109,7 +120,8 @@ describe('Markets', () => {
109
120
  MAX_IMPLIED_PERCENTAGE_DIFF,
110
121
  LeagueMocks.leagueInfoEnabledAll,
111
122
  lastPolledData,
112
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
123
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
124
+ playersMap
113
125
  );
114
126
 
115
127
  const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
@@ -164,7 +176,8 @@ describe('Markets', () => {
164
176
  MAX_IMPLIED_PERCENTAGE_DIFF,
165
177
  LeagueMocks.leagueInfoOnlyParentDiffSportId,
166
178
  lastPolledData,
167
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
179
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
180
+ playersMap
168
181
  );
169
182
 
170
183
  expect(warnSpy).toHaveBeenCalled();
@@ -173,5 +186,29 @@ describe('Markets', () => {
173
186
  // Restore the original implementation
174
187
  warnSpy.mockRestore();
175
188
  });
189
+
190
+ it('Should return child markets with player props', () => {
191
+ const freshMockSoccer = JSON.parse(JSON.stringify(MockRedisNba));
192
+ const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockNbaData));
193
+ const market = processMarket(
194
+ freshMockSoccer,
195
+ mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
196
+ ['bovada', 'draftkings'], // this will be ignored as primaryBookmaker is defined in LeagueMap
197
+ [],
198
+ true,
199
+ undefined,
200
+ MAX_IMPLIED_PERCENTAGE_DIFF,
201
+ LeagueMocks.PlayerAssist, // league map with player props configured
202
+ lastPolledData,
203
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
204
+ playersMap
205
+ );
206
+
207
+ market.childMarkets.forEach((child: any) => {
208
+ expect(child.playerProps).toBeDefined();
209
+ expect(child.playerProps.playerId).toBeDefined();
210
+ expect(child.playerProps.playerName).toBeDefined();
211
+ });
212
+ });
176
213
  });
177
214
  });
@@ -10,9 +10,14 @@ import {
10
10
  MockZeroOdds,
11
11
  } from '../mock/MockOpticSoccer';
12
12
  import { mockSoccer } from '../mock/MockSoccerRedis';
13
- import { getLastPolledDataForBookmakers, MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST } from '../utils/helper';
13
+ import {
14
+ getLastPolledDataForBookmakers,
15
+ getPlayersMap,
16
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
17
+ } from '../utils/helper';
14
18
 
15
19
  const lastPolledData = getLastPolledDataForBookmakers();
20
+ const playersMap = getPlayersMap();
16
21
 
17
22
  describe('Odds', () => {
18
23
  it('Should return odds for moneyline', () => {
@@ -28,7 +33,8 @@ describe('Odds', () => {
28
33
  MAX_IMPLIED_PERCENTAGE_DIFF,
29
34
  LeagueMocks.leagueInfoOnlyParent,
30
35
  lastPolledData,
31
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
36
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
37
+ playersMap
32
38
  );
33
39
 
34
40
  const hasOdds = market.odds.some(
@@ -51,7 +57,8 @@ describe('Odds', () => {
51
57
  MAX_IMPLIED_PERCENTAGE_DIFF,
52
58
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
53
59
  lastPolledData,
54
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
60
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
61
+ playersMap
55
62
  );
56
63
 
57
64
  const hasOdds = market.odds.some(
@@ -76,7 +83,8 @@ describe('Odds', () => {
76
83
  MAX_IMPLIED_PERCENTAGE_DIFF,
77
84
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
78
85
  lastPolledData,
79
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
86
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
87
+ playersMap
80
88
  );
81
89
 
82
90
  const hasChildMarkets = market.childMarkets.length > 0;
@@ -96,7 +104,8 @@ describe('Odds', () => {
96
104
  MAX_IMPLIED_PERCENTAGE_DIFF,
97
105
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
98
106
  lastPolledData,
99
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
107
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
108
+ playersMap
100
109
  );
101
110
 
102
111
  expect(market.childMarkets).toHaveLength(0);
@@ -5,9 +5,14 @@ import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
5
5
  import { LeagueMocks } from '../mock/MockLeagueMap';
6
6
  import { MockAfterSpreadZeroOdds1, MockOnlyMoneylineFavorite, MockOpticSoccer } from '../mock/MockOpticSoccer';
7
7
  import { mockSoccer } from '../mock/MockSoccerRedis';
8
- import { getLastPolledDataForBookmakers, MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST } from '../utils/helper';
8
+ import {
9
+ getLastPolledDataForBookmakers,
10
+ getPlayersMap,
11
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
12
+ } from '../utils/helper';
9
13
 
10
14
  const lastPolledData = getLastPolledDataForBookmakers();
15
+ const playersMap = getPlayersMap();
11
16
 
12
17
  describe('Spread configuration', () => {
13
18
  it('Should return zero odds for quotes that sum up total probability above 1', () => {
@@ -23,7 +28,8 @@ describe('Spread configuration', () => {
23
28
  MAX_IMPLIED_PERCENTAGE_DIFF,
24
29
  LeagueMocks.leagueInfoEnabledSpeadAndTotals,
25
30
  lastPolledData,
26
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
31
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
32
+ playersMap
27
33
  );
28
34
 
29
35
  const hasOdds = market.odds.some(
@@ -50,7 +56,8 @@ describe('Spread configuration', () => {
50
56
  MAX_IMPLIED_PERCENTAGE_DIFF,
51
57
  LeagueMocks.leagueInfoOnlyParent,
52
58
  lastPolledData,
53
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
59
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
60
+ playersMap
54
61
  )
55
62
  )
56
63
  );
@@ -67,7 +74,8 @@ describe('Spread configuration', () => {
67
74
  MAX_IMPLIED_PERCENTAGE_DIFF,
68
75
  LeagueMocks.leagueInfoOnlyParentWithSpreadAdded,
69
76
  lastPolledData,
70
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
77
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
78
+ playersMap
71
79
  )
72
80
  )
73
81
  );
@@ -104,7 +112,8 @@ describe('Spread configuration', () => {
104
112
  MAX_IMPLIED_PERCENTAGE_DIFF,
105
113
  LeagueMocks.leagueInfoOnlyParent,
106
114
  lastPolledData,
107
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
115
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
116
+ playersMap
108
117
  )
109
118
  )
110
119
  );
@@ -121,7 +130,8 @@ describe('Spread configuration', () => {
121
130
  MAX_IMPLIED_PERCENTAGE_DIFF,
122
131
  LeagueMocks.leagueInfoOnlyParentWithSpreadAdded,
123
132
  lastPolledData,
124
- MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST
133
+ MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST,
134
+ playersMap
125
135
  )
126
136
  )
127
137
  );
@@ -8,4 +8,12 @@ export const getLastPolledDataForBookmakers = () => {
8
8
  return lastPolledData;
9
9
  };
10
10
 
11
+ export const getPlayersMap = () => {
12
+ const playersMap: Map<string, number> = new Map<string, number>();
13
+ playersMap.set('0C07D14CC5DC', 13234);
14
+ playersMap.set('AD91EA260284', 56789);
15
+ playersMap.set('674851E026BC', 98765);
16
+ return playersMap;
17
+ };
18
+
11
19
  export const MAX_ALLOWED_PROVIDER_DATA_STALE_DELAY_TEST = 30000; // 30 seconds
@@ -30,7 +30,8 @@ export const processMarket = (
30
30
  maxPercentageDiffBetwenOdds: number,
31
31
  leagueMap: any,
32
32
  lastPolledData: LastPolledArray,
33
- maxAllowedProviderDataStaleDelay: number
33
+ maxAllowedProviderDataStaleDelay: number,
34
+ playersMap: Map<string, number>
34
35
  ) => {
35
36
  const sportSpreadData = spreadData.filter((data: any) => data.sportId === String(market.leagueId));
36
37
  const leagueInfo = getLeagueInfo(market.leagueId, leagueMap);
@@ -89,7 +90,8 @@ export const processMarket = (
89
90
  leagueMap,
90
91
  lastPolledData,
91
92
  maxAllowedProviderDataStaleDelay,
92
- maxPercentageDiffBetwenOdds
93
+ maxPercentageDiffBetwenOdds,
94
+ playersMap
93
95
  );
94
96
 
95
97
  const packedChildMarkets = childMarkets.map((childMarket: any) => {
package/src/utils/odds.ts CHANGED
@@ -214,7 +214,8 @@ export const createChildMarkets: (
214
214
  leagueMap: any,
215
215
  lastPolledData: LastPolledArray,
216
216
  maxAllowedProviderDataStaleDelay: number,
217
- maxImpliedPercentageDifference: number
217
+ maxImpliedPercentageDifference: number,
218
+ playersMap: Map<string, number>
218
219
  ) => ChildMarket[] = (
219
220
  apiResponseWithOdds,
220
221
  spreadDataForSport,
@@ -224,7 +225,8 @@ export const createChildMarkets: (
224
225
  leagueMap,
225
226
  lastPolledData,
226
227
  maxAllowedProviderDataStaleDelay,
227
- maxImpliedPercentageDifference
228
+ maxImpliedPercentageDifference,
229
+ playersMap
228
230
  ) => {
229
231
  const [spreadOdds, totalOdds, moneylineOdds, correctScoreOdds, doubleChanceOdds, ggOdds, childMarkets]: any[] = [
230
232
  [],
@@ -242,7 +244,7 @@ export const createChildMarkets: (
242
244
  };
243
245
 
244
246
  if (leagueInfo.length > 0) {
245
- const allChildOdds = filterOddsByMarketNameBookmaker(apiResponseWithOdds.odds, leagueInfo);
247
+ const allChildOdds = filterOdds(apiResponseWithOdds.odds, leagueInfo, playersMap);
246
248
  const checkedChildOdds = checkOddsFromBookmakersForChildMarkets(
247
249
  allChildOdds,
248
250
  leagueInfo,
@@ -269,7 +271,7 @@ export const createChildMarkets: (
269
271
 
270
272
  const homeAwayFormattedOdds = [
271
273
  ...groupAndFormatSpreadOdds(spreadOdds, commonData),
272
- ...groupAndFormatTotalOdds(totalOdds, commonData),
274
+ ...groupAndFormatTotalOdds(totalOdds, commonData), // playerProps are handled inside this function
273
275
  ...groupAndFormatMoneylineOdds(moneylineOdds, commonData),
274
276
  ...groupAndFormatGGOdds(ggOdds),
275
277
  ...groupAndFormatDoubleChanceOdds(doubleChanceOdds, commonData),
@@ -284,12 +286,20 @@ export const createChildMarkets: (
284
286
  );
285
287
 
286
288
  homeAwayOddsWithSpreadAdjusted.forEach((data) => {
289
+ let playerProps = undefined;
290
+ if (data.playerProps) {
291
+ playerProps = {
292
+ playerId: playersMap.get(data.playerProps.playerId.toString()), // convert from opticOdds playerId to our internal playerId
293
+ playerName: data.playerProps.playerName,
294
+ };
295
+ }
287
296
  const childMarket = {
288
297
  leagueId: Number(data.sportId),
289
298
  typeId: Number(data.typeId),
290
299
  type: MarketTypeMap[data.typeId as MarketType]?.key || '',
291
300
  line: Number(data.line || 0),
292
301
  odds: data.odds,
302
+ playerProps,
293
303
  };
294
304
  const leagueInfoByTypeId = leagueInfo.find((league) => Number(league.typeId) === Number(data.typeId));
295
305
  const minOdds = leagueInfoByTypeId?.minOdds; // minimum odds configured for child market (e.g. 0.95 implied probability)
@@ -343,7 +353,7 @@ export const createChildMarkets: (
343
353
  * @param {string} oddsProvider - The main odds provider to filter by.
344
354
  * @returns {Array} The filtered odds array.
345
355
  */
346
- export const filterOddsByMarketNameBookmaker = (oddsArray: Odds, leagueInfos: LeagueConfigInfo[]): any => {
356
+ export const filterOdds = (oddsArray: Odds, leagueInfos: LeagueConfigInfo[], playersMap: Map<string, number>): any => {
347
357
  const allChildMarketsTypes = leagueInfos
348
358
  .filter(
349
359
  (leagueInfo) =>
@@ -353,7 +363,10 @@ export const filterOddsByMarketNameBookmaker = (oddsArray: Odds, leagueInfos: Le
353
363
  .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
354
364
  return oddsArray.reduce((acc: any, odd: any) => {
355
365
  if (allChildMarketsTypes.includes(odd.marketName.toLowerCase())) {
356
- const { points, marketName, selection, selectionLine, sportsBookName } = odd;
366
+ const { points, marketName, selection, selectionLine, sportsBookName, playerId } = odd;
367
+ if (playerId && !playersMap.has(playerId)) {
368
+ return acc;
369
+ }
357
370
  const key = `${sportsBookName.toLowerCase()}_${marketName.toLowerCase()}_${points}_${selection}_${selectionLine}`;
358
371
  acc[key] = {
359
372
  ...odd,
@@ -440,6 +453,13 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
440
453
  acc[key].typeId = odd.typeId;
441
454
  acc[key].type = odd.type;
442
455
  acc[key].sportId = odd.sportId;
456
+
457
+ if (odd.playerId) {
458
+ acc[key].playerProps = {
459
+ playerId: odd.playerId, // Player ID from OpticOdds, this will be converted to our internal playerId later
460
+ playerName: odd.selection,
461
+ };
462
+ }
443
463
  }
444
464
 
445
465
  return acc;
@@ -447,8 +467,8 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
447
467
 
448
468
  // Format the grouped odds into the desired output
449
469
  const formattedOdds = Object.entries(groupedOdds as any).reduce((acc: any, [key, value]) => {
450
- const [_marketName, selection, selectionLine] = key.split('_');
451
- const line = parseFloat(selectionLine);
470
+ const [_marketName, selection, points] = key.split('_');
471
+ const line = parseFloat(points);
452
472
 
453
473
  // if we have away team in total odds we know the market is team total and we need to increase typeId by one.
454
474
  // if this is false typeId is already mapped correctly
@@ -460,6 +480,7 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
460
480
  typeId: !isAwayTeam ? (value as any).typeId : Number((value as any).typeId) + 1,
461
481
  sportId: (value as any).sportId,
462
482
  type: (value as any).type,
483
+ playerProps: (value as any).playerProps,
463
484
  });
464
485
  }
465
486
  return acc;