Пример #1
0
async def delete(request):
    userid = request.user
    algoname = request.match_info['algoname']

    try:
        algo = await get_existing_algo(userid, algoname)
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    if algo:
        try:
            async with aiosqlite.connect(get_main_db()) as db:
                await db.execute("delete from algos where userid = ? and algoname = ?", [userid, algoname])
                await db.execute("delete from deployed_algos where userid = ? and algoname = ?", [userid, algoname])
                await db.commit()

            try:
                async with aiosqlite.connect(get_backtest_db()) as db:
                    await db.execute("delete from backtest_request where userid = ? and algoname = ?",
                                     [userid, algoname])
                    await db.commit()
            except:
                pass
        except:
            return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)
    else:
        return json_response(STATUS_ERR % ERRORS[ERR_RESOURCE_NOT_FOUND], status=400)

    return web.Response(text="OK")
Пример #2
0
async def create(request):
    # get request parameter
    reqparams = await request.json()

    if type(reqparams) != dict:
        return json_response(STATUS_ERR % ERRORS[ERR_INCORRECT_REQUEST], status=400)

    userid = request.user
    algoname = reqparams['algo_name'] if 'algo_name' in reqparams else ''
    tradepair = reqparams['trade_pair'] if 'trade_pair' in reqparams else ''
    candlesize = reqparams['candle_size'] if 'candle_size' in reqparams else ''
    strategyname = reqparams['strategy_name'] if 'strategy_name' in reqparams else ''
    parameters = reqparams['strategy_parameters'] if 'strategy_parameters' in reqparams else ''

    if not (algoname and tradepair and candlesize and strategyname):
        return json_response(STATUS_ERR % ERRORS[ERR_INCORRECT_REQUEST], status=400)

    try:
        existing_algo = await get_existing_algo(userid, algoname)
        if existing_algo:
            return json_response(STATUS_ERR % ERRORS[ERR_RESOURCE_ALREADY_EXIST], status=400)

        async with aiosqlite.connect(get_main_db()) as db:
            await db.execute("insert into algos(userid, algoname, tradepair, candlesize, strategyname, parameters) "
                             "values (?, ?, ?, ?, ?, ?)",
                             [userid, algoname, tradepair, candlesize, strategyname, json.dumps(parameters)])
            await db.commit()
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    return json_response(STATUS_OK)
Пример #3
0
async def deployed_algo_trades(request):
    userid = request.user
    deployment_id = request.match_info['deployment_id']

    try:
        deployed = await get_deployed_algo(userid, deployment_id)
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    trades = []
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            async with db.execute("select ts, advice, sold_asset, sold_amount, bought_asset, bought_amount "
                                  "from trades where deployment_id = ?",
                                  [deployment_id]) as cursor:
                async for row in cursor:
                    trades += [
                        {
                            'ts': row[0],
                            'advice': row[1],
                            'sold_asset': row[2],
                            'sold_amount': row[3],
                            'bought_asset': row[4],
                            'bought_amount': row[5],
                        }
                    ]
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    return json_response(json.dumps(trades))
Пример #4
0
async def update_deployed_status(deployment_id, status):
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            await db.execute(
                "update deployed_algos set status = ? where id = ?",
                [status, deployment_id])
            await db.commit()
        logging.debug(
            'Updated deployed algo with deployment_id = %s, status = %s' %
            (deployment_id, status))
    except:
        logging.exception(
            'Error occurred while deployment_id = %s, status = %s' %
            (deployment_id, status))
        raise
Пример #5
0
async def get_deployed_algo(userid, deployment_id):
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            async with db.execute("select id, algoname, amount, num_cycles, status from "
                                  "deployed_algos where userid = ? and id = ?", [userid, deployment_id]) as cursor:
                async for row in cursor:
                    return {
                        'id': row[0],
                        'algo_name': row[1],
                        'amount': row[2],
                        'num_cycles': row[3],
                        'status': row[4],
                    }
    except:
        raise

    return None
Пример #6
0
async def get_existing_algo(userid, algoname):
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            async with db.execute("select algoname, tradepair, candlesize, strategyname, parameters from "
                                  "algos where userid = ? and algoname = ?", [userid, algoname]) as cursor:
                async for row in cursor:
                    return {
                        'algo_name': row[0],
                        'trade_pair': row[1],
                        'candle_size': row[2],
                        'strategy_name': row[3],
                        'strategy_parameters': json.loads(row[4]),
                    }
    except:
        raise

    return None
