I have data of stock
date open high low close volume day_name
9 2022-06-14 00:00:00+05:30 33180.60 33618.15 33123.90 33311.35 0 Tuesday
10 2022-06-15 00:00:00+05:30 33317.80 33554.55 33249.55 33339.00 0 Wednesday
11 2022-06-16 00:00:00+05:30 33648.80 33756.50 32537.95 32617.10 0 Thursday
12 2022-06-17 00:00:00+05:30 32393.45 32889.80 32290.55 32743.05 0 Friday
13 2022-06-20 00:00:00+05:30 32873.40 32923.75 32455.00 32762.50 0 Monday
And I want to query if stock changes from Friday to Wednesday by more than 5% then what is the historical change on Thursday / Next Week / etc...
I tried to set Friday as the first day of the week but was not able to get a clue about what to do next
data_frame['date'] = pandas.to_datetime(data_frame['date'])
data_frame['day_name'] = data_frame['date'].dt.day_name()
data_frame['change'] = data_frame['close'].pct_change(periods=1)
mask_map = data_frame.day_name == 'Friday'
data_frame['avg'] = data_frame.change.mask(mask_map).rolling(5, min_periods=1).mean().round(2)
Related
I am using intnx function.
date1=intnx('qtr',"01APR2021"d,0,'b');
I am thinking of following algo-
1.Check if last month's last day is not Friday.
2.Calculate the number of days till Friday appears(Current Month).
Can anyone help me with this?
Use INTNX to compute the 1st of the month, and then WEEKDAY of that to compute the number of days in the first week.
WEEKDAY function results are
1st-want 1st_want-v2
1 Sunday 1 2
2 Monday 2 3
3 Tuesday 3 4
4 Wednesday 4 5
5 Thursday 5 6
6 Friday 6 7
7 Saturday 7 1
Depending on what you want, (suppose the 1st is a Saturday, do you want 1 or 7 for your result?) For 1, you will need to perform additional calculations.
Example:
Presume if first is a Saturday you want 7 days in first week result.
data have;
call streaminit (2021);
do _n_ = 0 to 23;
date = intnx('month', '01-jan-2019'd, _n_) + rand('integer', 27);
output;
end;
format date date11.;
run;
data want;
set have;
month_1st = intnx('month', date, 0);
sas_weekday_1st = weekday(month_1st);
result = sas_weekday_1st;
result_v2 = mod(sas_weekday_1st,7) + 1;
format month_1st date11.;
run;
Find the first of the month (INTNX() or MDY())
Find the first friday (day=6) of the month (NWKDOM())
Subtract
Assume month and year are provided.
data want;
year = 2020;
month = 1;
start_date = mdy(month, 1, year);
first_friday = nwkdwom(1, 6, month, year);
length_week = start_date - first_friday + 1;
*Toms correction:;
length_week2 = day(nwkdom(1,6,month(date),year(date));
run;
Sounds like you want to know the date of the first Friday in the month. And hence the day of the month of the first Friday in the month.
So let's start with a dataset that has a month that starts on each day of the week.
data example;
input date :date9.;
format date date9.;
dow = weekday(date);
downame=put(date,downame.-l);
cards;
01OCT2000
01MAY2000
01FEB2000
01MAR2000
01JUN2000
01SEP2000
01JAN2000
;
Now we can use the INTNX() function with the WEEK interval to find the date of the first Friday. We could then use the DAY() function to find the day of the month for that Friday and hence how many days are in the first week of the month.
To get the first Friday find the Saturday at the end of the week containing the second day of the month and subtract one to move back to Friday.
data want;
set example;
friday = intnx('week',date+1,0,'e')-1 ;
want = day(friday);
want_name=put(friday,downame.-l);
format friday date9.;
run;
Results:
Obs date dow downame friday want want_name
1 01OCT2000 1 Sunday 06OCT2000 6 Friday
2 01MAY2000 2 Monday 05MAY2000 5 Friday
3 01FEB2000 3 Tuesday 04FEB2000 4 Friday
4 01MAR2000 4 Wednesday 03MAR2000 3 Friday
5 01JUN2000 5 Thursday 02JUN2000 2 Friday
6 01SEP2000 6 Friday 01SEP2000 1 Friday
7 01JAN2000 7 Saturday 07JAN2000 7 Friday
To do it with any day in the month use the INTNX() function with MONTH interval to find the first day of the month (and add one to find the second day of the month).
length_week1=day(intnx('week',intnx('month',date,0,'b')+1,0,'e')-1);
Need to find weekNumber like 1,2,3,4 but the week starts with Wednesday and ends with Tuesday from date column and after the 4th week, again the week restart by again as the 1st week and so on (no need to consider month).
Need to find the Period based on weekNumber only, 4 weeks as 1 Period and Periods end with 13 (period 1-13) will restart again 1st period.
(4 weeks = 1 period) (no need to consider month).
Now need to calculate the businessyear based on Period. 13 Periods as One businessyear. (13 periods = 1 year)
Calculation logic:
7 days * 4 weeks = 28 days = 1 period
13 periods = 1 businessyear
Example:
A year has 365 days normally
In my scenario, 4 weeks * 7 days = 28 days
28 days *13 periods = 364 days
The remaining days will come as the 5th week and period 14.
Datekey date Year semistor Quarter Month DayName DayNum Wnumber
20090101 01-01-2009 2009 1 1 January 1 Thursday 1 0
20090102 02-01-2009 2009 1 1 January 1 Friday 2 0
20090103 03-01-2009 2009 1 1 January 1 Saturday 3 0
20090104 04-01-2009 2009 1 1 January 1 Sunday 0
20090105 05-01-2009 2009 1 1 January 1 Monday 0
20090106 06-01-2009 2009 1 1 January 1 Tuesday 6 0
20090107 07-01-2009 2009 1 1 January 1 Wednesday 0 0
20090108 08-01-2009 2009 1 1 January 1 Thursday 1 1
20090109 09-01-2009 2009 1 1 January 1 Friday 2 1
20090110 10-01-2009 2009 1 1 January 1 Saturday 3 1
20090111 11-01-2009 2009 1 1 January 1 Sunday 4 1
20090112 12-01-2009 2009 1 1 January 1 Monday 5 1
20090113 13-01-2009 2009 1 1 January 1 Tuesday 6 1
20090114 14-01-2009 2009 1 1 January 1 Wednesday 0 1
No need to consider the month in my scenario, need to consider leap year also (2016, 2020).
The traditional way to do this type of thing is to create a calendar table in the database. Then, your queries can simply JOIN to the calendar table to extract the relevant value.
I find that the easiest way to create the calendar table is to use Excel. Simply write some formulas that provide the desired values and Copy Down for the next decade or so. Then, save the sheet as CSV and load it into the database.
This way, you can totally avoid complex calculations involving database functions and you can use whatever rules you wish.
My Data
A B C
1 Created Date Week No. of WorkDays
2 6/20/2018 11:36 06-w4 5
3 6/26/2018 12:56 06-w5 5
4 7/6/2018 23:01 07-w1 5
5 6/18/2018 18:11 06-w4 5
6 6/15/2018 12:01 06-w3 5
7 6/1/2018 13:31 06-w1 1
8 6/8/2018 12:17 06-w2 5
9 6/1/2018 13:32 06-w1 1
10 7/30/2018 13:32 07-w5 2
I have a week function that says whether an issue was created in Week 1 or 2 or so on. But for my calculation I need to consider workdays in that week, how do I do it. I'm calculating the no. of weekdays in that week manually now.
For example: June Week 1: No. of Weekdays is 1, because June 1 is Friday and June 2 is Saturday. Similarly for July Week 5 it is 2 days because July 29 is Sunday, July 30 & 31 are the weekdays.
My current formula for Week is
=CONCATENATE(TEXT(A1,"MM"),"-w",WEEKNUM(A1,1)-WEEKNUM(DATE(YEAR(A1),MONTH(A1),1),1)+1)
I'm trying out to use Workday function, but it does not provide my desired result.
Kindly help me out with this.
If the date in the A column is always a weekday, you can use this:
If that date can also be a weekend day, it will take the working days of the previous week. If you want to take the workinf days of the next week, you have to fiddle around still a bit.
=MIN(5,IF(MONTH(A2-WEEKDAY(A2,3))<MONTH(A2),7-WEEKDAY(DATE(YEAR(A2),MONTH(A2),1),1),IF(MONTH(A2+5-WEEKDAY(A2,2))>MONTH(A2),WEEKDAY(DATE(YEAR(A2),MONTH(A2)+1,0),2),5)))
First MIN: restrict to max 5 working days
First IF(): check if monday before or on date in A2 is in previous month
If so: take 7 minus weekday of first of month (sunday being 1)
If not so: second IF: check if friday this week is in next month
If so: take the weekday of the last of this month (monday being 1)
If not so: week in the middle of month, return 5
This of course does not take into account public holidays, only weekends.
For an inclusive # or workdays (e.g. Friday is 1 workday) try,
=NETWORKDAYS.INTL(A2, A2+5-WEEKDAY(A2,2), 1)
NETWORKDAYS.INTL allows for an optional holiday list if you want to create one.
Wrote my own VBA Formula - Results are as below
A B C D
1 Created Date Week No. of WorkDays No. of Days - Formula
2 6/20/2018 11:36 06-w4 5 5
3 3/2/2018 12:56 03-w1 2 2
4 7/6/2018 23:01 07-w1 5 5
5 6/18/2018 18:11 06-w4 5 5
6 6/15/2018 12:01 06-w3 5 5
7 6/1/2018 13:31 06-w1 1 1
8 6/8/2018 12:17 06-w2 5 5
9 6/1/2018 13:32 06-w1 1 1
10 7/30/2018 13:32 07-w5 2 2
Formula
=CalculateWorkdaysInWeek(A2)
VBA Code
Function CalculateWorkdaysInWeek(WeekRange As Range) As Variant
'Assume Week 2, 3 & 4 will always have 5 days
Dim WeekNo As Double
'Check if Week is 1 or 5
WeekNo = (Application.WorksheetFunction.WeekNum(WeekRange, 1) - _
Application.WorksheetFunction.WeekNum(DateSerial(Year(WeekRange), Month(WeekRange), 1))) + 1
Dim NoOfWeekDays As Integer
If WeekNo = 1 Then
FirstWeekDay = 7 - Weekday(DateSerial(Year(WeekRange), Month(WeekRange), 1), vbSunday)
If FirstWeekDay > 5 Then
FirstWeekDay = 5
End If
NoOfWeekDays = FirstWeekDay
ElseIf WeekNo = 5 Then
'Check the last day of the month as Monday as Start
LastWeekDay = Weekday(DateSerial(Year(WeekRange), Month(WeekRange) + 1, 0), vbMonday)
If LastWeekDay > 5 Then
LastWeekDay = 5
End If
NoOfWeekDays = LastWeekDay
Else ' Week 2,3 & 4 Return 5
NoOfWeekDays = 5
End If
CalculateWorkdaysInWeek = NoOfWeekDays
End Function
I want to add a column to my date dimension that contains the date of the first day of that week. here's a piece of what it looks like
CalendarDate DayOfWeekNumber DayKey DayOfWeekName WeekNumber
1996-01-01 2 19960101 MONDAY 1
1996-01-02 3 19960102 TUESDAY 1
1996-01-03 4 19960103 WEDNESDAY 1
1996-01-04 5 19960104 THURSDAY 1
1996-01-05 6 19960105 FRIDAY 1
1996-01-06 7 19960106 SATURDAY 1
1996-01-07 1 19960107 SUNDAY 1
1996-01-08 2 19960108 MONDAY 2
1996-01-09 3 19960109 TUESDAY 2
1996-01-10 4 19960110 WEDNESDAY 2
1996-01-11 5 19960111 THURSDAY 2
1996-01-12 6 19960112 FRIDAY 2
1996-01-13 7 19960113 SATURDAY 2
1996-01-14 1 19960114 SUNDAY 2
So basically i would want a column WeekStartDate that, for each WeekNumber would have the CalendarDate of the first dayOfWeekNumber (dayOfWeekNumber =1)
It would look like
CalendarDate DayOfWeekNumber DayKey DayOfWeekName WeekNumber WeekStart
1996-01-01 2 19960101 MONDAY 1 1996-01-01
1996-01-02 3 19960102 TUESDAY 1 1996-01-01
1996-01-03 4 19960103 WEDNESDAY 1 1996-01-01
1996-01-04 5 19960104 THURSDAY 1 "
1996-01-05 6 19960105 FRIDAY 1 "
1996-01-06 7 19960106 SATURDAY 1 "
1996-01-07 1 19960107 SUNDAY 1 "
1996-01-08 2 19960108 MONDAY 2 1996-01-08
1996-01-09 3 19960109 TUESDAY 2 "
1996-01-10 4 19960110 WEDNESDAY 2 "
1996-01-11 5 19960111 THURSDAY 2 "
1996-01-12 6 19960112 FRIDAY 2
1996-01-13 7 19960113 SATURDAY 2
1996-01-14 1 19960114 SUNDAY 2
so something like
update myTable set WeekStartDate = CalendarDate where dayofweeknumber=2 (monday) for each weeknumber (pseudocode, i know that's not what literally what i want it to do).
Thanks for suggestions. Pretty sure I need to window on weeknumber.
UPDATE C
SET WeekStartDate = week_start
FROM
(
select *, week_start = min(CalendarDate)
over (partition by year(CalendarDate), WeekNumber)
from Calendar
) AS C
We do patching of servers on a 4 week cycle starting the first Tuesday of the month on today/Wednesday and Thursday and I'm looking for a way to determine what number week cycle we would be on based on the current date.
For example first week cycle which has all three days the Tuesday falls on the 5th so wed(6th) and Thursday(7th) = week 1 and so on for the 4 week cycle.
But if the first Tuesday happened to be a 1st then in the month there would be 5 sets of these days. So no patching would occur on the 5th set of these days.
So I would like something like that would output the week number or display "no patching"
If week contains (Tuesday (maxdates 1st -7th), Wednesday (maxdates 2nd-8th), Thursday (maxdates 3rd-9th) = week 1
Then if week contains (Tuesday (maxdates 8th -14th), Wednesday (maxdates 9th-15th), Thursday (maxdates 10th-16th) = week 2
Then if week contains (Tuesday (maxdates 15th -21st), Wednesday (maxdates 16th-22nd), Thursday (maxdates 17th-23rd) = week 3
Then if week contains (Tuesday (maxdates 22nd -28th), Wednesday (maxdates 23rd-29th), Thursday (maxdates 24th-30th) = week 4
Else "no patching due to take place"
But if the month didn't contain a 29th or 30th for week 4 then I would need to include the 1st and the 2nd.
This would ideally allow me to incorporate this in my daily task list without the fear of the tasks accidently showing up on a week where no patching is due to take place. The task list is pulled daily from a sql database.
declare #v datetime = getdate()
select
DATENAME(weekday,#v) weekday,
#v date,
case
when DATENAME(weekday,#v) in ('Wednesday','Thursday')
AND 1 + ((DATEPART(day,#v) / 7) * 7) > 1
AND (DATEPART(day,#v) - ((DATEPART(day,#v) / 7) * 7) between 0 and 2)
then (DATEPART(day,#v) / 7)
else 1 + DATEPART(day,#v) / 7
end week_no