def perform_trade(self, sell_amt, sell_coin, buy_coin):
     """Performs the trade from 'sell_coin' to 'buy_coin'.
     Returns a 'Trade' object
     """
     # Find the trading fee for the given pairget_trade_fee(
     fee_amt_perc, fee_coin, fee_literal = self.get_trade_fee(
         sell_amt, sell_coin, buy_coin)
     if fee_amt_perc is None:
         self.logger.warning("perform_trade: No trade fee for '{}[{}/{}]'."
                             "Skipping trade calculation.".format(
                                 self.exchange.id, sell_coin.id,
                                 buy_coin.id))
         return None
     # Perform trade:
     buy_amt = fx_exchange(sell_coin.id, buy_coin.id,
                           sell_amt * (1 - fee_amt_perc / 100), self.logger)
     if buy_amt is None:
         self.logger.warning("perform_trade [2]: Trade could not be "
                             "performed '{}[{}/{}]'. "
                             "Skipping trade calculation.".format(
                                 self.exchange.id, sell_coin.id,
                                 buy_coin.id))
         return None
     elif buy_amt <= 0:
         self.logger.warning(
             "perform_trade [3]: Trade performed with negative outcome '{}[{} {} --> {} {}]'. "
             "Skipping trade calculation.".format(self.exchange.id,
                                                  sell_amt, sell_coin.id,
                                                  buy_amt, buy_coin.id))
         return None
     # Fees calculated by default in 'sell_coin'
     fee_amt = fee_amt_perc / 100 * sell_amt
     # If 'FeeCoin' has a value, calculate fees in 'FeeCoin'
     if fee_coin and fee_coin is not '-':
         fee_amt = fx_exchange(sell_coin.id, fee_coin, fee_amt, self.logger)
         fee_coin = get_coin(fee_coin)
     else:
         fee_coin = sell_coin
     # Return calculated trade
     self.logger.debug("perform_trade [3]: Trade for '{}[{}/{}]:"
                       " Sell={} {} / Buy={} {} / Fee={} {}'"
                       "".format(self.exchange.id, sell_coin.id,
                                 buy_coin.id, sell_amt, sell_coin.id,
                                 buy_amt, buy_coin.id, fee_amt,
                                 fee_coin.id))
     return Trade(sell_amt, sell_coin, buy_amt, buy_coin, fee_amt, fee_coin,
                  fee_literal)
 def calc_transfer_fees(self, fee_lst, coin, to_curr=False):
     """ Returns a string that contains the sum of the fees provided in
     'fee_lst' (withdrawal & deposit fees).
     If 'to_curr' is equeal to 'True', the function converts the sum
     to the calculation currency.
     """
     fee_sum = sum(filter(None, fee_lst))
     if fee_sum is not None:
         if to_curr:
             fee_sum = fx_exchange(coin, self.currency, fee_sum,
                                   self.logger)
             return num_2_str(fee_sum, self.currency)
         else:
             return "{} {}".format(fee_sum, coin)
     else:
         return ""
