def test_marketBuyInvalidAmount():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    with pytest.raises(ValueError) as execinfo:
        exchange.marketBuy('XXX-YYY', 0)
    assert str(execinfo.value) == 'Trade amount is too small (>= 10).'
def test_config_json_exists_and_valid():
    filename = 'config.json'
    assert os.path.exists(filename) == True
    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']
            AuthAPI(api_key, api_secret, api_passphrase, api_url)
        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']
            AuthAPI(api_key, api_secret, api_passphrase, api_url)
    pass
def test_getTime():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    resp = exchange.getTime()
    assert type(resp) is datetime
def test_marketBuyInvalidMarket():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    with pytest.raises(ValueError) as execinfo:
        exchange.marketBuy('ERROR', -1)
    assert str(execinfo.value) == 'Coinbase Pro market is invalid.'
def test_getOrdersInvalidStatus():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    with pytest.raises(ValueError) as execinfo:
        exchange.getOrders(status='ERROR')
    assert str(execinfo.value) == 'Invalid order status.'
def test_getMakerFeeWithMarket():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    fee = exchange.getMakerFee(getValidOrderMarket())
    assert type(fee) is float
    assert fee > 0
Beispiel #7
0
    def __init__(self, app:PyCryptoBot, account:TradingAccount) -> None:
        if app.getExchange() == 'binance':
            self.api = BAuthAPI(app.getAPIKey(), app.getAPISecret(), app.getAPIURL())
        elif app.getExchange() == 'coinbasepro':
            self.api = CAuthAPI(app.getAPIKey(), app.getAPISecret(), app.getAPIPassphrase(), app.getAPIURL())
        else:
            self.api = None

        self.app = app
        self.account = account

        self.action = 'WAIT'
        self.buy_count = 0
        self.buy_state = ''
        self.buy_sum = 0
        self.eri_text = ''
        self.fib_high = 0
        self.fib_low = 0
        self.first_buy_size = 0
        self.iterations = 0
        self.last_action = 'WAIT'
        self.last_buy_size = 0
        self.last_buy_price = 0
        self.last_buy_filled = 0
        self.last_buy_fee = 0
        self.last_buy_high = 0 
        self.last_df_index = ''
        self.sell_count = 0
        self.sell_sum = 0
Beispiel #8
0
 def getTakerFee(self):
     if self.exchange == 'coinbasepro':
         api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL())
         return api.getTakerFee()
     elif self.exchange == 'binance':
         api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL())
         return api.getTakerFee(self.getMarket())
     else:
         return 0.005
def test_get_maker_fee_with_market():
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    api_url = "https://public.sandbox.pro.coinbase.com"
    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    fee = exchange.getMakerFee()
    assert type(fee) is float
    assert fee == 0.005
Beispiel #10
0
 def marketSell(self, market, base_currency, sell_percent=100):
     if self.is_live == 1:
         if isinstance(sell_percent, int):
             if sell_percent > 0 and sell_percent < 100:
                 base_currency = (sell_percent / 100) * base_currency
             if self.exchange == 'coinbasepro':
                 api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL())
                 return api.marketSell(market, base_currency)
             elif self.exchange == 'binance':
                 api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL())
                 return api.marketSell(market, base_currency)
         else:
             return None
Beispiel #11
0
    def marketBuy(self, market, quote_currency, buy_percent=100):
        if self.is_live == 1:
            if isinstance(buy_percent, int):
                if buy_percent > 0 and buy_percent < 100:
                    quote_currency = (buy_percent / 100) * quote_currency

            if self.exchange == 'coinbasepro':
                api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL())
                return api.marketBuy(market, self.truncate(quote_currency, 2))
            elif self.exchange == 'binance':
                api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL())
                return api.marketBuy(market, quote_currency)
            else:
                return None
