示例#1
0
	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)
示例#2
0
    def getCurrentPrice(self, crypto, unit, exchange):
        resultData = ResultData()

        if crypto == 'CHSB' and unit == 'BTC':
            rate = 0.000015  # causes CHSB/CHF to be 1.5
        elif crypto == 'BTC' and unit == 'CHF':
            rate = 100000  # causes CHSB/CHF to be 1.5
        elif crypto == 'BTC' and unit == 'USD':
            rate = 113333.3333  # causes CHSB/USD to be 1.7
        elif crypto == 'BTC' and unit == 'EUR':
            rate = 44250  # causes CHSB/EUR to be 0.66 since CHSB/BTC is set to 0.000015, a value which is not conform to reality but causes CHSB/CHF to be 1.5 !
        elif crypto == 'USD' and unit == 'CHF':
            rate = 0.9105
        elif crypto == 'CHF' and unit == 'USD':
            rate = 1 / 0.9105
        elif crypto == 'USD' and unit == 'EUR':
            rate = 0.8
        elif crypto == 'USDC' and unit == 'CHF':
            rate = 0.9105
        elif crypto == 'ETH' and unit == 'CHF':
            rate = 4000
        elif crypto == 'ETH' and unit == 'USD':
            rate = 4400  # coherent with USD/CHF value of 0.90909090
        else:
            raise ValueError(
                'Crypto {}/{} pair not supported by PriceRequesterTestStub. Complete PriceRequesterTestStub.getCurrentPrice() method and retry !'
                .format(crypto, unit))

        resultData.setValue(resultData.RESULT_KEY_PRICE, rate)

        return resultData
示例#3
0
    def execute(self):
        resultData = ResultData()
        errorDetails = self.parsedParmData[self.COMMAND_ERROR_MSG_KEY]
        errorType = self.parsedParmData[self.COMMAND_ERROR_TYPE_KEY]
        errorTypeLabelStr = ''
        errorMsgTail = ''

        if errorType == self.COMMAND_ERROR_TYPE_FULL_REQUEST:
            errorTypeLabelStr = 'full request'
            errorMsgTail = ' violates format <crypto> <fiat> <date|time> <exchange> <opt commands>'
        elif errorType == self.COMMAND_ERROR_TYPE_PARTIAL_REQUEST:
            errorTypeLabelStr = 'invalid partial request'
        elif errorType == self.COMMAND_ERROR_TYPE_INVALID_COMMAND:
            errorTypeLabelStr = 'invalid request'

        if errorDetails != '':
            errorDetails = ': ' + errorDetails

        resultData.setValue(
            ResultData.RESULT_KEY_ERROR_MSG,
            "ERROR - {} {}{}{}".format(errorTypeLabelStr,
                                       self.requestInputString, errorDetails,
                                       errorMsgTail))

        return resultData
    def testGetCryptoPriceHistoricalWrongExchange(self):
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'unknown'
        day = 12
        month = 9
        year = 2017
        hour = 10
        minute = 5

        resultData = ResultData()

        resultData.setValue(
            resultData.RESULT_KEY_ERROR_MSG,
            "ERROR - unknown market does not exist for this coin pair (BTC-USD)"
        )
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_MINUTE)

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual(
            "ERROR - unknown market does not exist for this coin pair (BTC-USD)\n",
            capturedStdout.getvalue())
示例#5
0
    def _validateMandatoryData(self):
        resultData = True

        fiat = self.parsedParmData[self.FIAT]

        if fiat == None or any(char.isdigit() for char in fiat):
            resultData = ResultData()
            resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG,
                                "ERROR - fiat missing or invalid")

        # debug code useful on phone !
        #        dateTimeList = [dayStr, monthStr, yearStr, hourStr, minuteStr]
        #        with open('/sdcard/compri.txt', 'a') as f:
        #            f.write(str(dateTimeList) + '\n')

        return resultData
