overtime-live-trading-utils 3.0.0-rc.0 → 3.0.0-rc.2
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/main.js +1 -1
- package/package.json +1 -1
- package/src/tests/mock/MockLeagueMap.ts +25 -0
- package/src/tests/mock/OpticOddsMock/MockNBA.ts +17269 -0
- package/src/tests/mock/OpticOddsMock/MockRedisNba.ts +21 -0
- package/src/tests/utils/helper.ts +1 -0
- package/src/types/resolution.ts +4 -0
- package/src/utils/bookmakers.ts +20 -32
- package/src/utils/odds.ts +4 -5
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const MockRedisNba = {
|
|
2
|
+
leagueId: 4,
|
|
3
|
+
typeId: 0,
|
|
4
|
+
odds: [
|
|
5
|
+
{
|
|
6
|
+
american: -140.056022408986,
|
|
7
|
+
decimal: 1.71399999999988,
|
|
8
|
+
normalizedImplied: 0.583430571762,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
american: 450.00000000055,
|
|
12
|
+
decimal: 5.5000000000055,
|
|
13
|
+
normalizedImplied: 0.181818181818,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
american: 234.999999999514,
|
|
17
|
+
decimal: 3.34999999999514,
|
|
18
|
+
normalizedImplied: 0.298507462687,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
};
|
|
@@ -4,6 +4,7 @@ export const getLastPolledDataForBookmakers = () => {
|
|
|
4
4
|
const lastPolledData: LastPolledArray = [];
|
|
5
5
|
lastPolledData.push({ sportsbook: 'draftkings', timestamp: Date.now() });
|
|
6
6
|
lastPolledData.push({ sportsbook: 'bovada', timestamp: Date.now() });
|
|
7
|
+
lastPolledData.push({ sportsbook: 'superbet', timestamp: Date.now() });
|
|
7
8
|
return lastPolledData;
|
|
8
9
|
};
|
|
9
10
|
|
package/src/types/resolution.ts
CHANGED
|
@@ -352,6 +352,7 @@ export const HALVES_PERIOD_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
|
352
352
|
MarketTypeId.FIRST_PERIOD_SECONDARY_HOME_TEAM_SCORE,
|
|
353
353
|
MarketTypeId.FIRST_PERIOD_SECONDARY_AWAY_TEAM_SCORE,
|
|
354
354
|
MarketTypeId.CORRECT_SCORE_PERIOD_ONE,
|
|
355
|
+
MarketTypeId.DOUBLE_CHANCE_FIRST_PERIOD,
|
|
355
356
|
], // 1st half
|
|
356
357
|
2: [
|
|
357
358
|
MarketTypeId.SECOND_PERIOD_MONEYLINE,
|
|
@@ -369,6 +370,7 @@ export const HALVES_PERIOD_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
|
369
370
|
MarketTypeId.SECOND_PERIOD_SECONDARY_HOME_TEAM_SCORE,
|
|
370
371
|
MarketTypeId.SECOND_PERIOD_SECONDARY_AWAY_TEAM_SCORE,
|
|
371
372
|
MarketTypeId.CORRECT_SCORE_PERIOD_TWO,
|
|
373
|
+
MarketTypeId.DOUBLE_CHANCE_SECOND_PERIOD,
|
|
372
374
|
], // 2nd half
|
|
373
375
|
};
|
|
374
376
|
|
|
@@ -584,6 +586,7 @@ export const PERIOD_BASED_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
|
584
586
|
MarketTypeId.FIRST_PERIOD_AWAY_TEAM_SCORE,
|
|
585
587
|
MarketTypeId.CORRECT_SCORE_PERIOD_ONE,
|
|
586
588
|
MarketTypeId.FIRST_PERIOD_SCORE_SCORE,
|
|
589
|
+
MarketTypeId.DOUBLE_CHANCE_FIRST_PERIOD,
|
|
587
590
|
], // 1st period
|
|
588
591
|
2: [
|
|
589
592
|
MarketTypeId.SECOND_PERIOD_MONEYLINE,
|
|
@@ -597,6 +600,7 @@ export const PERIOD_BASED_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
|
597
600
|
MarketTypeId.SECOND_PERIOD_AWAY_TEAM_SCORE,
|
|
598
601
|
MarketTypeId.CORRECT_SCORE_PERIOD_TWO,
|
|
599
602
|
MarketTypeId.SECOND_PERIOD_SCORE_SCORE,
|
|
603
|
+
MarketTypeId.DOUBLE_CHANCE_SECOND_PERIOD,
|
|
600
604
|
], // 2nd period
|
|
601
605
|
3: [
|
|
602
606
|
MarketTypeId.THIRD_PERIOD_MONEYLINE,
|
package/src/utils/bookmakers.ts
CHANGED
|
@@ -204,7 +204,7 @@ export const checkOddsFromBookmakersForChildMarkets = (
|
|
|
204
204
|
odds: any,
|
|
205
205
|
leagueInfos: LeagueConfigInfo[],
|
|
206
206
|
oddsProviders: string[],
|
|
207
|
-
|
|
207
|
+
lastPolledData: LastPolledArray,
|
|
208
208
|
maxAllowedProviderDataStaleDelay: number,
|
|
209
209
|
maxImpliedPercentageDifference: number
|
|
210
210
|
): OddsWithLeagueInfo => {
|
|
@@ -212,20 +212,21 @@ export const checkOddsFromBookmakersForChildMarkets = (
|
|
|
212
212
|
const [sportsBookName, marketName, points, selection, selectionLine] = key.split('_');
|
|
213
213
|
const info = leagueInfos.find((leagueInfo) => leagueInfo.marketName.toLowerCase() === marketName.toLowerCase());
|
|
214
214
|
if (info) {
|
|
215
|
-
const
|
|
215
|
+
const bookmakers = getPrimaryAndSecondaryBookmakerForTypeId(
|
|
216
216
|
oddsProviders,
|
|
217
217
|
leagueInfos,
|
|
218
218
|
Number(info.typeId)
|
|
219
219
|
);
|
|
220
220
|
|
|
221
221
|
const isValidLastPolled = isLastPolledForBookmakersValid(
|
|
222
|
-
|
|
222
|
+
lastPolledData,
|
|
223
223
|
maxAllowedProviderDataStaleDelay,
|
|
224
|
-
|
|
225
|
-
secondaryBookmaker
|
|
224
|
+
bookmakers
|
|
226
225
|
);
|
|
227
226
|
|
|
228
227
|
if (isValidLastPolled) {
|
|
228
|
+
const primaryBookmaker = bookmakers[0];
|
|
229
|
+
const secondaryBookmaker = bookmakers[1];
|
|
229
230
|
if (primaryBookmaker && !secondaryBookmaker) {
|
|
230
231
|
if (sportsBookName.toLowerCase() === primaryBookmaker.toLowerCase()) {
|
|
231
232
|
acc.push(value);
|
|
@@ -267,7 +268,7 @@ export const getPrimaryAndSecondaryBookmakerForTypeId = (
|
|
|
267
268
|
defaultProviders: string[],
|
|
268
269
|
leagueInfos: LeagueConfigInfo[], // LeagueConfigInfo for specific sport, not the entire list from csv
|
|
269
270
|
typeId: number
|
|
270
|
-
):
|
|
271
|
+
): string[] => {
|
|
271
272
|
const info = leagueInfos.find((leagueInfo) => Number(leagueInfo.typeId) === typeId);
|
|
272
273
|
let primaryBookmaker = defaultProviders[0].toLowerCase();
|
|
273
274
|
let secondaryBookmaker = defaultProviders[1] ? defaultProviders[1].toLowerCase() : undefined;
|
|
@@ -277,43 +278,30 @@ export const getPrimaryAndSecondaryBookmakerForTypeId = (
|
|
|
277
278
|
secondaryBookmaker = info.secondaryBookmaker ? info.secondaryBookmaker.toLowerCase() : undefined;
|
|
278
279
|
}
|
|
279
280
|
}
|
|
280
|
-
return
|
|
281
|
+
return secondaryBookmaker ? [primaryBookmaker, secondaryBookmaker] : [primaryBookmaker];
|
|
281
282
|
};
|
|
282
283
|
|
|
283
284
|
export const isLastPolledForBookmakersValid = (
|
|
284
|
-
|
|
285
|
+
lastPolledData: LastPolledArray,
|
|
285
286
|
maxAllowedProviderDataStaleDelay: number,
|
|
286
|
-
|
|
287
|
-
secondaryBookmaker?: string
|
|
287
|
+
bookmakers: string[]
|
|
288
288
|
): boolean => {
|
|
289
|
-
const lastPolledTimePrimary = lastPolledMap.find(
|
|
290
|
-
(entry) => entry.sportsbook.toLowerCase() === primaryBookmaker.toLowerCase()
|
|
291
|
-
)?.timestamp;
|
|
292
|
-
if (typeof lastPolledTimePrimary !== 'number') {
|
|
293
|
-
return false;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
289
|
const now = new Date();
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
(entry) => entry.sportsbook.toLowerCase() ===
|
|
290
|
+
const isNotValid = bookmakers.some((bookmakerId) => {
|
|
291
|
+
const lastPolledTime = lastPolledData.find(
|
|
292
|
+
(entry) => entry.sportsbook.toLowerCase() === bookmakerId.toLowerCase()
|
|
300
293
|
)?.timestamp;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return false;
|
|
294
|
+
if (typeof lastPolledTime !== 'number') {
|
|
295
|
+
return true;
|
|
304
296
|
}
|
|
305
|
-
|
|
306
|
-
const oddsDate = new Date(lastPolledTimeSecondary * 1000);
|
|
297
|
+
const oddsDate = new Date(lastPolledTime * 1000);
|
|
307
298
|
const timeDiff = now.getTime() - oddsDate.getTime();
|
|
308
299
|
if (timeDiff > maxAllowedProviderDataStaleDelay) {
|
|
309
|
-
return
|
|
300
|
+
return true;
|
|
310
301
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const timeDiff = now.getTime() - oddsDate.getTime();
|
|
315
|
-
|
|
316
|
-
return timeDiff <= maxAllowedProviderDataStaleDelay;
|
|
302
|
+
return false;
|
|
303
|
+
});
|
|
304
|
+
return !isNotValid;
|
|
317
305
|
};
|
|
318
306
|
|
|
319
307
|
export const calculateImpliedOddsDifference = (impliedOddsA: number, impliedOddsB: number): number => {
|
package/src/utils/odds.ts
CHANGED
|
@@ -135,7 +135,7 @@ export const getParentOdds = (
|
|
|
135
135
|
) => {
|
|
136
136
|
const commonData = { homeTeam: oddsApiObject.homeTeam, awayTeam: oddsApiObject.awayTeam };
|
|
137
137
|
|
|
138
|
-
const
|
|
138
|
+
const bookmakers = getPrimaryAndSecondaryBookmakerForTypeId(
|
|
139
139
|
liveOddsProviders,
|
|
140
140
|
leagueInfo,
|
|
141
141
|
0 // typeId for moneyline
|
|
@@ -144,8 +144,7 @@ export const getParentOdds = (
|
|
|
144
144
|
const isValidLastPolled = isLastPolledForBookmakersValid(
|
|
145
145
|
lastPolledData,
|
|
146
146
|
maxAllowedProviderDataStaleDelay,
|
|
147
|
-
|
|
148
|
-
secondaryBookmaker
|
|
147
|
+
bookmakers
|
|
149
148
|
);
|
|
150
149
|
|
|
151
150
|
if (!isValidLastPolled) {
|
|
@@ -159,7 +158,7 @@ export const getParentOdds = (
|
|
|
159
158
|
const moneylineOddsMap = filterOddsByMarketNameTeamNameBookmaker(
|
|
160
159
|
oddsApiObject.odds,
|
|
161
160
|
MoneylineTypes.MONEYLINE,
|
|
162
|
-
|
|
161
|
+
bookmakers,
|
|
163
162
|
commonData,
|
|
164
163
|
isTwoPositionalSport
|
|
165
164
|
);
|
|
@@ -167,7 +166,7 @@ export const getParentOdds = (
|
|
|
167
166
|
// CHECKING AND COMPARING ODDS FOR THE GIVEN BOOKMAKERS
|
|
168
167
|
const oddsObject = checkOddsFromBookmakers(
|
|
169
168
|
moneylineOddsMap,
|
|
170
|
-
|
|
169
|
+
bookmakers,
|
|
171
170
|
isTwoPositionalSport,
|
|
172
171
|
maxPercentageDiffBetwenOdds,
|
|
173
172
|
MIN_ODDS_FOR_DIFF_CHECKING
|