I am trying to write a simple screener searching for buy signals among Dividend Aristocrats uploaded from a .csv file. The screener ought to iterate for each ticker and upload the dividends paid in the last year period (a setting). Then it should calculate three conditions
the amount of dividends paid within a year x100 should be above the 4 % of the current price
The last price should be at least 10 % or above the last year minimum price
The price should be above 50 SMA
I have two issues
First issue is that my ticker iteration does not start. It only iterates the first ticker. No code alarms of any kind, it just does not do the work.
Second issue is with my 1.st condition. I can not retrieve the dividends for the defined period of time nor do any kind of sumation.
Please advise
Thanks
Stock Screener
import pandas as pd
import yfinance as yf
import pandas_datareader as web
import datetime
from datetime import timedelta
import numpy as np
import talib as ta
# List of tickers
index_to_keep = [1]
data = pd.read_csv('/home/ata/MEGAsync/Python/DAI.csv',error_bad_lines = False,
engine = 'python',usecols = [0],skiprows=2)
# timeframe definition
st_dni=400 # one year + (can be changed)
end = datetime.date.today() # from today
start = end-timedelta(days=st_dni) # back
for ticker in data:
df = web.DataReader(ticker,'yahoo',start, end) # ticker data
stock=yf.Ticker(ticker,start) # dividend data
div = stock.dividends(period='st_dni')
sum(div) # dividend (1st cond)
dataframe = np.array(df) # np array conversion
hi = np.round(dataframe[:,1])
lo = np.round(dataframe[:,2])
hl = (hi+lo)/2 # hi/lo values
df_min = np.min(lo) # year low (2nd cond)
mabig = ta.SMA(ohlc,50) # SMA (3rd cond)
CSV file is available on this link
Problem solved
First issue solved with
...
for ticker in data:
ticker = data.loc[i,'SYMBOL']
...
Second issue solved with
...
stock = yf.Ticker(ticker)
temp = pd.DataFrame(stock.dividends)
div = temp.loc[start:end]
...
I hope someone find this useful.
Related
import pandas as pd
import yfinance as yf
import pendulum
from datetime import date
today = str(date.today())
print(today)
pd.options.display.max_rows=390
start = pendulum.parse('2022-12-5 08:30')
end = pendulum.parse('2022-12-5 15:00')
stock = input("Enter a stock ticker symbol: ")
print(stock + " 1 Minute Data")
print(start)
print(yf.download(tickers= stock, interval="1m", start=start, end=end))
Running the code and typing in "TSLA" will load up every tick for the specified date. How would I export this array in a clean fashion to excel?
Side note: I was also trying to put today's date instead of pendulum's manual date '2022-12-5'
Is there a way to also use the current date for pendulum.parse instead of manually typing it out every time? I tried making the date a variable but got an error etc.
Well, I suspect yf.download is returning a pandas dataframe, so you could just save it to Excel using panda's to_excel function, unless there is more structure or processing you need to do.
df = yf.download(...)
df.to_excel('ticker_data.xlsx')
Question 1:
It returns a dataframe but you need to reset the index to bring Datetime column from index to column. You can chain all the commands together.
Question 2:
pendulum.parse() takes a str so you just need to use an fstring.
import pendulum
import yfinance as yf
start = pendulum.parse(f"{pendulum.now().date()} 08:30")
end = pendulum.parse(f"{pendulum.now().date()} 15:00")
stock = input("Enter a stock ticker symbol: ")
(yf
.download(tickers=stock, interval="1m", start=start, end=end)
.reset_index()
.to_excel(f"/path/to/file/{stock.lower()}.xlsx", index=False, sheet_name=stock)
)
I am using yahooquery to download historical data for APPL
When I print the results I can see there is the Date alongside the price. However when I download the result in a csv file the date is no longer available.
As I would need to also have the date for the price I am wondering if I am doing anything wrong and if so how can I fix it
from yahooquery import Ticker
import numpy as np
aapl = Ticker('APPL')
price = aapl.history(period='max')
np.savetxt('C:\APPL.csv', price)
Yahooquery uses multiple index, so you should reset it to single index.
Use
price = price.reset_index(level=[0,1])
This will tranform the symbol column into index and the date column into first column
I am using the below code to parse a large tickers list to yahoo datareader, I am trying to get back a dataframe as per below. If the list is large, I often get a RemoteError back but on different tickers each time. I am not sure how to handle the RemoteError and I am happy to drop the ticker and continue with the next ticker in the list. I would, however, like to try again to get adj close ticker data. I thought using a for loop and adding a time delay would help with yahoo requests but I am still getting a Remote error. Any ideas?
IBM MSFT ORCL TSLA YELP
Date
2014-01-02 184.52 36.88 37.61 150.10 67.92
2014-01-03 185.62 36.64 37.51 149.56 67.66
2014-01-06 184.99 35.86 37.36 147.00 71.72
2014-01-07 188.68 36.14 37.74 149.36 72.66
2014-01-08 186.95 35.49 37.61 151.28 78.42
import pandas_datareader.data as web
import datetime as dt
import pandas as pd
import time
from pandas_datareader._utils import RemoteDataError
Which_group = ['Accident & Health Insurance'] ##<<<<put in group here
df = pd.read_csv('/home/ross/Downloads/UdemyPairs/stocks1.csv')
df.set_index('categoryName', inplace = True)
df1 = df.loc[Which_group]
tickers = df1.Ticker.tolist()
print(tickers)
#tickers = ['SPY', 'AAPL', 'MSFT'] # add as many tickers
start = dt.datetime(2013, 1,1)
end = dt.datetime.today()
# Function starts here
def get_previous_close(strt, end, tick_list, this_price):
""" arg: `this_price` can take str Open, High, Low, Close, Volume"""
#make an empty dataframe in which we will append columns
adj_close = pd.DataFrame([])
# loop here.
for idx, i in enumerate(tick_list):
try:
# time.sleep(0.01)
total = web.DataReader(i, 'yahoo', strt, end)
adj_close[i] = total[this_price]
except RemoteDataError:
pass
return adj_close
#call the function
print(get_previous_close(start, end, tickers, 'Adj Close'))
Maybe you can look at this question. This proposes a solution that it might work for you.
Pandas Dataframe - RemoteDataError - Python
From the daily stock price data, I want to sample and select end of the month price. I am accomplishing using the following code.
import datetime
from pandas_datareader import data as pdr
import pandas as pd
end = datetime.date.today()
begin=end-pd.DateOffset(365*2)
st=begin.strftime('%Y-%m-%d')
ed=end.strftime('%Y-%m-%d')
data = pdr.get_data_yahoo("AAPL",st,ed)
mon_data=pd.DataFrame(data['Adj Close'].resample('M').apply(lambda x: x[-2])).set_index(data.index)
The line above selects end of the month data and here is the output.
If I want to select penultimate value of the month, I can do it using the following code.
mon_data=pd.DataFrame(data['Adj Close'].resample('M').apply(lambda x: x[-2]))
Here is the output.
However the index shows end of the month value. When I choose penultimate value of the month, I want index to be 2015-12-30 instead of 2015-12-31.
Please suggest the way forward. I hope my question is clear.
Thanking you in anticipation.
Regards,
Abhishek
I am not sure if there is a way to do it with resample. But, you can get what you want using groupby and TimeGrouper.
import datetime
from pandas_datareader import data as pdr
import pandas as pd
end = datetime.date.today()
begin = end - pd.DateOffset(365*2)
st = begin.strftime('%Y-%m-%d')
ed = end.strftime('%Y-%m-%d')
data = pdr.get_data_yahoo("AAPL",st,ed)
data['Date'] = data.index
mon_data = (
data[['Date', 'Adj Close']]
.groupby(pd.TimeGrouper(freq='M')).nth(-2)
.set_index('Date')
)
simplest solution is to take the index of your newly created dataframe and subtract the number of days you want to go back:
n = 1
mon_data=pd.DataFrame(data['Adj Close'].resample('M').apply(lambda x: x[-1-n]))
mon_data.index = mon_data.index - datetime.timedelta(days=n)
also, seeing your data, i think that you should resample not to ' month end frequency' but rather to 'business month end frequency':
.resample('BM')
but even that won't cover it all, because for instance December 29, 2017 is a business month end, but this date doesn't appear in your data (which ends in December 08 2017). so you could add a small fix to that (assuming the original data is sorted by the date):
end_of_months = mon_data.index.tolist()
end_of_months[-1] = data.index[-1]
mon_data.index = end_of_months
so, the full code will look like:
n = 1
mon_data=pd.DataFrame(data['Adj Close'].resample('BM').apply(lambda x: x[-1-n]))
end_of_months = mon_data.index.tolist()
end_of_months[-1] = data.index[-1]
mon_data.index = end_of_months
mon_data.index = mon_data.index - datetime.timedelta(days=n)
btw: your .set_index(data.index) throw an error because data and mon_data are in different dimensions (mon_data is monthly grouped_by)
I want to use look ups for any online index, including those with digits. A random example is:
https://uk.finance.yahoo.com/quote/YSM6.AX/futures?p=YSM6.AX
A naive method is to use pandas-datareader:
from pandas_datareader import data as datareader
online_data = datareader.DataReader('YSM6.AX', 'yahoo', start, end)
However, this doesn't work. I think the digits in the ticker aren't handled properly. This command works fine with e.g. "AAPL".
How do I get this to work for any index?
The YSM6.AX link shows that there is no data for this stock.
If you want to grab multiple stock, and get specifically the adjusted close, you can use this code. It takes into account any funny stock tickers that have either a "-", or in the case of YSM6.AX, a "." inside the ticker.
import pandas as pd
import datetime
from pandas_datareader import data, wb
tickers = ["BRK.B", "AAPL", "MSFT", "YHOO", "JPM"]
series_list = []
start = datetime.datetime(2012, 4, 5)
end = datetime.datetime(2017, 3, 28)
for security in tickers:
s = data.DataReader(security.replace(".","-"),"yahoo",start, end )["Adj Close"]
s.name = security
series_list.append(s)
df = pd.concat(series_list, axis=1)
stocks= pd.DataFrame(df)
stocks
If you look at the link you have provided, YSM6 is a futures contract on ASX. Specifically it is the M6 expiry, meaning 2016-06. And Yahoo has no data for this contract on their site anymore--perhaps because it is expired, or perhaps because there was never any data available for it. Furthermore, this product (3 year AU interest rate swap futures) seems to have been discontinued by the exchange.
Your question says you want "stock" data. Here's an example of an actual stock with a numeric symbol:
https://uk.finance.yahoo.com/quote/7203.KL/?p=7203.KL