overtime-live-trading-utils 2.1.22 → 2.1.23

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.
Files changed (38) hide show
  1. package/.circleci/config.yml +32 -32
  2. package/.prettierrc +9 -9
  3. package/CLAUDE.md +77 -0
  4. package/codecov.yml +20 -20
  5. package/index.ts +26 -26
  6. package/jest.config.ts +16 -16
  7. package/main.js +1 -1
  8. package/package.json +30 -30
  9. package/resolution_live_markets.md +351 -0
  10. package/src/constants/common.ts +7 -7
  11. package/src/constants/errors.ts +6 -6
  12. package/src/constants/sports.ts +78 -78
  13. package/src/enums/sports.ts +109 -109
  14. package/src/tests/mock/MockLeagueMap.ts +170 -170
  15. package/src/tests/mock/MockOpticOddsEvents.ts +518 -518
  16. package/src/tests/mock/MockOpticSoccer.ts +9378 -9378
  17. package/src/tests/mock/MockSoccerRedis.ts +2308 -2308
  18. package/src/tests/unit/bookmakers.test.ts +79 -79
  19. package/src/tests/unit/markets.test.ts +156 -156
  20. package/src/tests/unit/odds.test.ts +92 -92
  21. package/src/tests/unit/resolution.test.ts +935 -1043
  22. package/src/tests/unit/sports.test.ts +58 -58
  23. package/src/tests/unit/spread.test.ts +131 -131
  24. package/src/types/missing-types.d.ts +2 -2
  25. package/src/types/odds.ts +61 -61
  26. package/src/types/resolution.ts +96 -96
  27. package/src/types/sports.ts +19 -19
  28. package/src/utils/bookmakers.ts +159 -159
  29. package/src/utils/constraints.ts +210 -210
  30. package/src/utils/gameMatching.ts +81 -81
  31. package/src/utils/markets.ts +119 -119
  32. package/src/utils/odds.ts +674 -674
  33. package/src/utils/opticOdds.ts +71 -71
  34. package/src/utils/resolution.ts +275 -229
  35. package/src/utils/sports.ts +51 -51
  36. package/src/utils/spread.ts +97 -97
  37. package/tsconfig.json +16 -16
  38. package/webpack.config.js +24 -24
