Skip to content
This repository has been archived by the owner on Jan 23, 2024. It is now read-only.

Rename buy/sell to make_offer/make_bid #159

Open
wants to merge 6 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
5,174 changes: 2,080 additions & 3,094 deletions abce/trade.c

Large diffs are not rendered by default.

239 changes: 171 additions & 68 deletions abce/trade.py

Large diffs are not rendered by default.

198 changes: 145 additions & 53 deletions abce/trade.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class Trade:

1. An agent sends an offer. :meth:`~.sell`

*The good offered is blocked and self.possession(...) does shows the decreased amount.*
*ABCE does not allow you to sell the same good twice; self.free(good) shows how much good is not reserved yet*

2. **Next subround:** An agent receives the offer :meth:`~.get_offers`, and can
:meth:`~.accept`, :meth:`~.reject` or partially accept it. :meth:`~.accept`
Expand All @@ -171,7 +171,7 @@ class Trade:
3. **Next subround:**

- in case of acceptance *the money is automatically credited.*
- in case of partial acceptance *the money is credited and part of the blocked good is unblocked.*
- in case of partial acceptance *the money is credited and part of the reserved good is unblocked.*
- in case of rejection *the good is unblocked.*

Analogously for buying: :meth:`~.buy`
Expand Down Expand Up @@ -249,25 +249,54 @@ class Trade:
self.database_connection.put(["trade_log", self._trade_log, self.time])
self._trade_log = defaultdict(int)

def get_buy_offers_all(self, descending=False, sorted=True):
goods = list(self._open_offers_buy.keys())
return {good: self.get_offers(good, descending, sorted) for good in goods}
def get_bids_all(self, descending=True, sorted=True):
""" returns all bids in a dictionary, with goods as key. The in each
goods-category the goods are ordered by price. The order can be reversed
by setting descending=False

def get_sell_offers_all(self, descending=False, sorted=True):
goods = list(self._open_offers_sell.keys())
*Bids that are not accepted in the same subround are
automatically rejected.* However you can also manually reject.

Args:

descending(=True):
False for descending True for ascending by price

sorted(=True):
Whether offers are sorted by price. Faster if False.

Returns:

a dictionary with good types as keys and list of :class:`abce.trade.Offer`
as values

Example::

oo = get_bids_all()
for good_category in oo:
print('The most expensive offer for good in category' + good_category
+ ' is ' + good_category[0])
for bid in oo[good_category]:
if bid.price < 0.5:
self.accept(bid)

for bid in oo.beer:
print(bid.price, bid.sender_group, bid.sender_id)
"""
goods = list(self._open_offers_buy.keys())
return {good: self.get_offers(good, descending, sorted) for good in goods}

def get_offers_all(self, descending=False, sorted=True):
""" returns all offers in a dictionary, with goods as key. The in each
goods-category the goods are ordered by price. The order can be reversed
by setting descending=True

*Offers that are not accepted in the same subround (def block) are
*Offers that are not accepted in the same subround are
automatically rejected.* However you can also manually reject.

Args:

descending(optional):
descending(=False):
is a bool. False for descending True for ascending by price

sorted(default=True):
Expand All @@ -291,10 +320,47 @@ class Trade:
for offer in oo.beer:
print(offer.price, offer.sender_group, offer.sender_id)
"""
goods = list(self._open_offers_sell.keys()) + list(self._open_offers_buy.keys())
goods = list(self._open_offers_sell.keys())
return {good: self.get_offers(good, descending, sorted) for good in goods}

def get_buy_offers(self, good, sorted=True, descending=False, shuffled=True):
def get_bids(self, good, sorted=True, descending=True, shuffled=True):
""" returns all bids of the 'good' ordered by price.

*Bids that are not accepted in the same subround are
automatically rejected.* However you can also manually reject.

peek_bids can be used to look at the bids without them being
rejected automatically

Args:
good:
the good which should be retrieved

sorted(=True):
Whether bids are sorted by price. Faster if False.

descending(=True):
False for descending True for ascending by price

shuffled(=True):
whether the order of messages is randomized or correlated with
the ID of the agent. Setting this to False speeds up the
simulation considerably, but introduces a bias.

Returns:
A list of :class:`abce.trade.Offer` ordered by price.

Example::

bids = get_bids('books')
for bid in bids:
if offer.price < 50:
self.accept(bid)
elif bid.price < 100:
self.accept(bid, 1)
else:
self.reject(bid) # optional
"""
ret = list(self._open_offers_buy[good].values())
self._polled_offers.update(self._open_offers_buy[good])
del self._open_offers_buy[good]
Expand All @@ -304,20 +370,10 @@ class Trade:
ret.sort(key=lambda objects: objects.price, reverse=descending)
return ret

