Ejemplo n.º 1
0
class AlphaBehavior:
    def __init__(self):
        self.da = DateAdjuster()

    def getStockData(self, baseURL, endpoint, ticker, outputSize, credentials,
                     end_date, start_date):

        sequence = (baseURL, endpoint, '&symbol=', ticker, '&outputsize=',
                    outputSize, '&apikey=', credentials)
        url = ''.join(map(str, sequence))
        response = requests.get(url)

        if response.status_code != 200:
            errorMessage = 'Check your AlphaVantage API key, or URL address'
            raise Exception(errorMessage)

        for key in response.json():
            if key != 'Meta Data':
                timeSeries = response.json()[key]
        if type(timeSeries) is str:
            raise Exception(
                'calling alphaVantage too quickly, slow your roll bro')
        values = list(timeSeries.values())

        endDateAsDate = self.da.convertToDate(end_date)
        startDateAsDate = self.da.convertToDate(start_date)

        data = dict()
        if len(timeSeries) < 1:
            print('Unable to retrieve company data from AlphaVantage for ' +
                  ticker)
        else:
            if end_date == start_date:
                for index, date in enumerate(
                        map(self.da.convertToDate, timeSeries.keys())):
                    if date <= endDateAsDate and date >= endDateAsDate - timedelta(
                            days=28):
                        data[date] = values[index]
            else:
                for index, date in enumerate(
                        map(self.da.convertToDate, timeSeries.keys())):
                    if date <= endDateAsDate and date >= startDateAsDate:
                        data[date] = values[index]

        return data
Ejemplo n.º 2
0
    def __init__(self, isHistoricalMode, appSettings, tickerInput):
        """
        The constructor takes in the historical mode bool, an AppSettings object,
        and a ticker symbol. It then grabs the api specs based on whether
        or not historical mode is true and passes it to the specifyAPI() method.
        """
        self.stockAPICallers = dict()
        self.da = DateAdjuster()
        self.isHistoricalMode = isHistoricalMode

        if isHistoricalMode is True:
            self.settings = appSettings.getHistoricalSettings()
            self.referenceDate = self.settings.pop('referenceDate')
        else:
            self.settings = appSettings.getDefaultSettings()
            self.referenceDate = self.da.adjustDate(datetime.today(),
                                                    'referenceDate')

        self.tickerInput = tickerInput

        for i in self.settings:
            self._specifyAPI(self.settings[i]['api'], self.settings[i]['key'],
                             self.settings[i]['dataRequest'])
class IntrinioBehavior_20DayAvg(IntrinioBehavior):
    def __init__(self):
        super().__init__()
        self.item = 'close_price'
        self.da = DateAdjuster()

    def getStockData(self, baseURL, endpoint, ticker, credentials, item,
                     end_date, start_date):

        intrinioData = super().getStockData(baseURL, endpoint, ticker,
                                            credentials, self.item, end_date,
                                            start_date)

        output = pd.DataFrame()
        close_price = []
        date = []
        if len(intrinioData) == 0:
            close_price.append(float('nan'))
            date.append(float('nan'))
            output = pd.DataFrame({
                'ticker': ticker,
                '20Day_Avg': close_price,
                '20Day_Avg_EndDate': ''
            })
            print(
                'Unable to retrieve 20-day moving average from Intrinio for ' +
                ticker)
        else:
            for i in reversed(intrinioData):
                close_price.append(float(i['value']))
                date.append(self.da.convertToDate(i['date']))

            output = pd.DataFrame({
                'ticker': ticker,
                'close_price': close_price,
                '20Day_Avg_EndDate': date
            })

            output['20Day_Avg'] = output['close_price'].rolling(
                20, min_periods=1).mean()

            output = pd.DataFrame(
                output[['ticker', '20Day_Avg',
                        '20Day_Avg_EndDate']].iloc[len(output) - 1]).T
        return output
 def __init__(self):
     super().__init__()
     self.da = DateAdjuster()
