From 7dd0e3f42105569b6e6ec02aeeec9b5a8bbd9dd3 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Tue, 22 Sep 2026 03:25:00 +0800 Subject: Add real AKShare stock daily history probe slice (3d-19) --- src/FundLab.Api/MarketData.fs | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'src/FundLab.Api/MarketData.fs') 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 = + 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" -- cgit v1.2.3