예제 #1
0
def buyCoin(coin):
    my_bittrex = Bittrex('******', '####')
    market = 'BTC-' + coin
    price_btc = my_bittrex.get_ticker(market)['result']['Ask']
    finance = finances.Finances()
    size = (finance.getBuyAmount() / price_btc)
    #size = ((profits*0.92)/(price_btc))
    my_bittrex.buy_limit(market, size, price_btc)
    print('BOUGHT', coin)
    ledger_list.append({'coin': coin, 'price': price_btc, 'size': size})
    print(ledger_list)
    f = open('ledger.txt', 'w+')
    f.write(str(ledger_list))
    # updateProfitsSpent(profits*0.92)
    f.close()
예제 #2
0
class TestBittrexMarketAPI(unittest.TestCase):
    def setUp(self):
        self.bittrex = Bittrex()

    def test_secret_and_key(self):
        try:
            os.environ['BITTREX_KEY']
            os.environ['BITTREX_SECRET']
        except KeyError:
            self.fail("Requires BITTREX_KEY and BITTREX_SECRET env variables")

    def test_buy_limit(self):
        self.assertRaises(TypeError, self.bittrex.buy_limit)
        actual = self.bittrex.buy_limit('BTC-LTC', 1, 1)
        test_response_structure(self, actual, 'buy_limit')

    def test_sell_limit(self):
        self.assertRaises(TypeError, self.bittrex.buy_limit)
        actual = self.bittrex.sell_limit('BTC-LTC', 1, 1)
        test_response_structure(self, actual, 'sell_limit')

    def test_cancel(self):
        self.assertRaises(TypeError, self.bittrex.cancel)
        # provide invalid uuid but test the json structure
        actual = self.bittrex.cancel('BTC-LTC')
        test_response_structure(self, actual, 'cancel')

    def test_open_orders(self):
        invalid_actual = self.bittrex.get_open_orders('Invalid Market')
        no_param_actual = self.bittrex.get_open_orders()
        actual = self.bittrex.get_open_orders('BTC-LTC')
        test_failed_response(self, invalid_actual, 'get_open_orders')
        test_basic_response(self, no_param_actual, 'get_open_orders')
        test_basic_response(self, actual, 'get_open_orders')
예제 #3
0
class BittrexWrapper(object):

    def __init__(self, apiKey, apiSecret):
	self.apiKey = apiKey
	self.apiSecret = apiSecret
	self.api = Bittrex(self.apiKey, self.apiSecret)
	self.failure = (False, 0, 0)

    def get_price(self, market_code, base_code='BTC'):
	self.currency_code = '%s-%s' % (base_code, market_code)
	price_ticker = bittrex_api.get_ticker(currency_code)
	if price_ticker['success']:
		return price_ticker
	else:
		return {}

    def get_address(self):
        deposit_address_query = self.api.get_deposit_address(base_code)
        if deposit_address_query['success'] == False and deposit_address_query['message'] == 'ADDRESS_GENERATING':
                time.sleep(10)
                deposit_address_query = self.api.get_deposit_address(base_code)

    def buy_coins(self, market_code, price, base_code='BTC'):
	currency_code = '%s-%s' % (base_code, market_code)

	price_ticker = self.api.get_ticker(currency_code)
	if price_ticker['success']:
		ask_price = price_ticker['result']['Ask']
	else:
		return self.failure

	quantity = price / ask_price 
	sell_market_query = self.api.buy_limit(currency_code, quantity, ask_price)
	if sell_market_query['success']:
		order_uuid = sell_market_query['result']['uuid']
	elif not sell_market_query['success']:
		return self.Failure

	# Sleep for long enough for bittrex to process the order
	time.sleep(30)  # 4) Check the Order
	order_status_query = bittrex_api.get_order(order_uuid)
	if order_status_query['success']:
		aOrder = dict()
		aOrder['price'] = order_status_query['result']['Price']
		aOrder['Quantity'] = order_status_query['result']['Quantity']
		aOrder['Exchange'] = order_status_query['result']['Exchange']
		aOrder['completed'] = True
		return aOrder['completed'], aOrder['price'], aOrder['Quantity']
	else:
		return self.Failure
예제 #4
0
class Trader(object):
    """
    Used for handling all trade functionality
    """
    def __init__(self, secrets):
        self.trade_params = secrets["tradeParameters"]
        self.pause_params = secrets["pauseParameters"]

        self.Bittrex = Bittrex(secrets)
        self.Messenger = Messenger(secrets)
        self.Database = Database()

    def initialise(self):
        """
        Fetch the initial coin pairs to track and to print the header line
        """
        try:
            if len(self.Database.app_data["coinPairs"]) < 1:
                self.Database.store_coin_pairs(self.get_markets("BTC"))
            self.Messenger.print_header(
                len(self.Database.app_data["coinPairs"]))
        except ConnectionError as exception:
            self.Messenger.print_exception_error("connection")
            logger.exception(exception)
            exit()

    def analyse_pauses(self):
        """
        Check all the paused buy and sell pairs and reactivate the necessary ones
        """
        if self.Database.check_resume(self.pause_params["buy"]["pauseTime"],
                                      "buy"):
            self.Database.store_coin_pairs(self.get_markets("BTC"))
            self.Messenger.print_resume_pause(
                len(self.Database.app_data["coinPairs"]), "buy")
        if self.Database.check_resume(self.pause_params["sell"]["pauseTime"],
                                      "sell"):
            self.Messenger.print_resume_pause(
                self.Database.app_data["pausedTrackedCoinPairs"], "sell")
            self.Database.resume_sells()

    def analyse_buys(self):
        """
        Analyse all the un-paused coin pairs for buy signals and apply buys
        """
        trade_len = len(self.Database.trades["trackedCoinPairs"])
        pause_trade_len = len(self.Database.app_data["pausedTrackedCoinPairs"])
        if (trade_len < 1 or pause_trade_len == trade_len
            ) and trade_len < self.trade_params["buy"]["maxOpenTrades"]:
            for coin_pair in self.Database.app_data["coinPairs"]:
                self.buy_strategy(coin_pair)

    def analyse_sells(self):
        """
        Analyse all the un-paused tracked coin pairs for sell signals and apply sells
        """
        for coin_pair in self.Database.trades["trackedCoinPairs"]:
            if coin_pair not in self.Database.app_data[
                    "pausedTrackedCoinPairs"]:
                self.sell_strategy(coin_pair)

    def buy_strategy(self, coin_pair):
        """
        Applies the buy checks on the coin pair and handles the results appropriately

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        """
        if (len(self.Database.trades["trackedCoinPairs"]) >=
                self.trade_params["buy"]["maxOpenTrades"]
                or coin_pair in self.Database.trades["trackedCoinPairs"]):
            return
        rsi = self.calculate_RSI(coin_pair=coin_pair,
                                 period=14,
                                 unit=self.trade_params["tickerInterval"])
        day_volume = self.get_current_24hr_volume(coin_pair)
        current_buy_price = self.get_current_price(coin_pair, "ask")

        if self.check_buy_parameters(rsi, day_volume, current_buy_price):
            buy_stats = {"rsi": rsi, "24HrVolume": day_volume}
            self.buy(coin_pair, self.trade_params["buy"]["btcAmount"],
                     current_buy_price, buy_stats)
        elif rsi is not None and rsi <= self.pause_params["buy"][
                "rsiThreshold"]:
            self.Messenger.print_no_buy(coin_pair, rsi, day_volume,
                                        current_buy_price)
        elif rsi is not None:
            self.Messenger.print_pause(coin_pair, rsi,
                                       self.pause_params["buy"]["pauseTime"],
                                       "buy")
            self.Database.pause_buy(coin_pair)

    def sell_strategy(self, coin_pair):
        """
        Applies the sell checks on the coin pair and handles the results appropriately

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        """
        if (coin_pair in self.Database.app_data["pausedTrackedCoinPairs"]
                or coin_pair not in self.Database.trades["trackedCoinPairs"]):
            return
        rsi = self.calculate_RSI(coin_pair=coin_pair,
                                 period=14,
                                 unit=self.trade_params["tickerInterval"])
        current_sell_price = self.get_current_price(coin_pair, "bid")
        profit_margin = self.Database.get_profit_margin(
            coin_pair, current_sell_price)

        if self.check_sell_parameters(rsi, profit_margin):
            sell_stats = {"rsi": rsi, "profitMargin": profit_margin}
            self.sell(coin_pair, current_sell_price, sell_stats)
        elif rsi is not None and profit_margin >= self.pause_params["sell"][
                "profitMarginThreshold"]:
            self.Messenger.print_no_sell(coin_pair, rsi, profit_margin,
                                         current_sell_price)
        elif rsi is not None:
            self.Messenger.print_pause(coin_pair, profit_margin,
                                       self.pause_params["sell"]["pauseTime"],
                                       "sell")
            self.Database.pause_sell(coin_pair)

    def check_buy_parameters(self, rsi, day_volume, current_buy_price):
        """
        Used to check if the buy conditions have been met

        :param rsi: The coin pair's current RSI
        :type rsi: float
        :param day_volume: The coin pair's current 24 hour volume
        :type day_volume: float
        :param current_buy_price: The coin pair's current price
        :type current_buy_price: float

        :return: Boolean indicating if the buy conditions have been met
        :rtype : bool
        """
        return (
            rsi is not None and rsi <= self.trade_params["buy"]["rsiThreshold"]
            and day_volume >= self.trade_params["buy"]["24HourVolumeThreshold"]
            and
            current_buy_price > self.trade_params["buy"]["minimumUnitPrice"])

    def check_sell_parameters(self, rsi, profit_margin):
        """
        Used to check if the sell conditions have been met

        :param rsi: The coin pair's current RSI
        :type rsi: float
        :param profit_margin: The coin pair's current profit margin
        :type profit_margin: float

        :return: Boolean indicating if the sell conditions have been met
        :rtype : bool
        """
        return ((rsi is not None
                 and rsi >= self.trade_params["sell"]["rsiThreshold"]
                 and profit_margin >
                 self.trade_params["sell"]["minProfitMarginThreshold"])
                or profit_margin >
                self.trade_params["sell"]["profitMarginThreshold"])

    def buy(self, coin_pair, btc_quantity, price, stats, trade_time_limit=2):
        """
        Used to place a buy order to Bittrex. Wait until the order is completed.
        If the order is not filled within trade_time_limit minutes cancel it.

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param btc_quantity: The amount of BTC to buy with
        :type btc_quantity: float
        :param price: The price at which to buy
        :type price: float
        :param stats: The buy stats object
        :type stats: dict
        :param trade_time_limit: The time in minutes to wait fot the order before cancelling it
        :type trade_time_limit: float
        """
        buy_data = self.Bittrex.buy_limit(coin_pair, btc_quantity / price,
                                          price)
        if not buy_data["success"]:
            return logger.error(
                "Failed to buy on {} market.".format(coin_pair))
        self.Database.store_initial_buy(coin_pair, buy_data["result"]["uuid"])

        buy_order_data = self.get_order(buy_data["result"]["uuid"],
                                        trade_time_limit * 60)
        self.Database.store_buy(buy_order_data["result"], stats)

        self.Messenger.send_buy_email(buy_order_data["result"], stats)
        self.Messenger.print_buy(coin_pair, price, stats["rsi"],
                                 stats["24HrVolume"])
        self.Messenger.play_sw_imperial_march()

    def sell(self, coin_pair, price, stats, trade_time_limit=2):
        """
        Used to place a sell order to Bittrex. Wait until the order is completed.
        If the order is not filled within trade_time_limit minutes cancel it.

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param price: The price at which to buy
        :type price: float
        :param stats: The buy stats object
        :type stats: dict
        :param trade_time_limit: The time in minutes to wait fot the order before cancelling it
        :type trade_time_limit: float
        """
        trade = self.Database.get_open_trade(coin_pair)
        sell_data = self.Bittrex.sell_limit(coin_pair, trade["quantity"],
                                            price)
        if not sell_data["success"]:
            return logger.error(
                "Failed to sell on {} market. Bittrex error message: {}".
                format(coin_pair, sell_data["message"]))

        sell_order_data = self.get_order(sell_data["result"]["uuid"],
                                         trade_time_limit * 60)
        # TODO: Handle partial/incomplete sales.
        self.Database.store_sell(sell_order_data["result"], stats)

        self.Messenger.send_sell_email(sell_order_data["result"], stats)
        self.Messenger.print_sell(coin_pair, price, stats["rsi"],
                                  stats["profitMargin"])
        self.Messenger.play_sw_theme()

    def get_markets(self, main_market_filter=None):
        """
        Gets all the Bittrex markets and filters them based on the main market filter

        :param main_market_filter: Main market to filter on (ex: BTC, ETH, USDT)
        :type main_market_filter: str

        :return: All Bittrex markets (with filter applied, if any)
        :rtype : list
        """
        markets = self.Bittrex.get_markets()
        if not markets["success"]:
            logger.error("Failed to fetch Bittrex markets")
            exit()

        markets = markets["result"]
        if main_market_filter is not None:
            market_check = main_market_filter + "-"
            markets = py_.filter_(
                markets, lambda market: market_check in market["MarketName"])
        markets = py_.map_(markets, lambda market: market["MarketName"])
        return markets

    def get_current_price(self, coin_pair, price_type):
        """
        Gets current market price for a coin pair

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        :param price_type: The type of price to get (one of: 'ask', 'bid')
        :type price_type: str

        :return: Coin pair's current market price
        :rtype : float
        """
        coin_summary = self.Bittrex.get_market_summary(coin_pair)
        if not coin_summary["success"]:
            logger.error(
                "Failed to fetch Bittrex market summary for the {} market".
                format(coin_pair))
            return None
        if price_type == "ask":
            return coin_summary["result"][0]["Ask"]
        if price_type == "bid":
            return coin_summary["result"][0]["Bid"]
        return coin_summary["result"][0]["Last"]

    def get_current_24hr_volume(self, coin_pair):
        """
        Gets current 24 hour market volume for a coin pair

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str

        :return: Coin pair's current 24 hour market volume
        :rtype : float
        """
        coin_summary = self.Bittrex.get_market_summary(coin_pair)
        if not coin_summary["success"]:
            logger.error(
                "Failed to fetch Bittrex market summary for the {} market".
                format(coin_pair))
            return None
        return coin_summary["result"][0]["BaseVolume"]

    def get_closing_prices(self, coin_pair, period, unit):
        """
        Returns closing prices within a specified time frame for a coin pair

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param period: Number of periods to query
        :type period: int
        :param unit: Ticker interval (one of: 'oneMin', 'fiveMin', 'thirtyMin', 'hour', 'week', 'day', and 'month')
        :type unit: str

        :return: Array of closing prices
        :rtype : list
        """
        historical_data = self.Bittrex.get_historical_data(
            coin_pair, period, unit)
        closing_prices = []
        for i in historical_data:
            closing_prices.append(i["C"])
        return closing_prices

    def get_order(self, order_uuid, trade_time_limit):
        """
        Used to get an order from Bittrex by it's UUID.
        First wait until the order is completed before retrieving it.
        If the order is not completed within trade_time_limit seconds, cancel it.

        :param order_uuid: The order's UUID
        :type order_uuid: str
        :param trade_time_limit: The time in seconds to wait fot the order before cancelling it
        :type trade_time_limit: float

        :return: Order object
        :rtype : dict
        """
        start_time = time.time()
        order_data = self.Bittrex.get_order(order_uuid)
        while time.time() - start_time <= trade_time_limit and order_data[
                "result"]["IsOpen"]:
            time.sleep(10)
            order_data = self.Bittrex.get_order(order_uuid)

        if order_data["result"]["IsOpen"]:
            error_str = self.Messenger.print_order_error(
                order_uuid, trade_time_limit, order_data["result"]["Exchange"])
            logger.error(error_str)
            if order_data["result"]["Type"] == "LIMIT_BUY":
                self.Bittrex.cancel(order_uuid)
            return order_data

        return order_data

    def calculate_RSI(self, coin_pair, period, unit):
        """
        Calculates the Relative Strength Index for a coin_pair
        If the returned value is above 75, it's overbought (SELL IT!)
        If the returned value is below 25, it's oversold (BUY IT!)

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param period: Number of periods to query
        :type period: int
        :param unit: Ticker interval (one of: 'oneMin', 'fiveMin', 'thirtyMin', 'hour', 'week', 'day', and 'month')
        :type unit: str

        :return: RSI
        :rtype : float
        """
        closing_prices = self.get_closing_prices(coin_pair, period * 3, unit)
        count = 0
        change = []
        # Calculating price changes
        for i in closing_prices:
            if count != 0:
                change.append(i - closing_prices[count - 1])
            count += 1
            if count == 15:
                break
        # Calculating gains and losses
        advances = []
        declines = []
        for i in change:
            if i > 0:
                advances.append(i)
            if i < 0:
                declines.append(abs(i))
        average_gain = (sum(advances) / 14)
        average_loss = (sum(declines) / 14)
        new_avg_gain = average_gain
        new_avg_loss = average_loss
        for _ in closing_prices:
            if 14 < count < len(closing_prices):
                close = closing_prices[count]
                new_change = close - closing_prices[count - 1]
                add_loss = 0
                add_gain = 0
                if new_change > 0:
                    add_gain = new_change
                if new_change < 0:
                    add_loss = abs(new_change)
                new_avg_gain = (new_avg_gain * 13 + add_gain) / 14
                new_avg_loss = (new_avg_loss * 13 + add_loss) / 14
                count += 1

        if new_avg_loss == 0:
            return None

        rs = new_avg_gain / new_avg_loss
        new_rs = 100 - 100 / (1 + rs)
        return new_rs
