def bitcoin_rebalance(db, exchange_data, algo, execute=False): algo.log('------- Bitcoin Balancer Report -----------', (), 'yellow') if exchange_data.name not in conf.withdrawals_enabled: algo.log('Withdrawals not enabled for %s, not balancing', exchange_data.name, 'yellow') return exchanges = get_deposit_enabled_exchanges(db) destination_exchange_data = get_destination_exchange( algo, exchange_data, exchanges) if destination_exchange_data is None: return elif destination_exchange_data == exchange_data: algo.log('%s not sending to self', exchange_data.name, 'yellow') return source_exchange = make_exchange_from_key(exchange_data.name) destination_exchange = make_exchange_from_key( destination_exchange_data.name) transfer_amount = TRANSFER_UNIT + create_uniquifier() algo.log( 'Sending %s from %s to %s', (transfer_amount, source_exchange.name, destination_exchange.name), 'yellow') if execute: # Send the bitcoins and record the transactions. deposit_address, transaction_hash, exchange_withdrawal_id = send_btc_to_exchange( source_exchange, destination_exchange, transfer_amount) transactions = exchange_data.record_withdrawal( destination_exchange_data, transfer_amount, deposit_address, transaction_hash, exchange_withdrawal_id, ) commit_mysql_session(db) else: algo.log('Not Sending Because of NO EXECUTE', (), 'yellow')
def main(exchanges, execute): exchanges = configuration.parse_configurable_as_list(exchanges) db = session.get_a_trading_db_mysql_session() for exchange_name in exchanges: exchange_wrapper = exchange_factory.make_exchange_from_key( exchange_name) initialize_exchange_ledger(db, exchange_wrapper) if execute is True: db.commit()
def export_ledger_for_exchange(exchange_name, start_time, end_time): exchange_obj = exchange_factory.make_exchange_from_key(exchange_name) lines = 'Description, %s Credit, %s Debit, BTC Credit, BTC Debit, BTC Balance, %s Balance, Date (UTC)\n' % ( exchange_obj.currency, exchange_obj.currency, exchange_obj.currency) _, _, ledger_table = get_ledger_table_for_time(exchange_name, start_time, end_time) for table_entry in ledger_table: fiat_debit = '' btc_debit = '' fiat_credit = '' btc_credit = '' if 'debit' in table_entry: if table_entry['debit'].currency == 'BTC': btc_debit = table_entry['debit'].amount else: fiat_debit = table_entry['debit'].amount if 'credit' in table_entry: if table_entry['credit'].currency == 'BTC': btc_credit = table_entry['credit'].amount else: fiat_credit = table_entry['credit'].amount btc_balance = table_entry['balance']['BTC'].amount fiat_balance = table_entry['balance'][exchange_obj.currency].amount date = table_entry.get('date') lines += '"%s",%s,%s,"%s","%s","%s","%s",%s\n' % ( table_entry.get('description', ''), fiat_credit, fiat_debit, btc_credit, btc_debit, btc_balance, fiat_balance, date, ) filename = '%s_ledger_%s_%s.csv' % ( exchange_name.lower(), start_time.strftime('%Y-%m-%d'), end_time.strftime('%Y-%m-%d'), ) f = open(filename, 'w') f.write(lines) f.close()
def withdraw(exchange_name, target_exchange_name, amount_str): db = session.get_a_trading_db_mysql_session() try: exchange_data = make_exchange_data_from_key(exchange_name, db) target_exchange_data = make_exchange_data_from_key(target_exchange_name, db) target_exchange = make_exchange_from_key(target_exchange_name) amount = Money.loads(amount_str) addr = target_exchange.current_deposit_address exchange_data.record_withdrawal(target_exchange_data, amount, addr) session.commit_mysql_session(db) logger.info(tc.colored("Recorded %s withdrawal from %s" % (amount, exchange_name), "green")) finally: db.remove()
def get_pl_from_open_orders(position_trades, exchange_name, open_orders): """ Given our current position, and the open orders on an exchange, what would our realized p&l be if a market order came in and consumed our order entirely? Details: we naively assume that our order is sized such that it would completely close our position. If there is no open order on that exchange, we return None. """ bids = open_orders['bids'] asks = open_orders['asks'] pl = Money('0', 'USD') open_position = positions.position_delta(position_trades) unmatched_fees = revenue_lib.all_fees(position_trades)[0].to('USD') fiat_position = open_position['fiat'].to('USD') btc_position = open_position['BTC'] value_of_btc = Money(0, 'USD') if btc_position > 0 and len(asks) > 0: close_order = asks[ 0] # Naively assume the first order is what we care about. close_price = Money(close_order[0], 'USD') value_of_btc = close_price * btc_position.amount elif btc_position <= 0 and len(bids) > 0: close_order = bids[0] close_price = Money(close_order[0], 'USD') value_of_btc = close_price * btc_position.amount else: return Money(0, 'USD'), Money(0, 'USD') revenue = fiat_position + unmatched_fees + value_of_btc.to('USD') exchange = exchange_factory.make_exchange_from_key(exchange_name) new_fee = exchange.limit_order_fee * abs(value_of_btc.to('USD')) fees = unmatched_fees + new_fee return revenue, fees
def get_pl_from_limit_order(position_trades, orderbook, exchange_name): """ Given our current position and an exchange orderbook, what would our realized p&l be on that position if we were the top order on this exchange, in the amount and side that would exactly close our position, and a market order came through and took the whole order? """ pl = Money('0', 'USD') open_position = positions.position_delta(position_trades) unmatched_fees = revenue_lib.all_fees(position_trades)[0].to('USD') fiat_position = open_position['fiat'].to('USD') btc_position = open_position['BTC'] value_of_btc = Money(0, 'USD') if btc_position > 0: # Then we're in a long position, we want to sell, so place an order in front # of the top ask. top_ask = orderbook['asks'][0] close_price = top_ask.price - Money('0.01', top_ask.price.currency) value_of_btc = close_price * btc_position.amount else: # Then we're in a long position, we want to sell, so place an order in front # of the top bid. top_bid = orderbook['bids'][0] close_price = top_bid.price + Money('0.01', top_bid.price.currency) value_of_btc = close_price * btc_position.amount revenue = fiat_position + unmatched_fees + value_of_btc.to('USD') exchange = exchange_factory.make_exchange_from_key(exchange_name) new_fee = exchange.market_order_fee * abs(value_of_btc.to('USD')) fees = unmatched_fees + new_fee return revenue, fees
def configure(self, configuration): self.init_configurable('price_currency', configuration) self.init_configurable('volume_currency', configuration) self.init_configurable('infinitisimal', configuration) self.init_configurable('infinity', configuration) self.init_configurable('zero', configuration) self.init_configurable('trading_pairs', configuration) self.init_configurable('DEFAULT_WIDTH', configuration) self.init_configurable('pair_name', configuration) # Parse as list and turn exchange names into exchange connections. self.trading_pair_names = config_lib.parse_configurable_as_list( self.trading_pairs, ) self.trading_pair_names = [t.upper() for t in self.trading_pair_names] self.trading_pairs = [] for trading_pair_name in self.trading_pair_names: e = exchange_factory.make_exchange_from_key(trading_pair_name) self.trading_pairs.append(e)
def fix_balance_issues_for_exchange(exchange_name, execute=False): db = session.get_a_trading_db_mysql_session() exchange = exchange_factory.make_exchange_from_key(exchange_name) if not exchange: raise Exception('No exchange %s' % exchange_name) exchange_balance = exchange.get_balance() reset_balance_for_exchange_in_currency( db, exchange, exchange_balance, exchange.currency, execute, ) reset_balance_for_exchange_in_currency( db, exchange, exchange_balance, exchange.volume_currency, execute, )
def get_pl_from_market_order(position_trades, orderbook, exchange_name): """ Given our current position and an exchange orderbook, what would our realized p&l be if we closed that position right now with a market order? """ pl = Money('0', 'USD') open_position = positions.position_delta(position_trades) unmatched_fees = revenue_lib.all_fees(position_trades)[0].to('USD') fiat_position = open_position['fiat'].to('USD') btc_position = open_position['BTC'] value_of_btc = Money(0, 'BTC') if btc_position > 0: value_of_btc = quote_lib.price_quote_from_orderbook( orderbook, Order.ASK, btc_position, )['total_price'] else: value_of_btc = quote_lib.price_quote_from_orderbook( orderbook, Order.BID, btc_position, )['total_price'] revenue = fiat_position + unmatched_fees + value_of_btc.to('USD') exchange = exchange_factory.make_exchange_from_key(exchange_name) new_fee = exchange.market_order_fee * abs(value_of_btc.to('USD')) fees = unmatched_fees + new_fee return revenue, fees
def audit_orderbook(self, orderbook, orderbook_timestamp): orderbook_timestamp_early = orderbook_timestamp - timedelta(seconds=5) orderbook_timestamp_late = orderbook_timestamp + timedelta(seconds=5) result = yield self.engine.execute( orderbook_table.select(orderbook_table).where( and_( orderbook_table.c.exchange == self.exchange_name, orderbook_table.c.timestamp.between( orderbook_timestamp_early, orderbook_timestamp_late)))) our_orderbooks = yield result.fetchall() # Non Blocking ^^^ # Potentially Blocking vvv start_time = Delorean().epoch audit_successful = 'SOFT' change_dict = {} fundamental_values = {} exchange_object = exchange_factory.make_exchange_from_key( self.exchange_name) price_limit = Money(ORDERBOOK_PRICE_LIMIT, exchange_object.currency) http_orderbook = exchange_object.parse_orderbook( orderbook, price_limit=price_limit, ) http_fundamental_value = self.fundamental_value(http_orderbook) indexed_http_ob = self.index_orderbook(http_orderbook) for our_ob in our_orderbooks: raw_db_orderbook = { 'bids': json.loads(our_ob.bids), 'asks': json.loads(our_ob.asks), } db_orderbook = exchange_object.parse_orderbook( raw_db_orderbook, price_limit=price_limit, cached_orders=True, ) # Check for soft falilures db_fundamental_value = self.fundamental_value(db_orderbook) fund_value_closeness = ( abs(db_fundamental_value - http_fundamental_value) / http_fundamental_value) indexed_db_ob = self.index_orderbook(db_orderbook) ask_diffs = DictDiffer(indexed_db_ob['asks'], indexed_http_ob['asks']) bid_diffs = DictDiffer(indexed_db_ob['bids'], indexed_http_ob['bids']) changes = (list(ask_diffs.added()) + list(ask_diffs.removed()) + list(ask_diffs.changed()) + list(bid_diffs.added()) + list(bid_diffs.removed()) + list(bid_diffs.changed())) total_changes = len(changes) change_dict[total_changes] = changes fundamental_values[fund_value_closeness] = { 'db_fundamental_value': db_fundamental_value, 'http_fundamental_value': http_fundamental_value, } hard_failure_fund_value_closeness = 10 if (total_changes < self.acceptable_changes_threshold and fund_value_closeness < self.acceptable_fund_value_threshold): audit_successful = 'SUCCESSFUL' # Check for hard failures. if self.detect_orderbook_cross(db_orderbook): audit_successful = 'HARD' log.err('%s Auditor Detects Cross - Bids:%s, Asks:%s' % (self.exchange_name, db_orderbook['bids'][:3], db_orderbook['asks'][:3])) break if fund_value_closeness > hard_failure_fund_value_closeness: audit_successful = 'HARD' log.err( 'Funamental Value difference is more than %s% its:' % (hard_failure_fund_value_closeness, fund_value_closeness)) break if not audit_successful == 'SUCCESSFUL': log.msg('%s Orderbook Auditor Soft Failure Report:' % self.exchange_name) if not our_orderbooks: log.msg('No orderbooks to audit against') for key, value in fundamental_values.iteritems(): log.msg( '------ Fundamental Value Closeness:%.6f, DBfv:%s, HTTPfv:%s' % (key, value['db_fundamental_value'], value['http_fundamental_value'])) for key, value in change_dict.iteritems(): log.msg('------ Change Count: %s' % key) log.msg('Time Elapsed Auditing %s Orderbook: %s' % ( self.exchange_name, Delorean().epoch - start_time, )) defer.returnValue(audit_successful)
def get_ledger_table_for_time(self, exchange_name, start_time, end_time, currency=None): if currency: currency = currency.upper() exchange_name = exchange_name.capitalize() exchange = exchange_factory.make_exchange_from_key(exchange_name) exchange_data = exchange_factory.make_exchange_data_from_key( exchange_name, self.trading_db, ) if exchange: # Normal bitcoin exchange. fiat_currency = exchange.currency else: # Bank Accounts don't have exchange objects. fiat_currency = self.currency_for_bank_account(exchange_name) # Bank Accounts only have one currency, so we set a currency filter by # default. It just makes the UI look nicer instead of having an empty BTC # column. currency = fiat_currency ledger = exchange_data.ledger( start_time=start_time, end_time=end_time, currency=currency, ) # ledger is empty for this time period. if len(ledger) == 0: return fiat_currency, currency, [] # get the exchange balance from before these ledger entries started oldest_entry = ledger[-1] oldest_time = oldest_entry.time_created # There can be multiple entries at the same time entries_at_oldest_time = [] for entry in ledger: if isinstance(entry, Trade) and entry.time_created == oldest_time: entries_at_oldest_time.append(entry) elif isinstance( entry, Transaction) and entry.time_completed == oldest_time: entries_at_oldest_time.append(entry) oldest_time = pytz.utc.localize(oldest_time) balance_at_oldest_time = exchange_data.ledger_balance( end_time=oldest_time) # balance_at_oldest_time includes all the entries_at_oldest_time # so we need to remove them to get the pre-ledger balance pre_ledger_balance = balance_at_oldest_time for entry in entries_at_oldest_time: pre_ledger_balance -= entry.position starting_ledger_balance = exchange_data.ledger_balance( end_time=start_time) ledger_table = [] for entry in ledger: if isinstance(entry, Trade): table_entries = self.table_entries_from_trade(entry) elif isinstance(entry, Transaction): table_entries = self.table_entries_from_transaction(entry) ledger_table += table_entries ledger_table = self.filter_to_currency(ledger_table, currency) current_balance = starting_ledger_balance for table_entry in reversed(ledger_table): if 'credit' in table_entry: current_balance += table_entry['credit'] if 'debit' in table_entry: current_balance -= table_entry['debit'] table_entry['balance'] = current_balance return fiat_currency, currency, ledger_table
def get_ledger_table_for_time(exchange_name, start_time, end_time, currency=None): if currency: currency = currency.upper() exchange_name = exchange_name.capitalize() exchange = exchange_factory.make_exchange_from_key(exchange_name) exchange_data = exchange_factory.make_exchange_data_from_key( exchange_name, db, ) fiat_currency = exchange.currency ledger = exchange_data.ledger( start_time=start_time, end_time=end_time, currency=currency, ) # ledger is empty for this time period. if len(ledger) == 0: return fiat_currency, currency, [] # get the exchange balance from before these ledger entries started oldest_entry = ledger[-1] oldest_time = oldest_entry.time_created # There can be multiple entries at the same time entries_at_oldest_time = [] for entry in ledger: if isinstance(entry, Trade) and entry.time_created == oldest_time: entries_at_oldest_time.append(entry) elif isinstance(entry, Transaction) and entry.time_completed == oldest_time: entries_at_oldest_time.append(entry) oldest_time = pytz.utc.localize(oldest_time) balance_at_oldest_time = exchange_data.ledger_balance(end_time=oldest_time) # balance_at_oldest_time includes all the entries_at_oldest_time # so we need to remove them to get the pre-ledger balance pre_ledger_balance = balance_at_oldest_time for entry in entries_at_oldest_time: pre_ledger_balance -= entry.position starting_ledger_balance = exchange_data.ledger_balance(end_time=start_time) ledger_diff = exchange_data.ledger_balance( start_time=start_time, end_time=end_time, ) ending_ledger_balance = starting_ledger_balance + ledger_diff ledger_table = [] for entry in ledger: if isinstance(entry, Trade): table_entries = table_entries_from_trade(entry) elif isinstance(entry, Transaction): table_entries = table_entries_from_transaction(entry) ledger_table += table_entries #ledger_table = self.filter_to_currency(ledger_table, currency) current_balance = starting_ledger_balance for table_entry in reversed(ledger_table): if 'credit' in table_entry: current_balance += table_entry['credit'] if 'debit' in table_entry: current_balance -= table_entry['debit'] table_entry['balance'] = current_balance return fiat_currency, currency, ledger_table