Get last price of stock data in python - python

I have searched for this topic and I found some packages that are useful. All what I am trying to get is the last price of any specific ticker such as "MSFT"
Here's a code that I found and it is good
import pandas_datareader as pdr
from datetime import datetime
ibm = pdr.get_data_yahoo(symbols='MSFT', start=datetime(2021, 3, 1), end=datetime(2021, 3, 12))
print(ibm['Adj Close'])
This works for range of dates. How can I get the last price only without hard-coding the start date or end date?

Just use tail keyword.
from datetime import datetime, date
ibm = pdr.get_data_yahoo(symbols='MSFT', start = date.today(), end = date.today())
print(ibm['Adj Close'].tail(1))

Related

How to identify actual day of week that markets end on?

As of Dec 30, 2021 ----
I did figure this out. New to Python, so this is not optimized or the most elegant, but it does return just the day that ends any market week. Because of how I specify the start and end dates, the dataframe always starts with a Monday, and ends with the last market day. Basically, it looks at each date in consecutive rows, assigns the difference in days to a new column. Each row will return a -1, except for the last day of the market week. The very last row of all data also returns a "NaN", which I had to deal with. I then delete just the rows with -1 in the Days column. Thank you for the feedback....here is the rest of the code that does the work, which follows the code I previously supplied.
data['Date'] = pd.to_datetime(data['Date'])
data['Days_from_date'] = pd.DatetimeIndex(data['Date']).day
data['Days'] = data['Days_from_date'] - data['Days_from_date'].shift(-1)
data=data.replace(np.nan,-1)
data["Days"]=data["Days"].astype(int)
data = data[data['Days'] != -1]
data = data[data['Days'].ne(-1)]
This is the previous post.....
I currently have python code that gets historical market info for various ETF tickers over a set period of time (currently 50 days). I run this code through Power BI. When I get done testing, I will be getting approximately 40 weeks of data for 60-ish ETFs. Current code is copied below.
I would like to minimize the amount of data returned to just the CLOSE data generated on the last market day of each week. Usually this is Friday, but sometimes it can be Thursday, and I think possibly Wednesday.
I am coming up short on how to identify each week's last market day and then pulling in just that data into a dataframe. Alternatively, I suppose it could pull in all data, and then drop the unwanted rows - I'm not sure which would be a better solution, and, in any case, I can't figure out how to do it!
Current code here, using Python 3.10 and Visual Studio Code for testing....
import yfinance as yf
import pandas as pd
from datetime import date
from datetime import timedelta
enddate = date.today()
startdate = enddate - timedelta(days=50)
tickerStrings = ['VUG', 'VV', 'MGC', 'MGK', 'VOO', 'VXF', 'VBK', 'VB']
df_list = list()
for ticker in tickerStrings:
data = yf.download(ticker, start=startdate, group_by="Ticker")
data['Ticker'] = ticker
df_list.append(data)
data = pd.concat(df_list)
data = data.drop(columns=["Adj Close", "High", "Low", "Open", "Volume"])
data = data.reset_index()
As I commented, I think you can get the desired data by getting the week number from the date data, grouping it and getting the last row. For example, if Friday is a holiday, I considered Thursday to be the last data of the week number.
import yfinance as yf
import pandas as pd
from datetime import date
from datetime import timedelta
enddate = date.today()
startdate = enddate - timedelta(days=50)
tickerStrings = ['VUG', 'VV', 'MGC', 'MGK', 'VOO', 'VXF', 'VBK', 'VB']
df = pd.DataFrame()
for ticker in tickerStrings:
data = yf.download(ticker, start=startdate, progress=False)['Close'].to_frame('Close')
data['Ticker'] = ticker
df = df.append(data)
df.reset_index(inplace=True)
df['week_no'] = df['Date'].dt.isocalendar().week
data = df.groupby(['Ticker','week_no']).tail(1).sort_values('Date', ascending=True)

Stock Price Start and End range from specified time

I have this code that works when manually entering a start date and an end date:
import datetime as dt
from datetime import date
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
import pandas_datareader as web
today = date.today()
style.use("ggplot")
start = dt.datetime(2020,1,1)
end = today
df = web.get_data_yahoo("TSLA", start, end)
df["Adj Close"].plot()
plt.xlabel("Date")
plt.ylabel("Price $")
plt.title("TSLA Stock Price ", )
plt.show()
It works when plotting the graph, but I want the start and end date to show up on the title as well. Is there anyway that I can import the "start" and "end" variables after "TSLA Stock Price "?
I think you can just use an f string in the plt.title().
plt.title(f"TSLA Stock Price {start.strftime('%x')} to {end.strftime('%x')}")
This code results in the title being formated like mm/dd/yy to mm/dd/yy

how to change date and month?