예제 #5
0
class TradeBot():
    def __init__(self, key=None, secret=None, **kwargs):
        self.exchange = Bittrex(key, secret)
        self.orders = []
        # Default config
        config = {
            'base_currency': 'ETH',
            'min_order': 0.001,
            'max_order': 0.05,
            'sleep_time': 60,
            'profit': 2,
            'min_volume': 75,
            'max_units': 100
        }
        # Update config from object constructor
        config.update(kwargs)
        # Set attributes based on config
        for attr in config.keys():
            setattr(self, attr, config[attr])

    def get_markets(self):
        logging.info(f'Getting markets for {self.base_currency}')
        all_markets = self.exchange.get_markets()['result']
        markets = set()
        for mkt in all_markets:
            if mkt['BaseCurrency'] == self.base_currency:
                markets.add(mkt['MarketName'])
        return markets

    def get_coins_with_open_orders(self):
        open_orders = self.exchange.get_open_orders()['result']
        if len(open_orders) == 0:
            return []
        else:
            return [x['Exchange'] for x in open_orders]

    def get_market_data(self):
        mkt_data = []
        for mkt in self.markets:
            logging.info(f'Getting market data for {mkt}')
            data = self.exchange.get_marketsummary(mkt)['result'][0]
            data['Change'] = calculate_change(data['Last'], data['Low'])
            mkt_data.append(data)
        return mkt_data

    def has_balance_to_buy(self):
        logging.info('checking if we have some balance to buy')
        q = self.exchange.get_balance(self.base_currency)
        # balance_adjustment to avoid INSUFFICIENT FUNDS MESSAGE
        balance_adjustment = 0.0005
        self.balance = q['result']['Available'] - balance_adjustment
        logging.debug(f'{self.balance}{self.base_currency} available')
        if self.balance >= self.min_order:
            return True
        else:
            return False

    def get_market_to_buy(self):
        self.update()
        mkt = [
            m for m in self.market_data if m['BaseVolume'] >= self.min_volume
        ]
        sorted_mkt = sorted(mkt, key=lambda x: x['BaseVolume'], reverse=True)
        while sorted_mkt[0]['MarketName'] in self.coins_with_open_orders:
            sorted_mkt.pop(0)
        return sorted_mkt[0]

    def buy(self, mkt):
        coin = mkt['MarketName']
        # get a price between ask and bid
        price = (mkt['Ask'] + mkt['Bid']) / 2
        if self.balance > self.max_order:
            qnt = self.max_order / price
        else:
            qnt = self.balance / price
        if qnt > self.max_units:
            qnt = self.max_units
        if (qnt * price) < self.min_order:
            qnt = self.min_order / price
        logging.info(f'BUY {qnt} {coin} - price {price}, total {price * qnt}')
        order = self.exchange.buy_limit(coin, qnt, price)
        if order['success']:
            self.orders.append(order['result']['uuid'])
        else:
            logging.error(f'BUY FAIL - {order}')
        return (order)

    def sell(self):
        for order in self.orders:
            order_info = self.exchange.get_order(order)['result']
            if order_info['Closed']:
                coin = order_info['Exchange']
                qnt = order_info['Quantity']
                price = profit(order_info['PricePerUnit'], self.profit)
                sell_order = self.exchange.sell_limit(coin, qnt, price)
                self.orders.remove(order)
                logging.info(f'SELL {order} {sell_order}')

    def update(self):
        logging.info('Updating data')
        self.markets = self.get_markets()
        self.market_data = self.get_market_data()
        self.coins_with_open_orders = self.get_coins_with_open_orders()

    def do_trade(self):
        if self.has_balance_to_buy():
            self.buy(self.get_market_to_buy())
        if len(self.orders) > 0:
            self.sell()
        logging.info(f'Sleeping for {self.sleep_time} seconds')
        sleep(self.sleep_time)

    def run(self):
        logging.info('Starting Bot')
        while True:
            self.do_trade()
