0

我试图弄清楚何时使用 f# 以及何时使用 c#。我有一个能源交易的实际问题。电力合同被引用为,交付开始,交付结束,关税,体积。例如,100MW Cal14 Offpeak,因此从 2014 年 1 月 1 日到 2014 年 12 月 31 日,如果工作时间在一周的 20 到 8 小时(夜间)或周末的所有时间之间,则合同每小时交付 100MW -总共约 5500 小时。高峰合同在工作日交付 8-20,而基地在期间交付所有时间。

如果您有这些合约的投资组合,您希望将它们聚合成每小时头寸向量。到目前为止,这是我的代码:

合同数据示例(日期为 Excel 格式):

let data = [(41275., 41639., "Base", 10.); (41275., 41639., "Base", 60.); (41275., 41639., "Peak", 20.); (41275.,41639.,"Offpeak",30.);  (41275.,41364.,"Peak",40.); (41275.,41364.,"Peak",70.); (41275.,41364.,"Offpeak", 50.)]

聚合相同合约的函数:

let group_fold keys value fold acc seq =
    seq |> Seq.groupBy keys 
        |> Seq.map (fun ((key1, key2, key3), seq) -> 
            (key1, key2, key3, seq |> Seq.map value |> Seq.fold fold acc))


let aggrTrades data =
data |> group_fold (fun (k1, k2, k3, _) -> k1, k2, k3) (fun (_, _, _, v) -> v) (+) 0.0

识别高峰和非高峰时间的功能:

let poindicator dts =
    let newdts = DateTime.FromOADate dts
    // Match on day of week and hour properties of the date time
    match newdts.DayOfWeek, newdts.Hour with
    // For weekend, return false
    | DayOfWeek.Saturday, _ | DayOfWeek.Sunday, _ -> false
    // For working hours, return true
    | _, h when h >= 8 && h < 20 -> true
    // For non-working weekday hours, return false
    | _ -> false

最后一个函数将它们放在一起并创建一个小时向量(std = 小时向量的开始日期和 edd = 结束日期):

let hourlyvec data std edd =
    let aggrdata = aggrTrades data
    let dtsvec = [std.. 1./24. .. edd]
    let nrhrs = dtsvec |> Seq.length
    let mutable res = Seq.init nrhrs (fun i -> 0.0)
    for i=0 to res |> Seq.length do
        for (a, b, c, d) in aggrdata do
            match a , b with
            | e, f when e <= dtsvec.[i] && f >= dtsvec.[i] -> 
                match c with
                | "Base" -> res.[i] <- res.[i] + d
                | "Peak" when poindicator (DateTime.FromOADate dtsvec.[i]) -> res.[i] <- res.[i] + d
                | "Offpeak" when not poindicator (DateTime.FromOADate dtsvec.[i]) -> res.[i] <- res.[i] + d
                | _ -> failwith "Not recognized tarif"
            |_ -> failwith "Not in period tarif"
    dtsvec, res

FS0039 失败:未定义字段、构造函数或成员“项目”,并且似乎也不喜欢嵌套指针函数

任何指针将不胜感激?另外,如果您认为这在 c# 中会更容易,请告诉我,我认为它是一个功能问题,所以我首先选择了 f#。

4

2 回答 2

2

所以问题就在这里

    match a , b with
    | e, f when e <= dtsvec.[i] && f >= dtsvec.[i] -> ...

如果不满足条件,您将收到匹配失败异常,并且编译器会正确发出警告。

这在这里永远行不通

        match _, _, c, _ with
        | "Base" -> res.[i] <- res.[i] + d
        | "Peak" when poindicator DateTime.FromOADate dtsvec.[i] -> res.[i] <- res.[i] + d
        | "Offpeak" when not poindic DateTime.FromOADate dtsvec.[i] -> res.[i] <- res.[i] + d
        | _ -> failwith "Not recognized tarif"

因为您只能将_in放在|not 之后的部分中match ... with

于 2013-10-04T11:18:35.307 回答
0

我希望您将此问题重新发布到 Code Review StackExchange,但既然您没有,我将在此处发布您的代码的简化版本,以防 OP 或未来的访问者发现它有用:

let group_fold keys valueExtractor folder state seq =
    seq
    |> Seq.groupBy keys
    |> Seq.map (fun ((key1, key2, key3), seq) ->
        let finalState =
            (state, seq)
            ||> Seq.fold (fun state v ->
                let mappedValue = valueExtractor v
                folder state mappedValue)
        key1, key2, key3, finalState)

let poindicator dts =
    let newdts = DateTime.FromOADate dts

    // Match on day of week and hour properties of the date time
    // For weekend, return false
    newdts.DayOfWeek <> DayOfWeek.Saturday
    && newdts.DayOfWeek <> DayOfWeek.Sunday
    // For working hours, return true
    // For non-working weekday hours, return false
    && newdts.Hour >= 8
    && newdts.Hour < 20

let aggrTrades data =
    data |> group_fold (fun (k1, k2, k3, _) -> k1, k2, k3) (fun (_, _, _, v) -> v) (+) 0.0

let hourlyvec data std edd =
    let dtsvec = [|std.. 1./24. .. edd|]

    let res =
        let nrhrs = Array.length dtsvec
        let aggrdata = aggrTrades data

        Array.init nrhrs <| fun i ->
            (0.0, aggrdata)
            ||> Seq.fold (fun periodValue (a, b, c, d) ->
                match a, b with
                | e, f when e <= dtsvec.[i] && f >= dtsvec.[i] -> 
                    match c with
                    | "Base" ->
                        periodValue + d
                    | "Peak" when poindicator dtsvec.[i] ->
                        periodValue + d
                    | "Offpeak" when not (poindicator dtsvec.[i]) ->
                        periodValue + d
                    | _ ->
                        failwith "Not in Tarif"
                |_ ->
                    failwith "Not in period")

    dtsvec, res
于 2013-10-08T12:42:08.257 回答