def getAccountBalances(self):
     """Returns a list of dictionaries of the balances. Returns -1 if error.
     Example output:
     [
     {
       "asset": "BTC",
       "free": "4723846.89208129",
       "locked": "0.00000000"
     },
     {
       "asset": "LTC",
       "free": "4763368.68006011",
       "locked": "0.00000000"
     }
     ]
   """
     rateLimitOK = self.rateLimits.update("ORDERS", 5)
     if rateLimitOK:
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         payload = {'timestamp': ts}            
                    
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/account', payload, reqType  = 'GET')  
         s = requests.Session()
         r = s.send(authReq)
         
         if str(r.status_code)[0] == '4' or str(r.status_code)[0] == '5': 
             logger.error('Return code error in getAccountBalances: ' + str(r.status_code) + ';' + str(r.content))  
             return -1
         
         res = r.json()   
         logger.debug('get account balances executed: ' + str(res))
         return res['balances']
     else:
         return -1    
 def placeOrder(self, symbol, side, ordType, quantity, clientOrderID, asMaker = False, price = 0, otherParams = {}):
     """
     side - BUY or SELL 
     ordtype - LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER
     quanity - required decimlar
     price - decimal (optional). If price = 0, order will be a market order.
     otherParams - optional list of additional key-value pairs to write to db (not otherwise used)
     """
     rateLimitOK = self.rateLimits.update("ORDERS", 1)
     if rateLimitOK:
         if price == 0 and not ordType == 'MARKET':
             logger.error('price indicates Market order order but ordType is not market.' )
             return -1
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         
         #Apply filters to price and quantity
         price, quantity = self._applyFilters(price, quantity, symbol)
         if price == None:
             return -1
         
         if price == 0:
             payload = {'symbol':symbol, 'side': side, 'type': ordType, 'quantity': quantity, 'timestamp': ts, 
                        'newClientOrderId': clientOrderID}
         else:
             price = round(price, self.symbolExchInfo[symbol]['quotePrecision'])
             fmtStr= '{:.' + str(self.symbolExchInfo[symbol]['quotePrecision']) + 'f}'
             payload = {'symbol':symbol, 'side': side, 'type': ordType, 'quantity': quantity, 'timestamp': ts, 'price': fmtStr.format(price), 
                        'timeInForce': 'GTC', 'newClientOrderId': clientOrderID}            
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/order', payload)  
         s = requests.Session()
         r = s.send(authReq)
         
         if r.status_code != 200:
             logger.error('Return code error in placeOrder: ' + str(r.status_code) + "  " + str(r.content))  
             return -1
         
         res = r.json()   
         newD = {'orderID': res['orderId'],
                             'exchange': 'binance',
                             'side': res['side'].lower(),
                             'amt':float(res['origQty']),
                             'amtFilled': float(res['executedQty']),
                             'amtRemaining': float(res['origQty']) - float(res['executedQty']),
                             'timestamp': res['transactTime']/1000,
                             'symbol': res['symbol'],
                             'clientTradeLabel': res['clientOrderId'],
                             'price' : float(res['price']),
                             'asMaker': asMaker}   
         
         #add additional parameters to the dictionary
         for k in otherParams.keys():
             if not k in newD:
                 newD[k] = otherParams[k]            
                 
         return newD                
     else:
         return -1
 def getOpenOrders(self, symbol):
     """Get open orders on a symbol. Set symbol to None for all open orders. Returns -1 if an error.
     Example Response, a list of:
     {
     "symbol": "LTCBTC",
     "orderId": 1,
     "clientOrderId": "myOrder1",
     "price": "0.1",
     "origQty": "1.0",
     "executedQty": "0.0",
     "status": "NEW",
     "timeInForce": "GTC",
     "type": "LIMIT",
     "side": "BUY",
     "stopPrice": "0.0",
     "icebergQty": "0.0",
     "time": 1499827319559,
     "isWorking": trueO
     }      
     """
     rateLimitOK = self.rateLimits.update("ORDERS", 1)
     if rateLimitOK:
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         payload = {'timestamp': ts}            
         if symbol:
             payload.update({'symbol': symbol})
         
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/openOrders', payload, reqType  = 'GET')  
         s = requests.Session()
         r = s.send(authReq)
         
         if str(r.status_code)[0] == '4' or str(r.status_code)[0] == '5': 
             logger.error('Return code error in getOpenOrders: ' + str(r.status_code) + ';' + json.loads(r.content)['msg'])  
             return -1
         
         res = r.json()   
         logger.debug('get open orders executed: ' + str(res))
         outL = []
         for d in res:
             newD = {'orderID': d['orderId'],
                     'exchange': 'binance',
                     'side': d['side'].lower(),
                     'amt': float(d['origQty']),
                     'amtFilled': float(d['executedQty']),
                     'amtRemaining': float(d['origQty']) - float(d['executedQty']),
                     'timestamp': d['time']/1000,
                     'symbol': d['symbol'],
                     'clientOrdID' : d['clientOrderId']}  
             if newD['amtFilled'] < newD['amt']:
                 outL.append(newD)            
         return outL
     else:
         return -1            
 def update(self, weightType, weight):
     """Update the counter value of the REQUESTS or ORDERS weight.
     Returns False if the counter is above an acceptable limit."""
     #increment counters
     blnOutput = True
     nowTS = getTimeStamp()
     self.lock.acquire() 
     if weightType == 'REQUESTS':
         for d in self.rateLimits['REQUESTS']:
             #update counter and list of previous entries 
             d['counter'] += weight
             d['lstOfEntries'].append((weight, nowTS))
             
             #delete entries as appropriate
             deleteCount = 0
             totalAdj = 0
             for w, ts in d['lstOfEntries']:
                 if nowTS - ts > d['interval']:
                     totalAdj += w
                     deleteCount += 1
                 else:
                     break
             d['counter'] = d['counter'] - totalAdj
             del d['lstOfEntries'][:deleteCount]   #delete expired entries   
             
             #check if rate violation
             if d['counter'] >= d['limit']:
                 blnOutput = False
                 logger.info("Binance: Rate violation for REQUESTS type")
     elif weightType == 'ORDERS':
         for d in self.rateLimits['ORDERS']:
             d['counter'] += weight
             d['lstOfEntries'].append((weight, nowTS))
             #delete entries as appropriate
             deleteCount = 0
             totalAdj = 0
             for w, ts in d['lstOfEntries']:
                 if nowTS - ts < d['interval']:
                     totalAdj += w
                     deleteCount += 1
                 else:
                     break
             d['counter'] = d['counter'] - totalAdj
             del d['lstOfEntries'][:deleteCount]   #delete expired entries   
             if d['counter'] >= d['limit']:
                 blnOutput = False
                 logger.info("Binance: Rate violation for ORDERS type")
     self.lock.release()        
     
     return blnOutput
    def getAggTrades(self, symbol, startTime = None, endTime = None):
        """
        Get compressed, aggregate trades. Trades that fill at the time, from the same order, with the same price will have the quantity aggregated.

        Parameters:
        Name 	Type 	Mandatory 	Description
        symbol 	STRING 	YES 	
        startTime 	LONG 	NO 	Timestamp in ms to get aggregate trades from INCLUSIVE.
        endTime 	LONG 	NO 	Timestamp in ms to get aggregate trades until INCLUSIVE.
        
        If both startTime and endTime are sent, limit should not be sent AND the distance between startTime and endTime must be less than 24 hours.
        If frondId, startTime, and endTime are not sent, the most recent aggregate trades will be returned.
        
        Example Response:
        [
        {
          "a": 26129,         // Aggregate tradeId
          "p": "0.01633102",  // Price
          "q": "4.70443515",  // Quantity
          "f": 27781,         // First tradeId
          "l": 27781,         // Last tradeId
          "T": 1498793709153, // Timestamp
          "m": true,          // Was the buyer the maker?
          "M": true           // Was the trade the best price match?
        }
      ]
        """
        rateLimitOK = self.rateLimits.update("ORDERS", 1)
        if rateLimitOK:
            ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
            payload = {'timestamp': ts, 'symbol': symbol}            
            if startTime != None:
                payload['startTime'] = startTime
            if endTime != None:
                payload['endTime'] = endTime
                       
            authReq = self._prepareAuthRequest(self.URL + '/api/v1/aggTrades', payload, reqType  = 'GET')  
            s = requests.Session()
            r = s.send(authReq)
            
            if r.status_code != 200:
                logger.error('Return code error in getAccountBalances: ' + str(r.status_code) + ';' + str(r.content))  
                return -1
            
            res = r.json()   
            logger.debug('get aggTrade executed: ' + str(res))
            return res
        else:
            return -1    
 def cancelOrder(self, orderID, symbol):
     """Returns a list of the orderIDs of the canceled orders."""
     rateLimitOK = self.rateLimits.update("ORDERS", 1)
     if rateLimitOK:
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         payload = {'symbol':symbol, 'orderId': orderID, 'timestamp': ts}            
         
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/order', payload, reqType  = 'DELETE')  
         s = requests.Session()
         r = s.send(authReq)
         
         if str(r.status_code)[0] == '4' or str(r.status_code)[0] == '5': 
             logger.debug('Return code error in cancelOrder: ' + str(r.status_code))  
             return -1
         
         res = r.json()   
         logger.info('Binance: Cancel order executed: ' + str(res))
         return [res['orderId']]
     else:
         return -1          
 def queryOrder(self, orderId, symbol):
     """Check an order's status.
     Example response:
     {
     "symbol": "LTCBTC",
     "orderId": 1,
     "clientOrderId": "myOrder1",
     "price": "0.1",
     "origQty": "1.0",
     "executedQty": "0.0",
     "status": "NEW",
     "timeInForce": "GTC",
     "type": "LIMIT",
     "side": "BUY",
     "stopPrice": "0.0",
     "icebergQty": "0.0",
     "time": 1499827319559,
     "isWorking": true
     }
     
     """
     rateLimitOK = self.rateLimits.update("ORDERS", 1)
     if rateLimitOK:
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         payload = {'symbol':symbol, 'orderId': orderId, 'timestamp': ts}            
         
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/order', payload, reqType  = 'GET')  
         s = requests.Session()
         r = s.send(authReq)
         
         if str(r.status_code)[0] == '4' or str(r.status_code)[0] == '5': 
             logger.debug('Return code error in queryOrder: ' + str(r.status_code))  
             return None
         
         res = r.json()  
         logger.info('Query order: ' + str(res))
         return res
     else:
         return None        
 def getAllOrders(self, symbol, orderId = None):
     """If orderId is set, it will get orders >= that orderId. Otherwise most recent orders are returned."""
     rateLimitOK = self.rateLimits.update("ORDERS", 5)
     if rateLimitOK:
         ts = int((getTimeStamp() + self.timeStampOffset) * 1000)
         
         payload = {'symbol':symbol, 'timestamp': ts}
         if orderId != None:
             payload['orderId'] = orderId
                 
         authReq = self._prepareAuthRequest(self.URL + '/api/v3/allOrders', payload, reqType = 'GET')  
         s = requests.Session()
         r = s.send(authReq)
         
         if r.status_code != 200:
             logger.error('Return code error in placeOrder: ' + str(r.status_code) + "  " + str(r.content))  
             return -1
         
         res = r.json()   
                    
         return res
     else:
         return -1        
 def processQuote(r):
     d = {'bidPrice': float(r['bidPrice']), 'bidQty': float(r['bidQty']), 'askPrice': float(r['askPrice']), 
          'askQty': float(r['askQty']),
          'timeStamp': getTimeStamp()}
     return r['symbol'], d