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
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 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
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
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)])
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)])
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
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
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
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:
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():