示例#6
0
    def getHistoricalPriceAtUTCTimeStamp(self, crypto, unit,
                                         timeStampLocalForHistoMinute, localTz,
                                         timeStampUTCNoHHMMForHistoDay,
                                         exchange):
        '''
        Why do we pass two different time stamp to the method ?
        
        When requesting a minute price the time stamp obtained
        from a local arrow datetime object is used. If we
        request a minute price for 15:18 Zurich time (+00.02)
        time, the minute price returned is the one at UTC 13:18.
        Asking the same price from Mumbay would require to
        ask the price for 20:18 (+00.05).
        
        Now, when asking an histo day price, the returned price
        is a close price. But crypto trade 24 H a day. The "close"
        price time stamp must not be dependant from the location 
        from which the request is sent. Instead, the "close" price
        is the one at the passed date with hour and minute set to 0.
        This date is not a localiszd date, but a UTC localization
        independent date.
        
        When you go on the Cryptocompare site and you search for 
        historical prices, the close price for a given date is
        the same whatever the location of the user is !

        :seqdiag_note Obtainins a minute price if request date < 7 days from now, else a day close price.
        :seqdiag_return ResultData
        '''
        resultData = ResultData()

        resultData.setValue(ResultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(ResultData.RESULT_KEY_UNIT, unit)
        resultData.setValue(ResultData.RESULT_KEY_EXCHANGE, exchange)

        if DateTimeUtil.isTimeStampOlderThan(
                timeStampLocalForHistoMinute,
                localTz,
                dayNumberInt=MINUTE_PRICE_DAY_NUMBER_LIMIT):
            return self._getHistoDayPriceAtUTCTimeStamp(
                crypto, unit, timeStampUTCNoHHMMForHistoDay, exchange,
                resultData)
        else:
            return self._getHistoMinutePriceAtUTCTimeStamp(
                crypto, unit, timeStampLocalForHistoMinute, exchange,
                resultData)
示例#7
0
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 testGetCryptoPriceHistoricalRecent(self):
        #here, requested date is less than 7 days ago
        now = DateTimeUtil.localNow('Europe/Zurich')
        recent = now.shift(days=-2)
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'bittrex'
        day = recent.day
        month = recent.month
        year = recent.year
        hour = 10
        minute = 5

        resultData = ResultData()

        recentDay = recent.day

        if recentDay < 10:
            recentDayStr = '0' + str(recentDay)
        else:
            recentDayStr = str(recentDay)

        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_MINUTE)
        resultData.setValue(resultData.RESULT_KEY_PRICE, 4122.09)

        dateTimeString = '{}/{}/{} 10:05'.format(recentDayStr, month,
                                                 year - 2000)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            dateTimeString)

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual(
            'BTC/USD on BitTrex: {}M 4122.09\n'.format(dateTimeString),
            capturedStdout.getvalue())
    def testGetCryptoPriceRealTimeExchangeNotSupportPair(self):
        now = DateTimeUtil.localNow('Europe/Zurich')
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'BTC38'
        day = 0
        month = 0
        year = 0
        hour = 1
        minute = 1

        resultData = ResultData()

        resultData.setValue(
            resultData.RESULT_KEY_ERROR_MSG,
            "ERROR - BTC38 market does not exist for this coin pair (BTC-USD)")
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, exchange)
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_RT)
        resultData.setValue(resultData.RESULT_KEY_PRICE, None)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING, None)
        resultData.setValue(resultData.RESULT_KEY_PRICE_TIME_STAMP, None)

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual(
            "ERROR - BTC38 market does not exist for this coin pair (BTC-USD)\n",
            capturedStdout.getvalue())
    def testPrintCryptoPriceHistorical(self):
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'bittrex'

        resultData = ResultData()
        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_DAY)
        resultData.setValue(resultData.RESULT_KEY_PRICE, 4122)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            '12/09/17 00:00')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TIME_STAMP, 1505174400)

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual('BTC/USD on BitTrex: 12/09/17 00:00C 4122\n',
                         capturedStdout.getvalue())
    def testGetCryptoPriceRealTime(self):
        now = DateTimeUtil.localNow('Europe/Zurich')
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'bittrex'
        day = 0
        month = 0
        year = 0
        hour = 1
        minute = 1

        resultData = ResultData()

        nowMinute = now.minute

        if nowMinute < 10:
            if nowMinute > 0:
                nowMinuteStr = '0' + str(nowMinute)
            else:
                nowMinuteStr = '00'
        else:
            nowMinuteStr = str(nowMinute)

        nowHour = now.hour

        if nowHour < 10:
            if nowHour > 0:
                nowHourStr = '0' + str(nowHour)
            else:
                nowHourStr = '00'
        else:
            nowHourStr = str(nowHour)

        nowDay = now.day

        if nowDay < 10:
            nowDayStr = '0' + str(nowDay)
        else:
            nowDayStr = str(nowDay)

        #rt price not provided here !
        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_RT)
        dateTimeString = '{}/{}/{} {}:{}'.format(nowDayStr, now.month,
                                                 now.year - 2000, nowHourStr,
                                                 nowMinuteStr)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            dateTimeString)

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual('BTC/USD on BitTrex: {}R \n'.format(dateTimeString),
                         capturedStdout.getvalue())
    def testGetFullCommandStringYearNone(self):
        now = DateTimeUtil.localNow('Europe/Zurich')

        nowYearStr, nowMonthStr, nowDayStr, nowHourStr, nowMinuteStr = UtilityForTest.getFormattedDateTimeComponentsForArrowDateTimeObj(
            now)

        crypto = 'ETH'
        fiat = 'USD'

        resultData = ResultData()

        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_MINUTE)
        resultData.setValue(resultData.RESULT_KEY_PRICE, 465.52)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            '5/12/17 09:30')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TIME_STAMP, 1512462600)
        resultData.setValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS, {
                'CRYPTO': 'eth',
                'FIAT': 'usd',
                'EXCHANGE': 'bittrex',
                'DAY': '5',
                'MONTH': '12',
                'YEAR': None,
                'HOUR': '9',
                'MINUTE': '30',
                'DMY': None,
                'HM': None
            })
        resultData.setValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS, {
                'CRYPTO': 'eth',
                'FIAT': 'usd',
                'EXCHANGE': 'bittrex',
                'DAY': '5',
                'MONTH': '12',
                'YEAR': '17',
                'HOUR': '9',
                'MINUTE': '30',
                'DMY': None,
                'HM': None,
                'PRICE_VAL_AMOUNT': None,
                'PRICE_VAL_SYMBOL': None
            })

        fullCommandString, fullCommandStrWithOptions, fullCommandStrWithSaveModeOptions = self.printer.getFullCommandString(
            resultData)
        self.assertEqual(None, fullCommandStrWithSaveModeOptions)
        self.assertEqual(fullCommandString, "eth usd 05/12/17 09:30 bittrex")
    def testPrintCryptoPriceHistoricalPriceValueWarning(self):
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'BitTrex'

        resultData = ResultData()
        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, exchange)
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_DAY)
        resultData.setValue(resultData.RESULT_KEY_PRICE, 4122)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            '12/09/17 00:00')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TIME_STAMP, 1505174400)
        resultData.setValue(resultData.RESULT_KEY_PRICE_VALUE_CRYPTO, None)
        resultData.setValue(resultData.RESULT_KEY_PRICE_VALUE_FIAT, None)
        resultData.setWarning(
            ResultData.WARNING_TYPE_COMMAND_VALUE,
            "WARNING - price value symbol ETH differs from both crypto (BTC) and fiat (USD). -v parameter ignored !"
        )

        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual(
            'BTC/USD on BitTrex: 12/09/17 00:00C 4122\nWARNING - price value symbol ETH differs from both crypto (BTC) and fiat (USD). -v parameter ignored !\n',
            capturedStdout.getvalue())