def get_sell_offers(self, good, sorted=True, descending=False, shuffled=True):
ret = list(self._open_offers_sell[good].values())
self._polled_offers.update(self._open_offers_sell[good])
del self._open_offers_sell[good]
if shuffled:
random.shuffle(ret)
if sorted:
ret.sort(key=lambda objects: objects.price, reverse=descending)
return ret

def get_offers(self, good, sorted=True, descending=False, shuffled=True):
""" returns all offers of the 'good' ordered by price.

*Offers that are not accepted in the same subround (def block) are
*Offers that are not accepted in the same subround are
automatically rejected.* However you can also manually reject.

peek_offers can be used to look at the offers without them being
Expand All @@ -327,13 +383,13 @@ class Trade:
good:
the good which should be retrieved

sorted(bool, default=True):
sorted(=True):
Whether offers are sorted by price. Faster if False.

descending(bool, default=False):
descending(=False):
False for descending True for ascending by price

shuffled(bool, default=True):
shuffled(=True):
whether the order of messages is randomized or correlated with
the ID of the agent. Setting this to False speeds up the
simulation considerably, but introduces a bias.
Expand All @@ -352,27 +408,52 @@ class Trade:
else:
self.reject(offer) # optional
"""
ret = (self.get_buy_offers(good, descending=False, sorted=False, shuffled=False) +
self.get_sell_offers(good, descending=False, sorted=False, shuffled=False))
ret = list(self._open_offers_sell[good].values())
self._polled_offers.update(self._open_offers_sell[good])
del self._open_offers_sell[good]
if shuffled:
random.shuffle(ret)
if sorted:
ret.sort(key=lambda objects: objects.price, reverse=descending)
return ret

def peak_buy_offers(self, good, sorted=True, descending=False, shuffled=True):
ret = []
for offer in self._open_offers_buy[good].values():
ret.append(offer)
if shuffled:
random.shuffle(ret)
if sorted:
ret.sort(key=lambda objects: objects.price, reverse=descending)
return ret

def peak_sell_offers(self, good, sorted=True, descending=False, shuffled=True):
def peak_bids(self, good, sorted=True, descending=True, shuffled=True):
""" returns a peak on all bids for the 'good' ordered by price.
Peaked bids can not be accepted or rejected and they do not
expire.

Args:
good:
the good which should be retrieved
descending(bool, default=False):
False for descending True for ascending by price

sorted(=True):
whether the bids are sorted, switch off for speed

descending(=True):
sort order

shuffled(=True):
randomizes equal prized bids, switch off for speed

Returns:
A list of bids ordered by price

Example::

bids = get_bids('books')
for bid in bids:
if bid.price < 50:
self.accept(bid)
elif bid.price < 100:
self.accept(bid, 1)
else:
self.reject(bid) # optional
"""
ret = []
for offer in self._open_offers_sell[good].values():
for offer in self._open_offers_buy[good].values():
ret.append(offer)
if shuffled:
random.shuffle(ret)
Expand All @@ -391,6 +472,17 @@ class Trade:
descending(bool, default=False):
False for descending True for ascending by price


sorted(=True):
whether the bids are sorted, switch off for speed

descending(=False):
sort order

shuffled(=True):
randomizes equal prized bids, switch off for speed


Returns:
A list of offers ordered by price

Expand All @@ -405,16 +497,17 @@ class Trade:
else:
self.reject(offer) # optional
"""
ret = (self.peak_buy_offers(good, sorted=False, descending=False, shuffled=False) +
self.peak_sell_offers(good, sorted=False, descending=False, shuffled=False))
ret = []
for offer in self._open_offers_sell[good].values():
ret.append(offer)
if shuffled:
random.shuffle(ret)
if sorted:
ret.sort(key=lambda objects: objects.price, reverse=descending)
return ret

def sell(self, receiver,
good, double quantity, double price, str currency='money', double epsilon=epsilon):
def make_offer(self, receiver,
good, double quantity, double price, str currency='money', double epsilon=epsilon):
""" commits to sell the quantity of good at price

