def compute_profit_by_pair(pair_id, trades_to_order_by_pair): file_name = get_pair_name_by_id(pair_id) + "_trace.txt" profit_coin = 0.0 profit_base_currency = 0.0 orders_by_arbitrage_id = defaultdict(list) # 1 stage group by arbitrage id for order, trades in trades_to_order_by_pair: orders_by_arbitrage_id[order.arbitrage_id].append((order, trades)) number_of_missing_pair = 0 for arbitrage_id in orders_by_arbitrage_id: if len(orders_by_arbitrage_id[arbitrage_id]) == 1: number_of_missing_pair += 1 msg = "Can't find paired arbitrage order for {arbitrage_id} {o}".format( arbitrage_id=arbitrage_id, o=orders_by_arbitrage_id[arbitrage_id][0]) log_to_file(msg, file_name) continue else: for order, trades in orders_by_arbitrage_id[arbitrage_id]: msg = "Computing trades for order {o}".format(o=order) log_to_file(msg, file_name) if order.trade_type == DEAL_TYPE.BUY: for trade in trades: profit_coin += trade.executed_volume base_currency_volume = trade.executed_volume * trade.price * 0.01 * ( 100 + get_fee_by_exchange(trade.exchange_id)) profit_base_currency -= base_currency_volume msg = """Analysing trade {o} ADD coin volume = {cv} SUBTRACT base currency = {base} """.format(o=trade, cv=trade.executed_volume, base=base_currency_volume) log_to_file(msg, file_name) elif order.trade_type == DEAL_TYPE.SELL: for trade in trades: profit_coin -= trade.executed_volume base_currency_volume = trade.executed_volume * trade.price * 0.01 * ( 100 - get_fee_by_exchange(trade.exchange_id)) profit_base_currency += base_currency_volume msg = """Analysing trade {o} SUBTRACT coin volume = {cv} ADD base currency = {base} """.format(o=trade, cv=trade.executed_volume, base=base_currency_volume) log_to_file(msg, file_name) else: print "WE HAVE WRONG trade_type", order.trade_type print "For order: ", order msg = "For {pair_name} Number of missing paired order is {num}".format( pair_name=get_pair_name_by_id(pair_id), num=number_of_missing_pair) log_to_file(msg, file_name) return profit_coin, profit_base_currency
def compute_loss(trades_to_order_by_pair): orders_by_arbitrage_id = defaultdict(list) # 1 stage group by arbitrage id for order, trades in trades_to_order_by_pair: orders_by_arbitrage_id[order.arbitrage_id].append((order, trades)) orders_by_pair = defaultdict(list) cnt = 0 for arbitrage_id in orders_by_arbitrage_id: if len(orders_by_arbitrage_id[arbitrage_id]) != 1: continue order, trades_list = orders_by_arbitrage_id[arbitrage_id][0] msg = "can't find pair order - {o}".format(o=order) log_to_file(msg, "missing_" + get_pair_name_by_id(order.pair_id) + ".txt") cnt += 1 orders_by_pair[order.pair_id].append((order, trades_list)) loss_details = defaultdict(list) loss_details_total = Counter() for pair_id in orders_by_pair: loss_by_coin, loss_by_base_coin = compute_loss_by_pair( orders_by_pair[pair_id]) base_currency_id, dst_currency_id = split_currency_pairs(pair_id) loss_details[base_currency_id].append( LossDetails(base_currency_id, dst_currency_id, pair_id, loss_by_coin, loss_by_base_coin)) loss_details_total[base_currency_id] += loss_by_base_coin return loss_details, loss_details_total
def __str__(self): str_repr = """Sell=Bid exchange - {sell_exch} id = {id1} Buy-Ask exchange - {buy_exch} id = {id2} currency pair - {pair} Arbitrage Threshold = {thrshld} Reverse Threshold = {rv_thr} Balance Threshold = {b_thr} deal_expire_timeout = {deal_expire_timeout} cfg_file_name = {cfg_file_name} log_file_name = {log_file_name} cap_update_timeout = {cap_update_timeout} balance_update_timeout = {balance_update_timeout} """.format( sell_exch=get_exchange_name_by_id(self.sell_exchange_id), id1=self.sell_exchange_id, buy_exch=get_exchange_name_by_id(self.buy_exchange_id), id2=self.buy_exchange_id, pair=get_pair_name_by_id(self.pair_id), pair_id = self.pair_id, thrshld=self.threshold, rv_thr=self.reverse_threshold, b_thr=self.balance_threshold, cfg_file_name=get_debug_level_name_by_id(self.cfg_file_name), deal_expire_timeout=self.deal_expire_timeout, log_file_name=self.log_file_name, cap_update_timeout=self.cap_update_timeout, balance_update_timeout=self.balance_update_timeout ) return str_repr
def __init__(self, pair_id, lowest_ask, highest_bid, timest, exchange_id): self.pair_id = int(pair_id) self.pair = get_pair_name_by_id(self.pair_id) self.ask = Decimal(lowest_ask) self.bid = Decimal(highest_bid) self.timest = long(timest) self.exchange_id = int(exchange_id) self.exchange = get_exchange_name_by_id(self.exchange_id)
def __iter__(self): return iter([ self.arbitrage_id, get_exchange_name_by_id(self.exchange_id), get_pair_name_by_id(self.pair_id), get_order_type_by_id(self.trade_type), self.price, self.volume, self.order_book_time, self.create_time, self.execute_time, ts_to_string_local(self.execute_time), self.order_id, self.trade_id, self.executed_volume ])
def __init__(self, pair_id, timest, deal_type, price, amount, total, exchange_id): # FIXME NOTE - various volume data? self.pair_id = int(pair_id) self.pair = get_pair_name_by_id(self.pair_id) self.timest = long(timest) self.deal_type = deal_type self.price = Decimal(price) self.amount = Decimal(amount) self.total = Decimal(total) self.exchange_id = int(exchange_id) self.exchange = get_exchange_name_by_id(self.exchange_id)
def __init__(self, pair_id, timest, price_high, price_low, price_open, price_close, exchange_id): # FIXME NOTE - various volume data? self.pair_id = int(pair_id) self.pair = get_pair_name_by_id(self.pair_id) self.timest = long(timest) self.high = Decimal(price_high) self.low = Decimal(price_low) self.open = Decimal(price_open) self.close = Decimal(price_close) self.exchange_id = int(exchange_id) self.exchange = get_exchange_name_by_id(self.exchange_id)
def log_arbitrage_determined_volume_not_enough(sell_order_book, buy_order_book, msg_queue): msg = """analyse order book - DETERMINED volume of deal is not ENOUGH {pair_name}: first_exchange: {first_exchange} first exchange volume: <b>{vol1}</b> second_exchange: {second_exchange} second_exchange_volume: <b>{vol2}</b>""".format( pair_name=get_pair_name_by_id(sell_order_book.pair_id), first_exchange=get_exchange_name_by_id(sell_order_book.exchange_id), second_exchange=get_exchange_name_by_id(buy_order_book.exchange_id), vol1=float_to_str(sell_order_book.bid[FIRST].volume), vol2=float_to_str(buy_order_book.ask[LAST].volume)) print_to_console(msg, LOG_ALL_MARKET_NETWORK_RELATED_CRAP) log_to_file(msg, DEBUG_LOG_FILE_NAME) if get_logging_level() >= LOG_ALL_TRACE: msg_queue.add_message(DEBUG_INFO_MSG, msg)
def log_arbitrage_heart_beat(sell_order_book, buy_order_book, difference): msg = """check_highest_bid_bigger_than_lowest_ask: \tFor pair - {pair_name} \tExchange1 - {exch1} BID = {bid} \tExchange2 - {exch2} ASK = {ask} \tDIFF = {diff}""".format(pair_name=get_pair_name_by_id(sell_order_book.pair_id), exch1=get_exchange_name_by_id(sell_order_book.exchange_id), bid=float_to_str(sell_order_book.bid[FIRST].price), exch2=get_exchange_name_by_id(buy_order_book.exchange_id), ask=float_to_str(buy_order_book.ask[LAST].price), diff=difference) print_to_console(msg, LOG_ALL_MARKET_NETWORK_RELATED_CRAP) log_to_file(msg, DEBUG_LOG_FILE_NAME)
def analyse_tickers(pg_connection, notify_queue): """ Retrieve tickers from ALL exchanges via REST api and save into DB. NOTE: Very first routine to analyse gap between rates at different exchanges. :param pg_connection: :param notify_queue: :return: """ processor = ConnectionPool() while True: timest = get_now_seconds_utc() results = get_ticker_speedup(timest, processor) tickers = filter(lambda x: type(x) != str, results) res = compare_price(tickers, TRIGGER_THRESHOLD, check_highest_bid_bigger_than_lowest_ask) for entry in res: msg = """Condition: {msg} at {ts} Date: {dt} Pair: {pair_name}, {ask_exchange}: {ask_price:.7f} {sell_exchange}: {sell_price:.7f} TAG: {ask_exchange}-{sell_exchange} """.format(msg=entry[0], ts=timest, dt=ts_to_string_local(timest), pair_name=get_pair_name_by_id(entry[1]), ask_exchange=entry[2].exchange, ask_price=entry[2].bid, sell_exchange=entry[3].exchange, sell_price=entry[3].ask) print_to_console(msg, LOG_ALL_ERRORS) notify_queue.add_message(ARBITRAGE_MSG, msg) save_alarm_into_pg(entry[2], entry[3], pg_connection) print_to_console( "Total amount of tickers = {num}".format(num=len(tickers)), LOG_ALL_DEBUG) load_to_postgres(tickers, TICKER_TYPE_NAME, pg_connection) print_to_console("Before sleep...", LOG_ALL_DEBUG) sleep_for(POLL_PERIOD_SECONDS)
def log_arbitrage_determined_price_not_enough(sell_price, sell_price_order_book, buy_price, buy_price_order_book, difference, final_difference, pair_id, msg_queue): msg = """analyse order book - adjusted prices below 0.2 hardcoded threshold: \tfinal_sell: {sell_price} initial_sell: {i_sell} \tfinal_buy: {final_buy} initial_buy: {i_buy} \tfinal_diff: {final_diff} original_diff: {diff} \tfor pair_id = {p_name}""".format(sell_price=float_to_str(sell_price), i_sell=float_to_str(sell_price_order_book), final_buy=float_to_str(buy_price), i_buy=float_to_str(buy_price_order_book), final_diff=final_difference, p_name=get_pair_name_by_id(pair_id), diff=difference) print_to_console(msg, LOG_ALL_MARKET_NETWORK_RELATED_CRAP) log_to_file(msg, DEBUG_LOG_FILE_NAME) msg_queue.add_message(DEBUG_INFO_MSG, msg)
def __init__(self, pair_id, timest, sell_bids, buy_bids, exchange_id, sequence_id=None): # FIXME NOTE - various volume data? self.pair_id = int(pair_id) self.pair_name = get_pair_name_by_id(self.pair_id) self.timest = timest self.ask = sell_bids self.bid = buy_bids self.exchange_id = int(exchange_id) self.exchange = get_exchange_name_by_id(self.exchange_id) self.sequence_id = sequence_id
def log_currency_disbalance_present(src_exchange_id, dst_exchange_id, pair_id, currency_id, balance_threshold, new_max_cap_volume, treshold): msg = """We have disbalance! Exchanges {exch1} {exch2} for {pair_id} with {balance_threshold}. Set max cap for {currency} to {vol} and try to find price diff more than {thrs}""".format( exch1=get_exchange_name_by_id(src_exchange_id), exch2=get_exchange_name_by_id(dst_exchange_id), pair_id=get_pair_name_by_id(pair_id), balance_threshold=balance_threshold, currency=get_currency_name_by_id(currency_id), vol=new_max_cap_volume, thrs=treshold ) print_to_console(msg, LOG_ALL_MARKET_NETWORK_RELATED_CRAP) log_to_file(msg, "history_trades.log") log_to_file(msg, "cap_price_adjustment.log")
def __str__(self): str_repr = """ Trade at Exchange: {exch} Type: {deal_type} Pair: {pair} for volume {vol} with price {price} order_book_time {ob_time} create_time {ct_time} execute_time {ex_time} Executed at: {dt} order_id {order_id} trade_id {trade_id} executed_volume {ex_volume} arbitrage_id {a_id} """.format(exch=get_exchange_name_by_id(self.exchange_id), deal_type=get_order_type_by_id(self.trade_type), pair=get_pair_name_by_id(self.pair_id), vol=truncate_float(self.volume, 8), price=truncate_float(self.price, 8), ob_time=self.order_book_time, ct_time=self.create_time, ex_time=self.execute_time, dt=ts_to_string_local(self.execute_time), order_id=self.order_id, trade_id=self.trade_id, ex_volume=self.executed_volume, a_id=self.arbitrage_id) return str_repr
def generate_window_name(self): window_name = "{pair_id} - {pair_name}".format(pair_id=self.pair_id, pair_name=get_pair_name_by_id(self.pair_id)) return window_name
def _generate_file_name(self): return "{sell_exch}==>{buy_exch}-{pair_name}.log".format( sell_exch=get_exchange_name_by_id(self.sell_exchange_id), buy_exch=get_exchange_name_by_id(self.buy_exchange_id), pair_name=get_pair_name_by_id(self.pair_id) )