Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
	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
Esempio n. 4
0
	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
Esempio n. 5
0
	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
Esempio n. 6
0
	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)
Esempio n. 7
0
	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")
Esempio n. 8
0
	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
Esempio n. 9
0
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)
Esempio n. 10
0
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)
Esempio n. 11
0
	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
Esempio n. 12
0
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)