Last active
November 18, 2021 09:28
-
-
Save normanlmfung/4cc9de2359b7ff1f15df0d6f7008f31b to your computer and use it in GitHub Desktop.
ccxt: check consistency in field names from exchange.load_markets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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