예제 #6
0
class CryptoArb(object):
    """
    Integration tests for the Bittrex Account API.
      * These will fail in the absence of an internet connection or if bittrex API goes down.
      * They require a valid API key and secret issued by Bittrex.
      * They also require the presence of a JSON file called secrets.json.
      It is structured as such:
    {
      "key": "12341253456345",
      "secret": "3345745634234534"
    }
    """
    def setUp(self):
        with open("secrets.json") as secrets_file:
            self.secrets = json.load(secrets_file)
            secrets_file.close()
        self.bittrex = Bittrex(self.secrets['key'], self.secrets['secret'])

    def test(self):

        desiredResult = .95

        ## ETHEREUM

        btcResult = 0
        LoopNumber = 1

        while btcResult < desiredResult:

            markets = self.bittrex.get_market_summaries()

            marketCount = len(markets["result"])

            print("Start - " + str(LoopNumber))
            btcCount = 0
            ethCount = 0

            ### ~~ Filling the BTC-ALT Matrix ~~ ###

            # Counting the number of BTC Currency Pairs
            btcLoopCount = 0
            while btcLoopCount < marketCount:
                if "BTC-" in markets["result"][btcLoopCount]["MarketName"]:
                    btcCount = btcCount + 1
                btcLoopCount = btcLoopCount + 1

            # Creating the BTC pair-exchange matrix
            btcCol, btcRow = 2, btcCount
            BTCMatrix = [[0 for x in range(btcCol)] for y in range(btcRow)]

            # Filling the BTC Matrix
            btcLoopCount = 0
            btcMatrixRowCount = 0

            while btcLoopCount < marketCount:
                if "BTC-" in markets["result"][btcLoopCount]["MarketName"]:

                    BTCMatrix[btcMatrixRowCount][0] = markets["result"][
                        btcLoopCount]["MarketName"]
                    BTCMatrix[btcMatrixRowCount][1] = markets["result"][
                        btcLoopCount]["Ask"]

                    btcMatrixRowCount = btcMatrixRowCount + 1

                btcLoopCount = btcLoopCount + 1

            ### ~~ Filling the ETH-ALT Matrix ~~ ###

            # Counting the number of ETH Currency Pairs
            ethLoopCount = 0
            while ethLoopCount < marketCount:
                if "ETH-" in markets["result"][ethLoopCount]["MarketName"]:
                    ethCount = ethCount + 1
                ethLoopCount = ethLoopCount + 1

            # Creating the ETH pair-exchange matrix
            ethCol, ethRow = 2, ethCount
            ETHMatrix = [[0 for x in range(ethCol)] for y in range(ethRow)]

            # Filling the ETH Matrix
            ethLoopCount = 0
            ethMatrixRowCount = 0

            while ethLoopCount < marketCount:
                if "ETH-" in markets["result"][ethLoopCount]["MarketName"]:

                    ETHMatrix[ethMatrixRowCount][0] = markets["result"][
                        ethLoopCount]["MarketName"]
                    ETHMatrix[ethMatrixRowCount][1] = markets["result"][
                        ethLoopCount]["Bid"]

                    ethMatrixRowCount = ethMatrixRowCount + 1

                ethLoopCount = ethLoopCount + 1

            btc_ethTick = self.bittrex.get_ticker("BTC-ETH")
            btc_eth_BTC = btc_ethTick["result"]["Bid"]

            # ~~~ Comparing Bitcoin Arbitrage Returns ~~~ #

            arbBTCPairs = []
            arbBTCReturn = []
            arbBTCTestReturn = []
            arbBTCRow = 0

            for btcAlt in BTCMatrix:

                for ethAlt in ETHMatrix:

                    if ethAlt[0][4:] == btcAlt[0][4:]:

                        btcResult = 0

                        #arbBTCPairs.append(str(btcAlt[0]) + " > " + str(ethAlt[0]) + " > BTC_ETH")
                        arbPath = str(btcAlt[0]) + " > " + str(
                            ethAlt[0]) + " > BTC_ETH"

                        btcAltDiff = 0.0000007
                        altEthDiff = -0.0000002
                        ethBtcDiff = -0.000001

                        # Forumla to check returns
                        print("BTC -> Alt: " + str(btcAlt[1]))
                        btc_altX = float(btcAlt[1] + btcAltDiff)
                        print("Alt -> ETH: " + str(ethAlt[1]))
                        eth_altX = float(ethAlt[1] + altEthDiff)
                        print("ETH -> BTC: " + str(btc_eth_BTC))
                        btc_ethX = float(btc_eth_BTC + ethBtcDiff)

                        #test1 = float(btcAlt[1] - 0.00000001)
                        #test2 = float(ethAlt[1] - 0.00000001)
                        #test3 = float(btc_eth_BTC - 0.0000004)

                        print(
                            str(btcAlt[0]) + " > " + str(ethAlt[0]) +
                            " > BTC_ETH")

                        btcUnits = 1
                        print("BTC = " + str(btcUnits))

                        altUnits = round(((btcUnits / 1.0025) / btc_altX), 8)
                        #testaltUnits = round(((btcUnits / 1.0025) / test1), 8)

                        print("Alt Units = " + str(altUnits) + " (" +
                              str(btc_altX) + ")")
                        #print("Test Alt Units = " + str(testaltUnits) + " (" + str(test1) + ")")

                        ethUnits = round(
                            ((altUnits - (altUnits * 0.0025)) * eth_altX), 8)
                        #testethUnits = round(((testaltUnits - (testaltUnits * 0.0025)) * test2), 8)

                        print("ETH Units = " + str(ethUnits) + " (" +
                              str(eth_altX) + ")")
                        #print("Test ETH Units = " + str(testethUnits) + " (" + str(test2) + ")")

                        btcResult = round(
                            ((ethUnits - (ethUnits * 0.0025)) * btc_ethX), 8)
                        #testbtcResult = round(((testethUnits - (testethUnits * 0.0025)) * test3), 8)

                        print("BTC Result = " + str(btcResult) + " (" +
                              str(btc_ethX) + ")")
                        #print("Test BTC Result = " + str(testbtcResult) + " (" + str(test3) + ")")

                        print("")

                        #arbBTCReturn.append(btcResult)
                        #arbBTCTestReturn.append(testbtcResult)
                        print(btcAlt[0])
                        if (btcResult
                            ) >= desiredResult and btcAlt[0] != "BTC-SALT":
                            print("!! Desired Result Reached !!")
                            break

                        arbBTCRow = arbBTCRow + 1

                if (btcResult) >= desiredResult and btcAlt[0] != "BTC-SALT":
                    break

            print("")

            # If desired result is not reached empty the lists to start again
            if btcResult <= desiredResult:
                BTCMatrix[:] = []
                ETHMatrix[:] = []
                arbBTCPairs[:] = []
                arbBTCReturn[:] = []

            LoopNumber = LoopNumber + 1

            # Loops if return isn't good enough i.e. > 1.005

        # Loop has been exited because return is good enough
        # If statement is final check to make sure return is good enough
        if float(btcResult) > desiredResult and btcAlt[0] != "BTC-SALT":

            print("Arb Return = " + str(btcResult))

            print("begin timer")

            startTime = time.time()

            # Path of the arb which yiels return i.e. BTC -> ALT -> ETH -> BTC
            #print(arbPath)

            # Getting name of Alt
            if len(arbPath) == 25:
                alt = arbPath[4:6]
                print("Alt = " + alt)

            elif len(arbPath) == 27:
                alt = arbPath[4:7]
                print("Alt = " + alt)

            elif len(arbPath) == 29:
                alt = arbPath[4:8]
                print("Alt = " + alt)

            elif len(arbPath) == 31:
                alt = arbPath[4:9]
                print("Alt = " + alt)

            else:
                print("Wrong Number Letters " + len(arbPath))

            print("Time elapsed " + str(time.time() - startTime))

            # Begin Buy Process

            orderBTCALTBook = self.bittrex.get_orderbook(
                "BTC-" + str(alt), "sell")

            print("")

            #BTCBal = self.bittrex.get_balance("BTC")

            #if str(BTCBal["result"]["Balance"]) == "None":
            #    principle = 0
            #else:
            #    principle = float(BTCBal["result"]["Balance"])

            principle = 0.00065
            print("Principle = " + str(principle))

            AltQuantity = 0
            ETHQuantity = 0
            BTCQuantity = 0
            market = "BTC-" + alt
            print("Market = " + market)
            print("")

            actBtcAltRate = 0
            actAltEthRate = 0
            actEthBtcRate = 0

            btcOrderCount = 0
            while principle > 0:

                print("BTC -> " + str(alt) + " Order " +
                      str(btcOrderCount + 1) + ": Principle = " +
                      str(principle))

                askQuantity = orderBTCALTBook["result"][btcOrderCount][
                    "Quantity"]
                askRate = orderBTCALTBook["result"][btcOrderCount]["Rate"]
                askTotal = askQuantity * askRate

                print("-- Order Details: --")
                print("---- Ask Quantity = " + str(askQuantity))
                print("---- Ask Rate = " + str(askRate))
                print("---- Ask Total = " + str(askTotal))
                print("---- Principle = " + str(principle))
                print("")

                if askTotal > principle:
                    print("---- Executing full final trade...")
                    tradeQuantity = math.floor(
                        ((principle / 1.0025) / askRate) *
                        100000000) / 100000000
                    print("---- Trade Quantity = " + str(tradeQuantity) +
                          " (" + str(principle / 1.0025) + " / " +
                          str(askRate) + ")")
                    # Execute full or remainder of trade
                    AltQuantity = AltQuantity + tradeQuantity
                    print("---- BUY " + str(AltQuantity) + " " + str(alt) +
                          " @ " + str(askRate) + "BTC = " +
                          str(round((AltQuantity * askRate), 8)))

                    altBuy = self.bittrex.buy_limit(market, AltQuantity,
                                                    askRate)
                    print("---- " + str(altBuy))
                    actBtcAltRate = askRate  # I can delete this because I have a more accurate below from get_order_history
                    altBuy = True
                    break
                else:
                    # Execute a portion of the trade
                    print("---- Partial Trade - CANCEL ... ")
                    print("---- BUY " + str(askQuantity) + str(alt) + " @ " +
                          str(askRate) + " BTC = " +
                          str(round((askQuantity * askRate), 8)))
                    AltQuantity = AltQuantity + askQuantity
                    principle = principle - askTotal
                    break
                    #buy = self.bittrex.buy_limit(market, askQuantity, askRate)
                    #print(buy)
                    #principle = (principle * 0.9975) - askTotal
                    # execute trade

                btcOrderCount = btcOrderCount + 1

            print("")
            print(str(alt) + " Quantity = " + str(AltQuantity))
            firstTrade = time.time() - startTime
            secondTrade = 0
            finalTrade = 0
            print("Time since arb calc = " + str(firstTrade))

            print("")

            if altBuy == True:

                orderETHALTBook = self.bittrex.get_orderbook(
                    "ETH-" + str(alt), "buy")

                market = "ETH-" + alt

                ogAltQuantity = AltQuantity

                altOrderCount = 0
                while AltQuantity > 0:

                    print(
                        str(alt) + " -> ETH Order " + str(altOrderCount + 1) +
                        ": Principle = " + str(AltQuantity))
                    bidQuantity = orderETHALTBook["result"][altOrderCount][
                        "Quantity"]
                    bidRate = orderETHALTBook["result"][altOrderCount]["Rate"]
                    bidTotal = bidQuantity * bidRate

                    print("-- Order Details: --")
                    print("---- Bid Quantity = " + str(bidQuantity))
                    print("---- Bid Rate = " + str(bidRate))
                    print("---- Bid Total = " + str(bidTotal))
                    print("---- Alt Quantity = " + str(AltQuantity))
                    print("")

                    if bidQuantity > AltQuantity:
                        print("Executing full final trade...")
                        tradeQuantity = math.floor(
                            ((AltQuantity * 0.9975) * bidRate) *
                            100000000) / 100000000
                        print("---- Trade Quantity = " + str(tradeQuantity) +
                              " (" + str(AltQuantity) + " * " + str(bidRate) +
                              ")")
                        # Execute full or remainder of trade
                        print("---- SELL " + str(ogAltQuantity) + " " +
                              str(alt) + " @ " + str(bidRate) + "ETH = " +
                              str(tradeQuantity))
                        ETHQuantity = ETHQuantity + tradeQuantity

                        altSell = self.bittrex.sell_limit(
                            market, ogAltQuantity, bidRate)
                        print("---- " + str(altSell))
                        actAltEthRate = bidRate  # I can delete this because I have a more accurate below from get_order_history
                        altSell = True
                        break
                    else:
                        # Execute a portion of the trade
                        print("---- Executing partial trade... " +
                              str(bidQuantity) + str(alt) + " @ " +
                              str(bidRate) + "ETH = " +
                              str(bidQuantity * bidRate))
                        ETHQuantity = (ETHQuantity + bidTotal) * 0.9975
                        sell = self.bittrex.sell_limit(market, bidQuantity,
                                                       bidRate)
                        print(sell)
                        AltQuantity = AltQuantity - bidQuantity
                        # execute trade

                    print("")
                    altOrderCount = altOrderCount + 1

                if altSell == True:

                    print("")
                    print("ETH Quantity = " + str(ETHQuantity))
                    secondTrade = time.time() - startTime
                    print("Time since arb calc = " + str(secondTrade))
                    print("")

                    orderBTCETHBook = self.bittrex.get_orderbook(
                        "BTC-ETH", "buy")

                    ogETHQuantity = ETHQuantity

                    market = "BTC-ETH"

                    ethOrderCount = 0
                    while ETHQuantity > 0:
                        print("ETH -> BTC Order " + str(ethOrderCount + 1) +
                              ": Principle = " + str(ETHQuantity))
                        bidQuantity = orderBTCETHBook["result"][ethOrderCount][
                            "Quantity"]
                        bidRate = orderBTCETHBook["result"][ethOrderCount][
                            "Rate"]
                        bidTotal = bidQuantity * bidRate

                        print("-- Order Details: --")
                        print("---- Bid Quantity = " + str(bidQuantity))
                        print("---- Bid Rate = " + str(bidRate))
                        print("---- Bid Total = " + str(bidTotal))
                        print("---- ETH Quantity = " + str(ETHQuantity))
                        print("")

                        if bidQuantity > ETHQuantity:
                            print("---- Executing full final trade...")
                            tradeQuantity = math.floor(
                                ((ETHQuantity * 0.9975) * bidRate) *
                                100000000) / 100000000
                            print("---- Trade Quantity = " +
                                  str(tradeQuantity) + " (" +
                                  str(ETHQuantity) + " * " + str(bidRate) +
                                  ")")
                            # Execute full or remainder of trade
                            print("---- SELL " + str(ogETHQuantity) +
                                  " ETH @ " + str(bidRate) + "BTC = " +
                                  str(tradeQuantity))
                            BTCQuantity = BTCQuantity + tradeQuantity

                            sell = self.bittrex.sell_limit(
                                market, ogETHQuantity, bidRate)
                            print("---- " + str(sell))
                            actEthBtcRate = bidRate  # I can delete this because I have a more accurate below from get_order_history
                            break
                        else:
                            # Execute a portion of the trade
                            print("---- Executing partial trade... " +
                                  str(bidQuantity) + "ETH @ " + str(bidRate) +
                                  "BTC = " + str(bidQuantity * bidRate))
                            BTCQuantity = BTCQuantity + bidTotal
                            sell = self.bittrex.sell_limit(
                                market, bidQuantity, bidRate)
                            print(sell)

                            ETHQuantity = ETHQuantity - bidQuantity
                            # execute trade

                        ethOrderCount = ethOrderCount + 1

                    print(BTCQuantity)

                    finalTrade = time.time() - startTime
                    print("Time since arb calc = " + str(finalTrade))

                    btcAltMarket = self.bittrex.get_market_summary("BTC-" +
                                                                   str(alt))
                    btcAltVolume = btcAltMarket["result"][0]["Volume"]

                    altEthMarket = self.bittrex.get_market_summary("ETH-" +
                                                                   str(alt))
                    altEthVolume = altEthMarket["result"][0]["Volume"]

                    ethBtcMarket = self.bittrex.get_market_summary("BTC-ETH")
                    ethBtcVolume = ethBtcMarket["result"][0]["Volume"]

                    #  Grab bittrex Trade Details
                    #  1 - BTC-ALT
                    #tradeDetails = self.bittrex.get_order_history()

                    tradeDetails = self.bittrex.get_order_history()
                    tradeOne = tradeDetails["result"][2]
                    tradeTwo = tradeDetails["result"][1]
                    tradeThree = tradeDetails["result"][0]

                    #  Actual Arb Return
                    tradeOneActualValue = tradeOne["Price"] + tradeOne[
                        "Commission"]
                    tradeThreeActualValue = tradeThree["Price"] + tradeThree[
                        "Commission"]
                    actualArbReturn = tradeThreeActualValue / tradeOneActualValue

                    # Actual Rates
                    tradeOneActualRate = tradeOne["PricePerUnit"]
                    tradeTwoActualRate = tradeTwo["PricePerUnit"]
                    tradeThreeActualRate = tradeThree["PricePerUnit"]

                    with open('Trade Tracker.csv', 'a', newline='') as csvfile:
                        tracker = csv.writer(csvfile,
                                             delimiter=',',
                                             quotechar='|',
                                             quoting=csv.QUOTE_MINIMAL)
                        tracker.writerow([
                            arbPath,
                            datetime.datetime.now().strftime(
                                "%Y-%m-%d %H:%M:%S.%f")[:-3], btcResult,
                            actualArbReturn,
                            str(btcAlt[1]),
                            str(btcAltDiff), btcAlt[1] + btcAltDiff,
                            tradeOneActualRate,
                            str(btcAlt[1] - tradeOneActualRate),
                            str((
                                (btcAlt[1] - tradeOneActualRate) / btcAlt[1]) *
                                100),
                            str(firstTrade),
                            str(btcAltVolume),
                            str(ethAlt[1]),
                            str(altEthDiff),
                            str(ethAlt[1] + altEthDiff), tradeTwoActualRate,
                            str(ethAlt[1] - tradeTwoActualRate),
                            str((
                                (ethAlt[1] - tradeTwoActualRate) / ethAlt[1]) *
                                100),
                            str(secondTrade),
                            str(altEthVolume),
                            str(btc_eth_BTC),
                            str(ethBtcDiff),
                            str(btc_eth_BTC + ethBtcDiff),
                            tradeThreeActualRate,
                            str(btc_eth_BTC - tradeThreeActualRate),
                            str(((btc_eth_BTC - tradeThreeActualRate) /
                                 btc_eth_BTC) * 100),
                            str(finalTrade),
                            str(ethBtcVolume)
                        ])

                    print("Excel Save Successful")

                    db = firebase.database()

                    data = {
                        "Arb Path":
                        arbPath,
                        "Date Time":
                        datetime.datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S.%f")[:-3],
                        "Principle":
                        principle,
                        "Actual Return":
                        BTCQuantity,
                        "Expected Arb Return":
                        btcResult,
                        "Actual Arb Return":
                        actualArbReturn,
                        "Trade 1 Quoted Rate":
                        str(btcAlt[1]),
                        "Trade 1 Adjustment":
                        str(btcAltDiff),
                        "Trade 1 Adjusted Quote":
                        btcAlt[1] + btcAltDiff,
                        "Trade 1 Actual Rate":
                        tradeOneActualRate,
                        "Trade 1 Actual-Quote Diff":
                        str(btcAlt[1] - tradeOneActualRate),
                        "Trade 1 Actual-Quote % Diff":
                        str(((btcAlt[1] - tradeOneActualRate) / btcAlt[1]) *
                            100),
                        "Trade 1 Time From Quote":
                        str(firstTrade),
                        "Trade 1 Market Volume":
                        str(btcAltVolume),
                        "Trade 2 Quoted Rate":
                        str(ethAlt[1]),
                        "Trade 2 Adjustment":
                        str(altEthDiff),
                        "Trade 2 Adjusted Quote":
                        str(ethAlt[1] + altEthDiff),
                        "Trade 2 Actual Rate":
                        tradeTwoActualRate,
                        "Trade 2 Actual-Quote Diff":
                        str(ethAlt[1] - tradeTwoActualRate),
                        "Trade 2 Actual-Quote % Diff":
                        str(((ethAlt[1] - tradeTwoActualRate) / ethAlt[1]) *
                            100),
                        "Trade 2 Time From Quote":
                        str(secondTrade),
                        "Trade 2 Market Volume":
                        str(altEthVolume),
                        "Trade 3 Quoted Rate":
                        str(btc_eth_BTC),
                        "Trade 3 Adjustment":
                        str(ethBtcDiff),
                        "Trade 3 Adjusted Quote":
                        str(btc_eth_BTC + ethBtcDiff),
                        "Trade 3 Actual Rate":
                        tradeThreeActualRate,
                        "Trade 3 Actual-Quote Diff":
                        str(btc_eth_BTC - tradeThreeActualRate),
                        "Trade 3 Actual-Quote % Diff Rate":
                        str(((btc_eth_BTC - tradeThreeActualRate) /
                             btc_eth_BTC) * 100),
                        "Trade 3 Time From Quote":
                        str(finalTrade),
                        "Trade 3 Market Volume":
                        str(ethBtcVolume)
                    }

                    db.child("Successful Transactions").push(data)

                else:
                    print("ALT -> ETH Fail")

            else:
                print("BTC -> ALT Fail")