def test_get_fees_with_market():
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    api_url = "https://public.sandbox.pro.coinbase.com"
    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI
    df = exchange.getFees()
    assert type(df) is pandas.core.frame.DataFrame
    assert len(df) == 1
    actual = df.columns.to_list()
    expected = ['maker_fee_rate', 'taker_fee_rate', 'usd_volume', 'market']
    assert len(actual) == len(expected)
    assert all([a == b for a, b in zip(actual, expected)])
Beispiel #13
0
 def getTakerFee(self):
     if self.isSimulation() is True and self.exchange == 'coinbasepro':
         return 0.005  # default lowest fee tier
     elif self.isSimulation() is True and self.exchange == 'binance':
         return 0.001  # default lowest fee tier
     elif self.exchange == 'coinbasepro':
         api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(),
                         self.getAPIPassphrase(), self.getAPIURL())
         return api.getTakerFee()
     elif self.exchange == 'binance':
         api = BAuthAPI(self.getAPIKey(), self.getAPISecret(),
                        self.getAPIURL())
         return api.getTakerFee()
     else:
         return 0.005
def test_get_orders():
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    api_url = "https://public.sandbox.pro.coinbase.com"
    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    df = exchange.getOrders()
    assert type(df) is pandas.core.frame.DataFrame
    assert len(df) > 0
    actual = df.columns.to_list()
    expected = ['created_at', 'market', 'action', 'type', 'size', 'filled', 'status', 'price']
    assert len(actual) == len(expected)
    diff = set(actual) ^ set(expected)
    assert not diff
def test_instantiate_authapi_without_error():
    global app
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    exchange = AuthAPI(api_key, api_secret, api_passphrase)
    assert type(exchange) is AuthAPI
def test_getAccount():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    df = exchange.getAccounts()

    assert len(df) > 0

    account = df[['id']].head(1).values[0][0]
    assert len(account) > 0

    df = exchange.getAccount(account)
    assert type(df) is pandas.core.frame.DataFrame

    assert len(df) == 1

    actual = df.columns.to_list()
    expected = [
        'id', 'currency', 'balance', 'hold', 'available', 'profile_id',
        'trading_enabled'
    ]
    assert len(actual) == len(expected)
    assert all([a == b for a, b in zip(actual, expected)])
def test_instantiate_authapi_with_api_passphrase_error():
    api_key = "00000000000000000000000000000000"
    api_secret = "0000/0000000000/0000000000000000000000000000000000000000000000000000000000/00000000000=="
    api_passphrase = "ERROR"

    with pytest.raises(SystemExit) as execinfo:
        AuthAPI(api_key, api_secret, api_passphrase)
    assert str(execinfo.value) == 'Coinbase Pro API passphrase is invalid'
def test_instantiate_authapi_with_api_url_error():
    api_key = "00000000000000000000000000000000"
    api_secret = "0000/0000000000/0000000000000000000000000000000000000000000000000000000000/00000000000=="
    api_passphrase = "00000000000"
    api_url = "ERROR"

    with pytest.raises(ValueError) as execinfo:
        AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert str(execinfo.value) == 'Coinbase Pro API URL is invalid'
def test_instantiate_authapi_with_api_url_error():
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    api_url = "https://foo.com"

    with pytest.raises(ValueError) as execinfo:
        AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert str(execinfo.value) == 'Coinbase Pro API URL is invalid'
