def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.exchange = None self.parserBias = bias self.filters = [] self.numericalParameters = [] self.platform = platform self.hasExchange = False self.requiresPro = False self.canCache = False self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "Alpha Paper Trader": { "filters": [] }, "Ichibot": { "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True)
def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.parserBias = bias self.filters = [] self.platform = platform self.requiresPro = False self.canCache = platform not in [] self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "CoinGecko": { "filters": [] }, "IEXC": { "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True)
def find_coingecko_crypto_market(ticker): if ticker.id in TickerParserServer.coinGeckoIndex: if ticker.id in TickerParserServer.ccxtIndex["CCXT"]: quote = TickerParserServer.ccxtIndex["CCXT"][ticker.id][0] return Ticker("{}{}".format(ticker.id, quote), "{}{}".format(ticker.id, quote), ticker.id, quote, TickerParserServer.coinGeckoIndex[ticker.id]["id"], hasParts=False, mcapRank=TickerParserServer.coinGeckoIndex[ticker.id]["market_cap_rank"]), None else: return Ticker("{}BTC".format(ticker.id), "{}BTC".format(ticker.id), ticker.id, "BTC", TickerParserServer.coinGeckoIndex[ticker.id]["id"], hasParts=False, mcapRank=TickerParserServer.coinGeckoIndex[ticker.id]["market_cap_rank"]), None else: for base in TickerParserServer.coinGeckoIndex: if ticker.id.startswith(base): for quote in TickerParserServer.coingeckoVsCurrencies: if ticker.id == "{}{}".format(base, quote): return Ticker(ticker.id, ticker.id, base, quote, TickerParserServer.coinGeckoIndex[base]["id"], hasParts=False, mcapRank=TickerParserServer.coinGeckoIndex[base]["market_cap_rank"]), None for base in TickerParserServer.coinGeckoIndex: if base.startswith(ticker.id): return Ticker("{}BTC".format(base), "{}BTC".format(base), base, "BTC", TickerParserServer.coinGeckoIndex[base]["id"], hasParts=False, mcapRank=TickerParserServer.coinGeckoIndex[base]["market_cap_rank"]), None for base in TickerParserServer.coinGeckoIndex: if ticker.id.endswith(base): for quote in TickerParserServer.coingeckoVsCurrencies: if ticker.id == "{}{}".format(quote, base): return Ticker(ticker.id, ticker.id, quote, base, TickerParserServer.coinGeckoIndex[base]["id"], hasParts=False, mcapRank=TickerParserServer.coinGeckoIndex[base]["market_cap_rank"], isReversed=True), None return None, None
def find_ccxt_crypto_market(ticker, exchange, platform, defaults): if platform not in supported.cryptoExchanges: return ticker, exchange exchanges = [TickerParserServer.exchanges[e] for e in supported.cryptoExchanges[platform]] if exchange is None else [exchange] if exchange is None and defaults["exchange"] is not None: exchanges.insert(0, TickerParserServer.exchanges[defaults["exchange"]]) for e in exchanges: if e.properties is not None and e.properties.symbols is not None: tokenizedStock = exchange is None and ticker.id in TickerParserServer.iexcStocksIndex and e.id in ["ftx", "bittrex"] if ticker.id in TickerParserServer.ccxtIndex[platform]: for quote in TickerParserServer.ccxtIndex[platform][ticker.id]: symbol = "{}/{}".format(ticker.id, quote) if symbol in e.properties.symbols and not tokenizedStock: base = e.properties.markets[symbol]["base"] quote = e.properties.markets[symbol]["quote"] if not base in TickerParserServer.coingeckoFiatCurrencies and ("active" not in e.properties.markets[symbol] or e.properties.markets[symbol]["active"]): return Ticker(Ticker.generate_market_name(symbol, e), Ticker.generate_market_name(symbol, e), ticker.id, quote, symbol, hasParts=False, mcapRank=(TickerParserServer.coinGeckoIndex[ticker.id]["market_cap_rank"] if ticker.id in TickerParserServer.coinGeckoIndex else None)), e else: currentBestMatch = sys.maxsize currentBestFit = sys.maxsize currentResult = None, exchange for symbol in e.properties.symbols: base = e.properties.markets[symbol]["base"] quote = e.properties.markets[symbol]["quote"] marketPair = symbol.split("/") marketPairName = Ticker.generate_market_name(symbol, e) mcapRank = TickerParserServer.coinGeckoIndex[base]["market_cap_rank"] if base in TickerParserServer.coinGeckoIndex else None isReversed = False if "active" not in e.properties.markets[symbol] or e.properties.markets[symbol]["active"]: if len(marketPair) == 1: for _ in range(2): if (ticker.id == marketPair[0] or (marketPairName.startswith(ticker.id) and len(marketPairName) * 0.5 <= len(ticker.id))) and currentBestFit > 2: currentBestFit = 2 currentResult = Ticker(marketPairName, marketPairName, base, quote, symbol, hasParts=False, mcapRank=mcapRank, isReversed=isReversed), e if platform not in ["CoinGecko", "CCXT", "IEXC", "Quandl"]: break marketPair.reverse() base, quote, marketPairName, isReversed = quote, base, "".join(marketPair), True elif marketPair[0] in TickerParserServer.ccxtIndex[platform] and marketPair[1] in TickerParserServer.ccxtIndex[platform][marketPair[0]]: rankScore = TickerParserServer.ccxtIndex[platform][marketPair[0]].index(marketPair[1]) for _ in range(2): if (ticker.id == marketPair[0] + marketPair[1] or (marketPairName.startswith(ticker.id) and len(marketPairName) * 0.5 <= len(ticker.id))) and currentBestFit >= 1 and base not in TickerParserServer.coingeckoFiatCurrencies and rankScore < currentBestMatch and not tokenizedStock: currentBestMatch = rankScore currentBestFit = 1 currentResult = Ticker(marketPairName, marketPairName, base, quote, symbol, hasParts=False, mcapRank=mcapRank, isReversed=isReversed), e break if platform not in ["CoinGecko", "CCXT", "IEXC", "Quandl"]: break marketPair.reverse() base, quote, marketPairName, isReversed = quote, base, "".join(marketPair), True if currentResult[0] is not None: return currentResult return None, exchange
def find_iexc_market(ticker): if ticker.id in TickerParserServer.iexcForexIndex: return Ticker(TickerParserServer.iexcForexIndex[ticker.id]["id"], TickerParserServer.iexcForexIndex[ticker.id]["name"], TickerParserServer.iexcForexIndex[ticker.id]["base"], TickerParserServer.iexcForexIndex[ticker.id]["quote"], "{}/{}".format(TickerParserServer.iexcForexIndex[ticker.id]["base"], TickerParserServer.iexcForexIndex[ticker.id]["quote"]), hasParts=False, isReversed=TickerParserServer.iexcForexIndex[ticker.id]["reversed"]), None elif ticker.id in TickerParserServer.iexcStocksIndex: return Ticker(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["name"], ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"], "{}/{}".format(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"]), hasParts=False), TickerParserServer.exchanges[TickerParserServer.iexcStocksIndex[ticker.id]["exchange"]] elif ticker.id in TickerParserServer.iexcOtcIndex: return Ticker(ticker.id, TickerParserServer.iexcOtcIndex[ticker.id]["name"], ticker.id, TickerParserServer.iexcOtcIndex[ticker.id]["quote"], "{}/{}".format(ticker.id, TickerParserServer.iexcOtcIndex[ticker.id]["quote"]), hasParts=False), TickerParserServer.exchanges[TickerParserServer.iexcOtcIndex[ticker.id]["exchange"]] elif ticker.id.endswith("USD") and ticker.id[:-3] in TickerParserServer.iexcStocksIndex: ticker.id = ticker.id[:-3] return Ticker(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["name"], ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"], "{}/{}".format(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"]), hasParts=False), TickerParserServer.exchanges[TickerParserServer.iexcStocksIndex[ticker.id]["exchange"]] elif ticker.id.startswith("USD") and ticker.id[3:] in TickerParserServer.iexcStocksIndex: ticker.id = ticker.id[3:] return Ticker(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["name"], ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"], "{}/{}".format(ticker.id, TickerParserServer.iexcStocksIndex[ticker.id]["quote"]), hasParts=False, isReversed=True), TickerParserServer.exchanges[TickerParserServer.iexcStocksIndex[ticker.id]["exchange"]] return None, None
def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.exchange = None self.parserBias = bias self.imageStyle = [] self.filters = [] self.numericalParameters = [] self.platform = platform self.hasExchange = False self.requiresPro = False self.canCache = platform not in [] self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "Alternative.me": { "imageStyle": [], "filters": [] }, "LLD": { "imageStyle": [], "filters": [] }, "CoinGecko": { "imageStyle": [], "filters": [] }, "CCXT": { "imageStyle": [], "filters": [] }, "IEXC": { "imageStyle": [], "filters": [] }, "Quandl": { "imageStyle": [], "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True)
def __init__(self): self.isServiceAvailable = True signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully) self.logging = error_reporting.Client() self.cache = Cache(ttl=5) self.coinGecko = CoinGeckoAPI() self.lastBitcoinQuote = { "quotePrice": [0], "quoteVolume": None, "ticker": Ticker("BTCUSD", "BTCUSD", "BTC", "USD", "BTC/USD", hasParts=False), "exchange": None, "timestamp": time.time() } try: rawData = self.coinGecko.get_coin_by_id(id="bitcoin", localization="false", tickers=False, market_data=True, community_data=False, developer_data=False) self.lastBitcoinQuote["quotePrice"] = [rawData["market_data"]["current_price"]["usd"]] self.lastBitcoinQuote["quoteVolume"] = rawData["market_data"]["total_volume"]["usd"] except: pass context = zmq.Context.instance() self.socket = context.socket(zmq.ROUTER) self.socket.bind("tcp://*:6900") print("[Startup]: Quote Server is online")
def request_coingecko_quote(self, request): ticker = request.get_ticker() exchange = request.get_exchange() try: try: rawData = self.coinGecko.get_coin_by_id(id=ticker.symbol, localization="false", tickers=False, market_data=True, community_data=False, developer_data=False) except: return None, None if ticker.quote.lower() not in rawData["market_data"]["current_price"] or ticker.quote.lower() not in rawData["market_data"]["total_volume"]: return None, "Requested price for `{}` is not available.".format(ticker.name) price = rawData["market_data"]["current_price"][ticker.quote.lower()] if ticker.isReversed: price = 1 / price volume = rawData["market_data"]["total_volume"][ticker.quote.lower()] priceChange = rawData["market_data"]["price_change_percentage_24h_in_currency"][ticker.quote.lower()] if ticker.quote.lower() in rawData["market_data"]["price_change_percentage_24h_in_currency"] else 0 if ticker.isReversed: priceChange = (1 / (priceChange / 100 + 1) - 1) * 100 payload = { "quotePrice": ("{:,.%df}" % (4 if TickerParser.check_if_fiat(ticker.quote)[0] and not ticker.isReversed else 8)).format(price), "quoteVolume": volume, "quoteConvertedPrice": None if ticker.quote == "USD" else "≈ ${:,.6f}".format(rawData["market_data"]["current_price"]["usd"]), "quoteConvertedVolume": None if ticker.quote == "USD" else "≈ ${:,.4f}".format(rawData["market_data"]["total_volume"]["usd"]), "title": ticker.name, "baseTicker": ticker.base if ticker.base.lower() in rawData["market_data"]["current_price"] else "BTC", "quoteTicker": ticker.quote if ticker.quote.lower() in rawData["market_data"]["current_price"] else "BTC", "change": priceChange, "thumbnailUrl": TickerParser.get_coingecko_image(ticker.base), "messageColor": "amber" if priceChange == 0 else ("green" if priceChange > 0 else "red"), "sourceText": "from CoinGecko", "platform": "CoinGecko", "raw": { "quotePrice": [price], "quoteVolume": volume, "ticker": ticker, "exchange": exchange, "timestamp": time.time() } } if ticker == Ticker("BTCUSD", "BTCUSD", "BTC", "USD", "BTC/USD", hasParts=False): self.lastBitcoinQuote = payload["raw"] return payload, None except Exception: print(traceback.format_exc()) if os.environ["PRODUCTION_MODE"]: self.logging.report_exception() return None, None
class TradeRequest(object): requestParameters = { "filters": [ Parameter("isAmountPercent", "percentage amount", ["%"], paper=True), Parameter("isPricePercent", "percentage price", ["%"], paper=True), Parameter("isLimitOrder", "limit order", ["@", "at"], paper=True), Parameter("isReduceOnlyMode", "reduce only option", ["reduce"], paper=True), Parameter("autoDeleteOverride", "autodelete", ["del", "delete", "autodelete"], paper=True, ichibot=True) ] } def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.exchange = None self.parserBias = bias self.filters = [] self.numericalParameters = [] self.platform = platform self.hasExchange = False self.requiresPro = False self.canCache = False self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "Alpha Paper Trader": { "filters": [] }, "Ichibot": { "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True) def __hash__(self): h1 = sorted([e.name for e in self.filters]) return hash("{}{}{}{}{}{}".format(self.ticker, self.exchange, h1, self.numericalParameters, self.platform, self.requiresPro)) def process_ticker(self, defaults, bias): filters = [e.parsed[self.platform] for e in self.filters] for i in range(len(self.ticker.parts)): part = self.ticker.parts[i] if type(part) is str: continue updatedTicker, updatedExchange = TickerParser.process_known_tickers( part, self.exchange, self.platform, defaults, bias) if updatedTicker is not None: self.ticker.parts[i] = updatedTicker if not self.ticker.isAggregatedTicker: self.exchange = updatedExchange else: self.shouldFail = True self.ticker.update_ticker_id() def add_parameter(self, argument, type): isSupported = None parsedParameter = None for param in TradeRequest.requestParameters[type]: if argument in param.parsablePhrases: parsedParameter = param isSupported = param.supports(self.platform) if isSupported: self.requiresPro = self.requiresPro or param.requiresPro break return isSupported, parsedParameter def add_exchange(self, argument): exchangeSupported, parsedExchange = TickerParser.find_exchange( argument, self.platform, self.parserBias) if parsedExchange is not None and not self.hasExchange: if not exchangeSupported: outputMessage = "`{}` exchange is not supported by {}.".format( parsedExchange.name, self.platform) return outputMessage, False self.exchange = parsedExchange self.hasExchange = True return None, True return None, None def add_filters(self, argument): filterSupported, parsedFilter = self.add_parameter(argument, "filters") if parsedFilter is not None and not self.has_parameter( parsedFilter.id, self.filters): if not filterSupported: outputMessage = "`{}` parameter is not supported by {}.".format( parsedFilter.name.title(), self.platform) return outputMessage, False self.filters.append(parsedFilter) return None, True return None, None def add_numerical_parameters(self, argument): try: numericalParameter = float(argument) if numericalParameter <= 0: outputMessage = "Only parameters greater than `0` are accepted." return outputMessage, False self.numericalParameters.append(numericalParameter) return None, True except: return None, None def process_special_tickers(self, argument): return None, None def set_default_for(self, type): if type == "filters": for parameter in self.__defaultParameters[self.platform][type]: if not self.has_parameter(parameter.id, self.filters): self.filters.append(parameter) def find_parameter_with_id(self, id, name=None, type=None): for t in (self.requestParameters.keys() if type is None else [type]): for parameter in self.requestParameters[t]: if id == parameter.id and (name is None or parameter.name == name): return parameter return None def is_parameter_present(self, id, argument): return self.has_parameter(id, self.filters, argument) def has_parameter(self, id, list, argument=None): for e in list: if e.id == id and (argument is None or e.parsed[self.platform] == argument): return True return False def set_error(self, error, isFatal=False): if len(self.errors) > 0 and self.errors[0] is None: return self.errorIsFatal = isFatal self.errors.insert(0, error)
class DetailRequest(object): requestParameters = { "filters": [ Parameter("autoDeleteOverride", "autodelete", ["del", "delete", "autodelete"], coingecko=True, iexc=True) ] } def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.parserBias = bias self.filters = [] self.platform = platform self.requiresPro = False self.canCache = platform not in [] self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "CoinGecko": { "filters": [] }, "IEXC": { "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True) def __hash__(self): h1 = sorted([e.name for e in self.filters]) return hash("{}{}{}{}".format(hash(self.ticker), h1, self.platform, self.requiresPro)) def process_ticker(self, defaults, bias): filters = [e.parsed[self.platform] for e in self.filters] for i in range(len(self.ticker.parts)): part = self.ticker.parts[i] if type(part) is str: continue updatedTicker, updatedExchange = TickerParser.process_known_tickers( part, None, self.platform, defaults, bias) if updatedTicker is not None: self.ticker.parts[i] = updatedTicker if not self.ticker.isAggregatedTicker: self.exchange = updatedExchange else: self.shouldFail = True self.ticker.update_ticker_id() def add_parameter(self, argument, type): isSupported = None parsedParameter = None for param in DetailRequest.requestParameters[type]: if argument in param.parsablePhrases: parsedParameter = param isSupported = param.supports(self.platform) if isSupported: self.requiresPro = self.requiresPro or param.requiresPro break return isSupported, parsedParameter def add_filters(self, argument): filterSupported, parsedFilter = self.add_parameter(argument, "filters") if parsedFilter is not None and not self.has_parameter( parsedFilter.id, self.filters): if not filterSupported: outputMessage = "`{}` parameter is not supported by {}.".format( parsedFilter.name.title(), self.platform) return outputMessage, False self.filters.append(parsedFilter) return None, True return None, None def process_special_tickers(self, argument): return None, None def set_default_for(self, type): if type == "filters": for parameter in self.__defaultParameters[self.platform][type]: if not self.has_parameter(parameter.id, self.filters): self.filters.append(parameter) def find_parameter_with_id(self, id, name=None, type=None): for t in (self.requestParameters.keys() if type is None else [type]): for parameter in self.requestParameters[t]: if id == parameter.id and (name is None or parameter.name == name): return parameter return None def is_parameter_present(self, id, argument): return self.has_parameter(id, self.filters, argument) def has_parameter(self, id, list, argument=None): for e in list: if e.id == id and (argument is None or e.parsed[self.platform] == argument): return True return False def set_error(self, error, isFatal=False): if len(self.errors) > 0 and self.errors[0] is None: return self.errorIsFatal = isFatal self.errors.insert(0, error)
def process_known_tickers(ticker, exchange, platform, defaults, bias): if (ticker.id.startswith("'") and ticker.id.endswith("'")) or (ticker.id.startswith('"') and ticker.id.endswith('"')) or (ticker.id.startswith("‘") and ticker.id.endswith("’")) or (ticker.id.startswith("“") and ticker.id.endswith("”")): ticker = Ticker(ticker.id[1:-1], ticker.id[1:-1], ticker.id[1:-1], "", ticker.id[1:-1], hasParts=False) else: if ticker.id.startswith("$"): ticker = Ticker(ticker.id[1:] + "USD", base=ticker.id[1:], quote="USD", hasParts=False) elif ticker.id.startswith("€"): ticker = Ticker(ticker.id[1:] + "EUR", base=ticker.id[1:], quote="EUR", hasParts=False) tickerOverrides = { "TradingView": [ (Ticker("(DJ:DJI)", "DJI", "DJI", "", "DJI", hasParts=False), None, ["DJI"]), (Ticker("SPX500USD", "SPX500USD", "SPX500USD", "", "SPX500USD", hasParts=False), None, ["SPX", "SP500"]) ] } cryptoTickerOverrides = { "TradingLite": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "TradingView": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]), (Ticker("(DJ:DJI)", "DJI", "DJI", "", "DJI", hasParts=False), None, ["DJI"]), (Ticker("SPX500USD", "SPX500USD", "SPX500USD", "", "SPX500USD", hasParts=False), None, ["SPX", "SP500"]), (Ticker("(BNC:BLX)", "BLX", "BTC", "USD", "BTC/USD", hasParts=False), None, ["BNC", "BLX"]), (Ticker("BTCUSDLONGS", "BTCUSD Longs", "BTC", "USD", "BTCUSDLONGS", hasParts=False), None, ["L", "LONGS"]), (Ticker("BTCUSDSHORTS", "BTCUSD Shorts", "BTC", "USD", "BTCUSDSHORTS", hasParts=False), None, ["S", "SHORTS"]), (Ticker("(BTCUSDLONGS/(BTCUSDLONGS+BTCUSDSHORTS))", "BTCUSD Longs/Shorts", None, "%", None), None, ["LS", "LONGS/SHORTS"]), (Ticker("(BTCUSDSHORTS/(BTCUSDLONGS+BTCUSDSHORTS))", "BTCUSD Shorts/Longs", None, "%", None), None, ["SL", "SHORTS/LONGS"]) ], "Bookmap": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "GoCharting": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "CoinGecko": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "LLD": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "CCXT": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "Alpha Paper Trader": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ], "Ichibot": [ (Ticker("BTCUSD", "XBTUSD", "BTC", "USD", "BTC/USD", hasParts=False, mcapRank=1), TickerParserServer.exchanges["bitmex"], ["XBT", "XBTUSD"]) ] } parsedTicker, parsedExchange = None, None if (platform in ["TradingView", "Bookmap", "GoCharting"] and bias == "crypto") or platform in ["TradingLite", "LLD", "CoinGecko", "CCXT", "Alpha Paper Trader", "Ichibot"]: if platform in cryptoTickerOverrides: for tickerOverride, exchangeOverride, triggers in cryptoTickerOverrides[platform]: if ticker.id in triggers: ticker = tickerOverride if exchangeOverride is not None: exchange = exchangeOverride break if platform == "CoinGecko" and defaults["exchange"] is None and exchange is None: parsedTicker, parsedExchange = TickerParserServer.find_coingecko_crypto_market(ticker) else: parsedTicker, parsedExchange = TickerParserServer.find_ccxt_crypto_market(ticker, exchange, platform, defaults) else: if platform in tickerOverrides: for tickerOverride, exchangeOverride, triggers in tickerOverrides[platform]: if ticker.id in triggers: ticker = tickerOverride if exchangeOverride is not None: exchange = exchangeOverride break if platform == "IEXC": parsedTicker, parsedExchange = TickerParserServer.find_iexc_market(ticker) elif platform == "Quandl": parsedTicker, parsedExchange = TickerParserServer.find_quandl_market(ticker) if parsedTicker is not None: ticker, exchange = parsedTicker, parsedExchange return ticker, exchange
class PriceRequest(object): requestParameters = { "imageStyle": [ Parameter("force", "force", ["--force"], ccxt="force", iexc="force"), Parameter("upload", "upload", ["--upload"], ccxt="upload", iexc="upload") ], "filters": [ Parameter("lld", "funding", ["fun", "fund", "funding"], lld="funding"), Parameter("lld", "open interest", ["oi", "openinterest", "ov", "openvalue"], lld="oi"), Parameter("lld", "longs/shorts ratio", ["ls", "l/s", "longs/shorts", "long/short"], lld="ls"), Parameter("lld", "shorts/longs ratio", ["sl", "s/l", "shorts/longs", "short/long"], lld="sl"), Parameter("lld", "dominance", ["dom", "dominance"], lld="dom"), Parameter("isAmountPercent", "percentage amount", ["%"], ccxt=True, iexc=True), Parameter("isPricePercent", "percentage price", ["%"], ccxt=True, iexc=True), Parameter("isLimitOrder", "limit order", ["@", "at"], ccxt=True, iexc=True), Parameter("autoDeleteOverride", "autodelete", ["del", "delete", "autodelete"], coingecko=True, ccxt=True, iexc=True, quandl=True, alternativeme=True, lld=True), Parameter("public", "public trigger", ["pub", "publish", "public"], ccxt=True, iexc=True), Parameter("forcePlatform", "Force quote on CoinGecko", ["cg", "coingecko"], coingecko=True), Parameter("forcePlatform", "Force quote on a crypto exchange", ["cx", "ccxt", "crypto"], ccxt=True), Parameter("forcePlatform", "Force quote on a stock exchange", ["ix", "iexc", "stock"], iexc=True), Parameter("forcePlatform", "Force quote on Alternative.me", ["am", "alternativeme"], alternativeme=True) ] } def __init__(self, tickerId, platform, bias): self.ticker = Ticker(tickerId) self.exchange = None self.parserBias = bias self.imageStyle = [] self.filters = [] self.numericalParameters = [] self.platform = platform self.hasExchange = False self.requiresPro = False self.canCache = platform not in [] self.errors = [] self.errorIsFatal = False self.__defaultParameters = { "Alternative.me": { "imageStyle": [], "filters": [] }, "LLD": { "imageStyle": [], "filters": [] }, "CoinGecko": { "imageStyle": [], "filters": [] }, "CCXT": { "imageStyle": [], "filters": [] }, "IEXC": { "imageStyle": [], "filters": [] }, "Quandl": { "imageStyle": [], "filters": [] } } self.specialTickerTriggers = [] if self.ticker.isAggregatedTicker and self.platform not in []: self.set_error("Aggregated tickers are not supported.", isFatal=True) def __hash__(self): h1 = sorted([e.name for e in self.filters]) return hash("{}{}{}{}{}{}".format(hash(self.ticker), hash(self.exchange), h1, self.numericalParameters, self.platform, self.requiresPro)) def process_ticker(self, defaults, bias): filters = [e.parsed[self.platform] for e in self.filters] if any([e in filters for e in ["funding", "oi"]]): if not self.hasExchange: self.exchange = TickerParser.find_exchange("bitmex", self.platform, self.parserBias)[1] elif any([e in filters for e in ["ls", "sl"]]): if not self.hasExchange: self.exchange = TickerParser.find_exchange("bitfinex", self.platform, self.parserBias)[1] for i in range(len(self.ticker.parts)): part = self.ticker.parts[i] if type(part) is str: continue updatedTicker, updatedExchange = TickerParser.process_known_tickers(part, self.exchange, self.platform, defaults, bias) if updatedTicker is not None: self.ticker.parts[i] = updatedTicker if not self.ticker.isAggregatedTicker: self.exchange = updatedExchange else: self.shouldFail = True self.ticker.update_ticker_id() def add_parameter(self, argument, type): isSupported = None parsedParameter = None for param in PriceRequest.requestParameters[type]: if argument in param.parsablePhrases: parsedParameter = param isSupported = param.supports(self.platform) if isSupported: self.requiresPro = self.requiresPro or param.requiresPro break return isSupported, parsedParameter def add_exchange(self, argument): exchangeSupported, parsedExchange = TickerParser.find_exchange(argument, self.platform, self.parserBias) if parsedExchange is not None and not self.hasExchange: if not exchangeSupported: outputMessage = "`{}` exchange is not supported by {}.".format(parsedExchange.name, self.platform) return outputMessage, False self.exchange = parsedExchange self.hasExchange = True return None, True return None, None def add_image_style(self, argument): imageStyleSupported, parsedImageStyle = self.add_parameter(argument, "imageStyle") if parsedImageStyle is not None and not self.has_parameter(parsedImageStyle.id, self.imageStyle): if not imageStyleSupported: outputMessage = "`{}` chart style is not supported on {}.".format(parsedImageStyle.name.title(), self.platform) return outputMessage, False self.imageStyle.append(parsedImageStyle) return None, True return None, None def add_filters(self, argument): filterSupported, parsedFilter = self.add_parameter(argument, "filters") if parsedFilter is not None and not self.has_parameter(parsedFilter.id, self.filters): if not filterSupported: outputMessage = "`{}` parameter is not supported by {}.".format(parsedFilter.name.title(), self.platform) return outputMessage, False self.filters.append(parsedFilter) return None, True return None, None def add_numerical_parameters(self, argument): try: numericalParameter = float(argument) if numericalParameter <= 0: outputMessage = "Only parameters greater than `0` are accepted." return outputMessage, False self.numericalParameters.append(numericalParameter) return None, True except: return None, None def process_special_tickers(self, argument): return None, None def set_default_for(self, type): if type == "filters": for parameter in self.__defaultParameters[self.platform][type]: if not self.has_parameter(parameter.id, self.filters): self.filters.append(parameter) def find_parameter_with_id(self, id, name=None, type=None): for t in (self.requestParameters.keys() if type is None else [type]): for parameter in self.requestParameters[t]: if id == parameter.id and (name is None or parameter.name == name): return parameter return None def is_parameter_present(self, id, argument): return self.has_parameter(id, self.filters, argument) def has_parameter(self, id, list, argument=None): for e in list: if e.id == id and (argument is None or e.parsed[self.platform] == argument): return True return False def set_error(self, error, isFatal=False): if len(self.errors) > 0 and self.errors[0] is None: return self.errorIsFatal = isFatal self.errors.insert(0, error)