def computeCryptoFiatRate(self, crypto, fiat, dateStr=None): ''' :raise UnsupportedCryptoFiatPairError in case the crypto fiat exchange CSV file does not have the necessary information to compute the crypto/fiat pair rate. :raise AfterNowPriceRequestDateError in case the passed dateStr is after now. @param crypto: @param fiat: @param dateStr: if not None, means that an historical rate must be obtained. Otherwise, a current rate is returned. :return crypto/fiat pair current rate ''' if dateStr is not None: nowDateArrow = DateTimeUtil.localNow(LOCAL_TIME_ZONE) requestDateArrow = DateTimeUtil.dateTimeStringToArrowLocalDate(dateStr, LOCAL_TIME_ZONE, DATE_FORMAT) if DateTimeUtil.isAfter(requestDateArrow, nowDateArrow): raise AfterNowPriceRequestDateError(dateStr) intermediateExchangeRateRequestLst = self._getIntermediateExchangeRateRequests(crypto, fiat) rateRequestNumber = len(intermediateExchangeRateRequestLst) if rateRequestNumber == 1: exchange = intermediateExchangeRateRequestLst[0][2] if exchange == '1': # the case if the crypto/fiat pair is a stablecoin/ coin fiat pair, # like USDC/USD ! return 1 else: resultData = self._getCurrentOrHistoRate(crypto, dateStr, exchange, fiat) if not self._checkIfProblem(resultData): return resultData.getValue(resultData.RESULT_KEY_PRICE) elif rateRequestNumber == 2: crypto = intermediateExchangeRateRequestLst[0][0] unit = intermediateExchangeRateRequestLst[0][1] exchange = intermediateExchangeRateRequestLst[0][2] if exchange == '1': resultData = ResultData() resultData.setValue(resultData.RESULT_KEY_PRICE, 1) else: resultData = self._getCurrentOrHistoRate(crypto, dateStr, exchange, unit) if not self._checkIfProblem(resultData): firstRate = resultData.getValue(resultData.RESULT_KEY_PRICE) crypto = intermediateExchangeRateRequestLst[1][0] fiat = intermediateExchangeRateRequestLst[1][1] exchange = intermediateExchangeRateRequestLst[1][2] resultData = self._getCurrentOrHistoRate(crypto, dateStr, exchange, fiat) if not self._checkIfProblem(resultData): secondRate = resultData.getValue(resultData.RESULT_KEY_PRICE) return firstRate * secondRate raise UnsupportedCryptoFiatPairError(crypto, fiat, self.cryptoFiatCsvFilePathName)
def test_getHistoDayPriceAtUTCTimeStampMidOfDay(self): crypto = 'BTC' fiat = 'USD' exchange = 'CCCAGG' utcArrowDateTimeObj_midOfDay = DateTimeUtil.dateTimeStringToArrowLocalDate("2017/09/30 12:59:59", 'UTC', "YYYY/MM/DD HH:mm:ss") resultData = ResultData() resultData = self.priceRequester._getHistoDayPriceAtUTCTimeStamp(crypto, fiat, utcArrowDateTimeObj_midOfDay.timestamp, exchange, resultData) self.assertEqual(1506729600, resultData.getValue(resultData.RESULT_KEY_PRICE_TIME_STAMP)) priceArrowUTCDateTime = DateTimeUtil.timeStampToArrowLocalDate(resultData.getValue(resultData.RESULT_KEY_PRICE_TIME_STAMP), 'UTC') self.assertEqual(resultData.getValue(resultData.RESULT_KEY_PRICE_TYPE), resultData.PRICE_TYPE_HISTO_DAY) self.assertEqual('30/09/17', priceArrowUTCDateTime.format(self.configMgr.dateOnlyFormat)) self.assertEqual(4360.62, resultData.getValue(resultData.RESULT_KEY_PRICE))
class TestResultData(unittest.TestCase): def setUp(self): self.resultData = ResultData() def testInit(self): self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_CRYPTO), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_UNIT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_EXCHANGE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_TIME_STAMP), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_DATE_TIME_STRING), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_TYPE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_ERROR_MSG), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_WARNINGS_DIC), {}) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_INITIAL_COMMAND_PARMS), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_VALUE_CRYPTO), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_VALUE_UNIT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_VALUE_FIAT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_VALUE_SAVE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_FIAT_RATE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_FIAT_COMPUTED_AMOUNT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_FIAT_SYMBOL), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_FIAT_EXCHANGE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_FIAT_SAVE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_PRICE_AMOUNT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_PRICE_SAVE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_RESULT_COMPUTED_AMOUNT_UNIT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_RESULT_COMPUTED_PERCENT_UNIT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_RESULT_COMPUTED_AMOUNT_FIAT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_RESULT_COMPUTED_PERCENT_FIAT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_RESULT_SAVE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_LIMIT_AMOUNT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_LIMIT_COMPUTED_UNIT_AMOUNT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_LIMIT_SYMBOL), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_LIMIT_EXCHANGE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_OPTION_LIMIT_SAVE), None) def testNoError(self): self.assertTrue(self.resultData.noError()) errorMsg = "ERROR - test error" self.resultData.setError(errorMsg) self.assertFalse(self.resultData.noError()) def testSetValue(self): self.resultData.setValue(self.resultData.RESULT_KEY_CRYPTO, 'USD') self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_CRYPTO), 'USD') def testSetGetWarning(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.resultData.setWarning(ResultData.WARNING_TYPE_OPTION_VALUE, commValWarningMsg) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertEqual(commValWarningMsg, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_OPTION_VALUE)) self.assertEqual(futureDateWarningMsg, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_FUTURE_DATE)) def testGetAllWarningMessages(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.resultData.setWarning(ResultData.WARNING_TYPE_OPTION_VALUE, commValWarningMsg) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertEqual([commValWarningMsg, futureDateWarningMsg], self.resultData.getAllWarningMessages()) def testContainsWarning(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.assertFalse(self.resultData.containsWarnings()) self.resultData.setWarning(ResultData.WARNING_TYPE_OPTION_VALUE, commValWarningMsg) self.assertTrue(self.resultData.containsWarning(ResultData.WARNING_TYPE_OPTION_VALUE)) self.assertFalse(self.resultData.containsWarning(ResultData.WARNING_TYPE_FUTURE_DATE)) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertTrue(self.resultData.containsWarning(ResultData.WARNING_TYPE_FUTURE_DATE)) def testOverwriteWarning(self): commValWarningMsgOne = "test warning command value one" futureDateWarningMsgOne = "test warning future date one" self.resultData.setWarning(ResultData.WARNING_TYPE_OPTION_VALUE, commValWarningMsgOne) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsgOne) commValWarningMsgTwo = "test warning command value two" futureDateWarningMsgTwo = "test warning future date two" self.resultData.setWarning(ResultData.WARNING_TYPE_OPTION_VALUE, commValWarningMsgTwo) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsgTwo) self.assertEqual(commValWarningMsgTwo, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_OPTION_VALUE)) self.assertEqual(futureDateWarningMsgTwo, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_FUTURE_DATE))
class TestResultData(unittest.TestCase): def setUp(self): self.resultData = ResultData() def testInit(self): self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_CRYPTO), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_FIAT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_EXCHANGE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_TIME_STAMP), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_DATE_TIME_STRING), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_TYPE), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_ERROR_MSG), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_VALUE_FIAT), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_VALUE_CRYPTO), None) self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_PRICE_VALUE_SAVE), None) def testIsEmpty(self): self.assertTrue(self.resultData.isEmpty(self.resultData.RESULT_KEY_CRYPTO)) def testSetValue(self): self.resultData.setValue(self.resultData.RESULT_KEY_CRYPTO, 'USD') self.assertEqual(self.resultData.getValue(self.resultData.RESULT_KEY_CRYPTO), 'USD') def testSetGetWarning(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.resultData.setWarning(ResultData.WARNING_TYPE_COMMAND_VALUE, commValWarningMsg) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertEqual(commValWarningMsg, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_COMMAND_VALUE)) self.assertEqual(futureDateWarningMsg, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_FUTURE_DATE)) def testGetAllWarningMessages(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.resultData.setWarning(ResultData.WARNING_TYPE_COMMAND_VALUE, commValWarningMsg) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertEqual([commValWarningMsg, futureDateWarningMsg], self.resultData.getAllWarningMessages()) def testContainsWarning(self): commValWarningMsg = "test warning command value" futureDateWarningMsg = "test warning future date" self.assertFalse(self.resultData.containsWarnings()) self.resultData.setWarning(ResultData.WARNING_TYPE_COMMAND_VALUE, commValWarningMsg) self.assertTrue(self.resultData.containsWarning(ResultData.WARNING_TYPE_COMMAND_VALUE)) self.assertFalse(self.resultData.containsWarning(ResultData.WARNING_TYPE_FUTURE_DATE)) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsg) self.assertTrue(self.resultData.containsWarning(ResultData.WARNING_TYPE_FUTURE_DATE)) def testOverwriteWarning(self): commValWarningMsgOne = "test warning command value one" futureDateWarningMsgOne = "test warning future date one" self.resultData.setWarning(ResultData.WARNING_TYPE_COMMAND_VALUE, commValWarningMsgOne) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsgOne) commValWarningMsgTwo = "test warning command value two" futureDateWarningMsgTwo = "test warning future date two" self.resultData.setWarning(ResultData.WARNING_TYPE_COMMAND_VALUE, commValWarningMsgTwo) self.resultData.setWarning(ResultData.WARNING_TYPE_FUTURE_DATE, futureDateWarningMsgTwo) self.assertEqual(commValWarningMsgTwo, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_COMMAND_VALUE)) self.assertEqual(futureDateWarningMsgTwo, self.resultData.getWarningMessage(ResultData.WARNING_TYPE_FUTURE_DATE))
def getCryptoPrice(self, crypto, unit, exchange, day, month, year, hour, minute, optionValueSymbol=None, optionValueAmount=None, optionValueSaveFlag=None, optionFiatSymbol=None, optionFiatExchange=None, optionPriceAmount=None, optionPriceSaveFlag=None, optionResultStrAmount=None, optionResultSaveFlag=None, optionLimitSymbol=None, optionLimitAmount=None, optionLimitExchange=None, optionLimitSaveFlag=None, requestInputString=''): """ Ask the PriceRequester either a RT price or a historical price. Then, in case a fiat (-f) or/and a value option (-v) was specified, computes them and add the results to the returned ResultData. :param crypto: :param unit: :param exchange: :param day: :param month: :param year: :param hour: :param minute: :param optionValueSymbol: upper case currency value symbol. If == crypto, this means that optionValueAmount provided is in crypto and must be converted into unit (counter party) at the rate returned by the PriceRequester. If the currency value symbol == unit, this means that optionValueAmount provided is in the counter party (unit or an other crypto) and must be converted into crypto at the rate returned by the PriceRequester. Ex 1: -v0.001btc crypto == BTC unit == USD optionValueSymbol == BTC optionValueAmount == 0.001 if returned rate (stored in ResultData.RESULT_KEY_PRICE entry) is 20000, converted value will be 20000 USD * 0.001 BTC => 200 USD Ex 2: -v500usd crypto == BTC unit == USD optionValueSymbol == USD optionValueAmount == 500 if returned rate (stored in ResultData.RESULT_KEY_PRICE entry) is 20000, converted value will be 1 / 20000 USD * 500 USD => 0.025 BTC :param optionValueAmount: float specified value option amount :param optionValueSaveFlag: used to refine warning if value option not applicable :param optionFiatSymbol: stores the fiat symbol, i.e. the fiat into which the returned unit amount is converted :param optionFiatExchange: :param optionPriceAmount: :param optionPriceSaveFlag: not sure if useful. May be used to refine warning if price option not applicable :param optionResultStrAmount: ex: '' means -1 or -2 or -1-3 or -2:-4 :param optionResultSaveFlag: not sure if useful. May be used to refine warning if result option not applicable :param optionLimitSymbol: :param optionLimitAmount: :param optionLimitExchange: :param optionLimitSaveFlag: not sure if useful. May be used to refine warning if limit option not applicable :param requestInputString): used for to complete the error msg with the request causing problem! :seqdiag_return ResultData :return: a ResultData filled with result values """ # validating exchange, fiat exchange and limit exchange if exchange == None: resultData = ResultData() resultData.setError("ERROR - exchange could not be parsed due to an error in your request ({}).".format(requestInputString)) return resultData else: try: validCryptoUnitExchangeSymbol = self.crypCompExchanges.getExchange(exchange) except(KeyError): resultData = ResultData() resultData.setError(MARKET_NOT_SUPPORTED_ERROR.format(exchange)) return resultData validFiatExchangeSymbol = None if optionFiatExchange: try: validFiatExchangeSymbol = self.crypCompExchanges.getExchange(optionFiatExchange) except(KeyError): resultData = ResultData() resultData.setError(MARKET_NOT_SUPPORTED_ERROR.format(optionFiatExchange)) return resultData validLimitExchangeSymbol = None if optionLimitExchange: try: validLimitExchangeSymbol = self.crypCompExchanges.getExchange(optionLimitExchange) except(KeyError): resultData = ResultData() resultData.setError(MARKET_NOT_SUPPORTED_ERROR.format(optionLimitExchange)) return resultData localTz = self.configManager.localTimeZone dateTimeFormat = self.configManager.dateTimeFormat resultData = self._getPrice(crypto, unit, validCryptoUnitExchangeSymbol, year, month, day, hour, minute, dateTimeFormat, localTz, optionPriceAmount, optionPriceSaveFlag) if not resultData.noError(): # since crypto/unit is not supported by the exchange, we try to request the unit/crypto inverted rate errorMsg = resultData.getErrorMessage() resultData = self._getPrice(unit, crypto, validCryptoUnitExchangeSymbol, year, month, day, hour, minute, dateTimeFormat, localTz, optionPriceAmount) resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto) resultData.setValue(resultData.RESULT_KEY_UNIT, unit) price = resultData.getValue(resultData.RESULT_KEY_PRICE) if price: resultData.setValue(resultData.RESULT_KEY_PRICE, 1 / price) resultData.setError(None) else: resultData.setError(errorMsg) if optionPriceAmount is not None and resultData.noError(): resultData.setValue(resultData.RESULT_KEY_PRICE, optionPriceAmount) resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE, resultData.PRICE_TYPE_EFFECTIVE) if optionFiatSymbol is not None and resultData.noError(): resultData = self._computeOptionFiatAmount(resultData, optionFiatSymbol, validFiatExchangeSymbol, crypto, unit, validCryptoUnitExchangeSymbol, year, month, day, hour, minute, dateTimeFormat, localTz) if optionValueSymbol is not None and resultData.noError(): resultData = self._computeOptionValueAmount(resultData, crypto, unit, optionFiatSymbol, optionValueSymbol, optionValueAmount, optionValueSaveFlag) return resultData
def getCryptoPrice(self, crypto, fiat, exchange, day, month, year, hour, minute, priceValueSymbol = None, priceValueAmount = None, priceValueSaveFlag = None, requestInputString = ''): ''' Ask the PriceRequester either a RT price or a historical price. Then, in case a price value parm (-v) was specified, does the conversion and add its result to the returned ResultData :param crypto: upper case crypto symbol :param fiat: upper case fiat symbol :param exchange: exchange name :param day: int day number :param month: int month number :param year: int year number :param hour: int hour number :param minute: int minute number :param priceValueSymbol: upper case price value symbol. If == crypto, this means that priceValueAmount provided is in crypto and must be converted into fiat at the rate returned by the PriceRequester. If the price value symbol == fiat, this means that priceValueAmount provided is in fiat and must be converted into crypto at the rate returned by the PriceRequester. Ex 1: -v0.001btc crypto == BTC fiat == USD priceValueSymbol == BTC priceValueAmount == 0.001 if returned rate (stored in ResultData.RESULT_KEY_PRICE entry) is 20000, converted value will be 20000 USD * 0.001 BTC => 200 USD Ex 2: -v500usd crypto == BTC fiat == USD priceValueSymbol == USD priceValueAmount == 500 if returned rate (stored in ResultData.RESULT_KEY_PRICE entry) is 20000, converted value will be 1 / 20000 USD * 500 USD => 0.025 BTC :param priceValueAmount: float price value amount :param priceValueSaveFlag: used to refine warning if value command not applicable :param requestInputString): used for better error msg ! :seqdiag_return ResultData :return: a ResultData filled with result values ''' if exchange == None: resultData = ResultData() resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG, "ERROR - exchange could not be parsed due to an error in your request ({})".format(requestInputString)) return resultData else: #this responsability is specific to the PriceRequester and should be moved to it ! try: validExchangeSymbol = self.crypCompExchanges.getExchange(exchange) except(KeyError): resultData = ResultData() resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG, "ERROR - {} market does not exist for this coin pair ({}-{})".format(exchange, crypto, fiat)) return resultData localTz = self.configManager.localTimeZone dateTimeFormat = self.configManager.dateTimeFormat if (day + month + year) == 0: # when the user specifies 0 for either the date, # this means current price is asked and date components # are set to zero ! resultData = self.priceRequester.getCurrentPrice(crypto, fiat, validExchangeSymbol) if resultData.isEmpty(ResultData.RESULT_KEY_ERROR_MSG): #adding date time info if no error returned timeStamp = resultData.getValue(ResultData.RESULT_KEY_PRICE_TIME_STAMP) requestedPriceArrowLocalDateTime = DateTimeUtil.timeStampToArrowLocalDate(timeStamp, localTz) requestedDateTimeStr = requestedPriceArrowLocalDateTime.format(dateTimeFormat) resultData.setValue(ResultData.RESULT_KEY_PRICE_DATE_TIME_STRING, requestedDateTimeStr) else: #getting historical price, either histo day or histo minute timeStampLocal = DateTimeUtil.dateTimeComponentsToTimeStamp(day, month, year, hour, minute, 0, localTz) timeStampUtcNoHHMM = DateTimeUtil.dateTimeComponentsToTimeStamp(day, month, year, 0, 0, 0, 'UTC') resultData = self.priceRequester.getHistoricalPriceAtUTCTimeStamp(crypto, fiat, timeStampLocal, timeStampUtcNoHHMM, validExchangeSymbol) if resultData.isEmpty(ResultData.RESULT_KEY_ERROR_MSG): #adding date time info if no error returned if resultData.getValue(ResultData.RESULT_KEY_PRICE_TYPE) == ResultData.PRICE_TYPE_HISTO_DAY: #histoday price returned requestedPriceArrowUtcDateTime = DateTimeUtil.timeStampToArrowLocalDate(timeStampUtcNoHHMM, 'UTC') requestedDateTimeStr = requestedPriceArrowUtcDateTime.format(self.configManager.dateTimeFormat) else: requestedPriceArrowLocalDateTime = DateTimeUtil.timeStampToArrowLocalDate(timeStampLocal, localTz) requestedDateTimeStr = requestedPriceArrowLocalDateTime.format(dateTimeFormat) resultData.setValue(ResultData.RESULT_KEY_PRICE_DATE_TIME_STRING, requestedDateTimeStr) if priceValueSymbol != None and not resultData.isError(): resultData = self._computePriceValue(resultData, crypto, fiat, priceValueSymbol, priceValueAmount, priceValueSaveFlag) return resultData