def test_instantiate_authapi_with_api_secret_error():
    global app
    api_key = app.getAPIKey()
    api_secret = "Ivalid"
    api_passphrase = app.getAPIPassphrase()

    with pytest.raises(SystemExit) as execinfo:
        AuthAPI(api_key, api_secret, api_passphrase)
    assert str(execinfo.value) == 'Coinbase Pro API secret is invalid'
 def checkBalance(self, account, last_action=''):
     api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(),
                     self.getAPIPassphrase(), self.getAPIURL())
     base_min_size, min_market_funds = api.marketMin(
         self.getMarket(), 0.001, 50)
     if last_action == 'SELL' and account.getBalance(
             self.getQuoteCurrency()) < min_market_funds:
         raise Exception(
             'Insufficient available funds to place buy order: ' +
             str(account.getBalance(self.getQuoteCurrency())) + ' < ' +
             min_market_funds + self.getQuoteCurrency() +
             "\nNote: A manual limit order places a hold on available funds."
         )
     elif last_action == 'BUY' and account.getBalance(
             self.getBaseCurrency()) < base_min_size:
         raise Exception(
             'Insufficient available funds to place sell order: ' +
             str(account.getBalance(self.getBaseCurrency())) + ' < ' +
             base_min_size + self.getBaseCurrency() +
             "\nNote: A manual limit order places a hold on available funds."
         )
def test_getOrdersValidStatusActive():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    df = exchange.getOrders(status='active')

    if len(df) == 0:
        pass
    else:
        actual = df.columns.to_list()
        expected = [
            'created_at', 'market', 'action', 'type', 'size', 'value',
            'status', 'price'
        ]
        assert len(actual) == len(expected)
        assert all([a == b for a, b in zip(actual, expected)])
def test_api_v3_account1():
    global app
    api_key = app.getAPIKey()
    api_secret = app.getAPISecret()
    api_passphrase = app.getAPIPassphrase()
    api_url = "https://public.sandbox.pro.coinbase.com"
    api = AuthAPI(api_key, api_secret, api_passphrase, api_url)

    with open('tests/unit_tests/responses/account1.json') as fh:
        responses.add(responses.GET, f'{api_url}/account', json=json.load(fh), status=200)
        df = api.getAccounts()
        fh.close()

        assert len(df) > 1
        assert df.columns.tolist() == [ 'index', 'id', 'currency', 'balance', 'hold', 'available', 'profile_id', 'trading_enabled' ]
        assert df.dtypes['index'] == 'int64'
        assert df.dtypes['id'] == 'object'
        assert df.dtypes['currency'] == 'object'
        assert df.dtypes['balance'] == 'object'
        assert df.dtypes['hold'] == 'object'
        assert df.dtypes['available'] == 'object'
        assert df.dtypes['profile_id'] == 'object'
        assert df.dtypes['trading_enabled'] == 'bool'
def getValidOrderMarket() -> str:
    filename = 'config.json'
    assert os.path.exists(filename) == True
    with open(filename) as config_file:
        config = json.load(config_file)

        if 'api_key' in config and 'api_secret' in config and (
                'api_pass' in config
                or 'api_passphrase' in config) and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            if 'api_pass' in config:
                api_passphrase = config['api_pass']
            else:
                api_passphrase = config['api_passphrase']
            api_url = config['api_url']
        elif 'coinbasepro' in config:
            if 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                    'coinbasepro'] and 'api_passphrase' in config[
                        'coinbasepro'] and 'api_url' in config['coinbasepro']:
                api_key = config['coinbasepro']['api_key']
                api_secret = config['coinbasepro']['api_secret']
                api_passphrase = config['coinbasepro']['api_passphrase']
                api_url = config['coinbasepro']['api_url']
            else:
                return DEFAULT_ORDER_MARKET
        else:
            return DEFAULT_ORDER_MARKET

        time.sleep(0.5)
        exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
        df = exchange.getOrders()
        if len(df) == 0:
            return DEFAULT_ORDER_MARKET

        return df['market'].tail(1).values[0]
    return DEFAULT_ORDER_MARKET
def test_getFeesWithMarket():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    df = exchange.getFees(getValidOrderMarket())
    assert type(df) is pandas.core.frame.DataFrame

    assert len(df) == 1

    actual = df.columns.to_list()
    expected = ['maker_fee_rate', 'taker_fee_rate', 'usd_volume', 'market']
    assert len(actual) == len(expected)
    assert all([a == b for a, b in zip(actual, expected)])
