Example #1
0
def smsalert(message):
    # Send message via SMS.
    snsresponse = snsclient.publish(PhoneNumber='+15108045618',
                                    Message=message)
    responseout = json.dumps(snsresponse,
                             sort_keys=True,
                             indent=4,
                             separators=(',', ': '))
    logger.debug(f'Response to SNS Request:\n{responseout}')
Example #2
0
def quotabid(pair: str, cash: str, cost: str) -> None:

    # Determine API transaction fee.
    # Refer to https://docs.gemini.com/rest-api/#basis-point.
    # Fees are calculated on the notional value of each trade (price × size).
    # Meaning (for API transactions): size * price * 1.001 = cash
    fraction = Decimal(constants.apitransactionfee)
    notional = Decimal(cash) / Decimal(1 + fraction)

    # Determine minimum order size (let's call it a tock).
    list = constants.minimumorders
    item = [
        item['minimumorder'] for item in list if item['currency'] == pair[:3]
    ]
    tock = Decimal(item[0])

    # Determine bid size.
    quantity = str(Decimal(notional / Decimal(cost)).quantize(tock))
    bidprice = str(cost)

    # Update logs.
    logger.debug(f'bidprice: {bidprice}')
    logger.debug(f'quantity: {quantity}')

    # Construct buy order payload.
    # Use 'options': ['maker-or-cancel'] for post only orders.
    endpoint = '/v1/order/new'
    t = datetime.datetime.now()
    payload = {
        'request': endpoint,
        'nonce': str(int(time.mktime(t.timetuple()) * 1000)),
        'symbol': pair,
        'amount': quantity,
        'price': bidprice,
        'side': 'buy',
        'type': 'exchange limit',
        'options': ['maker-or-cancel']
    }
    headers = authenticator.authenticate(payload)

    request = resourcelocator.restserver + endpoint
    response = requests.post(request, data=None, headers=headers['restheader'])

    return response
Example #3
0
    def on_message(ws, message, drop=drop, pair=pair, high=high, deal=deal):
        dictionary = json.loads(message)
        percentoff = Decimal(drop)
        sessionmax = Decimal(high.getvalue())
        # Uncomment this statement to debug messages:
        logger.debug(dictionary)

        # Process "type": "update" messages with events only.
        if 'update' in dictionary['type']:
            if dictionary['events'] != []:
                events = dictionary['events']

                # Process "type": "trade" events for latest price.
                for event in events:
                    if event['type'] == 'trade': last = Decimal(event["price"])
                    if last.compare(Decimal(sessionmax)) == 1:
                        sessionmax = last
                        high.setvalue(last)

                    # Calculate movement away from high [if any].
                    move = 100 * (sessionmax - last) / sessionmax

                    # Display impact of event information received.
                    logger.info(
                        f'{move:.2f}% off highs [{sessionmax}] : {pair} is {last} presently : [Message ID: {dictionary["socket_sequence"]}].'
                    )

                    # Define bargain (sale) price.
                    sale = Decimal(sessionmax * (1 - percentoff))

                    # Exit loop if there's a sale.
                    if sale.compare(last) == 1:
                        logger.info(
                            f'{pair} [now {last:.2f}] just went on sale [dropped below {sale:.2f}].'
                        )
                        smsalert(
                            f'There was a {percentoff*100}% drop in the price of the {pair} pair on Gemini.'
                        )

                        # Update deal price.
                        deal.setvalue(last)
                        ws.close()
Example #4
0
def quotabid(
        pair: str,
        cash: str,
    ) -> None:

    # Determine API transaction fee.
    # Refer to https://docs.gemini.com/rest-api/#basis-point.
    # Fees are calculated on the notional value of each trade (price × size).
    # Meaning (for API transactions): size * price * 1.001 = cash
    fraction = Decimal( constants.apitransactionfee )
    notional = Decimal(cash) / Decimal( 1 + fraction )

    # Determine tick size.
    list = constants.ticksizes
    item = [ item['tick'] for item in list if item['currency'] == pair[:3] ]
    tick = Decimal( item[0] )

    # Determine quantity size.
    list = constants.minimumquantities
    item = [ item['minimumquantity'] for item in list if item['currency'] == pair[:3] ]
    bump = Decimal( item[0] )

    # Get the highest bid in the orderbook.
    # Make an offer that's one tick better.
    # Then determine the bid order size.
    endpoint = '/v1/pubticker/' + pair
    response = requests.get( resourcelocator.restserver + endpoint )
    bidprice = Decimal( response.json()['bid'] )
    offering = str( Decimal( bidprice + tick ).quantize( tick ) )
    quantity = str( Decimal( notional / Decimal(offering) ).quantize( bump ) )

    # Update logs.
    logger.debug(f'bidprice: {bidprice}')
    logger.debug(f'offering: {offering}')
    logger.debug(f'quantity: {quantity}')

    # Construct buy order payload.
    # Use 'options': ['maker-or-cancel'] for post only orders.
    endpoint = '/v1/order/new'
    t = datetime.datetime.now()
    payload = {
        'request': endpoint,
        'nonce': str(int(time.mktime(t.timetuple())*1000)),
        'symbol': pair,
        'amount': quantity,
        'price': offering,
        'side': 'buy',
        'type': 'exchange limit',
        'options': ['maker-or-cancel']
    }
    headers = authenticator.authenticate(payload)

    request = resourcelocator.restserver + endpoint
    response = requests.post(request, data = None, headers = headers['restheader'])

    return response
Example #5
0
def bidorder(
        pair: str,
        size: str,
    ) -> None:

    # Determine tick size.
    list = constants.ticksizes
    item = [ item['tick'] for item in list if item['currency'] == pair[:3] ]
    tick = Decimal( item[0] )

    # Determine quantity size.
    list = constants.minimumquantities
    item = [ item['minimumquantity'] for item in list if item['currency'] == pair[:3] ]
    bump = Decimal( item[0] )

    # Get the highest bid in the orderbook.
    # Make an offer that's one tick better.
    endpoint = '/v1/pubticker/' + pair
    response = requests.get( resourcelocator.restserver + endpoint )
    bidprice = Decimal( response.json()['bid'] )
    offering = str( Decimal( bidprice + tick ).quantize( tick ) )
    quantity = str( Decimal( size ).quantize( bump ) )

    # Update logs.
    logger.debug(f'bidprice: {bidprice}')
    logger.debug(f'offering: {offering}')
    logger.debug(f'quantity: {quantity}')

    # Construct buy order payload.
    # Use 'options': ['maker-or-cancel'] for post only orders.
    endpoint = '/v1/order/new'
    t = datetime.datetime.now()
    payload = {
        'request': endpoint,
        'nonce': str(int(time.mktime(t.timetuple())*1000)),
        'symbol': pair,
        'amount': quantity,
        'price': offering,
        'side': 'buy',
        'type': 'exchange limit',
        'options': ['maker-or-cancel']
    }
    headers = authenticator.authenticate(payload)

    request = resourcelocator.restserver + endpoint
    response = requests.post(request, data = None, headers = headers['restheader'])

    return response
Example #6
0
# Override defaults with command line parameters.
if len(sys.argv) == 4:
    pair = sys.argv[1]
    size = sys.argv[2]
    rise = sys.argv[3]

# Open websocket connection.
# Wait for bids to rise in price.
logger.info(
    f'waiting for {pair} to rise {Decimal(rise)*100}% in price to sell {size} {pair[3:]} worth..'
)
deal = bidrise(pair, rise)
if deal:

    # Submit limit ask order.
    logger.debug(f'submitting {pair} frontrunning limit ask order.')
    post = askorder(pair, size)
    post = post.json()
    dump = json.dumps(post, sort_keys=True, indent=4, separators=(',', ': '))
    logger.debug(dump)

    # Define poststatus class.
    # Purpose: Stores the state of the orderid parameter upon exiting the websocket connection session.
    class Poststatus:
        def __init__(self, state):
            self.__state = state

        def getvalue(self):
            return self.__state

        def setvalue(self, state):
Example #7
0
# Set the pair.
# Set quote currency (USD in this case) budget.
# Set your price reservation.
pair = 'DAIUSD'
cash = '100'
cost = '1.00913'

# Override defaults with command line parameters from BASH wrapper.
if len(sys.argv) == 4:
    pair = sys.argv[1]
    cash = sys.argv[2]
    cost = sys.argv[3]

# Submit limit ask order.
logger.debug(
    f'submitting {pair} limit ask order: {cost} ask on a {cost} budget.')
post = quotaask(pair, cash, cost)
post = post.json()
dump = json.dumps(post, sort_keys=True, indent=4, separators=(',', ': '))
logger.debug(dump)


# Define poststatus class.
# Purpose: Stores the state of the orderid parameter upon exiting the websocket connection session.
class Poststatus:
    def __init__(self, state):
        self.__state = state

    def getvalue(self):
        return self.__state
Example #8
0
if len(sys.argv) == 5:
    pair = sys.argv[1]
    size = sys.argv[2]
    drop = sys.argv[3]
    rise = sys.argv[4]

# Open websocket connection.
# Wait for asks to fall in price.
logger.info(
    f'waiting for {pair} to drop {Decimal(drop)*100}% in price to buy {size} {pair[:3]}..'
)
deal = askfall(pair, drop)
if deal:

    # Submit limit bid order.
    logger.debug(f'submitting {pair} frontrunning limit bid order.')
    post = bidorder(pair, size)
    post = post.json()
    dump = json.dumps(post, sort_keys=True, indent=4, separators=(',', ': '))
    logger.debug(dump)

    # Define poststatus class.
    # Purpose: Stores the state of the orderid parameter upon exiting the websocket connection session.
    class Poststatus:
        def __init__(self, state):
            self.__state = state

        def getvalue(self):
            return self.__state

        def setvalue(self, state):
from libraries.logger import logger
from libraries.spreadkiller import askorder
from libraries.fillvalidator import confirmexecution


# Set bid size ['0.1' is the minimum for DAIUSD].
pair = 'DAIUSD'
size = '0.1'

# Override defaults with command line parameters.
if len(sys.argv) == 3:
    pair = sys.argv[1]
    size = sys.argv[2]

# Submit limit bid order.
logger.debug(f'submitting {pair} aggressive limit bid order.')
post = askorder( pair, size )
post = post.json()
dump = json.dumps( post, sort_keys=True, indent=4, separators=(',', ': ') )
logger.debug ( dump )

# Define poststatus class.
# Purpose: Stores the state of the orderid parameter upon exiting the websocket connection session.
class Poststatus:
    def __init__(self, state): self.__state = state
    def getvalue(self): return self.__state
    def setvalue(self, state): self.__state = state

poststatus = Poststatus('')

# Determine if the order was filled.
Example #10
0
 def on_error(ws, error):
     logger.debug(error)
Example #11
0
 def on_open(ws):
     logger.debug(f'{ws} connection opened.')
Example #12
0
 def on_close(ws):
     logger.debug(f'{ws} connection closed.')