示例#14
0
    def _validateDateTimeData(self, localNow):
        '''
        Ensures that date/time info contained in the parsedParmData dic are valid and in
        a right format. If everything is ok, returns True.

        ['1', '10', '0', '2', '58'] #btc usd 1/10/0 2:58
        [None, None, None, '2', '57'] # btc usd 1 2:57
        ['11', '10', None, None, None] # neo btc 11/10
        :param localNow:
        :return: True if date/time values stored in the parsedParmData dic are valid. If an
                 error was detected, a new ResultData with a meaningfull error msg is
                 returned.
        '''

        dtFormatDic = DateTimeUtil.getDateAndTimeFormatDictionary(
            self.configManager.dateTimeFormat)

        dateShortFormat = dtFormatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY]
        dateLongFormat = dtFormatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY]
        timeFormat = dtFormatDic[DateTimeUtil.TIME_FORMAT_KEY]

        resultData = True

        dayStr = self.parsedParmData[self.DAY]
        monthStr = self.parsedParmData[self.MONTH]
        yearStr = self.parsedParmData[self.YEAR]
        hourStr = self.parsedParmData[self.HOUR]
        minuteStr = self.parsedParmData[self.MINUTE]

        if (yearStr == '0' and monthStr == '0' and dayStr == '0'):
            # RT price asked
            return True
        else:
            # Here, the three date components are not all equal to 0 !
            if (yearStr == None and monthStr == None and dayStr == None
                    and hourStr != None and minuteStr != None):
                # Here, only time was specified in the full request, which is now possible.
                # Current day, month and year are fornatted into the parsed parm data
                # and True is returned
                self.parsedParmData[self.DAY] = localNow.format('DD')
                self.parsedParmData[self.MONTH] = localNow.format('MM')
                self.parsedParmData[self.YEAR] = localNow.format('YYYY')
                return True
            elif (yearStr == None and monthStr == None and dayStr != None
                  and hourStr != None and minuteStr != None):
                # Here, only day and time were specified in the full request, which is now possible.
                # Current month and year are fornatted into the parsed parm data
                # and True is returned
                self.parsedParmData[self.MONTH] = localNow.format('MM')
                self.parsedParmData[self.YEAR] = localNow.format('YYYY')
                return True
            elif (yearStr == '0' or
                  # yearStr is None when only day/month specified -> valid !
                  monthStr == '0' or monthStr == None or dayStr == '0'
                  or dayStr == None):
                # only when user enters -d0 for RT price,
                # is yearStr equal to '0' since 0 is put
                # by Requesèer into day, month and year !
                resultData = ResultData()
                resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG,
                                    "ERROR - date not valid")
                return resultData
            elif len(monthStr) > 2:
                resultData = ResultData()
                resultData.setValue(
                    ResultData.RESULT_KEY_ERROR_MSG,
                    "ERROR - {} not conform to accepted month format (MM or M)"
                    .format(monthStr))
                return resultData
            elif yearStr != None:
                yearStrLen = len(yearStr)
                if yearStrLen != 2 and yearStrLen != 4:
                    resultData = ResultData()
                    resultData.setValue(
                        ResultData.RESULT_KEY_ERROR_MSG,
                        "ERROR - {} not conform to accepted year format (YYYY, YY or '')"
                        .format(yearStr))

                    # avoiding that invalid year will pollute next price requests
                    self.parsedParmData[self.YEAR] = None
                    return resultData

            # validating full date. Catch inval day or inval month,
            # like day == 123 or day == 32 or month == 31
            if yearStr == None:
                yearStr = str(localNow.year)

            if hourStr == None:
                hourStr = str(localNow.hour)

            if minuteStr == None:
                minuteStr = str(localNow.minute)

            dateTimeTupleList = [('day', dayStr, dateShortFormat),
                                 ('month', monthStr, dateShortFormat),
                                 ('year', yearStr, dateLongFormat),
                                 ('hour', hourStr, timeFormat),
                                 ('minute', minuteStr, timeFormat)]

            try:
                for name, value, format in dateTimeTupleList:
                    int(value)
            except ValueError as e:
                resultData = ResultData()
                resultData.setValue(
                    ResultData.RESULT_KEY_ERROR_MSG,
                    "ERROR - invalid value: {} violates format for {} ({})".
                    format(value, name, format))
                return resultData

            try:
                date = DateTimeUtil.dateTimeComponentsToArrowLocalDate(
                    int(dayStr), int(monthStr), int(yearStr), int(hourStr),
                    int(minuteStr), 0, self.configManager.localTimeZone)
            except ValueError as e:
                resultData = ResultData()
                resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG,
                                    "ERROR - " + str(e))

        return resultData
    def testGetCryptoPriceRealTimeWithValueSaveFlag(self):
        #correspond to command btc usd 0 bittrex -vs0.01btc
        now = DateTimeUtil.localNow('Europe/Zurich')
        crypto = 'BTC'
        fiat = 'USD'
        exchange = 'bittrex'
        day = 0
        month = 0
        year = 0
        hour = 1
        minute = 1

        resultData = ResultData()

        nowMinute = now.minute

        if nowMinute < 10:
            if nowMinute > 0:
                nowMinuteStr = '0' + str(nowMinute)
            else:
                nowMinuteStr = '00'
        else:
            nowMinuteStr = str(nowMinute)

        nowHour = now.hour

        if nowHour < 10:
            if nowHour > 0:
                nowHourStr = '0' + str(nowHour)
            else:
                nowHourStr = '00'
        else:
            nowHourStr = str(nowHour)

        nowDay = now.day

        if nowDay < 10:
            nowDayStr = '0' + str(nowDay)
        else:
            nowDayStr = str(nowDay)

        #rt price not provided here !
        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_RT)
        dateTimeString = '{}/{}/{} {}:{}'.format(nowDayStr, now.month,
                                                 now.year - 2000, nowHourStr,
                                                 nowMinuteStr)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            dateTimeString)
        resultData.setValue(resultData.RESULT_KEY_PRICE_VALUE_CRYPTO, '0.01')
        resultData.setValue(resultData.RESULT_KEY_PRICE_VALUE_FIAT, '160')
        resultData.setValue(resultData.RESULT_KEY_PRICE_VALUE_SAVE, True)
        resultData.setValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS, {
                'CRYPTO': 'btc',
                'FIAT': 'usd',
                'EXCHANGE': 'bittrex',
                'DAY': '0',
                'MONTH': '0',
                'YEAR': '0',
                'HOUR': None,
                'MINUTE': None,
                'DMY': None,
                'HM': None,
                'PRICE_TYPE': 'REAL_TIME',
                'PRICE_VAL_DATA': None,
                'PRICE_VAL_AMOUNT': '0.01',
                'PRICE_VAL_SYMBOL': 'btc',
                'PRICE_VAL_SAVE': True
            })
        stdout = sys.stdout
        capturedStdout = StringIO()
        sys.stdout = capturedStdout

        self.printer.printDataToConsole(resultData)
        sys.stdout = stdout
        self.assertEqual(
            '0.01 BTC/160 USD on BitTrex: {}R \n'.format(dateTimeString),
            capturedStdout.getvalue())
        fullCommandString, fullCommandStrWithOptions, fullCommandStrWithSaveModeOptions = self.printer.getFullCommandString(
            resultData)
        self.assertEqual('btc usd 0 bittrex -vs0.01btc',
                         fullCommandStrWithSaveModeOptions)
        self.assertEqual('btc usd 0 bittrex', fullCommandString)