The good is not available for the agent. When the offer is
Expand All @@ -423,11 +516,8 @@ class Trade:
accordingly)

Args:
receiver_group:
group of the receiving agent

receiver_id:
number of the receiving agent
receiver:
the receiving agent

'good':
name of the good
Expand All @@ -453,7 +543,7 @@ class Trade:
Example::

def subround_1(self):
self.offer = self.sell('household', 1, 'cookies', quantity=5, price=0.1)
self.offer = self.make_offer('household', 1, 'cookies', quantity=5, price=0.1)

def subround_2(self):
offer = self.info(self.offer)
Expand Down Expand Up @@ -496,7 +586,7 @@ class Trade:
self._send(receiver, 'abce_propose_sell', offer)
return offer

def buy(self, receiver, good,
def make_bid(self, receiver, good,
double quantity, double price, str currency='money', double epsilon=epsilon):
""" commits to sell the quantity of good at price

Expand All @@ -514,7 +604,7 @@ class Trade:
name of the good

quantity:
maximum units disposed to buy at this price
maximum units available to buy at this price

price:
price per unit
Expand Down Expand Up @@ -561,8 +651,8 @@ class Trade:
return offer

def accept(self, Offer offer, double quantity=-999, double epsilon=epsilon):
""" The buy or sell offer is accepted and cleared. If no quantity is
given the offer is fully accepted; If a quantity is given the offer is
""" The offer or bid is accepted and cleared. If no quantity is
given the offer/bid is fully accepted; If a quantity is given the offer/bid is
partial accepted.

Args:
Expand Down Expand Up @@ -792,8 +882,10 @@ class Trade:
a fraction of number to high or low. You can increase the
floating point tolerance. See troubleshooting -- floating point problems
"""
self.buy(receiver, good=good, quantity=quantity, price=0, epsilon=epsilon)
self.make_bid(receiver, good=good, quantity=quantity, price=0, epsilon=epsilon)

def get_take(self, *args, **kwargs):
return self.get_bids(*args, **kwargs)

# TODO when cython supports function overloading overload this function with compare_with_ties(int x, int y)
cdef int compare_with_ties(double x, double y):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def build_extension(self, ext):
'tornado == 4.3']


version = '0.9.5b0'
version = '0.9.6b0'


setup(name='abce',
Expand Down
4 changes: 2 additions & 2 deletions unittest/buy.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def one(self):
self.money = self['money']
self.price = random.uniform(0.0001, 1)
quantity = random.uniform(0, self.money / self.price)
self.offer = self.buy(('buy', self.id + 1),
self.offer = self.make_bid(('buy', self.id + 1),
'cookies', quantity, self.price)
assert self.not_reserved('money') == self.money - \
quantity * self.price
Expand All @@ -32,7 +32,7 @@ def two(self):
if self.id % 2 == 1:
self.create('cookies', random.uniform(0, 10000))
cookies = self['cookies']
oo = self.get_offers('cookies')
oo = self.get_bids('cookies')
assert oo
for offer in oo:
if random.randint(0, 10) == 0:
Expand Down
2 changes: 1 addition & 1 deletion unittest/sell.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def one(self):
self.cookies = self['cookies']
self.price = random.uniform(0.0001, 1)
quantity = random.uniform(0, self.cookies)
self.offer = self.sell(receiver=('sell', self.id + 1),
self.offer = self.make_offer(receiver=('sell', self.id + 1),
good='cookies', quantity=quantity, price=self.price)
assert self.not_reserved('cookies') == self.cookies - quantity

Expand Down
3 changes: 2 additions & 1 deletion unittest/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import start_individual_access
import start_service
import start_transform

import start_take

def run_test(name, test):
print(name + " test, 1 core")
Expand Down Expand Up @@ -41,3 +41,4 @@ def run_test(name, test):
run_test("start_individual_access", start_individual_access)
run_test("Test service", start_service)
run_test("Test Transform method", start_transform)
run_test("Test taking", start_take)
Loading