Correct SQL Statement returns correct row that represents front month expiry contract
I have a SQL server 2008 R2 database of trade records for several equity options, each at one minute intervals, and each minute contains records for several expiry. e.g.,
Symbol, TradeDate, Expiry, Open, High, Low, Close
AMZN, 4/01/2009 9:31:00, 4/17/2009, 8, 10, 9, 8.5
AMZN, 4/01/2009 9:31:00, 5/17/2009, 10, 11, 10, 11
AMZN, 4/01/2009 9:31:00, 6/18/2009, 12,13,12,12
GOOG, 4/01/2009 9:31:00, 4/17/2009, 8, 9, 7, 7.5
AMZN, 4/01/2009 9:32:00, 4/17/2009, 8.2, 8.9, 8.3, 8.5
AMZN, 4/01/2009 9:32:00, 5/16/2009, 3, 4, 4, 4
...
AMZN, 4/20/2009 9:31:00, 5/16/2009, 8.5, 9, 8.75, 8.75
AMZN, 4/20/2009 9:31:00, 6/18/2009, 9, 10, 9, 9.2
In opt开发者_如何转开发ions there is always a notion of the front month contract. For this problem, define the front month contract to be: If there are TradeDate entries less than the expiry date for that contract, that is the front month. Else, the front month is the next months contract. So for example, in the data above, on 4/01/2009, the AMZN front month is the contract that expires on 4/17/2009. However, when we move to TradeDate 4/20/2009, the front month is the 5/16/2009 contract since the 4/17/2007 contract expired over the weekend.
What is the SQL statement that would always return all the correct rows giving the "front month contract" based on what the TradeDate is?
From what you have described. The following query should do it. A self join :
SELECT T1.Symbol, T1.TradeDate, T1.Expiry, MIN(T2.expiry) AS FrontMonrhContract, T1.Open, T1.High, T1.Low, T1.Close FROM <TABLE> T1, <TABLE> T2 WHERE T1.TradeDate <= T2.Expiry GROUP BY T1.Symbol , T1.TradeDate, T1.Expiry
But it will not work if there is no entry for a trade of the FrontMonth Contract.
What i would feel better is that you either hand input a list of Expiries or compute them based on some rule, like last Friday of the month or something like that (if there is a rule). So that you do not risk miscalculating the front month if there is no trade for the frontMonth contract.
Better still do it in your application instead of SQL, as SQL is not meant for such work. In your application it would be a simple comparison with a list of expiries.
I have reduced execution time of a charting function which worked on data from a sqlite database by over 90% by doing such computations in the application itself instead of SQL.
Update:
Try the following query. It assumes the table name to be TRADES.
SELECT
T1.Symbol,
T1.TradeDate,
T1.Expiry,
MIN(T2.expiry) AS 'FrontMonrhContract' ,
MIN(T1.[Open]) AS 'Open',
MIN(T1.[High]) AS 'High',
MIN(T1.[Low]) AS 'Low',
MIN(T1.[Close]) AS 'Close'
FROM
TRADES T1, TRADES T2
WHERE T1.TradeDate <= T2.Expiry AND T1.Symbol = T2.Symbol
GROUP BY T1.Symbol , T1.TradeDate, T1.Expiry
I just built a sample table with the data you provided in the question and this query works as expected on that data set. For note I have SQL Server 2005
Update 2:
To optimize the execution of the query, try adding an Index with the three GROUP BY columns Symbol, TradeDate, Expiry
in that order.
I created a query execution plan and over 60% time is for resolving the GROUP BY, and after adding this index in my sample db it was completely gone.
精彩评论