diff options
Diffstat (limited to 'src/FundLab.Api/MarketData.fs')
| -rw-r--r-- | src/FundLab.Api/MarketData.fs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/FundLab.Api/MarketData.fs b/src/FundLab.Api/MarketData.fs index 87ef145..82da1c9 100644 --- a/src/FundLab.Api/MarketData.fs +++ b/src/FundLab.Api/MarketData.fs @@ -59,6 +59,23 @@ type MarketDataStockQuotePayload = Currency: string } +type MarketDataStockDailyBar = + { + BarDate: DateOnly + Close: decimal + Volume: decimal option + Amount: decimal option + } + +type MarketDataStockDailyPayload = + { + Source: string + SourceRevision: string + CollectedAt: DateTimeOffset + Code: string + Bars: MarketDataStockDailyBar list + } + type MarketDataInstrumentRecord = { Code: string @@ -398,3 +415,55 @@ module MarketData = } with | :? JsonException -> Error "payload must be valid JSON" + + let private parseStockDailyBar root = + result { + let! dateText = requiredString root "date" + let! date = parseDate dateText + let! closeProperty = requiredProperty root "close" + let! close = parseDecimal "close" closeProperty + let! volumeProperty = requiredProperty root "volume" + let! volume = optionalDecimal "volume" volumeProperty + let! amountProperty = requiredProperty root "amount" + let! amount = optionalDecimal "amount" amountProperty + + return + { + BarDate = date + Close = close + Volume = volume + Amount = amount + } + } + + let parseStockDailyPayload (json: string) : Result<MarketDataStockDailyPayload, string> = + try + use document = JsonDocument.Parse(json) + let root = document.RootElement + + result { + let! source, sourceRevision, collectedAt = validateEnvelope root "stock-daily" + let! instrumentProperty = requiredProperty root "instrument" + let! codeProperty = requiredString instrumentProperty "code" + + if not (isFundCode codeProperty) then + return! Error "stock code must contain exactly six digits" + + let! observationsProperty = requiredProperty root "observations" + let! barsProperty = requiredProperty root "observations" + let! bars = parseArray parseStockDailyBar barsProperty + + if List.isEmpty bars then + return! Error "observations must not be empty" + + return + { + Source = source + SourceRevision = sourceRevision + CollectedAt = collectedAt + Code = codeProperty + Bars = bars + } + } + with + | :? JsonException -> Error "payload must be valid JSON" |