Пример #7
0
async def deployed_algo_list(request):
    userid = request.user
    deployed_list = []
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            async with db.execute("select id, algoname, amount, num_cycles, status "
                                  "from deployed_algos where userid = ?", [userid]) as cursor:
                async for row in cursor:
                    deployed_list += [
                        {
                            'id': row[0],
                            'algo_name': row[1],
                            'amount': row[2],
                            'num_cycles': row[3],
                            'status': row[4],
                        }
                    ]
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    return json_response(json.dumps(deployed_list))
Пример #8
0
async def algo_list(request):
    userid = request.user
    algolist = []
    try:
        async with aiosqlite.connect(get_main_db()) as db:
            async with db.execute("select algoname, tradepair, candlesize, strategyname, parameters from "
                                  "algos where userid = ?", [userid]) as cursor:
                async for row in cursor:
                    algolist += [
                        {
                            'algo_name': row[0],
                            'trade_pair': row[1],
                            'candle_size': row[2],
                            'strategy_name': row[3],
                            'strategy_parameters': json.loads(row[4]),
                        }
                    ]
    except:
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    return json_response(json.dumps(algolist))
Пример #9
0
async def deploy(request):
    userid = request.user
    reqparams = await request.json()

    if type(reqparams) != dict:
        return json_response(STATUS_ERR % ERRORS[ERR_INCORRECT_REQUEST], status=400)

    algoname = reqparams['algo_name'] if 'algo_name' in reqparams else ''
    amount = reqparams['amount'] if 'amount' in reqparams else ''
    num_cycles = reqparams['num_cycles'] if 'num_cycles' in reqparams else ''

    if not (algoname and amount and num_cycles):
        return json_response(STATUS_ERR % ERRORS[ERR_INCORRECT_REQUEST], status=400)

    try:
        existing_algo = await get_existing_algo(userid, algoname)
        if not existing_algo:
            return json_response(STATUS_ERR % ERRORS[ERR_RESOURCE_NOT_FOUND], status=400)

        async with aiosqlite.connect(get_main_db()) as db:
            cursor = await db.execute("insert into deployed_algos(userid, algoname, amount, num_cycles, status) "
                                      "values (?, ?, ?, ?, ?)",
                                      [userid, algoname, amount, num_cycles, DeployedAlgo.STATUS_NEW])
            await db.commit()
            deployment_id = cursor.lastrowid

            dreq = {'deploy_id': deployment_id}

        user_profile = UserProfile(userid, request.account, request.account_secret)
        deployment_details = DeployedAlgo(Algo.from_dict(existing_algo), deployment_id, amount, num_cycles)
        await request.app['engine_pipeline'].put((Engine.COMMAND_DEPLOY, user_profile, deployment_details))
    except:
        logging.exception('Exception occurred while processing deploy request')
        return json_response(STATUS_ERR % ERRORS[ERR_INTERNAL_ERROR], status=500)

    return json_response(json.dumps(dreq))