Beispiel #26
0
class AppState():
    def __init__(self, app:PyCryptoBot, account:TradingAccount) -> None:
        if app.getExchange() == 'binance':
            self.api = BAuthAPI(app.getAPIKey(), app.getAPISecret(), app.getAPIURL())
        elif app.getExchange() == 'coinbasepro':
            self.api = CAuthAPI(app.getAPIKey(), app.getAPISecret(), app.getAPIPassphrase(), app.getAPIURL())
        else:
            self.api = None

        self.app = app
        self.account = account

        self.action = 'WAIT'
        self.buy_count = 0
        self.buy_state = ''
        self.buy_sum = 0
        self.eri_text = ''
        self.fib_high = 0
        self.fib_low = 0
        self.first_buy_size = 0
        self.iterations = 0
        self.last_action = 'WAIT'
        self.last_buy_size = 0
        self.last_buy_price = 0
        self.last_buy_filled = 0
        self.last_buy_fee = 0
        self.last_buy_high = 0 
        self.last_df_index = ''
        self.sell_count = 0
        self.sell_sum = 0

    def minimumOrderBase(self):
        if self.app.getExchange() == 'binance':
            info = self.api.client.get_symbol_info(symbol=self.app.getMarket())

            base_min = 0
            if 'filters' in info:
                for filter_type in info['filters']:
                    if 'LOT_SIZE' == filter_type['filterType']:
                        base_min = float(filter_type['minQty'])

            base = float(self.account.getBalance(self.app.getBaseCurrency()))

            if base < base_min:
                sys.tracebacklimit = 0
                raise Exception(f'Insufficient Base Funds! (Actual: {base}, Minimum: {base_min})')

        elif self.app.getExchange() == 'coinbasepro':
            product = self.api.authAPI('GET', f'products/{self.app.getMarket()}')
            if len(product) == 0:
                sys.tracebacklimit = 0
                raise Exception(f'Market not found! ({self.app.getMarket()})')

            base = float(self.account.getBalance(self.app.getBaseCurrency()))
            base_min = float(product['base_min_size'])

            if base < base_min:
                sys.tracebacklimit = 0
                raise Exception(f'Insufficient Base Funds! (Actual: {base}, Minimum: {base_min})')

    def minimumOrderQuote(self):
        if self.app.getExchange() == 'binance':
            info = self.api.client.get_symbol_info(symbol=self.app.getMarket())

            quote_min = 0
            if 'filters' in info:
                for filter_type in info['filters']:
                    if 'MIN_NOTIONAL' == filter_type['filterType']:
                        quote_min = float(filter_type['minNotional'])

            quote = float(self.account.getBalance(self.app.getQuoteCurrency()))

            if quote < quote_min:
                sys.tracebacklimit = 0
                raise Exception(f'Insufficient Quote Funds! (Actual: {quote}, Minimum: {quote_min})')

        elif self.app.getExchange() == 'coinbasepro':
            product = self.api.authAPI('GET', f'products/{self.app.getMarket()}')
            if len(product) == 0:
                sys.tracebacklimit = 0
                raise Exception(f'Market not found! ({self.app.getMarket()})')

            ticker = self.api.authAPI('GET', f'products/{self.app.getMarket()}/ticker')
            price = float(ticker['price'])

            quote = float(self.account.getBalance(self.app.getQuoteCurrency()))
            base_min = float(product['base_min_size'])

            if (quote / price) < base_min:
                sys.tracebacklimit = 0
                raise Exception(f'Insufficient Quote Funds! (Actual: {"{:.8f}".format((quote / price))}, Minimum: {base_min})')

    def initLastAction(self):
        # ignore if manually set
        if self.app.getLastAction() is not None:
            self.last_action = self.app.getLastAction()
            return

        # if not live
        if not self.app.isLive():
            self.last_action = 'SELL'
            return

        orders = self.account.getOrders(self.app.getMarket(), '', 'done')
        if len(orders) > 0:
            last_order = orders[-1:]

            # if orders exist and last order is a buy
            if str(last_order.action.values[0]) == 'buy':
                self.last_buy_size = float(last_order[last_order.action == 'buy']['size'])
                self.last_buy_filled = float(last_order[last_order.action == 'buy']['filled'])
                self.last_buy_price = float(last_order[last_order.action == 'buy']['price'])

                # binance orders do not show fees
                if self.app.getExchange() == 'coinbasepro':
                    self.last_buy_fee = float(last_order[last_order.action == 'buy']['fees'])

                self.last_action = 'BUY'
                return
            else:
                self.minimumOrderQuote()
                self.last_action = 'SELL'
                self.last_buy_price = 0.0
                return
        else:
            base = float(self.account.getBalance(self.app.getBaseCurrency()))
            quote = float(self.account.getBalance(self.app.getQuoteCurrency()))

            # nil base or quote funds
            if base == 0.0 and quote == 0.0:
                sys.tracebacklimit = 0
                raise Exception(f'Insufficient Funds! ({self.app.getBaseCurrency()}={str(base)}, {self.app.getQuoteCurrency()}={str(base)})') 

            # determine last action by comparing normalised [0,1] base and quote balances 
            order_pairs = np_array([ base, quote ])
            order_pairs_normalised = (order_pairs - np_min(order_pairs)) / np_ptp(order_pairs)

            if order_pairs_normalised[0] < order_pairs_normalised[1]:
                self.minimumOrderQuote()
                self.last_action = 'SELL'
            elif order_pairs_normalised[0] > order_pairs_normalised[1]:
                self.minimumOrderBase()
                self.last_action = 'BUY'

            else:
                self.last_action = 'WAIT'

            return