示例#16
0
	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 testGetFullCommandStringYearDefinedDupl(self):
        crypto = 'ETH'
        fiat = 'USD'

        resultData = ResultData()

        resultData.setValue(resultData.RESULT_KEY_ERROR_MSG, None)
        resultData.setValue(resultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(resultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(resultData.RESULT_KEY_EXCHANGE, 'BitTrex')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_MINUTE)
        resultData.setValue(resultData.RESULT_KEY_PRICE, 465.52)
        resultData.setValue(resultData.RESULT_KEY_PRICE_DATE_TIME_STRING,
                            '5/12/17 09:30')
        resultData.setValue(resultData.RESULT_KEY_PRICE_TIME_STAMP, 1512462600)
        resultData.setValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS, {
                'CRYPTO': 'eth',
                'FIAT': 'usd',
                'EXCHANGE': 'bittrex',
                'DAY': '5',
                'MONTH': '12',
                'YEAR': '17',
                'HOUR': '9',
                'MINUTE': '30',
                'DMY': None,
                'HM': None,
                'PRICE_VAL_AMOUNT': None,
                'PRICE_VAL_SYMBOL': None
            })

        fullCommandString, fullCommandStrWithOptions, fullCommandStrWithSaveModeOptions = self.printer.getFullCommandString(
            resultData)
        self.assertEqual(None, fullCommandStrWithSaveModeOptions)
        self.assertEqual(fullCommandString, "eth usd 05/12/17 09:30 bittrex")