示例#3
0
def exch_results(url_orig_coin=None, url_dest_coin=None):
    """There are two ways of landing in this page:
         - Search form was filled: performs search and returns results
         - Direct external link (no form was filled!): in this case,
         a page with no results is shown, and then from the page a proper
         calculation is triggered. It is done like this to let the user
         load the page as soon as possible.
    """
    session_id = request.cookies.get('session')
    if not session_id:
        new_session_id = token_hex(8)
    sorted_paths = []
    input_form = SearchForm()
    # Choose currency: 1) Form 2) Cookie 3) Default
    currency = request.cookies.get('calc_currency')
    if input_form.currency.data != 'Empty':
        curr = input_form.currency.data
    elif currency:
        curr = currency
        input_form.currency.data = curr
    else:
        curr = Params.DEFAULT_CURRENCY
        input_form.currency.data = curr
    auto_search = False
    feedback_form = FeedbackForm()
    exchanges = get_exchanges(['Exchange'])
    user_exchanges = [exch.id for exch in exchanges]
    path_results = None
    open_fbck_modal = False
    # Get Meta tags (in case form was not filled)
    title = get_meta_tags('Exchanges|Results',
                          'Title',
                          [url_orig_coin.upper(), url_dest_coin.upper()])
    description = get_meta_tags('Exchanges|Results',
                                'Description',
                                [url_orig_coin.upper(), url_dest_coin.upper()])
    # 1) ACTIONS IF *SEARCH* FORM WAS FILLED
    if input_form.search_submit.data:
        if input_form.validate():
            curr = input_form.currency.data
            orig_loc = get_exch_by_name(input_form.orig_loc.data)
            orig_coin = get_coin_by_longname(input_form.orig_coin.data)
            # Save 'orig_amt' as Float or integer depending on value
            num = float(input_form.orig_amt.data)
            if num % 1 == 0:
                num = int(num)
            orig_amt = num
            dest_loc = get_exch_by_name(input_form.dest_loc.data)
            dest_coin = get_coin_by_longname(input_form.dest_coin.data)
            user_exchanges = input_form.exchanges.data
            # Get Meta tags (again, if form was filled)
            title = get_meta_tags('Exchanges|Results',
                                  'Title',
                                  [orig_coin.symbol, dest_coin.symbol])
            description = get_meta_tags('Exchanges|Results',
                                        'Description',
                                        [orig_coin.long_name,
                                         dest_coin.long_name])
            # If user selected all Exchanges or none of them, don't filter
            if len(user_exchanges) == len(exchanges):
                user_exchanges = []
            fee_settings = {"CEP": input_form.cep_promos.data,
                            "Default": input_form.default_fee.data,
                            "Binance": input_form.binance_fee.data}
            # start_time = datetime.datetime.now()
            try:
                paths = calc_paths(orig_loc, orig_coin, orig_amt,
                                   dest_loc, dest_coin,
                                   curr, fee_settings, logger)
                path_results = len(paths)
            # Catch generic exception just in case anything went wront in logic
            except Exception as e:
                db.session.rollback()
                error_notifier(type(e).__name__,
                               traceback.format_exc(),
                               mail,
                               logger)
                paths = []
                path_results = -1
            # If no results were found, send worning email
            if path_results == 0:
                args_dic = {"orig_amt": orig_amt,
                            "orig_coin": orig_coin.id,
                            "orig_loc": orig_loc.id,
                            "dest_coin": dest_coin.id,
                            "dest_loc": dest_loc.id,
                            "currency": curr}
                warning_notifier("Search with no results",
                                 args_dic,
                                 mail,
                                 logger)
            # Register query
            # finish_time = datetime.datetime.now()
            # results = len(paths)
            # exchs = ""
            # for exch in user_exchanges:
            #     exchs += exch + '|'
            # exchs = exchs[:-1]
            # try:
            #     query = QueryRegister(session_id=session_id,
            #                           orig_amt=orig_amt,
            #                           orig_coin=orig_coin.id,
            #                           orig_loc=orig_loc.id,
            #                           dest_coin=dest_coin.id,
            #                           dest_loc=dest_loc.id,
            #                           currency=curr,
            #                           connection_type=connection_type,
            #                           exchanges=exchs,
            #                           results=results,
            #                           start_time=start_time,
            #                           finish_time=finish_time)
            #     db.session.add(query)
            #     db.session.commit()
            # except Exception as e:
            #     db.session.rollback()
            #     error_notifier(type(e).__name__,
            #                    traceback.format_exc(),
            #                    mail,
            #                    logger)
            # Select all Exchanges if no partial selection was made
            if not user_exchanges:
                user_exchanges = [exch.id for exch in exchanges]
            # Return capped list of results
            sorted_paths = sorted(paths, key=lambda x: x.total_fees)
            sorted_paths = sorted_paths[0:Params.MAX_PATHS]
    # 2) ACTIONS IF *NO* FORM WAS FILLED (DIRECT LINK!)
    else:
        orig_coin = get_coin(url_orig_coin.upper())
        dest_coin = get_coin(url_dest_coin.upper())
        if orig_coin:
            input_form.orig_coin.data = orig_coin.long_name
            amt = fx_exchange("USD", orig_coin.id, 3000, logger)
            input_form.orig_amt.data = str(math.ceil(amt)) + " "
        if dest_coin:
            input_form.dest_coin.data = dest_coin.long_name
        auto_search = True
    resp = make_response(render_template('exch_results.html',
                                         form=input_form,
                                         curr=curr,
                                         exchanges=exchanges,
                                         user_exchanges=user_exchanges,
                                         paths=sorted_paths,
                                         path_results=path_results,
                                         auto_search=auto_search,
                                         feedback_form=feedback_form,
                                         title=title,
                                         description=description,
                                         open_feedback_modal=open_fbck_modal,
                                         url_orig_coin=url_orig_coin,
                                         url_dest_coin=url_dest_coin))
    # Store session ID & Currency in cookie if there are not already stored
    if not session_id:
        resp.set_cookie('session', new_session_id)
    if currency != curr:
        resp.set_cookie('calc_currency', curr)
    return resp
