コード例 #1
0
ファイル: bdaqapiparse.py プロジェクト: jpmit/betman
def ParsePlaceOrdersNoReceipt(resp, olist):
    """Return list of order objects."""

    _check_errors(resp)
    tstamp = resp.Timestamp

    # list of order refs - I am presuming BDAQ returns them in the order
    # the orders were given!
    orefs = resp.OrderHandles.OrderHandle

    # create and return order object.  Note we set status to UNMATCHED,
    # and unmatched stake and matched stake accordingly.
    allorders = {}
    for (o, ref) in zip(olist, orefs):
        allorders[ref] = order.Order(
            const.BDAQID,
            o.sid,
            o.stake,
            o.price,
            o.polarity,
            **{
                'oref': ref,
                'mid': o.mid,
                'status': order.UNMATCHED,
                'matchedstake': 0.0,
                'unmatchedstake': o.stake,
                # we will write t placed to the DB
                'tplaced': tstamp,
                'tupdated': tstamp
            })
    return allorders
コード例 #2
0
ファイル: bfapiparse.py プロジェクト: jpmit/betman
def ParsegetMUBets(res, odict):

    # here we override checking of errors, since the BF API returns an
    # error if no results are returned, but from our perspective there
    # is no problem with this, we just return an empty dict.
    if res.errorCode == 'NO_RESULTS':
        return {}

    _check_errors(res)

    #if len(res.bets.MUBet) != len(odict):
    #    betlog.betlog.debug('Got {0} results for updating {1} orders'\
    #                        .format(len(res.bets.MUBet), len(odict)))
    #    print res.bets.MUBet
    #    print odict
    #print res.bets.MUBet

    # The following is slightly complicated, this is because the BF
    # API can return multiple orders with the same betid, (although
    # they will have a different transactionId). We will get this if a
    # bet has been 'partially' matched.  From our perspective, this is
    # a single 'unmatched' bet.
    print 'odict from engine', odict
    print 'result', res

    # dictionary of orders we will return
    allorders = {}

    # first initialise each order as unmatched
    for oref in odict:
        o = odict[oref]
        idict = {'mid': o.mid, 'oref': oref, 'status' : order.UNMATCHED,
                 'matchedstake': 0.0, 'unmatchedstake': o.stake}
        allorders[oref] = order.Order(const.BFID, o.sid, o.stake,
                                      o.price, o.polarity, **idict)

    # go through each MUBet, and add the amount matched (if any) to
    # the appropriate order object.
    for r in res.bets.MUBet:

        if r.betStatus == 'M':

            # get the order in the order dict that has the matching id
            o = allorders[r.betId]
            
            # add matched amount
            o.matchedstake += r.size
            o.unmatchedstake -= r.size

    # go through all orders, and changed status of those with
    # matchedstake equal to original placed stake to order.MATCHED.
    for o in allorders.values():
        # fp arithmetic
        ms = o.matchedstake
        s = o.stake
        #print o, ms, s
        if (ms > s - _EPS) and (ms < s + _EPS):
            o.status = order.MATCHED

    return allorders
コード例 #3
0
ファイル: database.py プロジェクト: jpmit/betman
    def return_orders(self, sqlstr, sqlargs=None):
        """
        Execute query sqlquery, which should return a list of Orders.
        This convenience function will convert the database
        representation to a list of Order objects.
        """
        try:
            res = self.cursor.execute(sqlstr, sqlargs)
        except sqlite3.OperationalError:
            # query string was malformed somehow
            raise DbError, 'received malformed SQL statement'
        except ValueError:
            raise DbError, ('wrong parameters passed to SQL ' 'statement')
        odata = res.fetchall()
        # create Order objects from results of market data
        # pid and pname both None since we are not storing this info
        # in the database!
        # Note also we need to convert sqlite int into bool for
        # inrunning status of market.
        orders = [
            order.Order(
                o[1], o[3], o[6], o[5], o[7], **{
                    'oref': o[0],
                    'status': o[10],
                    'matchedstake': o[8],
                    'unmatchedstake': o[9],
                    'strategy': o[4],
                    'mid': o[2]
                }) for o in odata
        ]

        return orders
コード例 #4
0
ファイル: bfapiparse.py プロジェクト: jpmit/betman
def ParseplaceBets(res, olist):

    # _check_errors only checks errors in the header and the footer,
    # we can have other errors that are returned in resultCode of each
    # (PlaceBetsResult) e.g resultCode = "INVALID_SIZE", and this even
    # if the main errorcode is "OK".  This is a 'known issue' in the
    # BF API, as detailed by the documentation
    # BetfairSportsExchangeAPIReferenceGuidev6.pdf, p114.
    print res
    _check_errors(res)
    tstamp = res.header.timestamp

