Gemini Trading Script

Posted on Mon 11 May 2020 in dev-journal

Created a short script today to make trades on the gemini platform. Simple, not DRY, and it works. One improvement I will probably make the next time I use this is to change the buy function to accept units of a currency other than dollar.

import requests
import json
import base64
import hmac
import hashlib
import datetime
import time
import decimal

base_url = "https://api.sandbox.gemini.com"


def get_current_price(currency):
    if currency == 'btc':
        symbol = 'btcusd'
        response = requests.get(base_url + "/v2/ticker/btcusd")
        btc_data = response.json()
        bid_price = btc_data["bid"]
        ask_price = btc_data["ask"]
    elif currency == 'bat':
        response = requests.get(base_url + "/v2/ticker/batusd")
        bat_data = response.json()
        bid_price = bat_data["bid"]
        ask_price = bat_data["ask"]
        symbol = 'batusd'
    elif currency == 'eth':
        response = requests.get(base_url + "/v2/ticker/ethusd")
        eth_data = response.json()
        bid_price = eth_data["bid"]
        ask_price = eth_data["ask"]
        symbol = 'ethusd'
    return bid_price, ask_price, symbol


def buy(dollars, currency="btc"):
    bid_price, ask_price, symbol = get_current_price(currency)
    t = datetime.datetime.now()
    payload_nonce = str(int(time.mktime(t.timetuple())*1000))
    decimal.getcontext().prec = 8
    dollars = decimal.Decimal(dollars)
    ap = decimal.Decimal(ask_price)
    amount = str(dollars / ap)
    amount = amount[:10]
    print(amount[:10])

    payload = {
        "request": "/v1/order/new",
        "nonce": payload_nonce,
        "symbol": symbol,
        "amount": amount,
        "price": ask_price,
        "side": "buy",
        "type": "exchange limit",
        "options": ["immediate-or-cancel"]
    }

    encoded_payload = json.dumps(payload).encode()
    b64 = base64.b64encode(encoded_payload)
    signature = hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()

    request_headers = {'Content-Type': "text/plain",
                       'Content-Length': "0",
                       'X-GEMINI-APIKEY': gemini_api_key,
                       'X-GEMINI-PAYLOAD': b64,
                       'X-GEMINI-SIGNATURE': signature,
                       'Cache-Control': "no-cache"}

    endpoint = "/v1/order/new"
    url = base_url + endpoint
    response = requests.post(url,
                             data=None,
                             headers=request_headers)

    new_order = response.json()
    print(new_order)


def sell(amount, currency='btc'):
    currency = currency.lower()
    bid_price, ask_price, symbol = get_current_price(currency)

    t = datetime.datetime.now()
    payload_nonce = str(int(time.mktime(t.timetuple())*1000))
    # amount = "0.020000"

    payload = {
        "request": "/v1/order/new",
        "nonce": payload_nonce,
        "symbol": symbol,
        "amount": amount,
        "price": bid_price,
        "side": "sell",
        "type": "exchange limit",
        "options": ["immediate-or-cancel"]
    }

    encoded_payload = json.dumps(payload).encode()
    b64 = base64.b64encode(encoded_payload)
    signature = hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()

    request_headers = {'Content-Type': "text/plain",
                       'Content-Length': "0",
                       'X-GEMINI-APIKEY': gemini_api_key,
                       'X-GEMINI-PAYLOAD': b64,
                       'X-GEMINI-SIGNATURE': signature,
                       'Cache-Control': "no-cache"}

    endpoint = "/v1/order/new"
    url = base_url + endpoint
    response = requests.post(url,
                             data=None,
                             headers=request_headers)
    new_order = response.json()
    print(new_order)


# Examples: 
# note: buy is in dollar amounts, sell uses currency unit

# buy $100 in bitcoin
buy(100)

# sell 1 Eth
sell(1, currency='eth')

# buy $100 of bat
buy(100, 'bat')