Ejemplo n.º 1
0
 def __init__(self, ticker):
     self.ticker = ticker.upper()
     os.environ["FMP_API_KEY"] = "606d643d87241cde956b5cd85a3c56d1"
     self.fmp = FMP()
     self.today = datetime.today()
     self.this_year = self.today.year
     self.dividends_raw = self.get_dividends_raw()
Ejemplo n.º 2
0
 def test_get_quote_index(self, mock_request):
     fmp = FMP()
     file_path = self.get_file_from_name('mock_quote_index')
     with open(file_path) as f:
         mock_request.get(BASE_URL + "/quote/%5EGSPC?apikey=demo",
                          text=f.read())
         quote = fmp.get_index_quote('GSPC')
         self.assertIsInstance(quote, list)
Ejemplo n.º 3
0
 def test_get_quote(self, mock_request):
     fmp = FMP()
     file_path = self.get_file_from_name('mock_quote')
     with open(file_path) as f:
         mock_request.get(BASE_URL + "/quote/JMCRX,JSMTX,JUESX?apikey=demo",
                          text=f.read())
         quote = fmp.get_quote('JMCRX,JSMTX,JUESX')
         self.assertIsInstance(quote, list)
Ejemplo n.º 4
0
 def test_short_quote(self, mock_request):
     fmp = FMP()
     file_path = self.get_file_from_name('mock_quote_short')
     with open(file_path) as f:
         mock_request.get(BASE_URL + "/quote-short/AAPL?apikey=demo",
                          text=f.read())
         quote_short = fmp.get_quote_short('AAPL')
         self.assertIsInstance(quote_short, list)
Ejemplo n.º 5
0
 def test_get_historical_price(self, mock_request):
     fmp = FMP()
     file_path = self.get_file_from_name('mock_historical_price')
     with open(file_path) as f:
         mock_request.get(BASE_URL +
                          "/historical-price-full/JMCRX?apikey=demo",
                          text=f.read())
         quote = fmp.get_historical_price('JMCRX')
         self.assertIsInstance(quote, list)
Ejemplo n.º 6
0
 def test_get_historical_chart_index(self, mock_request):
     fmp = FMP()
     file_path = self.get_file_from_name('mock_historical_chart_index')
     with open(file_path) as f:
         mock_request.get(BASE_URL +
                          "/historical-chart/4hour/%5EGSPC?apikey=demo",
                          text=f.read())
         quote = fmp.get_historical_chart_index('4hour', 'GSPC')
         self.assertIsInstance(quote, list)
