Arrays 递归F#函数中的数组与列表

Arrays 递归F#函数中的数组与列表,arrays,list,optimization,f#,Arrays,List,Optimization,F#,我有这个功能: let calculate (candles: CandleData list) : decimal list = let inline range (q: CandleData) = q.High - q.Low let inline price (q: CandleData) = range q / 2m + q.Low let rec update (candles: CandleData list) (output: decimal list)

我有这个功能:

let calculate (candles: CandleData list) : decimal list =
    let inline range (q: CandleData) = q.High - q.Low
    let inline price (q: CandleData) = range q / 2m + q.Low

    let rec update (candles: CandleData list) (output: decimal list) lastPrice priceTracker rangeTracker stateTracker lambda =
        match candles with
        | [] -> output
        | h::t ->
            let priceTracker' = 0.2m * (price h - lastPrice) + 0.8m * priceTracker
            let rangeTracker' = 0.1m * (range h) + 0.8m * rangeTracker
            let lambda        = if rangeTracker <> 0m then abs(priceTracker / rangeTracker) else lambda
            let sqr           = decimal (sqrt (double (lambda * lambda * lambda * lambda + 16m * lambda * lambda)))
            let alpha         = (-lambda * lambda + sqr) / 8m
            let stateTracker' = alpha * price h + (1m - alpha) * stateTracker
            update t (output @ [decimal stateTracker']) (price h) priceTracker' rangeTracker' stateTracker' lambda

    update candles [] (price candles.Head) 0m (range candles.Head) (price candles.Head) 0.01m
让我们计算(烛光:烛光数据列表):十进制列表=
让内联范围(q:CandleData)=q.高-q.低
让内联价格(q:CandleData)=范围q/2m+q.低
让rec更新(烛光:烛光数据列表)(输出:十进制列表)lastPrice priceTracker rangeTracker stateTracker lambda=
用蜡烛配
|[]->输出
|h::t->
让priceTracker'=0.2m*(价格h-最新价格)+0.8m*priceTracker
让rangeTracker'=0.1m*(范围h)+0.8m*rangeTracker
设lambda=如果rangeTracker 0m,则为abs(价格跟踪器/rangeTracker),否则为lambda
设sqr=十进制(sqrt(双精度(λ*λ*λ*λ*λ+16m*λ*λ)))
设α=(-lambda*lambda+sqr)/8m
设stateTracker'=alpha*价格h+(1m-alpha)*stateTracker
更新t(输出@[十进制状态跟踪器])(价格h)价格跟踪器'rangeTracker'状态跟踪器'lambda
更新蜡烛[](价格蜡烛头)0米(范围蜡烛头)(价格蜡烛头)0.01米
它在列表上运行,但我想知道使用数组是否有意义,因为数据最初是以数组的形式出现的,所以我必须将其转换为列表,然后像数组一样依次遍历它


但是,如果我将其转换为数组,头/尾部分不是每次都会重新创建数组吗?那么,我是否应该保持数组的完整性并只使用索引进行迭代?

如果您想避免转换为
列表的成本,并且仍然将其作为惯用的F#,您可以使用原始数组而不是递归:

让我们来计算(蜡烛:[]=
让内联范围(q:CandleData)=q.高-q.低
让内联价格(q:CandleData)=范围q/2m+q.低
假设init=价格蜡烛[0],0米,范围蜡烛[0],价格蜡烛[0],0.01米
(初始,蜡烛)
||>Seq.scan(趣味(lastPrice、priceTracker、rangeTracker、stateTracker、lambda)蜡烛->
让priceTracker'=0.2m*(价格蜡烛-最新价格)+0.8m*priceTracker
让rangeTracker'=0.1m*(射程蜡烛)+0.8m*rangeTracker
设lambda=如果rangeTracker 0m,则为abs(价格跟踪器/rangeTracker),否则为lambda
设sqr=十进制(sqrt(双精度(λ*λ*λ*λ*λ+16m*λ*λ)))
设α=(-lambda*lambda+sqr)/8m
让stateTracker'=alpha*价格烛光+(1m-alpha)*stateTracker
价格蜡烛、价格跟踪器、rangeTracker、stateTracker、lambda)
|>Seq.map(乐趣(lastPrice、priceTracker、rangeTracker、stateTracker、lambda)->
状态跟踪器)
|>序号1
|>序号:toArray

另一种方法是使用
mapFold

let calculate3 (candles : _[]) =
    let inline range (q: CandleData) = q.High - q.Low
    let inline price (q: CandleData) = range q / 2m + q.Low

    let init = price candles.[0], 0m, range candles.[0], price candles.[0], 0.01m
    (init, candles)
    ||> Array.mapFold (fun (lastPrice, priceTracker, rangeTracker, stateTracker, lambda) candle ->
            let priceTracker' = 0.2m * (price candle - lastPrice) + 0.8m * priceTracker
            let rangeTracker' = 0.1m * (range candle) + 0.8m * rangeTracker
            let lambda        = if rangeTracker <> 0m then abs(priceTracker / rangeTracker) else lambda
            let sqr           = decimal (sqrt (double (lambda * lambda * lambda * lambda + 16m * lambda * lambda)))
            let alpha         = (-lambda * lambda + sqr) / 8m
            let stateTracker' = alpha * price candle + (1m - alpha) * stateTracker
            stateTracker, (price candle, priceTracker', rangeTracker', stateTracker', lambda) )
    |> fst
让我们计算3(蜡烛:[]=
让内联范围(q:CandleData)=q.高-q.低
让内联价格(q:CandleData)=范围q/2m+q.低
假设init=价格蜡烛[0],0米,范围蜡烛[0],价格蜡烛[0],0.01米
(初始,蜡烛)
||>Array.mapFold(趣味(lastPrice、priceTracker、rangeTracker、stateTracker、lambda)蜡烛->
让priceTracker'=0.2m*(价格蜡烛-最新价格)+0.8m*priceTracker
让rangeTracker'=0.1m*(射程蜡烛)+0.8m*rangeTracker
设lambda=如果rangeTracker 0m,则为abs(价格跟踪器/rangeTracker),否则为lambda
设sqr=十进制(sqrt(双精度(λ*λ*λ*λ*λ+16m*λ*λ)))
设α=(-lambda*lambda+sqr)/8m
让stateTracker'=alpha*价格烛光+(1m-alpha)*stateTracker
stateTracker,(price candle、price Tracker、rangeTracker、stateTracker、lambda))
|>fst

它的工作原理类似于
scan
,但同时生成一个数组。

事实上,如上所述的
update
函数效率低下,因为它将新元素添加到输出(
output@[…]
)。如果在头部添加元素,则效率会更高。
…:输出
,然后反转列表。另外,可以随意使用带有可变变量的循环。这并没有什么错,只要可变值保存在一个简单的函数中,并且不与代码的其他部分共享;谢谢