示例#18
0
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))
示例#19
0
    def getCurrentPrice(self, crypto, unit, exchange):
        url = "https://min-api.cryptocompare.com/data/price?fsym={}&tsyms={}&e={}".format(crypto, unit, exchange)
        resultData = ResultData()

        resultData.setValue(ResultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(ResultData.RESULT_KEY_UNIT, unit)
        resultData.setValue(ResultData.RESULT_KEY_EXCHANGE, exchange)
        resultData.setValue(ResultData.RESULT_KEY_PRICE_TYPE, resultData.PRICE_TYPE_RT)

        try:
            if self.ctx == None:
                #here, run in QPython under Python 3.2
                webURL = urllib.request.urlopen(url)
            else:
                webURL = urllib.request.urlopen(url, context=self.ctx)
        except HTTPError as e:
            resultData.setError('ERROR - could not complete request ' + url + '. Reason: ' + str(e.reason) + '.')
        except URLError as e:
            resultData.setError('ERROR - No internet. Please connect and retry !')
        except: 
            the_type, the_value, the_traceback = sys.exc_info()
            resultData.setError('ERROR - could not complete request ' + url + '. Reason: ' + str(the_type) + '.')
        else:
            page = webURL.read()
            soup = BeautifulSoup(page, 'html.parser')
            dic = json.loads(soup.prettify())
            
            if unit in dic:
                resultData.setValue(ResultData.RESULT_KEY_PRICE_TIME_STAMP, DateTimeUtil.utcNowTimeStamp())
                resultData.setValue(ResultData.RESULT_KEY_PRICE, dic[unit]) #current price is indexed by unit symbol in returned dic
            else:
                resultData = self._handleProviderError(dic, resultData, url, crypto, unit, exchange, isRealTime=True)

        return resultData
示例#20
0
    def execute(self):
        '''

        :seqdiag_return ResultData or False
        :return:
        '''
        resultPriceOrBoolean = self._validateMandatoryData()

        if resultPriceOrBoolean != True:
            return resultPriceOrBoolean

        localTimezone = self.configManager.localTimeZone
        localNow = DateTimeUtil.localNow(localTimezone)

        resultPriceOrBoolean = self._validateDateTimeData(localNow)

        if resultPriceOrBoolean != True:
            return resultPriceOrBoolean

        cryptoUpper = self.parsedParmData[self.CRYPTO].upper()
        fiatUpper = self.parsedParmData[self.FIAT].upper()
        exchange = self.parsedParmData[self.EXCHANGE]

        dayStr = self.parsedParmData[self.DAY]

        if dayStr != None:
            day = int(dayStr)
        else:
            day = 0

        monthStr = self.parsedParmData[self.MONTH]

        if monthStr != None:
            month = int(monthStr)
        else:
            month = localNow.month

        yearStr = self.parsedParmData[self.YEAR]

        if yearStr != None:
            if len(yearStr) == 2:
                year = 2000 + int(yearStr)
            elif len(yearStr) == 4:
                year = int(yearStr)
            elif yearStr == '0':  # user entered -d0 !
                year = 0
        else:
            year = localNow.year

        hourStr = self.parsedParmData[self.HOUR]

        if hourStr != None:
            hour = int(hourStr)
        else:
            hour = 0

        minuteStr = self.parsedParmData[self.MINUTE]

        if minuteStr != None:
            minute = int(minuteStr)
        else:
            minute = 0

        #storing the parsed parm gata dicèionary before it
        #may be modified in case the user requested a RT
        #price. The initial dictionary wiLl be added to the
        #returned resultData so the client can have access
        #to the full command request, even if only a partial
        #request like -d or -c was entered. This is necessary
        #bcecause if the client is a GUI, it stores the list
        #of requests in order to be able to replay them !
        initialParsedParmDataDic = self.parsedParmData.copy()

        wasDateInFutureSetToLastYear = False
        localRequestDateTime = None

        if day + month + year == 0:
            # asking for RT price here. Current date is stored in parsed parm data for possible
            # use in next request
            self._storeDateTimeDataForNextPartialRequest(localNow)
        else:
            try:
                localRequestDateTime = DateTimeUtil.dateTimeComponentsToArrowLocalDate(
                    day, month, year, hour, minute, 0, localTimezone)
            except ValueError as e:
                # is the when the user specify only the day if he enters 31 and the current month
                # has no 31st or if he enters 30 or 29 and we are on February
                result = ResultData()
                result.setValue(
                    ResultData.RESULT_KEY_ERROR_MSG,
                    "ERROR - {}: day {}, month {}".format(str(e), day, month))
                return result

            if DateTimeUtil.isAfter(localRequestDateTime, localNow):
                # request date is in the future ---> invalid. This happens for example in case
                # btc usd 31/12 bittrex entered sometime before 31/12. Then the request year is
                # forced to last year and a warning will be displayed.
                year = localNow.year - 1
                wasDateInFutureSetToLastYear = True

        priceValueSymbol = self.parsedParmData[self.PRICE_VALUE_SYMBOL]
        priceValueAmount = self.parsedParmData[self.PRICE_VALUE_AMOUNT]

        if priceValueSymbol:
            priceValueSymbol = priceValueSymbol.upper()

        if priceValueAmount:
            priceValueAmount = float(priceValueAmount)

        priceValueSaveFlag = self.parsedParmData[self.PRICE_VALUE_SAVE]
        result = self.receiver.getCryptoPrice(cryptoUpper, fiatUpper, exchange,
                                              day, month, year, hour, minute,
                                              priceValueSymbol,
                                              priceValueAmount,
                                              priceValueSaveFlag,
                                              self.requestInputString)

        #the command components	denoting the user request will be used to recreate
        #a full command request which will be stored in the command history list.
        #The historry list can be replayed, stored on disk, edited ...
        result.setValue(ResultData.RESULT_KEY_INITIAL_COMMAND_PARMS,
                        initialParsedParmDataDic)

        result.setValue(ResultData.RESULT_KEY_PRICE_VALUE_SAVE,
                        priceValueSaveFlag)

        if wasDateInFutureSetToLastYear:
            result.setWarning(
                ResultData.WARNING_TYPE_FUTURE_DATE,
                "Warning - request date {} can not be in the future and was shifted back to last year"
                .format(
                    localRequestDateTime.format(
                        self.configManager.dateTimeFormat)))

        unsupportedCommand = self.parsedParmData[self.UNSUPPORTED_COMMAND]

        if unsupportedCommand:
            result.setWarning(
                ResultData.WARNING_TYPE_UNSUPPORTED_COMMAND,
                "Warning - unsupported command {}{} in request {}".format(
                    unsupportedCommand,
                    self.parsedParmData[self.UNSUPPORTED_COMMAND_DATA],
                    self.requestInputString))

        return result
示例#21
0
    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