Ejemplo n.º 5
0
class BriefingBehavior_Earnings(BriefingBehavior):
    def __init__(self):
        super().__init__()
        self.da = DateAdjuster()

    def getStockData(self, baseURL, endpoint, ticker, credentials, item=''):
        rawHTML = super().getStockData(baseURL, endpoint, ticker, credentials,
                                       item)
        self.ticker = ticker
        output = self.parseHTML(rawHTML)
        return output

    def parseHTML(self, html):
        soup = BeautifulSoup(html, 'html.parser')
        divs = soup.find_all('div', class_='NoInplayDataContent')

        hasTable = divs[0].find_all(
            'div', class_="noInplayDataDiv DoNotHighlightAnything")

        if len(hasTable) is 0:
            table = pd.read_html(str(divs[0].table))[0]

            if len(table) <= 5:
                priorYear_s = float('nan')
            else:
                priorYear_s = float(table.iloc[5, 16])

            if len(table) < 2 or table.iloc[1, 20] != table.iloc[1, 20]:
                y2YRev = float('nan')
            else:
                y2YRev = float(re.sub('\\s|%', '', table.iloc[1, 20])) / 100

            if len(table) < 2 or table.iloc[1, 0] != table.iloc[1, 0]:
                date = ''
            else:
                date = self.da.convertToDate(table.iloc[1, 0],
                                             dateStringFormat='%d-%b-%y')

            if len(table) > 1:
                estimate_e = table.iloc[1, 12]
                actual_e = table.iloc[1, 10]
                estimate_s = table.iloc[1, 18]
                actual_s = table.iloc[1, 16]
                priorYear_e = table.iloc[1, 14]
            else:
                estimate_e = actual_e = estimate_s = actual_s = priorYear_e = float(
                    'nan')

            table = pd.DataFrame(data={
                'ticker': self.ticker,
                'Date': date,
                'Year2YearRev': y2YRev,
                'Estimate_E': estimate_e,
                'Actual_E': actual_e,
                'Estimate_S': estimate_s,
                'Actual_S': actual_s,
                'PriorYear_E': priorYear_e,
                'PriorYear_S': priorYear_s
            },
                                 index=[0])
        else:
            table = pd.DataFrame(data={
                'ticker': self.ticker,
                'Date': '',
                'Year2YearRev': float('nan'),
                'Estimate_E': float('nan'),
                'Actual_E': float('nan'),
                'Estimate_S': float('nan'),
                'Actual_S': float('nan'),
                'PriorYear_E': float('nan'),
                'PriorYear_S': float('nan')
            },
                                 index=[0])

        return table
Ejemplo n.º 6
0
class Controller:
    global da

    tickerInput = []
    stockAPICallers = dict()
    fileInput = False
    isHistoricalMode = False

    referenceDate = ''
    trailingDays = 155
    userSpecifiedDate = ''

    settings = dict()

    def __init__(self, isHistoricalMode, appSettings, tickerInput):
        """
        The constructor takes in the historical mode bool, an AppSettings object,
        and a ticker symbol. It then grabs the api specs based on whether
        or not historical mode is true and passes it to the specifyAPI() method.
        """
        self.stockAPICallers = dict()
        self.da = DateAdjuster()
        self.isHistoricalMode = isHistoricalMode

        if isHistoricalMode is True:
            self.settings = appSettings.getHistoricalSettings()
            self.referenceDate = self.settings.pop('referenceDate')
        else:
            self.settings = appSettings.getDefaultSettings()
            self.referenceDate = self.da.adjustDate(datetime.today(),
                                                    'referenceDate')

        self.tickerInput = tickerInput

        for i in self.settings:
            self._specifyAPI(self.settings[i]['api'], self.settings[i]['key'],
                             self.settings[i]['dataRequest'])

    def _specifyAPI(self, api, key, dataRequest):
        """
        Makes sure the api specs are formatted and specified properly with
        'validateDataRequest()', and then retrieves the appropriate StockAPICaller 
        objects from the factory.
        """
        apiArgs = dict()
        apiArgs[api] = key
        dataRequest = self._validateDataRequest(api, dataRequest)
        self.stockAPICallers[len(self.stockAPICallers)] = apiFactory.getAPI(
            apiFactory, apiArgs, dataRequest)

    def callAPIs(self, tickerInput):
        apiData = pd.DataFrame()
        for caller in self.stockAPICallers:
            results = self.stockAPICallers[caller].getStockData(tickerInput)
            if len(apiData) != 0:
                apiData = pd.merge(apiData, results, on='ticker', how='left')
            else:
                apiData = results
        return apiData

    def _validateDataRequest(self, api, dataRequest):
        """
        Raises exceptions if there data requests are specified improperly.
        Allows for specifying the historical_data requests incompletely by having 
        default behavior, i.e. it uses today as the end_date if end_date isn't specified.
        
        Adjusts dates based on day of week through the DateAdjuster class.
        """

        if 'endpoint' not in dataRequest:
            raise Exception('You must provide an endpoint!')
        elif 'item' not in dataRequest and api == 'intrinio':
            raise Exception(
                'You must provide an item when you call the Intrinio API!')
        else:
            if 'start_date' in dataRequest and 'end_date' not in dataRequest:
                raise Exception('If you provide a start_date,' +
                                ' then you must also provide an end_date!')
            elif 'end_date' in dataRequest and 'start_date' not in dataRequest:
                dataRequest['end_date'] = self.da.adjustDate(
                    dataRequest['end_date'], dataRequest['item'])
                dataRequest['start_date'] = self.da.defineStartDate(
                    dataRequest['end_date'])
            elif 'end_date' not in dataRequest and 'start_date' not in dataRequest:
                dataRequest['end_date'] = self.da.defineEndDate(
                    dataRequest['item'])
                dataRequest['start_date'] = self.da.defineStartDate(
                    dataRequest['end_date'])
            elif 'end_date' in dataRequest and 'start_date' in dataRequest:
                if dataRequest['end_date'] == dataRequest['start_date']:
                    dataRequest['end_date'] = self.da.adjustDate(
                        dataRequest['end_date'], 'pointVolume')
                    dataRequest['start_date'] = self.da.adjustDate(
                        dataRequest['start_date'], 'pointVolume')
                else:
                    dataRequest['end_date'] = self.da.adjustDate(
                        dataRequest['end_date'], dataRequest['item'])
                    dataRequest['start_date'] = self.da.adjustDate(
                        dataRequest['start_date'], dataRequest['item'])
            elif dataRequest['endpoint'] == 'data_point':
                if 'end_date' in dataRequest or 'start_date' in dataRequest:
                    raise Exception(
                        "The 'data_point' endpoint does not take in dates" +
                        " - it provides current data!")

        return dataRequest