예제 #7
0
class bittrex_private:
    def __init__(self):
        # self.bittrex_public = Bittrex(None, None)  # 公開情報を扱うBittrexオブジェクト
        self.bittrex_private = Bittrex(KEY, SECRET)  # 個人の情報を扱うBittrexオブジェクト

    # トレード履歴を取得
    def get_order_history(self):
        response = self.bittrex_private.get_order_history()
        pprint(response)
        return response

    # 買い注文を出す
    # marketに通貨ペア、quantityに注文する量、rateに価格を指定
    def buy_alt_coin(self, market, quantity, rate):
        response = self.bittrex_private.buy_limit(market=market,
                                                  quantity=quantity,
                                                  rate=rate)
        # 成功なら注文id、失敗ならfalseを返す
        if response['success'] is False:
            print(response)
            return False
        else:
            return response['result']['uuid']

    # 売り注文を出す
    # marketに通貨ペア、quantityに注文する量、rateに価格を指定
    def sell_alt_coin(self, market, quantity, rate):
        response = self.bittrex_private.sell_limit(market=market,
                                                   quantity=quantity,
                                                   rate=rate)
        # 成功なら注文id、失敗ならfalseを返す
        if response['success'] is False:
            print(response)
            return False
        else:
            return response['result']['uuid']

    # 注文をキャンセルする
    def order_cancel(self, uuid):
        response = self.bittrex_private.cancel(uuid=uuid)
        # 成功ならtrue、失敗ならfalseを返す
        print(response)
        return response['success']

    # 注文一覧を取得する
    def get_orders(self):
        order_list = []
        response = self.bittrex_private.get_open_orders()
        if response['success'] is False:
            print(response)
            return False
        else:
            # 注文が1件もない場合
            if len(response['result']) == 0:
                return None

            for item in response['result']:
                # 通貨の種類と量、注文IDを抜き出す
                balance = {}
                balance['market'] = item['Exchange']
                balance['quantity'] = item['Quantity']
                balance['uuid'] = item['OrderUuid']
                order_list.append(balance)

        return order_list

    # 所有している通貨をList型で返す
    def get_balances(self):
        balance_list = []
        response = self.bittrex_private.get_balances()
        if response['success'] is False:
            print(response)
            return False
        else:
            for item in response['result']:
                # 利用可能な通貨量が0の場合はスキップする
                if item['Available'] == 0:
                    continue
                # 通貨の種類と量を抜き出す
                balance = {}
                balance['currency'] = item['Currency']
                balance['available'] = item['Available']
                balance_list.append(balance)

        return balance_list
