Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for betfair scores API #67

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 82 additions & 10 deletions betfair/betfair.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from betfair import utils
from betfair import models
from betfair import exceptions

from betfair.models import ScoreEvent, Score, Incidents

IDENTITY_URLS = collections.defaultdict(
lambda: 'https://identitysso.betfair.com/api/',
Expand All @@ -26,6 +26,16 @@
australia='https://api-au.betfair.com/exchange/betting/json-rpc/v1',
)

SCORE_URLS = collections.defaultdict(
lambda: 'https://api.betfair.com/exchange/scores/json-rpc/v1'
)

urls = {
'Betting': 'https://api.betfair.com/exchange/betting/json-rpc/v1',
'Accounts': 'https://api.betfair.com/exchange/account/json-rpc/v1',
'Score': 'https://api.betfair.com/exchange/scores/json-rpc/v1'
}


class Betfair(object):
"""Betfair API client.
Expand All @@ -38,6 +48,7 @@ class Betfair(object):
:param Session session: Optional Requests session
:param int timeout: Optional timeout duration (seconds)
"""

def __init__(self, app_key, cert_file, content_type='application/json', locale=None,
session=None, timeout=None):
self.app_key = app_key
Expand All @@ -56,6 +67,10 @@ def identity_url(self):
def api_url(self):
return API_URLS[self.locale]

@property
def score_url(self):
return SCORE_URLS[self.locale]

