最有效的组合查询结果的方法

时间:2013-11-11 12:57:47

标签: linq entity-framework

这个问题有点探索性,因为我决定在尝试实施之前征求意见/建议,以期更及时地获得结果。我有一个数据库,以1分钟的格式存储商品和股票的日内数据。这背后的理由是,如果我有1分钟的酒吧,我可以创建我想要的任何时间序列栏(即5分钟,15分钟,60分钟等等)

我想过去的路线,例如,在15分钟的图表中,我只是遍历给定符号的整个结果子集,查找时间戳为:01,:16,:31:46的行开始捕获打开,关闭,maxhigh和minlow和累积量并从该合并创建新的数据点。问题在于,对于特别是24小时交易的商品,并不总是每分钟都有一个条形,所以可能存在一个没有:16 bar的情况,或者给定符号的31 bar。这可能会破坏正确获取条形数据的整个过程。这也消除了一次抓取15个条并捕获开放,关闭,最大和最小和累积音量的可能性。 (当然,表包含符号,日期时间,开放,高,低,关闭,音量)

为了使上述任何一种工作起作用,我必须每天通过检查丢失的条形码并复制先前的条形来为该缺失的行创建一个条,从而“修复”数据库。这不是首选的方法,但如果有必要,我会发生。

我正在寻找关于正确道路的任何指导,无论是从过去的经验还是从这里阅读这个问题。

更新 以下是我提出的代码,但它有点慢,从数据库表中的1分钟数据创建2个月30分钟的条形图需要大约30秒。

Partial Class testintracharts
Inherits Page
<WebMethod>
Public Shared Function GetBars(ByVal symbol As String, ByVal seriesInterval As Integer) As List(Of ArrayList)

    Dim barsList As New List(Of ArrayList)
    'replace with TD model
    Using ctx As New BATLEntities()

        ctx.Configuration.AutoDetectChangesEnabled = False

        'get all days for a given symbol, ordered from oldest to newest
        Dim dateList As List(Of DateTime) = GetDistinctDates(ctx, symbol, seriesInterval).ToList()

        'cache data series toa list for the given symbol
        Dim seriesList As List(Of tsintrachart) = GetSymbolSeries(ctx, symbol)

        If Not dateList Is Nothing And dateList.Any() Then
            For Each seriesDate As DateTime In dateList
                Dim curTime As TimeSpan = New TimeSpan(0, 1, 0)
                Dim maxTime As TimeSpan = New TimeSpan(24, 0, 0)

                'loop through the data series for the given day
                'series start at 00:01:00
                'series ends at 00:00:00 (next day)

                While curTime < maxTime
                    Dim seriesMax As TimeSpan = curTime.Add(New TimeSpan(0, seriesInterval - 1, 0))

                    'get the data chunk based on series interval
                    'special condition when seriesmax reaches 24:00:00, in TimeSpan this becomes 1.00:00:00 (SQL doesn't like this)
                    'query needs to incorporate 00:00:00 of next day as the last entry for this time series

                    Dim data As List(Of tsintrachart) = Nothing
                    If TimeSpan.Compare(seriesMax, maxTime) = 0 Then
                        Dim nextSeriesDate As DateTime = seriesDate.AddDays(1)
                        data = GetDataSeries(seriesList, seriesDate, curTime, nextSeriesDate, New TimeSpan(0, 0, 0))
                    Else
                        data = GetDataSeries(seriesList, seriesDate, curTime, seriesDate, seriesMax)
                    End If

                    If Not data Is Nothing And data.Any() Then

                        Dim lastbarnum As Integer = data.Count - 1
                        Dim intradayDatum As New ArrayList()
                        With intradayDatum
                            .Add(DateTimeToUnixTimestamp(seriesDate.Add(seriesMax))) 'date
                            .Add(data(0).Open)
                            '.Add((From d In data Where TimeSpan.Compare(d.Time, curTime) = 0 Select d.Open).FirstOrDefault()) 'open
                            .Add((From d In data Select d.High).Max()) 'high
                            .Add((From d In data Select d.Low).Min()) 'low 
                            .Add(data(lastbarnum).Close)
                            '.Add((From d In data Where TimeSpan.Compare(d.Time, seriesMax) = 0 Select d.Close).FirstOrDefault()) 'close or last sale
                            .Add((From d In data Select d.Volume).Sum()) 'volume 
                        End With
                        barsList.Add(intradayDatum)

                    End If

                    'update current series start time, move to next series chunk
                    curTime = curTime.Add(New TimeSpan(0, seriesInterval, 0))
                End While

            Next
        End If
    End Using

    Return barsList
End Function

Private Shared Function GetDataSeries(ByRef list As List(Of tsintrachart), ByVal startDate As DateTime, ByVal startSpan As TimeSpan, ByVal endDate As DateTime, ByVal endSpan As TimeSpan) As List(Of tsintrachart)
    'LINQ, where symbol/time>=startRange/time<=endRange

    Dim series = From data In list
                 Where (TimeSpan.Compare(data.Time, startSpan) >= 0 AndAlso data.Date = startDate) _
                 And (TimeSpan.Compare(data.Time, endSpan) <= 0 AndAlso data.Date = endDate)
                Select data

    Return series.ToList()
End Function

Private Shared Function GetSymbolSeries(ByRef ctx As BATLEntities, ByVal symbol As String) As List(Of tsintrachart)
    Dim series = From data In ctx.tsintracharts
                 Where (data.Symbol = symbol)
                Select data

    Return series.ToList()
End Function

Private Shared Function GetDistinctDates(ByRef ctx As BATLEntities, ByVal symbol As String, ByVal interval As Integer) As IQueryable(Of DateTime)
    Dim numDates As Integer = TakeValue(interval)
    Dim dates = (From data In ctx.tsintracharts
                Where data.Symbol = symbol
                Select data.Date
                Order By [Date]).Distinct().Take(numDates)

    Return dates
End Function
Private Shared Function TakeValue(ByVal interval As Integer) As Integer
    Select Case interval
       Case 0 To 15
            Return 1440
        Case 16 To 30
            Return 720
        Case 31 To 60
            Return 528
        Case Else
            Return 400
    End Select
End Function
End Class

1 个答案:

答案 0 :(得分:0)

您可以创建一个包含所有可能的1分钟时间点的表格。然后,您可以OUTER JOIN到该表,以使服务器填补任何空白。表格如下:

CREATE TABLE TimePoints (
 DateTime DATETIME2(0) PRIMARY KEY
)

你需要填写数十年的数据。要查询,您可以加入它:

SELECT *
FROM TimePoints
LEFT JOIN myOtherTable ON ...
WHERE TimePoints.DateTime >= (nowMinus15min) AND TimePoints.DateTime <= now