예제 #8
0
class Trader(object):
    """
    Used for handling all trade functionality
    """

    def __init__(self, secrets):
        self.trade_params = secrets["tradeParameters"]
        self.pause_params = secrets["pauseParameters"]

        self.Bittrex = Bittrex(secrets)
        self.Messenger = Messenger(secrets)
        self.Database = Database()

    def initialise(self):
        """
        Fetch the initial coin pairs to track and to print the header line
        """
        try:
            if len(self.Database.app_data["coinPairs"]) < 1:
                self.Database.store_coin_pairs(self.get_markets("BTC"))
            self.Messenger.print_header(len(self.Database.app_data["coinPairs"]))
        except ConnectionError as exception:
            self.Messenger.print_exception_error("connection")
            logger.exception(exception)
            exit()

    def analyse_pauses(self):
        """
        Check all the paused buy and sell pairs and reactivate the necessary ones
        """
        if self.Database.check_resume(self.pause_params["buy"]["pauseTime"], "buy"):
            self.Database.store_coin_pairs(self.get_markets("BTC"))
            self.Messenger.print_resume_pause(len(self.Database.app_data["coinPairs"]), "buy")
        if self.Database.check_resume(self.pause_params["sell"]["pauseTime"], "sell"):
            self.Messenger.print_resume_pause(self.Database.app_data["pausedTrackedCoinPairs"], "sell")
            self.Database.resume_sells()

    def analyse_buys(self):
        """
        Analyse all the un-paused coin pairs for buy signals and apply buys
        """
        trade_len = len(self.Database.trades["trackedCoinPairs"])
        pause_trade_len = len(self.Database.app_data["pausedTrackedCoinPairs"])
        if (trade_len < 1 or pause_trade_len == trade_len) and trade_len < self.trade_params["buy"]["maxOpenTrades"]:
            for coin_pair in self.Database.app_data["coinPairs"]:
                self.buy_strategy(coin_pair)

    def analyse_sells(self):
        """
        Analyse all the un-paused tracked coin pairs for sell signals and apply sells
        """
        for coin_pair in self.Database.trades["trackedCoinPairs"]:
            if coin_pair not in self.Database.app_data["pausedTrackedCoinPairs"]:
                self.sell_strategy(coin_pair)

    def buy_strategy(self, coin_pair):
        """
        Applies the buy checks on the coin pair and handles the results appropriately

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        """
        if (len(self.Database.trades["trackedCoinPairs"]) >= self.trade_params["buy"]["maxOpenTrades"] or
                coin_pair in self.Database.trades["trackedCoinPairs"]):
            return
        rsi = self.calculate_RSI(coin_pair=coin_pair, period=14, unit=self.trade_params["tickerInterval"])
        day_volume = self.get_current_24hr_volume(coin_pair)
        current_buy_price = self.get_current_price(coin_pair, "ask")

        if self.check_buy_parameters(rsi, day_volume, current_buy_price):
            buy_stats = {
                "rsi": rsi,
                "24HrVolume": day_volume
            }
            self.buy(coin_pair, self.trade_params["buy"]["btcAmount"], current_buy_price, buy_stats)
        elif rsi is not None and rsi <= self.pause_params["buy"]["rsiThreshold"]:
            self.Messenger.print_no_buy(coin_pair, rsi, day_volume, current_buy_price)
        elif rsi is not None:
            self.Messenger.print_pause(coin_pair, rsi, self.pause_params["buy"]["pauseTime"], "buy")
            self.Database.pause_buy(coin_pair)

    def sell_strategy(self, coin_pair):
        """
        Applies the sell checks on the coin pair and handles the results appropriately

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        """
        if (coin_pair in self.Database.app_data["pausedTrackedCoinPairs"] or
                coin_pair not in self.Database.trades["trackedCoinPairs"]):
            return
        rsi = self.calculate_RSI(coin_pair=coin_pair, period=14, unit=self.trade_params["tickerInterval"])
        current_sell_price = self.get_current_price(coin_pair, "bid")
        profit_margin = self.Database.get_profit_margin(coin_pair, current_sell_price)

        if self.check_sell_parameters(rsi, profit_margin):
            sell_stats = {
                "rsi": rsi,
                "profitMargin": profit_margin
            }
            self.sell(coin_pair, current_sell_price, sell_stats)
        elif rsi is not None and profit_margin >= self.pause_params["sell"]["profitMarginThreshold"]:
            self.Messenger.print_no_sell(coin_pair, rsi, profit_margin, current_sell_price)
        elif rsi is not None:
            self.Messenger.print_pause(coin_pair, profit_margin, self.pause_params["sell"]["pauseTime"], "sell")
            self.Database.pause_sell(coin_pair)

    def check_buy_parameters(self, rsi, day_volume, current_buy_price):
        """
        Used to check if the buy conditions have been met

        :param rsi: The coin pair's current RSI
        :type rsi: float
        :param day_volume: The coin pair's current 24 hour volume
        :type day_volume: float
        :param current_buy_price: The coin pair's current price
        :type current_buy_price: float

        :return: Boolean indicating if the buy conditions have been met
        :rtype : bool
        """
        return (rsi is not None and rsi <= self.trade_params["buy"]["rsiThreshold"] and
                day_volume >= self.trade_params["buy"]["24HourVolumeThreshold"] and
                current_buy_price > self.trade_params["buy"]["minimumUnitPrice"])

    def check_sell_parameters(self, rsi, profit_margin):
        """
        Used to check if the sell conditions have been met

        :param rsi: The coin pair's current RSI
        :type rsi: float
        :param profit_margin: The coin pair's current profit margin
        :type profit_margin: float

        :return: Boolean indicating if the sell conditions have been met
        :rtype : bool
        """
        return ((rsi is not None and rsi >= self.trade_params["sell"]["rsiThreshold"] and
                 profit_margin > self.trade_params["sell"]["minProfitMarginThreshold"]) or
                profit_margin > self.trade_params["sell"]["profitMarginThreshold"])

    def buy(self, coin_pair, btc_quantity, price, stats, trade_time_limit=2):
        """
        Used to place a buy order to Bittrex. Wait until the order is completed.
        If the order is not filled within trade_time_limit minutes cancel it.

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param btc_quantity: The amount of BTC to buy with
        :type btc_quantity: float
        :param price: The price at which to buy
        :type price: float
        :param stats: The buy stats object
        :type stats: dict
        :param trade_time_limit: The time in minutes to wait fot the order before cancelling it
        :type trade_time_limit: float
        """
        buy_data = self.Bittrex.buy_limit(coin_pair, btc_quantity / price, price)
        if not buy_data["success"]:
            return logger.error("Failed to buy on {} market.".format(coin_pair))
        self.Database.store_initial_buy(coin_pair, buy_data["result"]["uuid"])

        buy_order_data = self.get_order(buy_data["result"]["uuid"], trade_time_limit * 60)
        self.Database.store_buy(buy_order_data["result"], stats)

        self.Messenger.print_buy(coin_pair, price, stats["rsi"], stats["24HrVolume"])
        self.Messenger.send_buy_slack(coin_pair, stats["rsi"], stats["24HrVolume"])
        self.Messenger.send_buy_gmail(buy_order_data["result"], stats)
        self.Messenger.play_sw_imperial_march()

    def sell(self, coin_pair, price, stats, trade_time_limit=2):
        """
        Used to place a sell order to Bittrex. Wait until the order is completed.
        If the order is not filled within trade_time_limit minutes cancel it.

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param price: The price at which to buy
        :type price: float
        :param stats: The buy stats object
        :type stats: dict
        :param trade_time_limit: The time in minutes to wait fot the order before cancelling it
        :type trade_time_limit: float
        """
        trade = self.Database.get_open_trade(coin_pair)
        sell_data = self.Bittrex.sell_limit(coin_pair, trade["quantity"], price)
        if not sell_data["success"]:
            return logger.error(
                "Failed to sell on {} market. Bittrex error message: {}".format(coin_pair, sell_data["message"])
            )

        sell_order_data = self.get_order(sell_data["result"]["uuid"], trade_time_limit * 60)
        # TODO: Handle partial/incomplete sales.
        self.Database.store_sell(sell_order_data["result"], stats)

        self.Messenger.print_sell(coin_pair, price, stats["rsi"], stats["profitMargin"])
        self.Messenger.send_sell_slack(coin_pair, stats["rsi"], stats["profitMargin"])
        self.Messenger.send_sell_gmail(sell_order_data["result"], stats)
        self.Messenger.play_sw_theme()

    def get_markets(self, main_market_filter=None):
        """
        Gets all the Bittrex markets and filters them based on the main market filter

        :param main_market_filter: Main market to filter on (ex: BTC, ETH, USDT)
        :type main_market_filter: str

        :return: All Bittrex markets (with filter applied, if any)
        :rtype : list
        """
        markets = self.Bittrex.get_markets()
        if not markets["success"]:
            logger.error("Failed to fetch Bittrex markets")
            exit()

        markets = markets["result"]
        if main_market_filter is not None:
            market_check = main_market_filter + "-"
            markets = py_.filter_(markets, lambda market: market_check in market["MarketName"])
        markets = py_.map_(markets, lambda market: market["MarketName"])
        return markets

    def get_current_price(self, coin_pair, price_type):
        """
        Gets current market price for a coin pair

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str
        :param price_type: The type of price to get (one of: 'ask', 'bid')
        :type price_type: str

        :return: Coin pair's current market price
        :rtype : float
        """
        coin_summary = self.Bittrex.get_market_summary(coin_pair)
        if not coin_summary["success"]:
            logger.error("Failed to fetch Bittrex market summary for the {} market".format(coin_pair))
            return None
        if price_type == "ask":
            return coin_summary["result"][0]["Ask"]
        if price_type == "bid":
            return coin_summary["result"][0]["Bid"]
        return coin_summary["result"][0]["Last"]

    def get_current_24hr_volume(self, coin_pair):
        """
        Gets current 24 hour market volume for a coin pair

        :param coin_pair: Coin pair market to check (ex: BTC-ETH, BTC-FCT)
        :type coin_pair: str

        :return: Coin pair's current 24 hour market volume
        :rtype : float
        """
        coin_summary = self.Bittrex.get_market_summary(coin_pair)
        if not coin_summary["success"]:
            logger.error("Failed to fetch Bittrex market summary for the {} market".format(coin_pair))
            return None
        return coin_summary["result"][0]["BaseVolume"]

    def get_closing_prices(self, coin_pair, period, unit):
        """
        Returns closing prices within a specified time frame for a coin pair

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param period: Number of periods to query
        :type period: int
        :param unit: Ticker interval (one of: 'oneMin', 'fiveMin', 'thirtyMin', 'hour', 'week', 'day', and 'month')
        :type unit: str

        :return: Array of closing prices
        :rtype : list
        """
        historical_data = self.Bittrex.get_historical_data(coin_pair, period, unit)
        closing_prices = []
        for i in historical_data:
            closing_prices.append(i["C"])
        return closing_prices

    def get_order(self, order_uuid, trade_time_limit):
        """
        Used to get an order from Bittrex by it's UUID.
        First wait until the order is completed before retrieving it.
        If the order is not completed within trade_time_limit seconds, cancel it.

        :param order_uuid: The order's UUID
        :type order_uuid: str
        :param trade_time_limit: The time in seconds to wait fot the order before cancelling it
        :type trade_time_limit: float

        :return: Order object
        :rtype : dict
        """
        start_time = time.time()
        order_data = self.Bittrex.get_order(order_uuid)
        while time.time() - start_time <= trade_time_limit and order_data["result"]["IsOpen"]:
            time.sleep(10)
            order_data = self.Bittrex.get_order(order_uuid)

        if order_data["result"]["IsOpen"]:
            error_str = self.Messenger.print_order_error(order_uuid, trade_time_limit, order_data["result"]["Exchange"])
            logger.error(error_str)
            if order_data["result"]["Type"] == "LIMIT_BUY":
                self.Bittrex.cancel(order_uuid)
            return order_data

        return order_data

    def calculate_RSI(self, coin_pair, period, unit):
        """
        Calculates the Relative Strength Index for a coin_pair
        If the returned value is above 75, it's overbought (SELL IT!)
        If the returned value is below 25, it's oversold (BUY IT!)

        :param coin_pair: String literal for the market (ex: BTC-LTC)
        :type coin_pair: str
        :param period: Number of periods to query
        :type period: int
        :param unit: Ticker interval (one of: 'oneMin', 'fiveMin', 'thirtyMin', 'hour', 'week', 'day', and 'month')
        :type unit: str

        :return: RSI
        :rtype : float
        """
        closing_prices = self.get_closing_prices(coin_pair, period * 3, unit)
        count = 0
        change = []
        # Calculating price changes
        for i in closing_prices:
            if count != 0:
                change.append(i - closing_prices[count - 1])
            count += 1
            if count == 15:
                break
        # Calculating gains and losses
        advances = []
        declines = []
        for i in change:
            if i > 0:
                advances.append(i)
            if i < 0:
                declines.append(abs(i))
        average_gain = (sum(advances) / 14)
        average_loss = (sum(declines) / 14)
        new_avg_gain = average_gain
        new_avg_loss = average_loss
        for _ in closing_prices:
            if 14 < count < len(closing_prices):
                close = closing_prices[count]
                new_change = close - closing_prices[count - 1]
                add_loss = 0
                add_gain = 0
                if new_change > 0:
                    add_gain = new_change
                if new_change < 0:
                    add_loss = abs(new_change)
                new_avg_gain = (new_avg_gain * 13 + add_gain) / 14
                new_avg_loss = (new_avg_loss * 13 + add_loss) / 14
                count += 1

        if new_avg_loss == 0:
            return None

        rs = new_avg_gain / new_avg_loss
        new_rs = 100 - 100 / (1 + rs)
        return new_rs
