def attribute_to_partner(partner, partner_string_or_spec, amount): """Return the amount attributable to the given partner.""" try: a = attribute_to_partner_strict(partner, partner_string_or_spec, amount) except ValueError: a = Amount(0) return a
def attribute_to_residual(partner_string, amount, digits_of_precision=2): """Return the residual amount not attributable to any partners.""" spec = parse_partner_string(partner_string) v = round( float(amount) - sum(float(attribute_to_partner(partner, spec, amount)) for partner in spec), digits_of_precision, ) return Amount(str(v)).with_commodity(amount.commodity)
def get_open_orders(self, market=None): try: rawos = self.bitfinex_request('orders').json() except ValueError as e: self.logger.exception(e) orders = [] for o in rawos: if market is None or o['symbol'] == self.unformat_market(market): side = 'ask' if o['side'] == 'sell' else 'bid' # orders.append(em.LimitOrder(Amount("%s %s" % (o['price'], self.quote_commodity(market))), # Amount("%s %s" % (o['remaining_amount'], self.base_commodity(market))), side, # self.NAME, str(o['id']))) pair = self.format_market(o['symbol']) base = self.base_commodity(pair) amount = Amount("%s %s" % (o['remaining_amount'], base)) exec_amount = Amount("%s %s" % (o['executed_amount'], base)) quote = self.quote_commodity(pair) lo = None try: lo = get_order_by_order_id(str(o['id']), 'bitfinex', session=self.session) except Exception as e: self.logger.exception(e) if lo is None: lo = em.LimitOrder(Amount("%s %s" % (o['price'], quote)), amount, pair, side, self.NAME, str(o['id']), exec_amount=exec_amount, state='open') self.session.add(lo) else: lo.state = 'open' orders.append(lo) try: self.session.commit() except Exception as e: self.logger.exception(e) self.session.rollback() self.session.flush() return orders
def sync_balances(self): try: data = self.bitfinex_request('balances').json() except ValueError as e: self.logger.exception( '%s %s while sending to bitfinex get_balance' % (type(e), str(e))) if 'message' in data: self.logger.exception('%s while sending to bitfinex get_balance' % data['message']) self.logger.debug('balances data %s' % data) self.logger.debug('self.active_currencies %s' % self.active_currencies) total = Balance() available = Balance() for bal in data: comm = self.format_commodity(bal['currency']) total = total + Amount("%s %s" % (bal['amount'], comm)) available = available + Amount("%s %s" % (bal['available'], comm)) self.logger.debug("total balance: %s" % total) self.logger.debug("available balance: %s" % available) bals = {} for amount in total: comm = str(amount.commodity) bals[comm] = self.session.query(wm.Balance).filter(wm.Balance.user_id == self.manager_user.id) \ .filter(wm.Balance.currency == comm).one_or_none() if not bals[comm]: bals[comm] = wm.Balance( amount, available.commodity_amount(amount.commodity), comm, "", self.manager_user.id) self.session.add(bals[comm]) else: bals[comm].load_commodities() bals[comm].total = amount bals[comm].available = available.commodity_amount( amount.commodity) try: self.session.commit() except Exception as e: self.logger.exception(e) self.session.rollback() self.session.flush()
def attribute_to_partner_strict(partner, partner_string_or_spec, amount): """Return the amount attributable to the given partner.""" spec = ( partner_string_or_spec if isinstance(partner_string_or_spec, dict) else parse_partner_string(partner_string_or_spec) ) if partner not in spec: raise ValueError("Partner not found in partner string: %s" % partner) v100 = spec[partner] * float(amount.abs()) f_floor = round if isclose(v100, round(v100)) else floor v = amount.sign() * 0.01 * f_floor(v100) return Amount(str(v)).with_commodity(amount.commodity)
def sync_credits(self, rescan=False): for cur in self.active_currencies.union(set(["DRK"])): allknown = False end = time.time() while not allknown: history = self.get_dw_history(cur, end=end) if len(history) == 0: break allknown = True for row in history: if row['status'] != 'COMPLETED': continue rtype = row['type'].lower() found = 0 if rtype == "withdrawal": found = self.session.query(wm.Debit) \ .filter(wm.Debit.ref_id == 'bitfinex|%s' % row['id']) \ .count() elif rtype == "deposit": found = self.session.query(wm.Credit) \ .filter(wm.Credit.ref_id == 'bitfinex|%s' % row['id']) \ .count() if found != 0: print "; %s already known" % row['id'] continue allknown = False if float(row['timestamp']) < end: end = float(row['timestamp']) dtime = datetime.datetime.fromtimestamp( float(row['timestamp'])) asset = self.format_commodity(row['currency']) amount = Amount("%s %s" % (row['amount'], asset)) if row['status'] == 'COMPLETED': status = 'complete' elif row['status'] == 'CANCELED': status = 'canceled' else: status = 'unconfirmed' if rtype == "withdrawal": self.session.add( wm.Debit(amount, 0, row['address'], asset, "bitfinex", status, "bitfinex", "bitfinex|%s" % row['id'], self.manager_user.id, dtime)) elif rtype == "deposit": self.session.add( wm.Credit(amount, row['address'], asset, "bitfinex", status, "bitfinex", "bitfinex|%s" % row['id'], self.manager_user.id, dtime)) self.session.commit()
def test_cancel_order_order_id_no_prefix(self): bitfinex.sync_orders() order = create_order('bitfinex', 100, 0.1, 'BTC_USD', 'bid', session=bitfinex.session, expire=time.time() + 60) assert isinstance(order.id, int) assert isinstance(order.price, Amount) assert order.price == Amount("100 USD") assert order.state == 'pending' oorder = get_orders(oid=order.id, session=bitfinex.session) countdown = 1000 while oorder[0].state == 'pending' and countdown > 0: countdown -= 1 oorder = get_orders(oid=order.id, session=bitfinex.session) if oorder[0].state == 'pending': time.sleep(0.01) bitfinex.session.close() assert len(oorder) == 1 assert oorder[0].state == 'open' print oorder[0].order_id.split("|")[1] cancel_orders('bitfinex', order_id=oorder[0].order_id.split("|")[1]) #corder = get_orders(oid=order.id, session=bitfinex.session) corder = get_order_by_order_id(oorder[0].order_id, 'bitfinex', bitfinex.session) countdown = 1000 while (corder is None or corder.state != 'closed') and countdown > 0: countdown -= 1 #corder = get_orders(oid=order.id, session=bitfinex.session) corder = get_order_by_order_id(oorder[0].order_id, 'bitfinex', bitfinex.session) if (corder is None or corder.state != 'closed'): time.sleep(0.01) bitfinex.session.close() assert corder.state == 'closed'
def test_order_lifecycle(self): order = create_order('bitfinex', 100, 0.01, 'BTC_USD', 'bid', session=bitfinex.session, expire=time.time() + 60) assert isinstance(order.id, int) assert isinstance(order.price, Amount) assert order.price == Amount("100 USD") assert order.state == 'pending' oorder = get_orders(oid=order.id, session=bitfinex.session) countdown = 1000 while oorder[0].state == 'pending' and countdown > 0: countdown -= 1 oorder = get_orders(oid=order.id, session=bitfinex.session) if oorder[0].state == 'pending': time.sleep(0.01) bitfinex.session.close() assert len(oorder) == 1 assert oorder[0].state == 'open' bitfinex.session.close() cancel_orders('bitfinex', oid=order.id) countdown = 1000 corder = get_orders('bitfinex', order_id=oorder[0].order_id, session=bitfinex.session) while corder[0].state != 'closed' and countdown > 0: countdown -= 1 corder = get_orders('bitfinex', order_id=oorder[0].order_id, session=bitfinex.session) if corder[0].state != 'closed': time.sleep(0.01) bitfinex.session.close() assert len(corder) == 1 assert corder[0].state == 'closed'
file=sys.stderr) assert (False) ## if no match found, tag as default transaction if not isinstance(new_transaction, Transaction): if amountCmp > 0.0: new_transaction = unknown_revenue_default_transaction_.copy() elif amountCmp < 0.0: new_transaction = unknown_expense_default_transaction_.copy() else: new_transaction = unknown_equity_default_transaction_.copy() ## Convert FutureAmoutFractions to real Amounts for p in new_transaction.postings: if isinstance(p.amount, FutureAmountFraction): p.amount.convertToAmount(Amount(amountCmp, currency)) if date2 != date: p.setDate(date2) new_transaction.prependPosting( Posting(elba_primary_account_, Amount(amountCmp, currency))).addComment(description).setDate(date) transactions.append(new_transaction) not_balanced = [t for t in transactions if not t.isBalanced()] if len(not_balanced) > 0: print("ERROR: the following transactions are not balanced !!\n", file=sys.stderr) print("\n\n".join(map(str, (sortTransactionsByDate(not_balanced)))), file=sys.stderr)
if category.startswith("From '"): continue if not expenseacct in monefy_account_shorthands: print("%s not in %s" % (expenseacct, monefy_account_shorthands)) assert (False) targetacct = monefy_account_shorthands[expenseacct] description, *commentlist = csvdescription.split(";") description = description.strip() comment = " ".join(commentlist).strip() if comment == "": comment = None new_transaction = Transaction(description, date).addPosting( Posting(targetacct, Amount(amountCmp, currency))) if not comment is None and len(comment) > 0: new_transaction tm = transfer_regex_.search(category) if not tm is None: sourceacct = tm.group(1) if not sourceacct in monefy_account_shorthands: print("unknown sourceacct:", sourceacct, file=sys.stderr) assert (False) sourceacct = monefy_account_shorthands[sourceacct] if description == "Assert": new_transaction = Transaction(description, date).addPosting( Posting(sourceacct, Amount(0, currency)).addPostPostingAssertAmount( Amount(-1 * amountCmp, currency))).addTag("monefy")