#    print 'parse place bets:'
#    print olist
#    print res
    
    # check that we have one result for each order executed
    if len(res.betResults.PlaceBetsResult) != len(olist):
        raise ApiError, ('did not receive the correct number'
                         'of results from PlaceBets')

    allorders = {}
    # go through all results in turn and add to allorders list
    for betres, o in zip(res.betResults.PlaceBetsResult, olist):

        # first check that the bet was ok, there can be many possible
        # errors here, e.g. INVALID_SIZE: see
        # BetfairSportsExchangeAPIReferenceGuidev6.pdf, p119 for the
        # full list.
        if betres.resultCode != "OK":
            # we don't want to raise an exception here since the other
            # orders could have gone through ok, so print a warning
            # and skip to next order order id.
            betlog.betlog.debug('Warning: order {0} returned result {1}'\
                                .format(o, betres.resultCode))

        oref = betres.betId
        # check if we were matched
        matched = betres.sizeMatched
        if matched == o.stake:
            status = order.MATCHED
        else:
            # TODO: should we also have a part matched type? Probably.
            status = order.UNMATCHED

        odict = {'mid': o.mid, 'oref': oref, 'status': status,
                 'matchedstake': matched, 'unmatchedstake':
                 o.stake - matched, 'tplaced' : tstamp, 
                 'tupdated': tstamp}
        allorders[oref] = order.Order(const.BFID, o.sid, o.stake,
                                      o.price, o.polarity, **odict)
    
    return allorders
コード例 #5
0
    def store_opportunity(self, slay, sback, olay, oback, inst=False):
        """Store details of betting opportunity."""

        self.opp = True
        self.slay = slay
        self.sback = sback
        self.olay = olay
        self.oback = oback
        self.instant = inst

        # Figure out how much we want to back and how much to lay. For
        # now let us bet the minimum amount possible.  For this we
        # should note that BDAQ has a minimum bet of 0.5, and BF has a
        # minimum bet of 2.0.  First the lay bet: if we are laying on
        # BDAQ, we want to lay the smallest amount possible such that
        # the matching back is for 2.0.  If we are laying on BF, again
        # we want to lay the minimum amount possible such that the back
        # is at least 0.5.
        bstake, lstake = self.get_stakes(sback.exid, self.oback, slay.exid,
                                         self.olay)

        # create both back and lay orders.
        self.border = order.Order(
            sback.exid, sback.id, bstake, self.oback, 1, **{
                'mid': sback.mid,
                'src': sback.src,
                'wsn': sback.wsn,
                'sname': sback.name
            })
        self.lorder = order.Order(
            slay.exid, slay.id, lstake, self.olay, 2, **{
                'mid': slay.mid,
                'src': slay.src,
                'wsn': slay.wsn,
                'sname': slay.name
            })
コード例 #6
0
ファイル: bdaqapiparse.py プロジェクト: jpmit/betman
def ParseListOrdersChangedSince(resp):
    """Returns list of orders that have changed"""

    _check_errors(resp)
    tstamp = resp.Timestamp

    if not hasattr(resp, 'Orders'):
        # no orders have changed
        return {}

    # store the sequence numbers of the orders: we need to return the
    # maximum sequence number so that the next time we call the API
    # function we won't return this again!
    seqnums = []

    allorders = {}
    for o in resp.Orders.Order:

        # From API docs, order _Status can be
        # 1 - Unmatched.  Order has SOME amount available for matching.
        # 2 - Matched (but not settled).
        # 3 - Cancelled (at least some part of the order was unmatched).
        # 4 - Settled.
        # 5 - Void.
        # 6 - Suspended.  At least some part unmatched but is suspended.

        # Note: at the moment we are not storing all of the data that
        # comes from the BDAQ API function, only the information that
        # seems useful...
        # example of a full order dict returned is:
        # {
        #    _Polarity = 1
        #    _Status = 1
        #    _TotalForSideTakeStake = 0.0
        #    _TotalForSideMakeStake = 0.0
        #    _CancelOnInRunning = True
        #    _SequenceNumber = 7857
        #    _SelectionId = 21412244
        #    _MatchedPrice = 0.0
        #    _MatchedStake = 0.0
        #    _MatchedAgainstStake = 0.0
        #    _CancelIfSelectionReset = False
        #    _MarketId = 3886077
        #    _UnmatchedStake = 1.0
        #    _MakeCommissionRate = 5.0
        #    _PunterReferenceNumber = 0
        #    _TakeCommissionRate = 5.0
        #    _IssuedAt = 2014-03-01 12:12:44.563000
        #    _RequestedPrice = 6.6
        #    _IsCurrentlyInRunning = False
        #    _Id = 2184011240
        #    _PunterCommissionBasis = 1
        #  }
        odict = {
            'oref': o._Id,
            'status': o._Status,
            'mid': o._MarketId,
            'matchedstake': o._MatchedStake,
            'unmatchedstake': o._UnmatchedStake,
            'tupdated': tstamp
        }

        allorders[o._Id] = order.Order(const.BDAQID, o._SelectionId,
                                       o._MatchedStake + o._UnmatchedStake,
                                       o._RequestedPrice, o._Polarity, **odict)
        # store sequence number
        seqnums.append(o._SequenceNumber)

    return allorders, max(seqnums)