Ejemplo n.º 7
0
 def __init__(self):
     self.fw = FileWriter()
     self.fr = FileReader()
     self.asf = AppSettingsFactory()
     self.da = DateAdjuster()
Ejemplo n.º 8
0
class UserInterface:
    isHistoricalMode = False

    def __init__(self):
        self.fw = FileWriter()
        self.fr = FileReader()
        self.asf = AppSettingsFactory()
        self.da = DateAdjuster()

    def runApplication(self, userSettingsProfile, isHistoricalMode,
                       referenceDate, ticker):
        """
        This is the method that the user interacts with directly to retrieve stock data.
        """
        self.setAppSettings(userSettingsProfile, isHistoricalMode,
                            referenceDate)
        self.setTickerInput(ticker)
        return self.handleRequest()

    def setAppSettings(self, userSettings, isHistoricalMode, referenceDate):
        """
        Sends parameters to the AppSettingsFactory and returns the appropriate 
        AppSettings object.
        """
        if type(referenceDate) is not str:
            raise Exception(
                "Error: the referenceDate arg must be a text string")
        elif referenceDate == '':
            referenceDate = datetime.strftime(date.today(), '%Y-%m-%d')
        if type(isHistoricalMode) is not bool:
            raise Exception(
                "Error: the isHistoricalMode arg must be boolean ('True' or 'False')"
            )
        if type(userSettings) is not str:
            raise Exception(
                "Error: the desiredSettings arg must be a text string")

        self.referenceDate = referenceDate
        self.isHistoricalMode = isHistoricalMode
        self.appSettings = self.asf.getAppSettings(userSettings,
                                                   self.referenceDate,
                                                   self.isHistoricalMode)

    def setTickerInput(self, tickerInput):
        if type(tickerInput) is not str:
            raise Exception("Error: the tickers arg must be a text string")
        self.tickerInput = tickerInput

    def handleRequest(self):
        """
        Builds the Controller object, passes the relevant info, and calls the API with it.
        
        After that its cleaning the data based on UserSettings.OutputManager specs.
        
        It sets the referenceDate here outside of any other process to give the user feedback
        for what they entered, because the dates get shifted based on specs and day of week.
        """
        c = Controller(self.isHistoricalMode, self.appSettings,
                       self.tickerInput)
        stockData = c.callAPIs(self.tickerInput)

        outputManager = self.appSettings.getOutputManager()
        outputManager.setHistoricalMode(self.isHistoricalMode)

        outputManager.identifyColNames(stockData)
        stockData = outputManager.calcNewColumns(stockData)
        stockData = outputManager.deleteExtraCols(stockData)
        stockData['referenceDate'] = self.da.convertToDate(c.referenceDate)
        stockData = outputManager.reindexColumns(stockData)
        stockData = outputManager.renameColumns(stockData)
        return stockData

    def printToFile(self, dataFrame):
        self.fw.writeToFile(dataFrame, 'results.xlsx')

    def readTickerInput(self, userInput):
        output = userInput
        match = re.search('\\.[a-zA-Z]*$', userInput, flags=0)
        if match:
            if match.group(0) == '.xlsx' or match.group(0) == '.csv':
                output = self.fr.readExcel(userInput)
            else:
                raise Exception(
                    'Currently only .xlsx and .csv files are supported.')
        return output
Ejemplo n.º 9
0
 def __init__(self):
     self.da = DateAdjuster()
 def __init__(self):
     super().__init__()
     self.item = 'close_price'
     self.da = DateAdjuster()