overtime-live-trading-utils 4.0.4 → 4.0.5-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/main.js +1 -1
- package/package.json +1 -1
- package/src/enums/sports.ts +9 -0
- package/src/tests/mock/MockLeagueMap.ts +17 -16
- package/src/types/sports.ts +4 -1
- package/src/utils/bookmakers.ts +10 -8
- package/src/utils/markets.ts +2 -2
- package/src/utils/odds.ts +10 -10
package/package.json
CHANGED
package/src/enums/sports.ts
CHANGED
|
@@ -66,6 +66,15 @@ export enum MoneylineTypes {
|
|
|
66
66
|
MONEYLINE = 'Moneyline',
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
export enum ChildMarketType {
|
|
70
|
+
TOTAL = 'Total',
|
|
71
|
+
SPREAD = 'Spread',
|
|
72
|
+
MONEYLINE = 'Moneyline',
|
|
73
|
+
CORRECT_SCORE = 'Correct Score',
|
|
74
|
+
DOUBLE_CHANCE = 'Double Chance',
|
|
75
|
+
BOTH_TEAMS_TO_SCORE = 'Both Teams To Score',
|
|
76
|
+
}
|
|
77
|
+
|
|
69
78
|
export enum SpreadTypes {
|
|
70
79
|
ASIAN_HANDICAP = 'Asian Handicap',
|
|
71
80
|
GAME_SPREAD = 'Game Spread',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ChildMarketType } from '../../enums/sports';
|
|
1
2
|
import { LeagueConfigInfo } from '../../types/sports';
|
|
2
3
|
|
|
3
4
|
const baseLeagueInfo: LeagueConfigInfo = {
|
|
@@ -5,7 +6,7 @@ const baseLeagueInfo: LeagueConfigInfo = {
|
|
|
5
6
|
enabled: 'true',
|
|
6
7
|
marketName: 'Moneyline',
|
|
7
8
|
typeId: 0,
|
|
8
|
-
type:
|
|
9
|
+
type: ChildMarketType.MONEYLINE,
|
|
9
10
|
maxOdds: 0.25,
|
|
10
11
|
minOdds: 0.75,
|
|
11
12
|
};
|
|
@@ -15,7 +16,7 @@ const baseLeagueInfoNba: LeagueConfigInfo = {
|
|
|
15
16
|
enabled: 'true',
|
|
16
17
|
marketName: 'Moneyline',
|
|
17
18
|
typeId: 0,
|
|
18
|
-
type:
|
|
19
|
+
type: ChildMarketType.MONEYLINE,
|
|
19
20
|
maxOdds: 0.25,
|
|
20
21
|
minOdds: 0.75,
|
|
21
22
|
};
|
|
@@ -25,7 +26,7 @@ const spreadMock: LeagueConfigInfo = {
|
|
|
25
26
|
enabled: 'true',
|
|
26
27
|
marketName: 'Goal Spread',
|
|
27
28
|
typeId: 10001,
|
|
28
|
-
type:
|
|
29
|
+
type: ChildMarketType.SPREAD,
|
|
29
30
|
maxOdds: 0.25,
|
|
30
31
|
minOdds: 0.75,
|
|
31
32
|
};
|
|
@@ -35,7 +36,7 @@ const totalMock: LeagueConfigInfo = {
|
|
|
35
36
|
enabled: 'true',
|
|
36
37
|
marketName: 'Total Goals',
|
|
37
38
|
typeId: 10002,
|
|
38
|
-
type:
|
|
39
|
+
type: ChildMarketType.TOTAL,
|
|
39
40
|
maxOdds: 0.25,
|
|
40
41
|
minOdds: 0.75,
|
|
41
42
|
};
|
|
@@ -45,7 +46,7 @@ const doubleChanceMock: LeagueConfigInfo = {
|
|
|
45
46
|
enabled: 'true',
|
|
46
47
|
marketName: 'Double Chance',
|
|
47
48
|
typeId: 10003,
|
|
48
|
-
type:
|
|
49
|
+
type: ChildMarketType.DOUBLE_CHANCE,
|
|
49
50
|
maxOdds: 0.01,
|
|
50
51
|
minOdds: 0.99,
|
|
51
52
|
};
|
|
@@ -55,7 +56,7 @@ const correctScoreMock: LeagueConfigInfo = {
|
|
|
55
56
|
enabled: 'true',
|
|
56
57
|
marketName: 'Correct Score',
|
|
57
58
|
typeId: 10100,
|
|
58
|
-
type:
|
|
59
|
+
type: ChildMarketType.CORRECT_SCORE,
|
|
59
60
|
maxOdds: 0.25,
|
|
60
61
|
minOdds: 0.75,
|
|
61
62
|
};
|
|
@@ -65,7 +66,7 @@ const childMoneylineMock: LeagueConfigInfo = {
|
|
|
65
66
|
enabled: 'true',
|
|
66
67
|
marketName: '1st Half Moneyline',
|
|
67
68
|
typeId: 10022,
|
|
68
|
-
type:
|
|
69
|
+
type: ChildMarketType.MONEYLINE,
|
|
69
70
|
maxOdds: 0.25,
|
|
70
71
|
minOdds: 0.75,
|
|
71
72
|
};
|
|
@@ -75,7 +76,7 @@ const bothTeamsToScoreMock: LeagueConfigInfo = {
|
|
|
75
76
|
enabled: 'true',
|
|
76
77
|
marketName: 'Both Teams To Score',
|
|
77
78
|
typeId: 10009,
|
|
78
|
-
type:
|
|
79
|
+
type: ChildMarketType.BOTH_TEAMS_TO_SCORE,
|
|
79
80
|
maxOdds: 0.01,
|
|
80
81
|
minOdds: 0.99,
|
|
81
82
|
};
|
|
@@ -85,7 +86,7 @@ const bothTeamsToScoreMock1stHalf: LeagueConfigInfo = {
|
|
|
85
86
|
enabled: 'true',
|
|
86
87
|
marketName: '1st Half Both Teams To Score',
|
|
87
88
|
typeId: 10101,
|
|
88
|
-
type:
|
|
89
|
+
type: ChildMarketType.BOTH_TEAMS_TO_SCORE,
|
|
89
90
|
maxOdds: 0.01,
|
|
90
91
|
minOdds: 0.99,
|
|
91
92
|
};
|
|
@@ -95,7 +96,7 @@ const bothTeamsToScoreMock2ndHalf: LeagueConfigInfo = {
|
|
|
95
96
|
enabled: 'true',
|
|
96
97
|
marketName: '2nd Half Both Teams To Score',
|
|
97
98
|
typeId: 10102,
|
|
98
|
-
type:
|
|
99
|
+
type: ChildMarketType.BOTH_TEAMS_TO_SCORE,
|
|
99
100
|
maxOdds: 0.01,
|
|
100
101
|
minOdds: 0.99,
|
|
101
102
|
};
|
|
@@ -105,7 +106,7 @@ const drawNoBetMock: LeagueConfigInfo = {
|
|
|
105
106
|
enabled: 'true',
|
|
106
107
|
marketName: 'Draw No Bet',
|
|
107
108
|
typeId: 10010,
|
|
108
|
-
type:
|
|
109
|
+
type: ChildMarketType.MONEYLINE,
|
|
109
110
|
maxOdds: 0.01,
|
|
110
111
|
minOdds: 0.99,
|
|
111
112
|
};
|
|
@@ -115,7 +116,7 @@ const willThereBeOvertime: LeagueConfigInfo = {
|
|
|
115
116
|
enabled: 'true',
|
|
116
117
|
marketName: 'Will There Be Overtime',
|
|
117
118
|
typeId: 10131,
|
|
118
|
-
type:
|
|
119
|
+
type: ChildMarketType.BOTH_TEAMS_TO_SCORE,
|
|
119
120
|
maxOdds: 0.01,
|
|
120
121
|
minOdds: 0.99,
|
|
121
122
|
};
|
|
@@ -125,7 +126,7 @@ const teamTotal: LeagueConfigInfo = {
|
|
|
125
126
|
enabled: 'true',
|
|
126
127
|
marketName: 'Team Total',
|
|
127
128
|
typeId: 10017,
|
|
128
|
-
type:
|
|
129
|
+
type: ChildMarketType.TOTAL,
|
|
129
130
|
maxOdds: 0.25,
|
|
130
131
|
minOdds: 0.75,
|
|
131
132
|
primaryBookmaker: 'draftkings',
|
|
@@ -138,7 +139,7 @@ const PlayerAssist: LeagueConfigInfo[] = [
|
|
|
138
139
|
enabled: 'true',
|
|
139
140
|
marketName: 'Player Assists',
|
|
140
141
|
typeId: 11039,
|
|
141
|
-
type:
|
|
142
|
+
type: ChildMarketType.TOTAL,
|
|
142
143
|
maxOdds: 0.25,
|
|
143
144
|
minOdds: 0.75,
|
|
144
145
|
primaryBookmaker: 'superbet',
|
|
@@ -152,7 +153,7 @@ const PlayerAssistWithSecondaryBookmaker: LeagueConfigInfo[] = [
|
|
|
152
153
|
enabled: 'true',
|
|
153
154
|
marketName: 'Player Assists',
|
|
154
155
|
typeId: 11039,
|
|
155
|
-
type:
|
|
156
|
+
type: ChildMarketType.TOTAL,
|
|
156
157
|
maxOdds: 0.25,
|
|
157
158
|
minOdds: 0.75,
|
|
158
159
|
primaryBookmaker: 'superbet',
|
|
@@ -165,7 +166,7 @@ const teamTotal2: LeagueConfigInfo = {
|
|
|
165
166
|
enabled: 'true',
|
|
166
167
|
marketName: 'Team Total',
|
|
167
168
|
typeId: 10018,
|
|
168
|
-
type:
|
|
169
|
+
type: ChildMarketType.TOTAL,
|
|
169
170
|
maxOdds: 0.25,
|
|
170
171
|
minOdds: 0.75,
|
|
171
172
|
primaryBookmaker: 'draftkings',
|
package/src/types/sports.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { ChildMarketType } from '../enums/sports';
|
|
2
|
+
|
|
1
3
|
export type LeagueConfigInfo = {
|
|
2
4
|
sportId: number;
|
|
3
5
|
typeId: number;
|
|
4
6
|
marketName: string;
|
|
5
|
-
type:
|
|
7
|
+
type: ChildMarketType;
|
|
6
8
|
enabled: string;
|
|
7
9
|
minOdds: number;
|
|
8
10
|
maxOdds: number;
|
|
9
11
|
addedSpread?: number;
|
|
10
12
|
primaryBookmaker?: string;
|
|
11
13
|
secondaryBookmaker?: string;
|
|
14
|
+
percentageDiffForLines?: number;
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
export type ChildMarket = {
|
package/src/utils/bookmakers.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ZERO_ODDS_MESSAGE,
|
|
5
5
|
ZERO_ODDS_MESSAGE_SINGLE_BOOKMAKER,
|
|
6
6
|
} from '../constants/errors';
|
|
7
|
+
import { ChildMarketType } from '../enums/sports';
|
|
7
8
|
import { BookmakersConfig } from '../types/bookmakers';
|
|
8
9
|
import { Anchor, OddsWithLeagueInfo } from '../types/odds';
|
|
9
10
|
import { LastPolledArray, LeagueConfigInfo } from '../types/sports';
|
|
@@ -157,7 +158,7 @@ export const checkOddsFromBookmakersForChildMarkets = (
|
|
|
157
158
|
lastPolledData: LastPolledArray,
|
|
158
159
|
maxAllowedProviderDataStaleDelay: number,
|
|
159
160
|
anchors: Anchor[],
|
|
160
|
-
|
|
161
|
+
maxPercentageDiffForLines: number
|
|
161
162
|
): OddsWithLeagueInfo => {
|
|
162
163
|
const formattedOdds = Object.entries(odds as any).reduce((acc: any, [key, value]: [string, any]) => {
|
|
163
164
|
const [sportsBookName, marketName, points, selection, selectionLine] = key.split('_');
|
|
@@ -197,9 +198,12 @@ export const checkOddsFromBookmakersForChildMarkets = (
|
|
|
197
198
|
|
|
198
199
|
acc.push(value);
|
|
199
200
|
} else {
|
|
200
|
-
// if
|
|
201
|
-
if (
|
|
202
|
-
const steps = getStepsForPointAdjustment(
|
|
201
|
+
// if the market is Total or Spread and we didnt find the correct line, try adjusting points by steps defined and search again
|
|
202
|
+
if (info.type === ChildMarketType.SPREAD || info.type === ChildMarketType.TOTAL) {
|
|
203
|
+
const steps = getStepsForPointAdjustment(
|
|
204
|
+
Number(points),
|
|
205
|
+
info.percentageDiffForLines ?? maxPercentageDiffForLines // use the value defined in csv if available, else use default from env variable
|
|
206
|
+
);
|
|
203
207
|
for (const step of steps) {
|
|
204
208
|
const adjustedPoints = (Number(points) + step).toString();
|
|
205
209
|
|
|
@@ -317,14 +321,12 @@ const shouldBlockOdds = (ourOdds: number, otherOdds: number, anchors: Anchor[])
|
|
|
317
321
|
};
|
|
318
322
|
|
|
319
323
|
const getStepsForPointAdjustment = (points: number, percentageDiffForPPLines: number): number[] => {
|
|
320
|
-
const stepsDelta = Math.round((points * percentageDiffForPPLines) / 100);
|
|
324
|
+
const stepsDelta = Math.round((points * percentageDiffForPPLines) / 100);
|
|
321
325
|
const steps: number[] = [];
|
|
322
|
-
for (let index =
|
|
326
|
+
for (let index = 0.5; index <= stepsDelta; index += 0.5) {
|
|
323
327
|
steps.push(-index, index);
|
|
324
328
|
}
|
|
325
|
-
|
|
326
329
|
return steps;
|
|
327
330
|
};
|
|
328
|
-
|
|
329
331
|
// Export only when running tests
|
|
330
332
|
export const __test__ = { getRequiredOtherOdds, shouldBlockOdds };
|
package/src/utils/markets.ts
CHANGED
|
@@ -30,7 +30,7 @@ export const processMarket = (
|
|
|
30
30
|
lastPolledData: LastPolledArray,
|
|
31
31
|
maxAllowedProviderDataStaleDelay: number,
|
|
32
32
|
playersMap: Map<string, number>,
|
|
33
|
-
|
|
33
|
+
maxPercentageDiffForLines: number
|
|
34
34
|
) => {
|
|
35
35
|
const leagueInfo = getLeagueInfo(market.leagueId, leagueMap);
|
|
36
36
|
|
|
@@ -85,7 +85,7 @@ export const processMarket = (
|
|
|
85
85
|
maxAllowedProviderDataStaleDelay,
|
|
86
86
|
anchors,
|
|
87
87
|
playersMap,
|
|
88
|
-
|
|
88
|
+
maxPercentageDiffForLines
|
|
89
89
|
);
|
|
90
90
|
|
|
91
91
|
const packedChildMarkets = childMarkets.map((childMarket: any) => {
|
package/src/utils/odds.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as oddslib from 'oddslib';
|
|
|
2
2
|
import { isOneSideExtendedPlayerPropsMarket, MarketType, MarketTypeMap } from 'overtime-utils';
|
|
3
3
|
import { DRAW, ZERO } from '../constants/common';
|
|
4
4
|
import { LAST_POLLED_TOO_OLD, NO_MARKETS_FOR_LEAGUE_ID } from '../constants/errors';
|
|
5
|
-
import { MoneylineTypes } from '../enums/sports';
|
|
5
|
+
import { ChildMarketType, MoneylineTypes } from '../enums/sports';
|
|
6
6
|
import { Anchor, HomeAwayTeams, Odds, OddsObject } from '../types/odds';
|
|
7
7
|
import { ChildMarket, LastPolledArray, LeagueConfigInfo } from '../types/sports';
|
|
8
8
|
import {
|
|
@@ -238,17 +238,17 @@ export const createChildMarkets: (
|
|
|
238
238
|
maxPercentageDiffForPPLines
|
|
239
239
|
);
|
|
240
240
|
checkedChildOdds.forEach((odd) => {
|
|
241
|
-
if (odd.type ===
|
|
241
|
+
if (odd.type === ChildMarketType.TOTAL) {
|
|
242
242
|
if (Math.abs(Number(odd.points) % 1) === 0.5) totalOdds.push(odd);
|
|
243
|
-
} else if (odd.type ===
|
|
243
|
+
} else if (odd.type === ChildMarketType.SPREAD) {
|
|
244
244
|
if (Math.abs(Number(odd.points) % 1) === 0.5) spreadOdds.push(odd);
|
|
245
|
-
} else if (odd.type ===
|
|
245
|
+
} else if (odd.type === ChildMarketType.MONEYLINE) {
|
|
246
246
|
moneylineOdds.push(odd);
|
|
247
|
-
} else if (odd.type ===
|
|
247
|
+
} else if (odd.type === ChildMarketType.CORRECT_SCORE) {
|
|
248
248
|
correctScoreOdds.push(odd);
|
|
249
|
-
} else if (odd.type ===
|
|
249
|
+
} else if (odd.type === ChildMarketType.DOUBLE_CHANCE) {
|
|
250
250
|
doubleChanceOdds.push(odd);
|
|
251
|
-
} else if (odd.type ===
|
|
251
|
+
} else if (odd.type === ChildMarketType.BOTH_TEAMS_TO_SCORE) {
|
|
252
252
|
ggOdds.push(odd);
|
|
253
253
|
}
|
|
254
254
|
});
|
|
@@ -294,7 +294,7 @@ export const createChildMarkets: (
|
|
|
294
294
|
const maxOdds = leagueInfoByTypeId?.maxOdds; // maximum odds configured for child market (e.g. 0.05 implied probability)
|
|
295
295
|
|
|
296
296
|
if (minOdds && maxOdds) {
|
|
297
|
-
const allowZeroOdds = [
|
|
297
|
+
const allowZeroOdds = [ChildMarketType.TOTAL].includes(data.type);
|
|
298
298
|
const conditionToAddChildMarket = data.odds.every(
|
|
299
299
|
(odd: number) => (odd < minOdds && odd > maxOdds) || (allowZeroOdds && odd === ZERO)
|
|
300
300
|
);
|
|
@@ -875,7 +875,7 @@ export const groupAndFormatCorrectScoreOdds = (oddsArray: any[], commonData: Hom
|
|
|
875
875
|
line: 0,
|
|
876
876
|
positionNames: positionNames,
|
|
877
877
|
odds: Object.values(oddsMap),
|
|
878
|
-
type: odds?.[0]?.type ? odds[0].type :
|
|
878
|
+
type: odds?.[0]?.type ? odds[0].type : ChildMarketType.CORRECT_SCORE,
|
|
879
879
|
typeId: Number(typeId),
|
|
880
880
|
sportId: odds?.[0]?.sportId ? odds[0].sportId : undefined,
|
|
881
881
|
};
|
|
@@ -924,7 +924,7 @@ export const groupAndFormatDoubleChanceOdds = (oddsArray: any[], commonData: Hom
|
|
|
924
924
|
awayTeam: commonData.awayTeam,
|
|
925
925
|
line: 0,
|
|
926
926
|
odds: [probability1X, probability12, probabilityX2],
|
|
927
|
-
type:
|
|
927
|
+
type: ChildMarketType.DOUBLE_CHANCE,
|
|
928
928
|
typeId: 10003,
|
|
929
929
|
sportId: sportId,
|
|
930
930
|
};
|