예제 #9
0
class CapitVitaCrypto(CapitVita):
    def __init__(self,
                 home_path='',
                 num_coins=25,
                 mailing_list=[],
                 debug=False):

        self.num_coins = num_coins
        self.mailing_list = mailing_list
        self.coin_list = []
        self.df = []
        self.debug = debug
        self.home_path = home_path
        self.file_path = home_path + 'crypto-data/'
        self.volume_sum = []

        # bittrex
        self.B = Bittrex(key, secret)
        self.b_currencies = [
            x['Currency'] for x in self.B.get_currencies()['result']
        ]  # currencies available to trade in bittrex
        self.market_summaries = self.B.get_market_summaries()['result']
        self.markets = [x['MarketName']
                        for x in self.market_summaries]  # market names
        self.BTC_markets = [
            x for x in self.markets if 'BTC' in x and 'USDT' not in x
        ]
        self.ETH_markets = [
            x for x in self.markets if 'ETH' in x and 'USDT' not in x
        ]
        self.USDT_markets = [x for x in self.markets if 'USDT' in x]
        self.USDT_BTC = [
            x for x in self.market_summaries if x['MarketName'] == 'USDT-BTC'
        ][-1]['Last']
        self.USDT_ETH = [
            x for x in self.market_summaries if x['MarketName'] == 'USDT-ETH'
        ][-1]['Last']

    def get_coin_list(self):
        # get coin list (all coins, some are not tradeable on bittrex)

        url = 'https://www.cryptocompare.com/api/data/coinlist/'
        response = urllib2.urlopen(url)
        data = json.loads(response.read())
        self.coin_list = [
            x.encode('ascii', 'ignore') for x in data['Data'].keys()
        ]
        #print(len(self.coin_list))   # 1507 as of 2017-09-14

    def grab_data(self, coin):
        # get historical OHLC for one cryptocurrency

        url = 'https://min-api.cryptocompare.com/data/histoday?fsym={}&tsym=USD&limit={}&aggregate=1&e=CCCAGG'.format(
            coin, 80)
        response = urllib2.urlopen(url)
        data = json.loads(response.read())

        try:
            self.df = pd.DataFrame(data['Data'])
            self.df['date'] = self.df['time'].apply(
                lambda x: datetime.datetime.fromtimestamp(x))
            #self.df.drop(['time', 'volumefrom'], axis = 1)
            #self.df.columns = ['Adj. Close', 'Adj. High', 'Adj. Low', 'Adj. Open', 'time', 'volumefrom', 'volumeto', 'date']
        except KeyError:
            return False

        self.volume_sum.append(self.df['volumeto'].iloc[-20:].median())

        # generate signals
        self.df['rsi'] = self.RSI(self.df['close'], 14)
        self.df['26 ema'] = self.df['close'].ewm(ignore_na=False,
                                                 min_periods=0,
                                                 adjust=True,
                                                 com=26).mean()
        self.df['12 ema'] = self.df['close'].ewm(ignore_na=False,
                                                 min_periods=0,
                                                 adjust=True,
                                                 com=12).mean()
        self.df['MACD'] = self.df['12 ema'] - self.df['26 ema']
        self.df['MACD signal'] = self.df['MACD'] - self.df['MACD'].ewm(
            ignore_na=False, min_periods=0, adjust=True, com=9).mean()
        self.df['MACD_norm'] = self.normalize(self.df['MACD signal'])
        self.df['MACD_der'] = self.derivative(self.df['MACD_norm'])

    def get_points(self, coin):

        try:

            self.grab_data(coin)  ## get the data and store it in self.df

            if len(self.df) < 20 or self.df['volumeto'].iloc[-20:].median(
            ) < 850000 * 0.8:  # if grab is unsuccessful or below average volume * 0.7, end
                points = {'admin': -500}

            else:
                points = {}

                mb, tb, bb, = self.bbands(self.df['close'])
                if self.df['close'].iloc[-1] < (mb.iloc[-1] + bb.iloc[-1]) / 2:
                    points['admin'] = -500

                # RSI points (max 50)
                points['rsi'] = 50 - round(
                    1.2 * abs(30 - self.df['rsi'].iloc[-1]))

                # MACD points (max 50)
                points['macd1'] = round(
                    25 * self.df['MACD_norm'].iloc[-1] /
                    max([abs(x) for x in self.df['MACD_norm']]))
                points['macd2'] = round(
                    25 * self.df['MACD_der'].iloc[-1] /
                    max([abs(x) for x in self.df['MACD_der']]))

                # candlestick points (max 10)
                candlestickFactor = 1

                patterns = self.detectCandlestickPatterns(
                    self.df['open'][-7:], self.df['close'][-7:],
                    self.df['low'][-7:], self.df['high'][-7:],
                    candlestickFactor)
                points['candlesticks'] = self.rangeLimit(
                    round(sum([x[2] for x in patterns])), -20, 20)

        except BufferError as e:
            #except Exception as e:
            print('problem: {}'.format(e))

        return points

    def find_coins(self, graph=False, bittrex_currencies_only=True):
        # start counting duration of script
        start_time = time.time()

        print('Initiating log...')
        # create log
        ff = open(self.file_path + 'readme.txt', 'w')
        ff.write(str(datetime.datetime.now()))
        ff.write('\n')

        print('Deleting old plots...')
        # delete old files
        os.chdir(self.file_path)
        filelist = glob.glob('*.png')
        for f in filelist:
            os.remove(f)
        os.chdir(self.home_path)

        print('Fetching coin list...')
        if bittrex_currencies_only:
            self.update_B()
            self.coin_list = self.b_currencies
        else:
            self.get_coin_list()
            if self.debug:
                self.coin_list = self.coin_list[:30]

        len_coin_list = len(self.coin_list)
        print('  {} coins.'.format(len_coin_list))
        #print('  Expect script to take approximately {} minutes'.format(round(len_coin_list*1.0613 - 14)/60, 2))

        # grab data in batches
        print('Getting points for {} coins...'.format(len_coin_list))
        coin_points = {}
        for i, coin in enumerate(self.coin_list):
            if i % (len(self.coin_list) / 25) == 0:
                print('{}% done'.format(
                    round(100 * float(i) / len(self.coin_list), 1)))
            try:
                points = self.get_points(coin)
                coin_points[coin] = [sum([points[x] for x in points]), points]
            #except BufferError:
            except Exception as e:
                print('failed {} because {}'.format(coin, e))
        original_len_coin_list = len(coin_points)

        print('Sorting coins...')
        # sort stocks by point system
        sorted_coins = sorted(coin_points.items(),
                              key=itemgetter(1),
                              reverse=True)[:self.num_coins]

        print(sorted_coins)

        if graph:
            print('Graphing coins...')
            for coin in [x[0] for x in sorted_coins]:
                try:
                    self.graph_data(coin, saveLocation=self.file_path)
                except BufferError:
                    #except Exception as e:
                    print('failed {} because {}'.format(coin, e))

        # write into log
        ff.write('Cheap coins to invest in for 2 days ~ 1 week: \n\n')

        ff.write('#\n')
        for i in sorted_coins:
            ff.write(i[0] + ': ' + str(round(i[1][0], 1)) + '  ' +
                     str(i[1][1]) + '\n')
        ff.write('#\n')

        ff.write('\n\n  ' + str(original_len_coin_list) +
                 ' stocks shortened by point system to ' +
                 str(len(sorted_coins)) + ' stocks')

        ff.write("\n\n--- %s seconds ---" %
                 (round(time.time() - start_time, 2)))

        ff.write('\n\n\n  Capit-Vita Crypto Version 1.1  (2017-09-22)\n\n')
        ff.write('  - Buying is confirmed to work\n')
        ff.close()

        #print(self.volume_sum[-20:])
        #print('average volume', sum(self.volume_sum)/len(self.volume_sum))
        # median volumeto: 850k

        # send email
        if len(self.mailing_list) > 0:
            send_email(self.file_path,
                       'Top ' + str(self.num_coins) + ' Coin Prospects',
                       self.mailing_list)

        ###### remove coin types I currently own
        my_coins = [x['Currency'] for x in self.B.get_balances()['result']]
        print('my coins: {}'.format(my_coins))
        print('before: {}'.format([x[0] for x in sorted_coins]))
        sorted_coins = [x for x in sorted_coins if x[0] not in my_coins]
        print('after: {}'.format([x[0] for x in sorted_coins]))

        # save wanted coins
        with open(self.file_path + 'wanted_coins.txt', 'w') as f:
            f.write('{}, '.format([str(x[0]) for x in sorted_coins]))

        return sorted_coins

    def buy_next_coin(self):

        # save wanted_coins
        if os.path.isfile(self.file_path + 'wanted_coins.txt'):
            with open(self.file_path + 'wanted_coins.txt', 'r') as f:
                data = eval(f.readlines()[0][:-2])
        else:
            return False

        print(data)

    def update_B(self):

        self.b_currencies = [
            x['Currency'] for x in self.B.get_currencies()['result']
        ]  # currencies available to trade in bittrex
        self.market_summaries = self.B.get_market_summaries()['result']
        self.markets = [x['MarketName']
                        for x in self.market_summaries]  # market names
        self.BTC_markets = [
            x for x in self.markets if 'BTC' in x and 'USDT' not in x
        ]
        self.ETH_markets = [
            x for x in self.markets if 'ETH' in x and 'USDT' not in x
        ]
        self.USDT_markets = [x for x in self.markets if 'USDT' in x]
        self.USDT_BTC = [
            x for x in self.market_summaries if x['MarketName'] == 'USDT-BTC'
        ][-1]['Last']
        self.USDT_ETH = [
            x for x in self.market_summaries if x['MarketName'] == 'USDT-ETH'
        ][-1]['Last']
        #print len(self.b_currencies) # 277 as of 2017-09-21

    def thing(self):

        BTC_market_prices = []
        ETH_market_prices = []
        ### create value exchange rate
        for currency in self.b_currencies:
            if any(currency in x for x in BTC_markets):
                last_price = [
                    x['Last'] for x in self.market_summaries
                    if x['MarketName'] == 'BTC-{}'.format(currency)
                ]
                if len(last_price) > 0:
                    BTC_market_prices.append('Last price for {} is ${}'.format(
                        currency, round(last_price[0] * USDT_BTC, 2)))
            elif any(currency in x for x in ETH_markets):
                last_price = [
                    x['Last'] for x in self.market_summaries
                    if x['MarketName'] == 'ETH-{}'.format(currency)
                ]
                if len(last_price) > 0:
                    ETH_market_prices.append('Last price for {} is ${}'.format(
                        currency, round(last_price[0] * USDT_ETH, 2)))

        cnt_in = 0
        cnt_not_in = 0
        for currency in self.b_currencies:
            if all(currency not in x
                   for x in self.BTC_markets + self.ETH_markets):
                cnt_not_in += 1
                #print('{} not in any market'.format(currency))
            else:
                cnt_in += 1

        #print(cnt_in, cnt_not_in) #203 in market, 74 out of market as of 2017-09-21

        ### can only buy and sell on existing markets

    def my_coins(self):

        my_coins = [x for x in self.B.get_balances()['result']]
        print(my_coins)
        total = 0
        print('\n\n-----------  My Wallet -----------\n')
        for coin in my_coins:
            if coin['Currency'] == 'BTC':
                print('{} available for {} (${})'.format(
                    coin['Available'], coin['Currency'],
                    round(coin['Available'] * self.USDT_BTC, 2)))
                total += coin['Available'] * self.USDT_BTC
            elif any(coin['Currency'] in x for x in self.BTC_markets):
                BTC_coin_rate = [
                    x['Last'] for x in self.market_summaries
                    if x['MarketName'] == 'BTC-{}'.format(coin['Currency'])
                ][0]
                print('{} available for {} (${})'.format(
                    coin['Available'], coin['Currency'],
                    round(coin['Available'] * self.USDT_BTC * BTC_coin_rate,
                          2)))
                total += coin['Available'] * self.USDT_BTC * BTC_coin_rate
            else:
                print('{} available for {} (${})'.format(
                    coin['Available'], coin['Currency'],
                    'hold'))  ## add ethereum
        #return summary
        return my_coins

    def total_available_USD(self, BTC_ETH_only=True):

        balances = self.B.get_balances()['result']
        total_USD = 0

        for balance in balances:
            if balance['Balance'] > 0:
                if balance['Currency'] == 'BTC':
                    total_USD += balance['Balance'] * self.USDT_BTC
                    print('BTC: {}'.format(balance['Balance'] * self.USDT_BTC))
                elif balance['Currency'] == 'ETH':
                    total_USD += balance['Balance'] * self.USDT_ETH
                    print('ETH: {}'.format(balance['Balance'] * self.USDT_ETH))
                elif not BTC_ETH_only:
                    if any(balance['Currency'] in x for x in self.BTC_markets):
                        to_add = balance['Balance'] * [
                            x['Last']
                            for x in self.market_summaries if x['MarketName']
                            == 'BTC-{}'.format(balance['Currency'])
                        ][0] * self.USDT_BTC
                        total_USD += to_add
                        print('{}: {}'.format(balance['Currency'], to_add))
                    elif any(balance['Currency'] in x
                             for x in self.ETH_markets):
                        to_add = balance['Balance'] * [
                            x['Last']
                            for x in self.market_summaries if x['MarketName']
                            == 'ETH-{}'.format(balance['Currency'])
                        ][0] * self.USDT_ETH
                        total_USD += to_add
                        print('{}: {}'.format(balance['Currency'], to_add))
                # consider only BTC and ETH liquid?

        print('Total available: {}'.format(total_USD))

        return total_USD

    def buy_altcoin(self, coin):

        if any(coin in x['Currency'] for x in self.B.get_balances()['result']):
            print('not buying, already have')
            return False

        if any(coin in x for x in self.BTC_markets):

            market = [x for x in self.BTC_markets if coin in x][0]
            print(market)

            available_USD = self.total_available_USD()
            print('available USD', available_USD)

            increment_USD = available_USD / 20
            print('5% available USD: {}'.format(increment_USD))

            BTC_coin_rate = self.B.get_marketsummary(
                market)['result'][0]['Last']
            print('BTC - {} conversion: {}'.format(coin, BTC_coin_rate))

            print('BTC - USD conversion: {}'.format(self.USDT_BTC))

            print('want to buy {} {} coins'.format(
                increment_USD / self.USDT_BTC / BTC_coin_rate, coin))

            print('buying {}: {}'.format(
                coin,
                self.B.buy_limit(market,
                                 increment_USD / self.USDT_BTC / BTC_coin_rate,
                                 BTC_coin_rate)))  # market, quantity, rate

    def sell_altcoin(self, order):
        # takes a buy order and reverses it (sell)

        coin = order['Exchange'][4:]
        if any(coin in x for x in self.BTC_markets):
            market = [x for x in self.BTC_markets if coin in x][0]
        elif any(coin in x for x in self.ETH_markets):
            market = [x for x in self.ETH_markets if coin in x][0]
        coin_rate = self.B.get_marketsummary(market)['result'][0]['Last']
        quantity = order['Quantity']

        if all(coin not in x['Currency']
               for x in self.B.get_balances()['result']):
            print('cannot sell, do not have')
            return False

        #print('selling {}: {}'.format(market, self.B.sell_limit(market, quantity, coin_rate)))    # market, quantity, rate

    def coin_to_USD(self, order):

        coin = order['Exchange'][4:]

        market = [x for x in self.BTC_markets if coin in x][0]
        BTC_coin_rate = self.B.get_marketsummary(market)['result'][0]['Last']

        if coin == 'BTC':
            return order['Quantity'] * self.USDT_BTC
        elif coin == 'ETH':
            pass
        elif any([coin in x for x in self.BTC_markets]):
            last_price = [
                x['Last'] for x in self.market_summaries
                if coin in x['MarketName']
            ]
            return order['Quantity'] * self.USDT_BTC * BTC_coin_rate
        elif any(coin in x for x in self.ETH_markets):
            pass
        else:
            pass

    def my_coin_price_change(self):

        orders = self.B.get_order_history()['result']

        ## remove orders that I don't own
        orders = [x for x in orders]

        print(orders)

        self.update_B()

        for order in orders:
            bought_at = round(
                order['Quantity'] * order['PricePerUnit'] * self.USDT_BTC, 2)
            currently = round(self.coin_to_USD(order), 2)
            perc_change = round((currently / bought_at - 1) * 100, 1)
            timestamp = datetime.datetime.now() - datetime.datetime.strptime(
                order['TimeStamp'], '%Y-%m-%dT%H:%M:%S.%f')
            print(
                '   bought {} ({} ago) for relative BTC value of ${}, currently ${}: {}% change'
                .format(order['Exchange'][4:], timestamp, bought_at, currently,
                        perc_change))

            ### formula for selling:
            # cost of trade = 0.35% x 2 = 0.7%
            # have an open sell order at 10% -> 9.3% up
            # if simulataneous orders are possible, have an open sell order at -10% -> 10.7% down
            # if the coin is older than 5 days, lower the upper sell limit by 2% to 8% -> 7.3% up
            # every 3 days after that lower by 2% until @ 2%

            lower_limit = -10
            if timestamp < datetime.timedelta(days=5):
                upper_limit = 10
            elif timestamp < datetime.timedelta(days=8):  # approx one week
                upper_limit = 8
            elif timestamp < datetime.timedelta(days=11):
                upper_limit = 6
            elif timestamp < datetime.timedelta(days=14):  # two weeks
                upper_limit = 4
            elif timestamp < datetime.timedelta(days=17):
                upper_limit = 2
            elif timestamp > datetime.timedelta(
                    days=21):  # sell no matter what after 3 weeks
                upper_limit = -10

            if perc_change < lower_limit or perc_change > upper_limit:
                self.sell_altcoin(order)
