betcode-org / betconnect

betconnect - API client
MIT License
7 stars 6 forks source link

Pydantic raises error on staging area login #21

Closed demhadbale closed 2 years ago

demhadbale commented 2 years ago

Traceback (most recent call last): File "C:/FlumineNew/Lib/site-packages/flumine/examples/betconnecttest.py", line 138, in framework.run() File "C:\FlumineNew\lib\site-packages\flumine\flumine.py", line 15, in run with self:
File "C:\FlumineNew\lib\site-packages\flumine\baseflumine.py", line 412, in enter self.clients.login() File "C:\FlumineNew\lib\site-packages\flumine\clients\clients.py", line 58, in login client.login() File "C:\FlumineNew\lib\site-packages\flumine\clients\betconnectclient.py", line 21, in login return self.betting_client.account.login() File "C:\FlumineNew\lib\site-packages\betconnect\endpoints\account.py", line 84, in login ] = self.get_user_preferences() File "C:\FlumineNew\lib\site-packages\betconnect\endpoints\account.py", line 25, in get_user_preferences account_preferences = self.process_response( File "C:\FlumineNew\lib\site-packages\betconnect\endpoints\baseendpoint.py", line 192, in process_response return resource.create_from_dict(data) File "C:\FlumineNew\lib\site-packages\betconnect\resources\baseresource.py", line 26, in create_from_dict return cls.parse_obj(d) File "pydantic\main.py", line 511, in pydantic.main.BaseModel.parse_obj File "pydantic\main.py", line 331, in pydantic.main.BaseModel.init pydantic.error_wrappers.ValidationError: 1 validation error for AccountPreferences building none is not an allowed value (type=type_error.none.not_allowed) return cls.parse_obj(d) File "pydantic\main.py", line 511, in pydantic.main.BaseModel.parse_obj File "pydantic\main.py", line 331, in pydantic.main.BaseModel.init pydantic.error_wrappers.ValidationError: 1 validation error for AccountPreferences building none is not an allowed value (type=type_error.none.not_allowed)

demhadbale commented 2 years ago

`import time import logging import betconnect from betconnect.enums import Environment import betfairlightweight from betfairlightweight.filters import streaming_market_filter from pythonjsonlogger import jsonlogger from collections import defaultdict

from flumine import Flumine, clients, BaseStrategy, utils

logger = logging.getLogger()

custom_format = "%(asctime) %(levelname) %(message)" log_handler = logging.StreamHandler() formatter = jsonlogger.JsonFormatter(custom_format) formatter.converter = time.gmtime log_handler.setFormatter(formatter) logger.addHandler(log_handler) logger.setLevel(logging.INFO)

class ExampleStrategy(BaseStrategy): def start(self) -> None: self.context["betconnect"] = context = { "active_bookmakers": [], "active_sports": [], "active_regions": [], "active_fixtures": [], "active_markets": {}, # fixture_id: [market] "active_selections": defaultdict(list), # market_id: [selection] "active_fixtures_lookup": {}, }

get betconnect client

    client = self.clients.get_client(
        clients.ExchangeType.BETCONNECT, username="mandelbot",
    ).betting_client

    # get active bookmakers
    context["active_bookmakers"] = client.betting.active_bookmakers()
    # get active sports
    active_sports = context["active_sports"] = client.betting.active_sports()
    # get the horse racing sport
    horse_racing = [s for s in active_sports if s.name == "Horse Racing"][0]
    # get active regions
    active_regions = context["active_regions"] = client.betting.active_regions(
        sport_id=horse_racing.sport_id
    )
    # get the England region
    active_region = [r for r in active_regions if r.name == "England"][0]
    # get active market types for horse racing
    active_market_types = client.betting.active_market_types(
        sport_id=horse_racing.sport_id
    )
    # get win market type
    win_market_type = [mt for mt in active_market_types if mt.name == "WIN"][0]

    # Active fixtures
    active_fixtures = context["active_fixtures"] = client.betting.active_fixtures(
        sport_id=horse_racing.sport_id, region_id=active_region.region_id
    )
    for fixture in active_fixtures:
        # get markets
        context["active_markets"][
            fixture.fixture_id
        ] = client.betting.active_markets(fixture_id=fixture.fixture_id)
        # get the selections and prices for WIN market
        fixture_selection_prices = client.betting.selections_for_market(
            fixture_id=fixture.fixture_id,
            market_type_id=win_market_type.market_type_id,
            top_price_only=False,
        )
        for selection in fixture_selection_prices:
            context["active_selections"][selection.source_market_id].append(
                selection
            )
        context["active_fixtures_lookup"][
            (fixture.display_name, fixture.start_date_time)
        ] = fixture.fixture_id

def check_market_book(self, market, market_book):
    # process_market_book only executed if this returns True
    if market_book.status != "CLOSED" and market.market_catalogue:
        return True

def process_market_book(self, market, market_book):
    # betconnect_client = self.clients.get_client(
    #     clients.ExchangeType.BETCONNECT, username="username"
    # )

    fixture_id = self.context["betconnect"]["active_fixtures_lookup"][
        (market.venue, market.market_start_datetime)
    ]
    market_id = self.context["betconnect"]["active_markets"][fixture_id][
        0
    ].source_market_id  
    selections_lookup = {
        s.name: s
        for s in self.context["betconnect"]["active_selections"][market_id]
    }
    runner_names = {
        r.selection_id: r.runner_name for r in market.market_catalogue.runners
    }
    for runner in market_book.runners:
        if runner.status == "ACTIVE":
            # betfair
            runner_name = runner_names[runner.selection_id]
            best_back_price = utils.get_price(runner.ex.available_to_back, 0)
            # betconnect
            selection = selections_lookup[runner_name]
            max_price = selection.max_price

            diff = (1 / max_price) - (1 / best_back_price)

            print(runner_name, best_back_price, max_price, round(diff, 3))

framework = Flumine()

betconnect_client = clients.BetConnectClient( betconnect.APIClient("username", "password", "api_key", "https://.betconnect.com/", environment=Environment.STAGING) ) framework.add_client(betconnect_client)

strategy = ExampleStrategy( market_filter=None, streaming_timeout=2 ) framework.add_strategy(strategy)

framework.run()`

demhadbale commented 2 years ago

I'm sorry I don't know why it's formatting like that, but it's the same code as the example with Environment.STAGING added to the betconnect client

petercoles commented 2 years ago

Can you try again to see if the admin_area fix that BetConnect have made on your account has resolved the issue (at least for you)?

demhadbale commented 2 years ago

It has not, though may have changed the initial error to File "pydantic\main.py", line 511, in pydantic.main.BaseModel.parse_obj File "pydantic\main.py", line 331, in pydantic.main.BaseModel.init pydantic.error_wrappers.ValidationError: 1 validation error for AccountPreferences building value is not a valid integer (type=type_error.integer)

jbeasley123 commented 2 years ago

building isn't guaranteed to be an integer in the address

jbeasley123 commented 2 years ago

same with admin_area

varneyo commented 2 years ago

Looks like admin_area is already down as an optional string so thats all good, are we saying building should also be an optional string? building: Optional[str] = Field(default=None)