July 27, 2012 at 11:28 pm
Hi All,
I have a table of stock details for NSE holiding Daily data.
Here is the structure of the table:
Table Name: NseData
symbolid bigint
symbol varchar(200)
stimestamp datetime -- Stores everyday date - Values are updated End of Day
sopen numeric(18, 2)
shigh numeric(18, 2)
slow numeric(18, 2)
sclose numeric(18, 2)
tottrdqty bigint
Sample data looks like: (Daily Data)
1 20MICRONS 2011-02-01 42.00 42.55 41.50 42.00 5137
2 3IINFOTECH 2011-02-01 49.45 50.20 47.20 47.65 915994
3 3MINDIA 2011-02-01 3495.00 3500.00 3402.05 3494.35 989
4 A2ZMES 2011-02-01 268.00 299.85 265.10 266.25 290144
5 AARTIDRUGS 2011-02-01 139.80 140.00 134.00 138.80 3359
6 AARTIIND EQ 2011-02-01 54.85 50.75 51.30 51.30 126181
Requirement:
The above given data is daily data and there are a total of 1500 symbols everyday that gets open, high, low, close values and the data stretches for over an year with approximately 5 Lakh records. I need all these records to be converted to Weekly data.
Daily Data to Weekly Data Procedure:
When converting daily data to weekly data, following is the procedure that is followed:
Week starts from Monday and ends on Friday a total of 5 days
Week Date is taken as date of Monday
Open value is taken as the open value (sopen) of Monday
High Value is taken as Highest of High column (shigh) in the entire week of 5 days.
Low Value is taken as Lowest of Low column (slow) in the entire week of 5 days.
Close value is taken as close value (sclose) of Friday
For every week there is only one record generated per symbol. So approximately 52 records per symbol are generated in an year.
I want an sql view that can generate these weekly records based on the procedure given above by generating weekly data for each symbol and for all the weeks in an year and for all the symbols.
This is my first Post in this forum. So kindly guide me through if I have made any mistake posting things here.
Looking forward for your response and thanks for your help in advance.
July 28, 2012 at 1:06 am
CREATE TABLE NseData
(
symbolid bigint,
symbol varchar(200),
stimestamp datetime,
sopen numeric(18, 2),
shigh numeric(18, 2),
slow numeric(18, 2),
sclose numeric(18, 2),
tottrdqty bigint
)
INSERT INTO NseData
VALUES
(1,'Microsoft','Jul, 23 2012',42.00,43.5,38.25,43,10),
(1,'Microsoft','Jul, 24 2012',43.25,44.75,39.50,44.25,20),
(1,'Microsoft','Jul, 25 2012',44.50,46.00,40.75,45.50,30),
(1,'Microsoft','Jul, 26 2012',45.75,47.25,42.00,46.75,10),
(1,'Microsoft','Jul, 27 2012',47.00,48.50,43.25,48.00,20),
(2,'Infosys','Jul, 23 2012',48.25,49.75,44.50,49.25,30),
(2,'Infosys','Jul, 24 2012',49.50,51.00,45.75,50.50,10),
(2,'Infosys','Jul, 25 2012',50.75,52.25,47.00,51.75,20),
(2,'Infosys','Jul, 26 2012',52.00,53.50,48.25,53.00,30),
(2,'Infosys','Jul, 27 2012',53.25,54.75,49.50,54.25,10);
DECLARE @today datetime = CONVERT(DATETIME,CONVERT(DATE,getdate())) -- TODAY's Date
DECLARE @start_date DATETIME
DECLARE @end_date DATETIME
SELECT @start_date=DATEADD(d,-1*(DATEPART(dw,@today-1)-2),@today-1)
SELECT @end_date = DATEADD(s,-1,DATEADD(d,5,@start_date))
SELECT symbolid,symbol,@start_date as WeekDate,MAX(shigh) sHigh,
MIN(sLow) sLow,
MAX(CASE CONVERT(DATETIME,CONVERT(DATE,stimestamp))
WHEN @start_date THEN sOpen END) AS sOpen,
MAX(CASE CONVERT(DATETIME,CONVERT(DATE,stimestamp))
WHEN CONVERT(DATETIME,CONVERT(DATE,@end_date)) THEN sClose END) AS sClose
FROM NseData
WHERE stimestamp BETWEEN @start_date AND @end_date
GROUP BY symbolid,symbol
Run this query on any date (say x), It will give you the data from Monday to Friday for the week in which x lies.
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 1:09 am
As you are new to this forum try to know the best practices in order to get quicker answers on T-SQL questions, Follow this link
http://www.sqlservercentral.com/articles/Best+Practices/61537/
Cheers
Lokesh
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 3:10 am
Hi Lokesh,
Thanks a lot for your guidance.
Your query fetches me results between the start date and end date. If the start date is 01-JAN-2011'
end date is 31-DEC-2011 (1 Year), it is just giving me one row between these two dates for every symbol.
what I am expecting:
There are 52 weeks in a year. Every week i want a row to be generated for every symbol taking the values between Monday through Friday to compute open, high, low, close as described in the procedure of my post.
So for a symbol 'MICROSOFT' there are 52 records generated one for each week of an year
Here is procedure once again for each record generated in a week
sOpen value of Moday,
Highest of sHigh value between Monday to Friday
Lowest of sLow value between Monday to Friday
sClose value of Friday
I want a view to do this. I hope i could make it clear.
Looking forward for your response once again.
Regards,
Reuben
July 28, 2012 at 4:00 am
Here you go....
I have modified the Data Script to add one more week for both Microsoft and Infosys
CREATE TABLE NseData
(
symbolid bigint,
symbol varchar(200),
stimestamp datetime,
sopen numeric(18, 2),
shigh numeric(18, 2),
slow numeric(18, 2),
sclose numeric(18, 2),
tottrdqty bigint
)
INSERT INTO NseData
VALUES
(1,'Microsoft','Jul, 23 2012',42.00,43.5,38.25,43,10),
(1,'Microsoft','Jul, 24 2012',43.25,44.75,39.5,44.25,20),
(1,'Microsoft','Jul, 25 2012',44.5,46,40.75,45.5,30),
(1,'Microsoft','Jul, 26 2012',45.75,47.25,42,46.75,10),
(1,'Microsoft','Jul, 27 2012',47,48.5,43.25,48,20),
(2,'Infosys','Jul, 23 2012',48.25,49.75,44.5,49.25,30),
(2,'Infosys','Jul, 24 2012',49.5,51,45.75,50.5,10),
(2,'Infosys','Jul, 25 2012',50.75,52.25,47,51.75,20),
(2,'Infosys','Jul, 26 2012',52,53.5,48.25,53,30),
(2,'Infosys','Jul, 27 2012',53.25,54.75,49.5,54.25,10),
(1,'Microsoft','Jul, 02 2012',54.5,56,50.75,55.5,10),
(1,'Microsoft','Jul, 03 2012',55.75,57.25,52,56.75,20),
(1,'Microsoft','Jul, 04 2012',57,58.5,53.25,58,30),
(1,'Microsoft','Jul, 05 2012',58.25,59.75,54.5,59.25,10),
(1,'Microsoft','Jul, 06 2012',59.5,61,55.75,60.5,20),
(2,'Infosys','Jul, 02 2012',60.75,62.25,57,61.75,30),
(2,'Infosys','Jul, 03 2012',62,63.5,58.25,63,10),
(2,'Infosys','Jul, 04 2012',63.25,64.75,59.5,64.25,20),
(2,'Infosys','Jul, 05 2012',64.5,66,60.75,65.5,30),
(2,'Infosys','Jul, 06 2012',65.75,67.25,62,66.75,10);
Here is the query which will give you 2 records both for Microsoft and Infosys...Once you apply this on complete data set, it will give you 52 records for each symbol.
DECLARE @year_start DATETIME = '02-JAN-2012'
DECLARE @year_end DATETIME = '31-DEC-2012'
;WITH Date_range
AS
(
SELECT @year_start Start_date, DATEADD(s,-1,@year_start+5) End_date
UNION ALL
SELECT Start_date + 7, DATEADD(s,-1,Start_date+7+5)
FROM Date_range
WHERE Start_date + 1 <=@year_end
AND DATEADD(s,-1,Start_date+7+5) <=@year_end
AND DATEPART(dw,Start_date)=2
)
SELECT symbolid,symbol,Start_date as WeekDate,MAX(shigh) sHigh,
MIN(sLow) sLow,
MAX(CASE CONVERT(DATETIME,CONVERT(DATE,stimestamp))
WHEN Start_date THEN sOpen END) AS sOpen,
MAX(CASE CONVERT(DATETIME,CONVERT(DATE,stimestamp))
WHEN CONVERT(DATETIME,CONVERT(DATE,End_date)) THEN sClose END) AS sClose
FROM NseData n,Date_range d
WHERE n.stimestamp BETWEEN d.Start_date AND d.End_date
GROUP BY symbolid,symbol,Start_date
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 4:03 am
One more thing, i missed above
DECLARE @year_start DATETIME = '02-JAN-2012' --First Monday of the year
DECLARE @year_end DATETIME = '31-DEC-2012'
@Year_start is the first Monday of the year. End date can be any thing. Furthermore, you can apply this to any date span - like 1 yr,2 yr and so on.
Check the results 🙂
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 4:57 am
Hi Lokesh,
Thanks for it. 90% of the query works like charm!..
Now the problem is with sClose values.
I am executing the query with startdate = '03-JAN-2011' (MONDAY)
end date='31-DEC-2011' (SATURDAY)
sOpen, sHigh, sLow gets the values as per a week. But not sClose. If i'm not wrong, it is taking the value of the Last day in the year which actually should be a friday in the same week where sOpen, sHigh, sLow values are being generated.
I am attaching a picture for your information. I have made few changes to code to work as per my requirement but you please follow the code which you have written. I'll modify it as per my requirement. Just concentrate on sClose.
Thanks for all your help mate. You are excellent. This piece of code I have been trying for the past 3 days.. Help me through.
Regards,
Reuben.
July 28, 2012 at 5:04 am
Try putting Year end date as first friday of next year and check the results.
And I am not able to see your screen attachment, Please post again.
Thanks
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 5:26 am
Thanks for all your help mate. You are excellent. This piece of code I have been trying for the past 3 days..
Glad to know that was helpful. I am not able to view your screen shot. Kindly attached it in the post [check Attachements tab at the end of Post reply box]
I will look into and get back to you.
-Lokesh
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 5:42 am
https://www.sqlservercentral.com/Forums/Uploads/image-unavailable.png
visit the above link and you should be able to view the image.
thanks
July 28, 2012 at 5:50 am
sClose should not be NULL. Not sure why this is happening. On my machine with this sample data. It is showing the correct value.
| SYMBOLID | SYMBOL | WEEKDATE | SHIGH | SLOW | SOPEN | SCLOSE |
---------------------------------------------------------------------------------------
| 1 | Microsoft | July, 02 2012 00:00:00-0700 | 61 | 50.75 | 54.5 | 60.5 |
| 1 | Microsoft | July, 23 2012 00:00:00-0700 | 48.5 | 38.25 | 42 | 48 |
| 2 | Infosys | July, 02 2012 00:00:00-0700 | 67.25 | 57 | 60.75 | 66.75 |
| 2 | Infosys | July, 23 2012 00:00:00-0700 | 54.75 | 44.5 | 48.25 | 54.25 |
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 6:03 am
symbolid is an autonumber. You don't need to group that.
In the logic which you wrote sClose is taking the final value may be the end of the year or any other final end date which we take.
Could you please check and make sure sClose takes the final friday value as sOpen is taking the Monday value of the week.
July 28, 2012 at 6:37 am
Took a second look. With the sample data, here is the result which I am getting. Is sClose correct? | SYMBOL | WEEKDATE | SHIGH | SLOW | SOPEN | SCLOSE |
----------------------------------------------------------------------------
| Infosys | July, 02 2012 00:00:00-0700 | 67.25 | 57 | 60.75 | 66.75 |
| Microsoft | July, 02 2012 00:00:00-0700 | 61 | 50.75 | 54.5 | 60.5 |
| Infosys | July, 23 2012 00:00:00-0700 | 54.75 | 44.5 | 48.25 | 54.25 |
| Microsoft | July, 23 2012 00:00:00-0700 | 48.5 | 38.25 | 42 | 48 |[/code]
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
July 28, 2012 at 6:50 am
The values are correct.
Here is the complete code on how I'm using it taking your code and modifying it as per my needs.
DECLARE @year_start DATETIME
SELECT @year_start= '03-JAN-2011'
DECLARE @year_end DATETIME
SELECT @year_end= '31-DEC-2011'
;WITH Date_range
AS
(
SELECT @year_start Start_date, DATEADD(s,-1,@year_start+5) End_date
UNION ALL
SELECT Start_date + 7, DATEADD(s,-1,Start_date+7+5)
FROM Date_range
WHERE Start_date + 1 <=@year_end
AND DATEADD(s,-1,Start_date+7+5) <=@year_end
AND DATEPART(dw,Start_date)=2
)
SELECT symbol,Start_date as WeekDate,MAX(shigh) sHigh,
MIN(sLow) sLow,
Min(CASE CONVERT(DATETIME,CONVERT(DATETIME,stimestamp))
WHEN Start_date THEN sOpen END) AS sOpen,
MAX(CASE CONVERT(DATETIME,CONVERT(DATETIME,stimestamp))
WHEN CONVERT(DATETIME,CONVERT(DATETIME,End_date)) THEN sClose END) AS sClose
FROM usrstocks.NseData n,Date_range d
WHERE n.stimestamp BETWEEN d.Start_date AND d.End_date
GROUP BY symbol,Start_date
order by symbol,Start_date
July 28, 2012 at 7:01 am
Made some changes in your code. Please check now.
DECLARE @year_start DATETIME
SELECT @year_start= '03-JAN-2011'
DECLARE @year_end DATETIME
SELECT @year_end= '31-DEC-2011'
;WITH Date_range
AS
(
SELECT @year_start Start_date, DATEADD(s,-1,@year_start+5) End_date
UNION ALL
SELECT Start_date + 7, DATEADD(s,-1,Start_date+7+5)
FROM Date_range
WHERE Start_date + 1 <=@year_end
AND DATEADD(s,-1,Start_date+7+5) <=@year_end
AND DATEPART(dw,Start_date)=2
)
SELECT symbol,Start_date as WeekDate,MAX(shigh) sHigh,
MIN(sLow) sLow,
Min(CASE CONVERT(DATETIME,CONVERT(DATETIME,stimestamp))
WHEN Start_date THEN sOpen END) AS sOpen,
MIN(CASE CONVERT(DATETIME,CONVERT(DATETIME,stimestamp))
WHEN CONVERT(DATETIME,CONVERT(DATE,End_date)) THEN sClose END) AS sClose
FROM NseData n,Date_range d
WHERE n.stimestamp BETWEEN d.Start_date AND d.End_date
GROUP BY symbol,Start_date
order by symbol,Start_date
I am confident, it will work 🙂
- Lokesh
~ Lokesh Vij
Link to my Blog Post --> www.SQLPathy.com[/url]
Follow me @Twitter
Viewing 15 posts - 1 through 15 (of 18 total)
You must be logged in to reply to this topic. Login to reply