Ejemplo n.º 7
0
class DividendProcessor(object):
    def __init__(self, ticker):
        self.ticker = ticker.upper()
        os.environ["FMP_API_KEY"] = "606d643d87241cde956b5cd85a3c56d1"
        self.fmp = FMP()
        self.today = datetime.today()
        self.this_year = self.today.year
        self.dividends_raw = self.get_dividends_raw()

    def get_dividends_raw(self):
        # dividend, date  - historical dividend values and dates
        self.dividends_raw = self.fmp.get_dividends(self.ticker, 'historical-price-full/stock_dividend')

        # set proper DateTime object as the index of the dataframe
        self.dividends_raw['Datetime'] = pd.to_datetime(self.dividends_raw['date'])

        try:
            # find days difference between rows. Needed to see data gap (for instane AAPL dividends)
            self.dividends_raw['Datetime_DaysDiffRows']=self.dividends_raw['Datetime'].diff().dt.days
            # find if there is more than 400 days passed between rows. If that happens, delete all rows below
            index_of_first_gap = np.where(self.dividends_raw['Datetime_DaysDiffRows'].lt(-400))[0][0]
            self.dividends_raw = self.dividends_raw.iloc[:index_of_first_gap]
        except: 
            # no gaps found in datetime
            pass
        
        self.dividends_raw = self.dividends_raw.set_index('Datetime')
        self.dividends_raw["Symbol"] = self.ticker
        # export to csv. Use header only for the first time, then only append new rows
        # output_path = r'C:\Users\50000700\Python\Python_repos\dividends\excel_files\dividends_raw.csv'
        # self.dividends_raw.to_csv(output_path, mode='a', header=not os.path.exists(output_path))
        print (self.dividends_raw)
        return self.dividends_raw   

    def get_real_time_price(self):
        self.real_time_price = self.fmp.get_quote_short(self.ticker)
        print (f"REAL TIME PRICE {self.real_time_price}")
        return self.real_time_price

    def get_dividends_per_year(self):
        # resample annually and sum dividend values. Note that year end (Dec 31) will be shown for all groups
        dividends_per_year = self.dividends_raw.resample("A")["adjDividend"].sum()
        return dividends_per_year

    def get_dividend_frequency_of_prev_year(self):
        # calculates the last year's dividend frequency and returns how many times it was paid
        dividends = self.dividends_raw.resample("A")["date"].count()
        mask = (dividends.index > (str(self.this_year-1)+'-01-01')) & (dividends.index <= (str(self.this_year-1)+'-12-31'))
        dividends_filtered=dividends.loc[mask]
        return dividends_filtered.iloc[0]

    def get_dividend_dates_values_of_year(self, year):
        mask = (self.dividends_raw.index > (str(year)+'-01-01')) & (self.dividends_raw.index <= (str(year)+'-12-31'))
        dividends_filtered=self.dividends_raw.loc[mask]
        return dividends_filtered

    def get_dividend_months_of_year(self, year):
        mask = (self.dividends_raw.index > (str(year)+'-01-01')) & (self.dividends_raw.index <= (str(year)+'-12-31'))
        dividends_filtered_of_year=self.dividends_raw.loc[mask]
        list_of_div_months = dividends_filtered_of_year.index.tolist()
        list_of_div_months = [date.strftime("%m") for date in list_of_div_months]
        return list_of_div_months

    def is_div_frequency_same_for_years(self, new_year, old_year):
        # if no dividends paid - early in the year return same frequency as old year
        if len(self.get_dividend_months_of_year(new_year))==0:
            return True
        if all(elem in self.get_dividend_months_of_year(old_year)  for elem in self.get_dividend_months_of_year(new_year)):
            return True
        else:
            raise ValueError(f"Dividend frequency of ticker {self.ticker} for years {new_year} and {old_year} don't match. Further calculation is not possible!")

    def get_forward_dividend(self):
        # take last dividend paid and multiply it with the dividend payment frequency
        last_dividend = self.dividends_raw.iloc[0]["adjDividend"]
        if self.is_div_frequency_same_for_years(self.this_year, self.this_year-1):
            return (last_dividend * self.get_dividend_frequency_of_prev_year())
        else:
            raise ValueError(f"Dividend frequency of ticker {self.ticker} for years {self.this_year} and {self.this_year-1} don't match. Further calculation is not possible!")
        
    def get_dividend_yield(self):
        # returns dividend yield in %
        self.real_time_price = self.get_real_time_price()
        try: 
            return (self.get_forward_dividend() / self.real_time_price.iloc[0]["price"] * 100)
        except:
            print ("No real time price data is available from API")
            return -1

    def get_dividend_growth_per_year(self):
        # get dividend growth per year
        dividend_gr_per_yr = pd.DataFrame()
        # remove current year line as it cannot be complete and we are interested in historical data

        dividend_gr_per_yr['yearlyDividendValue'] = self.dividends_raw.resample("A")["adjDividend"].sum()
        dividend_gr_per_yr['dividendGrowth'] = dividend_gr_per_yr.pct_change()
        dividend_gr_per_yr = dividend_gr_per_yr.sort_index(ascending=False)

        # mask out row of current year
        mask = (dividend_gr_per_yr.index <= (str(self.this_year-1)+'-12-31'))
        dividend_gr_per_yr_filtered=dividend_gr_per_yr.loc[mask]

        return dividend_gr_per_yr_filtered

    def get_most_recent_dividend_cut_year(self):
        # result is the closest year from today when the dividend was cut last time. From that year he dividends are increasing again
        # if there is a dividend cut, then the yearly dividend growth rate will contain a negative growth for the particular cut year
        div_gr_per_year = self.get_dividend_growth_per_year()
        index = div_gr_per_year.dividendGrowth.lt(0).idxmax()

        # if index is the most recent date of the dataframe (first element), then set it to 1970-1-1 showing, that there was not a single cut in the dividends
        # print (f"first valid index {div_gr_per_year.first_valid_index()}")
        if index == div_gr_per_year.first_valid_index():
            # if there is an unlikely event of the most recent year was a div cut (see ticker ABM), then return this most recent year
            print (f"first element of div grwth rate {div_gr_per_year.iloc[0][1]}")
            if div_gr_per_year.iloc[0][1] < 0:
                return index
            else:  
                return datetime(1970, 1, 1)
        return index

    def get_DGR_3_5yr(self):
        # calculate DGR1yr, DGR3yr, DGR5yr and potentially DGR10yr
        # note, that CAGR calculation is used. http://www.moneychimp.com/features/cagr.htm
        # give it current dividend, old dividend and number of years
        # calculation gives uniform yearly growth value to reach final dividend
        # note that dripinvesting has mistakes in their input data and they will not always match with this result
        dividend_gr_per_yr = self.get_dividend_growth_per_year()
        years_to_check = [3,5,10,15]
        list_of_DGR = {}
            
        last_dividend_cut_year = self.get_most_recent_dividend_cut_year()
        print (f"first dividend cut year index from today {last_dividend_cut_year}")
        
        for year in years_to_check:
            mask = (dividend_gr_per_yr.index > (str(self.this_year-year)+'-01-01')) & (dividend_gr_per_yr.index <= (str(self.this_year-1)+'-12-31'))
            dividends_gr_x_yr=dividend_gr_per_yr.loc[mask]
            if len(dividends_gr_x_yr.index) == year and last_dividend_cut_year.year < (self.this_year-year) :
                div_current = dividends_gr_x_yr.iloc[0]["yearlyDividendValue"]
                div_old = dividends_gr_x_yr.iloc[-1]["yearlyDividendValue"]
                cagr = (((div_current / div_old) ** (1/year)) - 1) * 100
                print (f"year {year} div_current {div_current} div_old {div_old} cagr {cagr}")
                list_of_DGR[year] = cagr
        return (list_of_DGR)