예제 #10
0
class CryptoCommander:
    def __init__(self, poloapicreds=['', ''], bittrexapicreds=['', '']):
        print(
            "Initializing Crypto Commander, Intelligent and Responsive Crypto-Currency Platform..."
        )
        print(
            "Disclaimer!! You have launched this via command line, great caution is advised and the developers are NOT responsible for proper usage or lost coins!"
        )
        print(
            "Notice - :: :: Bitcoin & Crypto-Currencies are largely untested and come with no assurances! Trade with care. :: ::"
        )
        if poloapicreds == ['', '']:
            print(
                "No poloniex credentials found, skipping initialization. This may cause instability!"
            )
        else:
            try:
                self.poloniexBot = poloniex(poloapicreds[0], poloapicreds[1])
                self.btcBalance, self.btsBalance, self.clamBalance, self.dashBalance, self.dogeBalance, self.ethBalance, self.fctBalance, self.ltcBalance, self.maidBalance, self.strBalance, self.xmrBalance, self.xrpBalance, = Decimal(
                    0.0), Decimal(0.0), Decimal(0.0), Decimal(0.0), Decimal(
                        0.0), Decimal(0.0), Decimal(0.0), Decimal(
                            0.0), Decimal(0.0), Decimal(0.0), Decimal(
                                0.0), Decimal(0.0)
            except AttributeError:
                print(
                    "An error occurred trying to initialize Poloniex functionality."
                )
        if bittrexapicreds == ['', '']:
            print(
                "No bittrex credentials detected, skipping initialization. This may cause instability!"
            )
        else:
            try:
                self.bittrexBot = Bittrex(bittrexapicreds[0],
                                          bittrexapicreds[1])
            except AttributeError:
                print(
                    "An error occurred trying to initialized Bittrex functionality."
                )

    def convert_coinpair_poloniex(self, coinpair):
        return coinpair.replace('-', '_')

    def get_tickers_raw(self, market):
        # A clone of the bittrex get_markets() & poloniex returnTicker commands, in a unified stream.
        if market == 'poloniex':
            return self.poloniexBot.returnTicker()
        elif market == 'bittrex':
            return self.bittrexBot.get_markets()

    def get_coinpair_ticker_raw(self, market, coinpair):
        # Returns raw market information on coin pair  on market
        if market == 'poloniex':
            coinpair = self.convert_coinpair_poloniex(coinpair)
            rawtickerdata = self.get_tickers_raw(market)
            for coinpairdata in rawtickerdata:
                if coinpairdata == coinpair:
                    return rawtickerdata[coinpairdata]
        if market == 'bittrex':
            return self.bittrexBot.get_ticker(coinpair.capitalize())

    def getTickerData(self,
                      market,
                      bitcoinMarketsOnly=True,
                      activeOnly=True,
                      printFriendly=False,
                      decimalTypes=True):
        #if market == 'poloniex:

        if market == 'bittrex':
            cryptoCommandTickers = {'BTC': [], 'Other': []}
            btcMarketsList = cryptoCommandTickers['BTC']
            otherMarketsList = cryptoCommandTickers['Other']
            stagingList = []
            if printFriendly == True:
                decimalTypes = False
            for ticker in self.bittrexBot.get_markets()['result']:
                if ticker != None:
                    stagingList.append([
                        str(ticker['MarketName']),
                        str(ticker['BaseCurrency']),
                        bool(str(ticker['IsActive']))
                    ])
            for ticker in self.bittrexBot.get_market_summaries()['result']:
                if ticker != None:
                    for list in stagingList:
                        if list[0] == str(ticker['MarketName']):
                            list.extend([
                                ticker['High'], ticker['Low'], ticker['Ask'],
                                ticker['Bid'], ticker['Last'],
                                ticker['PrevDay'], ticker['Volume'],
                                ticker['BaseVolume'],
                                (ticker['High'] + ticker['Low'] / 2.0)
                            ])
            for list in stagingList:
                if list[1] == 'BTC':
                    btcMarketsList.append(list)
                else:
                    otherMarketsList.append(list)
            if printFriendly == True:
                for dictobject in cryptoCommandTickers:
                    for list in cryptoCommandTickers[dictobject]:
                        for n, listobject in enumerate(list):
                            if type(listobject) == float:
                                list[n] = format(listobject, '.8f')
            elif decimalTypes == True:
                for dictobject in cryptoCommandTickers:
                    for list in cryptoCommandTickers[dictobject]:
                        for n, listobject in enumerate(list):
                            if type(listobject) == float:
                                list[n] = Decimal(format(listobject, '.8f'))
            return cryptoCommandTickers

    def getActiveMarketCurrencies(self, market, appendString=''):
        currentMarketList = []
        if market == 'poloniex':
            rawCoinPairData = self.poloniexBot.api_query('returnTicker')
            for coinPairData in rawCoinPairData:
                if str(rawCoinPairData[coinPairData]['isFrozen']) == '0':
                    currentMarketList.append(
                        str(coinPairData).split('_', 1)[1])
        if market == 'bittrex':
            for coinData in self.bittrexBot.get_currencies()['result']:
                if coinData['IsActive'] == True:
                    currentMarketList.append(appendString +
                                             str(coinData['Currency']))
        return set(currentMarketList)

    def getCurrentBalance(self, market, coin):
        if market == 'poloniex':
            return self.poloniexBot.returnBalances()[coin.upper()]
        elif market == 'bittrex':
            return self.bittrexBot.get_balance(coin)['result']['Balance']

    def getTopOrder(self, market, coinPair, buyOrders):
        if buyOrders == True:
            if market == 'poloniex':
                for i in self.poloniexBot.returnOrderBook(
                        coinPair.replace('-', '_'))['bids']:
                    return i
            elif market == 'bittrex':
                for i in self.bittrexBot.get_orderbook(coinPair,
                                                       'buy')['result']:
                    return i
            else:
                print('Not a valid market: ' + str(market))
        else:
            if market == 'poloniex':
                for i in self.poloniexBot.returnOrderBook(
                        coinPair.replace('-', '_'))['asks']:
                    return i
            elif market == 'bittrex':
                for i in self.bittrexBot.get_orderbook(coinPair,
                                                       'sell')['results']:
                    return i
            else:
                print('Not a valid market: ' + str(market))

    def getWalletAddress(self, market, coin):
        if market == "poloniex" or market == "Poloniex":
            return self.poloniexBot.api_query('returnDepositAddresses')[coin]
        elif market == "bittrex" or market == "Bittrex":
            return self.bittrexBot.get_balance(coin)['result']['CryptoAddress']

    def compareMarkets(self, market1, market2):
        currentActiveMarketsLists = [
            self.getActiveMarketCurrencies(market1),
            self.getActiveMarketCurrencies(market2)
        ]
        comparisonList = []
        for i in currentActiveMarketsLists[0]:
            for y in currentActiveMarketsLists[1]:
                if i == y: comparisonList.append(i)
                else: continue
        return comparisonList

    def getCoinPairPriceDifferencePercent(self, buyPrice, sellPrice):
        return (((float(buyPrice) - float(sellPrice)) / float(buyPrice)) *
                100.00)

    def arbitrageScan(self, market1, market2, minPercent=0.45):
        try:
            arbOpportunitiesList = []
            for coinpair in self.doMarketComparison(market1, market2):
                print("Scanning Coin Pair : " + str(coinpair))
                differenceBetweenMarket1and2 = format(
                    self.getCoinPairPriceDifferencePercent(
                        float(self.getTopOrder(market1, coinpair, False, 1)),
                        float(self.getTopOrder(market2, coinpair, True, 1))))
                differenceBetweenMarket2and1 = format(
                    self.getCoinPairPriceDifferencePercent(
                        float(self.getTopOrder(market2, coinpair, False, 1)),
                        float(self.getTopOrder(market1, coinpair, True, 1))))
                if float(differenceBetweenMarket2and1) < (-.525 - minPercent):
                    if (float(self.getTopOrder(market1, coinpair, True)[0]) *
                            float(
                                self.getTopOrder(market1, coinpair, True)[1])
                        ) >= float(self.getCurrentBalance(market1, "BTC")):
                        print("Arb Op: " + str(differenceBetweenMarket2and1) +
                              " for coin pair ")
                        print("Info: Bittrex: Buy:: ")
                        print(self.getTopOrder('bittrex', coinpair, True))
                        print("- Sell:: ")
                        print(self.getTopOrder('bittrex', coinpair, False))
                        arbOpportunity = (coinpair, "Market2to1",
                                          differenceBetweenMarket2and1, 1)
                        arbOpportunitiesList.append(arbOpportunity)
                    else:
                        continue
                elif float(differenceBetweenMarket1and2) < (-.525 -
                                                            minPercent):
                    if float(
                            self.getTopOrder('bittrex', coinpair, True, 3)[0]
                    ) * float(self.getTopOrder(
                            'bittrex', coinpair, True)[1]) >= float(
                                self.getCurrentBalance(market2, "BTC")):
                        print("Arb Op: ")
                        print(str(differenceBetweenMarket1and2))
                        print("Info: Bittrex: Buy:: ")
                        print(self.getTopOrder('poloniex', coinpair, True))
                        print("- Sell:: ")
                        print(self.getTopOrder('poloniex', coinpair, False))
                        print("Info: Poloniex: Buy:: ")
                        print(self.getTopOrder('bittrex', coinpair, True))
                        print("- Sell:: ")
                        print(self.getTopOrder('bittrex', coinpair, False))
                        arbOpportunity = (coinpair, "Market1to2",
                                          differenceBetweenMarket1and2, 1)
                        arbOpportunitiesList.append(arbOpportunity)
                    else:
                        continue
                else:
                    print(differenceBetweenMarket1and2 + " or " +
                          differenceBetweenMarket2and1 + " is more than -.7")
                    continue
            return arbOpportunitiesList
        except AttributeError:
            print("Attribute Error")

    def selectBestOpportunity(self, market1, market2, minPercent=0.45):
        opportunitiesList = []
        while opportunitiesList == []:
            opportunitiesList = self.arbitrageScan(market1, market2,
                                                   minPercent)
        if len(opportunitiesList) != 0:
            bestOpportunity = opportunitiesList[0]
            for opportunity in opportunitiesList:
                if bestOpportunity[2] < opportunity[2]:
                    bestOpportunity = opportunity
        else:
            print("No Opportunities Found")
            bestOpportunity = ("", "", 0.0, 0)
        return bestOpportunity

    def activateArbitrage(self, market1, market2, minPercent=0.45):
        bestArbitrageOpportunity = self.selectBestOpportunity(
            market1, market2, minPercent)
        coinName = str(bestArbitrageOpportunity[0]).replace("BTC-", "")
        if bestArbitrageOpportunity[1] == 'Market1to2':
            fullTopBuyOrder = self.getTopOrder(market1,
                                               bestArbitrageOpportunity[0],
                                               False)
            btcBuyOrderAvailable = (float(fullTopBuyOrder[0]) *
                                    float(fullTopBuyOrder[1]))
            btcBalanceOnMarket = float(
                self.getCurrentBalance('poloniex', "BTC"))
            if float(btcBuyOrderAvailable) > float(btcBalanceOnMarket):
                btcBuyOrderAvailable = float(btcBalanceOnMarket)
            coinAvailable = float(btcBuyOrderAvailable) / float(
                fullTopBuyOrder[0])
            if market1 == "poloniex" or market1 == "Poloniex":
                try:
                    if float(
                            self.getTopOrder(
                                market1, bestArbitrageOpportunity[0], False,
                                0)[0]) * float(
                                    self.getTopOrder(
                                        market1, bestArbitrageOpportunity[0],
                                        False, 0)[1]) < float(
                                            self.getBalance('poloniex',
                                                            'BTC')):
                        self.poloniexBot.buy(
                            bestArbitrageOpportunity[0].replace("-", "_"),
                            fullTopBuyOrder[0], coinAvailable)
                        print(
                            "Successfully Bought on Poloniex, Attempting to Send to Bittrex Now..."
                        )
                        time.sleep(3)
                        self.poloniexBot.withdraw(
                            coinName,
                            (self.getCurrentBalance('poloniex', coinName)),
                            self.getWalletAddress('bittrex', coinName))
                        tempCounter = 0
                        print(self.getCurrentBalance('bittrex', coinName))
                        while float(self.getCurrentBalance(
                                'bittrex', coinName)) < 0.0005:
                            time.sleep(5)
                            tempCounter = tempCounter + 1
                            if tempCounter > 15:
                                print("Still Awaiting Deposit...")
                                tempCounter = 0
                        print(
                            "Deposit Confirmed & Active! Preparing to Dump in 5 Seconds"
                        )
                        time.sleep(5)
                        while float(self.getCurrentBalance(market2, coinName)
                                    ) > 0.00050055 or self.getCurrentBalance(
                                        market2, coinName) == None:
                            time.sleep(3)
                            self.bittrexBot.sell_limit(
                                bestArbitrageOpportunity[0],
                                self.getCurrentBalance('bittrex', coinName),
                                self.getTopOrder(market2,
                                                 bestArbitrageOpportunity[0],
                                                 True, 1))
                        print(
                            "Finished Selling All the Coins that Could be Sold. Cycle Complete."
                        )
                    else:
                        print(
                            "The order didnt stay high enough, starting over")
                        self.activateArbitrage(market1, market2, minPercent)
                except MemoryError:
                    print("Error")
        if bestArbitrageOpportunity[1] == 'Market2to1':
            fullTopBuyOrder = self.getTopOrder(market2,
                                               bestArbitrageOpportunity[0],
                                               False, 0)
            btcBuyOrderAvailable = (float(fullTopBuyOrder[0]) *
                                    float(fullTopBuyOrder[1]))
            btcBalanceOnMarket = float(self.getCurrentBalance(market2, "BTC"))
            if btcBuyOrderAvailable > btcBalanceOnMarket:
                btcBuyOrderAvailable = btcBalanceOnMarket
            coinAvailable = float(btcBuyOrderAvailable) / float(
                fullTopBuyOrder[0])
            if market2 == "bittrex" or market2 == "Bittrex":
                try:
                    if float(
                            self.getTopOrder(
                                market1, bestArbitrageOpportunity[0], False,
                                0)[0]) * float(
                                    self.getTopOrder(
                                        market1, bestArbitrageOpportunity[0],
                                        False, 0)[1]) < float(
                                            self.getCurrentBalance(
                                                'bittrex', 'BTC')):
                        print("Buying " + str(bestArbitrageOpportunity[0]) +
                              " " + str(coinAvailable))
                        buy = self.bittrexBot.buy_limit(
                            bestArbitrageOpportunity[0], coinAvailable,
                            fullTopBuyOrder[0])
                        print(buy)
                        time.sleep(5)
                        if buy['success'] == True:
                            print(
                                "Successfully Bought on Bittrex, Attempting to Send to Poloniex Now..."
                            )
                            time.sleep(5)
                            self.bittrexBot.withdraw(
                                coinName,
                                self.getCurrentBalance(market2, coinName),
                                self.getWalletAddress(market1, coinName))
                            tempCounter = 0
                            print(self.getCurrentBalance(market1, coinName))
                            while float(
                                    self.getCurrentBalance(market1, coinName)
                            ) < 0.00050055 or self.getCurrentBalance(
                                    market1, coinName) == None:
                                time.sleep(5)
                                tempCounter = tempCounter + 1
                                if tempCounter > 15:
                                    print("Still Awaiting Deposit...")
                                    tempCounter = 0
                            print(
                                "Deposit Confirmed and Active! Preparing to Dump in 5 Seconds"
                            )
                            time.sleep(5)
                            while float(
                                    self.getCurrentBalance(
                                        market1, coinName)) > 0.00010055:
                                time.sleep(5)
                                self.poloniexBot.sell(
                                    str(bestArbitrageOpportunity[0]).replace(
                                        "-", "_"),
                                    float(
                                        self.getTopOrder(
                                            market1,
                                            bestArbitrageOpportunity[0].
                                            replace("-", "_"), True, 1)),
                                    self.getCurrentBalance(market1, coinName))
                                print(
                                    "Attempting to Sell Maximum Amount of Coins that Could be Sold."
                                )
                            print("Finished Selling all coins. Cycle Complete")
                        else:
                            print("Failed to Buy")
                            return "Failed to Buy"
                    else:
                        print(
                            "The order didn't stay high enough, starting over")
                        self.activateArbitrage(market1, market2, minPercent)
                except AttributeError:
                    print("Attribute Error, sorry")

    def getLendingBalances(self):
        #Only works with Poloniex
        try:
            return cryptoCommander.poloniexBot.api_query(
                'returnAvailableAccountBalances')['lending']
        except KeyError:
            return []

    def getCurrentLoanOffers(self, coin):
        #Only works with Poloniex
        ret = urllib2.request.urlopen('http://poloniex.com/public?command=' +
                                      'returnLoanOrders' + '&currency=' +
                                      str(coin))
        return json.loads(ret.read())

    def getPrimeLendingRate(self, coin, minWeight=Decimal('25.0')):
        #Only works with Poloniex
        accumulatedWeight, bestRate = Decimal('0.0'), Decimal('0.0')
        print(accumulatedWeight)
        for offer in self.getCurrentLoanOffers(coin)['offers']:
            if accumulatedWeight < minWeight:
                print('Accumulated weight is less than 25: ' +
                      str(accumulatedWeight))
                accumulatedWeight = accumulatedWeight + Decimal(
                    str(offer['amount']))
            else:
                print('Best rate is: ' + str(offer['rate']))
                bestRate = Decimal(str(offer['rate'])) - Decimal('0.000001')
                break
        if bestRate < Decimal('0.000001'): bestRate = Decimal('0.000001')
        return bestRate

    def getActiveLoans(self):
        #Only works with Poloniex
        return self.poloniexBot.api_query('returnActiveLoans')

    def getOpenLoanOffers(self):
        #Only works with Poloniex
        try:
            return self.poloniexBot.api_query('returnOpenLoanOffers')
        except KeyError:
            return []

    def cancelLoanOffer(self, currency, orderNumber):
        #Only works with Poloniex
        return self.poloniexBot.api_query('cancelLoanOffer', {
            "currency": currency,
            "orderNumber": orderNumber
        })

    def cancelAllLoanOffers(self):
        openLoansDict = self.getOpenLoanOffers()
        for openLoanCoin in openLoansDict:
            for dataObject in openLoansDict[openLoanCoin]:
                self.cancelLoanOffer(openLoanCoin, dataObject[id])

    def createLoanOffer(self, currency, amount, duration, autoRenew,
                        lendingRate):
        return self.poloniexBot.api_query(
            'createLoanOffer', {
                "currency": currency,
                "amount": amount,
                "duration": duration,
                "autoRenew": autoRenew,
                "lendingRate": lendingRate,
            })

    def checkLendingStagnation(self):
        openLoansDict = self.getOpenLoanOffers()
        for openLoanCoin in openLoansDict:
            for data in openLoansDict[openLoanCoin]:
                if (datetime.datetime.utcnow() - datetime.datetime.strptime(
                        str(data['date']), '%Y-%m-%d %X') >
                        datetime.timedelta(minutes=2)):
                    print('Cancelling Loan Orders that are stagnant.')
                    self.cancelLoanOffer(openLoanCoin, data['id'])

    def placeAllLoans(self):
        balances = self.getLendingBalances()
        for coin in balances:
            try:
                print(balances[coin])
                if type(balances[coin]
                        ) != Decimal and balances[coin] > Decimal('0.0'):
                    balances[coin] = Decimal(str(balances[coin]))
                if type(balances[coin]
                        ) == Decimal and balances[coin] >= Decimal('0.01'):
                    #print "Print currency available is: " + str(balances[coin]) + str(coin) + ", Lending Now."
                    while Decimal(str(balances[coin])) >= Decimal('0.01'):
                        if Decimal(str(balances[coin])) <= Decimal(
                                '0.02') and Decimal(str(
                                    balances[coin])) >= Decimal('0.01'):
                            print('lending between 0.01 and 0.02')
                            print(
                                self.createLoanOffer(
                                    coin, float(balances[coin]), 2, 0,
                                    self.getPrimeLendingRate(coin)))
                        else:
                            primeRate = self.getPrimeLendingRate(coin)
                            print("Prime Rate is: " + str(primeRate))
                            if primeRate <= Decimal('0.000025') or Decimal(
                                    balances[coin]) > Decimal('0.1'):
                                if Decimal(balances[coin]) >= Decimal('10.0'):
                                    if Decimal(
                                            balances[coin]
                                    ) < Decimal('20.0') and Decimal(
                                            balances[coin]) > Decimal('10.0'):
                                        print('lending between 10 and 20')
                                        print(
                                            self.createLoanOffer(
                                                coin, float(balances[coin]), 2,
                                                0, primeRate))
                                    else:
                                        print('lending 10')
                                        print(
                                            self.createLoanOffer(
                                                coin, 10.0, 2, 0, primeRate))
                                else:
                                    if Decimal(
                                            balances[coin]) > Decimal('0.1'):
                                        if Decimal(balances[coin]) < Decimal(
                                                '0.2') and Decimal(
                                                    balances[coin]) > Decimal(
                                                        '0.1'):
                                            print(
                                                'lending between 0.1 and 0.2')
                                            print(
                                                self.createLoanOffer(
                                                    coin,
                                                    float(balances[coin]), 2,
                                                    0, primeRate))
                                        else:
                                            print('lending 0.1')
                                            print(
                                                self.createLoanOffer(
                                                    coin, 0.1, 2, 0,
                                                    primeRate))
                                    else:
                                        print('lending 0.01')
                                        print(
                                            self.createLoanOffer(
                                                coin, 0.01, 2, 0, primeRate))
                            else:
                                print('lending 0.01')
                                print(
                                    self.createLoanOffer(
                                        coin, 0.01, 2, 0, primeRate))
                        time.sleep(.2)
                        balances = self.getLendingBalances()
                else:
                    print('No coins available to lend, sorry!')
            except KeyError:
                print('All loans for ' + str(coin) + ' actively being lent.')

    def startLendingAutomation(self):
        while True:
            try:
                while self.getLendingBalances(
                ) != None and self.getOpenLoanOffers() != None:
                    while any(self.getLendingBalances()) > Decimal(
                            '0.001') or any(self.getOpenLoanOffers()):
                        self.placeAllLoans()
                        time.sleep(150)
                        self.checkLendingStagnation()
                print('All Done.')
            except TypeError:
                print("NOT done")
            break

        # покупает заданную монету
        while True:
            sellOrderBook = sorted(my_bittrex.get_orderbook(
                "BTC-" + last_message['text'])['result']['sell'][0:10],
                                   key=lambda k: k['Quantity'],
                                   reverse=True)

            for x in range(0, 10):
                # баланс БТС выраженный в xCoin  <  количество монет из книги ордеров
                if BTC / sellOrderBook[x]['Rate'] < sellOrderBook[x][
                        'Quantity']:
                    text = my_bittrex.buy_limit(
                        'BTC-' + last_message['text'],
                        BTC / sellOrderBook[x]['Rate'] *
                        float(1 - cfg.getfloat('Data', 'commission') / 100),
                        sellOrderBook[x]['Rate'])
                    print(
                        text, BTC / sellOrderBook[x]['Rate'] *
                        float(1 - cfg.getfloat('Data', 'commission') / 100),
                        sellOrderBook[x]['Rate'])
                else:
                    text = my_bittrex.buy_limit(
                        'BTC-' + last_message['text'],
                        sellOrderBook[x]['Quantity'] *
                        float(1 - cfg.getfloat('Data', 'commission') / 100),
                        sellOrderBook[x]['Rate'])

                BTC = BTC - BTC / sellOrderBook[x]['Rate'] * float(
                    1 - cfg.getfloat('Data', 'commission') / 100)