Beispiel #27
0
    def getLastBuy(self) -> dict:
        """Retrieves the last exchange buy order and returns a dictionary"""

        try:
            if self.exchange == 'coinbasepro':
                api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(),
                                self.getAPIPassphrase(), self.getAPIURL())
                orders = api.getOrders(self.getMarket(), '', 'done')

                if len(orders) == 0:
                    return None

                last_order = orders.tail(1)
                if last_order['action'].values[0] != 'buy':
                    return None

                return {
                    'side':
                    'buy',
                    'market':
                    self.getMarket(),
                    'size':
                    float(last_order['size']),
                    'filled':
                    float(last_order['filled']),
                    'price':
                    float(last_order['price']),
                    'fee':
                    float(last_order['fees']),
                    'date':
                    str(
                        pd.DatetimeIndex(
                            pd.to_datetime(
                                last_order['created_at']).dt.strftime(
                                    '%Y-%m-%dT%H:%M:%S.%Z'))[0])
                }
            elif self.exchange == 'binance':
                api = BAuthAPI(self.getAPIKey(), self.getAPISecret(),
                               self.getAPIURL())
                orders = api.getOrders(self.getMarket())

                if len(orders) == 0:
                    return None

                last_order = orders.tail(1)
                if last_order['action'].values[0] != 'buy':
                    return None

                return {
                    'side':
                    'buy',
                    'market':
                    self.getMarket(),
                    'size':
                    float(last_order['size']),
                    'filled':
                    float(last_order['filled']),
                    'price':
                    float(last_order['price']),
                    'fees':
                    float(last_order['size'] * 0.001),
                    'date':
                    str(
                        pd.DatetimeIndex(
                            pd.to_datetime(
                                last_order['created_at']).dt.strftime(
                                    '%Y-%m-%dT%H:%M:%S.%Z'))[0])
                }
            else:
                return None
        except Exception:
            return None
