ミリ秒の時間枠の一連の履歴ティックデータを処理する必要があります。特定の期間(毎時、毎分など)の開始ティックをフィルタリングする機能が必要です。シーケンスにはスパンよりも大きなギャップがある可能性があるため、そのようなギャップの後の最初のティックを開始ティックとして選択する必要があります。そうでない場合、開始ティックは、対応するタイムスパンのカレンダー開始のパスに最も近いものです。
最初に頭に浮かぶのは、次のステートフルフィルタリング関数opensTimespan:Timespan->(Timestamp->bool)
です。これは、各ギャップオープニングまたはインターバルオープニングティックのtimespanIdを、呼び出し間を通過するためのクロージャーにキャプチャします。
let opensTimespan (interval: Timespan)=
let lastTakenId = ref -1L // Timestamps are positive
fun (tickAt: Timestamp) ->
let tickId = tickAt / interval in
if tickId <> !lastTakenId then lastTakenId := tickId; true
else false
そしてこのように適用することができます:
let hourlyTicks = readTicks @"EURUSD-history.zip" "EURUSD-2012-04.csv"
|> Seq.filter (opensTimespan HOUR) |> Seq.toList
これは問題なく機能しますがopensTimespan
、副作用があることは間違いなく慣用的ではありません。
代替案の1つは、ティックの決定が1つを開くかどうかの決定に、自己と前のタイムスタンプのペアだけで次のステートレスフィルタリング関数を作成する必要があるという事実を使用することopensTimespanF:Timespan->Timestamp*Timestamp->bool
です。
let opensTimespanF interval (ticksPair: Timestamp*Timestamp) =
fst ticksPair/ interval <> snd ticksPair/ interval
それは次のように適用できます:
let hourlyTicks=
seq {
yield 0L;
yield! readTicks @"EURUSD-history.zip" "EURUSD-2012-04.csv"
}
|> Seq.pairwise |> Seq.filter (opensTimespanF HOUR)
|> Seq.map snd
|> Seq.toList
純粋に機能的なこのアプローチでは、わずかな(〜11%)パフォーマンスの低下だけで同等の結果が得られます。
私が見逃しているかもしれない純粋な機能的な方法でこのタスクに取り組む他の方法は何ですか?
ありがとうございました。