Ejemplo n.º 8
0
# read the excel file
# combine rows 4-5 to be the header. By doing this the real pandas df will start from the header (and you don't need to drop rows..)
# note that in case the top cell is empty, then it will use the closest top cell value to the left.
# EXAMPLE: "TickerSymbol" column (col "B" in excel) name is correct. But the next column is empty top cell and "Sector" bottom cell (col "C" in excel).
#           Now it will be "TickerSector"
df = pd.read_excel(listOfFiles[0], sheet_name='All CCC', header=[4, 5])

# flatten the multi index header: https://stackoverflow.com/questions/41931332/how-do-i-flatten-a-hierarchical-column-index-in-a-pandas-dataframe
df.columns = df.columns.map(lambda x: ''.join([*map(str, x)]))

# drop last rows of summary where not individual companies are shown but sector performance
df = df.dropna(subset=['TickerSector'])
ticker_list = df['TickerSymbol'].tolist()

os.environ["FMP_API_KEY"] = "606d643d87241cde956b5cd85a3c56d1"
fmp = FMP()


def get_dividend_df_of(symbol):
    # dividend, date  - historical dividend values and dates
    dividends_raw = fmp.get_dividends_and_stock_splits(
        symbol, 'historical-price-full/stock_dividend')
    # set proper DateTime object as the index of the dataframe
    dividends_raw['Datetime'] = pd.to_datetime(dividends_raw['date'])

    try:
        # find days difference between rows. Needed to see data gap (for instane AAPL dividends)
        dividends_raw['Datetime_DaysDiffRows'] = dividends_raw[
            'Datetime'].diff().dt.days
        # find if there is more than 400 days passed between rows. If that happens, delete all rows below
        index_of_first_gap = np.where(