overtime-live-trading-utils 2.1.17 → 2.1.18
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/.circleci/config.yml +32 -32
- package/.prettierrc +9 -9
- package/CLAUDE.md +77 -0
- package/codecov.yml +20 -20
- package/index.ts +26 -16
- package/jest.config.ts +16 -16
- package/main.js +1 -1
- package/package.json +30 -30
- package/resolution_live_markets.md +351 -0
- package/src/constants/common.ts +7 -7
- package/src/constants/errors.ts +6 -6
- package/src/constants/sports.ts +78 -78
- package/src/enums/sports.ts +109 -109
- package/src/tests/mock/MockLeagueMap.ts +170 -170
- package/src/tests/mock/MockOpticOddsEvents.ts +518 -0
- package/src/tests/mock/MockOpticSoccer.ts +9378 -9378
- package/src/tests/mock/MockSoccerRedis.ts +2308 -2308
- package/src/tests/unit/bookmakers.test.ts +79 -79
- package/src/tests/unit/markets.test.ts +156 -156
- package/src/tests/unit/odds.test.ts +92 -92
- package/src/tests/unit/resolution.test.ts +1043 -0
- package/src/tests/unit/sports.test.ts +58 -58
- package/src/tests/unit/spread.test.ts +131 -131
- package/src/types/missing-types.d.ts +2 -2
- package/src/types/odds.ts +61 -61
- package/src/types/resolution.ts +78 -0
- package/src/types/sports.ts +19 -19
- package/src/utils/bookmakers.ts +159 -159
- package/src/utils/constraints.ts +210 -210
- package/src/utils/gameMatching.ts +81 -81
- package/src/utils/markets.ts +119 -119
- package/src/utils/odds.ts +674 -674
- package/src/utils/opticOdds.ts +71 -71
- package/src/utils/resolution.ts +221 -0
- package/src/utils/sports.ts +51 -51
- package/src/utils/spread.ts +97 -97
- package/tsconfig.json +16 -16
- package/webpack.config.js +24 -24
package/src/utils/markets.ts
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
import * as oddslib from 'oddslib';
|
|
2
|
-
import {
|
|
3
|
-
DIFF_BETWEEN_BOOKMAKERS_MESSAGE,
|
|
4
|
-
ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT,
|
|
5
|
-
ZERO_ODDS_MESSAGE,
|
|
6
|
-
} from '../constants/errors';
|
|
7
|
-
import { OddsObject } from '../types/odds';
|
|
8
|
-
import { createChildMarkets, getParentOdds } from './odds';
|
|
9
|
-
import { getLeagueInfo } from './sports';
|
|
10
|
-
import { adjustAddedSpread } from './spread';
|
|
11
|
-
/**
|
|
12
|
-
* Processes a single sports event. This function maps event data to a specific format,
|
|
13
|
-
* filters invalid events, and optionally fetches player properties if the sport supports it.
|
|
14
|
-
* Returns the mapped event object or null if the event is filtered out or mapping results in a null object.
|
|
15
|
-
*
|
|
16
|
-
* @param {Object} market - The market API object to process
|
|
17
|
-
* @param {Object} apiResponseWithOdds - Provider's API object to process
|
|
18
|
-
* @param {Array} liveOddsProviders - Odds providers for live odds
|
|
19
|
-
* @param {Array} spreadData - Spread data for odds.
|
|
20
|
-
* @param {Boolean} isDrawAvailable - Is it two or three-positional sport
|
|
21
|
-
* @param {Number} defaultSpreadForLiveMarkets - Default spread for live markets
|
|
22
|
-
* @param {Number} maxPercentageDiffBetwenOdds - Maximum allowed percentage difference between same position odds from different providers
|
|
23
|
-
* @param {Boolean} isTestnet - Flag showing should we process for testnet or mainnet
|
|
24
|
-
* @returns {Promise<Object|null>} A promise that resolves to the processed event object or null if the event is invalid or mapping fails.
|
|
25
|
-
*/
|
|
26
|
-
export const processMarket = (
|
|
27
|
-
market: any,
|
|
28
|
-
apiResponseWithOdds: OddsObject,
|
|
29
|
-
liveOddsProviders: any,
|
|
30
|
-
spreadData: any,
|
|
31
|
-
isDrawAvailable: any,
|
|
32
|
-
defaultSpreadForLiveMarkets: any,
|
|
33
|
-
maxPercentageDiffBetwenOdds: any,
|
|
34
|
-
leagueMap: any
|
|
35
|
-
) => {
|
|
36
|
-
const sportSpreadData = spreadData.filter((data: any) => data.sportId === String(market.leagueId));
|
|
37
|
-
const leagueInfo = getLeagueInfo(market.leagueId, leagueMap);
|
|
38
|
-
|
|
39
|
-
const moneylineOdds = getParentOdds(
|
|
40
|
-
!isDrawAvailable,
|
|
41
|
-
sportSpreadData,
|
|
42
|
-
liveOddsProviders,
|
|
43
|
-
apiResponseWithOdds,
|
|
44
|
-
market.leagueId,
|
|
45
|
-
defaultSpreadForLiveMarkets,
|
|
46
|
-
maxPercentageDiffBetwenOdds
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const oddsAfterSpread = adjustAddedSpread(moneylineOdds.odds, leagueInfo, market.typeId);
|
|
50
|
-
|
|
51
|
-
if (moneylineOdds.errorMessage) {
|
|
52
|
-
market.odds = market.odds.map(() => {
|
|
53
|
-
return {
|
|
54
|
-
american: 0,
|
|
55
|
-
decimal: 0,
|
|
56
|
-
normalizedImplied: 0,
|
|
57
|
-
};
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
market.errorMessage = moneylineOdds.errorMessage;
|
|
61
|
-
} else {
|
|
62
|
-
// Pack market odds for UI
|
|
63
|
-
market.odds = oddsAfterSpread.map((probability) => {
|
|
64
|
-
if (probability != 0) {
|
|
65
|
-
return {
|
|
66
|
-
american: oddslib.from('impliedProbability', probability).to('moneyline'),
|
|
67
|
-
decimal: Number(oddslib.from('impliedProbability', probability).to('decimal').toFixed(10)),
|
|
68
|
-
normalizedImplied: probability,
|
|
69
|
-
};
|
|
70
|
-
} else {
|
|
71
|
-
market.errorMessage = ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT;
|
|
72
|
-
return {
|
|
73
|
-
american: 0,
|
|
74
|
-
decimal: 0,
|
|
75
|
-
normalizedImplied: 0,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if ([ZERO_ODDS_MESSAGE, DIFF_BETWEEN_BOOKMAKERS_MESSAGE].includes(moneylineOdds.errorMessage || '')) {
|
|
82
|
-
market.childMarkets = [];
|
|
83
|
-
} else {
|
|
84
|
-
const childMarkets = createChildMarkets(
|
|
85
|
-
apiResponseWithOdds,
|
|
86
|
-
sportSpreadData,
|
|
87
|
-
market.leagueId,
|
|
88
|
-
liveOddsProviders,
|
|
89
|
-
defaultSpreadForLiveMarkets,
|
|
90
|
-
leagueMap
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
const packedChildMarkets = childMarkets.map((childMarket: any) => {
|
|
94
|
-
const preparedMarket = { ...market, ...childMarket };
|
|
95
|
-
const oddsAfterSpread = adjustAddedSpread(preparedMarket.odds, leagueInfo, preparedMarket.typeId);
|
|
96
|
-
if (preparedMarket.odds.length > 0) {
|
|
97
|
-
preparedMarket.odds = oddsAfterSpread.map((probability) => {
|
|
98
|
-
if (probability == 0) {
|
|
99
|
-
return {
|
|
100
|
-
american: 0,
|
|
101
|
-
decimal: 0,
|
|
102
|
-
normalizedImplied: 0,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
american: oddslib.from('impliedProbability', probability).to('moneyline'),
|
|
108
|
-
decimal: Number(oddslib.from('impliedProbability', probability).to('decimal').toFixed(10)),
|
|
109
|
-
normalizedImplied: probability,
|
|
110
|
-
};
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
return preparedMarket;
|
|
114
|
-
});
|
|
115
|
-
market.childMarkets = packedChildMarkets;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return market;
|
|
119
|
-
};
|
|
1
|
+
import * as oddslib from 'oddslib';
|
|
2
|
+
import {
|
|
3
|
+
DIFF_BETWEEN_BOOKMAKERS_MESSAGE,
|
|
4
|
+
ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT,
|
|
5
|
+
ZERO_ODDS_MESSAGE,
|
|
6
|
+
} from '../constants/errors';
|
|
7
|
+
import { OddsObject } from '../types/odds';
|
|
8
|
+
import { createChildMarkets, getParentOdds } from './odds';
|
|
9
|
+
import { getLeagueInfo } from './sports';
|
|
10
|
+
import { adjustAddedSpread } from './spread';
|
|
11
|
+
/**
|
|
12
|
+
* Processes a single sports event. This function maps event data to a specific format,
|
|
13
|
+
* filters invalid events, and optionally fetches player properties if the sport supports it.
|
|
14
|
+
* Returns the mapped event object or null if the event is filtered out or mapping results in a null object.
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} market - The market API object to process
|
|
17
|
+
* @param {Object} apiResponseWithOdds - Provider's API object to process
|
|
18
|
+
* @param {Array} liveOddsProviders - Odds providers for live odds
|
|
19
|
+
* @param {Array} spreadData - Spread data for odds.
|
|
20
|
+
* @param {Boolean} isDrawAvailable - Is it two or three-positional sport
|
|
21
|
+
* @param {Number} defaultSpreadForLiveMarkets - Default spread for live markets
|
|
22
|
+
* @param {Number} maxPercentageDiffBetwenOdds - Maximum allowed percentage difference between same position odds from different providers
|
|
23
|
+
* @param {Boolean} isTestnet - Flag showing should we process for testnet or mainnet
|
|
24
|
+
* @returns {Promise<Object|null>} A promise that resolves to the processed event object or null if the event is invalid or mapping fails.
|
|
25
|
+
*/
|
|
26
|
+
export const processMarket = (
|
|
27
|
+
market: any,
|
|
28
|
+
apiResponseWithOdds: OddsObject,
|
|
29
|
+
liveOddsProviders: any,
|
|
30
|
+
spreadData: any,
|
|
31
|
+
isDrawAvailable: any,
|
|
32
|
+
defaultSpreadForLiveMarkets: any,
|
|
33
|
+
maxPercentageDiffBetwenOdds: any,
|
|
34
|
+
leagueMap: any
|
|
35
|
+
) => {
|
|
36
|
+
const sportSpreadData = spreadData.filter((data: any) => data.sportId === String(market.leagueId));
|
|
37
|
+
const leagueInfo = getLeagueInfo(market.leagueId, leagueMap);
|
|
38
|
+
|
|
39
|
+
const moneylineOdds = getParentOdds(
|
|
40
|
+
!isDrawAvailable,
|
|
41
|
+
sportSpreadData,
|
|
42
|
+
liveOddsProviders,
|
|
43
|
+
apiResponseWithOdds,
|
|
44
|
+
market.leagueId,
|
|
45
|
+
defaultSpreadForLiveMarkets,
|
|
46
|
+
maxPercentageDiffBetwenOdds
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const oddsAfterSpread = adjustAddedSpread(moneylineOdds.odds, leagueInfo, market.typeId);
|
|
50
|
+
|
|
51
|
+
if (moneylineOdds.errorMessage) {
|
|
52
|
+
market.odds = market.odds.map(() => {
|
|
53
|
+
return {
|
|
54
|
+
american: 0,
|
|
55
|
+
decimal: 0,
|
|
56
|
+
normalizedImplied: 0,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
market.errorMessage = moneylineOdds.errorMessage;
|
|
61
|
+
} else {
|
|
62
|
+
// Pack market odds for UI
|
|
63
|
+
market.odds = oddsAfterSpread.map((probability) => {
|
|
64
|
+
if (probability != 0) {
|
|
65
|
+
return {
|
|
66
|
+
american: oddslib.from('impliedProbability', probability).to('moneyline'),
|
|
67
|
+
decimal: Number(oddslib.from('impliedProbability', probability).to('decimal').toFixed(10)),
|
|
68
|
+
normalizedImplied: probability,
|
|
69
|
+
};
|
|
70
|
+
} else {
|
|
71
|
+
market.errorMessage = ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT;
|
|
72
|
+
return {
|
|
73
|
+
american: 0,
|
|
74
|
+
decimal: 0,
|
|
75
|
+
normalizedImplied: 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if ([ZERO_ODDS_MESSAGE, DIFF_BETWEEN_BOOKMAKERS_MESSAGE].includes(moneylineOdds.errorMessage || '')) {
|
|
82
|
+
market.childMarkets = [];
|
|
83
|
+
} else {
|
|
84
|
+
const childMarkets = createChildMarkets(
|
|
85
|
+
apiResponseWithOdds,
|
|
86
|
+
sportSpreadData,
|
|
87
|
+
market.leagueId,
|
|
88
|
+
liveOddsProviders,
|
|
89
|
+
defaultSpreadForLiveMarkets,
|
|
90
|
+
leagueMap
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const packedChildMarkets = childMarkets.map((childMarket: any) => {
|
|
94
|
+
const preparedMarket = { ...market, ...childMarket };
|
|
95
|
+
const oddsAfterSpread = adjustAddedSpread(preparedMarket.odds, leagueInfo, preparedMarket.typeId);
|
|
96
|
+
if (preparedMarket.odds.length > 0) {
|
|
97
|
+
preparedMarket.odds = oddsAfterSpread.map((probability) => {
|
|
98
|
+
if (probability == 0) {
|
|
99
|
+
return {
|
|
100
|
+
american: 0,
|
|
101
|
+
decimal: 0,
|
|
102
|
+
normalizedImplied: 0,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
american: oddslib.from('impliedProbability', probability).to('moneyline'),
|
|
108
|
+
decimal: Number(oddslib.from('impliedProbability', probability).to('decimal').toFixed(10)),
|
|
109
|
+
normalizedImplied: probability,
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return preparedMarket;
|
|
114
|
+
});
|
|
115
|
+
market.childMarkets = packedChildMarkets;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return market;
|
|
119
|
+
};
|