Skip to content

Instantly share code, notes, and snippets.

@idler921
Forked from prof7bit/.gitignore
Last active December 18, 2015 01:59

Revisions

  1. idler921 revised this gist Jun 4, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -85,11 +85,11 @@ def slot_keypress(self, gox, (key)):
    if vol_buy > 0:
    self.debug("buy %f at market" %
    goxapi.int2float(vol_buy, "BTC"))
    # gox.buy(0, vol_buy)
    gox.buy(0, vol_buy)
    else:
    self.debug("sell %f at market" %
    goxapi.int2float(-vol_buy, "BTC"))
    # gox.sell(0, -vol_buy)
    gox.sell(0, -vol_buy)



  2. idler921 revised this gist Jun 4, 2013. 1 changed file with 41 additions and 33 deletions.
    74 changes: 41 additions & 33 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,18 @@
    """
    The portfolio rebalancing bot will buy and sell to maintain a
    constant asset allocation ratio of exactly 50/50 = fiat/BTC
    constant asset allocation ratio of exactly 20/80 = fiat/BTC
    """

    import strategy
    import goxapi

    DISTANCE = 7 # percent price distance of next rebalancing orders
    FIAT_COLD = 0 # Amount of Fiat stored at home but included in calculations
    COIN_COLD = 0 # Amount of Coin stored at home but included in calculations

    DISTANCE = 3 # percent price distance of next rebalancing orders
    MARKER = 7 # lowest digit of price to identify bot's own orders
    COIN = 1E8 # number of satoshi per coin, this is a constant.
    FAITLV = 2
    BTCLV = 8

    bfr = BTCLV / FAITLV

    def add_marker(price, marker):
    """encode a marker in the price value to find bot's own orders"""
    @@ -36,6 +38,9 @@ def __init__(self, gox):
    strategy.Strategy.__init__(self, gox)
    self.temp_halt = False

    def slot_before_unload(self, _sender, _data):
    pass

    def slot_keypress(self, gox, (key)):
    """a key has been pressed"""

    @@ -55,9 +60,9 @@ def slot_keypress(self, gox, (key)):
    self.place_orders()

    if key == ord("u"):
    # update the own order list and wallet by forcing what
    # normally happens only after reconnect
    gox.client.channel_subscribe(False)
    # update the own order list, history, depth and wallet
    # by forcing what normally happens only after reconnect
    gox.client.channel_subscribe()

    if key == ord("i"):
    # print some information into the log file about
    @@ -66,9 +71,9 @@ def slot_keypress(self, gox, (key)):
    vol_buy = self.get_buy_at_price(price)
    price_balanced = self.get_price_where_it_was_balanced()
    self.debug("BTC difference at current price:",
    gox.base2float(vol_buy))
    goxapi.int2float(vol_buy, "BTC"))
    self.debug("Price where it would be balanced:",
    gox.quote2float(price_balanced))
    goxapi.int2float(price_balanced, self.gox.currency))

    if key == ord("b"):
    # manually rebalance with market order at current price
    @@ -79,12 +84,14 @@ def slot_keypress(self, gox, (key)):
    self.cancel_orders()
    if vol_buy > 0:
    self.debug("buy %f at market" %
    gox.base2float(vol_buy))
    gox.buy(0, vol_buy)
    goxapi.int2float(vol_buy, "BTC"))
    # gox.buy(0, vol_buy)
    else:
    self.debug("sell %f at market" %
    gox.base2float(-vol_buy))
    gox.sell(0, -vol_buy)
    goxapi.int2float(-vol_buy, "BTC"))
    # gox.sell(0, -vol_buy)



    def cancel_orders(self):
    """cancel all rebalancing orders, we identify
    @@ -104,30 +111,31 @@ def get_price_where_it_was_balanced(self):
    filled (because by definition it should be quite exactly balanced then),
    so even after missing the trade message due to disconnect it should be
    possible to place the next 2 orders precisely around the new center"""
    gox = self.gox
    fiat_have = gox.quote2float(gox.wallet[gox.curr_quote]) + FIAT_COLD
    btc_have = gox.base2float(gox.wallet[gox.curr_base]) + COIN_COLD
    return gox.quote2int(fiat_have / btc_have)
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    return goxapi.float2int(fiat_have * bfr / btc_have , currency)

    def get_buy_at_price(self, price_int):
    """calculate amount of BTC needed to buy at price to achieve
    rebalancing. price and return value are in mtgox integer format"""
    gox = self.gox
    fiat_have = gox.quote2float(gox.wallet[gox.curr_quote]) + FIAT_COLD
    btc_have = gox.base2float(gox.wallet[gox.curr_base]) + COIN_COLD
    price_then = gox.quote2float(price_int)
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    price_then = goxapi.int2float(price_int, currency)

    btc_value_then = btc_have * price_then
    diff = fiat_have - btc_value_then
    diff = (fiat_have * bfr - btc_value_then)/bfr
    diff_btc = diff / price_then
    must_buy = diff_btc / 2
    return self.gox.base2int(must_buy)
    must_buy = diff_btc / (BTCLV+FAITLV) * FAITLV
    return goxapi.float2int(must_buy, "BTC")

    def place_orders(self):
    """place two new rebalancing orders above and below center price"""
    center = self.get_price_where_it_was_balanced()
    self.debug(
    "center is %f" % self.gox.quote2float(center))
    "center is %f" % goxapi.int2float(center, self.gox.currency))
    currency = self.gox.currency
    step = int(center * DISTANCE / 100.0)
    next_sell = mark_own(center + step)
    next_buy = mark_own(center - step)
    @@ -144,17 +152,17 @@ def place_orders(self):
    self.debug("WARNING! minimal buy amount adjusted to 0.01")

    self.debug("new buy order %f at %f" % (
    self.gox.base2float(buy_amount),
    self.gox.quote2float(next_buy)
    goxapi.int2float(buy_amount, "BTC"),
    goxapi.int2float(next_buy, currency)
    ))
    self.gox.buy(next_buy, buy_amount)

    self.debug("new sell order %f at %f" % (
    self.gox.base2float(sell_amount),
    self.gox.quote2float(next_sell)
    goxapi.int2float(sell_amount, "BTC"),
    goxapi.int2float(next_sell, currency)
    ))
    self.gox.sell(next_sell, sell_amount)

    def slot_trade(self, gox, (date, price, volume, typ, own)):
    """a trade message has been receivd"""
    # not interested in other people's trades
    @@ -168,8 +176,8 @@ def slot_trade(self, gox, (date, price, volume, typ, own)):
    text = {"bid": "sold", "ask": "bought"}[typ]
    self.debug("*** %s %f at %f" % (
    text,
    gox.base2float(volume),
    gox.quote2float(price)
    goxapi.int2float(volume, "BTC"),
    goxapi.int2float(price, gox.currency)
    ))
    self.check_trades()

  3. @prof7bit prof7bit revised this gist May 16, 2013. 1 changed file with 26 additions and 30 deletions.
    56 changes: 26 additions & 30 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -4,9 +4,11 @@
    """

    import strategy
    import goxapi

    DISTANCE = 7 # percent price distance of next rebalancing orders
    FIAT_COLD = 0 # Amount of Fiat stored at home but included in calculations
    COIN_COLD = 0 # Amount of Coin stored at home but included in calculations

    MARKER = 7 # lowest digit of price to identify bot's own orders
    COIN = 1E8 # number of satoshi per coin, this is a constant.

    @@ -34,9 +36,6 @@ def __init__(self, gox):
    strategy.Strategy.__init__(self, gox)
    self.temp_halt = False

    def slot_before_unload(self, _sender, _data):
    pass

    def slot_keypress(self, gox, (key)):
    """a key has been pressed"""

    @@ -56,9 +55,9 @@ def slot_keypress(self, gox, (key)):
    self.place_orders()

    if key == ord("u"):
    # update the own order list, history, depth and wallet
    # by forcing what normally happens only after reconnect
    gox.client.channel_subscribe()
    # update the own order list and wallet by forcing what
    # normally happens only after reconnect
    gox.client.channel_subscribe(False)

    if key == ord("i"):
    # print some information into the log file about
    @@ -67,9 +66,9 @@ def slot_keypress(self, gox, (key)):
    vol_buy = self.get_buy_at_price(price)
    price_balanced = self.get_price_where_it_was_balanced()
    self.debug("BTC difference at current price:",
    goxapi.int2float(vol_buy, "BTC"))
    gox.base2float(vol_buy))
    self.debug("Price where it would be balanced:",
    goxapi.int2float(price_balanced, self.gox.currency))
    gox.quote2float(price_balanced))

    if key == ord("b"):
    # manually rebalance with market order at current price
    @@ -80,15 +79,13 @@ def slot_keypress(self, gox, (key)):
    self.cancel_orders()
    if vol_buy > 0:
    self.debug("buy %f at market" %
    goxapi.int2float(vol_buy, "BTC"))
    gox.base2float(vol_buy))
    gox.buy(0, vol_buy)
    else:
    self.debug("sell %f at market" %
    goxapi.int2float(-vol_buy, "BTC"))
    gox.base2float(-vol_buy))
    gox.sell(0, -vol_buy)



    def cancel_orders(self):
    """cancel all rebalancing orders, we identify
    them through the marker in the price value"""
    @@ -107,31 +104,30 @@ def get_price_where_it_was_balanced(self):
    filled (because by definition it should be quite exactly balanced then),
    so even after missing the trade message due to disconnect it should be
    possible to place the next 2 orders precisely around the new center"""
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    return goxapi.float2int(fiat_have / btc_have, currency)
    gox = self.gox
    fiat_have = gox.quote2float(gox.wallet[gox.curr_quote]) + FIAT_COLD
    btc_have = gox.base2float(gox.wallet[gox.curr_base]) + COIN_COLD
    return gox.quote2int(fiat_have / btc_have)

    def get_buy_at_price(self, price_int):
    """calculate amount of BTC needed to buy at price to achieve
    rebalancing. price and return value are in mtgox integer format"""
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    price_then = goxapi.int2float(price_int, currency)
    gox = self.gox
    fiat_have = gox.quote2float(gox.wallet[gox.curr_quote]) + FIAT_COLD
    btc_have = gox.base2float(gox.wallet[gox.curr_base]) + COIN_COLD
    price_then = gox.quote2float(price_int)

    btc_value_then = btc_have * price_then
    diff = fiat_have - btc_value_then
    diff_btc = diff / price_then
    must_buy = diff_btc / 2
    return goxapi.float2int(must_buy, "BTC")
    return self.gox.base2int(must_buy)

    def place_orders(self):
    """place two new rebalancing orders above and below center price"""
    center = self.get_price_where_it_was_balanced()
    self.debug(
    "center is %f" % goxapi.int2float(center, self.gox.currency))
    currency = self.gox.currency
    "center is %f" % self.gox.quote2float(center))
    step = int(center * DISTANCE / 100.0)
    next_sell = mark_own(center + step)
    next_buy = mark_own(center - step)
    @@ -148,14 +144,14 @@ def place_orders(self):
    self.debug("WARNING! minimal buy amount adjusted to 0.01")

    self.debug("new buy order %f at %f" % (
    goxapi.int2float(buy_amount, "BTC"),
    goxapi.int2float(next_buy, currency)
    self.gox.base2float(buy_amount),
    self.gox.quote2float(next_buy)
    ))
    self.gox.buy(next_buy, buy_amount)

    self.debug("new sell order %f at %f" % (
    goxapi.int2float(sell_amount, "BTC"),
    goxapi.int2float(next_sell, currency)
    self.gox.base2float(sell_amount),
    self.gox.quote2float(next_sell)
    ))
    self.gox.sell(next_sell, sell_amount)

    @@ -172,8 +168,8 @@ def slot_trade(self, gox, (date, price, volume, typ, own)):
    text = {"bid": "sold", "ask": "bought"}[typ]
    self.debug("*** %s %f at %f" % (
    text,
    goxapi.int2float(volume, "BTC"),
    goxapi.int2float(price, gox.currency)
    gox.base2float(volume),
    gox.quote2float(price)
    ))
    self.check_trades()

  4. @prof7bit prof7bit revised this gist Apr 20, 2013. 1 changed file with 33 additions and 19 deletions.
    52 changes: 33 additions & 19 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -32,7 +32,6 @@ class Strategy(strategy.Strategy):
    """a protfolio rebalancing bot"""
    def __init__(self, gox):
    strategy.Strategy.__init__(self, gox)
    self.last_trade = 0
    self.temp_halt = False

    def slot_before_unload(self, _sender, _data):
    @@ -42,29 +41,38 @@ def slot_keypress(self, gox, (key)):
    """a key has been pressed"""

    if key == ord("c"):
    # remove existing rebalancing orders
    # cancel existing rebalancing orders and suspend trading
    self.debug("canceling all rebalancing orders")
    self.temp_halt = True
    self.cancel_orders()

    if key == ord("p"):
    # create the initial two rebalancing orders. Before you
    # do this the portfolio should already be balanced.
    # create the initial two rebalancing orders and start trading.
    # Before you do this the portfolio should already be balanced.
    # use "i" to show current status and "b" to rebalance with a
    # market order at current price.
    self.debug("adding new initial rebalancing orders")
    book = self.gox.orderbook
    self.temp_halt = False
    self.place_orders((book.bid + book.ask) / 2)
    self.place_orders()

    if key == ord("u"):
    # update the own order list, history, depth and wallet
    # by forcing what normally happens only after reconnect
    gox.client.channel_subscribe()

    if key == ord("i"):
    # print some information into the log file about
    # current status (how much currently out of balance)
    price = (gox.orderbook.bid + gox.orderbook.ask) / 2
    vol_buy = self.get_buy_at_price(price)
    self.debug("BTC difference:",
    price_balanced = self.get_price_where_it_was_balanced()
    self.debug("BTC difference at current price:",
    goxapi.int2float(vol_buy, "BTC"))
    self.debug("Price where it would be balanced:",
    goxapi.int2float(price_balanced, self.gox.currency))

    if key == ord("b"):
    # manually rebalance with market order at current price
    price = (gox.orderbook.bid + gox.orderbook.ask) / 2
    vol_buy = self.get_buy_at_price(price)
    if abs(vol_buy) > 0.01 * COIN:
    @@ -92,6 +100,18 @@ def cancel_orders(self):
    for order in must_cancel:
    self.gox.cancel(order.oid)

    def get_price_where_it_was_balanced(self):
    """get the price at which it was perfectly balanced, given the current
    BTC and Fiat account balances. Immediately after a rebalancing order was
    filled this should be pretty much excactly the price where the order was
    filled (because by definition it should be quite exactly balanced then),
    so even after missing the trade message due to disconnect it should be
    possible to place the next 2 orders precisely around the new center"""
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    return goxapi.float2int(fiat_have / btc_have, currency)

    def get_buy_at_price(self, price_int):
    """calculate amount of BTC needed to buy at price to achieve
    rebalancing. price and return value are in mtgox integer format"""
    @@ -106,8 +126,11 @@ def get_buy_at_price(self, price_int):
    must_buy = diff_btc / 2
    return goxapi.float2int(must_buy, "BTC")

    def place_orders(self, center):
    def place_orders(self):
    """place two new rebalancing orders above and below center price"""
    center = self.get_price_where_it_was_balanced()
    self.debug(
    "center is %f" % goxapi.int2float(center, self.gox.currency))
    currency = self.gox.currency
    step = int(center * DISTANCE / 100.0)
    next_sell = mark_own(center + step)
    @@ -152,7 +175,6 @@ def slot_trade(self, gox, (date, price, volume, typ, own)):
    goxapi.int2float(volume, "BTC"),
    goxapi.int2float(price, gox.currency)
    ))
    self.last_trade = price
    self.check_trades()

    def slot_owns_changed(self, orderbook, _dummy):
    @@ -189,15 +211,7 @@ def check_trades(self):

    # if count is exacty 1 then one of the orders must have been filled,
    # now we cancel the other one and place two fresh orders in the
    # distance of DISTANCE around current price.
    # distance of DISTANCE around center price.
    if count == 1:
    price = self.last_trade
    self.last_trade = 0
    if not price:
    price = (book.ask + book.bid) / 2
    self.debug(
    "*** missed trade message, using current price %f" %
    goxapi.int2float(price, self.gox.currency)
    )
    self.cancel_orders()
    self.place_orders(price)
    self.place_orders()
  5. @prof7bit prof7bit revised this gist Apr 20, 2013. 1 changed file with 65 additions and 12 deletions.
    77 changes: 65 additions & 12 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -33,6 +33,7 @@ class Strategy(strategy.Strategy):
    def __init__(self, gox):
    strategy.Strategy.__init__(self, gox)
    self.last_trade = 0
    self.temp_halt = False

    def slot_before_unload(self, _sender, _data):
    pass
    @@ -43,15 +44,43 @@ def slot_keypress(self, gox, (key)):
    if key == ord("c"):
    # remove existing rebalancing orders
    self.debug("canceling all rebalancing orders")
    self.temp_halt = True
    self.cancel_orders()

    if key == ord("p"):
    # create the initial two rebalancing orders. Before you
    # do this the portfolio should already be balanced.
    self.debug("adding new initial rebalancing orders")
    book = self.gox.orderbook
    self.temp_halt = False
    self.place_orders((book.bid + book.ask) / 2)

    if key == ord("u"):
    gox.client.channel_subscribe()

    if key == ord("i"):
    price = (gox.orderbook.bid + gox.orderbook.ask) / 2
    vol_buy = self.get_buy_at_price(price)
    self.debug("BTC difference:",
    goxapi.int2float(vol_buy, "BTC"))

    if key == ord("b"):
    price = (gox.orderbook.bid + gox.orderbook.ask) / 2
    vol_buy = self.get_buy_at_price(price)
    if abs(vol_buy) > 0.01 * COIN:
    self.temp_halt = True
    self.cancel_orders()
    if vol_buy > 0:
    self.debug("buy %f at market" %
    goxapi.int2float(vol_buy, "BTC"))
    gox.buy(0, vol_buy)
    else:
    self.debug("sell %f at market" %
    goxapi.int2float(-vol_buy, "BTC"))
    gox.sell(0, -vol_buy)



    def cancel_orders(self):
    """cancel all rebalancing orders, we identify
    them through the marker in the price value"""
    @@ -117,8 +146,13 @@ def slot_trade(self, gox, (date, price, volume, typ, own)):
    if not is_own(price):
    return

    text = {"bid": "sold", "ask": "bought"}[typ]
    self.debug("*** %s %f at %f" % (
    text,
    goxapi.int2float(volume, "BTC"),
    goxapi.int2float(price, gox.currency)
    ))
    self.last_trade = price
    self.debug("trade (type: %s) detected!" % typ)
    self.check_trades()

    def slot_owns_changed(self, orderbook, _dummy):
    @@ -127,24 +161,43 @@ def slot_owns_changed(self, orderbook, _dummy):

    def check_trades(self):
    """find out if we need to place new orders and do it if neccesary"""
    # don't place double orders. only act if a trade has happened.
    if not self.last_trade:

    # bot temporarily disabled
    if self.temp_halt:
    return

    # since we have always exactly 2 orders, a bid and an ask we
    # must count the open orders and we know we must act when there
    # is exactly one open order.
    # still waiting for submitted orders,
    # can wait for next signal
    if self.gox.count_submitted:
    return

    # we count the open and pending orders
    count = 0
    for order in self.gox.orderbook.owns:
    count_pending = 0
    book = self.gox.orderbook
    for order in book.owns:
    if is_own(order.price):
    count += 1
    if order.status == "open":
    count += 1
    else:
    count_pending += 1

    # as long as there are ANY pending orders around we
    # just do nothing and wait for the next signal
    if count_pending:
    return

    # if count is exacty 1 then one of the orders must have been filled,
    # now we cancel the other one and place two fresh orders in the
    # distance of DISTANCE around current price.
    if count == 1:
    self.cancel_orders()
    self.place_orders(self.last_trade)

    # reset the flag again
    price = self.last_trade
    self.last_trade = 0
    if not price:
    price = (book.ask + book.bid) / 2
    self.debug(
    "*** missed trade message, using current price %f" %
    goxapi.int2float(price, self.gox.currency)
    )
    self.cancel_orders()
    self.place_orders(price)
  6. @prof7bit prof7bit created this gist Apr 16, 2013.
    150 changes: 150 additions & 0 deletions _balancer.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    """
    The portfolio rebalancing bot will buy and sell to maintain a
    constant asset allocation ratio of exactly 50/50 = fiat/BTC
    """

    import strategy
    import goxapi

    DISTANCE = 7 # percent price distance of next rebalancing orders
    MARKER = 7 # lowest digit of price to identify bot's own orders
    COIN = 1E8 # number of satoshi per coin, this is a constant.

    def add_marker(price, marker):
    """encode a marker in the price value to find bot's own orders"""
    return price / 10 * 10 + marker

    def has_marker(price, marker):
    """return true if the price value has the marker"""
    return (price % 10) == marker

    def mark_own(price):
    """return the price with our own marker embedded"""
    return add_marker(price, MARKER)

    def is_own(price):
    """return true if this price has our own marker"""
    return has_marker(price, MARKER)



    class Strategy(strategy.Strategy):
    """a protfolio rebalancing bot"""
    def __init__(self, gox):
    strategy.Strategy.__init__(self, gox)
    self.last_trade = 0

    def slot_before_unload(self, _sender, _data):
    pass

    def slot_keypress(self, gox, (key)):
    """a key has been pressed"""

    if key == ord("c"):
    # remove existing rebalancing orders
    self.debug("canceling all rebalancing orders")
    self.cancel_orders()

    if key == ord("p"):
    # create the initial two rebalancing orders. Before you
    # do this the portfolio should already be balanced.
    self.debug("adding new initial rebalancing orders")
    book = self.gox.orderbook
    self.place_orders((book.bid + book.ask) / 2)

    def cancel_orders(self):
    """cancel all rebalancing orders, we identify
    them through the marker in the price value"""
    must_cancel = []
    for order in self.gox.orderbook.owns:
    if is_own(order.price):
    must_cancel.append(order)

    for order in must_cancel:
    self.gox.cancel(order.oid)

    def get_buy_at_price(self, price_int):
    """calculate amount of BTC needed to buy at price to achieve
    rebalancing. price and return value are in mtgox integer format"""
    currency = self.gox.currency
    fiat_have = goxapi.int2float(self.gox.wallet[currency], currency)
    btc_have = goxapi.int2float(self.gox.wallet["BTC"], "BTC")
    price_then = goxapi.int2float(price_int, currency)

    btc_value_then = btc_have * price_then
    diff = fiat_have - btc_value_then
    diff_btc = diff / price_then
    must_buy = diff_btc / 2
    return goxapi.float2int(must_buy, "BTC")

    def place_orders(self, center):
    """place two new rebalancing orders above and below center price"""
    currency = self.gox.currency
    step = int(center * DISTANCE / 100.0)
    next_sell = mark_own(center + step)
    next_buy = mark_own(center - step)

    sell_amount = -self.get_buy_at_price(next_sell)
    buy_amount = self.get_buy_at_price(next_buy)

    if sell_amount < 0.01 * COIN:
    sell_amount = int(0.01 * COIN)
    self.debug("WARNING! minimal sell amount adjusted to 0.01")

    if buy_amount < 0.01 * COIN:
    buy_amount = int(0.01 * COIN)
    self.debug("WARNING! minimal buy amount adjusted to 0.01")

    self.debug("new buy order %f at %f" % (
    goxapi.int2float(buy_amount, "BTC"),
    goxapi.int2float(next_buy, currency)
    ))
    self.gox.buy(next_buy, buy_amount)

    self.debug("new sell order %f at %f" % (
    goxapi.int2float(sell_amount, "BTC"),
    goxapi.int2float(next_sell, currency)
    ))
    self.gox.sell(next_sell, sell_amount)

    def slot_trade(self, gox, (date, price, volume, typ, own)):
    """a trade message has been receivd"""
    # not interested in other people's trades
    if not own:
    return

    # not interested in manually entered (not bot) trades
    if not is_own(price):
    return

    self.last_trade = price
    self.debug("trade (type: %s) detected!" % typ)
    self.check_trades()

    def slot_owns_changed(self, orderbook, _dummy):
    """status or amount of own open orders has changed"""
    self.check_trades()

    def check_trades(self):
    """find out if we need to place new orders and do it if neccesary"""
    # don't place double orders. only act if a trade has happened.
    if not self.last_trade:
    return

    # since we have always exactly 2 orders, a bid and an ask we
    # must count the open orders and we know we must act when there
    # is exactly one open order.
    count = 0
    for order in self.gox.orderbook.owns:
    if is_own(order.price):
    count += 1

    # if count is exacty 1 then one of the orders must have been filled,
    # now we cancel the other one and place two fresh orders in the
    # distance of DISTANCE around current price.
    if count == 1:
    self.cancel_orders()
    self.place_orders(self.last_trade)

    # reset the flag again
    self.last_trade = 0