Пример #10
0
def execute_trade(trading_config, user_profile, deployment_id, trade_pair,
                  advice, amount, num_cycles):
    asset_pairs = trade_pair.split('_')
    base_asset = get_asset(asset_pairs[0], asset_pairs[1])
    counter_asset = get_asset(asset_pairs[2], asset_pairs[3])

    logging.debug('Executing trade for did=%s for trade_pair=%s' %
                  (deployment_id, trade_pair))

    tcontext = get_trade_context(deployment_id)
    while True:
        if tcontext:
            lock = tcontext['lock']

            lock.acquire()
            try:
                last_advice = tcontext['last_advice']
                first_advice = tcontext['first_advice']
                current_cycles = tcontext['current_cycles']
                buy_amount = tcontext['amount']
                sell_amount = tcontext['sell_amount']

                if current_cycles >= num_cycles:
                    logging.info(
                        'Did = %s is completed the %s cycles. Stopping.' %
                        (deployment_id, num_cycles))
                    return False, ALGO_DONE, None

                if last_advice == advice:
                    logging.info(
                        'Got sequential %s order from did=%s. Ignoring recent advice.'
                        % (advice, deployment_id))
                    return False, ALGO_CONT, None

                if first_advice != advice:
                    current_cycles += 1

                tcontext['last_advice'] = advice
                tcontext['current_cycles'] = current_cycles
            finally:
                lock.release()
            break
        else:
            if advice == TradeAdvice.SELL:
                logging.info(
                    'Sell order without first buy order from did=%s. Ignoring advice.'
                    % advice)
                return False, ALGO_CONT, None

            tcontext = dict()
            tcontext['lock'] = Lock()
            tcontext['first_advice'] = advice
            tcontext['last_advice'] = advice
            tcontext['current_cycles'] = 0
            tcontext['amount'] = buy_amount = amount
            tcontext['sell_amount'] = sell_amount = 0

            last_context = add_trade_context(deployment_id, tcontext)
            if last_context:
                tcontext = last_context
                continue
            else:
                break

    account = user_profile.account
    signer = user_profile.account_secret

    trxid = None
    err = None

    if advice == TradeAdvice.BUY:
        sell_asset, buy_asset = base_asset, counter_asset

        if math.floor(buy_amount) == 0:
            logging.info(
                'Algo %d trying to generate buy order without available asset %s'
                % (deployment_id, sell_asset))
            return False, ALGO_ERROR, ('Ran out of fund for asset = %s' %
                                       format_asset(sell_asset))

        book = stellar.orderbook(selling=base_asset,
                                 buying=counter_asset).fetch()
        if len(book.bids):
            # get current market price of the asset
            market_bid = book.bids[0]
            logging.debug(
                'Executing trade for did=%s amount=%s, at market_price=%s [%s -> %s]'
                % (deployment_id, buy_amount, market_bid[1], sell_asset,
                   buy_asset))
            with stellar.new_transaction(account, signers=[signer]) as t:
                # buy counter asset buy exchanging base asset
                t.add_offer(buy_amount, sell_asset, buy_asset, market_bid[1])

            if t.is_success():
                trxid, _ = t.result()
                logging.debug('Trade executed for did = %s, trxid = %s' %
                              (deployment_id, trxid))
            else:
                err = str(t.errors())
                logging.error('Trade execution failed for did = %s, err = %s' %
                              (deployment_id, err))
    elif advice == TradeAdvice.SELL:
        sell_asset, buy_asset = counter_asset, base_asset

        if math.floor(sell_amount) == 0:
            logging.info(
                'Algo %d trying to generate buy order without available asset %s'
                % (deployment_id, sell_asset))
            return False, ALGO_ERROR, ('Ran out of fund for asset = %s' %
                                       format_asset(sell_asset))

        book = stellar.orderbook(selling=counter_asset,
                                 buying=base_asset).fetch()
        if len(book.bids):
            # get current market price of the asset
            market_bid = book.bids[0]
            logging.debug(
                'Executing trade for did=%s amount=%s, at market_price=%s [%s -> %s]'
                % (deployment_id, sell_amount, market_bid[1], sell_asset,
                   buy_asset))
            with stellar.new_transaction(account, signers=[signer]) as t:
                # sell counter asset buy exchanging base asset
                t.add_offer(sell_amount, sell_asset, buy_asset, market_bid[1])

            if t.is_success():
                trxid, _ = t.result()
                logging.debug('Trade executed for did = %s, trxid = %s' %
                              (deployment_id, trxid))
            else:
                err = str(t.errors())
                logging.error('Trade execution failed for did = %s, err = %s' %
                              (deployment_id, err))
    else:
        logging.error('Incorrect advice %s' % advice)
        return False, ALGO_ERROR, 'Incorrect advice %s' % advice

    # todo log the trade in database recoconciliation

    if not trxid:
        # todo log error
        return False, ALGO_ERROR, err

    try:
        offerid = stellar.transaction(trxid).effects().first().offer_id
        if offerid:
            # remove offer if it still exist
            offers = stellar.account(account).offers().fetch().records
            for offer in offers:
                if offer.offerid == offerid:
                    logging.debug(
                        'Removing residue offer for did = %s, offerid = %s' %
                        (deployment_id, offerid))
                    # ignore the error assuming offer got fulfilled (hence offer-not-found)
                    # we will check the final bought/sold below
                    with stellar.new_transaction(account,
                                                 signers=[signer]) as t:
                        t.remove_offer(offerid, sell_asset, buy_asset)

        total_sold = 0
        total_bought = 0
        effects = stellar.transaction(trxid).effects().fetch().records
        for effect in effects:
            if effect.type == 'trade' and effect.account == account:
                total_sold += float(effect.sold_amount)
                total_bought += float(effect.bought_amount)

        if advice == TradeAdvice.BUY:
            lock = tcontext['lock']
            try:
                lock.acquire()
                tcontext['amount'] = buy_amount - total_sold
                tcontext['sell_amount'] = sell_amount + total_bought
            finally:
                lock.release()
        elif advice == TradeAdvice.SELL:
            lock = tcontext['lock']
            try:
                lock.acquire()
                tcontext['amount'] = buy_amount + total_bought
                tcontext['sell_amount'] = sell_amount - total_sold
            finally:
                lock.release()

        ts = (datetime.datetime.utcnow() - EPOCH).total_seconds()
        with sqlite.connect(get_main_db()) as db:
            db.execute(
                "insert into trades"
                "(ts, deployment_id, advice, sold_asset, sold_amount, bought_asset, bought_amount)"
                " values (?, ?, ?, ?, ?, ?, ?)", [
                    ts, deployment_id, advice,
                    format_asset(sell_asset),
                    float(total_sold),
                    format_asset(buy_asset),
                    float(total_bought)
                ])
            db.commit()
    except Exception as e:
        logging.exception('Exception occurred while processing trade advice')
        return False, ALGO_ERROR, ('Internal error %s' % str(e))

    logging.info(
        'Trade executed for did=%s, sold_asset=%s, sold_amount=%s, bought_asset=%s, bought_amount=%s'
        % (deployment_id, sell_asset, total_sold, buy_asset, total_bought))

    return True, None, None