コード例 #7
0
ファイル: bdaqapiparse.py プロジェクト: jpmit/betman
def ParseListBootstrapOrders(resp):
    """
    Parse a single order, return order object.  Note there are a few
    things the Api is returning that we are ignoring here.
    """

    _check_errors(resp)

    # no orders returned; end of bootstrapping process.
    if not hasattr(resp, 'Orders'):
        return {}

    # create and return list of order objects.
    allorders = {}
    for o in resp.Orders.Order:

        # The complete information returned by BDAQ for each order
        # looks like this:
        # {
        #    _Polarity = 1
        #    _Status = 1
        #    _TotalForSideTakeStake = 0.0
        #    _TotalForSideMakeStake = 0.0
        #    _CancelOnInRunning = True
        #    _SequenceNumber = 7857
        #    _SelectionId = 21412244
        #    _MatchedPrice = 0.0
        #    _MatchedStake = 0.0
        #    _MatchedAgainstStake = 0.0
        #    _CancelIfSelectionReset = False
        #    _MarketId = 3886077
        #    _UnmatchedStake = 1.0
        #    _MakeCommissionRate = 5.0
        #    _PunterReferenceNumber = 0
        #    _TakeCommissionRate = 5.0
        #    _IssuedAt = 2014-03-01 12:12:44.563000
        #    _RequestedPrice = 6.6
        #    _IsCurrentlyInRunning = False
        #    _Id = 2184011240
        #    _PunterCommissionBasis = 1
        #    OrderCommissionInformation =
        #       (OrderCommissionInformationType){
        #          _OrderCommission = 0.0
        #       }
        #  }

        sid = o._SelectionId
        mid = o._MarketId
        ustake = o._UnmatchedStake
        mstake = o._MatchedStake
        stake = ustake + mstake
        price = o._RequestedPrice
        pol = o._Polarity
        oref = o._Id
        status = o._Status

        allorders[oref] = order.Order(
            const.BDAQID, sid, stake, price, pol, **{
                'oref': oref,
                'mid': mid,
                'status': status,
                'matchedstake': mstake,
                'unmatchedstake': ustake
            })

    return allorders
コード例 #8
0
ファイル: mmstrategy.py プロジェクト: jpmit/betman
    def create_orders(self):
        """Create both back and lay orders."""

        # minimum stake at the moment
        exid = self.sel.exid

        # back and lay odds
        oback = self.sel.make_best_lay()
        olay = self.sel.make_best_back()

        if exid == const.BDAQID:
            # although minimum is 0.5, there are some difficulties
            # getting this to show up when calling prices from nonAPI
            # method, so lets go for 1
            bstake = 1
        else:
            # this will be 2, the minimum bet on BF
            bstake = _MINBETS[self.sel.exid]

        # we set the lay stake so that we are 'neutral' on whether the
        # selection pays out or not.  This means laying a slightly
        # larger stake than the back stake - how much larger depends
        # on the difference in the odds.  Note we are rounding (to
        # nearest penny) here, meaning we will typically win very
        # slightly more or less if the selection comes through versus
        # if it doesn't (see my notes).  This isn't the only sensible
        # staking strategy, we can stake any value between bstake and
        # this current lstake.
        lstake = round(bstake * (1.0 + oback) / (1.0 + olay), 2)

        sel = self.sel

        # note we put cancelrunning = False here
        self.border = order.Order(
            sel.exid,
            sel.id,
            bstake,
            oback,
            1,
            **{
                'mid': sel.mid,
                'src': sel.src,
                'wsn': sel.wsn,
                'sname': sel.name,
                # note we set both
                # cancel running (for
                # BDAQ) and persistence
                # (for BF)
                'cancelrunning': True,
                # warning: only some BF
                # markets allow 'IP'
                # persistence!  (and
                # only some allow SP
                # persistence)
                'persistence': 'NONE'
            })

        self.lorder = order.Order(
            sel.exid, sel.id, lstake, olay, 2, **{
                'mid': sel.mid,
                'src': sel.src,
                'wsn': sel.wsn,
                'sname': sel.name,
                'cancelrunning': True,
                'persistence': 'NONE'
            })
コード例 #9
0
# testorders.py
# an order dictionary that won't be matched

from betman import order, const

# BDAQ
# six nations, england
o1 = order.Order(1, 17676144, 0.5, 100.0, 1, **{'mid': 3291920})
# six nations, wales
o2 = order.Order(1, 17676142, 0.5, 1.22, 2, **{'mid': 3291920})

# BF
# six nations, england
o3 = order.Order(1, 15593, 2.0, 10.0, 1, **{
    'mid': 109590806,
    'persistence': 'NONE'
})
# six nations, wales
o4 = order.Order(2, 14118, 2.05, 10.0, 1, **{
    'mid': 109590806,
    'persistence': 'NONE'
})
d = {1: [], 2: []}