コード例 #1
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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()
コード例 #2
0
ファイル: app.py プロジェクト: mdusilva/cryptobot
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
コード例 #3
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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()
コード例 #4
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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()
コード例 #5
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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()
コード例 #6
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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
コード例 #7
0
ファイル: app.py プロジェクト: mdusilva/cryptobot
 def on_open(self):
     print("Connecting to TICKER channel")
     self.session = model.connect_to_session()
     self.error = None
コード例 #8
0
ファイル: app.py プロジェクト: mdusilva/cryptobot
            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:
コード例 #9
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
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
コード例 #10
0
ファイル: robot.py プロジェクト: mdusilva/cryptobot
 def on_open(self):
     logger.info("Connecting to USER channel")
     self.session = model.connect_to_session()
     self.error = None