示例#4
0
def exch_results(url_orig_coin=None, url_dest_coin=None):
    """There are two ways of landing in this page:
         - Search form was filled: performs search and returns results
         - Direct external link (no form was filled!): in this case,
         a page with no results is shown, and then from the page a proper
         calculation is triggered. It is done like this to let the user
         load the page as soon as possible.
    """
    try:
        session_id = request.cookies.get('session')
        if not session_id:
            new_session_id = token_hex(8)
        sorted_paths = []
        input_form = SearchForm()
        # Choose currency: 1) Form 2) Cookie 3) Default
        currency = request.cookies.get('calc_currency')
        if input_form.currency.data != 'Empty':
            curr = input_form.currency.data
        elif currency:
            curr = currency
            input_form.currency.data = curr
        else:
            curr = Params.DEFAULT_CURRENCY
            input_form.currency.data = curr
        curr = get_coin(curr)
        if not curr:
            curr = get_coin('usd-us-dollars')
        auto_search = False
        feedback_form = FeedbackForm()
        exchanges = get_exchanges(['Exchange'], status='Active')
        user_exchanges = [exch.id for exch in exchanges]
        path_results = None
        amt_warning = None
        # Get Meta tags (in case form was not filled)
        title = get_meta_tags('Exchanges|Results',
                              'Title',
                              [url_orig_coin.upper(), url_dest_coin.upper()])
        description = get_meta_tags('Exchanges|Results',
                                    'Description',
                                    [url_orig_coin.upper(),
                                     url_dest_coin.upper()])
        # 1) ACTIONS IF *SEARCH* FORM WAS FILLED
        if input_form.search_submit.data:
            if input_form.validate():
                curr = input_form.currency.data
                curr = get_coin(curr)
                orig_loc = get_exch_by_name(input_form.orig_loc.data)
                orig_coin = get_coin_by_longname(input_form.orig_coin.data)
                # Save 'orig_amt' as Float or integer depending on value
                num = float(input_form.orig_amt.data)
                if num % 1 == 0:
                    num = int(num)
                orig_amt = num
                dest_loc = get_exch_by_name(input_form.dest_loc.data)
                dest_coin = get_coin_by_longname(input_form.dest_coin.data)
                user_exchanges = input_form.exchanges.data
                # Get Meta tags (again, if form was filled)
                title = get_meta_tags('Exchanges|Results',
                                      'Title',
                                      [orig_coin.symbol, dest_coin.symbol])
                description = get_meta_tags('Exchanges|Results',
                                            'Description',
                                            [orig_coin.long_name,
                                             dest_coin.long_name])
                # If user selected all Exchanges or none of them, don't filter
                if len(user_exchanges) == len(exchanges):
                    user_exchanges = []
                fee_settings = {"CEP": input_form.cep_promos.data,
                                "Default": input_form.default_fee.data,
                                "Binance": input_form.binance_fee.data}
                # start_time = datetime.datetime.now()
                try:
                    paths = calc_paths(orig_loc, orig_coin, orig_amt,
                                       dest_loc, dest_coin,
                                       curr, fee_settings, logger)
                    path_results = len(paths)
                # Catch generic exception if anything went wrong in logic
                except Exception as e:
                    db.session.rollback()
                    error_notifier(type(e).__name__,
                                   traceback.format_exc(),
                                   mail,
                                   logger)
                    paths = []
                    path_results = -1
                # If no results were found, check "orign_amt" to try again
                if path_results == 0:
                    amount_usd = fx_exchange(orig_coin.id,
                                             'usd-us-dollars',
                                             orig_amt,
                                             logger)
                    if amount_usd and amount_usd < Params.RECALC_AMOUNT:
                        orig_amt = round_number(orig_amt * Params.RECALC_AMOUNT
                                                / amount_usd)
                        orig_amt = round_big_number(orig_amt)
                        input_form.orig_amt.data = orig_amt
                        try:
                            paths = calc_paths(orig_loc, orig_coin, orig_amt,
                                               dest_loc, dest_coin,
                                               curr, fee_settings, logger)
                            path_results = len(paths)
                            amt_warning = True
                        # Catch generic exception if anything went wrong
                        except Exception as e:
                            db.session.rollback()
                            error_notifier(type(e).__name__,
                                           traceback.format_exc(),
                                           mail,
                                           logger)
                            paths = []
                            path_results = -1
                # If no results were found, send worning email
                if path_results == 0:
                    args_dic = {"orig_amt": orig_amt,
                                "orig_coin": orig_coin.id,
                                "orig_loc": orig_loc.id,
                                "dest_coin": dest_coin.id,
                                "dest_loc": dest_loc.id,
                                "currency": curr.id}
                    warning_notifier("Search with no results",
                                     args_dic,
                                     mail,
                                     logger)
                # Select all Exchanges if no partial selection was made
                if not user_exchanges:
                    user_exchanges = [exch.id for exch in exchanges]
                # Return capped list of results
                sorted_paths = sorted(paths, key=lambda x: x.total_fees)
                sorted_paths = sorted_paths[0:Params.MAX_PATHS]
        # 2) ACTIONS IF *NO* FORM WAS FILLED (DIRECT LINK!)
        else:
            orig_coin = get_coin_by_symbol(url_orig_coin.upper())
            dest_coin = get_coin_by_symbol(url_dest_coin.upper())
            # If 'orig_coin' or 'dest_coin' not found, try in mappings table
            if not orig_coin:
                new_symbol = get_mapping('Coin',
                                         'symbol',
                                         url_orig_coin.upper())
                if new_symbol:
                    orig_coin = get_coin_by_symbol(new_symbol)
            if not dest_coin:
                new_symbol = get_mapping('Coin',
                                         'symbol',
                                         url_dest_coin.upper())
                if new_symbol:
                    dest_coin = get_coin_by_symbol(new_symbol)
            # Procced with function
            if orig_coin:
                input_form.orig_coin.data = orig_coin.long_name
                amt = fx_exchange('usd-us-dollars', orig_coin.id, 3000, logger)
                if amt:
                    amt = round_big_number(amt)
                    input_form.orig_amt.data = str(math.ceil(amt)) + " "
            if dest_coin:
                input_form.dest_coin.data = dest_coin.long_name
            auto_search = True
        # Actions if Feedback Form was filled
        if feedback_form.feedback_submit.data:
            if feedback_form.validate():
                manage_feedback_form(feedback_form, request.path)
    # Catch generic exception just in case anything went wront in logic
    except Exception as e:
        db.session.rollback()
        logger.error("Routes: Non-handled exception at '{}'"
                     .format(request.url))
        error_notifier(type(e).__name__,
                       traceback.format_exc(),
                       mail,
                       logger)
        return redirect(url_for('exchanges'))
    resp = make_response(render_template('exch_results.html',
                                         form=input_form,
                                         curr=curr,
                                         exchanges=exchanges,
                                         user_exchanges=user_exchanges,
                                         paths=sorted_paths,
                                         amt_warning=amt_warning,
                                         path_results=path_results,
                                         auto_search=auto_search,
                                         feedback_form=feedback_form,
                                         title=title,
                                         description=description,
                                         url_orig_coin=url_orig_coin,
                                         url_dest_coin=url_dest_coin))
    # Store session ID & Currency in cookie if there are not already stored
    if not session_id:
        resp.set_cookie('session', new_session_id)
    if currency != curr.id:
        resp.set_cookie('calc_currency', curr.id)
    return resp
 def calc_fees(self, currency, logger):
     """Calculates the overall path fees in the given 'currency'. Adds up:
     - Origin Withdraw fees (origin.withdraw_fee)
     - Hop 1 Deposit fees (hop_1.deposit_fee)
     - Hop 1 Trade fees (hop_1.trade.fee_amt)
     - Hop 1 Withdraw fees (hop_1.withdraw_fee)
     - Hop 2 Deposit fees (hop_2.deposit_fee)
     - Hop 2 Trade fees (hop_2.trade.fee_amt)
     - Hop 2 Withdraw fees (hop_2.withdraw_fee)
     - Destination Deposit fees (destination.deposit_fee)
     """
     total_fees = 0
     # Add Origin Withdraw fees (origin.withdraw_fee)
     if self.origin.withdraw_fee:
         fee = fx_exchange(self.origin.coin.id, currency,
                           self.origin.withdraw_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("origin.withdraw_fee",
                         self.origin.withdraw_fee,
                         self.origin.coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Hop 1 Deposit fees (hop_1.deposit_fee)
     if self.hop_1.deposit_fee:
         fee = fx_exchange(self.hop_1.trade.sell_coin.id, currency,
                           self.hop_1.deposit_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_1.deposit_fee",
                         self.hop_1.deposit_fee,
                         self.hop_1.trade.sell_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Hop 1 Trade fees (hop_1.trade.fee_amt)
     if self.hop_1.trade.fee_amt:
         fee = fx_exchange(self.hop_1.trade.fee_coin.id, currency,
                           self.hop_1.trade.fee_amt, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_1.trade.fee_amt",
                         self.hop_1.trade.fee_amt,
                         self.hop_1.trade.fee_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Add Hop 1 Withdraw fees (hop_1.withdraw_fee)
     if self.hop_1.withdraw_fee:
         fee = fx_exchange(self.hop_1.trade.buy_coin.id, currency,
                           self.hop_1.withdraw_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_1.withdraw_fee",
                         self.hop_1.withdraw_fee,
                         self.hop_1.trade.buy_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Add Hop 2 Deposit fees (hop_2.deposit_fee)
     if self.hop_2 and self.hop_2.deposit_fee:
         fee = fx_exchange(self.hop_2.trade.sell_coin.id, currency,
                           self.hop_2.deposit_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_2.deposit_fee",
                         self.hop_2.deposit_fee,
                         self.hop_2.trade.sell_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Add Hop 2 Trade fees (hop_2.trade.fee_amt)
     if self.hop_2 and self.hop_2.trade.fee_amt:
         fee = fx_exchange(self.hop_2.trade.fee_coin.id, currency,
                           self.hop_2.trade.fee_amt, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_2.trade.fee_amt",
                         self.hop_2.trade.fee_amt,
                         self.hop_2.trade.fee_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Add Hop 2 Withdraw fees (hop_2.withdraw_fee)
     if self.hop_2 and self.hop_2.withdraw_fee:
         fee = fx_exchange(self.hop_2.trade.buy_coin.id, currency,
                           self.hop_2.withdraw_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("hop_2.withdraw_fee",
                         self.hop_2.withdraw_fee,
                         self.hop_2.trade.buy_coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     # Add Destination Deposit fees (destination.deposit_fee)
     if self.destination.deposit_fee:
         fee = fx_exchange(self.destination.coin.id, currency,
                           self.destination.deposit_fee, logger)
         if fee:
             total_fees += fee
             msg = "calc_fees: {} = {} {} ({} {})"\
                 .format("destination.deposit_fee",
                         self.destination.deposit_fee,
                         self.destination.coin.id,
                         fee,
                         currency)
             logger.debug(msg)
     return total_fees
 def fee_to_currency(self, amount, orig_coin):
     fee_curr = fx_exchange(orig_coin, self.currency, amount, self.logger)
     return num_2_str(fee_curr, self.currency)