def buy(self, cryptoMarket, fiatMarket, fiatAmount=0, manualPrice=0.00000000): """Places a buy 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 """ # fiat funding amount must be an integer or float if not isinstance(fiatAmount, float) and not isinstance( fiatAmount, int): raise TypeError('QUOTE amount not numeric.') # fiat funding amount must be positive if fiatAmount <= 0: raise Exception('Invalid QUOTE amount.') 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 if self.app.getExchange() == 'binance': if self.mode == 'live': # execute a live market buy resp = self.client.order_market_buy(symbol=market, quantity=fiatAmount) # TODO: not finished print(resp) else: # fiat amount should exceed balance if fiatAmount > self.getBalance(fiatMarket): 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.') price = manualPrice # if manualPrice is non-positive retrieve the current live price if manualPrice <= 0: if self.app.getExchange() == 'binance': api = BPublicAPI() price = api.getTicker(market) else: 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']) # calculate purchase fees fee = fiatAmount * 0.005 fiatAmountMinusFee = fiatAmount - fee total = float(fiatAmountMinusFee / float(price)) # append dummy order into orders dataframe ts = pd.Timestamp.now() price = (fiatAmountMinusFee * 100) / (total * 100) order = pd.DataFrame([[ '', market, 'buy', 'market', float('{:.8f}'.format(total)), fiatAmountMinusFee, '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) - fiatAmount self.balance.loc[ self.balance['currency'] == fiatMarket, 'available'] = self.getBalance(fiatMarket) - fiatAmount # update the dummy crypto balance self.balance.loc[self.balance['currency'] == cryptoMarket, 'balance'] = self.getBalance(cryptoMarket) + ( fiatAmountMinusFee / price) self.balance.loc[ self.balance['currency'] == cryptoMarket, 'available'] = self.getBalance(cryptoMarket) + ( fiatAmountMinusFee / price) else: if self.mode == 'live': # connect to coinbase pro api (authenticated) model = CBAuthAPI(self.app.getAPIKey(), self.app.getAPISecret(), self.app.getAPIPassphrase(), self.app.getAPIURL()) # execute a live market buy if fiatAmount > 0: resp = model.marketBuy(market, fiatAmount) else: resp = model.marketBuy(market, float(self.getBalance(fiatMarket))) # TODO: not finished print(resp) else: # fiat amount should exceed balance if fiatAmount > self.getBalance(fiatMarket): 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.') 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']) # calculate purchase fees fee = fiatAmount * 0.005 fiatAmountMinusFee = fiatAmount - fee total = float(fiatAmountMinusFee / price) # append dummy order into orders dataframe ts = pd.Timestamp.now() price = (fiatAmountMinusFee * 100) / (total * 100) order = pd.DataFrame([[ '', market, 'buy', 'market', float('{:.8f}'.format(total)), fiatAmountMinusFee, 'done', 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) - fiatAmount self.balance.loc[ self.balance['currency'] == fiatMarket, 'available'] = self.getBalance(fiatMarket) - fiatAmount # update the dummy crypto balance self.balance.loc[self.balance['currency'] == cryptoMarket, 'balance'] = self.getBalance(cryptoMarket) + ( fiatAmountMinusFee / price) self.balance.loc[ self.balance['currency'] == cryptoMarket, 'available'] = self.getBalance(cryptoMarket) + ( fiatAmountMinusFee / price)
def test_instantiate_publicapi_without_error(): exchange = PublicAPI() assert type(exchange) is PublicAPI