overtime-live-trading-utils 3.0.2 → 4.0.0-rc.1

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.
@@ -1,6 +1,6 @@
1
1
  import * as oddslib from 'oddslib';
2
2
  import { ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT } from '../constants/errors';
3
- import { OddsObject } from '../types/odds';
3
+ import { Anchor, OddsObject } from '../types/odds';
4
4
  import { LastPolledArray } from '../types/sports';
5
5
  import { createChildMarkets, getParentOdds } from './odds';
6
6
  import { getLeagueInfo } from './sports';
@@ -16,8 +16,10 @@ import { adjustAddedSpread } from './spread';
16
16
  * @param {Array} spreadData - Spread data for odds.
17
17
  * @param {Boolean} isDrawAvailable - Is it two or three-positional sport
18
18
  * @param {Number} defaultSpreadForLiveMarkets - Default spread for live markets
19
- * @param {Number} maxPercentageDiffBetwenOdds - Maximum allowed percentage difference between same position odds from different providers
20
- * @param {Boolean} isTestnet - Flag showing should we process for testnet or mainnet
19
+ * @param {Object} leagueMap - League map for additional league information
20
+ * @param {LastPolledArray} lastPolledData - Array containing last polled timestamps for bookmakers
21
+ * @param {Number} maxAllowedProviderDataStaleDelay - Maximum allowed delay for provider data to be considered fresh
22
+ * @param {Map<string, number>} playersMap - Map of player OO IDs to our internal player ID
21
23
  * @returns {Promise<Object|null>} A promise that resolves to the processed event object or null if the event is invalid or mapping fails.
22
24
  */
