def write_submitted_order(submitted_order, execution_id, session=None): close_session = False if session is None: session = model.connect_to_session() r = session.query(model.Pairs).filter( model.Pairs.symbol == submitted_order.get('product_id')).one_or_none() pair_id = None if r is not None: pair_id = r.id try: session.add( model.Transaction(timestamp=submitted_order.get('created_at'), order_id=submitted_order.get('id'), pair_id=pair_id, size=submitted_order.get('size'), funds=submitted_order.get('funds'), price=None, side=submitted_order.get('side'), status=submitted_order.get('status'), execution_id=execution_id)) session.commit() except Exception as e: logger.error("Unable to write transaction to DB: %s" % e, exc_info=True) if close_session: session.close()
def update_positions(n, execution_id, current_portfolio_fig): session = model.connect_to_session() # execution_id = session.execute(sqlalchemy.select(model.Execution)).scalar().id execution_id = uuid.UUID(execution_id) subq = sqlalchemy.select(sqlalchemy.func.max( model.Positions.timestamp)).subquery() positions_query = sqlalchemy.select(model.Positions).join( subq, model.Positions.timestamp == subq).filter( model.Positions.execution_id == execution_id) result = session.execute(positions_query).scalars().all() # result = session.execute(sqlalchemy.select(model.Positions.value, model.Positions.timestamp, model.Positions.symbol).filter(model.Positions.execution_id == execution_id)).all() transactions_query = sqlalchemy.select(model.Transaction).filter( sqlalchemy.and_(model.Transaction.execution_id == execution_id, model.Transaction.status == 'pending')) last_transactions_pending = session.execute( transactions_query.order_by( model.Transaction.timestamp.desc()).limit(10)).scalars().all() pending_ids = {x.order_id: x for x in last_transactions_pending} last_transactions = session.execute( sqlalchemy.select(model.Transaction).filter( model.Transaction.order_id.in_(pending_ids.keys())).order_by( model.Transaction.timestamp.desc())).scalars().all() filled_ids = { x.order_id: x for x in last_transactions if x.status == 'filled' } matched_ids = { x.order_id: x for x in last_transactions if x.status == 'matched' } orders_records = [{ 'Timestamp': matched_ids.get(k, v).timestamp, 'Pair': filled_ids.get(k, v).pair.symbol, 'Size': matched_ids.get(k, v).size, 'Funds': v.funds, 'Price': matched_ids.get(k, v).price, 'Side': filled_ids.get(k, v).side, 'Status': filled_ids.get(k, v).status } for k, v in pending_ids.items()] prices_records = [{ 'Pair': n, 'Price': v } for n, v in ticker_wsClient.last_prices.items()] session.close() result_dic = {r.symbol: r.value for r in result} # current_prices = {n.split('-', 1)[0]: v for n, v in ticker_wsClient.last_prices.items()} # result_dic = {n: v * current_prices.get(n) if current_prices.get(n) is not None else v for n, v in result_dic.items()} result_dic = _get_current_values(result_dic, ticker_wsClient.last_prices) fig_positions = current_positions(result_dic) fig_portfolio_value = portfolio_value({pd.Timestamp(1).now(): result_dic}, current_portfolio_fig) current_value_text = "%s %s" % (sum(result_dic.values()), BASE_CURRENCY) return fig_positions, fig_portfolio_value, orders_records, current_value_text, prices_records
def write_amount(timestamp, amount, execution_id, session=None): close_session = False if session is None: session = model.connect_to_session() try: session.add( model.PortfolioValue(timestamp=timestamp, value=amount, execution_id=execution_id)) except Exception as e: logger.error("Unable to write amount to DB: %s" % e, exc_info=True) else: session.commit() if close_session: session.close()
def write_positions(timestamp, positions, execution_id, session=None): close_session = False if session is None: session = model.connect_to_session() try: session.add_all([ model.Positions(timestamp=timestamp, symbol=c, value=v, execution_id=execution_id) for c, v in positions.items() ]) except Exception as e: logger.error("Unable to write positions to DB: %s" % e, exc_info=True) else: session.commit() if close_session: session.close()
def write_pairs(product_pairs, session=None): close_session = False if session is None: session = model.connect_to_session() for p in product_pairs.values(): try: r = session.query( model.Pairs).filter(model.Pairs.symbol == p).one_or_none() if r is None: session.add(model.Pairs(symbol=p)) except Exception as e: logger.error("Unable to add trading pairs to DB: %s" % e, exc_info=True) try: session.commit() except Exception as e: logger.error("Failed to write to DB: %s" % e, exc_info=True) if close_session: session.close()
def get_configuration(configuration_file=None, session=None): close_session = False if session is None: session = model.connect_to_session() if configuration_file is None: configuration_file = "configuration" configuration_parameters = {} with open(configuration_file + ".json") as json_file: configuration_parameters = json.load(json_file) configuration_parameters['base_weight'] = float( configuration_parameters.get('base_weight')) universe = configuration_parameters.get('universe') base_currency = configuration_parameters.get('base_currency') configuration_parameters['portfolio_size'] = int( configuration_parameters.get('portfolio_size', 0)) product_pairs = {c: c + '-' + base_currency for c in universe} configuration_parameters['product_pairs'] = product_pairs try: r = session.query(model.Execution).filter( model.Execution.name == configuration_parameters['execution_name']).one_or_none() if r is None: new_execution = model.Execution( parameters=configuration_parameters, name=configuration_parameters['execution_name']) session.add(new_execution) session.flush() execution_id = new_execution.id session.commit() else: execution_id = r.id except Exception as e: logger.critical("Unable to get configuration: %s" % e, exc_info=True) raise else: configuration_parameters['execution_id'] = execution_id if close_session: session.close() return configuration_parameters
def on_open(self): print("Connecting to TICKER channel") self.session = model.connect_to_session() self.error = None
if 'type' in msg and 'price' in msg and 'product_id' in msg: if msg.get('product_id') is not None: self.last_prices[msg.get('product_id')] = float( msg.get('price')) def on_close(self): print("Lost connection to TICKER") self.session.close() def on_error(self, e): self.error = e self.stop = True print("There was an error with TICKER subscription: %s" % e) session = model.connect_to_session() try: currency_pairs = session.execute(sqlalchemy.select( model.Pairs.symbol)).scalars().all() ticker_wsClient = TickerClient(currency_pairs) execution_ids = session.execute(sqlalchemy.select( model.Execution)).scalars().all() executions_dict = {e.id: e for e in execution_ids} execution_options = [{ 'label': e.name, 'value': str(e.id) } for e in execution_ids] ticker_wsClient.start() # t0 = time.time() # while len(ticker_wsClient.last_prices) != len(currency_pairs) and time.time() - t0 < 5 * 60:
def run(env, configuration_file=None): session = model.connect_to_session() auth_client = get_rest_client(env) mkt_cap_key = get_mkt_cap_key() configuration_parameters = get_configuration( configuration_file=configuration_file, session=session) timestep = int(configuration_parameters['timestep']) universe = configuration_parameters.get('universe') base_currency = configuration_parameters.get('base_currency') base_weight = configuration_parameters['base_weight'] product_pairs = configuration_parameters['product_pairs'] execution_id = configuration_parameters['execution_id'] portfolio_size = configuration_parameters['portfolio_size'] portfolio_rank = configuration_parameters.get('portfolio_rank', 'large') write_pairs(product_pairs, session=session) ticker_wsClient, user_wsClient = get_wss_client( env, list(product_pairs.values())) has_prices = initialize_prices(ticker_wsClient, configuration_parameters['universe']) if has_prices and ticker_wsClient is not None and user_wsClient is not None and auth_client is not None: orders_submitted = {} while True: orders = {} try: market_caps = get_market_cap(mkt_cap_key) target_weights = get_target_weights( universe, market_caps, base_weight, portfolio_size, portfolio_rank=portfolio_rank) product_info = auth_client.get_products() min_increment = { p.get('base_currency'): p.get('quote_increment', '') for p in product_info if (p.get('quote_currency') == base_currency and p.get('id') in product_pairs.values()) } accounts = auth_client.get_accounts() current_orders = { c: sum([ f for i, f in v.items() if i in user_wsClient.current_orders.get(c, []) ]) for c, v in orders_submitted.items() } logger.debug("Current orders = %s" % current_orders) logger.debug("Current prices = %s" % ticker_wsClient.last_prices) current_positions = { acc.get('currency'): float(acc.get('balance')) for acc in accounts if acc.get('currency') in universe + [base_currency] } # write_positions(auth_client.get_time().get('iso'), current_positions, execution_id, session=session) current_positions = { c: ticker_wsClient.last_prices.get(product_pairs.get(c), np.nan) * v if c != base_currency else v for c, v in current_positions.items() } logger.debug("Current positions = %s" % current_positions) amount = sum(current_positions.values()) logger.debug("Total amount=%s" % amount) write_amount(auth_client.get_time().get('iso'), amount, execution_id, session=session) current_weights = {} if not np.isnan(amount) and amount != 0: current_weights = { c: v / amount for c, v in current_positions.items() if c in universe } logger.debug("Current weights = %s" % current_weights) logger.debug("Target weights = %s" % target_weights) target_positions = { c: amount * target_weights.get(c, np.nan) for c in universe } logger.debug("Target positions = %s" % target_positions) # orders = {c: target_positions.get(c, np.nan) - current_positions.get(c, np.nan) for c in universe} if len(market_caps) < 1: logger.debug( "No market caps received so weights are unreliable. Keeping current weights" ) orders = [] else: orders = create_orders(target_positions, current_positions, universe, min_increment) logger.debug("Current orders = %s" % orders) except Exception as e: logger.error("Error computing orders: %s" % e, exc_info=True) break try: for v, c in orders: if not np.isnan(v) and v != 0: trading_pair = product_pairs.get(c) side = 'buy' if v > 0 else 'sell' funds = abs(v) logger.debug( "Placing %s order of %s %s for %s" % (side, funds, base_currency, trading_pair)) r = auth_client.place_market_order( product_id=trading_pair, side=side, funds=funds) if 'status' in r and r[ 'status'] == 'pending' and 'id' in r and 'product_id' in r: if r['product_id'] in orders_submitted: orders_submitted[r['product_id']].update( {r['id']: r['funds']}) else: orders_submitted[r['product_id']] = { r['id']: r['funds'] } write_submitted_order(r, execution_id, session=session) logger.debug( "Submitted orders for %s are now: %s" % (r['product_id'], orders_submitted[r['product_id']])) logger.debug("Response is: %s" % r) current_positions = { acc.get('currency'): float(acc.get('balance')) for acc in accounts if acc.get('currency') in universe + [base_currency] } write_positions(auth_client.get_time().get('iso'), current_positions, execution_id, session=session) except Exception as e: logger.error("Error sending orders: %s" % e, exc_info=True) time.sleep(timestep) ticker_wsClient.close() user_wsClient.close() session.close() if __name__ == "__main__": pass
def on_open(self): logger.info("Connecting to USER channel") self.session = model.connect_to_session() self.error = None