Skip to content

Instantly share code, notes, and snippets.

@normanlmfung
Last active November 18, 2021 09:28
Show Gist options
  • Save normanlmfung/4cc9de2359b7ff1f15df0d6f7008f31b to your computer and use it in GitHub Desktop.
Save normanlmfung/4cc9de2359b7ff1f15df0d6f7008f31b to your computer and use it in GitHub Desktop.
ccxt: check consistency in field names from exchange.load_markets
from typing import Dict
from dotmap import DotMap
import ccxt
class binanceperps(ccxt.binance):
def describe(self) -> Dict:
description = super().describe()
description["options"]["defaultType"] = "future"
return description
class binancedelivery(ccxt.binance):
def describe(self) -> Dict:
description = super().describe()
description["options"]["defaultType"] = "delivery"
return description
class krakenfutures(ccxt.Exchange):
def describe(self):
return self.deep_extend(super().describe(), {
"id": "krakenfutures",
"name": "Kraken Futures",
"countries": ["US"],
"version": "v3",
"urls": {
"test": "https://conformance.cryptofacilities.com/derivatives",
"api": "https://futures.kraken.com/derivatives",
"history": "https://futures.kraken.com/api/history/v2",
},
"api": {
"public": {
"get": [
"instruments"
],
},
}
})
def fetch_markets(self, params={}):
response = self.publicGetInstruments(params)
return self.safe_value(response, "instruments")
def sign(self, path, api="public", method="GET", params={}, headers=None,body=None):
postData = self.urlencode(params)
endpointPath = "/api/" + self.version + "/" + path
url = self.urls["api"] + endpointPath + "?" + postData
return {"url": url, "method": method, "body": body, "headers": headers}
apiKey = 'lala'
secret = 'lala'
param = {
'apiKey' : apiKey,
'secret' : secret,
'rateLimit' : 5000, # 5 seconds
'enableRateLimit' : True
}
# 1) Binance Futures
exchange = binanceperps(param)
markets = exchange.load_markets()
# Look for duplicates/id clash
from collections import Counter
counts = Counter(market for market in markets.keys())
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTC/USDT' # BTCUSDT Perpetual (Linear) under USD-M
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert target.linear, "target.linear should be true"
denormalized_symbol = 'ADA/USDT' # ADAUSDT Perpetual (Linear) under USD-M
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert target.linear, "target.linear should be true"
denormalized_symbol = 'BTCUSDT_211231' # Linear, but dated!
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert target.linear, "target.linear should be true"
# 2) Binance delivery
exchange = binancedelivery(param)
markets = exchange.load_markets()
# Look for duplicates/id clash
from collections import Counter
counts = Counter(market for market in markets.keys())
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTC/USD' # BTCUSD Perpetual (Inverse) under USD-M
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert not target.future, "target.future should be false"
assert not target.linear, "target.linear should be false"
assert target.inverse, "target.inverse should be true"
assert 'type' in markets[denormalized_symbol]
assert 'contractSize' in markets[denormalized_symbol]
denormalized_symbol = 'ADA/USD' # ADAUSD Perpetual (Inverse) under COIN-M
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert not target.future, "target.future should be false"
assert not target.linear, "target.linear should be false"
assert target.inverse, "target.inverse should be true"
assert 'type' in markets[denormalized_symbol]
assert 'contractSize' in markets[denormalized_symbol]
denormalized_symbol = 'ADAUSD_211231' # ADA/USD-31DEC21 under COIN-M
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert not target.future, "target.future should be false"
assert not target.linear, "target.linear should be false"
assert target.inverse, "target.inverse should be true"
assert 'type' in markets[denormalized_symbol]
assert 'contractSize' in markets[denormalized_symbol]
# 3) FTX (No inverse)
exchange = ccxt.ftx(param)
markets = exchange.load_markets()
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTC-PERP'
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
# FTX (No inverse)
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol]
assert 'type' in markets[denormalized_symbol]
# 4) Deribit (Deribit has inverse. But from exchange.markets[symbol] we dont have no 'type', 'linear', 'inverse', 'contractSize'))
# https://legacy.deribit.com/pages/docs/futures
# Deribit everything is inverse, but ccxt response don't have the boolean flag
exchange = ccxt.deribit(param)
markets = exchange.load_markets(param)
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
futures = [future for future in derivatives if future[1].future]
denormalized_symbol = 'BTC-PERPETUAL' # BTC-PERPETUAL
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert not target.option, "target.future should be false"
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol]
assert 'type' in markets[denormalized_symbol]
denormalized_symbol = 'ETH-PERPETUAL' # ETH-PERPETUAL
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert not target.option, "target.future should be false"
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol]
assert 'type' in markets[denormalized_symbol]
denormalized_symbol = 'ETH-25MAR22'
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.future, "target.future should be true"
assert not target.option, "target.future should be false"
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol]
assert 'type' in markets[denormalized_symbol]
# 5) Kraken (Kraken has futures's: https://futures.kraken.com/ and https://support.kraken.com/hc/en-us/articles/360022835891-Ticker-symbols. But from exchange.markets[symbol] we dont have no 'type', 'linear', 'inverse', 'contractSize')
'''
https://support.kraken.com/hc/en-us/sections/360005997111-Contract-Specifications-Margin-Schedules
Perpetuals (inverses): Example PI_BTCUSD, https://support.kraken.com/hc/en-us/articles/360022835911-Inverse-crypto-collateral-perpetual-contract-specifications
Fixed maturity inverse: Example FI_ETHUSD_211231, https://support.kraken.com/hc/en-us/articles/360022632172-Inverse-crypto-collateral-fixed-maturity-contract-specifications
'''
# exchange = ccxt.kraken(param) # This is spot only!
exchange = krakenfutures(param)
markets = exchange.load_markets()
distinct_types = set([DotMap(markets[market]).type for market in markets]) # Krakenfutures only has inverses, no linear. This set will have one type: 'futures_inverse'
derivatives = [(market, DotMap(markets[market])) for market in markets]
denormalized_symbol = 'PI_XBTUSD' # PI for Perpetual Inverse Futures
denormalized_symbol = denormalized_symbol.lower()
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert target.type=="futures_inverse", "atm, 'futures_inverse' the only type"
assert float(target.contractSize)==1, "contractSize==1"
assert 'spot' not in markets[denormalized_symbol]
assert 'future' not in markets[denormalized_symbol]
assert 'option' not in markets[denormalized_symbol]
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
denormalized_symbol = 'FI_ETHUSD_211231' # FI for "Fixed Maturity" Inverse Futures
denormalized_symbol = denormalized_symbol.lower()
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert target.type=="futures_inverse", "atm, 'futures_inverse' the only type"
assert float(target.contractSize)==1, "contractSize==1"
assert 'spot' not in markets[denormalized_symbol]
assert 'future' not in markets[denormalized_symbol]
assert 'option' not in markets[denormalized_symbol]
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
denormalized_symbol = 'FI_BCHUSD_211126' # FI for "Fixed Maturity" Inverse Futures
denormalized_symbol = denormalized_symbol.lower()
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert target.type=="futures_inverse", "atm, 'futures_inverse' the only type"
assert float(target.contractSize)==1, "contractSize==1"
assert 'spot' not in markets[denormalized_symbol]
assert 'future' not in markets[denormalized_symbol]
assert 'option' not in markets[denormalized_symbol]
assert 'linear' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
# 6) OKEx
exchange = ccxt.okex(param)
markets = exchange.load_markets()
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTC-USD-SWAP' # Inverse swap
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
assert 'contractSize' in markets[denormalized_symbol] # Binance also call this contractSize!
assert 'type' in markets[denormalized_symbol]
denormalized_symbol = 'BTC-USDT-220325' # Linear futures
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.futures, "target.future should be true"
assert not target.swap, "target.future should be false"
assert not target.option, "target.future should be false"
assert not target.inverse, "target.inverse should be false"
assert target.linear, "target.linear should be true"
assert 'future' not in markets[denormalized_symbol] # It's 'futures' instead of 'future' (case of binance)
assert 'contractSize' in markets[denormalized_symbol] # Binance also call this contractSize!
assert 'type' in markets[denormalized_symbol]
# 7) Huobi (Houbi has Swap's. But from exchange.markets[symbol] we dont have no 'type', 'linear', 'inverse', 'contractSize')
exchange = ccxt.huobi(param)
markets = exchange.load_markets()
# Spot only?
distinct_types = set([markets[market]['type'] if 'type' in markets[market] else 'NA' for market in markets])
# 8) Bitfinex (Spot and futures only. No inverses. markets[symbol].swap is always False. Also no contractSize)
exchange = ccxt.bitfinex2(param)
markets = exchange.load_markets()
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTCF0/USTF0'
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.futures, "target.future should be true"
assert not target.swap, "target.future should be false"
assert 'future' not in markets[denormalized_symbol] # It's 'futures' instead of 'future' (case of binance)
assert 'inverse' not in markets[denormalized_symbol]
assert 'linear' not in markets[denormalized_symbol]
assert 'option' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol] # Binance also call this contractSize!
assert 'type' in markets[denormalized_symbol]
# 9) Eqonex
exchange = ccxt.eqonex(param)
markets = exchange.load_markets()
derivatives = [(market, DotMap(markets[market])) for market in markets if DotMap(markets[market]).type!='spot']
denormalized_symbol = 'BTC/USDC[F]'
target = [derivative[1] for derivative in derivatives if derivative[0]==denormalized_symbol][0]
print(f"denormalized_symbol: {denormalized_symbol}, id: {target.id}, {target}")
assert not target.spot, "target.spot should be false"
assert target.swap, "target.swap should be true"
assert target.type=='swap', "target.swap should be true"
assert 'linear' not in markets[denormalized_symbol]
assert 'future' not in markets[denormalized_symbol]
assert 'option' not in markets[denormalized_symbol]
assert 'inverse' not in markets[denormalized_symbol]
assert 'contractSize' not in markets[denormalized_symbol]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment