overtime-live-trading-utils 3.0.0-rc.3 → 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/main.js +1 -1
- package/package.json +2 -2
- package/src/constants/common.ts +1 -1
- package/src/tests/unit/bookmakers.test.ts +18 -7
- package/src/tests/unit/markets.test.ts +44 -7
- package/src/tests/unit/odds.test.ts +14 -5
- package/src/tests/unit/spread.test.ts +16 -6
- package/src/tests/utils/helper.ts +8 -0
- package/src/utils/markets.ts +4 -2
- package/src/utils/odds.ts +29 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "overtime-live-trading-utils",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2-rc.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@types/node": "^20.8.10",
|
|
16
16
|
"oddslib": "^2.1.1",
|
|
17
|
-
"overtime-utils": "^0.1.
|
|
17
|
+
"overtime-utils": "^0.1.50",
|
|
18
18
|
"react": "^17.0.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
package/src/constants/common.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const ZERO = 0;
|
|
2
2
|
export const DRAW = 'Draw';
|
|
3
3
|
export const MONEYLINE_TYPE_ID = 0;
|
|
4
|
-
export const MIN_ODDS_FOR_DIFF_CHECKING = 0.
|
|
4
|
+
export const MIN_ODDS_FOR_DIFF_CHECKING = 0.1;
|
|
5
5
|
export const MAX_IMPLIED_PERCENTAGE_DIFF = 20; // 20%
|
|
6
6
|
export const TAG_CHILD_SPREAD = 10001;
|
|
7
7
|
export const TAG_CHILD_TOTALS = 10002;
|
|
@@ -10,9 +10,14 @@ import {
|
|
|
10
10
|
MockOnlyMoneylineWithDifferentSportsbook,
|
|
11
11
|
} from '../mock/MockOpticSoccer';
|
|
12
12
|
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
13
|
-
import {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
package/src/utils/markets.ts
CHANGED
|
@@ -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
|
@@ -141,9 +141,6 @@ export const getParentOdds = (
|
|
|
141
141
|
0 // typeId for moneyline
|
|
142
142
|
);
|
|
143
143
|
|
|
144
|
-
console.log('defaultProviders', liveOddsProviders);
|
|
145
|
-
console.log('bookmakers for moneyline', bookmakers);
|
|
146
|
-
|
|
147
144
|
const isValidLastPolled = isLastPolledForBookmakersValid(
|
|
148
145
|
lastPolledData,
|
|
149
146
|
maxAllowedProviderDataStaleDelay,
|
|
@@ -217,7 +214,8 @@ export const createChildMarkets: (
|
|
|
217
214
|
leagueMap: any,
|
|
218
215
|
lastPolledData: LastPolledArray,
|
|
219
216
|
maxAllowedProviderDataStaleDelay: number,
|
|
220
|
-
maxImpliedPercentageDifference: number
|
|
217
|
+
maxImpliedPercentageDifference: number,
|
|
218
|
+
playersMap: Map<string, number>
|
|
221
219
|
) => ChildMarket[] = (
|
|
222
220
|
apiResponseWithOdds,
|
|
223
221
|
spreadDataForSport,
|
|
@@ -227,7 +225,8 @@ export const createChildMarkets: (
|
|
|
227
225
|
leagueMap,
|
|
228
226
|
lastPolledData,
|
|
229
227
|
maxAllowedProviderDataStaleDelay,
|
|
230
|
-
maxImpliedPercentageDifference
|
|
228
|
+
maxImpliedPercentageDifference,
|
|
229
|
+
playersMap
|
|
231
230
|
) => {
|
|
232
231
|
const [spreadOdds, totalOdds, moneylineOdds, correctScoreOdds, doubleChanceOdds, ggOdds, childMarkets]: any[] = [
|
|
233
232
|
[],
|
|
@@ -245,7 +244,7 @@ export const createChildMarkets: (
|
|
|
245
244
|
};
|
|
246
245
|
|
|
247
246
|
if (leagueInfo.length > 0) {
|
|
248
|
-
const allChildOdds =
|
|
247
|
+
const allChildOdds = filterOdds(apiResponseWithOdds.odds, leagueInfo, playersMap);
|
|
249
248
|
const checkedChildOdds = checkOddsFromBookmakersForChildMarkets(
|
|
250
249
|
allChildOdds,
|
|
251
250
|
leagueInfo,
|
|
@@ -272,7 +271,7 @@ export const createChildMarkets: (
|
|
|
272
271
|
|
|
273
272
|
const homeAwayFormattedOdds = [
|
|
274
273
|
...groupAndFormatSpreadOdds(spreadOdds, commonData),
|
|
275
|
-
...groupAndFormatTotalOdds(totalOdds, commonData),
|
|
274
|
+
...groupAndFormatTotalOdds(totalOdds, commonData), // playerProps are handled inside this function
|
|
276
275
|
...groupAndFormatMoneylineOdds(moneylineOdds, commonData),
|
|
277
276
|
...groupAndFormatGGOdds(ggOdds),
|
|
278
277
|
...groupAndFormatDoubleChanceOdds(doubleChanceOdds, commonData),
|
|
@@ -287,12 +286,20 @@ export const createChildMarkets: (
|
|
|
287
286
|
);
|
|
288
287
|
|
|
289
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
|
+
}
|
|
290
296
|
const childMarket = {
|
|
291
297
|
leagueId: Number(data.sportId),
|
|
292
298
|
typeId: Number(data.typeId),
|
|
293
299
|
type: MarketTypeMap[data.typeId as MarketType]?.key || '',
|
|
294
300
|
line: Number(data.line || 0),
|
|
295
301
|
odds: data.odds,
|
|
302
|
+
playerProps,
|
|
296
303
|
};
|
|
297
304
|
const leagueInfoByTypeId = leagueInfo.find((league) => Number(league.typeId) === Number(data.typeId));
|
|
298
305
|
const minOdds = leagueInfoByTypeId?.minOdds; // minimum odds configured for child market (e.g. 0.95 implied probability)
|
|
@@ -346,7 +353,7 @@ export const createChildMarkets: (
|
|
|
346
353
|
* @param {string} oddsProvider - The main odds provider to filter by.
|
|
347
354
|
* @returns {Array} The filtered odds array.
|
|
348
355
|
*/
|
|
349
|
-
export const
|
|
356
|
+
export const filterOdds = (oddsArray: Odds, leagueInfos: LeagueConfigInfo[], playersMap: Map<string, number>): any => {
|
|
350
357
|
const allChildMarketsTypes = leagueInfos
|
|
351
358
|
.filter(
|
|
352
359
|
(leagueInfo) =>
|
|
@@ -356,7 +363,10 @@ export const filterOddsByMarketNameBookmaker = (oddsArray: Odds, leagueInfos: Le
|
|
|
356
363
|
.map((leagueInfo) => leagueInfo.marketName.toLowerCase());
|
|
357
364
|
return oddsArray.reduce((acc: any, odd: any) => {
|
|
358
365
|
if (allChildMarketsTypes.includes(odd.marketName.toLowerCase())) {
|
|
359
|
-
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
|
+
}
|
|
360
370
|
const key = `${sportsBookName.toLowerCase()}_${marketName.toLowerCase()}_${points}_${selection}_${selectionLine}`;
|
|
361
371
|
acc[key] = {
|
|
362
372
|
...odd,
|
|
@@ -443,6 +453,13 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
|
|
|
443
453
|
acc[key].typeId = odd.typeId;
|
|
444
454
|
acc[key].type = odd.type;
|
|
445
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
|
+
}
|
|
446
463
|
}
|
|
447
464
|
|
|
448
465
|
return acc;
|
|
@@ -450,8 +467,8 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
|
|
|
450
467
|
|
|
451
468
|
// Format the grouped odds into the desired output
|
|
452
469
|
const formattedOdds = Object.entries(groupedOdds as any).reduce((acc: any, [key, value]) => {
|
|
453
|
-
const [_marketName, selection,
|
|
454
|
-
const line = parseFloat(
|
|
470
|
+
const [_marketName, selection, points] = key.split('_');
|
|
471
|
+
const line = parseFloat(points);
|
|
455
472
|
|
|
456
473
|
// if we have away team in total odds we know the market is team total and we need to increase typeId by one.
|
|
457
474
|
// if this is false typeId is already mapped correctly
|
|
@@ -463,6 +480,7 @@ export const groupAndFormatTotalOdds = (oddsArray: any[], commonData: HomeAwayTe
|
|
|
463
480
|
typeId: !isAwayTeam ? (value as any).typeId : Number((value as any).typeId) + 1,
|
|
464
481
|
sportId: (value as any).sportId,
|
|
465
482
|
type: (value as any).type,
|
|
483
|
+
playerProps: (value as any).playerProps,
|
|
466
484
|
});
|
|
467
485
|
}
|
|
468
486
|
return acc;
|