Esempio n. 1
0
class api(object):
    def __init__(self,
                 key='',
                 secret=''):
        self.url = 'https://api.cryptsy.com/api'
        self.key = key
        self.secret = secret
        self.markets = None
        self.rate_limiter = TokenBucket(RATE)
        random.seed(time.time())

    def __query(self, method, params={}):
        req = params
        req['method'] = method
        req['nonce'] = int(time.time())
        data = urllib.urlencode(req)
        sign = hmac.new(self.secret, data, hashlib.sha512).hexdigest()
        headers = {
            'Sign': sign,
            'Key': self.key
        }

        while not self.rate_limiter.may_i():
            time.sleep(random.uniform(0.5, 3.0))

        r = requests.post(self.url, data=data, headers=headers)
        if r.status_code == 200:
            c = json.loads(r.content)
            if c['success'] == u'1':
                if method == 'createorder':
                    return c['orderid']
                return c['return']
            else:
                log.error('Error calling %s(%s) on %s', method, params, self.url)
                log.error(c)
                log.error(c['error'])
        else:
            log.error('Error calling %s(%s) on %s', method, params, self.url)
        return None

    def getinfo(self):
        """
        Outputs:
            balances_available  Array of currencies and the balances availalbe for each
            balances_hold       Array of currencies and the amounts currently on hold for open orders
            servertimestamp     Current server timestamp
            servertimezone      Current timezone for the server
            serverdatetime      Current date/time on the server
            openordercount      Count of open orders on your account
        """
        return self.__query('getinfo')

    def getmarkets(self):
        """
        Outputs: Array of Active Markets
            marketid                Integer value representing a market
            label                   Name for this market, for example: AMC/BTC
            primary_currency_code   Primary currency code, for example: AMC
            primary_currency_name   Primary currency name, for example: AmericanCoin
            secondary_currency_code Secondary currency code, for example: BTC
            secondary_currency_name Secondary currency name, for example: BitCoin
            current_volume          24 hour trading volume in this market
            last_trade              Last trade price for this market
            high_trade              24 hour highest trade price in this market
            low_trade               24 hour lowest trade price in this market
            created                 Datetime (EST) the market was created
        """
        return self.__query('getmarkets')

    def getwalletstatus(self):
        """
        Outputs: Array of Wallet Statuses
            currencyid      Integer value representing a currency
            name            Name for this currency, for example: Bitcoin
            code            Currency code, for example: BTC
            blockcount      Blockcount of currency hot wallet as of lastupdate time
            difficulty      Difficulty of currency hot wallet as of lastupdate time
            version         Version of currency hotwallet as of lastupdate time
            peercount       Connected peers of currency hot wallet as of lastupdate time
            hashrate        Network hashrate of currency hot wallet as of lastupdate time
            gitrepo         Git Repo URL for this currency
            withdrawalfee   Fee charged for withdrawals of this currency
            lastupdate      Datetime (EST) the hot wallet information was last updated
        """
        return self.__query('getwalletstatus')

    def mytransactions(self):
        """
        Outputs: Array of Deposits and Withdrawals on your account
            currency    Name of currency account
            timestamp   The timestamp the activity posted
            datetime    The datetime the activity posted
            timezone    Server timezone
            type        Type of activity. (Deposit / Withdrawal)
            address     Address to which the deposit posted or Withdrawal was sent
            amount      Amount of transaction (Not including any fees)
            fee Fee     (If any) Charged for this Transaction (Generally only on Withdrawals)
            trxid       Network Transaction ID (If available)
        """
        return self.__query('mytransactions')

    def markettrades(self, marketid):
        """
        Inputs:
            marketid            Market ID for which you are querying

        Outputs: Array of last 1000 Trades for this Market, in Date Decending Order
            tradeid             A unique ID for the trade
            datetime            Server datetime trade occurred
            tradeprice          The price the trade occurred at
            quantity            Quantity traded
            total               Total value of trade (tradeprice * quantity)
            initiate_ordertype  The type of order which initiated this trade
        """
        return self.__query('markettrades', params={'marketid': marketid})

    def marketorders(self, marketid):
        """
        Inputs:
            marketid    Market ID for which you are querying


        Outputs: 2 Arrays. First array is sellorders listing current open sell orders ordered price ascending.
            Second array is buyorders listing current open buy orders ordered price descending.
            sellprice   If a sell order, price which order is selling at
            buyprice    If a buy order, price the order is buying at
            quantity    Quantity on order
            total       Total value of order (price * quantity)
        """
        return self.__query('marketorders', params={'marketid': marketid})

    def mytrades(self, marketid, limit=200):
        """

        Inputs:
            marketid    Market ID for which you are querying
            limit       (optional) Limit the number of results. Default: 200

        Outputs: Array your Trades for this Market, in Date Decending Order
            tradeid             An integer identifier for this trade
            tradetype           Type of trade (Buy/Sell)
            datetime            Server datetime trade occurred
            tradeprice          The price the trade occurred at
            quantity            Quantity traded
            total               Total value of trade (tradeprice * quantity) - Does not include fees
            fee                 Fee Charged for this Trade
            initiate_ordertype  The type of order which initiated this trade
            order_id            Original order id this trade was executed against
        """
        return self.__query('marketorders', params={'marketid': marketid, 'limit': limit})

    def allmytrades(self, startdate, enddate):
        """

        Inputs:
            startdate   (optional) Starting date for query (format: yyyy-mm-dd)
            enddate     (optional) Ending date for query (format: yyyy-mm-dd)

        Outputs: Array your Trades for all Markets, in Date Decending Order
            tradeid             An integer identifier for this trade
            tradetype           Type of trade (Buy/Sell)
            datetime            Server datetime trade occurred
            marketid            The market in which the trade occurred
            tradeprice          The price the trade occurred at
            quantity            Quantity traded
            total               Total value of trade (tradeprice * quantity) - Does not include fees
            fee                 Fee Charged for this Trade
            initiate_ordertype  The type of order which initiated this trade
            order_id            Original order id this trade was executed against
        """
        return self.__query('allmytrades',
                            params={'startdate': startdate, 'enddate': enddate})

    def myorders(self, marketid):
        """
        Inputs:
            marketid    Market ID for which you are querying

        Outputs: Array of your orders for this market listing your current open sell and buy orders.
            orderid         Order ID for this order
            created         Datetime the order was created
            ordertype       Type of order (Buy/Sell)
            price           The price per unit for this order
            quantity        Quantity remaining for this order
            total           Total value of order (price * quantity)
            orig_quantity   Original Total Order Quantity
        """
        return self.__query('myorders', params={'marketid': marketid})

    def depth(self, marketid):
        """
        Inputs:
            marketid    Market ID for which you are querying

        Outputs: Array of buy and sell orders on the market representing market depth.
            Output Format is:
            array(
              'sell'=>array(
                array(price,quantity),
                array(price,quantity),
                ....
              ),
              'buy'=>array(
                array(price,quantity),
                array(price,quantity),
                ....
              )
            )
        """
        return self.__query('depth', params={'marketid': marketid})

    def allmyorders(self):
        """
        Outputs: Array of all open orders for your account.
        orderid         Order ID for this order
        marketid        The Market ID this order was created for
        created         Datetime the order was created
        ordertype       Type of order (Buy/Sell)
        price           The price per unit for this order
        quantity        Quantity remaining for this order
        total           Total value of order (price * quantity)
        orig_quantity   Original Total Order Quantity
        """
        return self.__query('allmyorders')

    def createorder(self, marketid, ordertype, quantity, price):
        """
        Inputs:
            marketid    Market ID for which you are creating an order for
            ordertype   Order type you are creating (Buy/Sell)
            quantity    Amount of units you are buying/selling in this order
            price       Price per unit you are buying/selling at

        Outputs:
            orderid     If successful, the Order ID for the order which was created
        """
        return self.__query('createorder',
                            params={
                                'marketid': marketid,
                                'ordertype': ordertype,
                                'quantity': quantity,
                                'price': price
                            }
                            )

    def cancelorder(self, orderid):
        """
        Inputs:
            orderid Order ID for which you would like to cancel
        """
        return self.__query('cancelorder', params={'orderid': orderid})

    def cancelmarketorders(self, marketid):
        """
        Inputs:
            marketid    Market ID for which you would like to cancel all open orders

        Outputs:
            return      Array for return information on each order cancelled
        """
        return self.__query('cancelmarketorders', params={'marketid': marketid})

    def cancelallorders(self):
        """
        Inputs: N/A

        Outputs:
            return  Array for return information on each order cancelled
        """
        return self.__query('cancelallorders')

    def calculatefees(self, ordertype, quantity, price):
        """
        Inputs:
            ordertype   Order type you are calculating for (Buy/Sell)
            quantity    Amount of units you are buying/selling
            price       Price per unit you are buying/selling at

        Outputs:
            fee         The that would be charged for provided inputs
            net         The net total with fees
        """
        return self.__query('calculatefees',
                            params={'ordertype': ordertype,
                                    'quantity': quantity,
                                    'price': price
                                    })

    def generatenewaddress(self, currencyid, currencycode):
        """
        Inputs: (either currencyid OR currencycode required - you do not have to supply both)
            currencyid      Currency ID for the coin you want to generate a new address for (ie. 3 = BitCoin)
            currencycode    Currency Code for the coin you want to generate a new address for (ie. BTC = BitCoin)

        Outputs:
            address         The new generated address
        """
        return self.__query('generatewalletaddress',
                            params={'currencyid': currencyid,
                                    'currencycode': currencycode,
                                    })

    def mytransfers(self):
        """
        Inputs: n/a

        Outputs: Array of all transfers into/out of your account sorted by requested datetime descending.
            currency            Currency being transfered
            request_timestamp   Datetime the transfer was requested/initiated
            processed           Indicator if transfer has been processed (1) or not (0)
            processed_timestamp Datetime of processed transfer
            from                Username sending transfer
            to                  Username receiving transfer
            quantity            Quantity being transfered
            direction           Indicates if transfer is incoming or outgoing (in/out)
        """
        return self.__query('mytransfers')

    def makewithdrawal(self, address, amount):
        """
        Inputs:
            address Pre-approved Address for which you are withdrawing to (Set up these addresses on Settings page)
            amount  Amount you are withdrawing. Supports up to 8 decimal places.

        Outputs:
            Either successful or error. If error, gives reason for error.
        """
        return self.__query('makewithdrawal', params={'address': address, 'amount': amount})

    def getmydepositaddresses(self):
        """
        Inputs: n/a

        Outputs:
            return  Array for return information on each order cancelled ("coincode" => "despositaddress")
        """
        return self.__query('getmydepositaddresses')

    def getorderstatus(self, orderid):
        """
        Inputs:
            orderid     Order ID for which you are querying

        Outputs:

            tradeinfo is a list of all the trades that have occured in your order.
            Where orderinfo shows realtime status of the order.
            Orderinfo contains the 'active'; a boolean object showing if the order is still open.
            Orderinfo also contains 'remainqty' which shows the quantity left in your order.

            tradeinfo   A list of all trades that have occuried in your order.
            orderinfo   Information regarding status of the order. Contains 'active' and 'remainqty' keys.
        """
        return self.__query('getorderstatus', params={'orderid': orderid})

    def ex_coin_rev(self, buy_symbol, sell_symbol, sell_volume):
        orderids = []
        log.info('selling %.8f %s for %s',
                 sell_volume, sell_symbol, buy_symbol)
        if not self.markets:
            self.markets = self.getmarkets()

        market_id = ''
        for market in self.markets:
            if market['primary_currency_code'] == buy_symbol and \
                    market['secondary_currency_code'] == sell_symbol:
                log.info(market)
                market_id = market['marketid']
                break
        assert(market_id)

        # get buy orders for ltc
        depth = self.depth(market_id)
        bought = 0.0
        remaining_sell_volume = sell_volume
        for order in depth['sell']:
            log.debug(order)
            order_volume_to_sell = float(order[1])
            order_price_per_coin = float(order[0])
            total_price = order_volume_to_sell * order_price_per_coin
            log.debug('Order %.8f %s for %.8f per coin',
                      order_volume_to_sell, sell_symbol, order_price_per_coin)
            if remaining_sell_volume < total_price:
                order_volume_to_sell = remaining_sell_volume / order_price_per_coin
            #fees = float(self.calculatefees('Sell', order_volume_to_sell, order_price_per_coin)['fee'])
            # TODO
            fees = order_volume_to_sell * order_price_per_coin * 0.002
            log.debug('We buy %.8f %s for %.8f per coin (total btc %0.8f)',
                      order_volume_to_sell, buy_symbol, order_price_per_coin,
                      order_volume_to_sell * order_price_per_coin)
            orderid = self.createorder(market_id, 'Buy', order_volume_to_sell, order_price_per_coin)
            if not orderid:
                log.error('could not set order')
            else:
                orderids.append(orderid)
            bought += order_volume_to_sell - fees
            remaining_sell_volume -= total_price
            if remaining_sell_volume <= 0:
                break
        #return (bought, remaining_sell_volume)
        return orderids

    def ex_coin(self, buy_symbol, sell_symbol, sell_volume):
        orderids = []
        log.info('selling %.8f %s for %s',
                 sell_volume, sell_symbol, buy_symbol)
        if not self.markets:
            self.markets = self.getmarkets()

        market_id = ''
        for market in self.markets:
            if market['primary_currency_code'] == sell_symbol and \
                    market['secondary_currency_code'] == buy_symbol:
                log.info(market)
                market_id = market['marketid']
                break
        assert(market_id)

        # get buy orders for ltc
        depth = self.depth(market_id)
        bought = 0.0
        remaining_sell_volume = sell_volume
        for order in depth['buy']:
            log.debug(order)
            order_volume_to_sell = float(order[1])
            order_price_per_coin = float(order[0])
            log.debug('Order %f %s for %f per coin',
                      order_volume_to_sell, sell_symbol, order_price_per_coin)
            if remaining_sell_volume < order_volume_to_sell:
                order_volume_to_sell = remaining_sell_volume
            #fees = float(self.calculatefees('Sell', order_volume_to_sell, order_price_per_coin)['fee'])
            # TODO
            fees = order_volume_to_sell * order_price_per_coin * 0.002
            orderid = self.createorder(market_id, 'Sell', order_volume_to_sell, order_price_per_coin)
            if not orderid:
                log.error('could not set order')
            else:
                orderids.append(orderid)

            bought += order_volume_to_sell * order_price_per_coin - fees
            remaining_sell_volume -= order_volume_to_sell
            if remaining_sell_volume <= 0:
                break
        #return (bought, remaining_sell_volume)
        return orderids