Beispiel #28
0
    def sell(self,
             cryptoMarket,
             fiatMarket,
             cryptoAmount,
             manualPrice=0.00000000):
        """Places a sell order either live or simulation

        Parameters
        ----------
        cryptoMarket: str
            Crypto market you wish to purchase
        fiatMarket, str
            QUOTE market funding the purchase
        fiatAmount, float
            QUOTE amount of crypto currency to purchase
        manualPrice, float
            Used for simulations specifying the live price to purchase
        """
        if self.app.getExchange() == 'binance':
            # validate crypto market is syntactically correct
            p = re.compile(r"^[A-Z]{3,8}$")
            if not p.match(cryptoMarket):
                raise TypeError('Binance crypto market is invalid.')

            # validate fiat market is syntactically correct
            p = re.compile(r"^[A-Z]{3,8}$")
            if not p.match(fiatMarket):
                raise TypeError('Binance fiat market is invalid.')
        else:
            # crypto market should be either BCH, BTC, ETH, LTC or XLM
            if cryptoMarket not in ['BCH', 'BTC', 'ETH', 'LTC', 'XLM']:
                raise Exception(
                    'Invalid crypto market: BCH, BTC, ETH, LTC, ETH, or XLM')

            # fiat market should be either EUR, GBP, or USD
            if fiatMarket not in ['EUR', 'GBP', 'USD']:
                raise Exception('Invalid QUOTE market: EUR, GBP, USD')

        # reconstruct the exchange market using crypto and fiat inputs
        if self.app.getExchange() == 'binance':
            market = cryptoMarket + fiatMarket
        else:
            market = cryptoMarket + '-' + fiatMarket

        # crypto amount must be an integer or float
        if not isinstance(cryptoAmount, float) and not isinstance(
                cryptoAmount, int):
            raise TypeError('Crypto amount not numeric.')

        # crypto amount must be positive
        if cryptoAmount <= 0:
            raise Exception('Invalid crypto amount.')

        if self.app.getExchange() == 'binance':
            if self.mode == 'live':
                # execute a live market buy
                resp = self.client.order_market_sell(symbol=market,
                                                     quantity=cryptoAmount)

                # TODO: not finished
                print(resp)
            else:
                # crypto amount should exceed balance
                if cryptoAmount > self.getBalance(cryptoMarket):
                    raise Exception('Insufficient funds.')

                # manual price must be an integer or float
                if not isinstance(manualPrice, float) and not isinstance(
                        manualPrice, int):
                    raise TypeError('Optional manual price not numeric.')

                # calculate purchase fees
                fee = cryptoAmount * 0.005
                cryptoAmountMinusFee = cryptoAmount - fee

                price = manualPrice
                # if manualPrice is non-positive retrieve the current live price
                if manualPrice <= 0:
                    resp = requests.get(
                        'https://api-public.sandbox.pro.coinbase.com/products/'
                        + market + '/ticker')
                    if resp.status_code != 200:
                        raise Exception('GET /products/' + market +
                                        '/ticker {}'.format(resp.status_code))
                    resp.raise_for_status()
                    json = resp.json()
                    price = float(json['price'])

                total = price * cryptoAmountMinusFee

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = ((price * cryptoAmount) * 100) / (cryptoAmount * 100)
                order = pd.DataFrame([[
                    '', market, 'sell', 'market', cryptoAmountMinusFee,
                    float('{:.8f}'.format(total)), 'done', '{:.8f}'.format(
                        float(price))
                ]],
                                     columns=[
                                         'created_at', 'market', 'action',
                                         'type', 'size', 'value', 'status',
                                         'price'
                                     ],
                                     index=[ts])
                order['created_at'] = order.index
                self.orders = pd.concat(
                    [self.orders, pd.DataFrame(order)], ignore_index=False)

                # update the dummy fiat balance
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'balance'] = self.getBalance(fiatMarket) + total
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) + total

                # update the dummy crypto balance
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'balance'] = self.getBalance(cryptoMarket) - cryptoAmount
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) - cryptoAmount

        else:
            if self.mode == 'live':
                # connect to Coinbase Pro API live
                model = CBAuthAPI(self.app.getAPIKey(),
                                  self.app.getAPISecret(),
                                  self.app.getAPIPassphrase(),
                                  self.app.getAPIURL())

                # execute a live market sell
                resp = model.marketSell(market,
                                        float(self.getBalance(cryptoMarket)))

                # TODO: not finished
                print(resp)
            else:
                # crypto amount should exceed balance
                if cryptoAmount > self.getBalance(cryptoMarket):
                    raise Exception('Insufficient funds.')

                # manual price must be an integer or float
                if not isinstance(manualPrice, float) and not isinstance(
                        manualPrice, int):
                    raise TypeError('Optional manual price not numeric.')

                # calculate purchase fees
                fee = cryptoAmount * 0.005
                cryptoAmountMinusFee = cryptoAmount - fee

                price = manualPrice
                if manualPrice <= 0:
                    # if manualPrice is non-positive retrieve the current live price
                    resp = requests.get(
                        'https://api-public.sandbox.pro.coinbase.com/products/'
                        + market + '/ticker')
                    if resp.status_code != 200:
                        raise Exception('GET /products/' + market +
                                        '/ticker {}'.format(resp.status_code))
                    resp.raise_for_status()
                    json = resp.json()
                    price = float(json['price'])

                total = price * cryptoAmountMinusFee

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = ((price * cryptoAmount) * 100) / (cryptoAmount * 100)
                order = pd.DataFrame([[
                    market, 'sell', 'market', cryptoAmountMinusFee,
                    float('{:.8f}'.format(total)), 'done', price
                ]],
                                     columns=[
                                         'market', 'action', 'type', 'size',
                                         'value', 'status', 'price'
                                     ],
                                     index=[ts])
                order['created_at'] = order.index
                self.orders = pd.concat(
                    [self.orders, pd.DataFrame(order)], ignore_index=False)

                # update the dummy fiat balance
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'balance'] = self.getBalance(fiatMarket) + total
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) + total

                # update the dummy crypto balance
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'balance'] = self.getBalance(cryptoMarket) - cryptoAmount
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) - cryptoAmount
Beispiel #29
0
                config_list = [config]

            for config_item in config_list:
                if "cryptoMarket" in config:
                    base_currency = config["cryptoMarket"]
                elif "base_currency" in config:
                    base_currency = config["base_currency"]

                if "fiatMarket" in config:
                    quote_currency = config["fiatMarket"]
                elif "base_currency" in config:
                    quote_currency = config["quote_currency"]

                market = base_currency + "-" + quote_currency

                api = CBAuthAPI(api_key, api_secret, api_pass)

                orders = api.getOrders()
                df = pd.concat([df, orders])

                transfers = api.getTransfers()
                df = pd.concat([df, transfers])

    df["created_at"] = df["created_at"].map(
        lambda x: re.sub(r"\.\d{1,6}\+00$", "", str(x))
    )
    df["created_at"] = df["created_at"].map(lambda x: re.sub(r"\+00:00$", "", str(x)))

    try:
        df.to_csv("profitandloss.csv", index=False)
    except OSError:
Beispiel #30
0
            for config_item in config_list:
                total_markets += 1

                if "cryptoMarket" in config_item:
                    base_currency = config_item["cryptoMarket"]
                elif "base_currency" in config_item:
                    base_currency = config_item["base_currency"]

                if "fiatMarket" in config_item:
                    quote_currency = config_item["fiatMarket"]
                elif "base_currency" in config_item:
                    quote_currency = config_item["quote_currency"]

                market = base_currency + "-" + quote_currency

                api = CBAuthAPI(api_key, api_secret, api_pass)
                orders = api.getOrders(market)

                last_action = ""
                if len(orders) > 0:
                    for market in orders["market"].sort_values().unique():
                        df_market = orders[orders["market"] == market]
                else:
                    df_market = pd.DataFrame()

                df_buy = pd.DataFrame()
                df_sell = pd.DataFrame()

                pair = 0
                # pylint: disable=unused-variable
                for index, row in df_market.iterrows():