예제 #12
0
             new_slave_order = slave_bittrex.sell_limit(
                 market=new_order['Exchange'],
                 quantity=new_order['Quantity'],
                 rate=new_order['Limit'])
             if new_slave_order['success']:
                 print('Order Copied Successfully to Slave', slave_number)
                 order_mapping[slave_number - 1][new_order[
                     'OrderUuid']] = new_slave_order['result']['uuid']
             else:
                 print('Error in slave', slave_number,
                       new_slave_order['message'])
                 order_mapping[slave_number - 1][new_order['OrderUuid']] = 0
         elif new_order['OrderType'] == 'LIMIT_BUY':
             write_debug('Limit buy in slave', fl)
             new_slave_order = slave_bittrex.buy_limit(
                 market=new_order['Exchange'],
                 quantity=new_order['Quantity'],
                 rate=new_order['Limit'])
             if new_slave_order['success']:
                 print('Order Copied Successfully to Slave', slave_number)
                 order_mapping[slave_number - 1][new_order[
                     'OrderUuid']] = new_slave_order['result']['uuid']
             else:
                 print('Error in slave', slave_number,
                       new_slave_order['message'])
                 order_mapping[slave_number - 1][new_order['OrderUuid']] = 0
         else:
             print('Order type not supported')
     i_open_count += 1
     i_count = i_open_count + i_history_count
     sleep(10)
 elif len(master_order_history['result']) > i_history_count: