Пример #1
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()
Пример #2
0
    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)
            bidpricing.setvalue(rate)
Пример #3
0
# Configure price rise desired in decimal terms.
# For example, 20 basis points is '0.002'. This covers Gemini API trading fees round trip!
pair = 'YFIUSD'
size = '0.07765'
rise = '0.005'

# 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):
Пример #4
0
pair = 'BTCUSD'
size = '0.00001'
drop = '0.0076'
rise = '0.0078'

# Override defaults with command line parameters from BASH wrapper.
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):
Пример #5
0
# Wait for the price to drop.
last = decimaldrop(pair, drop)
if last:

    # Set bid size.
    size = '0.01'

    # Define trigger and stop loss prices. Redefine last for submission.
    last = Decimal(last * Decimal(0.999)).quantize(Decimal('1.00'))
    trip = Decimal(last * Decimal(0.999)).quantize(Decimal('1.00'))
    stop = Decimal(trip * Decimal(0.999)).quantize(Decimal('1.00'))

    post = makeliquidity(pair, size, str(last))
    post = post.json()
    dump = json.dumps(post, sort_keys=True, indent=4, separators=(',', ': '))
    logger.info(dump)

    # Determine if the order was filled.
    load = json.loads(dump)
    swap = load['order_id']
    fill = confirmexecution(swap)
    if fill:

        # Submit stop loss order.
        post = limitstop(pair, size, str(trip), str(stop))
        post = post.json()
        dump = json.dumps(post,
                          sort_keys=True,
                          indent=4,
                          separators=(',', ': '))
        logger.info(dump)
Пример #6
0
def askfall(pair: str, drop: str) -> None:

    # Define dataset class.
    # Purpose: Stores the offers received during the websocket connection session.
    dataset = []

    # Construct subscription request.
    subscriptionrequest = f'{{"type": "subscribe","subscriptions":[{{"name":"l2","symbols":["{pair}"]}}]}}'

    # Construct payload.
    request = resourcelocator.sockserver + '/v2/marketdata'
    nonce = int(time.time() * 1000)
    payload = {'request': request, 'nonce': nonce}
    authenticator.authenticate(payload)

    # Establish websocket connection.
    ws = create_connection(request)
    ws.send(subscriptionrequest)
    while True:
        newmessage = ws.recv()
        dictionary = json.loads(newmessage)
        percentoff = Decimal(drop)

        # Uncomment this statement to debug messages: logger.debug(dictionary)

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

                # Rank asks and determine the lowest ask among the changes in the Gemini L2 update response.
                askranking = [
                    Decimal(change[1]) for change in changes
                    if change[0] == 'sell'
                ]
                if askranking != []:
                    minimum = min(askranking)
                    dataset.append(minimum)

                    # Define session maximum and average values.
                    sessionmax = Decimal(max(dataset))
                    sessionavg = Decimal(statistics.mean(dataset))

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

                    # Determine how much the minimum deviates away from the session average.
                    # If it deviated by more than four standard deviations, then do nothing further.
                    # Continue at the start of the loop.
                    deviatedby = minimum - sessionavg
                    if len(dataset) != 1:
                        if deviatedby.compare(4 *
                                              statistics.stdev(dataset)) == 1:
                            logger.info(
                                f'{move:.2f}% off highs [{sessionmax}] : {pair} is {minimum} presently. Aberration... The mean is: {sessionavg:.2f}. Dumping!'
                            )
                            dataset.pop()
                            continue

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

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

                    # Exit loop and set "deal"...
                    # Only if there's a sale (bargain) offer.
                    if sale.compare(minimum) == 1:
                        text = f'{pair} fell {percentoff*100}% in price. '
                        text = text + f'It is now {minimum:.2f} on Gemini. '
                        text = text + f'{sale:.2f} is a deal.'
                        logger.info(text)
                        smsalert(text)
                        ws.close()
                        break

    # Return value on discount only.
    if minimum.compare(0) == 1: return minimum
    else: return False
Пример #7
0
 def on_error(ws, error):
     logger.info(error)
Пример #8
0
 def on_open(ws):
     logger.info(f'{ws} connection opened.')
Пример #9
0
 def on_close(ws):
     logger.info(f'{ws} connection closed.')
Пример #10
0
#!/usr/bin/env python3


# Strategy Outline:
#  1. Waiting for a drop in the ask offer for ETH.
#
# Execution:
#   - Copy this file from the strategies directory to the level below. Run with python3.

import json
import requests

from decimal import Decimal

from libraries.logger import logger
from libraries.dealseeker import askfall

pair = 'ETH-USDC'
drop = '0.03'

# Open websocket connection.
# Wait for asks to fall in price.
logger.info(f'waiting for {pair} to drop {Decimal(drop)*100}% in price.')
deal = askfall( pair, drop )
Пример #11
0
def askfall (
        pair: str,
        drop: str
        ) -> None:

    # Define high class.
    # Purpose: Stores the highest ask offer reached during the websocket connection session.
    class High:
        def __init__(self, price): self.__price = price
        def getvalue(self): return self.__price
        def setvalue(self, price): self.__price = price

    # Define deal class.
    # Purpose: Stores the deal (ask) offer reached during the websocket connection session.
    class Deal:
        def __init__(self, price): self.__price = price
        def getvalue(self): return self.__price
        def setvalue(self, price): self.__price = price

    # Instantiate high/deal objects.
    high = High(0)
    deal = Deal(0)

    # Construct subscription request.
    subscriptionrequest = f'{{ "type": "subscribe", "channels": [{{ "name": "orderbook", "marketIds": ["{pair}"]}}] }}'

    # Establish websocket connection.
    ws = create_connection(resourcelocator.sockserver)
    ws.send( subscriptionrequest )
    while True:
        newmessage = ws.recv()
        dictionary = json.loads( newmessage )
        percentoff = Decimal( drop )
        sessionmax = Decimal( high.getvalue() )

        # Unncomment this statement to debug messages: logger.debug(dictionary)

        # Process "type": "level2OrderbookSnapshot" messages.
        if 'level2OrderbookSnapshot' in dictionary['type']:
            if dictionary['asks'] != []:
                asks = dictionary['asks']

                # Rank bids and determine the highest bid in the orderbook from dYdX update response.
                askranking = [ Decimal(ask['price']) for ask in asks ]
                if askranking != []: minimumask = min(askranking)
                if minimumask.compare( Decimal(sessionmax) ) == 1 :
                        sessionmax = minimumask
                        high.setvalue(minimumask)

        # Process "type": "level2OrderbookUpdate" messages.
        if 'level2OrderbookUpdate' in dictionary['type']:
            if dictionary['changes'] != []:
                changes = dictionary['changes']

                # Rank bids and determine the highest bid in the orderbook from dYdX update response.
                askranking = [ Decimal(change['price']) for change in changes if change['side'] == 'sell' ]
                if askranking != []:
                    minimumask = min(askranking)
                    if minimumask.compare( Decimal(sessionmax) ) == 1 :
                            sessionmax = minimumask
                            high.setvalue(minimumask)

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

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

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

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

                        # Update deal price.
                        deal.setvalue(minimumask)
                        ws.close()
                        break

    # Return value on discount only.
    last = Decimal( deal.getvalue() )
    if last.compare(0) == 1 :
        return last
    else: return False
Пример #12
0
# This amount should exceed 20 cents ['0.00001' is the minimum for YFIUSD].
# Configure price drop desired in decimal terms.
# For example, 20 basis points is '0.002'. This covers Gemini API trading fees round trip!
pair = 'YFIUSD'
cash = '137.6'
drop = '0.005'

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

# 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
Пример #13
0
def bidrise(pair: str, gain: str) -> None:

    # Define base class.
    # Purpose: Stores the first best bid offer of the websocket connection session.
    class Base:
        def __init__(self, price):
            self.__price = price

        def getvalue(self):
            return self.__price

        def setvalue(self, price):
            self.__price = price

    # Instantiate base object.
    base = Base(0)

    # Construct subscription request.
    subscriptionrequest = f'{{ "type": "subscribe", "channels": [{{ "name": "orderbook", "marketIds": ["{pair}"]}}] }}'

    # Establish websocket connection.
    ws = create_connection(resourcelocator.sockserver)
    ws.send(subscriptionrequest)
    while True:
        newmessage = ws.recv()
        dictionary = json.loads(newmessage)
        profitable = Decimal(gain)

        # Unncomment this statement to debug messages: logger.debug(dictionary)

        # Process "type": "level2OrderbookSnapshot" messages.
        if 'level2OrderbookSnapshot' in dictionary['type']:
            if dictionary['bids'] != []:
                bids = dictionary['bids']

                # Rank bids and determine the highest bid in the orderbook from dYdX update response.
                bidranking = [Decimal(bid['price']) for bid in bids]
                if bidranking != []: maximumbid = max(bidranking)
                base.setvalue(maximumbid)

                # Define bargain (sale) bid offer.
                deal = Decimal(Decimal(base.getvalue()) * (1 + profitable))

        # Process "type": "level2OrderbookUpdate" messages.
        if 'level2OrderbookUpdate' in dictionary['type']:
            if dictionary['changes'] != []:
                changes = dictionary['changes']

                # Rank bids and determine the highest bid in the orderbook from dYdX update response.
                bidranking = [
                    Decimal(change['price']) for change in changes
                    if change['side'] == 'buy'
                ]
                if bidranking != []:
                    maximumbid = max(bidranking)
                    if maximumbid.compare(deal) == 1:
                        logger.info(
                            f'{pair} [now {maximumbid:.2f}] just rose above {deal:.2f}.'
                        )
                        smsalert(
                            f'There was a {profitable*100}% rise in the bid offer [{maximumbid}] on the {pair} pair on DDEX.'
                        )
                        ws.close()
                        break

                    else:
                        # Calculate movement away from base [if any].
                        move = 100 * (maximumbid -
                                      base.getvalue()) / base.getvalue()

                        # Display impact of event information received.
                        logger.info(
                            f'{move:.2f}% move away from [{base.getvalue()}] : {pair} is {maximumbid} presently.'
                        )

    # Return value on discount only.
    if maximumbid.compare(0) == 1:
        return maximumbid
    else:
        return False
Пример #14
0
def bidrise(pair: str, rise: str) -> None:

    # Define dataset class.
    # Purpose: Stores the offers received during the websocket connection session.
    dataset = []

    # Construct subscription request.
    subscriptionrequest = f'{{"type": "subscribe","subscriptions":[{{"name":"l2","symbols":["{pair}"]}}]}}'

    # Construct payload.
    request = resourcelocator.sockserver + '/v2/marketdata'
    nonce = int(time.time() * 1000)
    payload = {'request': request, 'nonce': nonce}
    authenticator.authenticate(payload)

    # Establish websocket connection.
    ws = create_connection(request)
    ws.send(subscriptionrequest)
    while True:
        newmessage = ws.recv()
        dictionary = json.loads(newmessage)
        grossmargin = Decimal(rise)

        # Uncomment this statement to debug messages: logger.debug(dictionary)

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

                # Rank bids and determine the highest bid among the changes in the Gemini L2 update response.
                bidranking = [
                    Decimal(change[1]) for change in changes
                    if change[0] == 'buy'
                ]
                if bidranking != []:
                    maximum = max(bidranking)
                    dataset.append(maximum)

                    # Define session minimum and average values.
                    sessionmin = Decimal(min(dataset))
                    sessionavg = Decimal(statistics.mean(dataset))

                    # Calculate movement away from cost [if any].
                    move = 100 * (maximum - sessionmin) / sessionmin

                    # Determine how much the maximum deviates away from the session average.
                    # If it deviated by more than four standard deviations, then do nothing further.
                    # Continue at the start of the loop.
                    deviatedby = maximum - sessionavg
                    if len(dataset) != 1:
                        if deviatedby.compare(4 *
                                              statistics.stdev(dataset)) == 1:
                            logger.info(
                                f'{move:.2f}% off lows [{sessionmin}] : {pair} is {maximum} presently. Aberration... The mean is: {sessionavg:.2f}. Dumping!'
                            )
                            dataset.pop()
                            continue

                    # Display impact of event information received.
                    logger.info(
                        f'{move:.2f}% off lows [{sessionmin}] : {pair} is {maximum} presently.'
                    )

                    # Define profitable (rent) price.
                    rent = Decimal(sessionmin * (1 + grossmargin))

                    # Exit loop if profitable.
                    # Return maximum bid.
                    if maximum.compare(rent) == 1:
                        text = f'{pair} rose {grossmargin*100}% in price. '
                        text = text + f'It is now {maximum:.2f} on Gemini. '
                        text = text + f'Selling above {rent:.2f} is profitable.'
                        logger.info(text)
                        smsalert(text)
                        ws.close()
                        break

    # Return value when profitable only.
    if maximum.compare(0) == 1: return maximum
    else: return False