OKX Ticker

Show price ticker from OKX. Currencies can be configured.

Image preview of OKX Ticker plugin.

okx_ticker.10s.py

Edit
Open on GitHub
#!/usr/bin/env python3
# coding: utf-8
# yc@2021/06/30

# <xbar.title>OKX Ticker</xbar.title>
# <xbar.version>v1.0</xbar.version>
# <xbar.author>yc</xbar.author>
# <xbar.author.github>ichuan</xbar.author.github>
# <xbar.desc>Show price ticker from OKX. Currencies can be configured.</xbar.desc>
# <xbar.image>https://i.imgur.com/mykIv6O.png</xbar.image>
# <xbar.dependencies>python</xbar.dependencies>
# <xbar.abouturl>https://www.okx.com/about.html</xbar.abouturl>
# <xbar.var>string(VAR_CURRENCIES="btc,eth"): Currencies, separated with comma.</xbar.var>
# <xbar.var>string(VAR_FONT_NAME=""): Font name.</xbar.var>

import re
import os
import json
from datetime import datetime
from decimal import Decimal
from urllib.request import urlopen, Request


HTTP_TIMEOUT = 10
DEFAULT_CURRENCIES = "btc,eth"


def normalize_decimal(val, precision=2):
    if type(val) is not Decimal:
        val = Decimal(val)
    mul = pow(10, precision)
    val = Decimal(int(val * mul)) / mul
    return format(val.normalize(), "f")


def get_update_time(timestamp):
    updated_at = datetime.utcfromtimestamp(int(timestamp) // 1000)
    delta = (datetime.utcnow() - updated_at).total_seconds()
    if delta < 1:
        return "just now"
    ret = []
    h, s = divmod(int(delta), 3600)
    if h:
        ret.append("{} hours".format(h))
    m, s = divmod(s, 60)
    if m:
        ret.append("{} minutes".format(m))
    if s:
        ret.append("{} seconds".format(s))
    return "{} ago".format(" ".join(ret))


def http_get_json(url):
    req = Request(
        url,
        headers={
            "User-Agent": "curl/7.55",
            "Cache-Control": "max-age=0",
            "accept": "*/*",
        },
    )
    return json.load(urlopen(req, timeout=HTTP_TIMEOUT))


def get_ticker_info(currency):
    url = "https://www.okx.com/api/v5/market/ticker?instId={}-USDT".format(currency)
    try:
        resp = http_get_json(url)["data"][0]
        updated_at = get_update_time(resp["ts"])
        change_24h = (
            (float(resp["last"]) - float(resp["open24h"]))
            / float(resp["open24h"])
            * 100
        )
        return {
            "currency": currency,
            "title": "${} ({}%)".format(
                normalize_decimal(resp["last"]),
                normalize_decimal(change_24h),
            ),
            "updated_at": updated_at,
            "24h_high_low": "{} / {}".format(resp["high24h"], resp["low24h"]),
        }
    except Exception as e:
        return {
            "currency": currency,
            "title": "ERR",
            "error": str(e),
        }


def get_extra_parameters():
    params = []
    font_name = os.environ.get("VAR_FONT_NAME")
    if font_name:
        params.append('font="{}"'.format(font_name.replace('"', '\\"')))
    return " ".join(params)


def main():
    currencies = os.environ.get("VAR_CURRENCIES", DEFAULT_CURRENCIES)
    currencies = [i.upper() for i in re.split(r"\s*,\s*", currencies) if i]
    infos = [get_ticker_info(i) for i in currencies]
    titles = ["{currency}: {title}".format(**i) for i in infos]
    title = "{} | color=white size=12 {}".format(
        "    ".join(titles), get_extra_parameters()
    )
    last_updates = [
        "--{}: {}".format(i["currency"], i["updated_at"])
        for i in infos
        if "updated_at" in i
    ]
    high_lows = [
        "--{}: {}".format(i["currency"], i["24h_high_low"])
        for i in infos
        if "24h_high_low" in i
    ]
    print(title)
    print("---")
    if last_updates:
        print("Last update")
        for i in last_updates:
            print(i)
    if high_lows:
        print("24 hours high/low")
        for i in high_lows:
            print(i)
    for i in infos:
        if "error" in i:
            print("{}: {} | color=red".format(i["currency"], i["error"]))
    print("Open www.okx.com | href=https://www.okx.com/")


if __name__ == "__main__":
    main()