this is a piece of code where I want to change the date and month in the link. I don't want to use the date-time module because I will be scraping and storing some information from the website for each day and for each month I will be saving the data in CSV so after every month I want to create a new CSV file
also if there would be a for loop for a month I want to use it in naming the CSV file while saving it
from selenium import webdriver
import time
path="C:\\Users\\Nihal\\Downloads\\chromedriver_win32\\chromedriver.exe"
import numpy
driver = webdriver.Chrome(path)
driver.get('https://www.wunderground.com/history/daily/in/mangalore/VOML/date/2013-4-14')
Plug the dates as tuples and use f-string to format them in URL:
from selenium import webdriver
import time
path="C:\\Users\\Nihal\\Downloads\\chromedriver_win32\\chromedriver.exe"
import numpy
driver = webdriver.Chrome(path)
dates = [(2013, 4, 14)]
for x in dates:
#https://www.wunderground.com/history/daily/in/mangalore/VOML/date/2013-4-14
driver.get(f'https://www.wunderground.com/history/daily/in/mangalore/VOML/date/{x[0]}-{x[1]}-{x[2]}')
I am not used to selenium, so I can't help you with the parsing that you do with it, but I am pretty sure that you can use the datetime module to iterate on every day of a month and on every month of the year. Here is an example of how you can iterate on this and generate the url that you need:
from datetime import timedelta, date
def daterange(start_date, end_date):
for n in range(int((end_date - start_date).days)):
yield start_date + timedelta(n)
start_date = date(2020, 8, 1)
end_date = date(2020, 8, 31)
days_to_scrape = []
for single_date in daterange(start_date, end_date):
days_to_scrape.append(f'https://www.wunderground.com/history/daily/in/mangalore/VOML/date/{single_date.strftime("%Y-%m-%d")}')
#Iteration with driver.get
If I understand, you will have no choice but to send as many requests as the number of days from which you want the data. You can then iterate on the items of the list with your scraping command. If there is another reason why you think datetime module can't do what you need it to do, please, explain it.
L.R.
P.S.
Thanks to vinzee who helped me to understand that kind of iteration with his answer: Iterating through a range of dates in Python

Dynamically count number of business days excluding holiday calendar in Python

I want to calculate the number of business days between two dates and create a new pandas dataframe column with those days. I also have a holiday calendar and I want to exclude dates in the holiday calendar while making my calculation.
I looked around and I saw the numpy busday_count function as a useful tool for it. The function counts the number of business days between two dates and also allows you to include a holiday calendar.
I also looked around and I saw the holidays package which gives me the holiday dates for different countries. I thought it will be great to add this holiday calendar into the numpy function.
Then I proceeded as follows;
import pandas as pd
import numpy as np
import holidays
from datetime import datetime, timedelta, date
df = {'start' : ['2019-01-02', '2019-02-01'],
'end' : ['2020-01-04', '2020-03-05']
}
df = pd.DataFrame(df)
holidays_country = holidays.CountryHoliday('UnitedKingdom')
start_date = [d.date for d in df['start']]
end_date = [d.date for d in df['end']]
holidays_numpy = holidays_country[start_date:end_date]
df['business_days'] = np.busday_count(begindates = start_date,
enddates = end_date,
holidays=holidays_numpy)
When I run this code, it throws this error TypeError: Cannot convert type '<class 'list'>' to date
When I looked further, I noticed that the start_date and end_date are lists and that might be whey the error was occuring.
I then changed the holidays_numpy variable to holidays_numpy = holidays_country['2019-01-01':'2019-12-31'] and it worked.
However, since my dates are different for each row in my dataframe, is there a way to set the two arguments in my holiday_numpy variable to select corresponding values (just like the zip function) each from start_date and end_date?
I'm also open to alternative ways of solving this problem.
This should work:
import pandas as pd
import numpy as np
import holidays
df = {'start' : ['2019-01-02', '2019-02-01'],
'end' : ['2020-01-04', '2020-03-05']}
df = pd.DataFrame(df)
holidays_country = holidays.CountryHoliday('UK')
def f(x):
return np.busday_count(x[0],x[1],holidays=holidays_country[x[0]:x[1]])
df['business_days'] = df[['start','end']].apply(f,axis=1)
df.head()

How can I change a month in a DateTime, using for loop (or better method )?

Revised question with appropriate MCVE:
As part of a script I'm writing I need to have a loop that contains a different pair of dates during each iteration, these dates are the first and last available stock trading dates of each month. I have managed to find a calendar with the available dates in an index however despite my research I am not sure how to select the correct dates from this index so that they can be used in the DateTime variables start and end.
Here is as far as my research has got me and I will continue to search for and build my own solution which I will post if I manage to find one:
from __future__ import division
import numpy as np
import pandas as pd
import datetime
import pandas_market_calendars as mcal
from pandas_datareader import data as web
from datetime import date
'''
Full date range:
'''
startrange = datetime.date(2016, 1, 1)
endrange = datetime.date(2016, 12, 31)
'''
Tradable dates in the year:
'''
nyse = mcal.get_calendar('NYSE')
available = nyse.valid_days(start_date='2016-01-01', end_date='2016-12-31')
'''
The loop that needs to take first and last trading date of each month:
'''
dict1 = {}
for i in available:
start = datetime.date('''first available trade day of the month''')
end = datetime.date('''last available trade day of the month''')
diffdays = ((end - start).days)/365
dict1 [i] = diffdays
print (dict1)
That is probably because 1 January 2016 was not a trading day. To check if I am right, try giving it the date 4 January 2016, which was the following Monday. If that works, then you will have to be more sophisticated about the dates you ask for.
Look in the documentaion for dm.BbgDataManager(). It is possible that you can ask it what dates are available.

Categories

Resources