def __init__(self, gox): strategy.Strategy.__init__(self, gox) gox.history.signal_changed.connect(self.slot_changed) self.already_executed = False if STOP_PRICE < 0: self.debug("initializing trailing stop: %f @ %f" % (STOP_VOLUME, STOP_PRICE)) self.stop_price = 0 self.trail_distance = goxapi.float2int(-STOP_PRICE, gox.currency) gox.history.signal_changed(gox.history, None) # fire the signal once else: self.debug("initializing stop loss: %f @ %f" % (STOP_VOLUME, STOP_PRICE)) self.stop_price = goxapi.float2int(STOP_PRICE, gox.currency) self.trail_distance = 0
class Strategy(strategy.Strategy): """a simple stoploss bot""" def __init__(self, gox): strategy.Strategy.__init__(self, gox) gox.stopOrders = [] gox.stopbot_active = False gox.stopbot_executed = strategy.goxapi.Signal() def slot_trade(self, gox, (date, last_price, volume, typ, own)): """a trade message has been received""" if gox.stopbot_active: for order in gox.stopOrders: stop_volume = float2int(order[1], gox.curr_base) stop_price = float2int(order[2], gox.curr_quote) if stop_volume > 0: if stop_price < 0: price_trail = last_price + stop_price if len(order) == 3: #on the first time run... order.append(stop_price) #store the trail distance order.append(price_trail ) #store the last trailing stop price stop_price = price_trail #set the stop price for this run elif len(order) == 5: #on all other subsequent runs if price_trail > order[ 4]: #if last trail price > old trail price order[ 4] = price_trail #store a new trail price stop_price = order[ 4] #then set it for the current run if last_price <= stop_price: self.debug( "StopLoss Executed. Market Sell %s %s (last trade was at or below: $%s)" % (order[1], gox.curr_base, order[2])) gox.stopbot_executed(order, None) if not SIMULATION: gox.sell(0, stop_volume) elif stop_volume < 0: if last_price >= stop_price: self.debug( "StopGain Executed. Market Buy %s %s (last trade was at or above: $%s)" % (abs(order[1]), gox.curr_base, order[2])) gox.stopbot_executed(order, None) if not SIMULATION: gox.buy(0, abs(stop_volume))
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 float2gox(value,currency): return float2int(value,currency)
def do_submit(self, price, volume): price = goxapi.float2int(price, self.gox.currency) volume = goxapi.float2int(volume, "BTC") self.gox.sell(price, volume)
def float2gox(value, currency): return float2int(value, currency)
def paint_depth_chart(self): """paint a depth chart""" # pylint: disable=C0103 if self.gox.currency == "JPY": BAR_LEFT_EDGE = 7 FORMAT_STRING = "%6.0f" else: BAR_LEFT_EDGE = 8 FORMAT_STRING = "%7.2f" def paint_depth(pos, price, vol, own, col_price): """paint one row of the depth chart""" i = 0 pricestr = FORMAT_STRING % goxapi.int2float(price, self.gox.currency) self.addstr(pos, 0, pricestr, col_price) for i in range(int(vol * mult_x)): # pylint: disable=E1101 self.win.addch(pos, BAR_LEFT_EDGE + i, curses.ACS_CKBOARD, col_bar) if own: self.addstr(pos, 1 + i + BAR_LEFT_EDGE, "o", col_own) self.win.bkgd(" ", COLOR_PAIR["chart_text"]) self.win.erase() book = self.gox.orderbook if not book.bid or not book.ask: # orderbook is not initialized yet, paint nothing return col_bar = COLOR_PAIR["book_vol"] col_bid = COLOR_PAIR["book_bid"] col_ask = COLOR_PAIR["book_ask"] col_own = COLOR_PAIR["book_own"] group = self.gox.config.get_float("goxtool", "depth_chart_group") if group == 0: group = 1 group = goxapi.float2int(group, self.gox.currency) bin_asks = [] bin_bids = [] mid = self.height / 2 # sum up the asks cnt = len(book.asks) bin_vol = 0 own_vol = 0 pos = mid - 1 i = 0 while i < cnt and pos >= 0: level = book.asks[i] price = level.price if i == 0: bin_price = int(math.ceil(float(price) / group) * group) if price > bin_price: bin_asks.append((bin_price, bin_vol, own_vol)) pos -= 1 bin_price = int(math.ceil(float(price) / group) * group) own_vol = level.own_volume else: own_vol += level.own_volume bin_vol += level.volume i += 1 #append the last one if bin_vol: bin_asks.append((bin_price, bin_vol, own_vol)) max_vol_ask = bin_vol # sum up the bids cnt = len(book.bids) bin_vol = 0 own_vol = 0 pos = mid + 1 i = 0 while i < cnt and pos < self.height: level = book.bids[i] price = level.price if i == 0: bin_price = int(math.floor(float(price) / group) * group) if price < bin_price: bin_bids.append((bin_price, bin_vol, own_vol)) pos += 1 bin_price = int(math.floor(float(price) / group) * group) own_vol = level.own_volume else: own_vol += level.own_volume bin_vol += level.volume * price / book.bid i += 1 #append the last one if bin_vol: bin_bids.append((bin_price, bin_vol, own_vol)) max_vol_bid = bin_vol if not max_vol_ask: return if not max_vol_bid: return max_vol_tot = max(max_vol_ask, max_vol_bid) mult_x = float(self.width - BAR_LEFT_EDGE - 1) / max_vol_tot # paint the asks pos = mid - 1 while len(bin_asks) and pos >= 0: (price, vol, own) = bin_asks.pop(0) paint_depth(pos, price, vol, own, col_ask) pos -= 1 # paint the bids pos = mid + 1 while len(bin_bids) and pos < self.height: (price, vol, own) = bin_bids.pop(0) paint_depth(pos, price, vol, own, col_bid) pos += 1
def paint(self): """paint the visible portion of the orderbook""" def paint_row(pos, price, vol, ownvol, color): """paint a row in the orderbook (bid or ask)""" self.addstr(pos, 0, goxapi.int2str(price, book.gox.currency), color) self.addstr(pos, 12, goxapi.int2str(vol, "BTC"), col_vol) if ownvol: self.addstr(pos, 28, goxapi.int2str(ownvol, "BTC"), col_own) self.win.bkgd(" ", COLOR_PAIR["book_text"]) self.win.erase() mid = self.height / 2 col_bid = COLOR_PAIR["book_bid"] col_ask = COLOR_PAIR["book_ask"] col_vol = COLOR_PAIR["book_vol"] col_own = COLOR_PAIR["book_own"] sum_total = self.gox.config.get_bool("goxtool", "orderbook_sum_total") group = self.gox.config.get_float("goxtool", "orderbook_group") group = goxapi.float2int(group, self.gox.currency) if group == 0: group = 1 # print the asks book = self.gox.orderbook cnt = len(book.asks) pos = mid - 1 i = 0 vol = 0 ownvol = 0 while pos >= 0 and i < cnt: price = book.asks[i].price if i == 0: this_bin = price vol = book.asks[i].volume ownvol = book.asks[i].own_volume else: if price <= this_bin: # still the same bin, add volumes vol += book.asks[i].volume ownvol += book.asks[i].own_volume else: # paint the existing bin and... paint_row(pos, this_bin, vol, ownvol, col_ask) pos -= 1 # ...begin a new bin this_bin = int(math.ceil(float(price) / group) * group) if sum_total: vol += book.asks[i].volume else: vol = book.asks[i].volume ownvol = book.asks[i].own_volume i += 1 if cnt and pos >= 0: paint_row(pos, this_bin, vol, ownvol, col_ask) # print the bids cnt = len(book.bids) pos = mid + 1 i = 0 vol = 0 ownvol = 0 while pos < self.height and i < cnt: price = book.bids[i].price if i == 0: this_bin = price vol = book.bids[i].volume ownvol = book.bids[i].own_volume else: if price >= this_bin: # still the same bin, add volumes vol += book.bids[i].volume ownvol += book.bids[i].own_volume else: # paint the current bin and... paint_row(pos, this_bin, vol, ownvol, col_bid) pos += 1 # ...begin a new bin this_bin = int(math.floor(float(price) / group) * group) if sum_total: vol += book.bids[i].volume else: vol = book.bids[i].volume ownvol = book.bids[i].own_volume i += 1 if cnt and pos < self.height: paint_row(pos, this_bin, vol, ownvol, col_bid)