Применить окно диапазона дат к тайм-серию данных - PullRequest
1 голос
/ 17 июля 2010

Я пишу программу, чтобы попытаться извлечь выгоду из набора временных серий идей биржевой торговли.Они находятся в массиве объектов quotedTrade ниже (с помощью JSONSerializer для извлечения данных с диска), отсортированных по полю даты startOn:

    [<DataContract>] 
    type trade = {
        [<field: DataMember(Name="tradeId") >] 
        tradeId : int ;
        [<field: DataMember(Name="analystId") >] 
        analystId: int
        [<field: DataMember(Name="startOn") >] 
        startOn : System.DateTime ;
        [<field: DataMember(Name="endOn") >] 
        endOn : System.DateTime option ;
        [<field: DataMember(Name="tradeType") >] 
        tradeType : string ;
        [<field: DataMember(Name="securityId") >] 
        securityId : int ;
        [<field: DataMember(Name="ricCode") >] 
        ricCode : string ;
        [<field: DataMember(Name="yahooSymbol") >] 
        yahooSymbol : string ;
        [<field: DataMember(Name="initialPrice") >] 
        initialPrice : float ;
    }

    [<DataContract>] 
    type quotedTrade = {
        [<field: DataMember(Name="trade") >] 
        trade : trade ;
        [<field: DataMember(Name="q7") >] 
        q7: float
        [<field: DataMember(Name="q14") >] 
        q14: float
        [<field: DataMember(Name="q21") >] 
        q21: float
    }

Я бы хотел

  • перерыв просмотра данных двумя способами

    • по analystId
    • по тикеру (символы ric или yahoo)
  • затем выполните итерации по представлениям с окнами дней

, возможно, представив записи:

    type byAnalyst = {
        analystId: int
        trades: quotedTrade array
    }

    type byTicker = {
        symbol: string
        trades: quotedTrade array
    }

и затем отфильтруйте их как-нибудь (sliceByAnalyst, sliceByTicker, которые будут предоставлены позже - хотя sugegstionsна чистом решении будет признателен, я рассматриваю использование функций Array.Map, Array.Filter)

let quotedTrades : quotedTrade array = getTradesFromDisk()
let tradesByAnalyst : byAnalyst array = sliceByAnalyst quotedTrades
let tradesByTicker : byTicker array = sliceByTicker quotedTrades

Основной вопрос вокруг применения скользящего окна:

// iterate over each analyst
for tradeByAnalyst in tradesByAnalyst do
    // look at trades on a per analyst basis
    let mySeries : quotedTrade array= tradeByAnalyst.trades
    // each window is an array of trades that occured in a seven day period
    let sevenDayWindowsByAnalyst : quotedTrade array = sliceByDays 7 mySeries
    // I want to evaluate the seven day window, per this analsyt independently
    for sevenDayWindowByAnalyst in sevenDayWindowsByAnalyst do
        let someResult = doSomethingWithTradesInWindow sevenDayWindowByAnalyst

Суть в том, что у меня есть набор данных на аналитика, где одна сделка в день 0 представлена ​​как: T0, а одна сделка в день 1: T1;Мой оригинальный набор содержит 3 сделки в день 0 и отдельные сделки на 1, 3, 5, 8, 10 периордах после:

[ T0 T0 T0 T1 T3 T5 T8 T10 ]

возвращает

[
  [ T0 T0 T0 T1 T3 T5 ] // incudes T0 -> T6
  [ T1 T3 T5 ] // incudes T1 -> T7
  [ T3 T5 T8 ] // incudes T2 -> T8
  [ T3 T5 T8 ] // incudes T3 -> T9
  [ T5 T8 T10 ] // incudes T4 -> T10
  [ T5 T8 T10 ] // incudes T5 -> T11
  [ T8 T10 ] // incudes T6 -> T12
  [ T8 T10 ] // incudes T7 -> T13
  [ T8 T10 ] // incudes T8 -> T14
  [ T10 ] // incudes T9 -> T15
  [ T10 ] // incudes T10 -> T16
]

Любые идеи поЛучший способ достичь этого был бы очень признателен.

Ответы [ 2 ]

1 голос
/ 17 июля 2010

Прежде всего, относительно вашего первого вопроса - как разбить данные - вы также можете использовать функции из модуля Seq (они работают с любым типом коллекции, например списками, массивами и т. Д.).Чтобы разбить данные на группы, вы можете использовать Seq.groupBy:

trades 
  |> Seq.groupBy (fun qt -> qt.trade.analystId)
  |> Seq.map (fun (key, values) -> 
        { analystId = key; trades = values |> Array.ofSeq )

Дальнейшая обработка данных может быть выполнена снова с помощью функций Seq (например, filter и map).Я думаю, что они предпочтительнее функций для Array, если вы хотите иметь более общий код (также некоторые функции недоступны в Array).Однако функции из Array работают немного быстрее (для больших объемов данных это может иметь значение).

В вопросе о скользящем окне я не совсем понимаю, каково ваше представление данных.Однако, если у вас есть (или вы можете построить) список всех сделок (например, введите list<quotedTrade> для каждого аналитика, вы можете использовать Seq.windowed:

trades 
  |> Seq.windowed 7
  |> Seq.map (fun win ->
      // all trades in the window as an array are in 'win' 
     )

Функция windowed создает только окнауказанной длины (более короткие окна опущены), так что это не совсем то, что вы хотели. Однако я думаю, что вы могли бы заполнить данные пустыми сделками, чтобы обойти это.

0 голосов
/ 17 июля 2010

Я думаю, что вы, вероятно, можете сделать что-то вроде этого, чтобы получить сделки, которые вас интересуют:

let sliceByDays n (qts : quotedTrade seq) =
  let dates = qts |> Seq.map (fun qt -> qt.trade.startOn)
  let min = dates |> Seq.min
  let max = dates |> Seq.max
  let days = min |> Seq.unfold (fun d -> if d > max then None else Some(d, d.AddDays(1.)))
  [for d in days do
     let tradesInRange =
       qts
       |> Seq.filter (fun qt -> qt.trade.startOn >= d && qt.trade.startOn < d.AddDays(float n))
     yield tradesInRange]

Это дает вам список последовательностей сделок, одна последовательность в день.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...