Example #13
0
def confirmexecution(orderid: str, poststatus: object) -> None:

    # Introduce function.
    logger.debug(
        f'Confirming execution of the order identified by the Gemini assigned number: {orderid}'
    )

    # Define websocket functions.
    def on_close(ws):
        logger.debug(f'{ws} connection closed.')

    def on_open(ws):
        logger.debug(f'{ws} connection opened.')

    def on_error(ws, error):
        logger.debug(error)

    def on_message(ws, message, orderid=orderid):
        dictionary = json.loads(message)
        exitstatus = ''

        # Remove comment to debug with: logger.debug( dictionary )

        # Check if this is an 'initial' message from Gemini.
        # It is actually the second message. The subscription acknowledgement is first.
        if dictionary == []: exitstatus = f'Order {orderid} not active.'

        if isinstance(dictionary, list):
            for listitem in dictionary:
                size = listitem['original_amount']
                pair = listitem['symbol'].upper()
                rate = listitem['price']
                side = listitem['side']
                cost = Decimal(size) * Decimal(rate)
                bit0 = f'{pair} {side} order {orderid} valued at '
                bit1 = f'{cost.quantize( Decimal(rate) )} {pair[3:].upper()} '
                bit2 = f'[{size} {pair[:3].upper()} at {rate} {pair[3:].upper()}] was '
                text = f'{bit0}{bit1}{bit2}'
                if listitem['order_id'] == orderid:
                    # Exit upon receiving order cancellation message.
                    if listitem['is_cancelled']:
                        exitstatus = f'{text} cancelled.'
                    if listitem['type'] == 'cancelled':
                        exitstatus = f'{text} cancelled [reason:{listitem["reason"]}].'
                    if listitem['type'] == 'rejected':
                        exitstatus = f'{text} rejected.'
                    if listitem['type'] == 'fill':
                        # Make sure that the order was completely filled.
                        if listitem['remaining_amount'] == '0':
                            exitstatus = f'{text} filled.'
        if exitstatus:
            ws.close()
            logger.info(exitstatus)
            smsalert(exitstatus)
            poststatus.setvalue(exitstatus)

    # Construct payload.
    endpoint = '/v1/order/events'
    nonce = int(time.time() * 1000)
    payload = {'request': endpoint, 'nonce': nonce}
    header = authenticator.authenticate(payload)

    # Establish websocket connection.
    logger.debug(
        f'Establishing websocket connection to confirm the execution of order number {orderid}.'
    )
    ws = websocket.WebSocketApp(str(resourcelocator.sockserver + endpoint),
                                on_open=on_open,
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close,
                                header=header['sockheader'])
    ws.run_forever(sslopt={'cert_reqs': ssl.CERT_NONE})
import requests
import locale

from libraries.logger import logger
from libraries.volumizer import notionalvolume


# Set default field value.
field = ''

# Override defaults with command line parameters.
if len(sys.argv) == 2:
    field = sys.argv[1]

# Submit request.
logger.debug(f'submitting request...')
post = notionalvolume()
data = post.json()
dump = json.dumps( data, sort_keys=True, indent=4, separators=(',', ': ') )


# Format response.
if field:
    if field == 'notional_30d_volume': print( f'your notional 30-day volume is {post.json()["notional_30d_volume"]:,} USD.' )
    if field == 'api_maker_fee_bps': print( f'the fee that Gemini is charging you for making orders via the API is {post.json()["api_maker_fee_bps"]} basis points.' )

logger.debug ( dump )


# Let the shell know we successfully made it this far!
if post: sys.exit(0)
if len(sys.argv) == 5:
    pair = sys.argv[1]
    cash = sys.argv[2]
    drop = sys.argv[3]
    rise = sys.argv[4]

# Open websocket connection.
# Wait for asks to fall in price.
logger.info(
    f'waiting for {pair} to drop {Decimal(drop)*100}% in price to buy {cash} {pair[3:]} worth..'
)
deal = askfall(pair, drop)
if deal:

    # Submit limit bid order.
    logger.debug(f'submitting {pair} frontrunning limit bid order.')
    post = quotabid(pair, cash)
    post = post.json()
    dump = json.dumps(post, sort_keys=True, indent=4, separators=(',', ': '))
    logger.debug(dump)

    # Define poststatus class.
    # Purpose: Stores the state of the orderid parameter upon exiting the websocket connection session.
    class Poststatus:
        def __init__(self, state):
            self.__state = state

        def getvalue(self):
            return self.__state

        def setvalue(self, state):