sharpapi 0.1.0__py3-none-any.whl
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.
- sharpapi/__init__.py +93 -0
- sharpapi/_base.py +121 -0
- sharpapi/_utils.py +39 -0
- sharpapi/async_client.py +464 -0
- sharpapi/client.py +682 -0
- sharpapi/exceptions.py +52 -0
- sharpapi/models.py +433 -0
- sharpapi/py.typed +0 -0
- sharpapi/streaming.py +200 -0
- sharpapi-0.1.0.dist-info/METADATA +203 -0
- sharpapi-0.1.0.dist-info/RECORD +12 -0
- sharpapi-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sharpapi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the SharpAPI real-time sports betting odds API
|
|
5
|
+
Project-URL: Homepage, https://sharpapi.io
|
|
6
|
+
Project-URL: Documentation, https://docs.sharpapi.io/sdks/python
|
|
7
|
+
Project-URL: Repository, https://github.com/sharpapi/sharpapi-python
|
|
8
|
+
Project-URL: Changelog, https://github.com/sharpapi/sharpapi-python/releases
|
|
9
|
+
Author-email: SharpAPI <support@sharpapi.io>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: api,arbitrage,ev,odds,pinnacle,real-time,sports-betting
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: httpx>=0.25.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: pandas
|
|
27
|
+
Requires-Dist: pandas>=1.5.0; extra == 'pandas'
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
31
|
+
Requires-Dist: respx>=0.21; extra == 'test'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# SharpAPI Python SDK
|
|
35
|
+
|
|
36
|
+
Official Python client for the [SharpAPI](https://sharpapi.io) real-time sports betting odds API.
|
|
37
|
+
|
|
38
|
+
Get pre-computed +EV opportunities, arbitrage detection, middles, and live odds from 20+ sportsbooks — with Pinnacle as the sharp reference.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install sharpapi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from sharpapi import SharpAPI
|
|
50
|
+
|
|
51
|
+
client = SharpAPI("sk_live_xxx")
|
|
52
|
+
|
|
53
|
+
# --- Arbitrage opportunities ---
|
|
54
|
+
arbs = client.arbitrage.get(min_profit=1.0, league="nba")
|
|
55
|
+
for arb in arbs.data:
|
|
56
|
+
print(f"{arb.profit_percent:.2f}% profit — {arb.event_name}")
|
|
57
|
+
for leg in arb.legs:
|
|
58
|
+
print(f" {leg.sportsbook}: {leg.selection} @ {leg.odds_american} ({leg.stake_percent:.1f}%)")
|
|
59
|
+
|
|
60
|
+
# --- +EV opportunities ---
|
|
61
|
+
evs = client.ev.get(min_ev=3.0, sport="basketball")
|
|
62
|
+
for opp in evs.data:
|
|
63
|
+
print(f"+{opp.ev_percent:.1f}% EV on {opp.selection} @ {opp.sportsbook}")
|
|
64
|
+
if opp.kelly_fraction:
|
|
65
|
+
print(f" Kelly: {opp.kelly_fraction:.1%} of bankroll")
|
|
66
|
+
|
|
67
|
+
# --- Best odds across books ---
|
|
68
|
+
odds = client.odds.best(league="nba", market="moneyline")
|
|
69
|
+
for line in odds.data:
|
|
70
|
+
print(f"{line.home_team} vs {line.away_team}: {line.selection} {line.odds_american}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Streaming
|
|
74
|
+
|
|
75
|
+
Real-time SSE streaming for odds updates and opportunity alerts (requires WebSocket add-on):
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
stream = client.stream.opportunities(league="nba")
|
|
79
|
+
|
|
80
|
+
@stream.on("ev:detected")
|
|
81
|
+
def on_ev(data):
|
|
82
|
+
for opp in data:
|
|
83
|
+
print(f"+EV: {opp['selection']} {opp['ev_percent']}% @ {opp['sportsbook']}")
|
|
84
|
+
|
|
85
|
+
@stream.on("arb:detected")
|
|
86
|
+
def on_arb(data):
|
|
87
|
+
for arb in data:
|
|
88
|
+
print(f"Arb: {arb['profit_percent']}% — {arb['event_name']}")
|
|
89
|
+
|
|
90
|
+
stream.connect() # Blocks, processing events
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or iterate over events:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
for event_type, data in stream.iter_events():
|
|
97
|
+
if event_type == "ev:detected":
|
|
98
|
+
print(data)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## All Resources
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# Odds
|
|
105
|
+
client.odds.get(sport="basketball", league="nba")
|
|
106
|
+
client.odds.best(league="nfl", market="moneyline")
|
|
107
|
+
client.odds.comparison(event_id="abc123")
|
|
108
|
+
client.odds.batch(event_ids=["abc123", "def456"])
|
|
109
|
+
|
|
110
|
+
# Opportunities
|
|
111
|
+
client.ev.get(min_ev=2.0, sportsbook="draftkings")
|
|
112
|
+
client.arbitrage.get(min_profit=0.5, sport="football")
|
|
113
|
+
client.middles.get(sport="football", min_size=3.0)
|
|
114
|
+
client.low_hold.get(max_hold=2.0)
|
|
115
|
+
|
|
116
|
+
# Reference data
|
|
117
|
+
client.sports.list()
|
|
118
|
+
client.leagues.list(sport="basketball")
|
|
119
|
+
client.sportsbooks.list()
|
|
120
|
+
client.events.list(league="nba", live=True)
|
|
121
|
+
client.events.search("Lakers")
|
|
122
|
+
|
|
123
|
+
# Account
|
|
124
|
+
client.account.me() # Tier, limits, features
|
|
125
|
+
client.account.usage() # Request counts
|
|
126
|
+
|
|
127
|
+
# Streaming
|
|
128
|
+
client.stream.odds(league="nba")
|
|
129
|
+
client.stream.opportunities(min_ev=3.0)
|
|
130
|
+
client.stream.all(sport="basketball")
|
|
131
|
+
client.stream.event("event_id_here")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Data Quality
|
|
135
|
+
|
|
136
|
+
Every opportunity response includes staleness metadata to avoid acting on stale odds:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
arbs = client.arbitrage.get()
|
|
140
|
+
for arb in arbs.data:
|
|
141
|
+
if arb.possibly_stale:
|
|
142
|
+
print(f" Skipping — odds may be stale ({arb.oldest_odds_age_seconds}s old)")
|
|
143
|
+
continue
|
|
144
|
+
if "LIVE_HIGH_PROFIT_SUSPICIOUS" in arb.warnings:
|
|
145
|
+
print(f" Skipping — likely phantom arb")
|
|
146
|
+
continue
|
|
147
|
+
print(f"Actionable: {arb.profit_percent}%")
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Rate Limits
|
|
151
|
+
|
|
152
|
+
Rate limit info is available after every request:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
response = client.odds.get()
|
|
156
|
+
print(f"Remaining: {client.rate_limit.remaining}/{client.rate_limit.limit}")
|
|
157
|
+
print(f"Tier: {client.rate_limit.tier}")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Error Handling
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from sharpapi import (
|
|
164
|
+
SharpAPI,
|
|
165
|
+
AuthenticationError,
|
|
166
|
+
TierRestrictedError,
|
|
167
|
+
RateLimitedError,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
client = SharpAPI("sk_live_xxx")
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
evs = client.ev.get()
|
|
174
|
+
except AuthenticationError:
|
|
175
|
+
print("Invalid API key")
|
|
176
|
+
except TierRestrictedError as e:
|
|
177
|
+
print(f"Upgrade to {e.required_tier} tier for this feature")
|
|
178
|
+
except RateLimitedError as e:
|
|
179
|
+
print(f"Rate limited — retry after {e.retry_after}s")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Odds Conversion Utilities
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from sharpapi import american_to_decimal, american_to_probability, decimal_to_american
|
|
186
|
+
|
|
187
|
+
american_to_decimal(-110) # 1.909
|
|
188
|
+
american_to_decimal(150) # 2.5
|
|
189
|
+
american_to_probability(-110) # 0.524
|
|
190
|
+
decimal_to_american(2.5) # 150
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Requirements
|
|
194
|
+
|
|
195
|
+
- Python 3.9+
|
|
196
|
+
- httpx
|
|
197
|
+
- pydantic v2
|
|
198
|
+
|
|
199
|
+
## Links
|
|
200
|
+
|
|
201
|
+
- [API Docs](https://docs.sharpapi.io)
|
|
202
|
+
- [Dashboard](https://sharpapi.io/dashboard)
|
|
203
|
+
- [Discord](https://discord.gg/sharpapi)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
sharpapi/__init__.py,sha256=fdNbuf3dIWJuhObJPK-NMt7SDq0hMuCxd0SHVc819MI,1971
|
|
2
|
+
sharpapi/_base.py,sha256=EDltuitiyOL_APd1N8vtTT-wYsWxIhnThhoTkt3GuFo,3372
|
|
3
|
+
sharpapi/_utils.py,sha256=nQU1gNkzepAIr93HDYX455aRO2yhc6BeBbaWDnpI5lw,1143
|
|
4
|
+
sharpapi/async_client.py,sha256=MrNM01ZTUcnSSoeJpw6Z_77-5iWi1kNHyIW58wJvPZc,15370
|
|
5
|
+
sharpapi/client.py,sha256=2v1h9hEfzFeTCRBprRSw3Ir7nY_Xc-8NZE9TQwEH2Gc,22516
|
|
6
|
+
sharpapi/exceptions.py,sha256=nseJ4BboGjSWIfDtMYQpXPIaOUxbPAJLsxUPbERZqpY,1272
|
|
7
|
+
sharpapi/models.py,sha256=-w-dxdmCLlj9yAj_4wM7GAgVNPVXg9LZpFKCTi2pGNM,12620
|
|
8
|
+
sharpapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
sharpapi/streaming.py,sha256=smQi9F-m7ET7s7V_psdg3S-butiuG_bIq3CnOE1zG8M,6971
|
|
10
|
+
sharpapi-0.1.0.dist-info/METADATA,sha256=ua99nCzSqkTkNkaI7H8wSZaL3vINzshkcrjL557pLQs,5789
|
|
11
|
+
sharpapi-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
12
|
+
sharpapi-0.1.0.dist-info/RECORD,,
|