def __init__(self, username, password, app_key): self.api = betfairlightweight.APIClient(username, password, app_key=app_key) self.api.login_interactive() self.leagues_list, self.last_since_id = {}, {} self.init_data() self.logger = init_logger() self.grouped_books = [] self.football_filter = filters.market_filter( event_type_ids=[1], # filter on just soccer competition_ids=self.FOOTBALL_COMPETITION_IDS, market_type_codes=[ "OVER_UNDER_25", "MATCH_ODDS", "ASIAN_HANDICAP" ]) self.esports_filter = filters.market_filter( event_type_ids=[27454571], # filter on esports competition_ids=self.ESPORT_COMPETITION_IDS, market_type_codes=["MATCH_ODDS" ], # filter on just odds market types ) self.default_market_projection = [ #"RUNNER_DESCRIPTION", "COMPETITION", "EVENT", "EVENT_TYPE", #"MARKET_DESCRIPTION", "MARKET_START_TIME", ]
def fetch_new_market_ids(trading, competition_ids, market_types): trading.login() # List of lists, calculate how many markets you can retrieve up market_ids = [] for ids in competition_ids: events = trading.betting.list_events( filter=market_filter( competition_ids=[ids], ), lightweight=True ) event_ids = [e['event']['id'] for e in events] markets = trading.betting.list_market_catalogue( filter=market_filter( event_ids=event_ids, market_type_codes=market_types, ), max_results=200, lightweight=True, ) market_ids.append([m['marketId'] for m in markets]) # Pack as many markets you can in each stream market_ids = list(chain(*market_ids)) step = 200 ms = [market_ids[i:i + step] for i in range(0, len(market_ids), step)] return ms
def list_market_cat(event_id=None, market_id=None): trading = get_betfair_client() time_ago = timezone.now() - datetime.timedelta(minutes=10) time_fwd = timezone.now() + datetime.timedelta(minutes=30) mfilter = market_filter( event_type_ids=[ET_TENNIS], # market_start_time=time_range( # from_=time_ago.strftime('%Y-%m-%dT%H:%I:%S.000Z'), # to=time_fwd.strftime('%Y-%m-%dT%H:%I:%S.000Z') ) res = trading.betting.list_market_catalogue(mfilter, market_projection=[ 'EVENT', 'MARKET_START_TIME', ], sort='FIRST_TO_START', max_results=500, lightweight=True) print(json.dumps(res, indent=4, default=str, sort_keys=True)) print(len(res)) if event_id: mfilter = market_filter(event_ids=[event_id]) elif market_id: mfilter = market_filter(market_ids=[market_id]) res = trading.betting.list_market_catalogue(mfilter) cat = res[0] print(f'runners: {len(cat.runners)}') for runner in cat.runners: print(f'{runner.name}')
def get_market_info( self, market_id: str) -> Tuple[str, datetime, Dict[int, str]]: """Get the market information from a Betfair market ID. Args: market_id: Betfair market ID. Returns: Market name, market start time (that is, when the event starts), market selections mapping from ID to name. """ market_filter_ = market_filter(market_ids=[market_id]) market = (self._client.betting.list_market_catalogue( filter=market_filter_, market_projection=['MARKET_START_TIME', 'RUNNER_DESCRIPTION'])[0]) market_name = market.market_name market_start_time = market.market_start_time selections = {} for runner in market.runners: selections[runner.selection_id] = runner.runner_name return market_name, market_start_time, selections
def poll_market_catalogue(context: dict, flumine) -> None: client = flumine.client markets = [ m.market_id for m in list(flumine.markets.markets.values()) if m.update_market_catalogue ] for market_ids in chunks(markets, 25): try: market_catalogues = client.betting_client.betting.list_market_catalogue( filter=filters.market_filter(market_ids=market_ids), max_results=25, market_projection=[ "COMPETITION", "EVENT", "EVENT_TYPE", "RUNNER_DESCRIPTION", "RUNNER_METADATA", "MARKET_START_TIME", "MARKET_DESCRIPTION", ], ) except BetfairError as e: logger.error( "poll_market_catalogue error", exc_info=True, extra={ "trading_function": "list_market_catalogue", "response": e }, ) continue if market_catalogues: flumine.handler_queue.put( events.MarketCatalogueEvent(market_catalogues))
def get_next_week_matches(self, fixtures_list=None): # Get a datetime object in a week and convert to string datetime_in_a_week = (datetime.datetime.utcnow() + datetime.timedelta(weeks=1)).strftime("%Y-%m-%dT%TZ") competitions = self.get_competition_ids(datetime_in_a_week) events = self.trading.betting.list_events( filter=filters.market_filter( competition_ids=competitions.ID.tolist(), market_start_time={ 'to': (datetime.datetime.utcnow() + datetime.timedelta(weeks=1)).strftime("%Y-%m-%dT%TZ") } ) ) # Create a DataFrame with all the events by iterating over each event object football_events_next_week = pd.DataFrame({ 'EventName': [event_object.event.name for event_object in events], 'EventID': [event_object.event.id for event_object in events], 'OpenDate': [event_object.event.open_date for event_object in events], 'MarketCount': [event_object.market_count for event_object in events], }) matches_df = football_events_next_week.loc[ football_events_next_week.EventName.str.split(' v ').str.len() > 1 ].sort_values('OpenDate') matches_df['Team1'] = matches_df.EventName.str.split(' v ').str[0] matches_df['Team2'] = matches_df.EventName.str.split(' v ').str[1] if fixtures_list: matches_df = matches_df.loc[matches_df.EventName.isin(fixtures_list)] self.matches_df = matches_df.set_index('EventID')
def list_venues(): login() mfilter = market_filter( event_type_ids=[ET_GREYHOUND_RACING, ET_HORSE_RACING], ) res = trading.betting.list_venues(mfilter) res.sort(key=lambda x: x.market_count, reverse=True) for item in res: print(f'venue: {item.market_count}: {item.venue}')
def list_events(): """list greyhound events""" trading = get_betfair_client() mfilter = market_filter(event_type_ids=[ET_TENNIS], ) res = trading.betting.list_events(mfilter) print(f'res length {len(res)}') res.sort(key=lambda x: x.event.open_date) for item in res: print(f'market count: {item.market_count}') print(f'event: [{item.event.id}] {item.event.name}') print(f'open: {item.event.open_date} {item.event.venue}')
def get_competition_ids(self, to_date): competition_filter = filters.market_filter( event_type_ids=[SOCCER_ID], market_start_time={ 'to': to_date }) # Get a list of competitions for soccer competitions = self.trading.betting.list_competitions( filter=competition_filter ) # Iterate over the competitions and create a dataframe of competitions and competition ids soccer_competitions = pd.DataFrame({ 'Competition': [competition_object.competition.name for competition_object in competitions], 'ID': [competition_object.competition.id for competition_object in competitions] }) return soccer_competitions.loc[soccer_competitions.Competition.isin([ # English competitions 'English Premier League', 'English Championship', 'English FA Cup', 'English Football League Cup', 'EFL Trophy', 'English League 1', 'English League 2', # European competitions 'UEFA Champions League', 'UEFA Europa League', 'UEFA Europa Conference League', 'UEFA Super Cup', 'UEFA Europa League Qualifiers', # International competitions 'UEFA Nations League', # FIFA World Cup 2022, 'FIFA World Cup Qualifiers', 'FIFA World Cup Qualifiers - Europe', # International Friendlies, 'UEFA Euro 2020', # Scottish 'Scottish Premiership', # Italian 'Italian Serie A', # Spanish 'Spanish La Liga', 'Spanish Copa del Rey', ])]
def get_match_odds(self, market_id): # Get market catalogues market_catalogue_filter = filters.market_filter( market_ids=[market_id], # market_countries=['GB' 'ES', 'IT', 'DE'] ) market_catalogue = self.trading.betting.list_market_catalogue( filter=market_catalogue_filter, market_projection=['RUNNER_DESCRIPTION'], max_results='100' ) if len(market_catalogue) == 0: print('EMPTY! ', market_id, market_catalogue) return None market_catalogue = market_catalogue[0] runner_names = { r.selection_id: r.runner_name for r in market_catalogue.runners } # Request market books market_books = self.trading.betting.list_market_book( market_ids=[market_id], price_projection=filters.price_projection( price_data=['EX_BEST_OFFERS'] ) ) assert len(market_books) == 1 book = market_books[0] assert book.number_of_winners == 1 runners = book.runners # Extract prices best_back_prices = [self.get_price(runner, kind='back') for runner in runners] best_lay_prices = [self.get_price(runner, kind='lay') for runner in runners] selection_ids = [runner.selection_id for runner in runners] statuses = [runner.status for runner in runners] runner_names = [runner_names[selection_id] for selection_id in selection_ids] return pd.DataFrame({ 'MarketID': [market_id]*len(selection_ids), 'SelectionID': selection_ids, 'SelectionName': runner_names, 'BestBackPrice': best_back_prices, 'BestLayPrice': best_lay_prices, 'Status': statuses, })
def list_events(): """list greyhound events""" trading = get_betfair_client() mfilter = market_filter( # event_type_ids=[EVENT_TYPE_GREYHOUND_RACING, EVENT_TYPE_HORSE_RACING]) event_ids=[28563458]) res = trading.betting.list_events(mfilter) print(f'res length {len(res)}') res.sort(key=lambda x: x.event.open_date) for item in res: print(f'market count: {item.market_count}') print(f'event: [{item.event.id}] {item.event.name}') print(f'open: {item.event.open_date} {item.event.venue}') print(f'loc: {item.event.country_code} {item.event.time_zone}')
def fetch_single_event_market_ids(self, event_id): market_catalogues = self.trading.betting.list_market_catalogue( filter=filters.market_filter(event_ids=[event_id]), max_results='1000', ) return { market_cat_object.market_name: market_cat_object.market_id for market_cat_object in market_catalogues if market_cat_object.market_name in [ 'Match Odds', 'Correct Score', 'Over/Under 1.5 Goals', 'Over/Under 2.5 Goals' ] }
def poll_market_catalogue(context: dict, flumine) -> None: # get betfair client client = flumine.clients.get_betfair_default() markets = [ m.market_id for m in list(flumine.markets.markets.values()) if m.update_market_catalogue and not m.closed ] for market_ids in chunks(markets, 25): try: market_catalogues = client.betting_client.betting.list_market_catalogue( filter=filters.market_filter(market_ids=market_ids), max_results=25, market_projection=[ "COMPETITION", "EVENT", "EVENT_TYPE", "RUNNER_DESCRIPTION", "RUNNER_METADATA", "MARKET_START_TIME", "MARKET_DESCRIPTION", ], ) except exceptions.StatusCodeError as e: # log as warning to prevent duplicate logs on betfair meltdown logger.warning( "poll_market_catalogue StatusCodeError", extra={ "trading_function": "list_market_catalogue", "response": e }, exc_info=True, ) continue except BetfairError as e: logger.error( "poll_market_catalogue error", exc_info=True, extra={ "trading_function": "list_market_catalogue", "response": e }, ) continue if market_catalogues: flumine.handler_queue.put( events.MarketCatalogueEvent(market_catalogues))
def list_market_catalogue(): trading = get_betfair_client() mfilter = market_filter(event_type_ids=[ET_TENNIS], market_start_time=time_range()) m = trading.betting.list_competitions(mfilter()) print(m) res = trading.betting.list_market_catalogue(mfilter, market_projection=[ 'EVENT', 'MARKET_START_TIME', 'RUNNER_METADATA', 'COMPETITION', ], sort='FIRST_TO_START', max_results=100, lightweight=True)
def grab_market_id(): # - soonest chosen? mb = trading.betting.list_market_catalogue( filter=filters.market_filter( event_type_ids=[7], # filter on just horse racing # assumes horse racing is event_type = 7 # market_countries=["GB"], # filter on just GB countries market_type_codes=["WIN"], # filter on just WIN market types ), market_projection=[ "MARKET_START_TIME", "RUNNER_DESCRIPTION", ], # runner description required max_results=1, )[0] print(f"Market ID : {mb.market_id}") print("Race info :", mb.market_name, mb.market_start_time) return mb.market_id
def get_event_info(self, market_id: str) -> Tuple[str, str, str]: """Get the event information for a Betfair market ID. Args: market_id: Betfair market ID. Returns: Event type, event name and competition name. """ market_filter_ = market_filter(market_ids=[market_id]) event_type = (self._client.betting.list_event_types( filter=market_filter_)[0].event_type.name) event = (self._client.betting.list_events( filter=market_filter_)[0].event.name) competition = (self._client.betting.list_competitions( filter=market_filter_)[0].competition.name) return event_type, event, competition
def list_market_cat(event_id=None, market_id=None): trading = get_betfair_client() time_ago = timezone.now() - datetime.timedelta(minutes=10) time_fwd = timezone.now() + datetime.timedelta(minutes=30) mfilter = market_filter( event_type_ids=[ET_HORSE_RACING, ET_GREYHOUND_RACING], market_start_time=time_range( from_=time_ago.strftime('%Y-%m-%dT%H:%I:%S.000Z'), to=time_fwd.strftime('%Y-%m-%dT%H:%I:%S.000Z'))) res = trading.betting.list_market_catalogue(mfilter, market_projection=[ 'EVENT', 'MARKET_START_TIME', 'MARKET_DESCRIPTION', 'RUNNER_METADATA', ], sort='FIRST_TO_START', max_results=1, lightweight=True) print(json.dumps(res, indent=4, default=str, sort_keys=True)) print(len(res))
def list_market_catalogue(self): logger.warning('+' * 80) trading = get_betfair_client() time_ago = timezone.now() + datetime.timedelta(minutes=1) time_fwd = timezone.now() + datetime.timedelta(minutes=60) mfilter = market_filter( event_type_ids=[ET_HORSE_RACING, ET_GREYHOUND_RACING], market_start_time=time_range( from_=time_ago.strftime('%Y-%m-%dT%H:%I:%S.000Z'), to=time_fwd.strftime('%Y-%m-%dT%H:%I:%S.000Z'))) res = trading.betting.list_market_catalogue(mfilter, market_projection=[ 'EVENT', 'MARKET_START_TIME', 'MARKET_DESCRIPTION', 'RUNNER_METADATA', ], sort='FIRST_TO_START', max_results=100, lightweight=True) if not len(res): logger.error('Market catalogue listing is empty') trading.session_token = None raise self.retry(countdown=5, max_retries=12) for cat in res: if 'venue' not in cat['event']: logger.error(f'No event venue in {cat}') continue try: event = parse_event(cat['event']) market = parse_market(event, cat) runners = parse_runners(market, cat['runners']) except: logger.warning(cat) raise logger.warning(f'BETFAIR: Scraped {len(res)} from market catalogue')
def get_selection_df(trading, event_id, prediction_obj): market_catalogue_filter = filters.market_filter(event_ids=[event_id]) market_catalogues = trading.betting.list_market_catalogue( filter=market_catalogue_filter, max_results='1000', market_projection=['RUNNER_DESCRIPTION']) market_catalogues_list = [ m for m in market_catalogues if m.market_name == prediction_obj.market_name ] if len(market_catalogues_list) == 0: return None market_catalogue = market_catalogues_list[0] selection_df = pd.DataFrame({ 'Selection ID': [runner.selection_id for runner in market_catalogue.runners], 'Runner Name': [runner.runner_name for runner in market_catalogue.runners] }) selection_df['Market Name'] = prediction_obj.market_name selection_df['Market ID'] = market_catalogue.market_id return selection_df
def get_soccer_df(trading, in_play_only=True): # Filter for just soccer soccer_live_filter = filters.market_filter(text_query='Soccer', in_play_only=in_play_only) # list events -> from event get id # Get a list of all thoroughbred events as objects soccer_events = trading.betting.list_events(filter=soccer_live_filter) # Create a DataFrame with all the events by iterating over each event object soccer_events_df = pd.DataFrame({ 'Event Name': [event_object.event.name.lower() for event_object in soccer_events], 'Home': [ event_object.event.name[:event_object.event.name.find(' v ')].trim( ) for event_object in soccer_events ], 'Away': [ event_object.event.name[event_object.event.name.find(' v ') + 3:].trim() for event_object in soccer_events ], 'Event ID': [event_object.event.id for event_object in soccer_events], 'Event Venue': [event_object.event.venue for event_object in soccer_events], 'Country Code': [event_object.event.country_code for event_object in soccer_events], 'Time Zone': [event_object.event.time_zone for event_object in soccer_events], 'Open Date': [event_object.event.open_date for event_object in soccer_events], 'Market Count': [event_object.market_count for event_object in soccer_events] }) return soccer_events_df
import betfairlightweight from betfairlightweight import filters import os # create trading instance username = os.environ.get('username') trading = betfairlightweight.APIClient(username) trading.login() # make event type request to find horse racing event type horse_racing_event_type_id = trading.betting.list_event_types( filter=filters.market_filter(text_query='Horse Racing')) # returns one result print(horse_racing_event_type_id) for event_type in horse_racing_event_type_id: # prints id, name and market count print(event_type.event_type.id, event_type.event_type.name, event_type.market_count) horse_racing_id = event_type.event_type.id # list all horse racing market catalogues market_catalogues = trading.betting.list_market_catalogue( filter=filters.market_filter( event_type_ids=[horse_racing_id], # filter on just horse racing market_countries=['GB'], # filter on just GB countries market_type_codes=['WIN'], # filter on just WIN market types ), market_projection=['MARKET_START_TIME', 'RUNNER_DESCRIPTION' ], # runner description required
def test_market_filter(self): response = market_filter() assert response == {} response = market_filter(market_ids=["1.123"]) assert response == {"marketIds": ["1.123"]}
def betfair_get(self, is_ip, counter, sport='Tennis'): start = timezone.now() ip = 'ip' if is_ip else 'ni' trading = get_betfair_client() trading.login() trading.keep_alive() tennis_event_type = self.sport[sport] markets = trading.betting.list_market_catalogue( market_filter(event_type_ids=[tennis_event_type], market_type_codes=["MATCH_ODDS"], in_play_only=is_ip), market_projection=[ "MARKET_DESCRIPTION", "RUNNER_DESCRIPTION", "EVENT", "EVENT_TYPE", "COMPETITION", "RUNNER_METADATA", "MARKET_START_TIME", ], max_results=100) mids = [m.market_id for m in markets] mids_portions = [mids[x:x + 40] for x in range(0, len(mids), 40)] #print(mids[0]) for mp in mids_portions: (','.join(mp)) books = trading.betting.list_market_book( market_ids=mp, price_projection=price_projection( price_data(ex_best_offers=True, )), lightweight=False) for b in books: m = next((x for x in markets if x.market_id == b.market_id), None) if m.competition == None: continue bfcid = m.competition.id marids = m.market_id print(marids) champname = m.competition.name country = m.event.country_code event_id = m.event.id ds = timezone.make_aware(m.event.open_date) p1 = m.runners[0].runner_name if (p1 == None or '/' in p1): continue rid1 = m.runners[0].selection_id p2 = m.runners[1].runner_name rid2 = m.runners[1].selection_id event, created = BFEvent.objects.get_or_create(bfid=event_id) if (created): champ = self.save_champ(bfcid, champname, tennis_event_type, country) player1 = self.save_player(p1) player2 = self.save_player(p2) event.cid = champ event.marids = marids event.rid1 = rid1 event.rid2 = rid2 event.pid1 = player1 event.pid2 = player2 event.dt = ds event.status = 1 if is_ip else 0 event.save() p1b1_odds = b.runners[0].ex.available_to_back[0].price if len( b.runners[0].ex.available_to_back) > 0 else 0 p1b1_size = b.runners[0].ex.available_to_back[0].size if len( b.runners[0].ex.available_to_back) > 0 else 0 p1l1_odds = b.runners[0].ex.available_to_lay[0].price if len( b.runners[0].ex.available_to_lay) > 0 else 0 p1l1_size = b.runners[0].ex.available_to_lay[0].size if len( b.runners[0].ex.available_to_lay) > 0 else 0 p2b1_odds = b.runners[1].ex.available_to_back[0].price if len( b.runners[1].ex.available_to_back) > 0 else 0 p2b1_size = b.runners[1].ex.available_to_back[0].size if len( b.runners[1].ex.available_to_back) > 0 else 0 p2l1_odds = b.runners[1].ex.available_to_lay[0].price if len( b.runners[1].ex.available_to_lay) > 0 else 0 p2l1_size = b.runners[1].ex.available_to_lay[0].size if len( b.runners[1].ex.available_to_lay) > 0 else 0 try: odds = BFOdds.objects.filter(eid=event).latest('dtc') if (odds.b1odds != p1b1_odds or odds.b2odds != p2b1_odds or odds.l1odds != p1l1_odds or odds.l2odds != p2l1_odds): self.save_odds(event, p1b1_odds, p2b1_odds, p1l1_odds, p2l1_odds, p1b1_size, p2b1_size, p1l1_size, p2l1_size, is_ip) if (self.is_debug): self.stdout.write( 'evid[%s], mid[%s] %s %s - %s in %s: %s/%s\n' % (event_id, b.market_id, ds, p1.replace( '\\', ''), p2.replace('\\', ''), country, b.total_matched, b.total_available), ending='') self.stdout.write( '[%s]%s:%s@%s\t|%s@%s\n' % (rid1, p1.replace('\\', ''), p1b1_size, p1b1_odds, p1l1_size, p1l1_odds), ending='') self.stdout.write( '[%s]%s:%s@%s\t|%s@%s\n' % (rid2, p2.replace('\\', ''), p2b1_size, p2b1_odds, p2l1_size, p2l1_odds), ending='') except: self.save_odds(event, p1b1_odds, p2b1_odds, p1l1_odds, p2l1_odds, p1b1_size, p2b1_size, p1l1_size, p2l1_size, is_ip) if (self.is_debug): self.stdout.write( 'evid[%s], mid[%s] %s %s - %s in %s: %s/%s\n' % (event_id, b.market_id, ds, p1.replace( '\\', ''), p2.replace('\\', ''), country, b.total_matched, b.total_available), ending='') self.stdout.write( '[%s]%s:%s@%s\t|%s@%s\n' % (rid1, p1.replace('\\', ''), p1b1_size, p1b1_odds, p1l1_size, p1l1_odds), ending='') self.stdout.write( '[%s]%s:%s@%s\t|%s@%s\n' % (rid2, p2.replace('\\', ''), p2b1_size, p2b1_odds, p2l1_size, p2l1_odds), ending='') end = timezone.now() log = ALog() log.name = 'update_bf_%s_%s' % (sport, ip) log.dts = start log.counter = counter log.duration = (end - start).total_seconds() log.save() if (self.is_debug): self.stdout.write('total execution is %s seconds\n' % (end - start), ending='')
def test_market_filter(self): response = market_filter() assert response == {} response = market_filter(market_ids=['1.123']) assert response == {'marketIds': ['1.123']}
# This would print all the files and directories # for file in dirs: # print(file) trading = betfairlightweight.APIClient(address, password, app_key=app_key, certs=certs) # login trading.login() # make event type request to find sport event type football_event_type_id = trading.betting.list_event_types( filter=filters.market_filter(text_query=sport)) # returns one result print(football_event_type_id) file = open("dict.txt") x = file.read() favourable_odds = literal_eval(x) f = open("dict_old.txt", "w") f.write(str(favourable_odds)) f.close() for event_type in football_event_type_id: # prints id, name and market count print( f"ID: {event_type.event_type.id}, Name: {event_type.event_type.name}, Market Count: {event_type.market_count}" )
# import packages from utils import bf_utils from betfairlightweight import filters import pandas as pd import time # logging in trading = bf_utils.api_login() # grab a horse race - soonest chosen? market_catalogues = trading.betting.list_market_catalogue( filter=filters.market_filter( event_type_ids=[ 7 ], # filter on just horse racing # assumes horse racing is event_type = 7 market_countries=["GB"], # filter on just GB countries market_type_codes=["WIN"], # filter on just WIN market types ), market_projection=[ "MARKET_START_TIME", "RUNNER_DESCRIPTION", ], # runner description required max_results=1, ) # race/market info race_info = {} for m in market_catalogues: race_info['id'] = m.market_id # race_info['start'] = m.market_start_time # race_info['runners'] = [(r.selection_id, r.runner_name) for r in m.runners]
streaming_market_filter, streaming_market_data_filter, replace_instruction) from datetime import date, timedelta from rx import Observable log = logging.getLogger(__name__) # https://developer.betfair.com/exchange-api/betting-api-demo/ RACE_CARD_MARKET_FILTER = market_filter( event_type_ids=['7'], # Horse racing market_type_codes=['WIN'], market_countries=['GB'], market_start_time={ 'from': f'{time.strftime("%Y-%m-%d")}T00:00:00Z', # 'to': f'{time.strftime("%Y-%m-%d")}T23:59:00Z' 'to': f'{str(date.today() + timedelta(days=1))}T23:59:00Z' }) class BetfairAccessLayer: def __init__(self): self._client = None self._market_observable = None self._order_observable = None self._todays_racecard = None self._market_stream = None self._order_stream = None