@@ -1,51 +1,51 @@
1
- import { League } from 'overtime-utils';
2
- import { LeagueConfigInfo } from '../types/sports';
3
-
4
- // Methods are using data from live-markets-map.csv
5
- export const getLiveSupportedLeagues = (leagueInfoArray: LeagueConfigInfo[]) => {
6
- const uniqueId = new Set();
7
- leagueInfoArray
8
- .filter((leagueInfo) => leagueInfo.enabled === 'true')
9
- .map((league) => uniqueId.add(Number(league.sportId)));
10
- return Array.from(uniqueId);
11
- };
12
-
13
- export const getBetTypesForLeague = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
14
- const uniqueMarketNames = new Set();
15
- leagueInfoArray
16
- .filter((leagueInfo) => Number(leagueInfo.sportId) === Number(league) && leagueInfo.enabled === 'true')
17
- .map((leagueInfo) => uniqueMarketNames.add(leagueInfo.marketName));
18
-
19
- return Array.from(uniqueMarketNames) as string[];
20
- };
21
-
22
- export const getLeagueInfo = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
23
- const leagueInfos = leagueInfoArray.filter((leagueInfo) => Number(leagueInfo.sportId) === league);
24
- return leagueInfos;
25
- };
26
-
27
- export const getLeagueSpreadTypes = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
28
- const betTypes = leagueInfoArray
29
- .filter(
30
- (leagueInfo) =>
31
- Number(leagueInfo.sportId) === Number(league) &&
32
- leagueInfo.type === 'Spread' &&
33
- leagueInfo.enabled === 'true'
34
- )
35
- .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
36
-
37
- return betTypes;
38
- };
39
-
40
- export const getLeagueTotalTypes = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
41
- const betTypes = leagueInfoArray
42
- .filter(
43
- (leagueInfo) =>
44
- Number(leagueInfo.sportId) === Number(league) &&
45
- leagueInfo.type === 'Total' &&
46
- leagueInfo.enabled === 'true'
47
- )
48
- .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
49
-
50
- return betTypes;
51
- };
1
+ import { League } from 'overtime-utils';
2
+ import { LeagueConfigInfo } from '../types/sports';
3
+
4
+ // Methods are using data from live-markets-map.csv
5
+ export const getLiveSupportedLeagues = (leagueInfoArray: LeagueConfigInfo[]) => {
6
+ const uniqueId = new Set();
7
+ leagueInfoArray
8
+ .filter((leagueInfo) => leagueInfo.enabled === 'true')
9
+ .map((league) => uniqueId.add(Number(league.sportId)));
10
+ return Array.from(uniqueId);
11
+ };
12
+
13
+ export const getBetTypesForLeague = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
14
+ const uniqueMarketNames = new Set();
15
+ leagueInfoArray
16
+ .filter((leagueInfo) => Number(leagueInfo.sportId) === Number(league) && leagueInfo.enabled === 'true')
17
+ .map((leagueInfo) => uniqueMarketNames.add(leagueInfo.marketName));
18
+
19
+ return Array.from(uniqueMarketNames) as string[];
20
+ };
21
+
22
+ export const getLeagueInfo = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
23
+ const leagueInfos = leagueInfoArray.filter((leagueInfo) => Number(leagueInfo.sportId) === league);
24
+ return leagueInfos;
25
+ };
26
+
27
+ export const getLeagueSpreadTypes = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
28
+ const betTypes = leagueInfoArray
29
+ .filter(
30
+ (leagueInfo) =>
31
+ Number(leagueInfo.sportId) === Number(league) &&
32
+ leagueInfo.type === 'Spread' &&
33
+ leagueInfo.enabled === 'true'
34
+ )
35
+ .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
36
+
37
+ return betTypes;
38
+ };
39
+
40
+ export const getLeagueTotalTypes = (league: League, leagueInfoArray: LeagueConfigInfo[]) => {
41
+ const betTypes = leagueInfoArray
42
+ .filter(
43
+ (leagueInfo) =>
44
+ Number(leagueInfo.sportId) === Number(league) &&
45
+ leagueInfo.type === 'Total' &&
46
+ leagueInfo.enabled === 'true'
47
+ )
48
+ .map((leagueInfo) => leagueInfo.marketName.toLowerCase());
49
+
50
+ return betTypes;
51
+ };
@@ -1,97 +1,97 @@
1
- import { LeagueConfigInfo } from '../types/sports';
2
-
3
- export const adjustSpreadOnOdds = (impliedProbs: number[], minSpread: number, targetSpread: number) => {
4
- // Step 1: Check if any implied probability is zero
5
- if (impliedProbs.some((prob) => prob === 0)) {
6
- return impliedProbs;
7
- }
8
-
9
- // Step 2: Calculate the current total implied probabilities
10
- const totalImpliedProbs = impliedProbs.reduce((sum, prob) => sum + prob, 0);
11
-
12
- // Step 3: Check if the sum of implied probabilities is greater than 1
13
- if (totalImpliedProbs <= 1) {
14
- return Array(impliedProbs.length).fill(0);
15
- }
16
-
17
- // Step 4: Check if targetSpread is zero
18
- if (targetSpread === 0) {
19
- const currentSpread = (totalImpliedProbs - 1) * 100;
20
- // If minSpread is set and greater than current spread, use minSpread
21
- if (minSpread > currentSpread) {
22
- targetSpread = minSpread;
23
- } else {
24
- // If minSpread is less than current spread, return odds as they are
25
- return impliedProbs;
26
- }
27
- }
28
-
29
- // Step 5: Calculate the target total implied probabilities
30
- const targetTotalImpliedProbs = 1 + targetSpread / 100;
31
-
32
- // Step 6: Calculate the adjustment factor
33
- const adjustmentFactor = targetTotalImpliedProbs / totalImpliedProbs;
34
-
35
- // Step 7: Adjust the probabilities to reflect the target spread
36
- let adjustedImpliedProbs = impliedProbs.map((prob) => prob * adjustmentFactor);
37
-
38
- // Step 8: Check if any adjusted probability equals or exceeds 1
39
- if (adjustedImpliedProbs.some((prob) => prob >= 1)) {
40
- return Array(impliedProbs.length).fill(0);
41
- }
42
-
43
- // Step 9: Ensure the sum of the adjusted probabilities equals the target total implied probabilities
44
- const sumAdjustedProbs = adjustedImpliedProbs.reduce((sum, prob) => sum + prob, 0);
45
-
46
- // Step 10: If the sum of the adjusted probabilities is less than 1, return zeros
47
- if (sumAdjustedProbs < 1) {
48
- return Array(impliedProbs.length).fill(0);
49
- }
50
-
51
- const normalizationFactor = targetTotalImpliedProbs / sumAdjustedProbs;
52
- adjustedImpliedProbs = adjustedImpliedProbs.map((prob) => prob * normalizationFactor);
53
-
54
- return adjustedImpliedProbs;
55
- };
56
-
57
- export const getSpreadData = (
58
- spreadData: any[],
59
- sportId: string,
60
- typeId: number,
61
- defaultSpreadForLiveMarkets: number
62
- ) => {
63
- const sportSpreadData = spreadData.find(
64
- (data) => Number(data.typeId) === Number(typeId) && Number(data.sportId) === Number(sportId)
65
- );
66
- if (sportSpreadData) {
67
- return {
68
- minSpread: sportSpreadData.minSpread ? Number(sportSpreadData.minSpread) : defaultSpreadForLiveMarkets,
69
- targetSpread: sportSpreadData.targetSpread ? Number(sportSpreadData.targetSpread) : 0,
70
- };
71
- }
72
- return { minSpread: defaultSpreadForLiveMarkets, targetSpread: 0 };
73
- };
74
-
75
- export const adjustAddedSpread = (odds: number[], leagueInfo: LeagueConfigInfo[], typeId: number) => {
76
- // Pack market odds for UI
77
- return odds.map((probability) => {
78
- if (probability != 0) {
79
- const leagueInfoByTypeId = leagueInfo.find((league) => Number(league.typeId) === Number(typeId));
80
- let finalProbability = probability;
81
-
82
- if (probability < 0.95) {
83
- if (leagueInfoByTypeId && Number(leagueInfoByTypeId.addedSpread)) {
84
- finalProbability = (probability * (100 + Number(leagueInfoByTypeId.addedSpread))) / 100;
85
- // edge case if added spread is bigger than 5%, it can happen that odd goes above 1, in that case return odd from api.
86
- if (finalProbability >= 1) {
87
- finalProbability = probability;
88
- }
89
- }
90
- }
91
-
92
- return finalProbability;
93
- } else {
94
- return 0;
95
- }
96
- });
97
- };
1
+ import { LeagueConfigInfo } from '../types/sports';
2
+
3
+ export const adjustSpreadOnOdds = (impliedProbs: number[], minSpread: number, targetSpread: number) => {
4
+ // Step 1: Check if any implied probability is zero
5
+ if (impliedProbs.some((prob) => prob === 0)) {
6
+ return impliedProbs;
7
+ }
8
+
9
+ // Step 2: Calculate the current total implied probabilities
10
+ const totalImpliedProbs = impliedProbs.reduce((sum, prob) => sum + prob, 0);
11
+
12
+ // Step 3: Check if the sum of implied probabilities is greater than 1
13
+ if (totalImpliedProbs <= 1) {
14
+ return Array(impliedProbs.length).fill(0);
15
+ }
16
+
17
+ // Step 4: Check if targetSpread is zero
18
+ if (targetSpread === 0) {
19
+ const currentSpread = (totalImpliedProbs - 1) * 100;
20
+ // If minSpread is set and greater than current spread, use minSpread
21
+ if (minSpread > currentSpread) {
22
+ targetSpread = minSpread;
23
+ } else {
24
+ // If minSpread is less than current spread, return odds as they are
25
+ return impliedProbs;
26
+ }
27
+ }
28
+
29
+ // Step 5: Calculate the target total implied probabilities
30
+ const targetTotalImpliedProbs = 1 + targetSpread / 100;
31
+
32
+ // Step 6: Calculate the adjustment factor
33
+ const adjustmentFactor = targetTotalImpliedProbs / totalImpliedProbs;
34
+
35
+ // Step 7: Adjust the probabilities to reflect the target spread
36
+ let adjustedImpliedProbs = impliedProbs.map((prob) => prob * adjustmentFactor);
37
+
38
+ // Step 8: Check if any adjusted probability equals or exceeds 1
39
+ if (adjustedImpliedProbs.some((prob) => prob >= 1)) {
40
+ return Array(impliedProbs.length).fill(0);
41
+ }
42
+
43
+ // Step 9: Ensure the sum of the adjusted probabilities equals the target total implied probabilities
44
+ const sumAdjustedProbs = adjustedImpliedProbs.reduce((sum, prob) => sum + prob, 0);
45
+
46
+ // Step 10: If the sum of the adjusted probabilities is less than 1, return zeros
47
+ if (sumAdjustedProbs < 1) {
48
+ return Array(impliedProbs.length).fill(0);
49
+ }
50
+
51
+ const normalizationFactor = targetTotalImpliedProbs / sumAdjustedProbs;
52
+ adjustedImpliedProbs = adjustedImpliedProbs.map((prob) => prob * normalizationFactor);
53
+
54
+ return adjustedImpliedProbs;
55
+ };
56
+
57
+ export const getSpreadData = (
58
+ spreadData: any[],
59
+ sportId: string,
60
+ typeId: number,
61
+ defaultSpreadForLiveMarkets: number
62
+ ) => {
63
+ const sportSpreadData = spreadData.find(
64
+ (data) => Number(data.typeId) === Number(typeId) && Number(data.sportId) === Number(sportId)
65
+ );
66
+ if (sportSpreadData) {
67
+ return {
68
+ minSpread: sportSpreadData.minSpread ? Number(sportSpreadData.minSpread) : defaultSpreadForLiveMarkets,
69
+ targetSpread: sportSpreadData.targetSpread ? Number(sportSpreadData.targetSpread) : 0,
70
+ };
71
+ }
72
+ return { minSpread: defaultSpreadForLiveMarkets, targetSpread: 0 };
73
+ };
74
+
75
+ export const adjustAddedSpread = (odds: number[], leagueInfo: LeagueConfigInfo[], typeId: number) => {
76
+ // Pack market odds for UI
77
+ return odds.map((probability) => {
78
+ if (probability != 0) {
79
+ const leagueInfoByTypeId = leagueInfo.find((league) => Number(league.typeId) === Number(typeId));
80
+ let finalProbability = probability;
81
+
82
+ if (probability < 0.95) {
83
+ if (leagueInfoByTypeId && Number(leagueInfoByTypeId.addedSpread)) {
84
+ finalProbability = (probability * (100 + Number(leagueInfoByTypeId.addedSpread))) / 100;
85
+ // edge case if added spread is bigger than 5%, it can happen that odd goes above 1, in that case return odd from api.
86
+ if (finalProbability >= 1) {
87
+ finalProbability = probability;
88
+ }
89
+ }
90
+ }
91
+
92
+ return finalProbability;
93
+ } else {
94
+ return 0;
95
+ }
96
+ });
97
+ };
package/tsconfig.json CHANGED
@@ -1,17 +1,17 @@
1
- {
2
- "compilerOptions": {
3
- "module": "esnext",
4
- "esModuleInterop": true,
5
- "target": "es5",
6
- "lib": [
7
- "dom",
8
- "dom.iterable",
9
- "esnext"
10
- ],
11
- "moduleResolution": "node",
12
- "sourceMap": true,
13
- "outDir": "build",
14
- "declaration": true,
15
- "strict": true,
16
- }
1
+ {
2
+ "compilerOptions": {
3
+ "module": "esnext",
4
+ "esModuleInterop": true,
5
+ "target": "es5",
6
+ "lib": [
7
+ "dom",
8
+ "dom.iterable",
9
+ "esnext"
10
+ ],
11
+ "moduleResolution": "node",
12
+ "sourceMap": true,
13
+ "outDir": "build",
14
+ "declaration": true,
15
+ "strict": true,
16
+ }
17
17
  }
package/webpack.config.js CHANGED
@@ -1,24 +1,24 @@
1
- const path = require('path');
2
-
3
- module.exports = {
4
- entry: './index.ts',
5
- module: {
6
- rules: [
7
- {
8
- test: /\.ts?$/,
9
- use: 'ts-loader',
10
- exclude: /node_modules/,
11
- },
12
- ],
13
- },
14
- resolve: {
15
- extensions: ['.tsx', '.ts', '.js'],
16
- },
17
- output: {
18
- filename: 'main.js',
19
- path: path.resolve(__dirname),
20
- library: 'thalesUtils',
21
- libraryTarget: 'umd',
22
- globalObject: 'this',
23
- },
24
- };
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ entry: './index.ts',
5
+ module: {
6
+ rules: [
7
+ {
8
+ test: /\.ts?$/,
9
+ use: 'ts-loader',
10
+ exclude: /node_modules/,
11
+ },
12
+ ],
13
+ },
14
+ resolve: {
15
+ extensions: ['.tsx', '.ts', '.js'],
16
+ },
17
+ output: {
18
+ filename: 'main.js',
19
+ path: path.resolve(__dirname),
20
+ library: 'thalesUtils',
21
+ libraryTarget: 'umd',
22
+ globalObject: 'this',
23
+ },
24
+ };