23
25
  export const processMarket = (
@@ -27,10 +29,11 @@ export const processMarket = (
27
29
  spreadData: any,
28
30
  isDrawAvailable: any,
29
31
  defaultSpreadForLiveMarkets: any,
30
- maxPercentageDiffBetwenOdds: number,
32
+ anchors: Anchor[],
31
33
  leagueMap: any,
32
34
  lastPolledData: LastPolledArray,
33
- maxAllowedProviderDataStaleDelay: number
35
+ maxAllowedProviderDataStaleDelay: number,
36
+ playersMap: Map<string, number>
34
37
  ) => {
35
38
  const sportSpreadData = spreadData.filter((data: any) => data.sportId === String(market.leagueId));
36
39
  const leagueInfo = getLeagueInfo(market.leagueId, leagueMap);
@@ -42,7 +45,7 @@ export const processMarket = (
42
45
  apiResponseWithOdds,
43
46
  market.leagueId,
44
47
  defaultSpreadForLiveMarkets,
45
- maxPercentageDiffBetwenOdds,
48
+ anchors,
46
49
  leagueInfo,
47
50
  lastPolledData,
48
51
  maxAllowedProviderDataStaleDelay
@@ -89,7 +92,8 @@ export const processMarket = (
89
92
  leagueMap,
90
93
  lastPolledData,
91
94
  maxAllowedProviderDataStaleDelay,
92
- maxPercentageDiffBetwenOdds
95
+ anchors,
96
+ playersMap
93
97
  );
94
98
 
95
99
  const packedChildMarkets = childMarkets.map((childMarket: any) => {
package/src/utils/odds.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as oddslib from 'oddslib';
2
2
  import { MarketType, MarketTypeMap } from 'overtime-utils';
3
- import { DRAW, MIN_ODDS_FOR_DIFF_CHECKING, MONEYLINE_TYPE_ID, ZERO } from '../constants/common';
3
+ import { DRAW, MONEYLINE_TYPE_ID, ZERO } from '../constants/common';
4
4
  import { LAST_POLLED_TOO_OLD, NO_MARKETS_FOR_LEAGUE_ID } from '../constants/errors';
5
5
  import { MoneylineTypes } from '../enums/sports';
6
- import { HomeAwayTeams, Odds, OddsObject } from '../types/odds';
6
+ import { Anchor, HomeAwayTeams, Odds, OddsObject } from '../types/odds';
7
7
  import { ChildMarket, LastPolledArray, LeagueConfigInfo } from '../types/sports';
8
8
  import {
9
9
  checkOddsFromBookmakers,
@@ -128,7 +128,7 @@ export const getParentOdds = (
128
128
  oddsApiObject: OddsObject,
129
129
  sportId: string,
130
130
  defaultSpreadForLiveMarkets: number,
131
- maxPercentageDiffBetwenOdds: number,
131
+ anchors: Anchor[],
132
132
  leagueInfo: LeagueConfigInfo[],
133
133
  lastPolledData: LastPolledArray,
134
134
  maxAllowedProviderDataStaleDelay: number
@@ -164,13 +164,7 @@ export const getParentOdds = (
164
164
  );
165
165
 
166
166
  // CHECKING AND COMPARING ODDS FOR THE GIVEN BOOKMAKERS
167
- const oddsObject = checkOddsFromBookmakers(
168
- moneylineOddsMap,
169
- bookmakers,
170
- isTwoPositionalSport,
171
- maxPercentageDiffBetwenOdds,
172
- MIN_ODDS_FOR_DIFF_CHECKING
173
- );
167
+ const oddsObject = checkOddsFromBookmakers(moneylineOddsMap, bookmakers, isTwoPositionalSport, anchors);
174
168
 
175
169
  if (oddsObject.errorMessage) {
176
170
  return {
@@ -214,7 +208,8 @@ export const createChildMarkets: (
214
208
  leagueMap: any,
215
209
  lastPolledData: LastPolledArray,
216
210
  maxAllowedProviderDataStaleDelay: number,
217
- maxImpliedPercentageDifference: number
211
+ anchors: Anchor[],
212
+ playersMap: Map<string, number>
218
213
  ) => ChildMarket[] = (
219
214
  apiResponseWithOdds,
220
215
  spreadDataForSport,
@@ -224,7 +219,8 @@ export const createChildMarkets: (
224
219
  leagueMap,
225
220
  lastPolledData,
226
221
  maxAllowedProviderDataStaleDelay,
227
- maxImpliedPercentageDifference
222
+ anchors,
223
+ playersMap
228
224
  ) => {
229
225
  const [spreadOdds, totalOdds, moneylineOdds, correctScoreOdds, doubleChanceOdds, ggOdds, childMarkets]: any[] = [
230
226
  [],
@@ -242,14 +238,14 @@ export const createChildMarkets: (
242
238
  };
243
239
 
244
240
  if (leagueInfo.length > 0) {
245
- const allChildOdds = filterOddsByMarketNameBookmaker(apiResponseWithOdds.odds, leagueInfo);
241
+ const allChildOdds = filterOdds(apiResponseWithOdds.odds, leagueInfo, playersMap);
246
242
  const checkedChildOdds = checkOddsFromBookmakersForChildMarkets(
247
243
  allChildOdds,
248
244
  leagueInfo,
249
245
  liveOddsProviders,
250
246
  lastPolledData,
251
247
  maxAllowedProviderDataStaleDelay,
252
- maxImpliedPercentageDifference
248
+ anchors
253
249
  );
254
250
  checkedChildOdds.forEach((odd) => {
255
251
  if (odd.type === 'Total') {
@@ -269,7 +265,7 @@ export const createChildMarkets: (
269
265
 
270
266
  const homeAwayFormattedOdds = [
271
267
  ...groupAndFormatSpreadOdds(spreadOdds, commonData),
272
- ...groupAndFormatTotalOdds(totalOdds, commonData),
268
+ ...groupAndFormatTotalOdds(totalOdds, commonData), // playerProps are handled inside this function
273
269
  ...groupAndFormatMoneylineOdds(moneylineOdds, commonData),
274
270
  ...groupAndFormatGGOdds(ggOdds),
275
271
  ...groupAndFormatDoubleChanceOdds(doubleChanceOdds, commonData),
@@ -284,13 +280,29 @@ export const createChildMarkets: (
284
280
  );
285
281
 
286
282
  homeAwayOddsWithSpreadAdjusted.forEach((data) => {
287
- const childMarket = {
283
+ let childMarket = {
288
284
  leagueId: Number(data.sportId),
289
285
  typeId: Number(data.typeId),
290
286
  type: MarketTypeMap[data.typeId as MarketType]?.key || '',
291
287
  line: Number(data.line || 0),
292
288
  odds: data.odds,
289
+ playerProps: {
290
+ playerId: 0,
291
+ playerName: '',
292
+ },
293
+ isPlayerPropsMarket: false,
293
294
  };
295
+ if (data.playerProps) {
296
+ childMarket = {
297
+ ...childMarket,
298
+ playerProps: {
299
+ playerId: playersMap.get(data.playerProps.playerId.toString()) || 0, // convert from opticOdds playerId to our internal playerId
300
+ playerName: data.playerProps.playerName,
301
+ },
302
+ isPlayerPropsMarket: true,
303
+ };
304
+ }
305
+
294
306
  const leagueInfoByTypeId = leagueInfo.find((league) => Number(league.typeId) === Number(data.typeId));
295
307
  const minOdds = leagueInfoByTypeId?.minOdds; // minimum odds configured for child market (e.g. 0.95 implied probability)
296
308
  const maxOdds = leagueInfoByTypeId?.maxOdds; // maximum odds configured for child market (e.g. 0.05 implied probability)
@@ -343,7 +355,7 @@ export const createChildMarkets: (
343
355
  * @param {string} oddsProvider - The main odds provider to filter by.
344
356
  * @returns {Array} The filtered odds array.
345
357
  */
346
- export const filterOddsByMarketNameBookmaker = (oddsArray: Odds, leagueInfos: LeagueConfigInfo[]): any => {
358
+ export const filterOdds = (oddsArray: Odds, leagueInfos: LeagueConfigInfo[], playersMap: Map<string, number>): any => {
347
359
  const allChildMarketsTypes = leagueInfos
348
360
  .filter(
349
361
  (leagueInfo) =>
@@ -353,7 +365,10 @@ export const filterOddsByMarketNameBookmaker = (oddsArray: Odds, leagueInfos: Le
353
365
  .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
354
366
  return oddsArray.reduce((acc: any, odd: any) => {
355
367
  if (allChildMarketsTypes.includes(odd.marketName.toLowerCase())) {
356
- const { points, marketName, selection, selectionLine, sportsBookName } = odd;
368
+ const { points, marketName, selection, selectionLine, sportsBookName, playerId } = odd;
369
+ if (playerId && !playersMap.has(playerId)) {
370
+ return acc;
371
+ }
357
372
  const key = `${sportsBookName.toLowerCase()}_${marketName.toLowerCase()}_${points}_${selection}_${selectionLine}`;
358
373
  acc[key] = {
359
374
  ...odd,
@@ -440,6 +455,13 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
440
455
  acc[key].typeId = odd.typeId;
441
456
  acc[key].type = odd.type;
442
457
  acc[key].sportId = odd.sportId;
458
+
459
+ if (odd.playerId) {
460
+ acc[key].playerProps = {
461
+ playerId: odd.playerId, // Player ID from OpticOdds, this will be converted to our internal playerId later
462
+ playerName: odd.selection,
463
+ };
464
+ }
443
465
  }
444
466
 
445
467
  return acc;
@@ -447,8 +469,8 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
447
469
 
448
470
  // Format the grouped odds into the desired output
449
471
  const formattedOdds = Object.entries(groupedOdds as any).reduce((acc: any, [key, value]) => {
450
- const [_marketName, selection, selectionLine] = key.split('_');
451
- const line = parseFloat(selectionLine);
472
+ const [_marketName, selection, points] = key.split('_');
473
+ const line = parseFloat(points);
452
474
 
453
475
  // if we have away team in total odds we know the market is team total and we need to increase typeId by one.
454
476
  // if this is false typeId is already mapped correctly
@@ -460,6 +482,7 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
460
482
  typeId: !isAwayTeam ? (value as any).typeId : Number((value as any).typeId) + 1,
461
483
  sportId: (value as any).sportId,
462
484
  type: (value as any).type,
485
+ playerProps: (value as any).playerProps,
463
486
  });
464
487
  }
465
488
  return acc;