@property
def headers(self):
return {
Expand All @@ -76,10 +91,13 @@ def make_auth_request(self, method):
if data.get('status') != 'SUCCESS':
raise exceptions.AuthError(response, data)

def make_api_request(self, base, method, params, codes=None, model=None):
def make_api_request(self, base, method, params, codes=None, model=None, api='Betting'):
payload = utils.make_payload(base, method, params)
url = urls.get(api)
if not url:
raise exceptions.ApiError("no such API", method)
response = self.session.post(
self.api_url,
url,
data=json.dumps(payload, cls=utils.BetfairEncoder),
headers=self.headers,
timeout=self.timeout,
Expand Down Expand Up @@ -235,7 +253,7 @@ def list_venues(self, filter=None, locale=None):
filter = filter or models.MarketFilter()
return self.make_api_request(
'Sports',
'listVenues',
'listCountries',
utils.get_kwargs(locals()),
model=models.VenueResult,
)
Expand Down Expand Up @@ -409,7 +427,7 @@ def cancel_orders(self, market_id, instructions, customer_ref=None):
'Sports',
'cancelOrders',
utils.get_kwargs(locals()),
model=models.CancelExecutionReport,
model=models.CancelInstructionReport,
)

@utils.requires_login
Expand Down Expand Up @@ -449,12 +467,14 @@ def get_account_funds(self, wallet=None):

:param Wallet wallet: Name of the wallet in question
"""
return self.make_api_request(
result = self.make_api_request(
'Account',
'getAccountFunds',
utils.get_kwargs(locals()),
model=models.AccountFundsResponse,
api='Accounts'
)
return result

@utils.requires_login
def get_account_statement(
Expand All @@ -469,7 +489,7 @@ def get_account_statement(
:param IncludeItem include_item: Which items to include
:param Wallet wallte: Which wallet to return statementItems for
"""
return self.make_api_request(
result = self.make_api_request(
'Account',
'getAccountStatement',
utils.get_kwargs(locals()),
Expand All @@ -481,20 +501,22 @@ def get_account_details(self):
"""Returns the details relating your account, including your discount
rate and Betfair point balance.
"""
return self.make_api_request(
result = self.make_api_request(
'Account',
'getAccountDetails',
utils.get_kwargs(locals()),
model=models.AccountDetailsResponse,
api='Accounts'
)
return result

@utils.requires_login
def list_currency_rates(self, from_currency=None):
"""Returns a list of currency rates based on given currency

:param str from_currency: The currency from which the rates are computed
"""
return self.make_api_request(
result = self.make_api_request(
'Account',
'listCurrencyRates',
utils.get_kwargs(locals()),
Expand All @@ -509,9 +531,59 @@ def transfer_funds(self, from_, to, amount):
:param Wallet to: Destination wallet
:param float amount: Amount to transfer
"""
return self.make_api_request(
result = self.make_api_request(
'Account',
'transferFunds',
utils.get_kwargs(locals()),
model=models.TransferResponse,
)

@utils.requires_login
def list_scores(self, update_keys):
"""List scores of keys in update keys from scores API

:param List update_keys: Keys to update
"""
update_keys = [{'eventId': k} for k in update_keys]
k = None
del k # Stop k from propagiting as part of locals()
return self.make_api_request(
'Scores',
'listScores',
utils.get_kwargs(locals()),
api='Score',
model=Score
)

@utils.requires_login
def list_available_events(self, event_ids=None, event_type_ids=None, event_status=None):
"""List events that one can query with the scores API

:param event_ids:
:param event_type_ids:
:param event_status:
"""
return self.make_api_request(
'Scores',
'listAvailableEvents',
utils.get_kwargs(locals()),
api='Score',
model=ScoreEvent
)

@utils.requires_login
def list_incidents(self, update_keys):
"""List incidents for the keys in update_keys

:param List update_keys: list of keys to get incidents for
"""
update_keys = [{'eventId': k} for k in update_keys]
k = None
del k # Stop k from propagiting as part of locals()
return self.make_api_request(
'Scores',
'listIncidents',
utils.get_kwargs(locals()),
api='Score',
model=Incidents
)
20 changes: 19 additions & 1 deletion betfair/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from enum import Enum


MarketProjection = Enum(
'MarketProjection', [
'COMPETITION',
Expand Down Expand Up @@ -174,6 +173,12 @@
]
)

TimeInForce = Enum(
'TimeInForce', [
'FILL_OR_KILL'
]
)

InstructionReportStatus = Enum(
'InstructionReportStatus', [
'SUCCESS',
Expand Down Expand Up @@ -270,3 +275,16 @@
'UNKNOWN',
]
)

EventStatus = Enum(
'EventStatus', [
'IN_PROGRESS',
'PENDING',
'NO_NEW_UPDATES',
'NO_LIVE_DATA_AVAILABLE',
'SERVICE_UNAVAILABLE',
'UNEXPECTED_ERROR',
'LIVE_DATA_TEMPORARILY_UNAVAILABLE',
'FINISHED'
]
)
2 changes: 1 addition & 1 deletion betfair/meta/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __new__(meta, name, bases, attrs):

class BetfairModel(six.with_metaclass(BetfairModelMeta, models.Model)):

def __init__(self, **data):
def __init__(self, *args, **data):
super(BetfairModel, self).__init__()
self.import_data(data)

Expand Down
49 changes: 44 additions & 5 deletions betfair/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ class LimitOrder(BetfairModel):
size = FloatType(required=True)
price = FloatType(required=True)
persistence_type = EnumType(constants.PersistenceType, required=True)
time_in_force = EnumType(constants.TimeInForce)
min_fill_size = FloatType()


class LimitOnCloseOrder(BetfairModel):
Expand All @@ -224,7 +226,6 @@ class MarketOnCloseOrder(BetfairModel):
# Results

class CompetitionResult(BetfairModel):

competition = ModelType(Competition)
market_count = IntType()
competition_region = StringType()
Expand All @@ -236,13 +237,11 @@ class CountryCodeResult(BetfairModel):


class EventResult(BetfairModel):

event = ModelType(Event)
market_count = IntType()


class EventTypeResult(BetfairModel):

event_type = ModelType(EventType)
market_count = IntType()

Expand All @@ -253,7 +252,6 @@ class MarketTypeResult(BetfairModel):


class TimeRangeResult(BetfairModel):

time_range = ModelType(TimeRange)
market_count = IntType()

Expand Down Expand Up @@ -350,7 +348,6 @@ class ClearedOrderSummary(BetfairModel):
size_settled = FloatType()
profit = FloatType()
size_cancelled = FloatType()
bet_outcome = StringType()


class ClearedOrderSummaryReport(BetfairModel):
Expand Down Expand Up @@ -480,3 +477,45 @@ class CurrencyRate(BetfairModel):

class TransferResponse(BetfairModel):
transaction_id = StringType()


# Score

class ScoreEvent(BetfairModel):
event_id = IntType()
event_status = StringType()
event_type_id = IntType()


class ScoreContext(BetfairModel):
event_time = StringType()
last_updated = DateTimeType()
update_sequence = IntType()
update_type = StringType()


class Score(BetfairModel):
event_id = IntType()
event_type_id = IntType()
update_context = ModelType(ScoreContext)
values = DictType(StringType)
event_status = EnumType(constants.EventStatus, required=True)


class UpdateContext(BetfairModel):
event_type = StringType()
last_updated = DateTimeType()
update_sequence = IntType()
update_type = StringType()


class Incident(BetfairModel):
update_context = ModelType(UpdateContext)
values = DictType(StringType)


class Incidents(BetfairModel):
event_id = IntType()
event_type_id = IntType()
event_status = EnumType(constants.EventStatus, required=True)
incidents = ListType(ModelType(Incident))