overtime-live-trading-utils 2.1.17 → 2.1.19
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 +96 -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 +255 -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
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getBetTypesForLeague,
|
|
3
|
-
getLeagueSpreadTypes,
|
|
4
|
-
getLeagueTotalTypes,
|
|
5
|
-
getLiveSupportedLeagues,
|
|
6
|
-
} from '../../utils/sports';
|
|
7
|
-
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
8
|
-
|
|
9
|
-
describe('Sports', () => {
|
|
10
|
-
it('Should return all enabled leagues for LIVE', () => {
|
|
11
|
-
const supportedLeageus = getLiveSupportedLeagues(LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
12
|
-
|
|
13
|
-
expect(supportedLeageus).toContain(9806);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('Should return all enabled bet types for league', () => {
|
|
17
|
-
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoEnabledAll);
|
|
18
|
-
|
|
19
|
-
expect(betTypes).toContain('Moneyline');
|
|
20
|
-
expect(betTypes).toContain('Goal Spread');
|
|
21
|
-
expect(betTypes).toContain('Total Goals');
|
|
22
|
-
expect(betTypes).toContain('Double Chance');
|
|
23
|
-
expect(betTypes).toContain('Correct Score');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('Should return all enabled bet types for league, and not contain disabled ones (Totals)', () => {
|
|
27
|
-
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoEnabledSpreadDisabledTotals);
|
|
28
|
-
|
|
29
|
-
expect(betTypes).toContain('Moneyline');
|
|
30
|
-
expect(betTypes).toContain('Goal Spread');
|
|
31
|
-
expect(betTypes).not.toContain('Total Goals');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('Should return all enabled bet types for league, and not contain disabled ones (Double Chance and Correct Score)', () => {
|
|
35
|
-
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoDisabledCorrectScoreAndDoubleChance);
|
|
36
|
-
|
|
37
|
-
expect(betTypes).toContain('Moneyline');
|
|
38
|
-
expect(betTypes).toContain('Goal Spread');
|
|
39
|
-
expect(betTypes).not.toContain('Double Chance');
|
|
40
|
-
expect(betTypes).not.toContain('Correct Score');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('Should return all enabled spread bet types for league', () => {
|
|
44
|
-
const betTypes = getLeagueSpreadTypes(9806, LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
45
|
-
|
|
46
|
-
expect(betTypes).not.toContain('moneyline');
|
|
47
|
-
expect(betTypes).toContain('goal spread');
|
|
48
|
-
expect(betTypes).not.toContain('total goals');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('Should return all enabled total bet types for league', () => {
|
|
52
|
-
const betTypes = getLeagueTotalTypes(9806, LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
53
|
-
|
|
54
|
-
expect(betTypes).not.toContain('moneyline');
|
|
55
|
-
expect(betTypes).not.toContain('goal spread');
|
|
56
|
-
expect(betTypes).toContain('total goals');
|
|
57
|
-
});
|
|
58
|
-
});
|
|
1
|
+
import {
|
|
2
|
+
getBetTypesForLeague,
|
|
3
|
+
getLeagueSpreadTypes,
|
|
4
|
+
getLeagueTotalTypes,
|
|
5
|
+
getLiveSupportedLeagues,
|
|
6
|
+
} from '../../utils/sports';
|
|
7
|
+
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
8
|
+
|
|
9
|
+
describe('Sports', () => {
|
|
10
|
+
it('Should return all enabled leagues for LIVE', () => {
|
|
11
|
+
const supportedLeageus = getLiveSupportedLeagues(LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
12
|
+
|
|
13
|
+
expect(supportedLeageus).toContain(9806);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('Should return all enabled bet types for league', () => {
|
|
17
|
+
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoEnabledAll);
|
|
18
|
+
|
|
19
|
+
expect(betTypes).toContain('Moneyline');
|
|
20
|
+
expect(betTypes).toContain('Goal Spread');
|
|
21
|
+
expect(betTypes).toContain('Total Goals');
|
|
22
|
+
expect(betTypes).toContain('Double Chance');
|
|
23
|
+
expect(betTypes).toContain('Correct Score');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('Should return all enabled bet types for league, and not contain disabled ones (Totals)', () => {
|
|
27
|
+
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoEnabledSpreadDisabledTotals);
|
|
28
|
+
|
|
29
|
+
expect(betTypes).toContain('Moneyline');
|
|
30
|
+
expect(betTypes).toContain('Goal Spread');
|
|
31
|
+
expect(betTypes).not.toContain('Total Goals');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('Should return all enabled bet types for league, and not contain disabled ones (Double Chance and Correct Score)', () => {
|
|
35
|
+
const betTypes = getBetTypesForLeague(9806, LeagueMocks.leagueInfoDisabledCorrectScoreAndDoubleChance);
|
|
36
|
+
|
|
37
|
+
expect(betTypes).toContain('Moneyline');
|
|
38
|
+
expect(betTypes).toContain('Goal Spread');
|
|
39
|
+
expect(betTypes).not.toContain('Double Chance');
|
|
40
|
+
expect(betTypes).not.toContain('Correct Score');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('Should return all enabled spread bet types for league', () => {
|
|
44
|
+
const betTypes = getLeagueSpreadTypes(9806, LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
45
|
+
|
|
46
|
+
expect(betTypes).not.toContain('moneyline');
|
|
47
|
+
expect(betTypes).toContain('goal spread');
|
|
48
|
+
expect(betTypes).not.toContain('total goals');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('Should return all enabled total bet types for league', () => {
|
|
52
|
+
const betTypes = getLeagueTotalTypes(9806, LeagueMocks.leagueInfoEnabledSpeadAndTotals);
|
|
53
|
+
|
|
54
|
+
expect(betTypes).not.toContain('moneyline');
|
|
55
|
+
expect(betTypes).not.toContain('goal spread');
|
|
56
|
+
expect(betTypes).toContain('total goals');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
import { ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT } from '../../constants/errors';
|
|
2
|
-
import { processMarket } from '../../utils/markets';
|
|
3
|
-
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
-
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
-
import { MockAfterSpreadZeroOdds1, MockOnlyMoneylineFavorite, MockOpticSoccer } from '../mock/MockOpticSoccer';
|
|
6
|
-
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
-
|
|
8
|
-
describe('Spread configuration', () => {
|
|
9
|
-
it('Should return zero odds for quotes that sum up total probability above 1', () => {
|
|
10
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
11
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockAfterSpreadZeroOdds1));
|
|
12
|
-
const market = processMarket(
|
|
13
|
-
freshMockSoccer,
|
|
14
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
15
|
-
['draftkings'],
|
|
16
|
-
[],
|
|
17
|
-
false,
|
|
18
|
-
undefined,
|
|
19
|
-
undefined,
|
|
20
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const hasOdds = market.odds.some(
|
|
24
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
expect(hasOdds).toBe(false);
|
|
28
|
-
expect(market).toHaveProperty('errorMessage');
|
|
29
|
-
expect(market.errorMessage).toBe(ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT); // should be no matching bookmakers mesage
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('Should have diff between odds equal to 3%', () => {
|
|
33
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
34
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
35
|
-
const market = JSON.parse(
|
|
36
|
-
JSON.stringify(
|
|
37
|
-
processMarket(
|
|
38
|
-
freshMockSoccer,
|
|
39
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
40
|
-
['draftkings'],
|
|
41
|
-
[],
|
|
42
|
-
true,
|
|
43
|
-
undefined,
|
|
44
|
-
undefined,
|
|
45
|
-
LeagueMocks.leagueInfoOnlyParent
|
|
46
|
-
)
|
|
47
|
-
)
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
const marketWithAddedSpread = JSON.parse(
|
|
51
|
-
JSON.stringify(
|
|
52
|
-
processMarket(
|
|
53
|
-
freshMockSoccer,
|
|
54
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
55
|
-
['draftkings'],
|
|
56
|
-
[],
|
|
57
|
-
true,
|
|
58
|
-
undefined,
|
|
59
|
-
undefined,
|
|
60
|
-
LeagueMocks.leagueInfoOnlyParentWithSpreadAdded
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const diff1 =
|
|
66
|
-
((market.odds[0].decimal - marketWithAddedSpread.odds[0].decimal) / marketWithAddedSpread.odds[0].decimal) *
|
|
67
|
-
100;
|
|
68
|
-
|
|
69
|
-
const diff2 =
|
|
70
|
-
((market.odds[1].decimal - marketWithAddedSpread.odds[1].decimal) / marketWithAddedSpread.odds[1].decimal) *
|
|
71
|
-
100;
|
|
72
|
-
|
|
73
|
-
const diff3 =
|
|
74
|
-
((market.odds[2].decimal - marketWithAddedSpread.odds[2].decimal) / marketWithAddedSpread.odds[2].decimal) *
|
|
75
|
-
100;
|
|
76
|
-
|
|
77
|
-
expect(Math.round(diff1)).toBe(3);
|
|
78
|
-
expect(Math.round(diff2)).toBe(3);
|
|
79
|
-
expect(Math.round(diff3)).toBe(3);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('Should have diff between odds equal to 3%, and one odd should stay the same', () => {
|
|
83
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
84
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneylineFavorite));
|
|
85
|
-
const market = JSON.parse(
|
|
86
|
-
JSON.stringify(
|
|
87
|
-
processMarket(
|
|
88
|
-
freshMockSoccer,
|
|
89
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
90
|
-
['draftkings'],
|
|
91
|
-
[],
|
|
92
|
-
true,
|
|
93
|
-
undefined,
|
|
94
|
-
undefined,
|
|
95
|
-
LeagueMocks.leagueInfoOnlyParent
|
|
96
|
-
)
|
|
97
|
-
)
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const marketWithAddedSpread = JSON.parse(
|
|
101
|
-
JSON.stringify(
|
|
102
|
-
processMarket(
|
|
103
|
-
freshMockSoccer,
|
|
104
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
105
|
-
['draftkings'],
|
|
106
|
-
[],
|
|
107
|
-
true,
|
|
108
|
-
undefined,
|
|
109
|
-
undefined,
|
|
110
|
-
LeagueMocks.leagueInfoOnlyParentWithSpreadAdded
|
|
111
|
-
)
|
|
112
|
-
)
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const diff1 =
|
|
116
|
-
((market.odds[0].decimal - marketWithAddedSpread.odds[0].decimal) / marketWithAddedSpread.odds[0].decimal) *
|
|
117
|
-
100;
|
|
118
|
-
|
|
119
|
-
const diff2 =
|
|
120
|
-
((market.odds[1].decimal - marketWithAddedSpread.odds[1].decimal) / marketWithAddedSpread.odds[1].decimal) *
|
|
121
|
-
100;
|
|
122
|
-
|
|
123
|
-
const diff3 =
|
|
124
|
-
((market.odds[2].decimal - marketWithAddedSpread.odds[2].decimal) / marketWithAddedSpread.odds[2].decimal) *
|
|
125
|
-
100;
|
|
126
|
-
|
|
127
|
-
expect(Math.round(diff1)).toBe(0);
|
|
128
|
-
expect(Math.round(diff2)).toBe(3);
|
|
129
|
-
expect(Math.round(diff3)).toBe(3);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
1
|
+
import { ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT } from '../../constants/errors';
|
|
2
|
+
import { processMarket } from '../../utils/markets';
|
|
3
|
+
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
+
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
+
import { MockAfterSpreadZeroOdds1, MockOnlyMoneylineFavorite, MockOpticSoccer } from '../mock/MockOpticSoccer';
|
|
6
|
+
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
+
|
|
8
|
+
describe('Spread configuration', () => {
|
|
9
|
+
it('Should return zero odds for quotes that sum up total probability above 1', () => {
|
|
10
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
11
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockAfterSpreadZeroOdds1));
|
|
12
|
+
const market = processMarket(
|
|
13
|
+
freshMockSoccer,
|
|
14
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
15
|
+
['draftkings'],
|
|
16
|
+
[],
|
|
17
|
+
false,
|
|
18
|
+
undefined,
|
|
19
|
+
undefined,
|
|
20
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const hasOdds = market.odds.some(
|
|
24
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(hasOdds).toBe(false);
|
|
28
|
+
expect(market).toHaveProperty('errorMessage');
|
|
29
|
+
expect(market.errorMessage).toBe(ZERO_ODDS_AFTER_SPREAD_ADJUSTMENT); // should be no matching bookmakers mesage
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('Should have diff between odds equal to 3%', () => {
|
|
33
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
34
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
35
|
+
const market = JSON.parse(
|
|
36
|
+
JSON.stringify(
|
|
37
|
+
processMarket(
|
|
38
|
+
freshMockSoccer,
|
|
39
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
40
|
+
['draftkings'],
|
|
41
|
+
[],
|
|
42
|
+
true,
|
|
43
|
+
undefined,
|
|
44
|
+
undefined,
|
|
45
|
+
LeagueMocks.leagueInfoOnlyParent
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const marketWithAddedSpread = JSON.parse(
|
|
51
|
+
JSON.stringify(
|
|
52
|
+
processMarket(
|
|
53
|
+
freshMockSoccer,
|
|
54
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
55
|
+
['draftkings'],
|
|
56
|
+
[],
|
|
57
|
+
true,
|
|
58
|
+
undefined,
|
|
59
|
+
undefined,
|
|
60
|
+
LeagueMocks.leagueInfoOnlyParentWithSpreadAdded
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const diff1 =
|
|
66
|
+
((market.odds[0].decimal - marketWithAddedSpread.odds[0].decimal) / marketWithAddedSpread.odds[0].decimal) *
|
|
67
|
+
100;
|
|
68
|
+
|
|
69
|
+
const diff2 =
|
|
70
|
+
((market.odds[1].decimal - marketWithAddedSpread.odds[1].decimal) / marketWithAddedSpread.odds[1].decimal) *
|
|
71
|
+
100;
|
|
72
|
+
|
|
73
|
+
const diff3 =
|
|
74
|
+
((market.odds[2].decimal - marketWithAddedSpread.odds[2].decimal) / marketWithAddedSpread.odds[2].decimal) *
|
|
75
|
+
100;
|
|
76
|
+
|
|
77
|
+
expect(Math.round(diff1)).toBe(3);
|
|
78
|
+
expect(Math.round(diff2)).toBe(3);
|
|
79
|
+
expect(Math.round(diff3)).toBe(3);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('Should have diff between odds equal to 3%, and one odd should stay the same', () => {
|
|
83
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
84
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneylineFavorite));
|
|
85
|
+
const market = JSON.parse(
|
|
86
|
+
JSON.stringify(
|
|
87
|
+
processMarket(
|
|
88
|
+
freshMockSoccer,
|
|
89
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
90
|
+
['draftkings'],
|
|
91
|
+
[],
|
|
92
|
+
true,
|
|
93
|
+
undefined,
|
|
94
|
+
undefined,
|
|
95
|
+
LeagueMocks.leagueInfoOnlyParent
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const marketWithAddedSpread = JSON.parse(
|
|
101
|
+
JSON.stringify(
|
|
102
|
+
processMarket(
|
|
103
|
+
freshMockSoccer,
|
|
104
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
105
|
+
['draftkings'],
|
|
106
|
+
[],
|
|
107
|
+
true,
|
|
108
|
+
undefined,
|
|
109
|
+
undefined,
|
|
110
|
+
LeagueMocks.leagueInfoOnlyParentWithSpreadAdded
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const diff1 =
|
|
116
|
+
((market.odds[0].decimal - marketWithAddedSpread.odds[0].decimal) / marketWithAddedSpread.odds[0].decimal) *
|
|
117
|
+
100;
|
|
118
|
+
|
|
119
|
+
const diff2 =
|
|
120
|
+
((market.odds[1].decimal - marketWithAddedSpread.odds[1].decimal) / marketWithAddedSpread.odds[1].decimal) *
|
|
121
|
+
100;
|
|
122
|
+
|
|
123
|
+
const diff3 =
|
|
124
|
+
((market.odds[2].decimal - marketWithAddedSpread.odds[2].decimal) / marketWithAddedSpread.odds[2].decimal) *
|
|
125
|
+
100;
|
|
126
|
+
|
|
127
|
+
expect(Math.round(diff1)).toBe(0);
|
|
128
|
+
expect(Math.round(diff2)).toBe(3);
|
|
129
|
+
expect(Math.round(diff3)).toBe(3);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare module 'oddslib';
|
|
2
|
-
declare module 'bytes32';
|
|
1
|
+
declare module 'oddslib';
|
|
2
|
+
declare module 'bytes32';
|
package/src/types/odds.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
export type Fixture = {
|
|
2
|
-
gameId: string;
|
|
3
|
-
startDate: number;
|
|
4
|
-
homeTeam: string;
|
|
5
|
-
awayTeam: string;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export type Odds = [
|
|
9
|
-
{
|
|
10
|
-
id: string;
|
|
11
|
-
sportsBookName: string;
|
|
12
|
-
name: string;
|
|
13
|
-
price: number;
|
|
14
|
-
timestamp: number;
|
|
15
|
-
points: number;
|
|
16
|
-
isMain: boolean;
|
|
17
|
-
isLive: boolean;
|
|
18
|
-
marketName: string;
|
|
19
|
-
playerId: string;
|
|
20
|
-
selection: string;
|
|
21
|
-
selectionLine: string;
|
|
22
|
-
}
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
export type OddsObject = {
|
|
26
|
-
gameId: string;
|
|
27
|
-
startDate: number;
|
|
28
|
-
homeTeam: string;
|
|
29
|
-
awayTeam: string;
|
|
30
|
-
isLive: boolean;
|
|
31
|
-
status: string;
|
|
32
|
-
sport: string;
|
|
33
|
-
league: string;
|
|
34
|
-
odds: Odds;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export type ScoresObject = {
|
|
38
|
-
gameId: string;
|
|
39
|
-
sport: string;
|
|
40
|
-
league: string;
|
|
41
|
-
status: string;
|
|
42
|
-
isLive: boolean;
|
|
43
|
-
clock: string;
|
|
44
|
-
period: string;
|
|
45
|
-
homeTeam: string;
|
|
46
|
-
awayTeam: string;
|
|
47
|
-
homeTotal: string;
|
|
48
|
-
awayTotal: string;
|
|
49
|
-
homePeriod1: string;
|
|
50
|
-
awayPeriod1: string;
|
|
51
|
-
homePeriod2: string;
|
|
52
|
-
awayPeriod2: string;
|
|
53
|
-
homePeriod3: string;
|
|
54
|
-
awayPeriod3: string;
|
|
55
|
-
homePeriod4: string;
|
|
56
|
-
awayPeriod4: string;
|
|
57
|
-
homePeriod5: string;
|
|
58
|
-
awayPeriod5: string;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export type HomeAwayTeams = { homeTeam: string; awayTeam: string };
|
|
1
|
+
export type Fixture = {
|
|
2
|
+
gameId: string;
|
|
3
|
+
startDate: number;
|
|
4
|
+
homeTeam: string;
|
|
5
|
+
awayTeam: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type Odds = [
|
|
9
|
+
{
|
|
10
|
+
id: string;
|
|
11
|
+
sportsBookName: string;
|
|
12
|
+
name: string;
|
|
13
|
+
price: number;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
points: number;
|
|
16
|
+
isMain: boolean;
|
|
17
|
+
isLive: boolean;
|
|
18
|
+
marketName: string;
|
|
19
|
+
playerId: string;
|
|
20
|
+
selection: string;
|
|
21
|
+
selectionLine: string;
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export type OddsObject = {
|
|
26
|
+
gameId: string;
|
|
27
|
+
startDate: number;
|
|
28
|
+
homeTeam: string;
|
|
29
|
+
awayTeam: string;
|
|
30
|
+
isLive: boolean;
|
|
31
|
+
status: string;
|
|
32
|
+
sport: string;
|
|
33
|
+
league: string;
|
|
34
|
+
odds: Odds;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ScoresObject = {
|
|
38
|
+
gameId: string;
|
|
39
|
+
sport: string;
|
|
40
|
+
league: string;
|
|
41
|
+
status: string;
|
|
42
|
+
isLive: boolean;
|
|
43
|
+
clock: string;
|
|
44
|
+
period: string;
|
|
45
|
+
homeTeam: string;
|
|
46
|
+
awayTeam: string;
|
|
47
|
+
homeTotal: string;
|
|
48
|
+
awayTotal: string;
|
|
49
|
+
homePeriod1: string;
|
|
50
|
+
awayPeriod1: string;
|
|
51
|
+
homePeriod2: string;
|
|
52
|
+
awayPeriod2: string;
|
|
53
|
+
homePeriod3: string;
|
|
54
|
+
awayPeriod3: string;
|
|
55
|
+
homePeriod4: string;
|
|
56
|
+
awayPeriod4: string;
|
|
57
|
+
homePeriod5: string;
|
|
58
|
+
awayPeriod5: string;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type HomeAwayTeams = { homeTeam: string; awayTeam: string };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export type PeriodScores = {
|
|
2
|
+
[key: string]: { home: number; away: number };
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type PeriodResolutionData = {
|
|
6
|
+
completedPeriods: number[];
|
|
7
|
+
readyForResolution: boolean;
|
|
8
|
+
periodScores: PeriodScores;
|
|
9
|
+
currentPeriod?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* OpticOdds Event type from their API response
|
|
14
|
+
* Uses 'any' for flexibility as API structure may vary
|
|
15
|
+
*/
|
|
16
|
+
export type OpticOddsEvent = any;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Sport period structure types
|
|
20
|
+
* Different sports have different period structures that affect how typeIds are resolved
|
|
21
|
+
*/
|
|
22
|
+
export enum SportPeriodType {
|
|
23
|
+
/** Sports with 2 halves (Soccer, NCAAB) */
|
|
24
|
+
HALVES_BASED = 'halves_based',
|
|
25
|
+
/** Sports with 4 quarters (NFL, NBA) */
|
|
26
|
+
QUARTERS_BASED = 'quarters_based',
|
|
27
|
+
/** Sports with 9+ innings (MLB, NPB, KBO, College Baseball, etc.) */
|
|
28
|
+
INNINGS_BASED = 'innings_based',
|
|
29
|
+
/** Sports with 9 periods without halves or secondary moneyline types */
|
|
30
|
+
PERIOD_BASED = 'period_based',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Halves-based sports period-to-typeId mapping (Soccer, NCAAB)
|
|
35
|
+
* Period 1 = 1st half
|
|
36
|
+
* Period 2 = 2nd half
|
|
37
|
+
*/
|
|
38
|
+
export const HALVES_PERIOD_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
39
|
+
1: [10021, 10031, 10041, 10051, 10061, 10071, 10081, 10111, 10112, 10121, 10163], // 1st half
|
|
40
|
+
2: [10022, 10032, 10042, 10052, 10062, 10072, 10082, 10211, 10212, 10122], // 2nd half
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Quarters-based sports period-to-typeId mapping (NFL, NBA)
|
|
45
|
+
* Period 1 = 1st quarter
|
|
46
|
+
* Period 2 = 2nd quarter (also completes 1st half - typeId 10051)
|
|
47
|
+
* Period 3 = 3rd quarter
|
|
48
|
+
* Period 4 = 4th quarter (also completes 2nd half - typeId 10052)
|
|
49
|
+
* Period 5+ = Overtime
|
|
50
|
+
*/
|
|
51
|
+
export const QUARTERS_PERIOD_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
52
|
+
1: [10021, 10031, 10041, 10061, 10071, 10081, 10111, 10112, 10121, 10163], // 1st quarter
|
|
53
|
+
2: [10022, 10032, 10042, 10051, 10062, 10072, 10082, 10211, 10212, 10122], // 2nd quarter + 1st half
|
|
54
|
+
3: [10023, 10033, 10043, 10063, 10073, 10083, 10311, 10312, 10123], // 3rd quarter
|
|
55
|
+
4: [10024, 10034, 10044, 10052, 10064, 10074, 10084, 10411, 10412, 10124], // 4th quarter + 2nd half
|
|
56
|
+
5: [10025, 10035, 10045, 10055, 10065, 10075, 10085, 10511, 10512], // Overtime/5th period
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Innings-based sports period-to-typeId mapping (MLB, NPB, KBO, College Baseball)
|
|
61
|
+
* Period 1-5 = Innings 1-5 (period 5 completes 1st half - typeId 10051)
|
|
62
|
+
* Period 6-9 = Innings 6-9 (period 9 completes 2nd half - typeId 10052)
|
|
63
|
+
*/
|
|
64
|
+
export const INNINGS_PERIOD_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
65
|
+
1: [10021, 10031, 10041, 10061, 10071, 10081, 10111, 10112, 10121, 10163], // 1st inning
|
|
66
|
+
2: [10022, 10032, 10042, 10062, 10072, 10082, 10211, 10212, 10122], // 2nd inning
|
|
67
|
+
3: [10023, 10033, 10043, 10063, 10073, 10083, 10311, 10312, 10123], // 3rd inning
|
|
68
|
+
4: [10024, 10034, 10044, 10064, 10074, 10084, 10411, 10412, 10124], // 4th inning
|
|
69
|
+
5: [10025, 10035, 10045, 10051, 10065, 10075, 10085, 10511, 10512], // 5th inning + 1st half
|
|
70
|
+
6: [10026, 10036, 10046, 10056, 10066, 10076, 10086, 10611, 10612], // 6th inning
|
|
71
|
+
7: [10027, 10037, 10047, 10057, 10067, 10077, 10087, 10711, 10712], // 7th inning
|
|
72
|
+
8: [10028, 10038, 10048, 10058, 10068, 10078, 10088, 10811, 10812], // 8th inning
|
|
73
|
+
9: [10029, 10039, 10049, 10052, 10069, 10079, 10089], // 9th inning + 2nd half
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Period-based sports period-to-typeId mapping (9 periods)
|
|
78
|
+
* Excludes halves types (10051, 10052) and secondary moneyline types (ending in 11/12)
|
|
79
|
+
*/
|
|
80
|
+
export const PERIOD_BASED_TYPE_ID_MAPPING: { [period: number]: number[] } = {
|
|
81
|
+
1: [10021, 10031, 10041, 10061, 10071, 10081, 10121, 10163], // 1st period
|
|
82
|
+
2: [10022, 10032, 10042, 10062, 10072, 10082, 10122], // 2nd period
|
|
83
|
+
3: [10023, 10033, 10043, 10063, 10073, 10083, 10123], // 3rd period
|
|
84
|
+
4: [10024, 10034, 10044, 10064, 10074, 10084, 10124], // 4th period
|
|
85
|
+
5: [10025, 10035, 10045, 10065, 10075, 10085], // 5th period
|
|
86
|
+
6: [10026, 10036, 10046, 10056, 10066, 10076, 10086], // 6th period
|
|
87
|
+
7: [10027, 10037, 10047, 10057, 10067, 10077, 10087], // 7th period
|
|
88
|
+
8: [10028, 10038, 10048, 10058, 10068, 10078, 10088], // 8th period
|
|
89
|
+
9: [10029, 10039, 10049, 10069, 10079, 10089], // 9th period
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Full game type IDs that should NOT be resolved during live games
|
|
94
|
+
* These can only be resolved when the game status is "completed"
|
|
95
|
+
*/
|
|
96
|
+
export const FULL_GAME_TYPE_IDS: number[] = [0, 10001, 10002, 10003, 10004, 10010, 10011, 10012];
|
package/src/types/sports.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
export type LeagueConfigInfo = {
|
|
3
|
-
sportId: number;
|
|
4
|
-
typeId: number;
|
|
5
|
-
marketName: string;
|
|
6
|
-
type: string;
|
|
7
|
-
enabled: string;
|
|
8
|
-
minOdds: number;
|
|
9
|
-
maxOdds: number;
|
|
10
|
-
addedSpread?: number;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type ChildMarket = {
|
|
14
|
-
leagueId: number;
|
|
15
|
-
typeId: number;
|
|
16
|
-
type: string;
|
|
17
|
-
line: number;
|
|
18
|
-
odds: Array<number>;
|
|
19
|
-
};
|
|
1
|
+
|
|
2
|
+
export type LeagueConfigInfo = {
|
|
3
|
+
sportId: number;
|
|
4
|
+
typeId: number;
|
|
5
|
+
marketName: string;
|
|
6
|
+
type: string;
|
|
7
|
+
enabled: string;
|
|
8
|
+
minOdds: number;
|
|
9
|
+
maxOdds: number;
|
|
10
|
+
addedSpread?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type ChildMarket = {
|
|
14
|
+
leagueId: number;
|
|
15
|
+
typeId: number;
|
|
16
|
+
type: string;
|
|
17
|
+
line: number;
|
|
18
|
+
odds: Array<number>;
|
|
19
|
+
};
|